mirror of
https://github.com/nxp-imx/mwifiex.git
synced 2024-11-15 03:25:35 +00:00
5fc6a71423
The MxM wifi driver is merged from below repo and applied some patches for block and build issues. ssh://git@bitbucket.sw.nxp.com/wcswrel/ rel-nxp-wifi-fp92-bt-fp85-linux-android-mxm4x17169-mgpl.git The commit is to update the license to GPL v2. Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
14528 lines
390 KiB
C
14528 lines
390 KiB
C
/** @file uaputl.c
|
|
*
|
|
* @brief Program to send AP commands to the driver/firmware of the uAP
|
|
* driver.
|
|
*
|
|
*
|
|
* 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 <stdarg.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/select.h>
|
|
#include <stdio.h>
|
|
#include <getopt.h>
|
|
#include <netinet/in.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <linux/if.h>
|
|
#include <sys/ioctl.h>
|
|
#include <errno.h>
|
|
#include "uaputl.h"
|
|
#include "uapcmd.h"
|
|
|
|
/****************************************************************************
|
|
Definitions
|
|
****************************************************************************/
|
|
/** Default debug level */
|
|
int debug_level = MSG_NONE;
|
|
|
|
/** Enable or disable debug outputs */
|
|
#define DEBUG 1
|
|
|
|
/** Convert character to integer */
|
|
#define CHAR2INT(x) (((x) >= 'A') ? ((x) - 'A' + 10) : ((x) - '0'))
|
|
|
|
/** Supported stream modes */
|
|
#define HT_STREAM_MODE_1X1 0x11
|
|
#define HT_STREAM_MODE_2X2 0x22
|
|
|
|
static int get_bss_config(t_u8 *buf);
|
|
|
|
/****************************************************************************
|
|
Global variables
|
|
****************************************************************************/
|
|
/** Device name */
|
|
static char dev_name[IFNAMSIZ + 1];
|
|
/** Option for cmd */
|
|
struct option cmd_options[] = {
|
|
{"help", 0, 0, 'h'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
/** Flag to check if custom IE is present in sys_config response from FW */
|
|
int custom_ie_present = 0;
|
|
|
|
/** Flag to check if max mgmt IE is printed in sys_config response from FW */
|
|
int max_mgmt_ie_print = 0;
|
|
|
|
/** Flag to bypass re-route path */
|
|
int uap_ioctl_no_reroute = 0;
|
|
|
|
/****************************************************************************
|
|
Local functions
|
|
****************************************************************************/
|
|
/**
|
|
* @brief Convert char to hex integer
|
|
*
|
|
* @param chr Char
|
|
* @return Hex integer
|
|
*/
|
|
unsigned char
|
|
hexc2bin(char chr)
|
|
{
|
|
if (chr >= '0' && chr <= '9')
|
|
chr -= '0';
|
|
else if (chr >= 'A' && chr <= 'F')
|
|
chr -= ('A' - 10);
|
|
else if (chr >= 'a' && chr <= 'f')
|
|
chr -= ('a' - 10);
|
|
|
|
return chr;
|
|
}
|
|
|
|
/**
|
|
* @brief Check protocol is valid or not
|
|
*
|
|
* @param protocol Protocol
|
|
*
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_protocol_valid(int protocol)
|
|
{
|
|
int ret = UAP_FAILURE;
|
|
switch (protocol) {
|
|
case PROTOCOL_NO_SECURITY:
|
|
case PROTOCOL_STATIC_WEP:
|
|
case PROTOCOL_WPA:
|
|
case PROTOCOL_WPA2:
|
|
case PROTOCOL_WPA2_MIXED:
|
|
case PROTOCOL_WPA3_SAE:
|
|
ret = UAP_SUCCESS;
|
|
break;
|
|
default:
|
|
printf("ERR: Invalid Protocol: %d\n", protocol);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Function to check valid rate
|
|
*
|
|
*
|
|
* @param rate Rate to verify
|
|
*
|
|
* return UAP_SUCCESS or UAP_FAILURE
|
|
**/
|
|
int
|
|
is_rate_valid(int rate)
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
switch (rate) {
|
|
case 2:
|
|
case 4:
|
|
case 11:
|
|
case 13:
|
|
case 22:
|
|
case 12:
|
|
case 18:
|
|
case 24:
|
|
case 48:
|
|
case 72:
|
|
case 96:
|
|
case 108:
|
|
case 36:
|
|
break;
|
|
default:
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Check for mandatory rates
|
|
*
|
|
*
|
|
* 2, 4, 11, 22 must be present
|
|
*
|
|
* 6 12 and 24 must be present for ofdm
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_FAILURE or UAP_SUCCESS
|
|
*
|
|
*/
|
|
static int
|
|
check_mandatory_rates(int argc, char **argv)
|
|
{
|
|
int i;
|
|
int tmp;
|
|
t_u32 rate_bitmap = 0;
|
|
int cck_enable = 0;
|
|
int ofdm_enable = 0;
|
|
#define BITMAP_RATE_1M 0x01
|
|
#define BITMAP_RATE_2M 0x02
|
|
#define BITMAP_RATE_5_5M 0x04
|
|
#define BITMAP_RATE_11M 0x8
|
|
#define B_RATE_MANDATORY 0x0f
|
|
#define BITMAP_RATE_6M 0x10
|
|
#define BITMAP_RATE_12M 0x20
|
|
#define BITMAP_RATE_24M 0x40
|
|
#define G_RATE_MANDATORY 0x70
|
|
for (i = 0; i < argc; i++) {
|
|
tmp = (A2HEXDECIMAL(argv[i]) & ~BASIC_RATE_SET_BIT);
|
|
switch (tmp) {
|
|
case 2:
|
|
cck_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_1M;
|
|
break;
|
|
case 4:
|
|
cck_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_2M;
|
|
break;
|
|
case 11:
|
|
cck_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_5_5M;
|
|
break;
|
|
case 22:
|
|
cck_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_11M;
|
|
break;
|
|
case 12:
|
|
ofdm_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_6M;
|
|
break;
|
|
case 24:
|
|
ofdm_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_12M;
|
|
break;
|
|
case 48:
|
|
ofdm_enable = 1;
|
|
rate_bitmap |= BITMAP_RATE_24M;
|
|
break;
|
|
case 18:
|
|
case 36:
|
|
case 72:
|
|
case 96:
|
|
case 108:
|
|
ofdm_enable = 1;
|
|
break;
|
|
}
|
|
}
|
|
#ifdef WIFI_DIRECT_SUPPORT
|
|
if (strncmp(dev_name, "wfd", 3))
|
|
#endif
|
|
if ((rate_bitmap & B_RATE_MANDATORY) != B_RATE_MANDATORY) {
|
|
if (cck_enable) {
|
|
printf("Basic Rates 2, 4, 11 and 22 (500K units) \n" "must be present in basic or non-basic rates\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (ofdm_enable &&
|
|
((rate_bitmap & G_RATE_MANDATORY) != G_RATE_MANDATORY)) {
|
|
printf("OFDM Rates 12, 24 and 48 ( 500Kb units)\n"
|
|
"must be present in basic or non-basic rates\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert string to hex integer
|
|
*
|
|
* @param s A pointer string buffer
|
|
* @return Hex integer
|
|
*/
|
|
unsigned int
|
|
a2hex(char *s)
|
|
{
|
|
unsigned int val = 0;
|
|
if (!strncasecmp("0x", s, 2)) {
|
|
s += 2;
|
|
}
|
|
while (*s && isxdigit(*s)) {
|
|
val = (val << 4) + hexc2bin(*s++);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* @brief Dump hex data
|
|
*
|
|
* @param prompt A pointer prompt buffer
|
|
* @param p A pointer to data buffer
|
|
* @param len The len of data buffer
|
|
* @param delim Delim char
|
|
* @return None
|
|
*/
|
|
void
|
|
hexdump_data(char *prompt, void *p, int len, char delim)
|
|
{
|
|
int i;
|
|
unsigned char *s = p;
|
|
|
|
if (prompt) {
|
|
printf("%s: len=%d\n", prompt, (int)len);
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
if (i != len - 1)
|
|
printf("%02x%c", *s++, delim);
|
|
else
|
|
printf("%02x\n", *s);
|
|
if ((i + 1) % 16 == 0)
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
#if DEBUG
|
|
/**
|
|
* @brief Conditional printf
|
|
*
|
|
* @param level Severity level of the message
|
|
* @param fmt Printf format string, followed by optional arguments
|
|
*/
|
|
void
|
|
uap_printf(int level, char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
if (level <= debug_level) {
|
|
vprintf(fmt, ap);
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
|
/**
|
|
* @brief Dump hex data
|
|
*
|
|
* @param prompt A pointer prompt buffer
|
|
* @param p A pointer to data buffer
|
|
* @param len The len of data buffer
|
|
* @param delim Delim char
|
|
* @return None
|
|
*/
|
|
void
|
|
hexdump(char *prompt, void *p, int len, char delim)
|
|
{
|
|
if (debug_level < MSG_ALL)
|
|
return;
|
|
hexdump_data(prompt, p, len, delim);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Hex to number
|
|
*
|
|
* @param c Hex value
|
|
* @return Integer value or -1
|
|
*/
|
|
int
|
|
hex2num(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return c - '0';
|
|
if (c >= 'a' && c <= 'f')
|
|
return c - 'a' + 10;
|
|
if (c >= 'A' && c <= 'F')
|
|
return c - 'A' + 10;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sys_info command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sys_info_usage(void)
|
|
{
|
|
printf("\nUsage : sys_info\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Get Max sta num from firmware
|
|
*
|
|
* @return max number of stations
|
|
*/
|
|
int
|
|
get_max_sta_num_supported(t_u16 *max_sta_num_supported)
|
|
{
|
|
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;
|
|
|
|
/* Initialize the command length */
|
|
cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_sta_num);
|
|
|
|
/* 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;
|
|
tlv->length = 4;
|
|
cmd_buf->action = ACTION_GET;
|
|
|
|
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) {
|
|
printf("ERR:Could not get max station number!\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (tlv->length == 4) {
|
|
*max_sta_num_supported =
|
|
tlv->max_sta_num_supported;
|
|
} else {
|
|
*max_sta_num_supported = MAX_STA_COUNT;
|
|
}
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Parse domain name for domain_code
|
|
*
|
|
* @param dom_name Domain name
|
|
* @return domain_code / UAP_FAILURE
|
|
*/
|
|
static t_u8
|
|
parse_domain_name(char *domain_name)
|
|
{
|
|
t_u8 domain_code = UAP_FAILURE;
|
|
|
|
if (strstr(domain_name, "DOMAIN_CODE_")) {
|
|
domain_name += sizeof("DOMAIN_CODE_") - 1;
|
|
|
|
if (!(strncmp(domain_name, "FCC", sizeof("FCC") - 1)))
|
|
domain_code = DOMAIN_CODE_FCC;
|
|
else if (!(strcmp(domain_name, "ETSI")))
|
|
domain_code = DOMAIN_CODE_ETSI;
|
|
else if (!(strcmp(domain_name, "MKK")))
|
|
domain_code = DOMAIN_CODE_MKK;
|
|
else if (!(strcmp(domain_name, "IN")))
|
|
domain_code = DOMAIN_CODE_IN;
|
|
else if (!(strcmp(domain_name, "MY")))
|
|
domain_code = DOMAIN_CODE_MY;
|
|
}
|
|
return domain_code;
|
|
}
|
|
|
|
/**
|
|
* @brief Parse domain file for country information
|
|
*
|
|
* @param country Country name
|
|
* @param band Band Info. 0x01 : B band, 0x02 : G band, 0x04 : A band.
|
|
* @param sub_bands Band information
|
|
* @param pdomain_code Pointer to receive domain_code
|
|
* @return number of band/ UAP_FAILURE
|
|
*/
|
|
t_u8
|
|
parse_domain_file(char *country, int band, ieeetypes_subband_set_t *sub_bands,
|
|
t_u8 *pdomain_code)
|
|
{
|
|
FILE *fp;
|
|
char str[64];
|
|
char domain_name[64];
|
|
int cflag = 0;
|
|
int dflag = 0;
|
|
int found = 0;
|
|
int skip = 0;
|
|
int j = -1, reset_j = 0;
|
|
t_u8 no_of_sub_band = 0;
|
|
char *strp = NULL;
|
|
int ret = 0;
|
|
|
|
fp = fopen("config/80211d_domain.conf", "r");
|
|
if (fp == NULL) {
|
|
printf("File opening Error\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* Search specific domain name
|
|
*/
|
|
memset(domain_name, 0, sizeof(domain_name));
|
|
memset(str, 0, 64);
|
|
while (!feof(fp)) {
|
|
ret = fscanf(fp, "%63s", str);
|
|
if (ret <= 0)
|
|
break;
|
|
if (cflag) {
|
|
strncpy(domain_name, str, sizeof(domain_name) - 1);
|
|
cflag = 0;
|
|
}
|
|
if (!strcmp(str, "COUNTRY:")) {
|
|
/** Store next string to domain_name */
|
|
cflag = 1;
|
|
}
|
|
|
|
if (!strcmp(str, country)) {
|
|
/** Country is matched ;)*/
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
printf("No match found for Country = %s in the 80211d_domain.conf \n", country);
|
|
fclose(fp);
|
|
found = 0;
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* Search domain specific information
|
|
*/
|
|
while (!feof(fp)) {
|
|
ret = fscanf(fp, "%63s", str);
|
|
if (ret <= 0)
|
|
break;
|
|
|
|
if (feof(fp)
|
|
) {
|
|
break;
|
|
}
|
|
|
|
if (dflag && !strcmp(str, "DOMAIN:")) {
|
|
|
|
if ((band & BAND_A) == 0)
|
|
break;
|
|
|
|
/* parse next domain */
|
|
cflag = 0;
|
|
dflag = 0;
|
|
j = -1;
|
|
reset_j = 0;
|
|
}
|
|
if (dflag) {
|
|
j++;
|
|
if (strchr(str, ','))
|
|
reset_j = 1;
|
|
|
|
strp = strtok(str, ", ");
|
|
|
|
if (strp == NULL) {
|
|
if (reset_j) {
|
|
j = -1;
|
|
reset_j = 0;
|
|
}
|
|
continue;
|
|
} else {
|
|
strncpy(str, strp, (sizeof(str) - 1));
|
|
}
|
|
|
|
if (IS_HEX_OR_DIGIT(str) == UAP_FAILURE) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
fclose(fp);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
switch (j) {
|
|
case 0:
|
|
sub_bands[no_of_sub_band].first_chan =
|
|
(t_u8)A2HEXDECIMAL(str);
|
|
break;
|
|
case 1:
|
|
sub_bands[no_of_sub_band].no_of_chan =
|
|
(t_u8)A2HEXDECIMAL(str);
|
|
break;
|
|
case 2:
|
|
sub_bands[no_of_sub_band++].max_tx_pwr =
|
|
(t_u8)A2HEXDECIMAL(str);
|
|
break;
|
|
default:
|
|
printf("ERR: Incorrect 80211d_domain.conf file\n");
|
|
fclose(fp);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (reset_j) {
|
|
j = -1;
|
|
reset_j = 0;
|
|
}
|
|
}
|
|
|
|
if (cflag && !strcmp(str, domain_name)) {
|
|
/* Followed will be the band details */
|
|
cflag = 0;
|
|
if (band & (BAND_B | BAND_G) || skip)
|
|
dflag = 1;
|
|
else
|
|
skip = 1;
|
|
}
|
|
if (!dflag && !strcmp(str, "DOMAIN:")) {
|
|
cflag = 1;
|
|
}
|
|
}
|
|
fclose(fp);
|
|
|
|
if (pdomain_code && no_of_sub_band && (band & BAND_A)) {
|
|
*pdomain_code = parse_domain_name(domain_name);
|
|
}
|
|
return (no_of_sub_band);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief Set/Get SNMP MIB
|
|
*
|
|
* @param action 0-GET 1-SET
|
|
* @param oid Oid
|
|
* @param size Size of oid value
|
|
* @param oid_buf Oid value
|
|
* @return UAP_FAILURE or UAP_SUCCESS
|
|
*
|
|
*/
|
|
int
|
|
sg_snmp_mib(t_u16 action, t_u16 oid, t_u16 size, t_u8 *oid_buf)
|
|
{
|
|
apcmdbuf_snmp_mib *cmd_buf = NULL;
|
|
tlvbuf_header *tlv = NULL;
|
|
int ret = UAP_FAILURE;
|
|
t_u8 *buf = NULL;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
t_u16 cmd_len;
|
|
int i;
|
|
|
|
cmd_len = sizeof(apcmdbuf_snmp_mib) + sizeof(tlvbuf_header) + size;
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return ret;
|
|
}
|
|
memset(buf, 0, buf_len);
|
|
|
|
/* Locate Headers */
|
|
cmd_buf = (apcmdbuf_snmp_mib *)buf;
|
|
tlv = (tlvbuf_header *)(buf + sizeof(apcmdbuf_snmp_mib));
|
|
cmd_buf->size = buf_len - BUF_HEADER_SIZE;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->cmd_code = HostCmd_SNMP_MIB;
|
|
|
|
tlv->type = uap_cpu_to_le16(oid);
|
|
tlv->len = uap_cpu_to_le16(size);
|
|
for (i = 0; action && (i < size); i++) {
|
|
tlv->data[i] = oid_buf[i];
|
|
}
|
|
|
|
cmd_buf->action = uap_cpu_to_le16(action);
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
if (!action) {
|
|
/** Relocate the headers */
|
|
tlv = (tlvbuf_header *)((t_u8 *)cmd_buf +
|
|
sizeof
|
|
(apcmdbuf_snmp_mib));
|
|
for (i = 0;
|
|
i < MIN(uap_le16_to_cpu(tlv->len), size);
|
|
i++) {
|
|
oid_buf[i] = tlv->data[i];
|
|
}
|
|
}
|
|
ret = UAP_SUCCESS;
|
|
} else {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a sys_info request and sends to the driver
|
|
*
|
|
* Usage: "sys_info"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_info(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_sys_info_request *cmd_buf = NULL;
|
|
apcmdbuf_sys_info_response *response_buf = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len;
|
|
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_info_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 0) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_sys_info_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Alloc buf for command */
|
|
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_len = sizeof(apcmdbuf_sys_info_request);
|
|
cmd_buf = (apcmdbuf_sys_info_request *)buf;
|
|
response_buf = (apcmdbuf_sys_info_response *)buf;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->cmd_code = APCMD_SYS_INFO;
|
|
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) {
|
|
/* Verify response */
|
|
if (response_buf->cmd_code !=
|
|
(APCMD_SYS_INFO | APCMD_RESP_CHECK)) {
|
|
printf("ERR:Corrupted response!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Print response */
|
|
if (response_buf->result == CMD_SUCCESS) {
|
|
printf("System information = %s\n",
|
|
response_buf->sys_info);
|
|
} else {
|
|
printf("ERR:Could not retrieve system information!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for deepsleep command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_deepsleep_usage(void)
|
|
{
|
|
printf("\nUsage : deepsleep [MODE][IDLE_TIME]");
|
|
printf("\nOptions: MODE : 0 - Disable auto deep sleep mode");
|
|
printf("\n 1 - Enable auto deep sleep mode");
|
|
printf("\n IDLE_TIME: Idle time in milliseconds, default value is 100 ms");
|
|
printf("\n empty - get auto deep sleep mode\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates deepsleep request and send to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_deepsleep(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
deep_sleep_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_deepsleep_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (argc > 2) {
|
|
printf("ERR:wrong arguments. Only support 2 arguments\n");
|
|
print_deepsleep_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_DEEP_SLEEP;
|
|
if (argc) {
|
|
if (argc >= 1) {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_deepsleep_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
param.action = 1;
|
|
param.deep_sleep = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
param.idle_time = 0;
|
|
if (argc == 2) {
|
|
if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_deepsleep_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.idle_time = (t_u16)A2HEXDECIMAL(argv[1]);
|
|
}
|
|
} else {
|
|
param.action = 0;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
if (argc)
|
|
printf("ERR: deep sleep must be disabled before changing idle time\n");
|
|
else {
|
|
perror("");
|
|
printf("ERR:deep sleep failed\n");
|
|
}
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
if (param.deep_sleep == 1) {
|
|
printf("deep sleep mode: enabled\n");
|
|
printf("idle time = %dms\n", param.idle_time);
|
|
} else {
|
|
printf("deep sleep mode: disabled\n");
|
|
}
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Configure Band Steering
|
|
*
|
|
* Usage: band_steering_cfg state block_2g_prb_req max_btm_req_allowed
|
|
*
|
|
* State 0 or 1
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
|
|
int
|
|
apcmd_band_steering(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
band_steer_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 state = 0;
|
|
t_u8 block2gPrbReq = 0;
|
|
t_u8 maxBtmReqAllowed = 0;
|
|
|
|
t_u8 i;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
printf("\nUsage: band_steering_cfg <state 0/1> <block_2g_prb_req> <max_btm_req_allowed>\n");
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (!(argc == 0 || argc == 2 || argc == 4 || argc == 6)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_BAND_STEER;
|
|
|
|
if (argc) {
|
|
if (strcmp(argv[0], "state") &&
|
|
strcmp(argv[0], "block_2g_prb_req") &&
|
|
strcmp(argv[0], "max_btm_req_allowed")) {
|
|
printf("ERR: Incorrect input. Either state, block_2g_prb_req or max_btm_req_allowed is needed.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/** SET */
|
|
for (i = 0; i < argc; i = i + 2) {
|
|
if (strcmp(argv[i], "state") == 0) {
|
|
param.action += ACT_SET_STATE;
|
|
if (strcmp(argv[i + 1], "0") == 0) {
|
|
state = 0;
|
|
} else if (strcmp(argv[i + 1], "1") == 0) {
|
|
state = 1;
|
|
} else {
|
|
printf("ERR: Invalid State value.");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strcmp(argv[i], "block_2g_prb_req") == 0) {
|
|
param.action += ACT_SET_BLOCK_2G_PRB_REQ;
|
|
block2gPrbReq = atoi(argv[i + 1]);
|
|
if (block2gPrbReq < 0 || block2gPrbReq > 15) {
|
|
printf("ERR: Invalid block_2g_prb_req value. Enter value between 0 and 15");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strcmp(argv[i], "max_btm_req_allowed") == 0) {
|
|
param.action += ACT_SET_MAX_BTM_REQ_ALLOWED;
|
|
maxBtmReqAllowed = atoi(argv[i + 1]);
|
|
if (maxBtmReqAllowed <= 0 ||
|
|
maxBtmReqAllowed > 255) {
|
|
printf("ERR: Invalid max_btm_req_allowed value.");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR: Incorrect input. state, block_2g_prb_req and/or max_btm_req_allowed is needed in decimal format.");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
param.state = state;
|
|
param.block_2g_prb_req = block2gPrbReq;
|
|
param.max_btm_req_allowed = maxBtmReqAllowed;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
ioctl(sockfd, UAP_IOCTL_CMD, &ifr);
|
|
|
|
if (argc) {
|
|
printf("Set Successfull\n");
|
|
printf("state = %d \n", param.state);
|
|
printf("block_2g_prb_req = %d\n", param.block_2g_prb_req);
|
|
printf("max_btm_req_allowed = %d\n", param.max_btm_req_allowed);
|
|
} else {
|
|
printf("Get Successfull\n");
|
|
if (param.state == 1) {
|
|
printf("band steering mode: enabled\n");
|
|
printf("block_2g_prb_req = %d\n",
|
|
param.block_2g_prb_req);
|
|
printf("max_btm_req_allowed = %d\n",
|
|
param.max_btm_req_allowed);
|
|
} else {
|
|
printf("band steering: disabled\n");
|
|
}
|
|
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for tx_data_pause command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_txdatapause_usage(void)
|
|
{
|
|
printf("\nUsage : tx_data_pause [ENABLE][TX_BUF_CNT]");
|
|
printf("\nOptions: ENABLE : 0 - Disable Tx data pause events");
|
|
printf("\n 1 - Enable Tx data pause events");
|
|
printf("\n TX_BUF_CNT: Max number of TX buffer for PS clients");
|
|
printf("\n empty - get Tx data pause settings\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Set/get txpause setting
|
|
*
|
|
* @param txpause A pointer to the Tx data pause parameters structure
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
send_txpause_ioctl(tx_data_pause_para *txpause)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)txpause;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:txpause is not supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates tx_data_pause request and sends to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_txdatapause(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
tx_data_pause_para param;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_txdatapause_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (argc > 2) {
|
|
printf("ERR: Wrong number of arguments\n");
|
|
print_txdatapause_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_TX_DATA_PAUSE;
|
|
if (argc) {
|
|
if (argc >= 1) {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
((atoi(argv[0]) < TX_DATA_PAUSE_DISABLE) ||
|
|
(atoi(argv[0]) > TX_DATA_PAUSE_ENABLE))) {
|
|
printf("ERR: First argument can either be 0 or 1\n");
|
|
print_txdatapause_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (argc == 1) {
|
|
param.action = ACTION_GET;
|
|
if (UAP_FAILURE == send_txpause_ioctl(¶m)) {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
param.action = ACTION_SET;
|
|
param.txpause = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
if (argc == 2) {
|
|
if (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) {
|
|
printf("ERR: Max buffer length must be numeric\n");
|
|
print_txdatapause_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.txbufcnt = (t_u16)A2HEXDECIMAL(argv[1]);
|
|
}
|
|
} else {
|
|
param.action = ACTION_GET;
|
|
}
|
|
if (UAP_FAILURE == send_txpause_ioctl(¶m))
|
|
return UAP_FAILURE;
|
|
if ((argc == 2) && ((t_u16)A2HEXDECIMAL(argv[1]) != param.txbufcnt)) {
|
|
printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("Tx data pause: %s\n",
|
|
(param.txpause == 1) ? "enabled" : "disabled");
|
|
printf("Max number of TX buffer allowed for all PS client: %d\n", param.txbufcnt);
|
|
}
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Process host_cmd
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return N/A
|
|
*/
|
|
int
|
|
apcmd_hostcmd(int argc, char *argv[])
|
|
{
|
|
apcmdbuf *hdr;
|
|
t_u8 *buffer = NULL;
|
|
int ret = UAP_SUCCESS;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
char cmdname[256];
|
|
|
|
if (argc <= 2) {
|
|
printf("Error: invalid no of arguments\n");
|
|
printf("Syntax: ./uaputl hostcmd <hostcmd.conf> <cmdname>\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
buffer = (t_u8 *)malloc(buf_len);
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
memset(buffer, 0, buf_len);
|
|
sprintf(cmdname, "%s", argv[2]);
|
|
ret = prepare_host_cmd_buffer(argv[1], cmdname, buffer);
|
|
if (ret == UAP_FAILURE)
|
|
goto _exit_;
|
|
|
|
/* Locate headers */
|
|
hdr = (apcmdbuf *)buffer;
|
|
cmd_len = hdr->size + BUF_HEADER_SIZE;
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)buffer, &cmd_len, buf_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
hdr->cmd_code &= HostCmd_CMD_ID_MASK;
|
|
if (!hdr->result) {
|
|
printf("UAPHOSTCMD: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result);
|
|
hexdump_data("payload",
|
|
(void *)(buffer + APCMDHEADERLEN),
|
|
hdr->size - (APCMDHEADERLEN -
|
|
BUF_HEADER_SIZE), ' ');
|
|
} else
|
|
printf("UAPHOSTCMD failed: CmdCode=%#04x, Size=%#04x, SeqNum=%#04x, Result=%#04x\n", hdr->cmd_code, hdr->size, hdr->seq_num, hdr->result);
|
|
} else
|
|
printf("ERR:Command sending failed!\n");
|
|
|
|
_exit_:
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef SDIO
|
|
/**
|
|
* @brief Show usage information for cmd52rw command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_cmd52rw_usage(void)
|
|
{
|
|
printf("\nUsage : sdcmd52rw <FN no.> <address> [data]");
|
|
printf("\nOptions: FN no : SDIO function number.");
|
|
printf("\n address: SDIO address");
|
|
printf("\n data: data for SDIO write operation.");
|
|
printf("\n Read is performed if data is not provided.");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Process cmd52 read/write handler
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return N/A
|
|
*/
|
|
int
|
|
apcmd_cmd52_readwrite(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
sdcmd52_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_cmd52rw_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(sdcmd52_para));
|
|
/* Check arguments */
|
|
if (argc < 2 || argc > 3) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_cmd52rw_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
(IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_cmd52rw_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.cmd52_params[0] = (t_u8)A2HEXDECIMAL(argv[0]);
|
|
if (param.cmd52_params[0] > 7) {
|
|
printf("ERR: Invalid function number!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
param.cmd52_params[1] = (t_u8)A2HEXDECIMAL(argv[1]);
|
|
param.action = 0;
|
|
if (argc == 3) {
|
|
if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_cmd52rw_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.cmd52_params[2] = (t_u8)A2HEXDECIMAL(argv[2]);
|
|
param.action = 1;
|
|
}
|
|
param.subcmd = UAP_SDCMD52_RW;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:cmd52rw failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 2)
|
|
printf("Cmd52 read done. ");
|
|
else
|
|
printf("Cmd52 write done. ");
|
|
printf("func=%d, reg=%d, data=0x%02X\n",
|
|
param.cmd52_params[0], param.cmd52_params[1],
|
|
param.cmd52_params[2]);
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Show usage information for addbapara command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_addbapara_usage(void)
|
|
{
|
|
printf("\nUsage : addbapara [timeout txwinsize rxwinsize]");
|
|
printf("\nOptions: timeout : 0 - Disable");
|
|
printf("\n 1 - 65535 : Block Ack Timeout in TU");
|
|
printf("\n txwinsize: Buffer size for ADDBA request");
|
|
printf("\n rxwinsize: Buffer size for ADDBA response");
|
|
printf("\n txamsdu: amsdu for ADDBA request");
|
|
printf("\n rxamsdu: amsdu for ADDBA response");
|
|
printf("\n empty - get ADDBA parameters\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates addbaparam request and send to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_addbapara(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
addba_param param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_addbapara_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if ((argc != 0) && (argc != 5)) {
|
|
printf("ERR:wrong arguments. Only support 0 or 5 arguments\n");
|
|
print_addbapara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_ADDBA_PARA;
|
|
if (argc) {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)
|
|
|| (IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE)
|
|
|| (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
|
|
|| (IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE)
|
|
|| (IS_HEX_OR_DIGIT(argv[4]) == UAP_FAILURE)
|
|
) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_addbapara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.action = 1;
|
|
param.timeout = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
if (param.timeout > DEFAULT_BLOCK_ACK_TIMEOUT) {
|
|
printf("ERR: Block Ack timeout should be in range [1-65535]\n");
|
|
print_addbapara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.txwinsize = (t_u32)A2HEXDECIMAL(argv[1]);
|
|
param.rxwinsize = (t_u32)A2HEXDECIMAL(argv[2]);
|
|
if (param.txwinsize > MAX_TXRX_WINDOW_SIZE ||
|
|
param.rxwinsize > MAX_TXRX_WINDOW_SIZE) {
|
|
printf("ERR: Tx/Rx window size should not be greater than 1023\n");
|
|
print_addbapara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.txamsdu = (t_u8)A2HEXDECIMAL(argv[3]);
|
|
param.rxamsdu = (t_u8)A2HEXDECIMAL(argv[4]);
|
|
if (param.txamsdu > 1 || param.rxamsdu > 1) {
|
|
printf("ERR: Tx/Rx amsdu should not be 0 or 1\n");
|
|
print_addbapara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
param.action = 0;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:ADDBA PARA failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("ADDBA parameters:\n");
|
|
printf("\ttimeout=%d\n", (int)param.timeout);
|
|
printf("\ttxwinsize=%d\n", (int)param.txwinsize);
|
|
printf("\trxwinsize=%d\n", (int)param.rxwinsize);
|
|
printf("\ttxamsdu=%d\n", (int)param.txamsdu);
|
|
printf("\trxamsdu=%d\n", (int)param.rxamsdu);
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for aggrpriotbl command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_aggrpriotbl_usage(void)
|
|
{
|
|
printf("\nUsage : aggrpriotbl <m0> <n0> <m1> <n1> ... <m7> <n7>");
|
|
printf("\nOptions: <mx> : 0 - 7, 0xff to disable AMPDU aggregation.");
|
|
printf("\n <nx> : 0 - 7, 0xff to disable AMSDU aggregation.");
|
|
printf("\n empty - get the priority table\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates aggrpriotbl request and send to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_aggrpriotbl(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
aggr_prio_tbl prio_tbl;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 value;
|
|
int i;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_aggrpriotbl_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(&prio_tbl, 0, sizeof(prio_tbl));
|
|
/* Check arguments */
|
|
if ((argc != 0) && (argc != 16)) {
|
|
printf("ERR:wrong arguments. Only support 0 or 16 arguments\n");
|
|
print_aggrpriotbl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
prio_tbl.subcmd = UAP_AGGR_PRIOTBL;
|
|
if (argc) {
|
|
for (i = 0; i < argc; i++) {
|
|
if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE)) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_aggrpriotbl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
value = (t_u8)A2HEXDECIMAL(argv[i]);
|
|
if ((value > 7) && (value != 0xff)) {
|
|
printf("ERR: Invalid priority, Valid value 0-7, 0xff to disable aggregation.\n");
|
|
print_aggrpriotbl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
prio_tbl.action = 1;
|
|
for (i = 0; i < MAX_NUM_TID; i++) {
|
|
prio_tbl.ampdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2]);
|
|
prio_tbl.amsdu[i] = (t_u8)A2HEXDECIMAL(argv[i * 2 + 1]);
|
|
}
|
|
} else {
|
|
prio_tbl.action = 0;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&prio_tbl;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: priority table failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("AMPDU/AMSDU priority table:");
|
|
for (i = 0; i < MAX_NUM_TID; i++) {
|
|
printf(" %d %d", prio_tbl.ampdu[i], prio_tbl.amsdu[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for addbareject command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_addba_reject_usage(void)
|
|
{
|
|
printf("\nUsage : addbareject <m0> <m1> ... <m7>");
|
|
printf("\nOptions: <mx> : 1 enables rejection of ADDBA request for TidX.");
|
|
printf("\n 0 would accept any ADDBAs for TidX.");
|
|
printf("\n empty - get the addbareject table\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates addbareject request and send to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_addbareject(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
addba_reject_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
int i;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_addba_reject_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if ((argc != 0) && (argc != 8)) {
|
|
printf("ERR:wrong arguments. Only support 0 or 8 arguments\n");
|
|
print_addba_reject_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_ADDBA_REJECT;
|
|
if (argc) {
|
|
for (i = 0; i < argc; i++) {
|
|
if ((ISDIGIT(argv[i]) == UAP_FAILURE) ||
|
|
(atoi(argv[i]) < 0) || (atoi(argv[i]) > 1)) {
|
|
printf("ERR: Only allow 0 or 1\n");
|
|
print_addba_reject_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
param.action = 1;
|
|
for (i = 0; i < MAX_NUM_TID; i++) {
|
|
param.addba_reject[i] = (t_u8)atoi(argv[i]);
|
|
}
|
|
} else {
|
|
param.action = 0;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: addba reject table failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("addba reject table: ");
|
|
for (i = 0; i < MAX_NUM_TID; i++) {
|
|
printf("%d ", param.addba_reject[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates get_fw_info request and send to driver
|
|
*
|
|
*
|
|
* @param pfw_info Pointer to FW information structure
|
|
* @return 0--success, otherwise fail
|
|
*/
|
|
int
|
|
get_fw_info(fw_info *pfw_info)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
memset(pfw_info, 0, sizeof(fw_info));
|
|
pfw_info->subcmd = UAP_FW_INFO;
|
|
pfw_info->action = 0;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return -1;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)pfw_info;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: get fw info failed\n");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for HT Tx command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_ht_tx_usage(void)
|
|
{
|
|
printf("\nUsage : httxcfg [<txcfg>]");
|
|
printf("\nOptions: txcfg : This is a bitmap and should be used as following");
|
|
printf("\n Bit 15-7: Reserved set to 0");
|
|
printf("\n Bit 6: Short GI in 40 Mhz enable/disable");
|
|
printf("\n Bit 5: Short GI in 20 Mhz enable/disable");
|
|
printf("\n Bit 4: Green field enable/disable");
|
|
printf("\n Bit 3-2: Reserved set to 0");
|
|
printf("\n Bit 1: 20/40 Mhz enable disable.");
|
|
printf("\n Bit 0: Reserved set to 0");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Process HT Tx configuration
|
|
* @param argc Number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
apcmd_sys_cfg_ht_tx(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
ht_tx_cfg_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_ht_tx_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (argc == 0) {
|
|
param.action = ACTION_GET;
|
|
} else if (argc == 1) {
|
|
param.action = ACTION_SET;
|
|
param.tx_cfg.httxcap = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
} else {
|
|
print_ht_tx_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_HT_TX_CFG;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: HT Tx configuration failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Handle response */
|
|
if (param.action == ACTION_GET) {
|
|
printf("HT Tx cfg: 0x%08x\n", param.tx_cfg.httxcap);
|
|
}
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for vhtcfg command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_vht_usage(void)
|
|
{
|
|
printf("\nUsage : vhtcfg <band> <txrx> <bwcfg> <vhtcap> <tx_mcs_map>"
|
|
"<rx_mcs_map>");
|
|
printf("\nOption: band : This is the band info for vhtcfg settings.");
|
|
printf("\n 0: Settings for both 2.4G and 5G bands");
|
|
printf("\n 1: Settings for 2.4G band");
|
|
printf("\n 2: Settings for 5G band");
|
|
printf("\n txrx : This parameter specifies the configuration of VHT" "operation for TX or/and VHT capabilities.");
|
|
printf("\n 1: configuration of VHT capabilities tx");
|
|
printf("\n 2: configuration of VHT capabilities rx");
|
|
printf("\n bwcfg : This parameter specifies the bandwidth (BW)"
|
|
"configuration applied to the vhtcfg.");
|
|
printf("\n If <txrx> is 1/3 (Tx operations)");
|
|
printf("\n 0: Tx BW follows the BW (20/40 MHz) from" "11N CFG");
|
|
printf("\n 1: Tx BW follows the BW (80/160/80+80 MHz)" "from VHT Capabilities.");
|
|
printf("\n vhtcap : This parameter specifies the VHT capabilities info.");
|
|
printf("\n tx_mcs_map : This parameter specifies the TX MCS map.");
|
|
printf("\n rx_mcs_map : This parameter specifies the RX MCS map.\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle response of the vhtcfg command
|
|
*
|
|
* @param vhtcfg Pointer to structure eth_priv_vhtcfg
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_vht_response(struct eth_priv_vhtcfg *vhtcfg)
|
|
{
|
|
/* GET operation */
|
|
/* Band */
|
|
if (vhtcfg->band == BAND_SELECT_BG)
|
|
printf("Band: 2.4G\n");
|
|
else
|
|
printf("Band: 5G\n");
|
|
/* BW confi9 */
|
|
if (vhtcfg->txrx & 0x3) {
|
|
if (vhtcfg->bwcfg == 0)
|
|
printf(" BW config: the 11N config\n");
|
|
else
|
|
printf(" BW config: the VHT Capabilities\n");
|
|
}
|
|
/* Tx/Rx */
|
|
if (vhtcfg->txrx & 0x1)
|
|
printf(" VHT operation for Tx: 0x%08x\n",
|
|
vhtcfg->vht_cap_info);
|
|
if (vhtcfg->txrx & 0x2)
|
|
/* VHT capabilities */
|
|
printf(" VHT Capabilities Info: 0x%08x\n",
|
|
vhtcfg->vht_cap_info);
|
|
/* MCS */
|
|
printf(" Tx MCS set: 0x%04x\n", vhtcfg->vht_tx_mcs);
|
|
printf(" Rx MCS set: 0x%04x\n", vhtcfg->vht_rx_mcs);
|
|
}
|
|
|
|
/**
|
|
* @brief Set/Get 11AC configurations
|
|
* @param argc Number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
apcmd_sys_cfg_vht(int argc, char *argv[])
|
|
{
|
|
int opt, i = 0;
|
|
vht_cfg_para param;
|
|
struct eth_priv_vhtcfg vhtcfg;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 *respbuf = NULL, num = 0;
|
|
fw_info fw;
|
|
if (0 == get_fw_info(&fw)) {
|
|
/*check whether support 802.11AC through BAND_AAC bit */
|
|
if (!(fw.fw_bands & BAND_AAC)) {
|
|
printf("ERR: No support 802 11AC.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR: get_fw_info fail\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_vht_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
if (!respbuf) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
|
|
/* Check arguments */
|
|
if ((argc > 6) || (argc < 2)) {
|
|
printf("ERR: Invalid number of arguments.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[0]) < 0) || (atoi(argv[0]) > 2)) {
|
|
printf("ERR: Invalid band selection.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
} else {
|
|
param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
}
|
|
if ((atoi(argv[1]) <= 0) || (atoi(argv[1]) > 3)) {
|
|
printf("ERR: Invalid Tx/Rx selection.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
} else {
|
|
param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]);
|
|
}
|
|
if (argc == 2) {
|
|
param.action = ACTION_GET;
|
|
} else if (argc > 2) {
|
|
param.vht_cfg.band = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
param.vht_cfg.txrx = (t_u32)A2HEXDECIMAL(argv[1]);
|
|
if (argc == 3) {
|
|
printf("ERR: Invalid number of arguments.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc >= 4) {
|
|
if ((atoi(argv[2]) < 0) || (atoi(argv[2]) > 1) ||
|
|
((atoi(argv[2]) == 1) &&
|
|
(atoi(argv[0]) & BAND_SELECT_BG))) {
|
|
printf("ERR: Invalid BW cfg selection.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
} else {
|
|
param.vht_cfg.bwcfg =
|
|
(t_u32)A2HEXDECIMAL(argv[2]);
|
|
}
|
|
param.vht_cfg.vht_cap_info =
|
|
(t_u32)A2HEXDECIMAL(argv[3]);
|
|
if (argc == 4) {
|
|
param.vht_cfg.vht_tx_mcs = 0xffffffff;
|
|
param.vht_cfg.vht_rx_mcs = 0xffffffff;
|
|
} else {
|
|
if (argc == 5) {
|
|
printf("ERR: Invalid number of arguments.\n");
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
param.vht_cfg.vht_tx_mcs =
|
|
(t_u32)A2HEXDECIMAL(argv[4]);
|
|
param.vht_cfg.vht_rx_mcs =
|
|
(t_u32)A2HEXDECIMAL(argv[5]);
|
|
}
|
|
}
|
|
param.action = ACTION_SET;
|
|
} else {
|
|
print_vht_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_VHT_CFG;
|
|
memcpy(respbuf, ¶m, sizeof(vht_cfg_para));
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)respbuf;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: 11ac VHT configuration failed\n");
|
|
close(sockfd);
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Handle response */
|
|
if (param.action == ACTION_GET) {
|
|
/* Process result */
|
|
/* the first attribute is the number of vhtcfg entries */
|
|
num = *respbuf;
|
|
printf("11AC VHT Configuration: \n");
|
|
for (i = 0; i < num; i++) {
|
|
memcpy(&vhtcfg, respbuf + 1 + i * sizeof(vhtcfg),
|
|
sizeof(vhtcfg));
|
|
print_vht_response(&vhtcfg);
|
|
}
|
|
} else
|
|
printf("11AC VHT Configuration success!\n");
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
if (respbuf)
|
|
free(respbuf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for TX BF command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_tx_bf_usage(void)
|
|
{
|
|
printf("\nUsage : httxbfcfg <ACTION> [ACT_DATA]");
|
|
printf("\nOptions: ACTION : 1 - Performs NDP Sounding for PEER");
|
|
printf("\n 2 - TX BF interval in milliseconds");
|
|
printf("\n 3 - Not to perform any sounding");
|
|
printf("\n 4 - TX BF SNR Threshold for peer");
|
|
printf("\n ACT_DATA : Specific data for the above actions");
|
|
printf("\n For 1: PEER MAC and status");
|
|
printf("\n For 2: TX BF interval");
|
|
printf("\n For 3: PEER MAC");
|
|
printf("\n For 4: PEER MAC and SNR");
|
|
printf("\n empty - get action specific settings\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Handle response of the TX BF command
|
|
*
|
|
* @param param Pointer to structure tx_bf_cfg_para
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_tx_bf_response(tx_bf_cfg_para *param)
|
|
{
|
|
int i;
|
|
trigger_sound_args *bf_sound = param->body.bf_sound;
|
|
tx_bf_peer_args *tx_bf_peer = param->body.tx_bf_peer;
|
|
snr_thr_args *bf_snr = param->body.bf_snr;
|
|
bf_periodicity_args *bf_periodicity = param->body.bf_periodicity;
|
|
bf_global_cfg_args *bf_global = ¶m->body.bf_global_cfg;
|
|
|
|
switch (param->bf_action) {
|
|
case BF_GLOBAL_CONFIGURATION:
|
|
printf("Global BF Status :%s\n",
|
|
bf_global->bf_enbl ? "ENABLED" : "DISABLED");
|
|
printf("Global Sounding Status :%s\n",
|
|
bf_global->sounding_enbl ? "ENABLED" : "DISABLED");
|
|
printf("Default FB Type :%d\n", bf_global->fb_type);
|
|
printf("Default SNR Threshold :%d\n", bf_global->snr_threshold);
|
|
printf("Default Sounding Interval :%d\n",
|
|
bf_global->sounding_interval);
|
|
printf("Beamforming Mode :%d\n", bf_global->bf_mode);
|
|
break;
|
|
case TRIGGER_SOUNDING_FOR_PEER:
|
|
printf("PEER MAC = %02X:%02X:%02X:%02X:%02X:%02X, STATUS = %s\n", bf_sound->peer_mac[0], bf_sound->peer_mac[1], bf_sound->peer_mac[2], bf_sound->peer_mac[3], bf_sound->peer_mac[4], bf_sound->peer_mac[5], bf_sound->status ? "Failure" : "Success");
|
|
break;
|
|
case SET_GET_BF_PERIODICITY:
|
|
printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, Interval (ms) = %d\n", bf_periodicity->peer_mac[0], bf_periodicity->peer_mac[1], bf_periodicity->peer_mac[2], bf_periodicity->peer_mac[3], bf_periodicity->peer_mac[4], bf_periodicity->peer_mac[5], bf_periodicity->interval);
|
|
break;
|
|
case TX_BF_FOR_PEER_ENBL:
|
|
for (i = 0; i < param->no_of_peers; i++) {
|
|
printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
tx_bf_peer->peer_mac[0], tx_bf_peer->peer_mac[1],
|
|
tx_bf_peer->peer_mac[2], tx_bf_peer->peer_mac[3],
|
|
tx_bf_peer->peer_mac[4],
|
|
tx_bf_peer->peer_mac[5]);
|
|
printf("BF Status : %s\n",
|
|
tx_bf_peer->bf_enbl ? "ENABLED" : "DISABLED");
|
|
printf("Sounding Status : %s\n",
|
|
tx_bf_peer->
|
|
sounding_enbl ? "ENABLED" : "DISABLED");
|
|
printf("FB Type : %d\n", tx_bf_peer->fb_type);
|
|
tx_bf_peer++;
|
|
}
|
|
break;
|
|
case SET_SNR_THR_PEER:
|
|
for (i = 0; i < param->no_of_peers; i++) {
|
|
printf("PEER MAC = %02x:%02x:%02x:%02x:%02x:%02x, SNR = %d\n", bf_snr->peer_mac[0], bf_snr->peer_mac[1], bf_snr->peer_mac[2], bf_snr->peer_mac[3], bf_snr->peer_mac[4], bf_snr->peer_mac[5], bf_snr->snr);
|
|
bf_snr++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** Tx BF Global conf argument index */
|
|
#define BF_ENABLE_PARAM 1
|
|
#define SOUND_ENABLE_PARAM 2
|
|
#define FB_TYPE_PARAM 3
|
|
#define SNR_THRESHOLD_PARAM 4
|
|
#define SOUND_INTVL_PARAM 5
|
|
#define BF_MODE_PARAM 6
|
|
#define BF_CFG_ACT_GET 0
|
|
#define BF_CFG_ACT_SET 1
|
|
|
|
/**
|
|
* @brief Creates TX BF request and send to driver
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_cfg_tx_bf(int argc, char *argv[])
|
|
{
|
|
int opt, ret = UAP_FAILURE;
|
|
tx_bf_cfg_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u32 bf_action = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_tx_bf_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (argc < 1) {
|
|
printf("ERR: wrong arguments.\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
((atoi(argv[0]) < BF_GLOBAL_CONFIGURATION) ||
|
|
(atoi(argv[0]) > SET_SNR_THR_PEER))) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
bf_action = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
param.subcmd = UAP_TX_BF_CFG;
|
|
param.bf_action = bf_action;
|
|
switch (bf_action) {
|
|
case BF_GLOBAL_CONFIGURATION:
|
|
if (argc != 1 && argc != 7) {
|
|
printf("Invalid argument for Global BF Configuration\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
param.bf_cmd_action = BF_CFG_ACT_GET;
|
|
param.action = ACTION_GET;
|
|
} else {
|
|
param.bf_cmd_action = BF_CFG_ACT_SET;
|
|
param.action = ACTION_SET;
|
|
param.body.bf_global_cfg.bf_enbl =
|
|
atoi(argv[BF_ENABLE_PARAM]);
|
|
param.body.bf_global_cfg.sounding_enbl =
|
|
atoi(argv[SOUND_ENABLE_PARAM]);
|
|
param.body.bf_global_cfg.fb_type =
|
|
atoi(argv[FB_TYPE_PARAM]);
|
|
param.body.bf_global_cfg.snr_threshold =
|
|
atoi(argv[SNR_THRESHOLD_PARAM]);
|
|
param.body.bf_global_cfg.sounding_interval =
|
|
atoi(argv[SOUND_INTVL_PARAM]);
|
|
param.body.bf_global_cfg.bf_mode =
|
|
atoi(argv[BF_MODE_PARAM]);
|
|
}
|
|
break;
|
|
case TRIGGER_SOUNDING_FOR_PEER:
|
|
if (argc != 2) {
|
|
printf("ERR: wrong arguments.\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((ret =
|
|
mac2raw(argv[1],
|
|
param.body.bf_sound[0].peer_mac)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n",
|
|
ret == UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
param.bf_cmd_action = BF_CFG_ACT_SET;
|
|
param.action = ACTION_SET;
|
|
break;
|
|
case SET_GET_BF_PERIODICITY:
|
|
if (argc != 2 && argc != 3) {
|
|
printf("ERR: wrong arguments.\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((ret =
|
|
mac2raw(argv[1],
|
|
param.body.bf_periodicity[0].peer_mac)) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n",
|
|
ret == UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc == 3) {
|
|
if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
param.body.bf_periodicity[0].interval =
|
|
(t_u32)A2HEXDECIMAL(argv[2]);
|
|
param.bf_cmd_action = BF_CFG_ACT_SET;
|
|
param.action = ACTION_SET;
|
|
} else {
|
|
param.bf_cmd_action = BF_CFG_ACT_GET;
|
|
param.action = ACTION_GET;
|
|
}
|
|
break;
|
|
case TX_BF_FOR_PEER_ENBL:
|
|
if (argc != 1 && argc != 5) {
|
|
printf("ERR: wrong arguments.\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
param.bf_cmd_action = BF_CFG_ACT_GET;
|
|
param.action = ACTION_GET;
|
|
} else {
|
|
if ((ret =
|
|
mac2raw(argv[1],
|
|
param.body.tx_bf_peer[0].peer_mac)) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n",
|
|
ret ==
|
|
UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
param.body.tx_bf_peer->bf_enbl = atoi(argv[2]);
|
|
param.body.tx_bf_peer->sounding_enbl = atoi(argv[3]);
|
|
param.body.tx_bf_peer->fb_type = atoi(argv[4]);
|
|
param.bf_cmd_action = BF_CFG_ACT_SET;
|
|
param.action = ACTION_SET;
|
|
}
|
|
break;
|
|
case SET_SNR_THR_PEER:
|
|
if (argc != 1 && argc != 3) {
|
|
printf("ERR: wrong arguments.\n");
|
|
print_tx_bf_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
param.bf_cmd_action = BF_CFG_ACT_GET;
|
|
param.action = ACTION_GET;
|
|
} else {
|
|
if ((ret =
|
|
mac2raw(argv[1],
|
|
param.body.bf_snr[0].peer_mac)) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n",
|
|
ret ==
|
|
UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
param.body.bf_snr[0].snr = (t_u8)A2HEXDECIMAL(argv[2]);
|
|
param.bf_cmd_action = BF_CFG_ACT_SET;
|
|
param.action = ACTION_SET;
|
|
}
|
|
break;
|
|
default:
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: TX BF configuration failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
printf("TX BF configuration successful\n");
|
|
/* Handle response */
|
|
if (param.action == ACTION_GET)
|
|
print_tx_bf_response(¶m);
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for hscfg command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_hscfg_usage(void)
|
|
{
|
|
printf("\nUsage : hscfg [condition [[GPIO# [gap]]]]");
|
|
printf("\nOptions: condition : bit 0 = 1 -- broadcast data");
|
|
printf("\n bit 1 = 1 -- unicast data");
|
|
printf("\n bit 2 = 1 -- mac event");
|
|
printf("\n bit 3 = 1 -- multicast packet");
|
|
printf("\n bit 6 = 1 -- mgmt frame received");
|
|
printf("\n GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host");
|
|
printf("\n or 0xff interface (e.g. SDIO) used to wakeup the host");
|
|
printf("\n gap: time between wakeup signal and wakeup event (in milliseconds)");
|
|
printf("\n or 0xff for special setting when GPIO is used to wakeup host");
|
|
printf("\n empty - get current host sleep parameters\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates host sleep parameter request and send to driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_hscfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int i = 0;
|
|
ds_hs_cfg hscfg;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
if ((argc == 2) && strstr(argv[1], "-1"))
|
|
strcpy(argv[1], "0xffff");
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_hscfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(&hscfg, 0, sizeof(hscfg));
|
|
hscfg.subcmd = UAP_HS_CFG;
|
|
/* Check arguments */
|
|
if (argc > 3) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_hscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc) {
|
|
for (i = 0; i < argc; i++) {
|
|
if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
|
|
printf("ERR: Invalid argument %s\n", argv[i]);
|
|
print_hscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (argc) {
|
|
hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION;
|
|
hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
if (hscfg.conditions >= 0xffff)
|
|
hscfg.conditions = HS_CFG_CANCEL;
|
|
if ((hscfg.conditions != HS_CFG_CANCEL) &&
|
|
(hscfg.conditions & ~HS_CFG_CONDITION_MASK)) {
|
|
printf("ERR:Illegal conditions 0x%x\n",
|
|
hscfg.conditions);
|
|
print_hscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc > 1) {
|
|
hscfg.flags |= HS_CFG_FLAG_GPIO;
|
|
hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]);
|
|
if (hscfg.gpio > 255) {
|
|
printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio);
|
|
print_hscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (argc > 2) {
|
|
hscfg.flags |= HS_CFG_FLAG_GAP;
|
|
hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]);
|
|
}
|
|
} else {
|
|
hscfg.flags = HS_CFG_FLAG_GET;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&hscfg;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_HS_CFG failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("Host sleep parameters:\n");
|
|
printf("\tconditions=%d\n", (int)hscfg.conditions);
|
|
printf("\tGPIO=%d\n", (int)hscfg.gpio);
|
|
printf("\tgap=%d\n", (int)hscfg.gap);
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for hssetpara command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_hssetpara_usage(void)
|
|
{
|
|
printf("\nUsage : hssetpara condition [[GPIO# [gap]]]");
|
|
printf("\nOptions: condition : bit 0 = 1 -- broadcast data");
|
|
printf("\n bit 1 = 1 -- unicast data");
|
|
printf("\n bit 2 = 1 -- mac event");
|
|
printf("\n bit 3 = 1 -- multicast packet");
|
|
printf("\n bit 6 = 1 -- mgmt frame received");
|
|
printf("\n GPIO: the pin number (e.g. 0-7) of GPIO used to wakeup the host");
|
|
printf("\n or 0xff interface (e.g. SDIO) used to wakeup the host");
|
|
printf("\n gap: time between wakeup signal and wakeup event (in milliseconds)");
|
|
printf("\n or 0xff for special setting when GPIO is used to wakeup host\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates host sleep parameter request and send to driver
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_hssetpara(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int i = 0;
|
|
ds_hs_cfg hscfg;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
if ((argc == 2) && strstr(argv[1], "-1"))
|
|
strcpy(argv[1], "0xffff");
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_hssetpara_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(&hscfg, 0, sizeof(hscfg));
|
|
hscfg.subcmd = UAP_HS_SET_PARA;
|
|
/* Check arguments */
|
|
if ((argc < 1) || (argc > 3)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_hssetpara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < argc; i++) {
|
|
if (IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) {
|
|
printf("ERR: Invalid argument %s\n", argv[i]);
|
|
print_hssetpara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
hscfg.flags |= HS_CFG_FLAG_SET | HS_CFG_FLAG_CONDITION;
|
|
hscfg.conditions = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
if (hscfg.conditions >= 0xffff)
|
|
hscfg.conditions = HS_CFG_CANCEL;
|
|
if ((hscfg.conditions != HS_CFG_CANCEL) &&
|
|
(hscfg.conditions & ~HS_CFG_CONDITION_MASK)) {
|
|
printf("ERR:Illegal conditions 0x%x\n", hscfg.conditions);
|
|
print_hssetpara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc > 1) {
|
|
hscfg.flags |= HS_CFG_FLAG_GPIO;
|
|
hscfg.gpio = (t_u32)A2HEXDECIMAL(argv[1]);
|
|
if (hscfg.gpio > 255) {
|
|
printf("ERR:Illegal gpio 0x%x\n", hscfg.gpio);
|
|
print_hssetpara_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (argc > 2) {
|
|
hscfg.flags |= HS_CFG_FLAG_GAP;
|
|
hscfg.gap = (t_u32)A2HEXDECIMAL(argv[2]);
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)&hscfg;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_HS_SET_PARA failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("Host sleep parameters setting successful!\n");
|
|
printf("\tconditions=%d\n", (int)hscfg.conditions);
|
|
printf("\tGPIO=%d\n", (int)hscfg.gpio);
|
|
printf("\tgap=%d\n", (int)hscfg.gap);
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief get dfs repeater mode
|
|
*
|
|
* @param mode status of DFS repeater mode is returned here
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
uap_ioctl_dfs_repeater_mode(int *mode)
|
|
{
|
|
struct ifreq ifr;
|
|
dfs_repeater_mode param;
|
|
t_s32 sockfd;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
param.action = ACTION_GET;
|
|
param.subcmd = UAP_DFS_REPEATER_MODE;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
printf("ERR:UAP_DFS_REPEATER_MODE is not"
|
|
"supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
*mode = (int)param.mode;
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Get CAC timer status
|
|
*
|
|
* @param mode status of CAC timer is returned here
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
uap_ioctl_cac_timer_status(unsigned int *mode)
|
|
{
|
|
struct ifreq ifr;
|
|
cac_timer_status param;
|
|
t_s32 sockfd;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
param.action = ACTION_GET;
|
|
param.subcmd = UAP_CAC_TIMER_STATUS;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
printf("ERR:UAP_CAC_TIMER_STATUS is not"
|
|
"supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
*mode = (int)param.mode;
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Set/get power mode
|
|
*
|
|
* @param pm A pointer to ps_mgmt structure
|
|
* @param flag flag for query
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
send_power_mode_ioctl(ps_mgmt * pm, int flag)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u32 result = 0;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)pm;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_POWER_MODE, &ifr)) {
|
|
memcpy((void *)&result, (void *)pm, sizeof(result));
|
|
if (result == 1) {
|
|
printf("ERR:Power mode needs to be disabled before modifying it\n");
|
|
} else {
|
|
perror("");
|
|
printf("ERR:UAP_POWER_MODE is not supported by %s\n",
|
|
dev_name);
|
|
}
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (flag) {
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
switch (pm->ps_mode) {
|
|
case 0:
|
|
printf("power mode = Disabled\n");
|
|
break;
|
|
case 1:
|
|
printf("power mode = Periodic DTIM PS\n");
|
|
break;
|
|
case 2:
|
|
printf("power mode = Inactivity based PS \n");
|
|
break;
|
|
}
|
|
if (pm->flags & PS_FLAG_SLEEP_PARAM) {
|
|
printf("Sleep param:\n");
|
|
printf("\tctrl_bitmap=%d\n", (int)pm->sleep_param.ctrl_bitmap);
|
|
printf("\tmin_sleep=%d us\n", (int)pm->sleep_param.min_sleep);
|
|
printf("\tmax_sleep=%d us\n", (int)pm->sleep_param.max_sleep);
|
|
}
|
|
if (pm->flags & PS_FLAG_INACT_SLEEP_PARAM) {
|
|
printf("Inactivity sleep param:\n");
|
|
printf("\tinactivity_to=%d us\n",
|
|
(int)pm->inact_param.inactivity_to);
|
|
printf("\tmin_awake=%d us\n", (int)pm->inact_param.min_awake);
|
|
printf("\tmax_awake=%d us\n", (int)pm->inact_param.max_awake);
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the pscfg command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_pscfg_usage(void)
|
|
{
|
|
printf("\nUsage : pscfg [MODE] [CTRL INACTTO MIN_SLEEP MAX_SLEEP MIN_AWAKE MAX_AWAKE]");
|
|
printf("\nOptions: MODE : 0 - disable power mode");
|
|
printf("\n 1 - periodic DTIM power save mode");
|
|
printf("\n 2 - inactivity based power save mode");
|
|
printf("\n PS PARAMS:");
|
|
printf("\n CTRL: 0 - disable protection frame Tx before PS");
|
|
printf("\n 1 - enable protection frame Tx before PS");
|
|
printf("\n INACTTO: Inactivity timeout in miroseconds");
|
|
printf("\n MIN_SLEEP: Minimum sleep duration in microseconds");
|
|
printf("\n MAX_SLEEP: Maximum sleep duration in miroseconds");
|
|
printf("\n MIN_AWAKE: Minimum awake duration in microseconds");
|
|
printf("\n MAX_AWAKE: Maximum awake duration in microseconds");
|
|
printf("\n MIN_AWAKE,MAX_AWAKE only valid for inactivity based power save mode");
|
|
printf("\n empty - get current power mode\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates power mode request and send to driver
|
|
* and sends to the driver
|
|
*
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_pscfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
ps_mgmt pm;
|
|
int ret = UAP_SUCCESS;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_pscfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(&pm, 0, sizeof(ps_mgmt));
|
|
/* Check arguments */
|
|
if ((argc > 7) ||
|
|
((argc != 0) && (argc != 1) && (argc != 5) && (argc != 7))) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc) {
|
|
if (send_power_mode_ioctl(&pm, 1) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 2)) {
|
|
printf("ERR:Illegal power mode %s. Must be either '0' '1' or '2'.\n", argv[0]);
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
pm.flags = PS_FLAG_PS_MODE;
|
|
pm.ps_mode = atoi(argv[0]);
|
|
if ((pm.ps_mode == PS_MODE_DISABLE) && (argc > 1)) {
|
|
printf("ERR: Illegal parameter for disable power mode\n");
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((pm.ps_mode != PS_MODE_INACTIVITY) && (argc > 5)) {
|
|
printf("ERR:Min awake period and Max awake period are valid only for inactivity based power save mode\n");
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc >= 5) {
|
|
if ((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) ||
|
|
(atoi(argv[1]) > 1)) {
|
|
printf("ERR:Illegal ctrl bitmap = %s. Must be either '0' or '1'.\n", argv[1]);
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
pm.flags |=
|
|
PS_FLAG_SLEEP_PARAM | PS_FLAG_INACT_SLEEP_PARAM;
|
|
pm.sleep_param.ctrl_bitmap = atoi(argv[1]);
|
|
if ((ISDIGIT(argv[2]) == 0) || (ISDIGIT(argv[3]) == 0)
|
|
|| (ISDIGIT(argv[4]) == 0)) {
|
|
printf("ERR:Illegal parameter\n");
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
pm.inact_param.inactivity_to = atoi(argv[2]);
|
|
pm.sleep_param.min_sleep = atoi(argv[3]);
|
|
pm.sleep_param.max_sleep = atoi(argv[4]);
|
|
if (pm.sleep_param.min_sleep > pm.sleep_param.max_sleep) {
|
|
printf("ERR: MIN_SLEEP value should be less than or equal to MAX_SLEEP\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (pm.sleep_param.min_sleep < PS_SLEEP_PARAM_MIN ||
|
|
((pm.sleep_param.max_sleep > PS_SLEEP_PARAM_MAX) &&
|
|
pm.sleep_param.ctrl_bitmap)) {
|
|
printf("ERR: Incorrect value of sleep period. Please check README\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 7) {
|
|
if ((ISDIGIT(argv[5]) == 0) ||
|
|
(ISDIGIT(argv[6]) == 0)) {
|
|
printf("ERR:Illegal parameter\n");
|
|
print_pscfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
pm.inact_param.min_awake = atoi(argv[5]);
|
|
pm.inact_param.max_awake = atoi(argv[6]);
|
|
if (pm.inact_param.min_awake >
|
|
pm.inact_param.max_awake) {
|
|
printf("ERR: MIN_AWAKE value should be less than or equal to MAX_AWAKE\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (pm.inact_param.min_awake <
|
|
PS_AWAKE_PERIOD_MIN) {
|
|
printf("ERR: Incorrect value of MIN_AWAKE period.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ret = send_power_mode_ioctl(&pm, 0);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Get bss status started/stopped
|
|
*
|
|
* @param current bss status
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
static int
|
|
get_bss_status(int *status)
|
|
{
|
|
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_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) {
|
|
if (tlv->bss_status == 0)
|
|
*status = UAP_BSS_STOP;
|
|
else
|
|
*status = UAP_BSS_START;
|
|
} else {
|
|
printf("ERR:Could not get BSS status!\n");
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief start/stop/reset bss
|
|
*
|
|
* @param mode bss control mode
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
send_bss_ctl_ioctl(int mode)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u32 data = (t_u32)mode;
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&data;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_BSS_CTRL, &ifr)) {
|
|
printf("ERR:UAP_BSS_CTRL fail, result=%d\n", (int)data);
|
|
switch (mode) {
|
|
case UAP_BSS_START:
|
|
if (data == BSS_FAILURE_START_INVAL)
|
|
printf("ERR:Could not start BSS! Invalid BSS parameters.\n");
|
|
else
|
|
printf("ERR:Could not start BSS!\n");
|
|
break;
|
|
case UAP_BSS_STOP:
|
|
printf("ERR:Could not stop BSS!\n");
|
|
break;
|
|
case UAP_BSS_RESET:
|
|
printf("ERR:Could not reset system!\n");
|
|
break;
|
|
}
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
switch (mode) {
|
|
case UAP_BSS_START:
|
|
printf("BSS start successful!\n");
|
|
break;
|
|
case UAP_BSS_STOP:
|
|
printf("BSS stop successful!\n");
|
|
break;
|
|
case UAP_BSS_RESET:
|
|
printf("System reset successful!\n");
|
|
break;
|
|
}
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sys_reset command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sys_reset_usage(void)
|
|
{
|
|
printf("\nUsage : sys_reset\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a sys_reset request and sends to the driver
|
|
*
|
|
* Usage: "sys_reset"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_reset(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int ret = UAP_SUCCESS;
|
|
ps_mgmt pm;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sys_reset_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 0) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_sys_reset_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(&pm, 0, sizeof(ps_mgmt));
|
|
pm.flags = PS_FLAG_PS_MODE;
|
|
pm.ps_mode = PS_MODE_DISABLE;
|
|
if (send_power_mode_ioctl(&pm, 0) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
ret = send_bss_ctl_ioctl(UAP_BSS_RESET);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the bss_start command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_bss_start_usage(void)
|
|
{
|
|
printf("\nUsage : bss_start\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a BSS start request and sends to the driver
|
|
*
|
|
* Usage: "bss_start"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_bss_start(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
t_u8 *buf = NULL;
|
|
t_u16 buf_len = 0;
|
|
int status = 0;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_bss_start_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 0) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_bss_start_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (get_bss_status(&status) != UAP_SUCCESS) {
|
|
printf("ERR:Cannot get current bss status!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (status == UAP_BSS_START) {
|
|
printf("ERR: Could not start BSS! BSS already started!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Query BSS settings */
|
|
|
|
/* Alloc buf for command */
|
|
buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t);
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset((char *)buf, 0, buf_len);
|
|
|
|
/* Get all parametes first */
|
|
if (get_bss_config(buf) == UAP_FAILURE) {
|
|
printf("ERR:Reading current bss configuration\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
ret = check_bss_config(buf + sizeof(apcmdbuf_bss_configure));
|
|
|
|
if (ret == UAP_FAILURE) {
|
|
printf("ERR: Wrong bss configuration!\n");
|
|
goto done;
|
|
}
|
|
|
|
ret = send_bss_ctl_ioctl(UAP_BSS_START);
|
|
|
|
done:
|
|
if (buf)
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the bss_stop command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_bss_stop_usage(void)
|
|
{
|
|
printf("\nUsage : bss_stop\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a BSS stop request and sends to the driver
|
|
*
|
|
* Usage: "bss_stop"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_bss_stop(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int status = 0;
|
|
int ret = UAP_SUCCESS;
|
|
unsigned int cac_timer = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_bss_stop_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind; /* Check arguments */
|
|
|
|
if (argc != 0) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_bss_stop_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (get_bss_status(&status) != UAP_SUCCESS) {
|
|
printf("ERR:Cannot get current bss status!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((status != UAP_BSS_STOP)
|
|
|| ((uap_ioctl_cac_timer_status(&cac_timer) == UAP_SUCCESS)
|
|
&& (cac_timer))
|
|
)
|
|
ret = send_bss_ctl_ioctl(UAP_BSS_STOP);
|
|
else {
|
|
printf("ERR: Could not stop BSS! BSS already stopped!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
print_skip_cac_usage(void)
|
|
{
|
|
printf("\nUsage : skip_cac [MODE]");
|
|
printf("\nOptions: MODE : 0 - Disable skip CAC mode");
|
|
printf("\n 1 - Enable skip CAC mode");
|
|
printf("\n empty - get skip CAC mode\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Skip CAC for next immediate BSS_START
|
|
*
|
|
* Usage: "skip_cac [1/0]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_skip_cac(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
skip_cac_para param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_skip_cac_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:wrong arguments. Only support 1 argument\n");
|
|
print_skip_cac_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
param.subcmd = UAP_SKIP_CAC;
|
|
if (argc) {
|
|
if (argc == 1) {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
((atoi(argv[0]) < 0) || (atoi(argv[0]) > 1))) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_skip_cac_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
param.action = 1;
|
|
param.skip_cac = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
} else {
|
|
param.action = 0;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
if (argc)
|
|
printf("ERR:skip_cac set failed\n");
|
|
else {
|
|
perror("");
|
|
printf("ERR:skip_cac get failed\n");
|
|
}
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
if (param.skip_cac == 1) {
|
|
printf("skip CAC mode: enabled\n");
|
|
} else {
|
|
printf("skip CAC mode: disabled\n");
|
|
}
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sta_list command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sta_list_usage(void)
|
|
{
|
|
printf("\nUsage : sta_list\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a STA list request and sends to the driver
|
|
*
|
|
* Usage: "sta_list"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sta_list(int argc, char *argv[])
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
sta_list list;
|
|
int i = 0;
|
|
int opt;
|
|
int rssi = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sta_list_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 0) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_sta_list_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(&list, 0, sizeof(sta_list));
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&list;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_GET_STA_LIST, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_GET_STA_LIST is not supported by %s\n",
|
|
dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("Number of STA = %d\n\n", list.sta_count);
|
|
|
|
for (i = 0; i < list.sta_count; i++) {
|
|
printf("STA %d information:\n", i + 1);
|
|
printf("=====================\n");
|
|
printf("MAC Address: ");
|
|
print_mac(list.info[i].mac_address);
|
|
printf("\nPower mgmt status: %s\n",
|
|
(list.info[i].power_mgmt_status ==
|
|
0) ? "active" : "power save");
|
|
printf("Mode: %s\n",
|
|
(list.info[i].bandmode ==
|
|
BAND_B) ? "11b," : (list.info[i].bandmode ==
|
|
BAND_G) ? "11g," : (list.info[i].
|
|
bandmode ==
|
|
BAND_A) ? "11a,"
|
|
: (list.info[i].bandmode ==
|
|
BAND_GN) ? "2.4G_11n," : (list.info[i].bandmode ==
|
|
BAND_AN) ? "5G_11n,"
|
|
: (list.info[i].bandmode ==
|
|
BAND_GAC) ? "2.4G_11ac," : (list.info[i].bandmode ==
|
|
BAND_AAC) ? "5G_11ac,"
|
|
: (list.info[i].bandmode ==
|
|
BAND_GAX) ? "2.4G_11ax," : (list.info[i].bandmode ==
|
|
BAND_AAX) ? "5G_11ax," :
|
|
"unknown");
|
|
/** On some platform, s8 is same as unsigned char*/
|
|
rssi = (int)list.info[i].rssi;
|
|
if (rssi > 0x7f)
|
|
rssi = -(256 - rssi);
|
|
printf("Rssi : %d dBm\n\n", rssi);
|
|
if (list.info[i].ie_len)
|
|
hexdump_data("IE", (void *)list.info[i].ie_buf,
|
|
list.info[i].ie_len, ' ');
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sta_deauth command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sta_deauth_usage(void)
|
|
{
|
|
printf("\nUsage : sta_deauth <STA_MAC_ADDRESS>\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a STA deauth request and sends to the driver
|
|
*
|
|
* Usage: "sta_deauth <STA_MAC_ADDRESS>"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sta_deauth(int argc, char *argv[])
|
|
{
|
|
APCMDBUF_STA_DEAUTH *cmd_buf = 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;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sta_deauth_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 1) {
|
|
printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n");
|
|
print_sta_deauth_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Initialize the command length */
|
|
cmd_len = sizeof(APCMDBUF_STA_DEAUTH);
|
|
|
|
/* 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_STA_DEAUTH *)buffer;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->cmd_code = APCMD_STA_DEAUTH;
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
if ((ret = mac2raw(argv[0], cmd_buf->sta_mac_address)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" :
|
|
ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast");
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* 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_STA_DEAUTH | APCMD_RESP_CHECK)) {
|
|
printf("ERR:Corrupted response!\n");
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Print response */
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("Deauthentication successful!\n");
|
|
} else {
|
|
printf("ERR:Deauthentication unsuccessful!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sta_deauth_ext command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sta_deauth_ext_usage(void)
|
|
{
|
|
printf("\nUsage : sta_deauth <STA_MAC_ADDRESS> <REASCON_CODE>\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a STA deauth request and sends to the driver
|
|
*
|
|
* Usage: "sta_deauth <STA_MAC_ADDRESS><REASON_CODE>"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sta_deauth_ext(int argc, char *argv[])
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
deauth_param param;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u32 result = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sta_deauth_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 2) {
|
|
printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS, REASON_CODE.\n");
|
|
print_sta_deauth_ext_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(¶m, 0, sizeof(deauth_param));
|
|
|
|
if ((ret = mac2raw(argv[0], param.mac_addr)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" :
|
|
ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) ||
|
|
(atoi(argv[1]) > MAX_DEAUTH_REASON_CODE)) {
|
|
printf("ERR: Invalid input for reason code\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
param.reason_code = (t_u16)A2HEXDECIMAL(argv[1]);
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_STA_DEAUTH, &ifr)) {
|
|
memcpy((void *)&result, (void *)¶m, sizeof(result));
|
|
if (result == 1)
|
|
printf("ERR:UAP_STA_DEAUTH fail\n");
|
|
else
|
|
perror("");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("Station deauth successful\n");
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the radioctrl command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_radio_ctl_usage(void)
|
|
{
|
|
printf("\nUsage : radioctrl [ 0 | 1 ]\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a Radio control request and sends to the driver
|
|
*
|
|
* Usage: "radioctrl [0 | 1]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_radio_ctl(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int param[2] = { 0, 0 }; /* action (Set/Get), Control (ON/OFF) */
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_radio_ctl_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:wrong arguments! Only 1 or 0 arguments are supported.\n");
|
|
print_radio_ctl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc && (is_input_valid(RADIOCONTROL, argc, argv) != UAP_SUCCESS)) {
|
|
print_radio_ctl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc) {
|
|
param[0] = ACTION_SET;
|
|
param[1] = atoi(argv[0]);
|
|
}
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)param;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_RADIO_CTL, &ifr)) {
|
|
printf("ERR:UAP_RADIO_CTL fail\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc)
|
|
printf("Radio setting successful\n");
|
|
else
|
|
printf("Radio is %s.\n", (param[1]) ? "on" : "off");
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the txratecfg command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_txratecfg_usage(void)
|
|
{
|
|
printf("\nUsage : txratecfg <datarate index> Index should be one of the following.\n");
|
|
printf("\n [l] is <format>");
|
|
printf("\n <format> - This parameter specifies the data rate format used in this command");
|
|
printf("\n 0: LG");
|
|
printf("\n 1: HT");
|
|
printf("\n 2: VHT");
|
|
printf("\n 3: HE");
|
|
printf("\n 0xff: Auto");
|
|
printf("\n");
|
|
printf("\n [m] is <index>");
|
|
printf("\n <index> - This parameter specifies the rate or MCS index");
|
|
printf("\n If <format> is 0 (LG),");
|
|
printf("\n 0 1 Mbps");
|
|
printf("\n 1 2 Mbps");
|
|
printf("\n 2 5.5 Mbps");
|
|
printf("\n 3 11 Mbps");
|
|
printf("\n 4 6 Mbps");
|
|
printf("\n 5 9 Mbps");
|
|
printf("\n 6 12 Mbps");
|
|
printf("\n 7 18 Mbps");
|
|
printf("\n 8 24 Mbps");
|
|
printf("\n 9 36 Mbps");
|
|
printf("\n 10 48 Mbps");
|
|
printf("\n 11 54 Mbps");
|
|
printf("\n If <format> is 1 (HT), ");
|
|
printf("\n 0 MCS0");
|
|
printf("\n 1 MCS1");
|
|
printf("\n 2 MCS2");
|
|
printf("\n 3 MCS3");
|
|
printf("\n 4 MCS4");
|
|
printf("\n 5 MCS5");
|
|
printf("\n 6 MCS6");
|
|
printf("\n 7 MCS7");
|
|
printf("\n 8 MCS8");
|
|
printf("\n 9 MCS9");
|
|
printf("\n 10 MCS10");
|
|
printf("\n 11 MCS11");
|
|
printf("\n 12 MCS12");
|
|
printf("\n 13 MCS13");
|
|
printf("\n 14 MCS14");
|
|
printf("\n 15 MCS15");
|
|
printf("\n 32 MCS32");
|
|
printf("\n If <format> is 2 (VHT), ");
|
|
printf("\n 0 MCS0");
|
|
printf("\n 1 MCS1");
|
|
printf("\n 2 MCS2");
|
|
printf("\n 3 MCS3");
|
|
printf("\n 4 MCS4");
|
|
printf("\n 5 MCS5");
|
|
printf("\n 6 MCS6");
|
|
printf("\n 7 MCS7");
|
|
printf("\n 8 MCS8");
|
|
printf("\n 9 MCS9");
|
|
printf("\n [n] is <nss>");
|
|
printf("\n <nss> - This parameter specifies the NSS. It is valid only for VHT");
|
|
printf("\n If <format> is 2 (VHT), ");
|
|
printf("\n 1 NSS1");
|
|
printf("\n 2 NSS2");
|
|
printf("\n If <format> is 3 (HE), ");
|
|
printf("\n 0 MCS0");
|
|
printf("\n 1 MCS1");
|
|
printf("\n 2 MCS2");
|
|
printf("\n 3 MCS3");
|
|
printf("\n 4 MCS4");
|
|
printf("\n 5 MCS5");
|
|
printf("\n 6 MCS6");
|
|
printf("\n 7 MCS7");
|
|
printf("\n 8 MCS8");
|
|
printf("\n 9 MCS9");
|
|
printf("\n 10 MCS10");
|
|
printf("\n 11 MCS11");
|
|
printf("\n [n] is <nss>");
|
|
printf("\n <nss> - This parameter specifies the NSS. It is valid only for HE");
|
|
printf("\n If <format> is 3 (HE), ");
|
|
printf("\n 1 NSS1");
|
|
printf("\n 2 NSS2");
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a Tx Rate Config get request and sends to the driver
|
|
* @param rate_config Tx rate config struct
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
static int
|
|
get_tx_rate_cfg(tx_rate_cfg_t *rate_config)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(rate_config, 0, sizeof(tx_rate_cfg_t));
|
|
rate_config->subcmd = UAP_TX_RATE_CFG;
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)rate_config;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
printf("ERR:UAP_IOCTL_CMD fail\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return ret;
|
|
}
|
|
|
|
static char *rate_format[4] = { "LG", "HT", "VHT", "HE" };
|
|
|
|
static char *lg_rate[] = { "1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps",
|
|
"6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps",
|
|
"24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"
|
|
};
|
|
|
|
/**
|
|
* @brief Creates a Tx Rate Config request and sends to the driver
|
|
*
|
|
* Usage: "txratecfg <datarate>"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_tx_rate_cfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int status = 0;
|
|
tx_rate_cfg_t tx_rate_config;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
HTCap_t htcap;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_txratecfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 3) {
|
|
printf("ERR:wrong arguments! Only 0~3 arguments are supported.\n");
|
|
print_txratecfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc && (is_input_valid(TXRATECFG, argc, argv) != UAP_SUCCESS)) {
|
|
print_txratecfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
|
|
tx_rate_config.subcmd = UAP_TX_RATE_CFG;
|
|
if (argc) {
|
|
tx_rate_config.action = ACTION_SET;
|
|
tx_rate_config.rate_format = A2HEXDECIMAL(argv[0]);
|
|
if (argc >= 2)
|
|
tx_rate_config.rate = A2HEXDECIMAL(argv[1]);
|
|
if (argc >= 3)
|
|
tx_rate_config.nss = A2HEXDECIMAL(argv[2]);
|
|
if (argc == 4)
|
|
tx_rate_config.rate_setting = A2HEXDECIMAL(argv[3]);
|
|
tx_rate_config.user_data_cnt = argc;
|
|
/* If bss is already started and uAP is in (short GI in 20 MHz + GF) mode, block MCS0-MCS7 rates */
|
|
if (get_bss_status(&status) != UAP_SUCCESS) {
|
|
printf("ERR:Cannot get current bss status!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (UAP_SUCCESS == get_sys_cfg_11n(&htcap)) {
|
|
if (htcap.supported_mcs_set[0] &&
|
|
(status == UAP_BSS_START)) {
|
|
if (((tx_rate_config.rate >= 0) &&
|
|
(tx_rate_config.rate <= 7))
|
|
&&
|
|
(IS_11N_20MHZ_SHORTGI_ENABLED
|
|
(htcap.ht_cap_info) &&
|
|
IS_11N_GF_ENABLED(htcap.ht_cap_info))) {
|
|
printf("ERR: Invalid rate for bss in (20MHz Short GI + Green Field) mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((tx_rate_config.rate == 32) &&
|
|
(!(IS_11N_40MHZ_ENABLED
|
|
(htcap.ht_cap_info)))) {
|
|
printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)&tx_rate_config;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
printf("ERR:UAP_IOCTL_CMD fail\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc) {
|
|
printf("Transmit Rate setting successful\n");
|
|
} else {
|
|
/* GET operation */
|
|
printf("Tx Rate Configuration: \n");
|
|
/* format */
|
|
if (tx_rate_config.rate_format == 0xFF) {
|
|
printf(" Type: 0xFF (Auto)\n");
|
|
} else if (tx_rate_config.rate_format <= 3) {
|
|
printf(" Type: %d (%s)\n",
|
|
tx_rate_config.rate_format,
|
|
rate_format[tx_rate_config.rate_format]);
|
|
if (tx_rate_config.rate_format == 0)
|
|
printf(" Rate Index: %d (%s)\n",
|
|
tx_rate_config.rate,
|
|
lg_rate[tx_rate_config.rate]);
|
|
else if (tx_rate_config.rate_format >= 1)
|
|
printf(" MCS Index: %d\n",
|
|
(int)tx_rate_config.rate);
|
|
if (tx_rate_config.rate_format == 2 ||
|
|
tx_rate_config.rate_format == 3)
|
|
printf(" NSS: %d\n",
|
|
(int)tx_rate_config.nss);
|
|
if (tx_rate_config.rate_setting == 0xffff)
|
|
printf("Rate setting :Preamble type/BW/GI/STBC/.. : auto \n");
|
|
else {
|
|
printf("Preamble type: %x\n",
|
|
(tx_rate_config.rate_setting & 0x0003));
|
|
printf("BW: %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x001C) >> 2);
|
|
printf("LTF + GI size %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x0060) >> 5);
|
|
printf("STBC %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x0080) >> 7);
|
|
printf("DCM %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x0100) >> 8);
|
|
printf("Coding %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x0200) >> 9);
|
|
printf("maxPE %x\n",
|
|
(tx_rate_config.
|
|
rate_setting & 0x3000) >> 12);
|
|
}
|
|
} else {
|
|
printf(" Unknown rate format.\n");
|
|
}
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the antcfg
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_antcfg_usage(void)
|
|
{
|
|
printf("\nUsage : antcfg [<TX_MODE> <RX_MODE>]\n");
|
|
printf("\n MODE : 1 - Antenna A");
|
|
printf("\n 2 - Antenna B");
|
|
printf("\n 3 - Antenna A+B");
|
|
printf("\n empty - Get current antenna settings\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a RF Antenna Mode Config request and sends to the driver
|
|
*
|
|
* Usage: "antcfg [MODE]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_antcfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int tx_val = 0;
|
|
int rx_val = 0;
|
|
ant_cfg_t antenna_config;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_antcfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 2) {
|
|
printf("ERR:wrong arguments!\n");
|
|
print_antcfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc) {
|
|
sscanf(argv[0], "%x", (unsigned int *)&tx_val);
|
|
if (tx_val < 1 || tx_val > 0x303) {
|
|
printf("ERR:Illegal ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[0]);
|
|
print_antcfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 2) {
|
|
sscanf(argv[1], "%x", (unsigned int *)&rx_val);
|
|
if (rx_val < 1 || rx_val > 0x303) {
|
|
printf("ERR:Illegal RX ANTENNA parameter %s. Must be either '1', '2' or '3'.\n", argv[1]);
|
|
print_antcfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
memset(&antenna_config, 0, sizeof(ant_cfg_t));
|
|
antenna_config.subcmd = UAP_ANTENNA_CFG;
|
|
if (argc) {
|
|
antenna_config.action = ACTION_SET;
|
|
if (argc == 1) {
|
|
antenna_config.tx_mode = tx_val;
|
|
antenna_config.rx_mode = tx_val;
|
|
} else {
|
|
antenna_config.tx_mode = tx_val;
|
|
antenna_config.rx_mode = rx_val;
|
|
}
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)&antenna_config;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
printf("ERR:UAP_IOCTL_CMD fail\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc) {
|
|
printf("Antenna mode setting successful\n");
|
|
} else {
|
|
printf("TX Antenna mode is 0x%x.\n", antenna_config.tx_mode);
|
|
printf("RX Antenna mode is 0x%x.\n", antenna_config.rx_mode);
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the htstreamcfg
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_htstreamcfg_usage(void)
|
|
{
|
|
printf("\nUsage : htstreamcfg [<n>]\n");
|
|
printf("\n Where <n> ");
|
|
printf("\n 0x11: HT stream 1x1 mode");
|
|
printf("\n 0x22: HT stream 2x2 mode\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Set/get HT stream configurations
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_htstreamcfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
htstream_cfg_t htstream_cfg;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_htstreamcfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
|
|
memset(&htstream_cfg, 0, sizeof(htstream_cfg));
|
|
if (argc == 0) {
|
|
htstream_cfg.action = ACTION_GET;
|
|
} else if (argc == 1) {
|
|
if ((t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_1X1
|
|
&& (t_u32)A2HEXDECIMAL(argv[0]) != HT_STREAM_MODE_2X2) {
|
|
printf("ERR:Invalid argument\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
htstream_cfg.action = ACTION_SET;
|
|
htstream_cfg.stream_cfg = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
} else {
|
|
print_htstreamcfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
htstream_cfg.subcmd = UAP_HT_STREAM_CFG;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&htstream_cfg;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: HT STREAM configuration failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Handle response */
|
|
if (htstream_cfg.action == ACTION_GET) {
|
|
if (htstream_cfg.stream_cfg == HT_STREAM_MODE_1X1)
|
|
printf("HT stream is in 1x1 mode\n");
|
|
else if (htstream_cfg.stream_cfg == HT_STREAM_MODE_2X2)
|
|
printf("HT stream is in 2x2 mode\n");
|
|
else
|
|
printf("HT stream is unknown mode\n");
|
|
}
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
get_802_11ac_cfg(struct eth_priv_vhtcfg *vhtcfg)
|
|
{
|
|
t_u8 *buf = NULL;
|
|
t_u8 *pos = NULL;
|
|
mrvl_priv_cmd *cmd = NULL;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
if (!buf) {
|
|
printf("ERR: cannot allocate buffer for command payload \n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
|
|
cmd = (mrvl_priv_cmd *)malloc(sizeof(mrvl_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR: cannot allocate buffer for cmd \n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/*prepare command: mlanutl uap0 vhtcfg 2 3 , GET operation */
|
|
pos = buf;
|
|
strncpy((char *)pos, CMD_NXP, strlen(CMD_NXP));
|
|
pos += strlen(CMD_NXP);
|
|
strncpy((char *)pos, "vhtcfg2 3", strlen("vhtcfg2 3"));
|
|
|
|
/* fill up buffer */
|
|
cmd->buf = buf;
|
|
cmd->used_len = 0;
|
|
cmd->total_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
|
|
/* Perform IOCTL */
|
|
memset(&ifr, 0, sizeof(struct ifreq));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
if (cmd)
|
|
free(cmd);
|
|
if (buf)
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) {
|
|
if (cmd)
|
|
free(cmd);
|
|
if (buf)
|
|
free(buf);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Process result */
|
|
memcpy(vhtcfg, buf + 1, sizeof(struct eth_priv_vhtcfg));
|
|
|
|
close(sockfd);
|
|
free(cmd);
|
|
free(buf);
|
|
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sys_config command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sys_config_usage(void)
|
|
{
|
|
printf("\nUsage : sys_config [CONFIG_FILE]\n");
|
|
printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
|
|
printf("CONFIG_FILE is file contain all the Micro AP settings.\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the rdeeprom command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_apcmd_read_eeprom_usage(void)
|
|
{
|
|
printf("\nUsage: rdeeprom <offset> <bytecount>\n");
|
|
printf(" offset : 0,4,8,..., multiple of 4\n");
|
|
printf(" bytecount : 4-20, multiple of 4\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Show protocol tlv
|
|
*
|
|
* @param protocol Protocol number
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_protocol(t_u16 protocol)
|
|
{
|
|
switch (protocol) {
|
|
case 0:
|
|
case PROTOCOL_NO_SECURITY:
|
|
printf("PROTOCOL = No security\n");
|
|
break;
|
|
case PROTOCOL_STATIC_WEP:
|
|
printf("PROTOCOL = Static WEP\n");
|
|
break;
|
|
case PROTOCOL_WPA:
|
|
printf("PROTOCOL = WPA \n");
|
|
break;
|
|
case PROTOCOL_WPA2:
|
|
printf("PROTOCOL = WPA2 \n");
|
|
break;
|
|
case PROTOCOL_WPA | PROTOCOL_WPA2:
|
|
printf("PROTOCOL = WPA/WPA2 \n");
|
|
break;
|
|
case PROTOCOL_WPA3_SAE:
|
|
printf("PROTOCOL = WPA3 SAE \n");
|
|
break;
|
|
default:
|
|
printf("Unknown PROTOCOL: 0x%x \n", protocol);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Show wep tlv
|
|
*
|
|
* @param tlv Pointer to wep tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_wep_key(tlvbuf_wep_key *tlv)
|
|
{
|
|
int i;
|
|
t_u16 tlv_len;
|
|
|
|
tlv_len = *(t_u8 *)&tlv->length;
|
|
tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8);
|
|
|
|
if (tlv_len <= 2) {
|
|
printf("wrong wep_key tlv: length=%d\n", tlv_len);
|
|
return;
|
|
}
|
|
printf("WEP KEY_%d = ", tlv->key_index);
|
|
for (i = 0; i < tlv_len - 2; i++)
|
|
printf("%02x ", tlv->key[i]);
|
|
if (tlv->is_default)
|
|
printf("\nDefault WEP Key = %d\n", tlv->key_index);
|
|
else
|
|
printf("\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Parses a command line
|
|
*
|
|
* @param line The line to parse
|
|
* @param args Pointer to the argument buffer to be filled in
|
|
* @return Number of arguments in the line or EOF
|
|
*/
|
|
static int
|
|
parse_line(char *line, char *args[])
|
|
{
|
|
int arg_num = 0;
|
|
int is_start = 0;
|
|
int is_quote = 0;
|
|
int is_escape = 0;
|
|
int length = 0;
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
arg_num = 0;
|
|
length = strlen(line);
|
|
/* Process line */
|
|
|
|
/* Find number of arguments */
|
|
is_start = 0;
|
|
is_quote = 0;
|
|
for (i = 0; i < length; i++) {
|
|
/* Ignore leading spaces */
|
|
if (is_start == 0) {
|
|
if (line[i] == ' ') {
|
|
continue;
|
|
} else if (line[i] == '\t') {
|
|
continue;
|
|
} else if (line[i] == '\n') {
|
|
break;
|
|
} else {
|
|
is_start = 1;
|
|
args[arg_num] = &line[i];
|
|
arg_num++;
|
|
}
|
|
}
|
|
if (is_start == 1) {
|
|
if ((line[i] == '\\') && (i < (length - 1))) {
|
|
if (line[i + 1] == '"') {
|
|
is_escape = 1;
|
|
for (j = i; j < length - 1; j++) {
|
|
line[j] = line[j + 1];
|
|
}
|
|
line[length - 1] = '\0';
|
|
continue;
|
|
}
|
|
}
|
|
/* Ignore comments */
|
|
if (line[i] == '#') {
|
|
if (is_quote == 0) {
|
|
line[i] = '\0';
|
|
arg_num--;
|
|
}
|
|
break;
|
|
}
|
|
/* Separate by '=' */
|
|
if (line[i] == '=') {
|
|
if (is_quote == 0) {
|
|
line[i] = '\0';
|
|
is_start = 0;
|
|
continue;
|
|
}
|
|
}
|
|
/* Separate by ',' */
|
|
if (line[i] == ',') {
|
|
if (is_quote == 0) {
|
|
line[i] = '\0';
|
|
is_start = 0;
|
|
continue;
|
|
}
|
|
}
|
|
/* Change ',' to ' ', but not inside quotes */
|
|
if ((line[i] == ',') && (is_quote == 0)) {
|
|
line[i] = ' ';
|
|
continue;
|
|
}
|
|
}
|
|
/* Remove newlines */
|
|
if (line[i] == '\n') {
|
|
line[i] = '\0';
|
|
}
|
|
/* Check for quotes */
|
|
if (line[i] == '"') {
|
|
if (is_escape) {
|
|
is_escape = 0;
|
|
/* no change in is_quote */
|
|
} else {
|
|
is_quote = (is_quote == 1) ? 0 : 1;
|
|
}
|
|
continue;
|
|
}
|
|
if (((line[i] == ' ') || (line[i] == '\t')) && (is_quote == 0)) {
|
|
line[i] = '\0';
|
|
is_start = 0;
|
|
continue;
|
|
}
|
|
}
|
|
return arg_num;
|
|
}
|
|
|
|
/**
|
|
* @brief Parse function for a configuration line
|
|
*
|
|
* @param s Storage buffer for data
|
|
* @param size Maximum size of data
|
|
* @param stream File stream pointer
|
|
* @param line Pointer to current line within the file
|
|
* @param _pos Output string or NULL
|
|
* @return String or NULL
|
|
*/
|
|
static char *
|
|
config_get_line(char *s, int size, FILE * stream, int *line, char **_pos)
|
|
{
|
|
*_pos = mlan_config_get_line(stream, s, size, line);
|
|
return *_pos;
|
|
}
|
|
|
|
/**
|
|
* @brief Read the profile and sends to the driver
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_config_profile(int argc, char *argv[])
|
|
{
|
|
FILE *config_file = NULL;
|
|
char *line = NULL;
|
|
int li = 0;
|
|
char *pos = NULL;
|
|
int arg_num = 0;
|
|
char *args[30];
|
|
int i;
|
|
int is_ap_config = 0;
|
|
int is_ap_mac_filter = 0;
|
|
apcmdbuf_sys_configure *cmd_buf = NULL;
|
|
HTCap_t htcap;
|
|
int enable_11n = -1;
|
|
t_u16 tlv_offset_11n = 0;
|
|
t_u32 supported_mcs_set = 0;
|
|
t_u8 *buffer = NULL;
|
|
t_u8 *tmp_buffer = NULL;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 tlv_len = 0;
|
|
int keyindex = -1;
|
|
int protocol = -1;
|
|
int pwkcipher_wpa = -1;
|
|
int pwkcipher_wpa2 = -1;
|
|
int gwkcipher = -1;
|
|
tlvbuf_sta_mac_addr_filter *filter_tlv = NULL;
|
|
tlvbuf_channel_config *channel_band_tlv = NULL;
|
|
int filter_mac_count = -1;
|
|
int tx_data_rate = -1;
|
|
int tx_beacon_rate = -1;
|
|
int mcbc_data_rate = -1;
|
|
t_u8 rate[MAX_RATES];
|
|
int found = 0;
|
|
char country_80211d[4];
|
|
t_u8 state_80211d = 0;
|
|
int chan_mode = 0;
|
|
int band = 0;
|
|
int band_flag = 0;
|
|
int chan_number = 0;
|
|
t_u16 max_sta_num_supported = 0;
|
|
fw_info fw;
|
|
struct eth_priv_vhtcfg vhtcfg = { 0 };
|
|
int ret = UAP_SUCCESS;
|
|
memset(rate, 0, MAX_RATES);
|
|
/* Check if file exists */
|
|
config_file = fopen(argv[0], "r");
|
|
if (config_file == NULL) {
|
|
printf("\nERR:Config file can not open.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
line = (char *)malloc(MAX_CONFIG_LINE);
|
|
if (!line) {
|
|
printf("ERR:Cannot allocate memory for line\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
memset(line, 0, MAX_CONFIG_LINE);
|
|
|
|
/* Parse file and process */
|
|
while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
|
|
li, line);
|
|
#endif
|
|
arg_num = parse_line(line, args);
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
|
|
arg_num);
|
|
for (i = 0; i < arg_num; i++) {
|
|
uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
|
|
args[i]);
|
|
}
|
|
#endif
|
|
/* Check for end of AP configurations */
|
|
if (is_ap_config == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
is_ap_config = 0;
|
|
if (tx_data_rate != -1) {
|
|
if ((!rate[0]) && (tx_data_rate) &&
|
|
(is_tx_rate_valid
|
|
((t_u8)tx_data_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (rate[0] && tx_data_rate) {
|
|
for (i = 0; rate[i] != 0; i++) {
|
|
if ((rate[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
== tx_data_rate) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
if (tx_beacon_rate != -1) {
|
|
if ((!rate[0]) && (tx_beacon_rate) &&
|
|
(is_tx_rate_valid
|
|
((t_u8)tx_beacon_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Beacon Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (rate[0] && tx_beacon_rate) {
|
|
for (i = 0; rate[i] != 0; i++) {
|
|
if ((rate[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
== tx_beacon_rate) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid Tx Beacon Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
/* Append a new TLV */
|
|
tlvbuf_tx_data_rate *tlv = NULL;
|
|
tlv_len = sizeof(tlvbuf_tx_data_rate);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append tx beacon rate TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_tx_data_rate *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_TX_BEACON_RATE_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->tx_data_rate = tx_beacon_rate;
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->tx_data_rate =
|
|
uap_cpu_to_le16(tlv->
|
|
tx_data_rate);
|
|
}
|
|
if (mcbc_data_rate != -1) {
|
|
if ((!rate[0]) && (mcbc_data_rate) &&
|
|
(is_mcbc_rate_valid
|
|
((t_u8)mcbc_data_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (rate[0] && mcbc_data_rate) {
|
|
for (i = 0; rate[i] != 0; i++) {
|
|
if (rate[i] &
|
|
BASIC_RATE_SET_BIT)
|
|
{
|
|
if ((rate[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
==
|
|
mcbc_data_rate)
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid MCBC Data Rate \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Append a new TLV */
|
|
tlvbuf_mcbc_data_rate *tlv = NULL;
|
|
tlv_len = sizeof(tlvbuf_mcbc_data_rate);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append tx data rate TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_mcbc_data_rate *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_MCBC_DATA_RATE_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->mcbc_datarate = mcbc_data_rate;
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->mcbc_datarate =
|
|
uap_cpu_to_le16(tlv->
|
|
mcbc_datarate);
|
|
}
|
|
if ((protocol == PROTOCOL_STATIC_WEP) &&
|
|
(enable_11n == 1)) {
|
|
printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if ((protocol == PROTOCOL_WPA2_MIXED) &&
|
|
((pwkcipher_wpa < 0) ||
|
|
(pwkcipher_wpa2 < 0))) {
|
|
printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (((pwkcipher_wpa >= 0) ||
|
|
(pwkcipher_wpa2 >= 0)) &&
|
|
(gwkcipher >= 0)) {
|
|
if ((protocol == PROTOCOL_WPA) ||
|
|
(protocol == PROTOCOL_WPA2_MIXED)) {
|
|
if (enable_11n != -1) {
|
|
if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else if
|
|
(is_cipher_valid_with_proto
|
|
(pwkcipher_wpa,
|
|
gwkcipher,
|
|
protocol) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
if ((protocol == PROTOCOL_WPA2) ||
|
|
(protocol == PROTOCOL_WPA2_MIXED)
|
|
|| (protocol == PROTOCOL_WPA3_SAE)
|
|
) {
|
|
if (enable_11n != -1) {
|
|
if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else if
|
|
(is_cipher_valid_with_proto
|
|
(pwkcipher_wpa2,
|
|
gwkcipher,
|
|
protocol) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 == get_fw_info(&fw)) {
|
|
/*check whether support 802.11AC through BAND_AAC bit */
|
|
if (fw.fw_bands & BAND_AAC) {
|
|
ret = get_802_11ac_cfg(&vhtcfg);
|
|
if (ret != UAP_SUCCESS)
|
|
goto done;
|
|
if (enable_11n != -1) {
|
|
/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
|
|
if ((vhtcfg.
|
|
vht_rx_mcs !=
|
|
0xffff) &&
|
|
(!enable_11n)) {
|
|
printf("ERR: 11n must be enabled when AP operates in 11ac mode. \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
} else
|
|
printf("No support 802 11AC.\n");
|
|
} else {
|
|
printf("ERR: get_fw_info fail\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (protocol != -1) {
|
|
tlvbuf_protocol *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_protocol);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append protocol TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_protocol *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_PROTOCOL_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->protocol = protocol;
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->protocol =
|
|
uap_cpu_to_le16(tlv->protocol);
|
|
if (protocol &
|
|
(PROTOCOL_WPA | PROTOCOL_WPA2 |
|
|
PROTOCOL_WPA3_SAE)) {
|
|
tlvbuf_akmp *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_akmp);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len +
|
|
tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append AKMP TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure
|
|
*)buffer;
|
|
tlv = (tlvbuf_akmp *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_AKMP_TLV_ID;
|
|
tlv->length = 4; /* sizeof(tlvbuf_akmp) - TLVHEADER */
|
|
if (protocol &
|
|
PROTOCOL_WPA3_SAE) {
|
|
tlv->key_mgmt =
|
|
KEY_MGMT_SAE;
|
|
} else {
|
|
tlv->key_mgmt =
|
|
KEY_MGMT_PSK;
|
|
}
|
|
endian_convert_tlv_header_out
|
|
(tlv);
|
|
tlv->key_mgmt =
|
|
uap_cpu_to_le16(tlv->
|
|
key_mgmt);
|
|
tlv->key_mgmt_operation = 0;
|
|
}
|
|
}
|
|
if (pwkcipher_wpa >= 0) {
|
|
tlvbuf_pwk_cipher *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_pwk_cipher);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append cipher TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_pwk_cipher *)(buffer +
|
|
cmd_len);
|
|
memset(tlv, 0, tlv_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_CIPHER_PWK_TLV_ID;
|
|
tlv->length =
|
|
sizeof(tlvbuf_pwk_cipher) -
|
|
TLVHEADER_LEN;
|
|
tlv->pairwise_cipher = pwkcipher_wpa;
|
|
tlv->protocol = PROTOCOL_WPA;
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->protocol =
|
|
uap_cpu_to_le16(tlv->protocol);
|
|
}
|
|
|
|
if (pwkcipher_wpa2 >= 0) {
|
|
tlvbuf_pwk_cipher *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_pwk_cipher);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append cipher TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_pwk_cipher *)(buffer +
|
|
cmd_len);
|
|
memset(tlv, 0, tlv_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_CIPHER_PWK_TLV_ID;
|
|
tlv->length =
|
|
sizeof(tlvbuf_pwk_cipher) -
|
|
TLVHEADER_LEN;
|
|
tlv->pairwise_cipher = pwkcipher_wpa2;
|
|
tlv->protocol = PROTOCOL_WPA2;
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->protocol =
|
|
uap_cpu_to_le16(tlv->protocol);
|
|
}
|
|
|
|
if (gwkcipher >= 0) {
|
|
tlvbuf_gwk_cipher *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_gwk_cipher);
|
|
tmp_buffer =
|
|
realloc(buffer,
|
|
cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append cipher TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf =
|
|
(apcmdbuf_sys_configure *)
|
|
buffer;
|
|
tlv = (tlvbuf_gwk_cipher *)(buffer +
|
|
cmd_len);
|
|
memset(tlv, 0, tlv_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_CIPHER_GWK_TLV_ID;
|
|
tlv->length =
|
|
sizeof(tlvbuf_gwk_cipher) -
|
|
TLVHEADER_LEN;
|
|
tlv->group_cipher = gwkcipher;
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
|
|
cmd_buf->size = cmd_len;
|
|
/* Send collective command */
|
|
if (uap_ioctl
|
|
((t_u8 *)cmd_buf, &cmd_len,
|
|
cmd_len) == UAP_SUCCESS) {
|
|
if (cmd_buf->result != CMD_SUCCESS) {
|
|
printf("ERR: Failed to set the configuration!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR: Command sending failed!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
cmd_len = 0;
|
|
if (buffer) {
|
|
free(buffer);
|
|
buffer = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check for beginning of AP configurations */
|
|
if (strcmp(args[0], "ap_config") == 0) {
|
|
is_ap_config = 1;
|
|
cmd_len = sizeof(apcmdbuf_sys_configure);
|
|
if (buffer) {
|
|
free(buffer);
|
|
buffer = NULL;
|
|
}
|
|
buffer = (t_u8 *)malloc(cmd_len);
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate memory!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
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 = ACTION_SET;
|
|
continue;
|
|
}
|
|
|
|
/* Check for end of AP MAC address filter configurations */
|
|
if (is_ap_mac_filter == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
is_ap_mac_filter = 0;
|
|
if (filter_tlv->count != filter_mac_count) {
|
|
printf("ERR:Number of MAC address provided does not match 'Count'\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (filter_tlv->count) {
|
|
filter_tlv->length =
|
|
(filter_tlv->count * ETH_ALEN) +
|
|
2;
|
|
cmd_len -=
|
|
(MAX_MAC_ONESHOT_FILTER -
|
|
filter_mac_count) * ETH_ALEN;
|
|
} else {
|
|
filter_tlv->length =
|
|
(MAX_MAC_ONESHOT_FILTER *
|
|
ETH_ALEN) + 2;
|
|
memset(filter_tlv->mac_address, 0,
|
|
MAX_MAC_ONESHOT_FILTER *
|
|
ETH_ALEN);
|
|
}
|
|
cmd_buf->size = cmd_len;
|
|
endian_convert_tlv_header_out(filter_tlv);
|
|
if (uap_ioctl
|
|
((t_u8 *)cmd_buf, &cmd_len,
|
|
cmd_len) == UAP_SUCCESS) {
|
|
if (cmd_buf->result != CMD_SUCCESS) {
|
|
printf("ERR: Failed to set the configuration!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR: Command sending failed!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
cmd_len = 0;
|
|
if (buffer) {
|
|
free(buffer);
|
|
buffer = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "11d_enable") == 0) {
|
|
if (IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) {
|
|
printf("ERR: valid input for state are 0 or 1\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
state_80211d = (t_u8)A2HEXDECIMAL(args[1]);
|
|
|
|
if ((state_80211d != 0) && (state_80211d != 1)) {
|
|
printf("ERR: valid input for state are 0 or 1 \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (sg_snmp_mib
|
|
(ACTION_SET, OID_80211D_ENABLE,
|
|
sizeof(state_80211d), &state_80211d)
|
|
== UAP_FAILURE) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "country") == 0) {
|
|
apcmdbuf_cfg_80211d *cmd_buf = NULL;
|
|
ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
|
|
t_u8 no_of_sub_band = 0;
|
|
t_u16 buf_len;
|
|
t_u16 cmdlen;
|
|
t_u8 *buf = NULL;
|
|
|
|
if ((strlen(args[1]) > 3) || (strlen(args[1]) == 0)) {
|
|
printf("In-correct country input\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
strncpy(country_80211d, args[1],
|
|
sizeof(country_80211d) - 1);
|
|
for (i = 0; (unsigned int)i < strlen(country_80211d);
|
|
i++) {
|
|
if ((country_80211d[i] < 'A') ||
|
|
(country_80211d[i] > 'z')) {
|
|
printf("Invalid Country Code\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (country_80211d[i] > 'Z')
|
|
country_80211d[i] =
|
|
country_80211d[i] - 'a' + 'A';
|
|
}
|
|
no_of_sub_band =
|
|
parse_domain_file(country_80211d, band,
|
|
sub_bands, NULL);
|
|
if (no_of_sub_band == UAP_FAILURE) {
|
|
printf("Parsing Failed\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
buf_len = sizeof(apcmdbuf_cfg_80211d);
|
|
buf_len +=
|
|
no_of_sub_band *
|
|
sizeof(ieeetypes_subband_set_t);
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
memset(buf, 0, buf_len);
|
|
cmd_buf = (apcmdbuf_cfg_80211d *)buf;
|
|
cmdlen = buf_len;
|
|
cmd_buf->size = cmdlen - BUF_HEADER_SIZE;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_SET);
|
|
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_80211d,
|
|
strlen(country_80211d));
|
|
memcpy(cmd_buf->domain.subband, sub_bands,
|
|
no_of_sub_band *
|
|
sizeof(ieeetypes_subband_set_t));
|
|
|
|
/* Send the command */
|
|
if (uap_ioctl((t_u8 *)cmd_buf, &cmdlen, cmdlen) ==
|
|
UAP_SUCCESS) {
|
|
if (cmd_buf->result != CMD_SUCCESS) {
|
|
printf("ERR: Failed to set the configuration!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR: Command sending failed!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (buf)
|
|
free(buf);
|
|
}
|
|
|
|
/* Check for beginning of AP MAC address filter configurations */
|
|
if (strcmp(args[0], "ap_mac_filter") == 0) {
|
|
is_ap_mac_filter = 1;
|
|
cmd_len =
|
|
sizeof(apcmdbuf_sys_configure) +
|
|
sizeof(tlvbuf_sta_mac_addr_filter) +
|
|
(MAX_MAC_ONESHOT_FILTER * ETH_ALEN);
|
|
if (buffer) {
|
|
free(buffer);
|
|
buffer = NULL;
|
|
}
|
|
buffer = (t_u8 *)malloc(cmd_len);
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate memory!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
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 = ACTION_SET;
|
|
filter_tlv =
|
|
(tlvbuf_sta_mac_addr_filter *)(buffer +
|
|
sizeof
|
|
(apcmdbuf_sys_configure));
|
|
filter_tlv->tag = MRVL_STA_MAC_ADDR_FILTER_TLV_ID;
|
|
filter_tlv->length = 2;
|
|
filter_tlv->count = 0;
|
|
filter_mac_count = 0;
|
|
continue;
|
|
}
|
|
if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
|
|
(atoi(args[1]) > 2)) {
|
|
printf("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", atoi(args[1]));
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
filter_tlv->filter_mode = atoi(args[1]);
|
|
continue;
|
|
}
|
|
if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) {
|
|
filter_tlv->count = atoi(args[1]);
|
|
if ((ISDIGIT(args[1]) == 0) ||
|
|
(filter_tlv->count > MAX_MAC_ONESHOT_FILTER)) {
|
|
printf("ERR: Illegal Count parameter.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) {
|
|
if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) {
|
|
if (mac2raw
|
|
(args[1],
|
|
&filter_tlv->mac_address[filter_mac_count *
|
|
ETH_ALEN]) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: Invalid MAC address %s \n",
|
|
args[1]);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
filter_mac_count++;
|
|
} else {
|
|
printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "SSID") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:SSID field is blank!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
tlvbuf_ssid *tlv = NULL;
|
|
if (args[1][0] == '"') {
|
|
args[1]++;
|
|
}
|
|
if (args[1][strlen(args[1]) - 1] == '"') {
|
|
args[1][strlen(args[1]) - 1] = '\0';
|
|
}
|
|
if ((strlen(args[1]) > MAX_SSID_LENGTH) ||
|
|
(strlen(args[1]) == 0)) {
|
|
printf("ERR:SSID length out of range (%d to %d).\n", MIN_SSID_LENGTH, MAX_SSID_LENGTH);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_ssid) + strlen(args[1]);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot realloc SSID TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_ssid *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_SSID_TLV_ID;
|
|
tlv->length = strlen(args[1]);
|
|
memcpy(tlv->ssid, args[1], tlv->length);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "BeaconPeriod") == 0) {
|
|
if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_beacon_period *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_beacon_period);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot realloc beacon period TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_beacon_period *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_BEACON_PERIOD_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->beacon_period_ms = (t_u16)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->beacon_period_ms =
|
|
uap_cpu_to_le16(tlv->beacon_period_ms);
|
|
}
|
|
if (strcmp(args[0], "ChanList") == 0) {
|
|
if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
tlvbuf_channel_list *tlv = NULL;
|
|
channel_list *pchan_list = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len =
|
|
sizeof(tlvbuf_channel_list) +
|
|
((arg_num - 1) * sizeof(channel_list));
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append channel list TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_channel_list *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_CHANNELLIST_TLV_ID;
|
|
tlv->length = sizeof(channel_list) * (arg_num - 1);
|
|
pchan_list = (channel_list *) tlv->chan_list;
|
|
for (i = 0; i < (arg_num - 1); i++) {
|
|
band_flag = -1;
|
|
sscanf(args[i + 1], "%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;
|
|
}
|
|
pchan_list++;
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "Channel") == 0) {
|
|
if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_channel_config *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_channel_config);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append channel TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_channel_config *)(buffer + cmd_len);
|
|
channel_band_tlv = tlv;
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_CHANNELCONFIG_TLV_ID;
|
|
tlv->length =
|
|
sizeof(tlvbuf_channel_config) - TLVHEADER_LEN;
|
|
tlv->chan_number = (t_u8)atoi(args[1]);
|
|
if (tlv->chan_number > MAX_CHANNELS_BG)
|
|
band = BAND_A;
|
|
else
|
|
band = BAND_B | BAND_G;
|
|
if ((arg_num - 1) == 2) {
|
|
chan_mode = atoi(args[2]);
|
|
memset(&(tlv->bandcfg), 0,
|
|
sizeof(tlv->bandcfg));
|
|
if (chan_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 (chan_mode & BITMAP_CHANNEL_ABOVE)
|
|
tlv->bandcfg.chan2Offset =
|
|
SEC_CHAN_ABOVE;
|
|
if (chan_mode & BITMAP_CHANNEL_BELOW)
|
|
tlv->bandcfg.chan2Offset =
|
|
SEC_CHAN_BELOW;
|
|
} else
|
|
memset(&(tlv->bandcfg), 0,
|
|
sizeof(tlv->bandcfg));
|
|
if (tlv->chan_number > MAX_CHANNELS_BG) {
|
|
tlv->bandcfg.chanBand = BAND_5GHZ;
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "Band") == 0) {
|
|
if (is_input_valid(BAND, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (channel_band_tlv == NULL) {
|
|
printf("ERR: Channel parameter should be specified before Band\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* If band is provided, clear previous value of band */
|
|
channel_band_tlv->bandcfg.chanBand = BAND_2GHZ;
|
|
if (atoi(args[1]) == 0) {
|
|
band = BAND_B | BAND_G;
|
|
} else {
|
|
channel_band_tlv->bandcfg.chanBand = BAND_5GHZ;
|
|
band = BAND_A;
|
|
}
|
|
}
|
|
if (strcmp(args[0], "AP_MAC") == 0) {
|
|
tlvbuf_ap_mac_address *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_ap_mac_address);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append ap_mac TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_ap_mac_address *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
cmd_buf->action = ACTION_SET;
|
|
tlv->tag = MRVL_AP_MAC_ADDRESS_TLV_ID;
|
|
tlv->length = ETH_ALEN;
|
|
if ((ret =
|
|
mac2raw(args[1],
|
|
tlv->ap_mac_addr)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address \n",
|
|
ret ==
|
|
UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
|
|
if (strcmp(args[0], "Rate") == 0) {
|
|
if (is_input_valid(RATE, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: Invalid Rate input\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_rates *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_rates) + arg_num - 1;
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append rates TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_rates *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_RATES_TLV_ID;
|
|
tlv->length = arg_num - 1;
|
|
for (i = 0; i < tlv->length; i++) {
|
|
rate[i] = tlv->operational_rates[i] =
|
|
(t_u8)A2HEXDECIMAL(args[i + 1]);
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "TxPowerLevel") == 0) {
|
|
if (is_input_valid(TXPOWER, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Invalid TxPowerLevel \n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
tlvbuf_tx_power *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_tx_power);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append tx power level TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_tx_power *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_TX_POWER_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->tx_power_dbm = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "BroadcastSSID") == 0) {
|
|
if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_bcast_ssid_ctl *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_bcast_ssid_ctl);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append SSID broadcast control TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_bcast_ssid_ctl *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_BCAST_SSID_CTL_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->bcast_ssid_ctl = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "RTSThreshold") == 0) {
|
|
if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_rts_threshold *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_rts_threshold);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append RTS threshold TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_rts_threshold *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_RTS_THRESHOLD_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->rts_threshold = (t_u16)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->rts_threshold =
|
|
uap_cpu_to_le16(tlv->rts_threshold);
|
|
}
|
|
if (strcmp(args[0], "FragThreshold") == 0) {
|
|
if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_frag_threshold *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_frag_threshold);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append Fragmentation threshold TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_frag_threshold *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_FRAG_THRESHOLD_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->frag_threshold = (t_u16)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->frag_threshold =
|
|
uap_cpu_to_le16(tlv->frag_threshold);
|
|
}
|
|
if (strcmp(args[0], "DTIMPeriod") == 0) {
|
|
if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_dtim_period *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_dtim_period);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append DTIM period TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_dtim_period *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_DTIM_PERIOD_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->dtim_period = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "RSNReplayProtection") == 0) {
|
|
if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_rsn_replay_prot *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_rsn_replay_prot);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append RSN replay protection TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_rsn_replay_prot *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_RSN_REPLAY_PROT_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->rsn_replay_prot = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "TxBeaconRate") == 0) {
|
|
if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]);
|
|
}
|
|
if (strcmp(args[0], "MCBCdataRate") == 0) {
|
|
if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PktFwdCtl") == 0) {
|
|
if (is_input_valid(PKTFWD, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_pkt_fwd_ctl *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_pkt_fwd_ctl);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append packet forwarding control TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_pkt_fwd_ctl *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_PKT_FWD_CTL_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->pkt_fwd_ctl = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "StaAgeoutTimer") == 0) {
|
|
if (is_input_valid
|
|
(STAAGEOUTTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_sta_ageout_timer *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_sta_ageout_timer);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append STA ageout timer TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_sta_ageout_timer *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_STA_AGEOUT_TIMER_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->sta_ageout_timer_ms = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->sta_ageout_timer_ms =
|
|
uap_cpu_to_le32(tlv->sta_ageout_timer_ms);
|
|
}
|
|
if (strcmp(args[0], "PSStaAgeoutTimer") == 0) {
|
|
if (is_input_valid
|
|
(PSSTAAGEOUTTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_ps_sta_ageout_timer *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_ps_sta_ageout_timer);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append PS STA ageout timer TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_ps_sta_ageout_timer *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_PS_STA_AGEOUT_TIMER_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->ps_sta_ageout_timer_ms = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->ps_sta_ageout_timer_ms =
|
|
uap_cpu_to_le32(tlv->ps_sta_ageout_timer_ms);
|
|
}
|
|
if (strcmp(args[0], "AuthMode") == 0) {
|
|
if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_auth_mode *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_auth_mode);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append auth mode TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_auth_mode *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_AUTH_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->auth_mode = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "KeyIndex") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("KeyIndex is blank!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
keyindex = atoi(args[1]);
|
|
if ((keyindex < 0) || (keyindex > 3)) {
|
|
printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
if (strncmp(args[0], "Key_", 4) == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:%s is blank!\n", args[0]);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
tlvbuf_wep_key *tlv = NULL;
|
|
int key_len = 0;
|
|
if (args[1][0] == '"') {
|
|
if ((strlen(args[1]) != 2) &&
|
|
(strlen(args[1]) != 7) &&
|
|
(strlen(args[1]) != 15)) {
|
|
printf("ERR:Wrong key length!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
key_len = strlen(args[1]) - 2;
|
|
} else {
|
|
if ((strlen(args[1]) != 0) &&
|
|
(strlen(args[1]) != 10) &&
|
|
(strlen(args[1]) != 26)) {
|
|
printf("ERR:Wrong key length!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (UAP_FAILURE == ishexstring(args[1])) {
|
|
printf("ERR:Only hex digits are allowed when key length is 10 or 26\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
key_len = strlen(args[1]) / 2;
|
|
}
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_wep_key) + key_len;
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append WEP key configurations TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_wep_key *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_WEP_KEY_TLV_ID;
|
|
tlv->length = key_len + 2;
|
|
if (strcmp(args[0], "Key_0") == 0) {
|
|
tlv->key_index = 0;
|
|
} else if (strcmp(args[0], "Key_1") == 0) {
|
|
tlv->key_index = 1;
|
|
} else if (strcmp(args[0], "Key_2") == 0) {
|
|
tlv->key_index = 2;
|
|
} else if (strcmp(args[0], "Key_3") == 0) {
|
|
tlv->key_index = 3;
|
|
}
|
|
if (keyindex == tlv->key_index) {
|
|
tlv->is_default = 1;
|
|
} else {
|
|
tlv->is_default = 0;
|
|
}
|
|
if (args[1][0] == '"') {
|
|
memcpy(tlv->key, &args[1][1],
|
|
strlen(args[1]) - 2);
|
|
} else {
|
|
string2raw(args[1], tlv->key);
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "PSK") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PSK is blank!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
tlvbuf_wpa_passphrase *tlv = NULL;
|
|
if (args[1][0] == '"') {
|
|
args[1]++;
|
|
}
|
|
if (args[1][strlen(args[1]) - 1] == '"') {
|
|
args[1][strlen(args[1]) - 1] = '\0';
|
|
}
|
|
tlv_len =
|
|
sizeof(tlvbuf_wpa_passphrase) +
|
|
strlen(args[1]);
|
|
if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) {
|
|
printf("ERR:PSK too long.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) {
|
|
printf("ERR:PSK too short.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (strlen(args[1]) ==
|
|
MAX_WPA_PASSPHRASE_LENGTH) {
|
|
if (UAP_FAILURE == ishexstring(args[1])) {
|
|
printf("ERR:Only hex digits are allowed when passphrase's length is 64\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
/* Append a new TLV */
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append WPA passphrase TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_wpa_passphrase *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_WPA_PASSPHRASE_TLV_ID;
|
|
tlv->length = strlen(args[1]);
|
|
memcpy(tlv->passphrase, args[1], tlv->length);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "Protocol") == 0) {
|
|
if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
protocol = (t_u16)atoi(args[1]);
|
|
}
|
|
if ((strcmp(args[0], "PairwiseCipher") == 0) ||
|
|
(strcmp(args[0], "GroupCipher") == 0)) {
|
|
printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" " Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" " and group cipher using GwkCipher in the config file.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if ((protocol == PROTOCOL_NO_SECURITY) ||
|
|
(protocol == PROTOCOL_STATIC_WEP)) {
|
|
if ((strcmp(args[0], "PwkCipherWPA") == 0) ||
|
|
(strcmp(args[0], "PwkCipherWPA2") == 0)
|
|
|| (strcmp(args[0], "GwkCipher") == 0)) {
|
|
printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "PwkCipherWPA") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PwkCipherWPA is blank!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) & ~CIPHER_BITMAP) {
|
|
printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
pwkcipher_wpa = atoi(args[1]);
|
|
if (enable_11n &&
|
|
protocol != PROTOCOL_WPA2_MIXED) {
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS ==
|
|
get_sys_cfg_11n(&htcap)) {
|
|
if (htcap.supported_mcs_set[0]
|
|
&& (atoi(args[1]) ==
|
|
CIPHER_TKIP)) {
|
|
printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "PwkCipherWPA2") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PwkCipherWPA2 is blank!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) & ~CIPHER_BITMAP) {
|
|
printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
pwkcipher_wpa2 = atoi(args[1]);
|
|
if (enable_11n &&
|
|
protocol != PROTOCOL_WPA2_MIXED) {
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS ==
|
|
get_sys_cfg_11n(&htcap)) {
|
|
if (htcap.supported_mcs_set[0]
|
|
&& (atoi(args[1]) ==
|
|
CIPHER_TKIP)) {
|
|
printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(args[0], "GwkCipher") == 0) {
|
|
if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
gwkcipher = atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "GroupRekeyTime") == 0) {
|
|
if (is_input_valid
|
|
(GROUPREKEYTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_group_rekey_timer *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_group_rekey_timer);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append group rekey timer TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_group_rekey_timer *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_GRP_REKEY_TIME_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->group_rekey_time_sec = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->group_rekey_time_sec =
|
|
uap_cpu_to_le32(tlv->group_rekey_time_sec);
|
|
}
|
|
if (strcmp(args[0], "MaxStaNum") == 0) {
|
|
if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (get_max_sta_num_supported(&max_sta_num_supported) ==
|
|
UAP_FAILURE) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) > max_sta_num_supported) {
|
|
printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_max_sta_num *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len =
|
|
sizeof(tlvbuf_max_sta_num) -
|
|
sizeof(tlv->max_sta_num_supported);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot realloc max station number TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_max_sta_num *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_MAX_STA_CNT_TLV_ID;
|
|
tlv->length = 2;
|
|
tlv->max_sta_num_configured = (t_u16)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->max_sta_num_configured =
|
|
uap_cpu_to_le16(tlv->max_sta_num_configured);
|
|
}
|
|
if (strcmp(args[0], "Retrylimit") == 0) {
|
|
if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_retry_limit *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_retry_limit);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot realloc retry limit TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_retry_limit *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_RETRY_LIMIT_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->retry_limit = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_eapol_pwk_hsk_timeout *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_timeout);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append pairwise update timeout TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_eapol_pwk_hsk_timeout *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->pairwise_update_timeout = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->pairwise_update_timeout =
|
|
uap_cpu_to_le32(tlv->pairwise_update_timeout);
|
|
}
|
|
if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_eapol_pwk_hsk_retries *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_eapol_pwk_hsk_retries);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append pairwise handshake retries TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_eapol_pwk_hsk_retries *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->pwk_retries = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->pwk_retries = uap_cpu_to_le32(tlv->pwk_retries);
|
|
}
|
|
if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_eapol_gwk_hsk_timeout *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_timeout);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append groupwise update timeout TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_eapol_gwk_hsk_timeout *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->groupwise_update_timeout = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->groupwise_update_timeout =
|
|
uap_cpu_to_le32(tlv->groupwise_update_timeout);
|
|
}
|
|
if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_eapol_gwk_hsk_retries *tlv = NULL;
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_eapol_gwk_hsk_retries);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append groupwise handshake retries TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_eapol_gwk_hsk_retries *)(buffer +
|
|
cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID;
|
|
tlv->length = 4;
|
|
tlv->gwk_retries = (t_u32)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
tlv->gwk_retries = uap_cpu_to_le32(tlv->gwk_retries);
|
|
}
|
|
|
|
if (strcmp(args[0], "Enable11n") == 0) {
|
|
if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
|
|
(atoi(args[1]) < 0) || (atoi(args[1]) > 1)) {
|
|
printf("ERR: Invalid Enable11n value\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_htcap_t *tlv = NULL;
|
|
enable_11n = atoi(args[1]);
|
|
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) {
|
|
printf("ERR: Reading current 11n configuration.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_htcap_t);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append HT Cap TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_htcap_t *)(buffer + cmd_len);
|
|
tlv_offset_11n = cmd_len;
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = HT_CAPABILITY_TLV_ID;
|
|
tlv->length = sizeof(HTCap_t);
|
|
memcpy(&tlv->ht_cap, &htcap, sizeof(HTCap_t));
|
|
if (enable_11n == 1) {
|
|
/* enable mcs rate */
|
|
tlv->ht_cap.supported_mcs_set[0] =
|
|
DEFAULT_MCS_SET_0;
|
|
tlv->ht_cap.supported_mcs_set[4] =
|
|
DEFAULT_MCS_SET_4;
|
|
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;
|
|
}
|
|
} else {
|
|
/* 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;
|
|
}
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "HTCapInfo") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before HTCapInfo.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
|
|
((((t_u16)A2HEXDECIMAL(args[1])) &
|
|
(~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) {
|
|
printf("ERR: Invalid HTCapInfo value\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Find HT tlv pointer in buffer and set HTCapInfo */
|
|
tlvbuf_htcap_t *tlv = NULL;
|
|
tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
|
|
tlv->ht_cap.ht_cap_info =
|
|
DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK;
|
|
tlv->ht_cap.ht_cap_info |=
|
|
(t_u16)A2HEXDECIMAL(args[1]) &
|
|
HT_CAP_CONFIG_MASK;
|
|
tlv->ht_cap.ht_cap_info =
|
|
uap_cpu_to_le16(tlv->ht_cap.ht_cap_info);
|
|
}
|
|
if (strcmp(args[0], "AMPDU") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before AMPDU.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
|
|
((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) {
|
|
printf("ERR: Invalid AMPDU value\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Find HT tlv pointer in buffer and set AMPDU */
|
|
tlvbuf_htcap_t *tlv = NULL;
|
|
tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
|
|
tlv->ht_cap.ampdu_param =
|
|
(t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK;
|
|
}
|
|
if (strcmp(args[0], "HT_MCS_MAP") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
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(args[1]) & MCS_SET_1_MASK)) {
|
|
printf("ERR: Invalid HT_MCS_MAP\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Find HT tlv pointer in buffer and set supported MCS set */
|
|
tlvbuf_htcap_t *tlv = NULL;
|
|
tlv = (tlvbuf_htcap_t *)(buffer + tlv_offset_11n);
|
|
supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]);
|
|
supported_mcs_set = uap_cpu_to_le32(supported_mcs_set);
|
|
memcpy(tlv->ht_cap.supported_mcs_set,
|
|
&supported_mcs_set, sizeof(t_u32));
|
|
}
|
|
if (strcmp(args[0], "Enable2040Coex") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
|
|
(atoi(args[1]) > 1)) {
|
|
printf("ERR: Invalid Enable2040Coex value\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tlvbuf_2040_coex *tlv = NULL;
|
|
/* Append a new TLV */
|
|
tlv_len = sizeof(tlvbuf_2040_coex);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append 2040 coex TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_2040_coex *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_2040_BSS_COEX_CONTROL_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->enable = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
if (strcmp(args[0], "PreambleType") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
|
|
(atoi(args[1]) > 2)) {
|
|
printf("ERR: Invalid PreambleType value\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Append a new TLV */
|
|
tlvbuf_preamble_ctl *tlv = NULL;
|
|
tlv_len = sizeof(tlvbuf_preamble_ctl);
|
|
tmp_buffer = realloc(buffer, cmd_len + tlv_len);
|
|
if (!tmp_buffer) {
|
|
printf("ERR:Cannot append preamble type TLV!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
buffer = tmp_buffer;
|
|
tmp_buffer = NULL;
|
|
}
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_preamble_ctl *)(buffer + cmd_len);
|
|
cmd_len += tlv_len;
|
|
/* Set TLV fields */
|
|
tlv->tag = MRVL_PREAMBLE_CTL_TLV_ID;
|
|
tlv->length = 1;
|
|
tlv->preamble_type = (t_u8)atoi(args[1]);
|
|
endian_convert_tlv_header_out(tlv);
|
|
}
|
|
#if DEBUG
|
|
if (cmd_len != 0) {
|
|
hexdump("Command Buffer", (void *)cmd_buf, cmd_len,
|
|
' ');
|
|
}
|
|
#endif
|
|
}
|
|
done:
|
|
fclose(config_file);
|
|
if (buffer)
|
|
free(buffer);
|
|
if (line)
|
|
free(line);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Get band from current channel
|
|
* @param band
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
static int
|
|
get_band(int *band)
|
|
{
|
|
apcmdbuf_sys_configure *cmd_buf = NULL;
|
|
tlvbuf_channel_config *tlv = NULL;
|
|
t_u8 *buffer = NULL;
|
|
t_u16 cmd_len;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
/* Initialize the command length */
|
|
cmd_len =
|
|
sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_channel_config);
|
|
|
|
/* Initialize the command buffer */
|
|
buffer = (t_u8 *)malloc(cmd_len);
|
|
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, cmd_len);
|
|
|
|
/* Locate headers */
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_channel_config *)(buffer +
|
|
sizeof(apcmdbuf_sys_configure));
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->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;
|
|
cmd_buf->action = ACTION_GET;
|
|
|
|
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);
|
|
|
|
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);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
if (tlv->chan_number > MAX_CHANNELS_BG)
|
|
*band = BAND_A;
|
|
else
|
|
*band = BAND_B | BAND_G;
|
|
} else {
|
|
printf("ERR:Could not get band!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the cfg_80211d command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_apcmd_cfg_80211d_usage(void)
|
|
{
|
|
printf("\nUsage: cfg_80211d <state 0/1> <country Country_code> \n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the uap_stats command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_apcmd_uap_stats(void)
|
|
{
|
|
printf("Usage: uap_stats \n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* SNMP MIB OIDs Table
|
|
*/
|
|
static oids_table snmp_oids[] = {
|
|
{0x0b, 4, "dot11LocalTKIPMICFailures"},
|
|
{0x0c, 4, "dot11CCMPDecryptErrors"},
|
|
{0x0d, 4, "dot11WEPUndecryptableCount"},
|
|
{0x0e, 4, "dot11WEPICVErrorCount"},
|
|
{0x0f, 4, "dot11DecryptFailureCount"},
|
|
{0x12, 4, "dot11FailedCount"},
|
|
{0x13, 4, "dot11RetryCount"},
|
|
{0x14, 4, "dot11MultipleRetryCount"},
|
|
{0x15, 4, "dot11FrameDuplicateCount"},
|
|
{0x16, 4, "dot11RTSSuccessCount"},
|
|
{0x17, 4, "dot11RTSFailureCount"},
|
|
{0x18, 4, "dot11ACKFailureCount"},
|
|
{0x19, 4, "dot11ReceivedFragmentCount"},
|
|
{0x1a, 4, "dot11MulticastReceivedFrameCount"},
|
|
{0x1b, 4, "dot11FCSErrorCount"},
|
|
{0x1c, 4, "dot11TransmittedFrameCount"},
|
|
{0x1d, 4, "dot11RSNATKIPCounterMeasuresInvoked"},
|
|
{0x1e, 4, "dot11RSNA4WayHandshakeFailures"},
|
|
{0x1f, 4, "dot11MulticastTransmittedFrameCount"}
|
|
};
|
|
|
|
/**
|
|
* @brief Get uAP stats
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
*
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_uap_stats(int argc, char *argv[])
|
|
{
|
|
t_u8 no_of_oids = sizeof(snmp_oids) / sizeof(snmp_oids[0]);
|
|
t_u16 i, j;
|
|
int size;
|
|
apcmdbuf_snmp_mib *cmd_buf = NULL;
|
|
t_u8 *buf = NULL;
|
|
tlvbuf_header *tlv = NULL;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
int opt;
|
|
t_u16 oid_size, byte2 = 0;
|
|
t_u32 byte4 = 0;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_apcmd_uap_stats();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
if (argc) {
|
|
printf("Error: Invalid Input\n");
|
|
print_apcmd_uap_stats();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/** Command Header */
|
|
cmd_len += sizeof(apcmdbuf_snmp_mib);
|
|
|
|
for (i = 0; i < no_of_oids; i++) {
|
|
/**
|
|
* Size of Oid + Oid_value + Oid_size
|
|
*/
|
|
cmd_len += snmp_oids[i].len + sizeof(tlvbuf_header);
|
|
}
|
|
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_snmp_mib *)buf;
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->cmd_code = HostCmd_SNMP_MIB;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
|
|
|
|
tlv = (tlvbuf_header *)((t_u8 *)cmd_buf + sizeof(apcmdbuf_snmp_mib));
|
|
/* Add oid, oid_size and oid_value for each OID */
|
|
for (i = 0; i < no_of_oids; i++) {
|
|
/** Copy Index as Oid */
|
|
tlv->type = uap_cpu_to_le16(snmp_oids[i].type);
|
|
/** Copy its size */
|
|
tlv->len = uap_cpu_to_le16(snmp_oids[i].len);
|
|
/** Next TLV */
|
|
tlv = (tlvbuf_header *)&(tlv->data[snmp_oids[i].len]);
|
|
}
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
tlv = (tlvbuf_header *)((t_u8 *)cmd_buf +
|
|
sizeof(apcmdbuf_snmp_mib));
|
|
|
|
size = cmd_buf->size - (sizeof(apcmdbuf_snmp_mib) -
|
|
BUF_HEADER_SIZE);
|
|
|
|
while ((unsigned int)size >= sizeof(tlvbuf_header)) {
|
|
tlv->type = uap_le16_to_cpu(tlv->type);
|
|
for (i = 0; i < no_of_oids; i++) {
|
|
if (snmp_oids[i].type == tlv->type) {
|
|
printf("%s: ",
|
|
snmp_oids[i].name);
|
|
break;
|
|
}
|
|
}
|
|
oid_size = uap_le16_to_cpu(tlv->len);
|
|
switch (oid_size) {
|
|
case 1:
|
|
printf("%d",
|
|
(unsigned int)tlv->data[0]);
|
|
break;
|
|
case 2:
|
|
memcpy(&byte2, &tlv->data[0],
|
|
sizeof(oid_size));
|
|
printf("%d",
|
|
(unsigned int)
|
|
uap_le16_to_cpu(byte2));
|
|
break;
|
|
case 4:
|
|
memcpy(&byte4, &tlv->data[0],
|
|
sizeof(oid_size));
|
|
printf("%d",
|
|
(unsigned int)
|
|
uap_le32_to_cpu(byte4));
|
|
break;
|
|
default:
|
|
for (j = 0; j < oid_size; j++) {
|
|
printf("%d ",
|
|
(t_u8)tlv->data[j]);
|
|
}
|
|
break;
|
|
}
|
|
/** Next TLV */
|
|
tlv = (tlvbuf_header *)&(tlv->data[oid_size]);
|
|
size -= (sizeof(tlvbuf_header) + oid_size);
|
|
size = (size > 0) ? size : 0;
|
|
printf("\n");
|
|
}
|
|
|
|
} else {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief parser for sys_cfg_80211d input
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @param output Stores indexes for "state, country"
|
|
* arguments
|
|
*
|
|
* @return NA
|
|
*
|
|
*/
|
|
static void
|
|
parse_input_80211d(int argc, char **argv, int output[2][2])
|
|
{
|
|
int i, j, k = 0;
|
|
char *keywords[2] = { "state", "country" };
|
|
|
|
for (i = 0; i < 2; i++)
|
|
output[i][0] = -1;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
if (strcmp(argv[i], keywords[j]) == 0) {
|
|
output[j][1] = output[j][0] = i;
|
|
k = j;
|
|
break;
|
|
}
|
|
}
|
|
output[k][1] += 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Set/Get 802.11D country information
|
|
*
|
|
* Usage: cfg_80211d state country_code
|
|
*
|
|
* State 0 or 1
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_cfg_80211d(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_cfg_80211d *cmd_buf = NULL;
|
|
ieeetypes_subband_set_t *subband = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
int output[2][2];
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
int status = 0;
|
|
int i, j;
|
|
t_u8 state = 0;
|
|
char country[4] = { ' ', ' ', 0, 0 };
|
|
t_u8 sflag = 0, cflag = 0;
|
|
ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
|
|
t_u8 no_of_sub_band = 0;
|
|
int band;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if (argc) {
|
|
if (strcmp(argv[0], "state") && strcmp(argv[0], "country")) {
|
|
printf("ERR: Incorrect input. Either state or country is needed.");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
/** SET */
|
|
parse_input_80211d(argc, argv, output);
|
|
|
|
/** State */
|
|
if ((output[0][0] != -1) && (output[0][1] > output[0][0])) {
|
|
if ((output[0][1] - output[0][0]) != 2) {
|
|
printf("ERR: Invalid state inputs\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (IS_HEX_OR_DIGIT(argv[output[0][0] + 1]) ==
|
|
UAP_FAILURE) {
|
|
printf("ERR: valid input for state are 0 or 1\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
state = (t_u8)A2HEXDECIMAL(argv[output[0][0] + 1]);
|
|
|
|
if ((state != 0) && (state != 1)) {
|
|
printf("ERR: valid input for state are 0 or 1 \n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
sflag = 1;
|
|
}
|
|
|
|
/** Country */
|
|
if ((output[1][0] != -1) && (output[1][1] > output[1][0])) {
|
|
if ((output[1][1] - output[1][0]) != 2) {
|
|
printf("ERR: Invalid country inputs\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((strlen(argv[output[1][0] + 1]) > 3) ||
|
|
(strlen(argv[output[1][0] + 1]) == 0)) {
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Only 2 characters of country code are copied here as indoor/outdoor
|
|
* conditions are not handled in domain file */
|
|
strncpy(country, argv[output[1][0] + 1], 2);
|
|
|
|
for (i = 0; (unsigned int)i < strlen(country); i++) {
|
|
if ((country[i] < 'A') || (country[i] > 'z')) {
|
|
printf("Invalid Country Code\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (country[i] > 'Z')
|
|
country[i] = country[i] - 'a' + 'A';
|
|
}
|
|
|
|
cflag = 1;
|
|
if (!get_band(&band)) {
|
|
printf("ERR:couldn't get band from channel!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/** Get domain information from the file */
|
|
no_of_sub_band =
|
|
parse_domain_file(country, band, sub_bands,
|
|
NULL);
|
|
if (no_of_sub_band == UAP_FAILURE) {
|
|
printf("Parsing Failed\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (get_bss_status(&status) != UAP_SUCCESS) {
|
|
printf("ERR:Cannot get current bss status!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (status == UAP_BSS_START) {
|
|
printf("ERR: 11d status can not be changed after BSS start!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (argc && !cflag && !sflag) {
|
|
printf("ERR: Invalid input\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (sflag && !cflag) {
|
|
/**
|
|
* Update MIB only and return
|
|
*/
|
|
if (sg_snmp_mib
|
|
(ACTION_SET, OID_80211D_ENABLE, sizeof(state),
|
|
&state) == UAP_SUCCESS) {
|
|
printf("802.11d %sd \n", state ? "enable" : "disable");
|
|
return UAP_SUCCESS;
|
|
} else {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
cmd_len = sizeof(apcmdbuf_cfg_80211d);
|
|
|
|
if (cflag) {
|
|
cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t);
|
|
} else {
|
|
/** Get */
|
|
cmd_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 = argc ? cmd_len :
|
|
/** Set */
|
|
(sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
|
|
/** Get */
|
|
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->action = argc ? ACTION_SET : ACTION_GET;
|
|
cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
|
|
cmd_buf->cmd_code = HostCmd_CMD_802_11D_DOMAIN_INFO;
|
|
|
|
if (cflag) {
|
|
/* third character of country code is copied here as indoor/outdoor
|
|
* condition is not supported in domain file*/
|
|
strncpy(country, argv[output[1][0] + 1], sizeof(country) - 1);
|
|
for (i = 0; (unsigned int)i < strlen(country); i++) {
|
|
if ((country[i] < 'A') || (country[i] > 'z')) {
|
|
printf("Invalid Country Code\n");
|
|
print_apcmd_cfg_80211d_usage();
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (country[i] > 'Z')
|
|
country[i] = country[i] - 'a' + 'A';
|
|
}
|
|
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));
|
|
}
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
if (argc) {
|
|
printf("Set executed successfully\n");
|
|
if (sflag) {
|
|
if (sg_snmp_mib
|
|
(ACTION_SET, OID_80211D_ENABLE,
|
|
sizeof(state),
|
|
&state) == UAP_SUCCESS) {
|
|
printf("802.11d %sd \n",
|
|
state ? "enable" :
|
|
"disable");
|
|
}
|
|
}
|
|
} else {
|
|
j = uap_le16_to_cpu(cmd_buf->domain.length);
|
|
if (sg_snmp_mib
|
|
(ACTION_GET, OID_80211D_ENABLE,
|
|
sizeof(state), &state)
|
|
== UAP_SUCCESS) {
|
|
printf("State = %sd\n",
|
|
state ? "enable" : "disable");
|
|
}
|
|
|
|
if (cmd_buf->domain.country_code[0] ||
|
|
cmd_buf->domain.country_code[1] ||
|
|
cmd_buf->domain.country_code[2]) {
|
|
printf("Country string = %c%c%c",
|
|
cmd_buf->domain.country_code[0],
|
|
cmd_buf->domain.country_code[1],
|
|
cmd_buf->domain.country_code[2]);
|
|
j -= sizeof(cmd_buf->domain.
|
|
country_code);
|
|
subband =
|
|
(ieeetypes_subband_set_t *)
|
|
cmd_buf->domain.subband;
|
|
printf("\nSub-band info=");
|
|
printf("\t(1st, #chan, MAX-power) \n");
|
|
for (i = 0; i < (j / 3); i++) {
|
|
printf("\t\t(%d, \t%d, \t%d dbm)\n", subband->first_chan, subband->no_of_chan, subband->max_tx_pwr);
|
|
subband++;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
if (argc)
|
|
printf("11d info is allowed to set only before bss start.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a sys_config request and sends to the driver
|
|
*
|
|
* Usage: "Usage : sys_config [CONFIG_FILE]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_config(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_sys_configure *cmd_buf = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len;
|
|
t_u16 buf_len;
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
char **argv_dummy = NULL;
|
|
ps_mgmt pm;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sys_config_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_sys_config_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
/* Read profile and send command to firmware */
|
|
ret = apcmd_sys_config_profile(argc, argv);
|
|
return ret;
|
|
}
|
|
|
|
/** Query AP's setting */
|
|
buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
|
|
/* Alloc buf for command */
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(buf, 0, buf_len);
|
|
|
|
/* Reset custom_ie_present flag */
|
|
custom_ie_present = 0;
|
|
|
|
/* Reset max_mgmt_ie_print flag */
|
|
max_mgmt_ie_print = 0;
|
|
|
|
/* Locate headers */
|
|
cmd_len = sizeof(apcmdbuf_sys_configure);
|
|
cmd_buf = (apcmdbuf_sys_configure *)buf;
|
|
|
|
/* 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;
|
|
|
|
/* 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(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Print response */
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("AP settings:\n");
|
|
print_tlv(buf + sizeof(apcmdbuf_sys_configure),
|
|
cmd_buf->size -
|
|
sizeof(apcmdbuf_sys_configure) +
|
|
BUF_HEADER_SIZE);
|
|
if (apcmd_addbapara(1, argv_dummy) == UAP_FAILURE) {
|
|
printf("Couldn't get ADDBA parameters\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (apcmd_aggrpriotbl(1, argv_dummy) == UAP_FAILURE) {
|
|
printf("Couldn't get AMSDU/AMPDU priority table\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (apcmd_addbareject(1, argv_dummy) == UAP_FAILURE) {
|
|
printf("Couldn't get ADDBA reject table\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("\n802.11D setting:\n");
|
|
if (apcmd_cfg_80211d(1, argv_dummy) == UAP_FAILURE) {
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!custom_ie_present) {
|
|
printf("\nCustom IE settings:\n");
|
|
if (apcmd_sys_cfg_custom_ie(1, argv_dummy) ==
|
|
UAP_FAILURE) {
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
printf("ERR:Could not retrieve system configure\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
free(buf);
|
|
memset(&pm, 0, sizeof(ps_mgmt));
|
|
ret = send_power_mode_ioctl(&pm, 0);
|
|
return ret;
|
|
}
|
|
|
|
/** Update domain info with given country and band
|
|
*
|
|
* @param country_80211d country to be set
|
|
* @param band band of operation
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
static int
|
|
update_domain_info(char *country_80211d, int band)
|
|
{
|
|
apcmdbuf_cfg_80211d *cmd_buf = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
ieeetypes_subband_set_t sub_bands[MAX_SUB_BANDS];
|
|
t_u8 no_of_sub_band = 0;
|
|
char country[4] = { ' ', ' ', 0, 0 };
|
|
int ret = UAP_SUCCESS;
|
|
t_u8 domain_code = 0;
|
|
rgn_dom_code_t *prgn_dom_code = NULL;
|
|
|
|
/* Get currently set country code from FW */
|
|
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) && (cmd_buf->result == CMD_SUCCESS) &&
|
|
(cmd_buf->domain.country_code[0] ||
|
|
cmd_buf->domain.country_code[1] ||
|
|
cmd_buf->domain.country_code[2])) {
|
|
country[0] = cmd_buf->domain.country_code[0];
|
|
country[1] = cmd_buf->domain.country_code[1];
|
|
} else {
|
|
/* country_80211d will only be used if country code is not already set */
|
|
country[0] = country_80211d[0];
|
|
country[1] = country_80211d[1];
|
|
}
|
|
|
|
if (band == BAND_A)
|
|
printf("Enabling 11d for 11h operation and setting country code to %s\n", country);
|
|
cmd_len = sizeof(apcmdbuf_cfg_80211d);
|
|
/** Get domain information from the file */
|
|
no_of_sub_band =
|
|
parse_domain_file(country, band, sub_bands, &domain_code);
|
|
if (no_of_sub_band == UAP_FAILURE) {
|
|
printf("Parsing Failed\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Copy third character of country code here */
|
|
if (cmd_buf->domain.country_code[2]) {
|
|
country[2] = cmd_buf->domain.country_code[2];
|
|
} else {
|
|
country[2] = country_80211d[2];
|
|
}
|
|
|
|
/* Set domain for this country code */
|
|
memset(buf, 0, buf_len);
|
|
cmd_len += no_of_sub_band * sizeof(ieeetypes_subband_set_t);
|
|
/* Locate headers */
|
|
cmd_buf = (apcmdbuf_cfg_80211d *)buf;
|
|
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));
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result != CMD_SUCCESS) {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
printf("11d info is allowed to set only before bss start.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
|
|
if ((band == BAND_A) && domain_code) {
|
|
/* Send 11D_CMD a second time, with reg_dom_code TLV appended.
|
|
* Use hostcmd instead of re-route. */
|
|
cmd_len = cmd_buf->size + BUF_HEADER_SIZE;
|
|
prgn_dom_code = (rgn_dom_code_t *)((t_u8 *)cmd_buf + cmd_len);
|
|
cmd_len += sizeof(rgn_dom_code_t);
|
|
cmd_buf->size += sizeof(rgn_dom_code_t);
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG,
|
|
"Adding Region Domain Code TLV. Domain_code=%d\n",
|
|
domain_code);
|
|
#endif
|
|
prgn_dom_code->tag =
|
|
uap_cpu_to_le16(MRVL_REGION_DOMAIN_CODE_TLV_ID);
|
|
prgn_dom_code->length = uap_cpu_to_le16(sizeof(rgn_dom_code_t)
|
|
- BUF_HEADER_SIZE);
|
|
prgn_dom_code->domain_code = domain_code;
|
|
|
|
/* Send the command */
|
|
uap_ioctl_no_reroute = 1;
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
uap_ioctl_no_reroute = 0;
|
|
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result != CMD_SUCCESS) {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
printf("11d info is allowed to set only before bss start.\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
}
|
|
|
|
done:
|
|
if (buf)
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Covert MCS Rate Bitmap to MCS Rate index
|
|
*
|
|
* @param rate_bitmap Pointer to rate bitmap
|
|
* @param size Size of the bitmap array
|
|
*
|
|
* @return Rate index
|
|
*/
|
|
int
|
|
get_rate_index_from_bitmap(t_u16 *rate_bitmap, int size)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < size * 8; i++) {
|
|
if (rate_bitmap[i / 16] & (1 << (i % 16))) {
|
|
return i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks current system configuration
|
|
*
|
|
* @param buf pointer to TLV buffer
|
|
* @param len TLV buffer length
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
check_sys_config(t_u8 *buf, t_u16 len)
|
|
{
|
|
tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf;
|
|
int tlv_buf_left = len;
|
|
t_u16 tlv_type;
|
|
t_u16 tlv_len;
|
|
tlvbuf_channel_config *channel_tlv = NULL;
|
|
tlvbuf_channel_list *chnlist_tlv = NULL;
|
|
tlvbuf_pwk_cipher *pwk_cipher_tlv = NULL;
|
|
tlvbuf_gwk_cipher *gwk_cipher_tlv = NULL;
|
|
tlvbuf_auth_mode *auth_tlv = NULL;
|
|
tlvbuf_protocol *protocol_tlv = NULL;
|
|
tlvbuf_wep_key *wep_key_tlv = NULL;
|
|
tlvbuf_wpa_passphrase *passphrase_tlv = NULL;
|
|
tlvbuf_rates *rates_tlv = NULL;
|
|
tlvbuf_mcbc_data_rate *mcbc_data_rate_tlv = NULL;
|
|
t_u16 protocol = 0;
|
|
t_u16 mcbc_data_rate = 0;
|
|
t_u16 op_rates_len = 0;
|
|
t_u8 acs_mode_enabled = 0;
|
|
t_u8 *cbuf = NULL;
|
|
apcmdbuf_cfg_80211d *cmd_buf = NULL;
|
|
t_u16 buf_len, cmd_len;
|
|
char country_80211d[4] = { 'U', 'S', ' ', 0 };
|
|
t_u8 state_80211h = 0;
|
|
int channel_tlv_band = BAND_B | BAND_G;
|
|
t_u8 secondary_ch_set = 0;
|
|
int scan_channels_band = BAND_B | BAND_G;
|
|
t_u8 state_80211d = 0;
|
|
t_u8 rate = 0;
|
|
t_u32 rate_bitmap = 0;
|
|
tlvbuf_htcap_t *ht_cap_tlv = NULL;
|
|
t_u16 enable_40Mhz = 0;
|
|
t_u16 enable_20Mhz_sgi = 0;
|
|
t_u16 enable_gf = 0;
|
|
t_u8 enable_11n = 0;
|
|
int flag = 0;
|
|
fw_info fw;
|
|
channel_list *pchan_list;
|
|
tlvbuf_tx_power *txpower_tlv = NULL;
|
|
int i = 0, ret = UAP_SUCCESS;
|
|
int pairwise_cipher_wpa = -1;
|
|
int pairwise_cipher_wpa2 = -1;
|
|
int group_cipher = -1;
|
|
int chan_list_len = 0;
|
|
int key_set = 0;
|
|
t_u8 channel = 0;
|
|
tx_rate_cfg_t tx_rate_config;
|
|
t_u32 mcs_rate_index = 0;
|
|
struct eth_priv_vhtcfg vhtcfg = { 0 };
|
|
|
|
#define BITMAP_RATE_1M 0x01
|
|
#define BITMAP_RATE_2M 0x02
|
|
#define BITMAP_RATE_5_5M 0x04
|
|
#define BITMAP_RATE_11M 0x8
|
|
#define B_RATE_MANDATORY 0x0f
|
|
|
|
if (pcurrent_tlv == NULL) {
|
|
printf("ERR: No TLV buffer available!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d),
|
|
&state_80211d);
|
|
|
|
buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
cbuf = (t_u8 *)malloc(buf_len);
|
|
if (!cbuf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(cbuf, 0, buf_len);
|
|
/* Locate headers */
|
|
cmd_buf = (apcmdbuf_cfg_80211d *)cbuf;
|
|
cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
|
|
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 && cmd_buf->result == CMD_SUCCESS) {
|
|
if (cmd_buf->domain.country_code[0] ||
|
|
cmd_buf->domain.country_code[1] ||
|
|
cmd_buf->domain.country_code[2]) {
|
|
strncpy(country_80211d,
|
|
(char *)cmd_buf->domain.country_code,
|
|
COUNTRY_CODE_LEN);
|
|
}
|
|
}
|
|
free(cbuf);
|
|
|
|
/* get region code to handle special cases */
|
|
memset(&fw, 0, sizeof(fw));
|
|
if (get_fw_info(&fw)) {
|
|
printf("Could not get fw info!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) {
|
|
printf("Could not get tx_rate_cfg!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
while (tlv_buf_left >= (int)sizeof(tlvbuf_header) &&
|
|
(ret != UAP_FAILURE)) {
|
|
tlv_type = *(t_u8 *)&pcurrent_tlv->type;
|
|
tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8);
|
|
tlv_len = *(t_u8 *)&pcurrent_tlv->len;
|
|
tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8);
|
|
if ((sizeof(tlvbuf_header) + tlv_len) >
|
|
(unsigned int)tlv_buf_left) {
|
|
printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n",
|
|
tlv_len, tlv_buf_left);
|
|
break;
|
|
}
|
|
switch (tlv_type) {
|
|
case MRVL_CHANNELCONFIG_TLV_ID:
|
|
channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv;
|
|
channel = channel_tlv->chan_number;
|
|
|
|
if ((!state_80211d) &&
|
|
(channel_tlv->chan_number == MAX_CHANNELS_BG)
|
|
&&
|
|
(strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
|
|
== 0)
|
|
) {
|
|
printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (channel_tlv->bandcfg.chanBand == BAND_5GHZ)
|
|
channel_tlv_band = BAND_A;
|
|
secondary_ch_set = channel_tlv->bandcfg.chan2Offset;
|
|
if (channel_tlv_band != BAND_A) {
|
|
/* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US
|
|
* only for secondary channel below */
|
|
if (secondary_ch_set == SEC_CHAN_BELOW) {
|
|
if (!strncmp
|
|
(country_80211d, "US",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (channel_tlv->chan_number >
|
|
DEFAULT_MAX_CHANNEL_BELOW) {
|
|
printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strncmp
|
|
(country_80211d, "JP",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (channel_tlv->chan_number >
|
|
DEFAULT_MAX_CHANNEL_BELOW_NON_US)
|
|
{
|
|
printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US
|
|
* only for secondary channel above */
|
|
if (secondary_ch_set == SEC_CHAN_ABOVE) {
|
|
if (!strncmp
|
|
(country_80211d, "US",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (channel_tlv->chan_number >
|
|
DEFAULT_MAX_CHANNEL_ABOVE) {
|
|
printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strncmp
|
|
(country_80211d, "JP",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (channel_tlv->chan_number >
|
|
DEFAULT_MAX_CHANNEL_ABOVE_NON_US)
|
|
{
|
|
printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!(channel_tlv->bandcfg.scanMode == SCAN_MODE_ACS)) {
|
|
if (check_channel_validity_11d
|
|
(channel_tlv->chan_number, channel_tlv_band,
|
|
1) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
if (state_80211d) {
|
|
/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
|
|
if ((channel_tlv->chan_number <
|
|
MAX_CHANNELS_BG) &&
|
|
(channel_tlv_band == BAND_A))
|
|
strncpy(country_80211d, "JP ",
|
|
sizeof(country_80211d) -
|
|
1);
|
|
} else {
|
|
if ((channel_tlv_band == BAND_A) &&
|
|
((channel_tlv->chan_number == 8) ||
|
|
(channel_tlv->chan_number ==
|
|
12))) {
|
|
printf("ERR:Invalid band for given channel\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
acs_mode_enabled = 1;
|
|
}
|
|
#define JP_REGION_0xFE 0xFE
|
|
if (fw.region_code == JP_REGION_0xFE &&
|
|
((channel_tlv->chan_number == 12) ||
|
|
(channel_tlv->chan_number == 13))) {
|
|
printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
break;
|
|
case MRVL_CHANNELLIST_TLV_ID:
|
|
chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv;
|
|
pchan_list =
|
|
(channel_list *) & (chnlist_tlv->chan_list);
|
|
if (tlv_len % sizeof(channel_list)) {
|
|
printf("ERR:Invalid Scan channel list TLV!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
chan_list_len = tlv_len / sizeof(channel_list);
|
|
|
|
for (i = 0; i < chan_list_len; i++) {
|
|
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)
|
|
return UAP_FAILURE;
|
|
pchan_list++;
|
|
}
|
|
break;
|
|
case MRVL_TX_POWER_TLV_ID:
|
|
txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv;
|
|
if (state_80211d) {
|
|
if (check_tx_pwr_validity_11d
|
|
(txpower_tlv->tx_power_dbm) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
}
|
|
break;
|
|
case MRVL_CIPHER_PWK_TLV_ID:
|
|
pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv;
|
|
pwk_cipher_tlv->protocol =
|
|
uap_le16_to_cpu(pwk_cipher_tlv->protocol);
|
|
if (pwk_cipher_tlv->protocol == PROTOCOL_WPA)
|
|
pairwise_cipher_wpa =
|
|
pwk_cipher_tlv->pairwise_cipher;
|
|
else if (pwk_cipher_tlv->protocol == PROTOCOL_WPA2)
|
|
pairwise_cipher_wpa2 =
|
|
pwk_cipher_tlv->pairwise_cipher;
|
|
break;
|
|
case MRVL_CIPHER_GWK_TLV_ID:
|
|
gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv;
|
|
group_cipher = gwk_cipher_tlv->group_cipher;
|
|
break;
|
|
case MRVL_AUTH_TLV_ID:
|
|
auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv;
|
|
break;
|
|
case MRVL_PROTOCOL_TLV_ID:
|
|
protocol_tlv = (tlvbuf_protocol *)pcurrent_tlv;
|
|
protocol = uap_le16_to_cpu(protocol_tlv->protocol);
|
|
break;
|
|
case MRVL_WPA_PASSPHRASE_TLV_ID:
|
|
passphrase_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv;
|
|
break;
|
|
case MRVL_WEP_KEY_TLV_ID:
|
|
wep_key_tlv = (tlvbuf_wep_key *)pcurrent_tlv;
|
|
if (wep_key_tlv->is_default) {
|
|
key_set = 1;
|
|
}
|
|
break;
|
|
case HT_CAPABILITY_TLV_ID:
|
|
ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv;
|
|
ht_cap_tlv->ht_cap.ht_cap_info =
|
|
uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info);
|
|
if (ht_cap_tlv->ht_cap.supported_mcs_set[0]) {
|
|
enable_11n = 1;
|
|
enable_40Mhz =
|
|
IS_11N_40MHZ_ENABLED(ht_cap_tlv->ht_cap.
|
|
ht_cap_info);
|
|
enable_20Mhz_sgi =
|
|
IS_11N_20MHZ_SHORTGI_ENABLED
|
|
(ht_cap_tlv->ht_cap.ht_cap_info);
|
|
enable_gf =
|
|
IS_11N_GF_ENABLED(ht_cap_tlv->ht_cap.
|
|
ht_cap_info);
|
|
}
|
|
break;
|
|
case MRVL_RATES_TLV_ID:
|
|
rates_tlv = (tlvbuf_rates *)pcurrent_tlv;
|
|
op_rates_len = tlv_len;
|
|
break;
|
|
case MRVL_MCBC_DATA_RATE_TLV_ID:
|
|
mcbc_data_rate_tlv =
|
|
(tlvbuf_mcbc_data_rate *)pcurrent_tlv;
|
|
mcbc_data_rate =
|
|
uap_le16_to_cpu(mcbc_data_rate_tlv->
|
|
mcbc_datarate);
|
|
if (mcbc_data_rate &&
|
|
(is_mcbc_rate_valid((t_u8)mcbc_data_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid MCBC Data Rate \n");
|
|
return UAP_FAILURE;
|
|
}
|
|
break;
|
|
}
|
|
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
|
|
pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len);
|
|
}
|
|
|
|
if ((protocol == PROTOCOL_STATIC_WEP) && !key_set) {
|
|
printf("ERR:WEP keys not set!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (auth_tlv == NULL) {
|
|
printf("ERR: No authentication found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((auth_tlv->auth_mode == 1) && (protocol != PROTOCOL_STATIC_WEP)) {
|
|
printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (passphrase_tlv == NULL) {
|
|
printf("ERR: No passphrase found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2)
|
|
|| (protocol == PROTOCOL_WPA3_SAE)
|
|
|| (protocol == PROTOCOL_WPA2_MIXED))
|
|
&& !(passphrase_tlv->length)) {
|
|
printf("ERR:Passphrase must be set for WPA/WPA2/Mixed/WPA3 SAE mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((protocol == PROTOCOL_WPA) || (protocol == PROTOCOL_WPA2_MIXED)) {
|
|
if (is_cipher_valid(pairwise_cipher_wpa, group_cipher) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((protocol == PROTOCOL_WPA2) || (protocol == PROTOCOL_WPA2_MIXED)
|
|
|| (protocol == PROTOCOL_WPA3_SAE)
|
|
) {
|
|
if (is_cipher_valid(pairwise_cipher_wpa2, group_cipher) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (chnlist_tlv == NULL) {
|
|
printf("ERR: No channel list found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (acs_mode_enabled) {
|
|
pchan_list = (channel_list *) & (chnlist_tlv->chan_list);
|
|
for (i = 0; i < chan_list_len; i++) {
|
|
if ((!state_80211d) &&
|
|
(pchan_list->chan_number == MAX_CHANNELS_BG)
|
|
&&
|
|
(strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
|
|
== 0)
|
|
) {
|
|
printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (fw.region_code == JP_REGION_0xFE &&
|
|
((pchan_list->chan_number == 12) ||
|
|
(pchan_list->chan_number == 13))) {
|
|
printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
pchan_list++;
|
|
}
|
|
|
|
if (!state_80211d) {
|
|
/* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */
|
|
pchan_list =
|
|
(channel_list *) & (chnlist_tlv->chan_list);
|
|
for (i = 0; i < chan_list_len; i++) {
|
|
if ((pchan_list->bandcfg.chanBand == BAND_5GHZ)
|
|
&& ((pchan_list->chan_number == 8) ||
|
|
(pchan_list->chan_number == 12))) {
|
|
printf("ERR: Invalid band for scan channel %d\n", pchan_list->chan_number);
|
|
return UAP_FAILURE;
|
|
}
|
|
pchan_list++;
|
|
}
|
|
}
|
|
if (state_80211d) {
|
|
/* Set default country code to US */
|
|
strncpy(country_80211d, "US ",
|
|
sizeof(country_80211d) - 1);
|
|
pchan_list =
|
|
(channel_list *) & (chnlist_tlv->chan_list);
|
|
for (i = 0; i < chan_list_len; i++) {
|
|
/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
|
|
if ((pchan_list->chan_number < MAX_CHANNELS_BG)
|
|
&& (scan_channels_band == BAND_A)) {
|
|
strncpy(country_80211d, "JP ",
|
|
sizeof(country_80211d) - 1);
|
|
}
|
|
if (check_channel_validity_11d
|
|
(pchan_list->chan_number,
|
|
scan_channels_band, 0) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
pchan_list++;
|
|
}
|
|
if (update_domain_info
|
|
(country_80211d,
|
|
scan_channels_band) == UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
#ifdef WIFI_DIRECT_SUPPORT
|
|
if (strncmp(dev_name, "wfd", 3))
|
|
#endif
|
|
if ((!acs_mode_enabled &&
|
|
(channel_tlv_band == (BAND_B | BAND_G)))
|
|
|| (acs_mode_enabled &&
|
|
(scan_channels_band == (BAND_B | BAND_G)))) {
|
|
if (rates_tlv == NULL) {
|
|
printf("ERR: No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < op_rates_len; i++) {
|
|
rate = rates_tlv->
|
|
operational_rates[i] &
|
|
~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
rate_bitmap |= BITMAP_RATE_1M;
|
|
break;
|
|
case 4:
|
|
rate_bitmap |= BITMAP_RATE_2M;
|
|
break;
|
|
case 11:
|
|
rate_bitmap |= BITMAP_RATE_5_5M;
|
|
break;
|
|
case 22:
|
|
rate_bitmap |= BITMAP_RATE_11M;
|
|
break;
|
|
}
|
|
}
|
|
if ((rate_bitmap & B_RATE_MANDATORY) !=
|
|
B_RATE_MANDATORY) {
|
|
if (acs_mode_enabled)
|
|
printf("ERR: Rates/Scan channels do not match!\n");
|
|
else
|
|
printf("ERR: Rates/Channel do not match!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((!acs_mode_enabled && (channel_tlv_band == BAND_A))
|
|
|| (acs_mode_enabled && (scan_channels_band == BAND_A))) {
|
|
if (rates_tlv == NULL) {
|
|
printf("ERR: No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < op_rates_len; i++) {
|
|
rate = rates_tlv->
|
|
operational_rates[i] & ~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
case 4:
|
|
case 11:
|
|
case 22:
|
|
if (acs_mode_enabled)
|
|
printf("ERR: Rates/Scan channels do not match!\n");
|
|
else
|
|
printf("ERR: Rates/Channel do not match!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
state_80211h = 1;
|
|
if (sg_snmp_mib
|
|
(ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h),
|
|
&state_80211h)
|
|
== UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
|
|
#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
|
|
|
|
if (enable_40Mhz) {
|
|
if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) {
|
|
printf("ERR: It's not support HT40 from Hardware Cap\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (enable_11n) {
|
|
/*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */
|
|
if ((protocol == PROTOCOL_WPA2_MIXED) &&
|
|
(pairwise_cipher_wpa2 == CIPHER_TKIP)) {
|
|
printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n");
|
|
return UAP_FAILURE;
|
|
} else if (protocol == PROTOCOL_STATIC_WEP) {
|
|
printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) {
|
|
printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_20Mhz_sgi && enable_gf) {
|
|
if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) &&
|
|
(tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) {
|
|
printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
mcs_rate_index =
|
|
get_rate_index_from_bitmap(tx_rate_config.bitmap_rates,
|
|
sizeof(tx_rate_config.bitmap_rates));
|
|
if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) &&
|
|
(mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) {
|
|
mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0);
|
|
if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) {
|
|
printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_20Mhz_sgi && enable_gf) {
|
|
if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) &&
|
|
(mcs_rate_index <= UAP_RATE_INDEX_MCS7)) {
|
|
printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if 11d enabled, Channel 14, country code "JP", only B rates are allowed */
|
|
if ((channel == 14) && state_80211d &&
|
|
(strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) {
|
|
if (rates_tlv == NULL) {
|
|
printf("ERR:No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_11n) {
|
|
printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < op_rates_len; i++) {
|
|
rate = rates_tlv->
|
|
operational_rates[i] & ~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
case 4:
|
|
case 11:
|
|
case 22:
|
|
break;
|
|
default:
|
|
printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Channels 14, 165 are not allowed to operate in 40MHz mode */
|
|
if (!acs_mode_enabled && enable_40Mhz) {
|
|
if ((channel == 14)
|
|
|| (channel == 165)
|
|
) {
|
|
printf("ERR:Invalid channel %d for 40MHz operation\n",
|
|
channel);
|
|
return UAP_FAILURE;
|
|
} else if (!secondary_ch_set) {
|
|
printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
/* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */
|
|
if (acs_mode_enabled && enable_40Mhz) {
|
|
if (chnlist_tlv == NULL) {
|
|
printf("ERR: No channel list found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
pchan_list = (channel_list *) & (chnlist_tlv->chan_list);
|
|
for (i = 0; i < chan_list_len; i++) {
|
|
if ((pchan_list->chan_number != 14)
|
|
&& (pchan_list->chan_number != 140) &&
|
|
(pchan_list->chan_number != 165)
|
|
) {
|
|
flag = 1;
|
|
break;
|
|
}
|
|
pchan_list++;
|
|
}
|
|
if (!flag) {
|
|
printf("ERR:Invalid channels in scan channel list for 40MHz operation\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (0 == get_fw_info(&fw)) {
|
|
/*check whether support 802.11AC through BAND_AAC bit */
|
|
if (fw.fw_bands & BAND_AAC) {
|
|
ret = get_802_11ac_cfg(&vhtcfg);
|
|
if (UAP_SUCCESS == ret) {
|
|
/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
|
|
if ((vhtcfg.vht_rx_mcs != 0xffff) &&
|
|
(!enable_11n)) {
|
|
printf("ERR: 11ac enable while 11n disable, it is forbidden! \n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("Don't support 802.11AC \n");
|
|
return UAP_SUCCESS;
|
|
}
|
|
} else
|
|
printf("No support 802 11AC.\n");
|
|
} else {
|
|
printf("ERR: get_fw_info fail\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks current bss configuration
|
|
*
|
|
* @param buf pointer to bss_config_t
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
check_bss_config(t_u8 *buf)
|
|
{
|
|
bss_config_t *bss_config = NULL;;
|
|
t_u8 acs_mode_enabled = 0;
|
|
t_u8 *cbuf = NULL;
|
|
apcmdbuf_cfg_80211d *cmd_buf = NULL;
|
|
t_u16 buf_len, cmd_len;
|
|
char country_80211d[4] = { 'U', 'S', ' ', 0 };
|
|
t_u8 state_80211h = 0;
|
|
int channel_tlv_band = BAND_B | BAND_G;
|
|
t_u8 secondary_ch_set = 0;
|
|
int scan_channels_band = BAND_B | BAND_G;
|
|
t_u8 state_80211d = 0;
|
|
t_u8 rate = 0;
|
|
t_u32 rate_bitmap = 0;
|
|
t_u16 enable_40Mhz = 0;
|
|
t_u16 enable_20Mhz_sgi = 0;
|
|
t_u16 enable_gf = 0;
|
|
t_u8 enable_11n = 0;
|
|
int flag = 0;
|
|
fw_info fw;
|
|
int i = 0, ret = UAP_SUCCESS;
|
|
tx_rate_cfg_t tx_rate_config;
|
|
t_u32 mcs_rate_index = 0;
|
|
struct eth_priv_vhtcfg vhtcfg = { 0 };
|
|
|
|
#define BITMAP_RATE_1M 0x01
|
|
#define BITMAP_RATE_2M 0x02
|
|
#define BITMAP_RATE_5_5M 0x04
|
|
#define BITMAP_RATE_11M 0x8
|
|
#define B_RATE_MANDATORY 0x0f
|
|
|
|
if (NULL == buf) {
|
|
printf("ERR: No buffer for bss_configure!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
bss_config = (bss_config_t *)buf;
|
|
|
|
ret = sg_snmp_mib(ACTION_GET, OID_80211D_ENABLE, sizeof(state_80211d),
|
|
&state_80211d);
|
|
|
|
buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
cbuf = (t_u8 *)malloc(buf_len);
|
|
if (!cbuf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(cbuf, 0, buf_len);
|
|
/* Locate headers */
|
|
cmd_buf = (apcmdbuf_cfg_80211d *)cbuf;
|
|
cmd_len = (sizeof(apcmdbuf_cfg_80211d) - sizeof(domain_param_t));
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
|
|
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 && cmd_buf->result == CMD_SUCCESS) {
|
|
if (cmd_buf->domain.country_code[0] ||
|
|
cmd_buf->domain.country_code[1] ||
|
|
cmd_buf->domain.country_code[2]) {
|
|
strncpy(country_80211d,
|
|
(char *)cmd_buf->domain.country_code,
|
|
COUNTRY_CODE_LEN);
|
|
}
|
|
}
|
|
free(cbuf);
|
|
|
|
/* get region code to handle special cases */
|
|
memset(&fw, 0, sizeof(fw));
|
|
if (get_fw_info(&fw)) {
|
|
printf("Could not get fw info!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (get_tx_rate_cfg(&tx_rate_config) == UAP_FAILURE) {
|
|
printf("Could not get tx_rate_cfg!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((!state_80211d) && (bss_config->channel == MAX_CHANNELS_BG)
|
|
&& (strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)
|
|
) {
|
|
printf("ERR: Invalid channel 14, 802.11d disabled, country code JP!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((fw.fw_bands & (BAND_B | BAND_G | BAND_GN | BAND_GAC))
|
|
&& !(fw.fw_bands & (BAND_A | BAND_AAC))
|
|
) {
|
|
if (bss_config->channel > MAX_CHANNELS_BG) {
|
|
printf("ERR: Invalid channel in 2.4GHz band!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (!(fw.fw_bands & (BAND_B | BAND_G | BAND_GN
|
|
| BAND_GAC)) && (fw.fw_bands & (BAND_A
|
|
| BAND_AAC))) {
|
|
if (bss_config->channel < 36 ||
|
|
bss_config->channel > MAX_CHANNELS) {
|
|
printf("ERR: Invalid channel in 5GHz band!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if (bss_config->bandcfg.chanBand == BAND_5GHZ)
|
|
channel_tlv_band = BAND_A;
|
|
secondary_ch_set = bss_config->bandcfg.chan2Offset;
|
|
if (channel_tlv_band != BAND_A) {
|
|
/* When country code is not Japan, allow channels 5-11 for US and 5-13 for non-US
|
|
* only for secondary channel below */
|
|
if (secondary_ch_set == SEC_CHAN_BELOW) {
|
|
if (!strncmp
|
|
(country_80211d, "US", COUNTRY_CODE_LEN - 1)) {
|
|
if (bss_config->channel >
|
|
DEFAULT_MAX_CHANNEL_BELOW) {
|
|
printf("ERR: Only channels 5-11 are allowed with secondary channel below for the US\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strncmp
|
|
(country_80211d, "JP",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (bss_config->channel >
|
|
DEFAULT_MAX_CHANNEL_BELOW_NON_US) {
|
|
printf("ERR: Only channels 5-13 are allowed with secondary channel below for" "non-Japan countries!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* When country code is not Japan, allow channels 1-7 for US and 1-9 for non-US
|
|
* only for secondary channel above */
|
|
if (secondary_ch_set == SEC_CHAN_ABOVE) {
|
|
if (!strncmp
|
|
(country_80211d, "US", COUNTRY_CODE_LEN - 1)) {
|
|
if (bss_config->channel >
|
|
DEFAULT_MAX_CHANNEL_ABOVE) {
|
|
printf("ERR: Only channels 1-7 are allowed with secondary channel above for the US\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else if (strncmp
|
|
(country_80211d, "JP",
|
|
COUNTRY_CODE_LEN - 1)) {
|
|
if (bss_config->channel >
|
|
DEFAULT_MAX_CHANNEL_ABOVE_NON_US) {
|
|
printf("ERR: Only channels 1-9 are allowed with secondary channel above for" "non-Japan countries!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(bss_config->bandcfg.scanMode == SCAN_MODE_ACS)) {
|
|
if (check_channel_validity_11d
|
|
(bss_config->channel, channel_tlv_band, 1) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
if (state_80211d) {
|
|
/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
|
|
if ((bss_config->channel < MAX_CHANNELS_BG) &&
|
|
(channel_tlv_band == BAND_A))
|
|
strncpy(country_80211d, "JP ",
|
|
sizeof(country_80211d) - 1);
|
|
} else {
|
|
if ((channel_tlv_band == BAND_A) &&
|
|
((bss_config->channel == 8) ||
|
|
(bss_config->channel == 12))) {
|
|
printf("ERR:Invalid band for given channel\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
acs_mode_enabled = 1;
|
|
}
|
|
|
|
#define JP_REGION_0xFE 0xFE
|
|
if (fw.region_code == JP_REGION_0xFE &&
|
|
((bss_config->channel == 12) || (bss_config->channel == 13))) {
|
|
printf("ERR:Channel 12 or 13 is not allowed for region code 0xFE\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < bss_config->num_of_chan; i++) {
|
|
scan_channels_band = BAND_B | BAND_G;
|
|
if ((scan_channels_band != BAND_A) &&
|
|
(bss_config->chan_list[i].bandcfg.chanBand == BAND_5GHZ)) {
|
|
scan_channels_band = BAND_A;
|
|
}
|
|
if (check_channel_validity_11d
|
|
(bss_config->chan_list[i].chan_number, scan_channels_band,
|
|
0) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (state_80211d) {
|
|
if (check_tx_pwr_validity_11d(bss_config->tx_power_level) ==
|
|
UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (bss_config->supported_mcs_set[0]) {
|
|
enable_11n = 1;
|
|
enable_40Mhz = IS_11N_40MHZ_ENABLED(bss_config->ht_cap_info);
|
|
enable_20Mhz_sgi =
|
|
IS_11N_20MHZ_SHORTGI_ENABLED(bss_config->ht_cap_info);
|
|
enable_gf = IS_11N_GF_ENABLED(bss_config->ht_cap_info);
|
|
}
|
|
|
|
if (bss_config->mcbc_data_rate &&
|
|
(is_mcbc_rate_valid(bss_config->mcbc_data_rate) != UAP_SUCCESS)) {
|
|
printf("ERR: Invalid MCBC Data Rate \n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((bss_config->protocol == PROTOCOL_STATIC_WEP)
|
|
&& (0 == bss_config->wep_cfg.key0.is_default)
|
|
&& (0 == bss_config->wep_cfg.key1.is_default)
|
|
&& (0 == bss_config->wep_cfg.key2.is_default)
|
|
&& (0 == bss_config->wep_cfg.key3.is_default)) {
|
|
printf("ERR:WEP keys not set!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((bss_config->auth_mode == 1) &&
|
|
(bss_config->protocol != PROTOCOL_STATIC_WEP)) {
|
|
printf("ERR:Shared key authentication is not allowed for Open/WPA/WPA2/Mixed mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (((bss_config->protocol == PROTOCOL_WPA) ||
|
|
(bss_config->protocol == PROTOCOL_WPA2)
|
|
|| (bss_config->protocol == PROTOCOL_WPA3_SAE)
|
|
|| (bss_config->protocol == PROTOCOL_WPA2_MIXED)) &&
|
|
!(bss_config->wpa_cfg.length)) {
|
|
printf("ERR:Passphrase must be set for WPA/WPA2/Mixed/WPA3 SAE mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((bss_config->protocol == PROTOCOL_WPA) ||
|
|
(bss_config->protocol == PROTOCOL_WPA2_MIXED)) {
|
|
if (is_cipher_valid
|
|
(bss_config->wpa_cfg.pairwise_cipher_wpa,
|
|
bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((bss_config->protocol == PROTOCOL_WPA2) ||
|
|
(bss_config->protocol == PROTOCOL_WPA2_MIXED)
|
|
|| (bss_config->protocol == PROTOCOL_WPA3_SAE)
|
|
) {
|
|
if (is_cipher_valid
|
|
(bss_config->wpa_cfg.pairwise_cipher_wpa2,
|
|
bss_config->wpa_cfg.group_cipher) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (0 == bss_config->num_of_chan) {
|
|
printf("ERR: No channel list found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (acs_mode_enabled) {
|
|
for (i = 0; i < bss_config->num_of_chan; i++) {
|
|
if ((!state_80211d) &&
|
|
(bss_config->chan_list[i].chan_number ==
|
|
MAX_CHANNELS_BG)
|
|
&&
|
|
(strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1)
|
|
== 0)
|
|
) {
|
|
printf("ERR: Invalid scan channel 14, 802.11d disabled, country code JP!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (fw.region_code == JP_REGION_0xFE &&
|
|
((bss_config->chan_list[i].chan_number == 12) ||
|
|
(bss_config->chan_list[i].chan_number == 13))) {
|
|
printf("ERR:Scan Channel 12 or 13 is not allowed for region code 0xFE\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (!state_80211d) {
|
|
/* Block scan channels 8 and 12 in 5GHz band if 11d is not enabled and country code not set to JP */
|
|
for (i = 0; i < bss_config->num_of_chan; i++) {
|
|
if ((bss_config->chan_list[i].bandcfg.
|
|
chanBand == BAND_5GHZ)
|
|
&&
|
|
((bss_config->chan_list[i].chan_number == 8)
|
|
|| (bss_config->chan_list[i].chan_number ==
|
|
12))) {
|
|
printf("ERR: Invalid band for scan channel %d\n", bss_config->chan_list[i].chan_number);
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (state_80211d) {
|
|
/* Set default country code to US */
|
|
strncpy(country_80211d, "US ",
|
|
sizeof(country_80211d) - 1);
|
|
for (i = 0; i < bss_config->num_of_chan; i++) {
|
|
/* Set country code to JP if channel is 8 or 12 and band is 5GHZ */
|
|
if ((bss_config->chan_list[i].chan_number <
|
|
MAX_CHANNELS_BG) &&
|
|
(scan_channels_band == BAND_A)) {
|
|
strncpy(country_80211d, "JP ",
|
|
sizeof(country_80211d) - 1);
|
|
}
|
|
if (check_channel_validity_11d
|
|
(bss_config->chan_list[i].chan_number,
|
|
scan_channels_band, 0) == UAP_FAILURE)
|
|
return UAP_FAILURE;
|
|
}
|
|
if (update_domain_info
|
|
(country_80211d,
|
|
scan_channels_band) == UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
#ifdef WIFI_DIRECT_SUPPORT
|
|
if (strncmp(dev_name, "wfd", 3))
|
|
#endif
|
|
if ((!acs_mode_enabled &&
|
|
(channel_tlv_band == (BAND_B | BAND_G)))
|
|
|| (acs_mode_enabled &&
|
|
(scan_channels_band == (BAND_B | BAND_G)))) {
|
|
if (0 == bss_config->rates[0]) {
|
|
printf("ERR: No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i];
|
|
i++) {
|
|
rate = bss_config->
|
|
rates[i] & ~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
rate_bitmap |= BITMAP_RATE_1M;
|
|
break;
|
|
case 4:
|
|
rate_bitmap |= BITMAP_RATE_2M;
|
|
break;
|
|
case 11:
|
|
rate_bitmap |= BITMAP_RATE_5_5M;
|
|
break;
|
|
case 22:
|
|
rate_bitmap |= BITMAP_RATE_11M;
|
|
break;
|
|
}
|
|
}
|
|
if ((rate_bitmap & B_RATE_MANDATORY) !=
|
|
B_RATE_MANDATORY) {
|
|
if (acs_mode_enabled)
|
|
printf("ERR: Rates/Scan channels do not match!\n");
|
|
else
|
|
printf("ERR: Rates/Channel do not match!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((!acs_mode_enabled && (channel_tlv_band == BAND_A))
|
|
|| (acs_mode_enabled && (scan_channels_band == BAND_A))) {
|
|
if (0 == bss_config->rates[0]) {
|
|
printf("ERR: No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) {
|
|
rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
case 4:
|
|
case 11:
|
|
case 22:
|
|
if (acs_mode_enabled)
|
|
printf("ERR: Rates/Scan channels do not match!\n");
|
|
else
|
|
printf("ERR: Rates/Channel do not match!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
state_80211h = 1;
|
|
if (sg_snmp_mib
|
|
(ACTION_SET, OID_80211H_ENABLE, sizeof(state_80211h),
|
|
&state_80211h)
|
|
== UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
if (update_domain_info(country_80211d, BAND_A) == UAP_FAILURE) {
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & MBIT(17))
|
|
#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & MBIT(24))
|
|
|
|
if (enable_40Mhz) {
|
|
if (!ISSUPP_CHANWIDTH40(fw.hw_dot_11n_dev_cap)) {
|
|
printf("ERR: It's not support HT40 from Hardware Cap\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (enable_11n) {
|
|
/*For protocol = Mixed, 11n enabled, only allow TKIP cipher for WPA protocol, not for WPA2 */
|
|
if ((bss_config->protocol == PROTOCOL_WPA2_MIXED) &&
|
|
(bss_config->wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP)) {
|
|
printf("ERR: WPA2 pairwise cipher cannot be TKIP when AP operates in 802.11n Mixed mode.\n");
|
|
return UAP_FAILURE;
|
|
} else if (bss_config->protocol == PROTOCOL_STATIC_WEP) {
|
|
printf("ERR: WEP cannot be used when AP operates in 802.11n mode.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((tx_rate_config.rate == UAP_RATE_INDEX_MCS32) && !enable_40Mhz) {
|
|
printf("ERR:uAP must be configured to operate in 40MHz if tx_rate is MCS32\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_20Mhz_sgi && enable_gf) {
|
|
if ((tx_rate_config.rate >= UAP_RATE_INDEX_MCS0) &&
|
|
(tx_rate_config.rate <= UAP_RATE_INDEX_MCS7)) {
|
|
printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
mcs_rate_index =
|
|
get_rate_index_from_bitmap(tx_rate_config.bitmap_rates,
|
|
sizeof(tx_rate_config.bitmap_rates));
|
|
if ((mcs_rate_index >= UAP_RATE_BITMAP_MCS0) &&
|
|
(mcs_rate_index <= UAP_RATE_BITMAP_MCS127)) {
|
|
mcs_rate_index -= (UAP_RATE_BITMAP_MCS0 - UAP_RATE_INDEX_MCS0);
|
|
if ((mcs_rate_index == UAP_RATE_INDEX_MCS32) & !enable_40Mhz) {
|
|
printf("ERR:uAP must be configured to operate in 40MHz if rate_bitmap contains MCS32\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_20Mhz_sgi && enable_gf) {
|
|
if ((mcs_rate_index >= UAP_RATE_INDEX_MCS0) &&
|
|
(mcs_rate_index <= UAP_RATE_INDEX_MCS7)) {
|
|
printf("ERR: Invalid tx_rate for uAP in (20MHz Short GI + Green Field) mode\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if 11d enabled, Channel 14, country code "JP", only B rates are allowed*/
|
|
if ((bss_config->channel == 14) && state_80211d &&
|
|
(strncmp(country_80211d, "JP", COUNTRY_CODE_LEN - 1) == 0)) {
|
|
if (0 == bss_config->rates[0]) {
|
|
printf("ERR:No rates found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (enable_11n) {
|
|
printf("ERR:11n must be disabled and the only B rates are allowed if 11d enabled and country code is JP with channel 14.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < MAX_DATA_RATES && bss_config->rates[i]; i++) {
|
|
rate = bss_config->rates[i] & ~BASIC_RATE_SET_BIT;
|
|
switch (rate) {
|
|
case 2:
|
|
case 4:
|
|
case 11:
|
|
case 22:
|
|
break;
|
|
default:
|
|
printf("ERR:If 11d enabled, channel 14 and country code is JP, the only B rates are allowed.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Channels 14, 165 are not allowed to operate in 40MHz mode */
|
|
if (!acs_mode_enabled && enable_40Mhz) {
|
|
if ((bss_config->channel == 14)
|
|
|| (bss_config->channel == 165)
|
|
) {
|
|
printf("ERR:Invalid channel %d for 40MHz operation\n",
|
|
bss_config->channel);
|
|
return UAP_FAILURE;
|
|
} else if (!secondary_ch_set) {
|
|
printf("ERR:Secondary channel should be set when 40Mhz is enabled!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
/* Channels 14, 140, 165 are not allowed to operate in 40MHz mode */
|
|
if (acs_mode_enabled && enable_40Mhz) {
|
|
if (bss_config->num_of_chan == 0) {
|
|
printf("ERR: No channel list found\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < bss_config->num_of_chan; i++) {
|
|
if ((bss_config->chan_list[i].chan_number != 14)
|
|
&& (bss_config->chan_list[i].chan_number != 140) &&
|
|
(bss_config->chan_list[i].chan_number != 165)
|
|
) {
|
|
flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag) {
|
|
printf("ERR:Invalid channels in scan channel list for 40MHz operation\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (0 == get_fw_info(&fw)) {
|
|
/*check whether support 802.11AC through BAND_AAC bit */
|
|
if (fw.fw_bands & BAND_AAC) {
|
|
ret = get_802_11ac_cfg(&vhtcfg);
|
|
if (UAP_SUCCESS == ret) {
|
|
/* Note: When 11AC is disabled, FW sets vht_rx_mcs to 0xffff */
|
|
if ((vhtcfg.vht_rx_mcs != 0xffff) &&
|
|
(!enable_11n)) {
|
|
printf("ERR: 11ac enable while 11n disable, it is forbidden! \n");
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("Don't support 802.11AC \n");
|
|
return UAP_SUCCESS;
|
|
}
|
|
} else
|
|
printf("No support 802 11AC.\n");
|
|
} else {
|
|
printf("ERR: get_fw_info fail\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Send read/write command along with register details to the driver
|
|
* @param reg Reg type
|
|
* @param offset Pointer to register offset string
|
|
* @param strvalue Pointer to value string
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_regrdwr_process(int reg, char *offset, char *strvalue)
|
|
{
|
|
apcmdbuf_reg_rdwr *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;
|
|
char *whichreg;
|
|
|
|
/* Alloc buf for command */
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(buf, 0, buf_len);
|
|
|
|
/* Locate headers */
|
|
cmd_len = sizeof(apcmdbuf_reg_rdwr);
|
|
cmd_buf = (apcmdbuf_reg_rdwr *)buf;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
|
|
switch (reg) {
|
|
case CMD_MAC:
|
|
whichreg = "MAC";
|
|
cmd_buf->cmd_code = HostCmd_CMD_MAC_REG_ACCESS;
|
|
break;
|
|
case CMD_BBP:
|
|
whichreg = "BBP";
|
|
cmd_buf->cmd_code = HostCmd_CMD_BBP_REG_ACCESS;
|
|
break;
|
|
case CMD_RF:
|
|
cmd_buf->cmd_code = HostCmd_CMD_RF_REG_ACCESS;
|
|
whichreg = "RF";
|
|
break;
|
|
default:
|
|
printf("Invalid register set specified.\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (strvalue) {
|
|
cmd_buf->action = 1; // WRITE
|
|
} else {
|
|
cmd_buf->action = 0; // READ
|
|
}
|
|
cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
|
|
cmd_buf->offset = A2HEXDECIMAL(offset);
|
|
cmd_buf->offset = uap_cpu_to_le16(cmd_buf->offset);
|
|
if (strvalue) {
|
|
cmd_buf->value = A2HEXDECIMAL(strvalue);
|
|
cmd_buf->value = uap_cpu_to_le32(cmd_buf->value);
|
|
}
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("Successfully executed the command\n");
|
|
printf("%s[0x%04hx] = 0x%08x\n",
|
|
whichreg, uap_le16_to_cpu(cmd_buf->offset),
|
|
uap_le32_to_cpu(cmd_buf->value));
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
free(buf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Send read command for EEPROM
|
|
*
|
|
* Usage: "Usage : rdeeprom <offset> <byteCount>"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_read_eeprom(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_eeprom_access *cmd_buf = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
t_u16 byte_count, offset;
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_apcmd_read_eeprom_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (!argc ||
|
|
(argc && is_input_valid(RDEEPROM, argc, argv) != UAP_SUCCESS)) {
|
|
print_apcmd_read_eeprom_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
offset = A2HEXDECIMAL(argv[0]);
|
|
byte_count = A2HEXDECIMAL(argv[1]);
|
|
|
|
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_eeprom_access *)buf;
|
|
cmd_len = sizeof(apcmdbuf_eeprom_access);
|
|
|
|
cmd_buf->size = sizeof(apcmdbuf_eeprom_access) - BUF_HEADER_SIZE;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->action = 0;
|
|
|
|
cmd_buf->cmd_code = HostCmd_EEPROM_ACCESS;
|
|
cmd_buf->offset = uap_cpu_to_le16(offset);
|
|
cmd_buf->byte_count = uap_cpu_to_le16(byte_count);
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("Successfully executed the command\n");
|
|
byte_count = uap_le16_to_cpu(cmd_buf->byte_count);
|
|
offset = uap_le16_to_cpu(cmd_buf->offset);
|
|
hexdump_data("EEPROM", (void *)cmd_buf->value,
|
|
byte_count, ' ');
|
|
} else {
|
|
printf("ERR:Command Response incorrect!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the regrdwr command
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_regrdwr_usage(void)
|
|
{
|
|
printf("\nUsage : uaputl.exe regrdwr <TYPE> <OFFSET> [value]\n");
|
|
printf("\nTYPE Options: 1 - read/write MAC register");
|
|
printf("\n 2 - read/write BBP register");
|
|
printf("\n 3 - read/write RF register");
|
|
printf("\n");
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief Provides interface to perform read/write operations on regsiters
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_regrdwr(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
t_s32 reg;
|
|
int ret = UAP_SUCCESS;
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_regrdwr_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if ((argc < 2) || (argc > 3)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_regrdwr_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[0]) != 1) && (atoi(argv[0]) != 2) &&
|
|
(atoi(argv[0]) != 3)) {
|
|
printf("ERR:Illegal register type %s. Must be either '1','2' or '3'.\n", argv[0]);
|
|
print_regrdwr_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
reg = atoi(argv[0]);
|
|
ret = apcmd_regrdwr_process(reg, argv[1], argc > 2 ? argv[2] : NULL);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the memaccess command
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_memaccess_usage(void)
|
|
{
|
|
printf("\nUsage : uaputl.exe memaccess <ADDRESS> [value]\n");
|
|
printf("\nRead/Write memory location");
|
|
printf("\nADDRESS: Address of the memory location to be read/written");
|
|
printf("\nValue : Value to be written at that address\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Provides interface to perform read/write memory location
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_memaccess(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
apcmdbuf_mem_access *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;
|
|
char *address = NULL;
|
|
char *value = NULL;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_memaccess_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if ((argc < 1) || (argc > 2)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_memaccess_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
address = argv[0];
|
|
if (argc == 2)
|
|
value = argv[1];
|
|
|
|
/* Alloc buf for command */
|
|
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_len = sizeof(apcmdbuf_mem_access);
|
|
cmd_buf = (apcmdbuf_mem_access *)buf;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->cmd_code = HostCmd_CMD_MEM_ACCESS;
|
|
|
|
if (value)
|
|
cmd_buf->action = 1; // WRITE
|
|
else
|
|
cmd_buf->action = 0; // READ
|
|
|
|
cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
|
|
cmd_buf->address = A2HEXDECIMAL(address);
|
|
cmd_buf->address = uap_cpu_to_le32(cmd_buf->address);
|
|
|
|
if (value) {
|
|
cmd_buf->value = A2HEXDECIMAL(value);
|
|
cmd_buf->value = uap_cpu_to_le32(cmd_buf->value);
|
|
}
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("Successfully executed the command\n");
|
|
printf("[0x%04x] = 0x%08x\n",
|
|
uap_le32_to_cpu(cmd_buf->address),
|
|
uap_le32_to_cpu(cmd_buf->value));
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
free(buf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a sys_debug request to send data packet directly to driver
|
|
* @param pkt_type packet type 0 or 5.
|
|
* @param control management packet tx control field.
|
|
* @param file packet data file.
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_debug_data_packet_inject(int pkt_type, int control, char *file)
|
|
{
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 *buf = NULL;
|
|
t_u32 data_len;
|
|
FILE *fp = NULL;
|
|
pkt_header *header = NULL;
|
|
|
|
/* Check if file exists */
|
|
fp = fopen(file, "r");
|
|
if (fp == NULL) {
|
|
printf("\nERR:Data file can not be opened %s.\n", file);
|
|
return UAP_FAILURE;
|
|
}
|
|
buf = (t_u8 *)malloc(MRVDRV_SIZE_OF_PKT_BUFFER);
|
|
if (buf == NULL) {
|
|
printf("Error: allocate memory for packet buffer failed\n");
|
|
fclose(fp);
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(buf, 0, MRVDRV_SIZE_OF_PKT_BUFFER);
|
|
header = (pkt_header *)buf;
|
|
data_len = fparse_for_hex(fp, buf + sizeof(pkt_header));
|
|
fclose(fp);
|
|
if (data_len > (MRVDRV_SIZE_OF_PKT_BUFFER - sizeof(pkt_header))) {
|
|
printf("ERR: Config file is too big %d\n", data_len);
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
header->tx_pkt_type = pkt_type;
|
|
header->tx_control = control;
|
|
header->pkt_len = data_len;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)buf;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAPHOSTPKTINJECT, &ifr)) {
|
|
perror("");
|
|
printf("ERR:ioctl is not supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
|
|
if (buf)
|
|
free(buf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the bss_config command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_bss_config_usage(void)
|
|
{
|
|
printf("\nUsage : bss_config [CONFIG_FILE]\n");
|
|
printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
|
|
printf("CONFIG_FILE is file containing all the BSS settings.\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Read the BSS profile and populate structure
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @param bss Pointer to BSS configuration buffer
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
parse_bss_config(int argc, char *argv[], bss_config_t *bss)
|
|
{
|
|
FILE *config_file = NULL;
|
|
char *line = NULL;
|
|
int li = 0;
|
|
char *pos = NULL;
|
|
int arg_num = 0;
|
|
char *args[30];
|
|
int i;
|
|
int is_ap_config = 0;
|
|
int is_ap_mac_filter = 0;
|
|
int keyindex = -1;
|
|
int pwkcipher_wpa = -1;
|
|
int pwkcipher_wpa2 = -1;
|
|
int gwkcipher = -1;
|
|
int protocol = -1;
|
|
int tx_beacon_rate = -1;
|
|
int tx_data_rate = -1;
|
|
int mcbc_data_rate = -1;
|
|
int num_rates = 0;
|
|
int found = 0;
|
|
int filter_mac_count = -1;
|
|
int retval = UAP_SUCCESS;
|
|
int chan_mode = 0;
|
|
int band_flag = 0;
|
|
int chan_number = 0;
|
|
t_u16 max_sta_num_supported = 0;
|
|
fw_info fw;
|
|
HTCap_t htcap;
|
|
int enable_11n = -1;
|
|
t_u32 supported_mcs_set = 0;
|
|
int ac = 0;
|
|
int is_wmm_parameters = 0;
|
|
char oui_type[4] = { 0x00, 0x50, 0xf2, 0x02 };
|
|
struct eth_priv_vhtcfg vhtcfg = { 0 };
|
|
|
|
/* Check if file exists */
|
|
config_file = fopen(argv[0], "r");
|
|
if (config_file == NULL) {
|
|
printf("\nERR:Config file can not open.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
line = (char *)malloc(MAX_CONFIG_LINE);
|
|
if (!line) {
|
|
printf("ERR:Cannot allocate memory for line\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
memset(line, 0, MAX_CONFIG_LINE);
|
|
|
|
/* Parse file and process */
|
|
while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
|
|
li, line);
|
|
#endif
|
|
arg_num = parse_line(line, args);
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
|
|
arg_num);
|
|
for (i = 0; i < arg_num; i++) {
|
|
uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
|
|
args[i]);
|
|
}
|
|
#endif
|
|
/* Check for end of AP configurations */
|
|
if (is_ap_config == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
is_ap_config = 0;
|
|
if (tx_data_rate != -1) {
|
|
if ((!bss->rates[0]) && (tx_data_rate)
|
|
&&
|
|
(is_tx_rate_valid
|
|
((t_u8)tx_data_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (bss->rates[0] && tx_data_rate) {
|
|
for (i = 0; bss->rates[i] != 0;
|
|
i++) {
|
|
if ((bss->
|
|
rates[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
== tx_data_rate) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Set Tx data rate field */
|
|
bss->tx_data_rate = tx_data_rate;
|
|
}
|
|
if (tx_beacon_rate != -1) {
|
|
if ((!bss->rates[0]) && (tx_beacon_rate)
|
|
&&
|
|
(is_tx_rate_valid
|
|
((t_u8)tx_beacon_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Beacon Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (bss->rates[0] && tx_beacon_rate) {
|
|
for (i = 0; bss->rates[i] != 0;
|
|
i++) {
|
|
if ((bss->
|
|
rates[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
== tx_beacon_rate) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid Tx Beacon Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Set Tx beacon rate field */
|
|
bss->tx_beacon_rate = tx_beacon_rate;
|
|
}
|
|
if (mcbc_data_rate != -1) {
|
|
if ((!bss->rates[0]) && (mcbc_data_rate)
|
|
&&
|
|
(is_mcbc_rate_valid
|
|
((t_u8)mcbc_data_rate) !=
|
|
UAP_SUCCESS)) {
|
|
printf("ERR: Invalid Tx Data Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (bss->rates[0] && mcbc_data_rate) {
|
|
for (i = 0; bss->rates[i] != 0;
|
|
i++) {
|
|
if (bss->
|
|
rates[i] &
|
|
BASIC_RATE_SET_BIT)
|
|
{
|
|
if ((bss->
|
|
rates[i] &
|
|
~BASIC_RATE_SET_BIT)
|
|
==
|
|
mcbc_data_rate)
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERR: Invalid MCBC Data Rate \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Set MCBC data rate field */
|
|
bss->mcbc_data_rate = mcbc_data_rate;
|
|
}
|
|
if ((protocol == PROTOCOL_STATIC_WEP) &&
|
|
(enable_11n == 1)) {
|
|
printf("ERR:WEP cannot be used when AP operates in 802.11n mode.\n");
|
|
goto done;
|
|
}
|
|
if (0 == get_fw_info(&fw)) {
|
|
/*check whether support 802.11AC through BAND_AAC bit */
|
|
if (fw.fw_bands & BAND_AAC) {
|
|
retval = get_802_11ac_cfg
|
|
(&vhtcfg);
|
|
if (retval != UAP_SUCCESS)
|
|
goto done;
|
|
if ((enable_11n == 1) &&
|
|
(vhtcfg.vht_rx_mcs !=
|
|
0xffff)) {
|
|
printf("ERR: 11n must be enabled when AP operates in 11ac mode.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else
|
|
printf("No support 802 11AC.\n");
|
|
} else {
|
|
printf("ERR: get_fw_info fail\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if ((protocol == PROTOCOL_WPA2_MIXED) &&
|
|
((pwkcipher_wpa < 0) ||
|
|
(pwkcipher_wpa2 < 0))) {
|
|
printf("ERR:Both PwkCipherWPA and PwkCipherWPA2 should be defined for Mixed mode.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (protocol != -1) {
|
|
bss->protocol = protocol;
|
|
if (protocol &
|
|
(PROTOCOL_WPA | PROTOCOL_WPA2)) {
|
|
/* Set key management field */
|
|
bss->key_mgmt = KEY_MGMT_PSK;
|
|
bss->key_mgmt_operation = 0;
|
|
}
|
|
}
|
|
if (((pwkcipher_wpa >= 0) ||
|
|
(pwkcipher_wpa2 >= 0)) &&
|
|
(gwkcipher >= 0)) {
|
|
if ((protocol == PROTOCOL_WPA) ||
|
|
(protocol == PROTOCOL_WPA2_MIXED)) {
|
|
if (enable_11n != -1) {
|
|
if (is_cipher_valid_with_11n(pwkcipher_wpa, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else if
|
|
(is_cipher_valid_with_proto
|
|
(pwkcipher_wpa,
|
|
gwkcipher,
|
|
protocol) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA pairwise cipher combination!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
if ((protocol == PROTOCOL_WPA2) ||
|
|
(protocol == PROTOCOL_WPA2_MIXED)
|
|
|| (protocol == PROTOCOL_WPA3_SAE)
|
|
) {
|
|
if (enable_11n != -1) {
|
|
if (is_cipher_valid_with_11n(pwkcipher_wpa2, gwkcipher, protocol, enable_11n) != UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
} else if
|
|
(is_cipher_valid_with_proto
|
|
(pwkcipher_wpa2,
|
|
gwkcipher,
|
|
protocol) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Wrong group cipher and WPA2 pairwise cipher combination!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
/* Set pairwise and group cipher fields */
|
|
bss->wpa_cfg.pairwise_cipher_wpa =
|
|
pwkcipher_wpa;
|
|
bss->wpa_cfg.pairwise_cipher_wpa2 =
|
|
pwkcipher_wpa2;
|
|
bss->wpa_cfg.group_cipher = gwkcipher;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check for beginning of AP configurations */
|
|
if (strcmp(args[0], "ap_config") == 0) {
|
|
is_ap_config = 1;
|
|
continue;
|
|
}
|
|
|
|
/* Check for end of AP MAC address filter configurations */
|
|
if (is_ap_mac_filter == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
is_ap_mac_filter = 0;
|
|
if (bss->filter.mac_count != filter_mac_count) {
|
|
printf("ERR:Number of MAC address provided does not match 'Count'\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (bss->filter.filter_mode &&
|
|
(bss->filter.mac_count == 0)) {
|
|
printf("ERR:Filter list can not be empty for %s Filter mode\n", (bss->filter.filter_mode == 1) ? "'Allow'" : "'Block'");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check for beginning of AP MAC address filter configurations */
|
|
if (strcmp(args[0], "ap_mac_filter") == 0) {
|
|
is_ap_mac_filter = 1;
|
|
bss->filter.mac_count = 0;
|
|
filter_mac_count = 0;
|
|
continue;
|
|
}
|
|
if ((strcmp(args[0], "FilterMode") == 0) && is_ap_mac_filter) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
|
|
(atoi(args[1]) > 2)) {
|
|
printf("ERR:Illegal FilterMode paramter %d. Must be either '0', '1', or '2'.\n", atoi(args[1]));
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
bss->filter.filter_mode = atoi(args[1]);
|
|
continue;
|
|
}
|
|
if ((strcmp(args[0], "Count") == 0) && is_ap_mac_filter) {
|
|
bss->filter.mac_count = atoi(args[1]);
|
|
if ((ISDIGIT(args[1]) == 0) ||
|
|
(bss->filter.mac_count > MAX_MAC_ONESHOT_FILTER)) {
|
|
printf("ERR: Illegal Count parameter.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
if ((strncmp(args[0], "mac_", 4) == 0) && is_ap_mac_filter) {
|
|
if (filter_mac_count < MAX_MAC_ONESHOT_FILTER) {
|
|
if (mac2raw
|
|
(args[1],
|
|
bss->filter.mac_list[filter_mac_count]) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: Invalid MAC address %s \n",
|
|
args[1]);
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
filter_mac_count++;
|
|
} else {
|
|
printf("ERR: Filter table can not have more than %d MAC addresses\n", MAX_MAC_ONESHOT_FILTER);
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Check for end of Wmm Parameters configurations */
|
|
if (is_wmm_parameters == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
is_wmm_parameters = 0;
|
|
continue;
|
|
}
|
|
}
|
|
/* Check for beginning of Sticky Tim Sta MAC address Configurations */
|
|
if (strcmp(args[0], "Wmm_parameters") == 0) {
|
|
is_wmm_parameters = 1;
|
|
memset(&(bss->wmm_para), 0, sizeof(bss->wmm_para));
|
|
memcpy(bss->wmm_para.ouitype, oui_type,
|
|
sizeof(oui_type));
|
|
bss->wmm_para.ouisubtype = 1;
|
|
bss->wmm_para.version = 1;
|
|
continue;
|
|
}
|
|
if ((strcmp(args[0], "Qos_info") == 0) && is_wmm_parameters) {
|
|
bss->wmm_para.qos_info = A2HEXDECIMAL(args[1]);
|
|
printf("wmm_para.qos_info = %2x\n",
|
|
bss->wmm_para.qos_info);
|
|
if ((bss->wmm_para.qos_info != ENABLE_WMM_PS) &&
|
|
(bss->wmm_para.qos_info != DISABLE_WMM_PS)) {
|
|
printf("ERR:qos_info must be either 0x80 or 0x00.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
if ((strcmp(args[0], "AC_BE") == 0) && is_wmm_parameters) {
|
|
ac = 0;
|
|
}
|
|
if ((strcmp(args[0], "AC_BK") == 0) && is_wmm_parameters) {
|
|
ac = 1;
|
|
}
|
|
if ((strcmp(args[0], "AC_VI") == 0) && is_wmm_parameters) {
|
|
ac = 2;
|
|
}
|
|
if ((strcmp(args[0], "AC_VO") == 0) && is_wmm_parameters) {
|
|
ac = 3;
|
|
}
|
|
if ((strcmp(args[0], "Aifsn") == 0) && is_wmm_parameters) {
|
|
bss->wmm_para.ac_params[ac].aci_aifsn.aifsn =
|
|
(t_u8)A2HEXDECIMAL(args[1]);
|
|
printf("wmm_para.ac_params[%d].aci_aifsn.aifsn = %x\n",
|
|
ac, bss->wmm_para.ac_params[ac].aci_aifsn.aifsn);
|
|
bss->wmm_para.ac_params[ac].aci_aifsn.aci = (t_u8)ac;
|
|
printf("wmm_para.ac_params[%d].aci_aifsn.aci = %x\n",
|
|
ac, bss->wmm_para.ac_params[ac].aci_aifsn.aci);
|
|
}
|
|
if ((strcmp(args[0], "Ecw_max") == 0) && is_wmm_parameters) {
|
|
bss->wmm_para.ac_params[ac].ecw.ecw_max =
|
|
(t_u8)A2HEXDECIMAL(args[1]);
|
|
printf("wmm_para.ac_params[%d].ecw.ecw_max = %x\n", ac,
|
|
bss->wmm_para.ac_params[ac].ecw.ecw_max);
|
|
}
|
|
if ((strcmp(args[0], "Ecw_min") == 0) && is_wmm_parameters) {
|
|
bss->wmm_para.ac_params[ac].ecw.ecw_min =
|
|
(t_u8)A2HEXDECIMAL(args[1]);
|
|
printf("wmm_para.ac_params[%d].ecw.ecw_min = %x\n", ac,
|
|
bss->wmm_para.ac_params[ac].ecw.ecw_min);
|
|
}
|
|
if ((strcmp(args[0], "Tx_op") == 0) && is_wmm_parameters) {
|
|
bss->wmm_para.ac_params[ac].tx_op_limit =
|
|
(t_u8)A2HEXDECIMAL(args[1]);
|
|
printf("wmm_para.ac_params[%d].tx_op_limit = %x\n", ac,
|
|
bss->wmm_para.ac_params[ac].tx_op_limit);
|
|
}
|
|
|
|
if (strcmp(args[0], "SSID") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:SSID field is blank!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (args[1][0] == '"') {
|
|
args[1]++;
|
|
}
|
|
if (args[1][strlen(args[1]) - 1] == '"') {
|
|
args[1][strlen(args[1]) - 1] = '\0';
|
|
}
|
|
if ((strlen(args[1]) > MAX_SSID_LENGTH) ||
|
|
(strlen(args[1]) == 0)) {
|
|
printf("ERR:SSID length out of range (%d to %d).\n", MIN_SSID_LENGTH, MAX_SSID_LENGTH);
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set SSID field */
|
|
bss->ssid.ssid_len = strlen(args[1]);
|
|
memcpy(bss->ssid.ssid, args[1],
|
|
bss->ssid.ssid_len);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "BeaconPeriod") == 0) {
|
|
if (is_input_valid(BEACONPERIOD, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set beacon period field */
|
|
bss->beacon_period = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "ChanList") == 0) {
|
|
if (is_input_valid(SCANCHANNELS, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Set channel list field */
|
|
if ((arg_num - 1) < MAX_CHANNELS) {
|
|
bss->num_of_chan = arg_num - 1;
|
|
} else {
|
|
bss->num_of_chan = MAX_CHANNELS;
|
|
}
|
|
for (i = 0; (unsigned int)i < bss->num_of_chan; i++) {
|
|
sscanf(args[i + 1], "%d.%d", &chan_number,
|
|
&band_flag);
|
|
bss->chan_list[i].chan_number = chan_number;
|
|
bss->chan_list[i].bandcfg.chanBand = BAND_2GHZ;
|
|
if (((band_flag != -1) && (band_flag)) ||
|
|
(chan_number > MAX_CHANNELS_BG)) {
|
|
bss->chan_list[i].bandcfg.chanBand =
|
|
BAND_5GHZ;
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(args[0], "Channel") == 0) {
|
|
if (is_input_valid(CHANNEL, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set channel field */
|
|
bss->channel = (t_u8)atoi(args[1]);
|
|
if ((arg_num - 1) == 2) {
|
|
chan_mode = atoi(args[2]);
|
|
memset(&(bss->bandcfg), 0,
|
|
sizeof(bss->bandcfg));
|
|
if (chan_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");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
bss->bandcfg.scanMode = SCAN_MODE_ACS;
|
|
}
|
|
if (chan_mode & BITMAP_CHANNEL_ABOVE)
|
|
bss->bandcfg.chan2Offset =
|
|
SEC_CHAN_ABOVE;
|
|
if (chan_mode & BITMAP_CHANNEL_BELOW)
|
|
bss->bandcfg.chan2Offset =
|
|
SEC_CHAN_BELOW;
|
|
} else
|
|
memset(&(bss->bandcfg), 0,
|
|
sizeof(bss->bandcfg));
|
|
if (bss->channel > MAX_CHANNELS_BG)
|
|
bss->bandcfg.chanBand = BAND_5GHZ;
|
|
}
|
|
if (strcmp(args[0], "Band") == 0) {
|
|
if (is_input_valid(BAND, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Clear previously set band */
|
|
bss->bandcfg.chanBand = BAND_2GHZ;
|
|
if (atoi(args[1]) == 1)
|
|
bss->bandcfg.chanBand = BAND_5GHZ;
|
|
}
|
|
if (strcmp(args[0], "AP_MAC") == 0) {
|
|
int ret;
|
|
if ((ret =
|
|
mac2raw(args[1], bss->mac_addr)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address \n",
|
|
ret ==
|
|
UAP_FAILURE ? "Invalid MAC" : ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" :
|
|
"Multicast");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "Rate") == 0) {
|
|
if (is_input_valid(RATE, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR: Invalid Rate input\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set rates field */
|
|
if ((arg_num - 1) < MAX_DATA_RATES) {
|
|
num_rates = arg_num - 1;
|
|
} else {
|
|
num_rates = MAX_DATA_RATES;
|
|
}
|
|
for (i = 0; i < num_rates; i++) {
|
|
bss->rates[i] = (t_u8)A2HEXDECIMAL(args[i + 1]);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "TxPowerLevel") == 0) {
|
|
if (is_input_valid(TXPOWER, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
printf("ERR:Invalid TxPowerLevel \n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Tx power level field */
|
|
bss->tx_power_level = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "BroadcastSSID") == 0) {
|
|
if (is_input_valid(BROADCASTSSID, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set broadcast SSID control field */
|
|
bss->bcast_ssid_ctl = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "RTSThreshold") == 0) {
|
|
if (is_input_valid(RTSTHRESH, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set RTS threshold field */
|
|
bss->rts_threshold = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "FragThreshold") == 0) {
|
|
if (is_input_valid(FRAGTHRESH, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Frag threshold field */
|
|
bss->frag_threshold = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "DTIMPeriod") == 0) {
|
|
if (is_input_valid(DTIMPERIOD, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set DTIM period field */
|
|
bss->dtim_period = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "RSNReplayProtection") == 0) {
|
|
if (is_input_valid(RSNREPLAYPROT, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set RSN replay protection field */
|
|
bss->wpa_cfg.rsn_protection = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PairwiseUpdateTimeout") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Pairwise Update Timeout field */
|
|
bss->pairwise_update_timeout = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PairwiseHandshakeRetries") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Pairwise Hanshake Retries */
|
|
bss->pwk_retries = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "GroupwiseUpdateTimeout") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Groupwise Update Timeout field */
|
|
bss->groupwise_update_timeout = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "GroupwiseHandshakeRetries") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0)) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set Groupwise Hanshake Retries */
|
|
bss->gwk_retries = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "TxBeaconRate") == 0) {
|
|
if (is_input_valid(TXBEACONRATE, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
tx_beacon_rate = (t_u16)A2HEXDECIMAL(args[1]);
|
|
}
|
|
if (strcmp(args[0], "MCBCdataRate") == 0) {
|
|
if (is_input_valid(MCBCDATARATE, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
mcbc_data_rate = (t_u16)A2HEXDECIMAL(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PktFwdCtl") == 0) {
|
|
if (is_input_valid(PKTFWD, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set packet forward control field */
|
|
bss->pkt_forward_ctl = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "StaAgeoutTimer") == 0) {
|
|
if (is_input_valid
|
|
(STAAGEOUTTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set STA ageout timer field */
|
|
bss->sta_ageout_timer = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PSStaAgeoutTimer") == 0) {
|
|
if (is_input_valid
|
|
(PSSTAAGEOUTTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set PS STA ageout timer field */
|
|
bss->ps_sta_ageout_timer = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "AuthMode") == 0) {
|
|
if (is_input_valid(AUTHMODE, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set auth mode field */
|
|
bss->auth_mode = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "KeyIndex") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("KeyIndex is blank!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
keyindex = atoi(args[1]);
|
|
if ((keyindex < 0) || (keyindex > 3)) {
|
|
printf("ERR:Illegal KeyIndex parameter. Must be either '0', '1', '2', or '3'.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
switch (keyindex) {
|
|
case 0:
|
|
bss->wep_cfg.key0.is_default = 1;
|
|
break;
|
|
case 1:
|
|
bss->wep_cfg.key1.is_default = 1;
|
|
break;
|
|
case 2:
|
|
bss->wep_cfg.key2.is_default = 1;
|
|
break;
|
|
case 3:
|
|
bss->wep_cfg.key3.is_default = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (strncmp(args[0], "Key_", 4) == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:%s is blank!\n", args[0]);
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
int key_len = 0;
|
|
if (args[1][0] == '"') {
|
|
if ((strlen(args[1]) != 2) &&
|
|
(strlen(args[1]) != 7) &&
|
|
(strlen(args[1]) != 15)) {
|
|
printf("ERR:Wrong key length!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
key_len = strlen(args[1]) - 2;
|
|
} else {
|
|
if ((strlen(args[1]) != 0) &&
|
|
(strlen(args[1]) != 10) &&
|
|
(strlen(args[1]) != 26)) {
|
|
printf("ERR:Wrong key length!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (UAP_FAILURE == ishexstring(args[1])) {
|
|
printf("ERR:Only hex digits are allowed when key length is 10 or 26\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
key_len = strlen(args[1]) / 2;
|
|
}
|
|
/* Set WEP key fields */
|
|
if (strcmp(args[0], "Key_0") == 0) {
|
|
bss->wep_cfg.key0.key_index = 0;
|
|
bss->wep_cfg.key0.length = key_len;
|
|
if (args[1][0] == '"') {
|
|
memcpy(bss->wep_cfg.key0.key,
|
|
&args[1][1],
|
|
strlen(args[1]) - 2);
|
|
} else {
|
|
string2raw(args[1],
|
|
bss->wep_cfg.key0.
|
|
key);
|
|
}
|
|
} else if (strcmp(args[0], "Key_1") == 0) {
|
|
bss->wep_cfg.key1.key_index = 1;
|
|
bss->wep_cfg.key1.length = key_len;
|
|
if (args[1][0] == '"') {
|
|
memcpy(bss->wep_cfg.key1.key,
|
|
&args[1][1],
|
|
strlen(args[1]) - 2);
|
|
} else {
|
|
string2raw(args[1],
|
|
bss->wep_cfg.key1.
|
|
key);
|
|
}
|
|
} else if (strcmp(args[0], "Key_2") == 0) {
|
|
bss->wep_cfg.key2.key_index = 2;
|
|
bss->wep_cfg.key2.length = key_len;
|
|
if (args[1][0] == '"') {
|
|
memcpy(bss->wep_cfg.key2.key,
|
|
&args[1][1],
|
|
strlen(args[1]) - 2);
|
|
} else {
|
|
string2raw(args[1],
|
|
bss->wep_cfg.key2.
|
|
key);
|
|
}
|
|
} else if (strcmp(args[0], "Key_3") == 0) {
|
|
bss->wep_cfg.key3.key_index = 3;
|
|
bss->wep_cfg.key3.length = key_len;
|
|
if (args[1][0] == '"') {
|
|
memcpy(bss->wep_cfg.key3.key,
|
|
&args[1][1],
|
|
strlen(args[1]) - 2);
|
|
} else {
|
|
string2raw(args[1],
|
|
bss->wep_cfg.key3.
|
|
key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(args[0], "PSK") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PSK is blank!\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
} else {
|
|
if (args[1][0] == '"') {
|
|
args[1]++;
|
|
}
|
|
if (args[1][strlen(args[1]) - 1] == '"') {
|
|
args[1][strlen(args[1]) - 1] = '\0';
|
|
}
|
|
if (strlen(args[1]) > MAX_WPA_PASSPHRASE_LENGTH) {
|
|
printf("ERR:PSK too long.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (strlen(args[1]) < MIN_WPA_PASSPHRASE_LENGTH) {
|
|
printf("ERR:PSK too short.\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (strlen(args[1]) ==
|
|
MAX_WPA_PASSPHRASE_LENGTH) {
|
|
if (UAP_FAILURE == ishexstring(args[1])) {
|
|
printf("ERR:Only hex digits are allowed when passphrase's length is 64\n");
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
/* Set WPA passphrase field */
|
|
bss->wpa_cfg.length = strlen(args[1]);
|
|
memcpy(bss->wpa_cfg.passphrase, args[1],
|
|
bss->wpa_cfg.length);
|
|
}
|
|
}
|
|
if (strcmp(args[0], "Protocol") == 0) {
|
|
if (is_input_valid(PROTOCOL, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set protocol field */
|
|
protocol = (t_u16)atoi(args[1]);
|
|
}
|
|
if ((strcmp(args[0], "PairwiseCipher") == 0) ||
|
|
(strcmp(args[0], "GroupCipher") == 0)) {
|
|
printf("ERR:PairwiseCipher and GroupCipher are not supported.\n" " Please configure pairwise cipher using parameters PwkCipherWPA or PwkCipherWPA2\n" " and group cipher using GwkCipher in the config file.\n");
|
|
goto done;
|
|
}
|
|
|
|
if ((protocol == PROTOCOL_NO_SECURITY) ||
|
|
(protocol == PROTOCOL_STATIC_WEP)) {
|
|
if ((strcmp(args[0], "PwkCipherWPA") == 0) ||
|
|
(strcmp(args[0], "PwkCipherWPA2") == 0)
|
|
|| (strcmp(args[0], "GwkCipher") == 0)) {
|
|
printf("ERR:Pairwise cipher and group cipher should not be defined for Open and WEP mode.\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (strcmp(args[0], "PwkCipherWPA") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PwkCipherWPA is blank!\n");
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) & ~CIPHER_BITMAP) {
|
|
printf("ERR:Illegal PwkCipherWPA parameter. Must be either bit '2' or '3'.\n");
|
|
goto done;
|
|
}
|
|
pwkcipher_wpa = atoi(args[1]);
|
|
if (enable_11n &&
|
|
protocol != PROTOCOL_WPA2_MIXED) {
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS ==
|
|
get_sys_cfg_11n(&htcap)) {
|
|
if (htcap.supported_mcs_set[0]
|
|
&& (atoi(args[1]) ==
|
|
CIPHER_TKIP)) {
|
|
printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(args[0], "PwkCipherWPA2") == 0) {
|
|
if (arg_num == 1) {
|
|
printf("ERR:PwkCipherWPA2 is blank!\n");
|
|
goto done;
|
|
} else {
|
|
if (ISDIGIT(args[1]) == 0) {
|
|
printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) & ~CIPHER_BITMAP) {
|
|
printf("ERR:Illegal PwkCipherWPA2 parameter. Must be either bit '2' or '3'.\n");
|
|
goto done;
|
|
}
|
|
pwkcipher_wpa2 = atoi(args[1]);
|
|
if (enable_11n &&
|
|
protocol != PROTOCOL_WPA2_MIXED) {
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS ==
|
|
get_sys_cfg_11n(&htcap)) {
|
|
if (htcap.supported_mcs_set[0]
|
|
&& (atoi(args[1]) ==
|
|
CIPHER_TKIP)) {
|
|
printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(args[0], "GwkCipher") == 0) {
|
|
if (is_input_valid(GWK_CIPHER, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
goto done;
|
|
}
|
|
gwkcipher = atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "GroupRekeyTime") == 0) {
|
|
if (is_input_valid
|
|
(GROUPREKEYTIMER, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Set group rekey time field */
|
|
bss->wpa_cfg.gk_rekey_time = (t_u32)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "MaxStaNum") == 0) {
|
|
if (is_input_valid(MAXSTANUM, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (get_max_sta_num_supported(&max_sta_num_supported) ==
|
|
UAP_FAILURE) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (atoi(args[1]) > max_sta_num_supported) {
|
|
printf("ERR: MAX_STA_NUM must be less than %d\n", max_sta_num_supported);
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Set max STA number field */
|
|
bss->max_sta_count = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "Retrylimit") == 0) {
|
|
if (is_input_valid(RETRYLIMIT, arg_num - 1, args + 1) !=
|
|
UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Set retry limit field */
|
|
bss->retry_limit = (t_u16)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "PreambleType") == 0) {
|
|
if (is_input_valid(PREAMBLETYPE, arg_num - 1, args + 1)
|
|
!= UAP_SUCCESS) {
|
|
retval = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* Set preamble type field */
|
|
bss->preamble_type = (t_u8)atoi(args[1]);
|
|
}
|
|
if (strcmp(args[0], "Enable11n") == 0) {
|
|
if ((ISDIGIT(args[1]) != UAP_SUCCESS) ||
|
|
(atoi(args[1]) < 0) || (atoi(args[1]) > 1)) {
|
|
printf("ERR: Invalid Enable11n value\n");
|
|
goto done;
|
|
}
|
|
enable_11n = atoi(args[1]);
|
|
|
|
memset(&htcap, 0, sizeof(htcap));
|
|
if (UAP_SUCCESS != get_sys_cfg_11n(&htcap)) {
|
|
printf("ERR: Reading current 11n configuration.\n");
|
|
goto done;
|
|
}
|
|
bss->ht_cap_info = htcap.ht_cap_info;
|
|
bss->ampdu_param = htcap.ampdu_param;
|
|
memcpy(bss->supported_mcs_set, htcap.supported_mcs_set,
|
|
16);
|
|
bss->ht_ext_cap = htcap.ht_ext_cap;
|
|
bss->tx_bf_cap = htcap.tx_bf_cap;
|
|
bss->asel = htcap.asel;
|
|
if (enable_11n == 1) {
|
|
/* enable mcs rate */
|
|
bss->supported_mcs_set[0] = DEFAULT_MCS_SET_0;
|
|
bss->supported_mcs_set[4] = DEFAULT_MCS_SET_4;
|
|
if (0 == get_fw_info(&fw)) {
|
|
if ((fw.hw_dev_mcs_support & 0x0f) >= 2)
|
|
bss->supported_mcs_set[1] =
|
|
DEFAULT_MCS_SET_1;
|
|
}
|
|
} else {
|
|
/* disable mcs rate */
|
|
bss->supported_mcs_set[0] = 0;
|
|
bss->supported_mcs_set[4] = 0;
|
|
bss->supported_mcs_set[1] = 0;
|
|
}
|
|
}
|
|
if (strcmp(args[0], "HTCapInfo") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before HTCapInfo.\n");
|
|
goto done;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
|
|
((((t_u16)A2HEXDECIMAL(args[1])) &
|
|
(~HT_CAP_CONFIG_MASK)) != HT_CAP_CHECK_MASK)) {
|
|
printf("ERR: Invalid HTCapInfo value\n");
|
|
goto done;
|
|
}
|
|
bss->ht_cap_info =
|
|
DEFAULT_HT_CAP_VALUE & ~HT_CAP_CONFIG_MASK;
|
|
bss->ht_cap_info |=
|
|
(t_u16)A2HEXDECIMAL(args[1]) &
|
|
HT_CAP_CONFIG_MASK;
|
|
bss->ht_cap_info = uap_cpu_to_le16(bss->ht_cap_info);
|
|
}
|
|
if (strcmp(args[0], "AMPDU") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before AMPDU.\n");
|
|
goto done;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE) ||
|
|
((A2HEXDECIMAL(args[1])) > AMPDU_CONFIG_MASK)) {
|
|
printf("ERR: Invalid AMPDU value\n");
|
|
goto done;
|
|
}
|
|
/* Find HT tlv pointer in buffer and set AMPDU */
|
|
bss->ampdu_param =
|
|
(t_u8)A2HEXDECIMAL(args[1]) & AMPDU_CONFIG_MASK;
|
|
}
|
|
if (strcmp(args[0], "HT_MCS_MAP") == 0) {
|
|
if (enable_11n <= 0) {
|
|
printf("ERR: Enable11n parameter should be set before HT_MCS_MAP.\n");
|
|
goto done;
|
|
}
|
|
if ((IS_HEX_OR_DIGIT(args[1]) == UAP_FAILURE)) {
|
|
printf("ERR: Invalid HT_MCS_MAP value\n");
|
|
goto done;
|
|
}
|
|
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(args[1]) & MCS_SET_1_MASK)) {
|
|
printf("ERR: Invalid HT_MCS_MAP\n");
|
|
goto done;
|
|
}
|
|
}
|
|
supported_mcs_set = (t_u32)A2HEXDECIMAL(args[1]);
|
|
supported_mcs_set = uap_cpu_to_le32(supported_mcs_set);
|
|
memcpy(bss->supported_mcs_set, &supported_mcs_set,
|
|
sizeof(t_u32));
|
|
}
|
|
if (strcmp(args[0], "Enable2040Coex") == 0) {
|
|
if ((ISDIGIT(args[1]) == 0) || (atoi(args[1]) < 0) ||
|
|
(atoi(args[1]) > 1)) {
|
|
printf("ERR:Invalid Enable2040Coex value.\n");
|
|
goto done;
|
|
}
|
|
bss->enable_2040coex = (t_u8)atoi(args[1]);
|
|
}
|
|
}
|
|
done:
|
|
fclose(config_file);
|
|
if (line)
|
|
free(line);
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* @brief Show all the BSS configuration in the buffer
|
|
*
|
|
* @param buf Pointer to BSS configuration buffer
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_bss_config(bss_config_t *buf)
|
|
{
|
|
int i = 0;
|
|
int flag = 0;
|
|
|
|
if (!buf) {
|
|
printf("ERR:Empty BSS config!\n");
|
|
return;
|
|
}
|
|
|
|
/* Print AP MAC address */
|
|
printf("AP MAC address = ");
|
|
print_mac(buf->mac_addr);
|
|
printf("\n");
|
|
|
|
/* Print SSID */
|
|
if (buf->ssid.ssid_len) {
|
|
printf("SSID = %s\n", buf->ssid.ssid);
|
|
}
|
|
|
|
/* Print broadcast SSID control */
|
|
printf("SSID broadcast = %s\n",
|
|
(buf->bcast_ssid_ctl == 1) ? "enabled" : "disabled");
|
|
|
|
/* Print DTIM period */
|
|
printf("DTIM period = %d\n", buf->dtim_period);
|
|
|
|
/* Print beacon period */
|
|
printf("Beacon period = %d\n", buf->beacon_period);
|
|
|
|
/* Print rates */
|
|
printf("Basic Rates =");
|
|
for (i = 0; i < MAX_DATA_RATES; i++) {
|
|
if (!buf->rates[i])
|
|
break;
|
|
if (buf->rates[i] > (BASIC_RATE_SET_BIT - 1)) {
|
|
flag = flag ? : 1;
|
|
printf(" 0x%x", buf->rates[i]);
|
|
}
|
|
}
|
|
printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) ");
|
|
for (flag = 0, i = 0; i < MAX_DATA_RATES; i++) {
|
|
if (!buf->rates[i])
|
|
break;
|
|
if (buf->rates[i] < BASIC_RATE_SET_BIT) {
|
|
flag = flag ? : 1;
|
|
printf(" 0x%x", buf->rates[i]);
|
|
}
|
|
}
|
|
printf("%s\n", flag ? "" : " ( none ) ");
|
|
|
|
/* Print Tx data rate */
|
|
printf("Tx data rate = ");
|
|
if (buf->tx_data_rate == 0)
|
|
printf("auto\n");
|
|
else
|
|
printf("0x%x\n", buf->tx_data_rate);
|
|
|
|
/* Print MCBC data rate */
|
|
printf("MCBC data rate = ");
|
|
if (buf->mcbc_data_rate == 0)
|
|
printf("auto\n");
|
|
else
|
|
printf("0x%x\n", buf->mcbc_data_rate);
|
|
|
|
/* Print Tx power level */
|
|
printf("Tx power = %d dBm\n", buf->tx_power_level);
|
|
|
|
/* Print Tx antenna */
|
|
printf("Tx antenna = %s\n", (buf->tx_antenna) ? "B" : "A");
|
|
|
|
/* Print Rx antenna */
|
|
printf("Rx antenna = %s\n", (buf->rx_antenna) ? "B" : "A");
|
|
|
|
/* Print packet forward control */
|
|
printf("%s handles packet forwarding -\n",
|
|
((buf->pkt_forward_ctl & PKT_FWD_FW_BIT) ==
|
|
0) ? "Host" : "Firmware");
|
|
printf("\tIntra-BSS broadcast packets are %s\n",
|
|
((buf->pkt_forward_ctl & PKT_FWD_INTRA_BCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
printf("\tIntra-BSS unicast packets are %s\n",
|
|
((buf->pkt_forward_ctl & PKT_FWD_INTRA_UCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
printf("\tInter-BSS unicast packets are %s\n",
|
|
((buf->pkt_forward_ctl & PKT_FWD_INTER_UCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
|
|
/* Print maximum STA count */
|
|
printf("Max Station Number configured = %d\n", buf->max_sta_count);
|
|
|
|
/* Print mgmt frame FWD control */
|
|
printf("MGMT frame Fwd Control = 0x%x\n", buf->mgmt_ie_passthru_mask);
|
|
|
|
/* Print MAC filter */
|
|
if (buf->filter.filter_mode == 0) {
|
|
printf("Filter Mode = Filter table is disabled\n");
|
|
} else {
|
|
if (buf->filter.filter_mode == 1) {
|
|
printf("Filter Mode = Allow MAC addresses specified in the allowed list\n");
|
|
} else if (buf->filter.filter_mode == 2) {
|
|
printf("Filter Mode = Block MAC addresses specified in the banned list\n");
|
|
} else {
|
|
printf("Filter Mode = Unknown\n");
|
|
}
|
|
for (i = 0; i < buf->filter.mac_count; i++) {
|
|
printf("MAC_%d = ", i);
|
|
print_mac(buf->filter.mac_list[i]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
/* Print STA ageout timer */
|
|
printf("STA ageout timer = %d\n", buf->sta_ageout_timer);
|
|
|
|
/* Print PS STA ageout timer */
|
|
printf("PS STA ageout timer = %d\n", buf->ps_sta_ageout_timer);
|
|
|
|
/* Print RTS threshold */
|
|
printf("RTS threshold = %d\n", buf->rts_threshold);
|
|
|
|
/* Print Fragmentation threshold */
|
|
printf("Fragmentation threshold = %d\n", buf->frag_threshold);
|
|
|
|
/* Print retry limit */
|
|
printf("Retry Limit = %d\n", buf->retry_limit);
|
|
|
|
/* Print preamble type */
|
|
printf("Preamble type = %s\n", (buf->preamble_type == 0) ?
|
|
"auto" : ((buf->preamble_type == 1) ? "short" : "long"));
|
|
|
|
/* Print channel */
|
|
printf("Channel = %d\n", buf->channel);
|
|
printf("Band = %s\n",
|
|
(buf->bandcfg.chanBand == BAND_5GHZ) ? "5GHz" : "2.4GHz");
|
|
printf("Channel Select Mode = %s\n",
|
|
(buf->bandcfg.scanMode == SCAN_MODE_ACS) ? "ACS" : "Manual");
|
|
if (buf->bandcfg.chan2Offset == SEC_CHAN_NONE)
|
|
printf("no secondary channel\n");
|
|
else if (buf->bandcfg.chan2Offset == SEC_CHAN_ABOVE)
|
|
printf("secondary channel is above primary channel\n");
|
|
else if (buf->bandcfg.chan2Offset == SEC_CHAN_BELOW)
|
|
printf("secondary channel is below primary channel\n");
|
|
|
|
/* Print channel list */
|
|
printf("Channels List = ");
|
|
for (i = 0; (unsigned int)i < buf->num_of_chan; i++) {
|
|
printf("\n%d\t%sGHz", buf->chan_list[i].chan_number,
|
|
(buf->chan_list[i].bandcfg.chanBand ==
|
|
BAND_5GHZ) ? "5" : "2.4");
|
|
}
|
|
printf("\n");
|
|
|
|
/* Print auth mode */
|
|
switch (buf->auth_mode) {
|
|
case 0:
|
|
printf("AUTHMODE = Open authentication\n");
|
|
break;
|
|
case 1:
|
|
printf("AUTHMODE = Shared key authentication\n");
|
|
break;
|
|
case 3:
|
|
printf("AUTHMODE = WPA3 SAE\n");
|
|
break;
|
|
case 255:
|
|
printf("AUTHMODE = Auto (open and shared key)\n");
|
|
break;
|
|
default:
|
|
printf("ERR: Invalid authmode=%d\n", buf->auth_mode);
|
|
break;
|
|
}
|
|
|
|
/* Print protocol */
|
|
switch (buf->protocol) {
|
|
case 0:
|
|
case PROTOCOL_NO_SECURITY:
|
|
printf("PROTOCOL = No security\n");
|
|
break;
|
|
case PROTOCOL_STATIC_WEP:
|
|
printf("PROTOCOL = Static WEP\n");
|
|
break;
|
|
case PROTOCOL_WPA:
|
|
printf("PROTOCOL = WPA \n");
|
|
break;
|
|
case PROTOCOL_WPA2:
|
|
printf("PROTOCOL = WPA2 \n");
|
|
break;
|
|
case PROTOCOL_WPA | PROTOCOL_WPA2:
|
|
printf("PROTOCOL = WPA/WPA2 \n");
|
|
break;
|
|
case PROTOCOL_WPA3_SAE:
|
|
printf("PROTOCOL = WPA3 SAE \n");
|
|
break;
|
|
default:
|
|
printf("Unknown PROTOCOL: 0x%x \n", buf->protocol);
|
|
break;
|
|
}
|
|
|
|
/* Print key management */
|
|
if (buf->key_mgmt == KEY_MGMT_PSK)
|
|
printf("KeyMgmt = PSK\n");
|
|
else
|
|
printf("KeyMgmt = NONE\n");
|
|
|
|
/* Print WEP configurations */
|
|
if (buf->wep_cfg.key0.length) {
|
|
printf("WEP KEY_0 = ");
|
|
for (i = 0; i < buf->wep_cfg.key0.length; i++) {
|
|
printf("%02x ", buf->wep_cfg.key0.key[i]);
|
|
}
|
|
(buf->wep_cfg.key0.
|
|
is_default) ? (printf("<Default>\n")) : (printf("\n"));
|
|
} else {
|
|
printf("WEP KEY_0 = NONE\n");
|
|
}
|
|
if (buf->wep_cfg.key1.length) {
|
|
printf("WEP KEY_1 = ");
|
|
for (i = 0; i < buf->wep_cfg.key1.length; i++) {
|
|
printf("%02x ", buf->wep_cfg.key1.key[i]);
|
|
}
|
|
(buf->wep_cfg.key1.
|
|
is_default) ? (printf("<Default>\n")) : (printf("\n"));
|
|
} else {
|
|
printf("WEP KEY_1 = NONE\n");
|
|
}
|
|
if (buf->wep_cfg.key2.length) {
|
|
printf("WEP KEY_2 = ");
|
|
for (i = 0; i < buf->wep_cfg.key2.length; i++) {
|
|
printf("%02x ", buf->wep_cfg.key2.key[i]);
|
|
}
|
|
(buf->wep_cfg.key2.
|
|
is_default) ? (printf("<Default>\n")) : (printf("\n"));
|
|
} else {
|
|
printf("WEP KEY_2 = NONE\n");
|
|
}
|
|
if (buf->wep_cfg.key3.length) {
|
|
printf("WEP KEY_3 = ");
|
|
for (i = 0; i < buf->wep_cfg.key3.length; i++) {
|
|
printf("%02x ", buf->wep_cfg.key3.key[i]);
|
|
}
|
|
(buf->wep_cfg.key3.
|
|
is_default) ? (printf("<Default>\n")) : (printf("\n"));
|
|
} else {
|
|
printf("WEP KEY_3 = NONE\n");
|
|
}
|
|
|
|
/* Print WPA configurations */
|
|
if (buf->protocol & PROTOCOL_WPA) {
|
|
switch (buf->wpa_cfg.pairwise_cipher_wpa) {
|
|
case CIPHER_TKIP:
|
|
printf("PwkCipherWPA = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("PwkCipherWPA = AES CCMP\n");
|
|
break;
|
|
case CIPHER_TKIP | CIPHER_AES_CCMP:
|
|
printf("PwkCipherWPA = TKIP + AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("PwkCipherWPA = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown PwkCipherWPA 0x%x\n",
|
|
buf->wpa_cfg.pairwise_cipher_wpa);
|
|
break;
|
|
}
|
|
}
|
|
if (buf->protocol & (PROTOCOL_WPA2 | PROTOCOL_WPA3_SAE)) {
|
|
switch (buf->wpa_cfg.pairwise_cipher_wpa2) {
|
|
case CIPHER_TKIP:
|
|
printf("PwkCipherWPA2 = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("PwkCipherWPA2 = AES CCMP\n");
|
|
break;
|
|
case CIPHER_TKIP | CIPHER_AES_CCMP:
|
|
printf("PwkCipherWPA2 = TKIP + AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("PwkCipherWPA2 = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown PwkCipherWPA2 0x%x\n",
|
|
buf->wpa_cfg.pairwise_cipher_wpa2);
|
|
break;
|
|
}
|
|
}
|
|
switch (buf->wpa_cfg.group_cipher) {
|
|
case CIPHER_TKIP:
|
|
printf("GroupCipher = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("GroupCipher = AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("GroupCipher = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown Group cipher 0x%x\n",
|
|
buf->wpa_cfg.group_cipher);
|
|
break;
|
|
}
|
|
printf("RSN replay protection = %s\n",
|
|
(buf->wpa_cfg.rsn_protection) ? "enabled" : "disabled");
|
|
printf("Pairwise Handshake timeout = %d\n",
|
|
buf->pairwise_update_timeout);
|
|
printf("Pairwise Handshake Retries = %d\n", buf->pwk_retries);
|
|
printf("Groupwise Handshake timeout = %d\n",
|
|
buf->groupwise_update_timeout);
|
|
printf("Groupwise Handshake Retries = %d\n", buf->gwk_retries);
|
|
if (buf->wpa_cfg.length > 0) {
|
|
printf("WPA passphrase = ");
|
|
for (i = 0; (unsigned int)i < buf->wpa_cfg.length; i++)
|
|
printf("%c", buf->wpa_cfg.passphrase[i]);
|
|
printf("\n");
|
|
} else {
|
|
printf("WPA passphrase = None\n");
|
|
}
|
|
if (buf->wpa_cfg.gk_rekey_time == 0)
|
|
printf("Group re-key time = disabled\n");
|
|
else
|
|
printf("Group re-key time = %d second\n",
|
|
buf->wpa_cfg.gk_rekey_time);
|
|
printf("20/40 coex = %s\n",
|
|
(buf->enable_2040coex) ? "enabled" : "disabled");
|
|
printf("wmm parameters:\n");
|
|
printf("\tqos_info = 0x%x\n", buf->wmm_para.qos_info);
|
|
printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
buf->wmm_para.ac_params[AC_BE].aci_aifsn.aifsn,
|
|
buf->wmm_para.ac_params[AC_BE].ecw.ecw_max,
|
|
buf->wmm_para.ac_params[AC_BE].ecw.ecw_min,
|
|
buf->wmm_para.ac_params[AC_BE].tx_op_limit);
|
|
printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
buf->wmm_para.ac_params[AC_BK].aci_aifsn.aifsn,
|
|
buf->wmm_para.ac_params[AC_BK].ecw.ecw_max,
|
|
buf->wmm_para.ac_params[AC_BK].ecw.ecw_min,
|
|
buf->wmm_para.ac_params[AC_BK].tx_op_limit);
|
|
printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
buf->wmm_para.ac_params[AC_VI].aci_aifsn.aifsn,
|
|
buf->wmm_para.ac_params[AC_VI].ecw.ecw_max,
|
|
buf->wmm_para.ac_params[AC_VI].ecw.ecw_min,
|
|
buf->wmm_para.ac_params[AC_VI].tx_op_limit);
|
|
printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
buf->wmm_para.ac_params[AC_VO].aci_aifsn.aifsn,
|
|
buf->wmm_para.ac_params[AC_VO].ecw.ecw_max,
|
|
buf->wmm_para.ac_params[AC_VO].ecw.ecw_min,
|
|
buf->wmm_para.ac_params[AC_VO].tx_op_limit);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Send command to Read the BSS profile
|
|
*
|
|
* @param buf Pointer to bss command buffer for get
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
static int
|
|
get_bss_config(t_u8 *buf)
|
|
{
|
|
apcmdbuf_bss_configure *cmd_buf = NULL;
|
|
t_s32 sockfd;
|
|
struct ifreq ifr;
|
|
|
|
cmd_buf = (apcmdbuf_bss_configure *)buf;
|
|
cmd_buf->action = ACTION_GET;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
#if DEBUG
|
|
/* Dump request buffer */
|
|
hexdump("Get Request buffer", (void *)buf,
|
|
sizeof(apcmdbuf_bss_configure)
|
|
+ sizeof(bss_config_t), ' ');
|
|
#endif
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
|
|
if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) {
|
|
printf("ERR:UAP_BSS_CONFIG is not supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
#if DEBUG
|
|
/* Dump request buffer */
|
|
hexdump("Get Response buffer", (void *)buf,
|
|
sizeof(apcmdbuf_bss_configure)
|
|
+ sizeof(bss_config_t), ' ');
|
|
#endif
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a bss_config request and sends to the driver
|
|
*
|
|
* Usage: "Usage : bss_config [CONFIG_FILE]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_bss_config(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_bss_configure *cmd_buf = NULL;
|
|
bss_config_t *bss = NULL;
|
|
t_u8 *buf = NULL;
|
|
t_u16 cmd_len;
|
|
t_u16 buf_len;
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
t_s32 sockfd;
|
|
struct ifreq ifr;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_bss_config_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_bss_config_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Query BSS settings */
|
|
|
|
/* Alloc buf for command */
|
|
buf_len = sizeof(apcmdbuf_bss_configure) + sizeof(bss_config_t);
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset((char *)buf, 0, buf_len);
|
|
|
|
/* Locate headers */
|
|
cmd_len = sizeof(apcmdbuf_bss_configure);
|
|
cmd_buf = (apcmdbuf_bss_configure *)buf;
|
|
bss = (bss_config_t *)(buf + cmd_len);
|
|
|
|
/* Get all parametes first */
|
|
if (get_bss_config(buf) == UAP_FAILURE) {
|
|
printf("ERR:Reading current parameters\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc == 1) {
|
|
/* Parse config file and populate structure */
|
|
ret = parse_bss_config(argc, argv, bss);
|
|
if (ret == UAP_FAILURE) {
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
cmd_len += sizeof(bss_config_t);
|
|
cmd_buf->action = ACTION_SET;
|
|
|
|
/* Send the command */
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd_buf;
|
|
#if DEBUG
|
|
/* Dump request buffer */
|
|
hexdump("Request buffer", (void *)buf, buf_len, ' ');
|
|
#endif
|
|
if (ioctl(sockfd, UAP_BSS_CONFIG, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_BSS_CONFIG is not supported by %s\n",
|
|
dev_name);
|
|
close(sockfd);
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
#if DEBUG
|
|
/* Dump respond buffer */
|
|
hexdump("Respond buffer", (void *)buf, buf_len, ' ');
|
|
#endif
|
|
close(sockfd);
|
|
} else {
|
|
/* Print response */
|
|
printf("BSS settings:\n");
|
|
print_bss_config(bss);
|
|
}
|
|
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Read the profile and sends to the driver
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_coex_config_profile(int argc, char *argv[])
|
|
{
|
|
FILE *config_file = NULL;
|
|
char *line = NULL;
|
|
int i, index, li = 0;
|
|
int ret = UAP_SUCCESS;
|
|
char *pos = NULL;
|
|
int arg_num = 0;
|
|
char *args[30];
|
|
int is_coex_config = 0;
|
|
int is_coex_common_config = 0;
|
|
int is_coex_sco_config = 0;
|
|
int is_coex_acl_config = 0;
|
|
t_u8 *buf = NULL;
|
|
apcmdbuf_coex_config *cmd_buf = NULL;
|
|
tlvbuf_coex_common_cfg *coex_common_tlv;
|
|
tlvbuf_coex_sco_cfg *coex_sco_tlv;
|
|
tlvbuf_coex_acl_cfg *coex_acl_tlv;
|
|
t_u16 acl_enabled = 0;
|
|
t_u32 conf_bitmap = 0;
|
|
t_u32 ap_coex_enable = 0;
|
|
t_u16 cmd_len = 0, tlv_len = 0;
|
|
t_u16 sco_prot_qtime[4] = { 0, 0, 0, 0 }, sco_prot_rate =
|
|
0, sco_acl_freq = 0;
|
|
t_u16 acl_bt_time = 0, acl_wlan_time = 0, acl_prot_rate = 0;
|
|
|
|
/* Check if file exists */
|
|
config_file = fopen(argv[0], "r");
|
|
if (config_file == NULL) {
|
|
printf("\nERR:Config file can not open.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
line = (char *)malloc(MAX_CONFIG_LINE);
|
|
if (!line) {
|
|
printf("ERR:Cannot allocate memory for line\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
bzero(line, MAX_CONFIG_LINE);
|
|
|
|
/* fixed command length */
|
|
cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg)
|
|
+ sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg);
|
|
/* alloc buf for command */
|
|
buf = (t_u8 *)malloc(cmd_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
bzero((char *)buf, cmd_len);
|
|
|
|
cmd_buf = (apcmdbuf_coex_config *)buf;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->cmd_code = HostCmd_ROBUST_COEX;
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_SET);
|
|
|
|
/* Parse file and process */
|
|
while (config_get_line(line, MAX_CONFIG_LINE, config_file, &li, &pos)) {
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Received config line (%d) = %s\n",
|
|
li, line);
|
|
#endif
|
|
arg_num = parse_line(line, args);
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG:Number of arguments = %d\n",
|
|
arg_num);
|
|
for (i = 0; i < arg_num; i++) {
|
|
uap_printf(MSG_DEBUG, "\tDBG:Argument %d. %s\n", i + 1,
|
|
args[i]);
|
|
}
|
|
#endif
|
|
/* Check for end of Coex configurations */
|
|
if (is_coex_acl_config == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
coex_acl_tlv =
|
|
(tlvbuf_coex_acl_cfg *)(cmd_buf->
|
|
tlv_buffer +
|
|
tlv_len);
|
|
coex_acl_tlv->tag = MRVL_BT_COEX_ACL_CFG_TLV_ID;
|
|
coex_acl_tlv->length =
|
|
sizeof(tlvbuf_coex_acl_cfg) -
|
|
sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_acl_tlv);
|
|
coex_acl_tlv->enabled =
|
|
uap_cpu_to_le16(acl_enabled);
|
|
coex_acl_tlv->bt_time =
|
|
uap_cpu_to_le16(acl_bt_time);
|
|
coex_acl_tlv->wlan_time =
|
|
uap_cpu_to_le16(acl_wlan_time);
|
|
coex_acl_tlv->protection_rate =
|
|
uap_cpu_to_le16(acl_prot_rate);
|
|
tlv_len += sizeof(tlvbuf_coex_acl_cfg);
|
|
is_coex_acl_config = 0;
|
|
}
|
|
} else if (is_coex_sco_config == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
coex_sco_tlv =
|
|
(tlvbuf_coex_sco_cfg *)(cmd_buf->
|
|
tlv_buffer +
|
|
tlv_len);
|
|
coex_sco_tlv->tag = MRVL_BT_COEX_SCO_CFG_TLV_ID;
|
|
coex_sco_tlv->length =
|
|
sizeof(tlvbuf_coex_sco_cfg) -
|
|
sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_sco_tlv);
|
|
for (i = 0; i < 4; i++)
|
|
coex_sco_tlv->protection_qtime[i] =
|
|
uap_cpu_to_le16(sco_prot_qtime
|
|
[i]);
|
|
coex_sco_tlv->protection_rate =
|
|
uap_cpu_to_le16(sco_prot_rate);
|
|
coex_sco_tlv->acl_frequency =
|
|
uap_cpu_to_le16(sco_acl_freq);
|
|
tlv_len += sizeof(tlvbuf_coex_sco_cfg);
|
|
is_coex_sco_config = 0;
|
|
}
|
|
} else if (is_coex_common_config == 1) {
|
|
if (strcmp(args[0], "}") == 0) {
|
|
coex_common_tlv =
|
|
(tlvbuf_coex_common_cfg *)(cmd_buf->
|
|
tlv_buffer +
|
|
tlv_len);
|
|
coex_common_tlv->tag =
|
|
MRVL_BT_COEX_COMMON_CFG_TLV_ID;
|
|
coex_common_tlv->length =
|
|
sizeof(tlvbuf_coex_common_cfg) -
|
|
sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_common_tlv);
|
|
coex_common_tlv->config_bitmap =
|
|
uap_cpu_to_le32(conf_bitmap);
|
|
coex_common_tlv->ap_bt_coex =
|
|
uap_cpu_to_le32(ap_coex_enable);
|
|
tlv_len += sizeof(tlvbuf_coex_common_cfg);
|
|
is_coex_common_config = 0;
|
|
}
|
|
} else if (is_coex_config == 1) {
|
|
if (strcmp(args[0], "}") == 0)
|
|
is_coex_config = 0;
|
|
}
|
|
if (strcmp(args[0], "coex_config") == 0) {
|
|
is_coex_config = 1;
|
|
} else if (strcmp(args[0], "common_config") == 0) {
|
|
is_coex_common_config = 1;
|
|
} else if (strcmp(args[0], "sco_config") == 0) {
|
|
is_coex_sco_config = 1;
|
|
} else if (strcmp(args[0], "acl_config") == 0) {
|
|
is_coex_acl_config = 1;
|
|
}
|
|
if ((strcmp(args[0], "bitmap") == 0) && is_coex_common_config) {
|
|
if (is_input_valid
|
|
(COEX_COMM_BITMAP, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
conf_bitmap = (t_u32)A2HEXDECIMAL(args[1]);
|
|
} else if ((strcmp(args[0], "APBTCoex") == 0) &&
|
|
is_coex_common_config) {
|
|
if (is_input_valid
|
|
(COEX_COMM_AP_COEX, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
ap_coex_enable = (t_u32)A2HEXDECIMAL(args[1]);
|
|
} else if ((strncmp(args[0], "protectionFromQTime", 19) == 0) &&
|
|
is_coex_sco_config) {
|
|
index = atoi(args[0] + strlen("protectionFromQTime"));
|
|
if (index < 0 || index > 3) {
|
|
printf("ERR:Incorrect index %d.\n", index);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
sco_prot_qtime[index] = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "scoProtectionFromRate") == 0) &&
|
|
is_coex_sco_config) {
|
|
if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
sco_prot_rate = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "aclFrequency") == 0) &&
|
|
is_coex_sco_config) {
|
|
if (is_input_valid
|
|
(COEX_SCO_ACL_FREQ, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
sco_acl_freq = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "enabled") == 0) &&
|
|
is_coex_acl_config) {
|
|
if (is_input_valid
|
|
(COEX_ACL_ENABLED, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
acl_enabled = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "btTime") == 0) &&
|
|
is_coex_acl_config) {
|
|
if (is_input_valid
|
|
(COEX_ACL_BT_TIME, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
acl_bt_time = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "wlanTime") == 0) &&
|
|
is_coex_acl_config) {
|
|
if (is_input_valid
|
|
(COEX_ACL_WLAN_TIME, arg_num - 1,
|
|
args + 1) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
acl_wlan_time = (t_u16)atoi(args[1]);
|
|
} else if ((strcmp(args[0], "aclProtectionFromRate") == 0) &&
|
|
is_coex_acl_config) {
|
|
if (is_input_valid(COEX_PROTECTION, arg_num, args) !=
|
|
UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
acl_prot_rate = (t_u16)atoi(args[1]);
|
|
}
|
|
}
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, cmd_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
/* Verify response */
|
|
if (cmd_buf->cmd_code !=
|
|
(HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) {
|
|
printf("ERR:Corrupted response!\n");
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
/* Print response */
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("BT Coex settings sucessfully set.\n");
|
|
} else {
|
|
printf("ERR:Could not set coex configuration.\n");
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
done:
|
|
fclose(config_file);
|
|
if (buf)
|
|
free(buf);
|
|
if (line)
|
|
free(line);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the coex_config command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_coex_config_usage(void)
|
|
{
|
|
printf("\nUsage : coex_config [CONFIG_FILE]\n");
|
|
printf("\nIf CONFIG_FILE is provided, a 'set' is performed, else a 'get' is performed.\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a coex_config request and sends to the driver
|
|
*
|
|
* Usage: "Usage : coex_config [CONFIG_FILE]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_coex_config(int argc, char *argv[])
|
|
{
|
|
apcmdbuf_coex_config *cmd_buf = NULL;
|
|
tlvbuf_coex_common_cfg *coex_common_tlv;
|
|
tlvbuf_coex_sco_cfg *coex_sco_tlv;
|
|
tlvbuf_coex_acl_cfg *coex_acl_tlv;
|
|
tlvbuf_coex_stats *coex_stats_tlv;
|
|
t_u8 *buf = 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_coex_config_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_coex_config_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 1) {
|
|
/* Read profile and send command to firmware */
|
|
ret = apcmd_coex_config_profile(argc, argv);
|
|
return ret;
|
|
}
|
|
|
|
/* fixed command length */
|
|
cmd_len = sizeof(apcmdbuf_coex_config) + sizeof(tlvbuf_coex_common_cfg)
|
|
+ sizeof(tlvbuf_coex_sco_cfg) + sizeof(tlvbuf_coex_acl_cfg)
|
|
+ sizeof(tlvbuf_coex_stats);
|
|
/* alloc buf for command */
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer from command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
bzero((char *)buf, buf_len);
|
|
|
|
cmd_buf = (apcmdbuf_coex_config *)buf;
|
|
|
|
coex_common_tlv = (tlvbuf_coex_common_cfg *)cmd_buf->tlv_buffer;
|
|
coex_common_tlv->tag = MRVL_BT_COEX_COMMON_CFG_TLV_ID;
|
|
coex_common_tlv->length =
|
|
sizeof(tlvbuf_coex_common_cfg) - sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_common_tlv);
|
|
|
|
coex_sco_tlv = (tlvbuf_coex_sco_cfg *)(cmd_buf->tlv_buffer +
|
|
sizeof(tlvbuf_coex_common_cfg));
|
|
coex_sco_tlv->tag = MRVL_BT_COEX_SCO_CFG_TLV_ID;
|
|
coex_sco_tlv->length =
|
|
sizeof(tlvbuf_coex_sco_cfg) - sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_sco_tlv);
|
|
|
|
coex_acl_tlv = (tlvbuf_coex_acl_cfg *)(cmd_buf->tlv_buffer +
|
|
sizeof(tlvbuf_coex_common_cfg) +
|
|
sizeof(tlvbuf_coex_sco_cfg));
|
|
coex_acl_tlv->tag = MRVL_BT_COEX_ACL_CFG_TLV_ID;
|
|
coex_acl_tlv->length =
|
|
sizeof(tlvbuf_coex_acl_cfg) - sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_acl_tlv);
|
|
|
|
coex_stats_tlv = (tlvbuf_coex_stats *)(cmd_buf->tlv_buffer +
|
|
sizeof(tlvbuf_coex_common_cfg) +
|
|
sizeof(tlvbuf_coex_sco_cfg)
|
|
+ sizeof(tlvbuf_coex_acl_cfg));
|
|
coex_stats_tlv->tag = MRVL_BT_COEX_STATS_TLV_ID;
|
|
coex_stats_tlv->length =
|
|
sizeof(tlvbuf_coex_stats) - sizeof(tlvbuf_header);
|
|
endian_convert_tlv_header_out(coex_stats_tlv);
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->cmd_code = HostCmd_ROBUST_COEX;
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->action = uap_cpu_to_le16(ACTION_GET);
|
|
|
|
/* 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 !=
|
|
(HostCmd_ROBUST_COEX | APCMD_RESP_CHECK)) {
|
|
printf("ERR:Corrupted response!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Print response */
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("BT Coex settings:\n");
|
|
print_tlv(buf + sizeof(apcmdbuf_coex_config),
|
|
cmd_buf->size - sizeof(apcmdbuf_coex_config) +
|
|
BUF_HEADER_SIZE);
|
|
} else {
|
|
printf("ERR:Could not retrieve coex configuration.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the mic_err command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_mic_err_usage(void)
|
|
{
|
|
printf("\nUsage : mic_err <STA_MAC_ADDRESS>\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief report station mic error to the driver
|
|
*
|
|
* Usage: "mic_err <STA_MAC_ADDRESS>"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_mic_err(int argc, char *argv[])
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 mac_addr[ETH_ALEN];
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_mic_err_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc != 1) {
|
|
printf("ERR:wrong arguments! Must provide STA_MAC_ADDRESS.\n");
|
|
print_mic_err_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(mac_addr, 0, ETH_ALEN);
|
|
|
|
if ((ret = mac2raw(argv[0], mac_addr)) != UAP_SUCCESS) {
|
|
printf("ERR: %s Address\n", ret == UAP_FAILURE ? "Invalid MAC" :
|
|
ret ==
|
|
UAP_RET_MAC_BROADCAST ? "Broadcast" : "Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
#if DEBUG
|
|
/* Dump mac address */
|
|
hexdump("report mic error", (void *)mac_addr, ETH_ALEN, ' ');
|
|
#endif
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)mac_addr;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_REPORT_MIC_ERR, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_REPORT_MIC_ERR is not supported by %s\n",
|
|
dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("MIC error reporting successful!\n");
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sta_deauth_ext command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_set_key_usage(void)
|
|
{
|
|
printf("\nUsage : key_material <MAC_ADDRESS> <KEY> [KEY_ID]\n");
|
|
printf("\n MAC_ADDRESS: station mac address or ff:ff:ff:ff:ff:ff");
|
|
printf("\n KEY: hex string, valid length 32 or 64\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a set key request and sends to the driver
|
|
*
|
|
* Usage: "set_key <MAC_ADDRESS><KEY>[KEY_ID]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_set_key(int argc, char *argv[])
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
int opt;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
encrypt_key key;
|
|
int key_id = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_set_key_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc < 2 || argc > 3) {
|
|
print_set_key_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(&key, 0, sizeof(encrypt_key));
|
|
|
|
ret = mac2raw(argv[0], key.mac_addr);
|
|
|
|
if ((ret != UAP_SUCCESS) && (ret != UAP_RET_MAC_BROADCAST)) {
|
|
printf("ERR: %s Address\n",
|
|
ret == UAP_FAILURE ? "Invalid MAC" : "Multicast");
|
|
return UAP_FAILURE;
|
|
}
|
|
if ((strlen(argv[1]) != 32) && (strlen(argv[1]) != 64)) {
|
|
printf("ERR: key must be hex string with length 32 or 64");
|
|
print_set_key_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (UAP_FAILURE == ishexstring(argv[1])) {
|
|
printf("ERR:Only hex digits are allowed\n");
|
|
print_set_key_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc == 3) {
|
|
if ((ISDIGIT(argv[2]) == 0) || (atoi(argv[2]) < 0) ||
|
|
(atoi(argv[2]) > 3)) {
|
|
printf("ERR:Illegal key id %s. Must be either '0', '1', '2', or '3'.\n", argv[2]);
|
|
print_set_key_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
key_id = atoi(argv[2]);
|
|
}
|
|
|
|
key.key_len = strlen(argv[1]) / 2;
|
|
string2raw(argv[1], key.key_material);
|
|
key.key_index = key_id;
|
|
|
|
#if DEBUG
|
|
/* dump key buffer */
|
|
hexdump("set key", (void *)&key, sizeof(encrypt_key), ' ');
|
|
#endif
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&key;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_SET_KEY, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_SET_KEY is not supported by %s\n", dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
printf("Key setting successful.\n");
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sys_cfg_custom_ie
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sys_cfg_custom_ie_usage(void)
|
|
{
|
|
printf("\nUsage : sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]");
|
|
printf("\n empty - Get all IE settings\n");
|
|
printf("\n INDEX: 0 - Get/Set IE index 0 setting");
|
|
printf("\n 1 - Get/Set IE index 1 setting");
|
|
printf("\n 2 - Get/Set IE index 2 setting");
|
|
printf("\n 3 - Get/Set IE index 3 setting");
|
|
printf("\n . ");
|
|
printf("\n . ");
|
|
printf("\n . ");
|
|
printf("\n -1 - Append/Delete IE automatically");
|
|
printf("\n Delete will delete the IE from the matching IE buffer");
|
|
printf("\n Append will append the IE to the buffer with the same mask");
|
|
printf("\n MASK : Management subtype mask value as per bit defintions");
|
|
printf("\n : Bit 0 - Association request.");
|
|
printf("\n : Bit 1 - Association response.");
|
|
printf("\n : Bit 2 - Reassociation request.");
|
|
printf("\n : Bit 3 - Reassociation response.");
|
|
printf("\n : Bit 4 - Probe request.");
|
|
printf("\n : Bit 5 - Probe response.");
|
|
printf("\n : Bit 8 - Beacon.");
|
|
printf("\n MASK : MASK = 0 to clear the mask and the IE buffer");
|
|
printf("\n IEBuffer : IE Buffer in hex (max 256 bytes)\n\n");
|
|
return;
|
|
}
|
|
|
|
/** custom IE, auto mask value */
|
|
#define UAP_CUSTOM_IE_AUTO_MASK 0xffff
|
|
|
|
/**
|
|
* @brief Get max management IE index
|
|
* @param max_mgmt_ie
|
|
* @param print flag
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
static int
|
|
get_max_mgmt_ie(int *max_mgmt_ie, int flag)
|
|
{
|
|
apcmdbuf_sys_configure *cmd_buf = NULL;
|
|
tlvbuf_max_mgmt_ie *tlv = NULL;
|
|
t_u8 *buffer = NULL;
|
|
t_u16 cmd_len = 0, i = 0;
|
|
t_u16 buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
*max_mgmt_ie = 0;
|
|
/* Initialize the command length */
|
|
cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_max_mgmt_ie);
|
|
|
|
/* 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_mgmt_ie *)(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_MGMT_IE_TLV_ID;
|
|
tlv->length = 0;
|
|
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);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
/* Verify response */
|
|
if ((cmd_buf->cmd_code !=
|
|
(APCMD_SYS_CONFIGURE | APCMD_RESP_CHECK)) ||
|
|
(tlv->tag != MRVL_MAX_MGMT_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) {
|
|
tlv->count = uap_le16_to_cpu(tlv->count);
|
|
for (i = 0; i < tlv->count; i++) {
|
|
tlv->info[i].buf_size =
|
|
uap_le16_to_cpu(tlv->info[i].buf_size);
|
|
tlv->info[i].buf_count =
|
|
uap_le16_to_cpu(tlv->info[i].buf_count);
|
|
*max_mgmt_ie += tlv->info[i].buf_count;
|
|
if (flag) {
|
|
printf("buf%d_size = %d\n", i,
|
|
tlv->info[i].buf_size);
|
|
printf("number of buffers = %d\n",
|
|
tlv->info[i].buf_count);
|
|
printf("\n");
|
|
}
|
|
}
|
|
} else {
|
|
printf("ERR:Could not get max_mgmt_ie_index!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
}
|
|
if (buffer)
|
|
free(buffer);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a sys_cfg request for custom IE settings
|
|
* and sends to the driver
|
|
*
|
|
* Usage: "sys_cfg_custom_ie [INDEX] [MASK] [IEBuffer]"
|
|
*
|
|
* Options: INDEX : 0 - Get/Set IE index 0 setting
|
|
* 1 - Get/Set IE index 1 setting
|
|
* 2 - Get/Set IE index 2 setting
|
|
* 3 - Get/Set IE index 3 setting
|
|
* .
|
|
* .
|
|
* .
|
|
* MASK : Management subtype mask value
|
|
* IEBuffer: IE Buffer in hex
|
|
* empty - Get all IE settings
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_sys_cfg_custom_ie(int argc, char *argv[])
|
|
{
|
|
tlvbuf_custom_ie *tlv = NULL;
|
|
tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv = NULL;
|
|
custom_ie *ie_ptr = NULL;
|
|
t_u8 *buffer = NULL;
|
|
t_u16 buf_len = 0;
|
|
t_u16 mgmt_subtype_mask = 0;
|
|
int ie_buf_len = 0, ie_len = 0, i = 0, max_mgmt_ie = 0, print_flag = 0;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
if (argc == 1 && max_mgmt_ie_print == 0) {
|
|
/* Print buffer sizes only if (argc == 1) i.e. get all indices one by one
|
|
* && (max_mgmt_ie_print == 0) i.e. max mgmt IE is not printed via sys_config cmd */
|
|
print_flag = 1;
|
|
}
|
|
|
|
/* Reset the max_mgmt_ie_print for successive cmds */
|
|
max_mgmt_ie_print = 0;
|
|
|
|
if (!get_max_mgmt_ie(&max_mgmt_ie, print_flag)) {
|
|
printf("ERR:couldn't get max_mgmt_ie!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
if (max_mgmt_ie == 0) {
|
|
max_mgmt_ie = MAX_MGMT_IE_INDEX;
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG,
|
|
"WARN: max_mgmt_ie=0, defaulting to MAX_MGMT_IE_INDEX\n");
|
|
#endif
|
|
}
|
|
|
|
/* Check arguments */
|
|
if (argc > 4) {
|
|
printf("ERR:Too many arguments.\n");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Error checks and initialize the command length */
|
|
if (argc >= 2) {
|
|
if (((IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) &&
|
|
(atoi(argv[1]) != -1)) || (atoi(argv[1]) < -1)) {
|
|
printf("ERR:Illegal index %s\n", argv[1]);
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
switch (argc) {
|
|
case 1:
|
|
buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
break;
|
|
case 2:
|
|
if ((atoi(argv[1]) < 0) || (atoi(argv[1]) >= max_mgmt_ie)) {
|
|
printf("ERR:Illegal index %s. Must be either greater than or equal to 0 and less than %d for Get Operation \n", argv[1], max_mgmt_ie);
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
buf_len = MRVDRV_SIZE_OF_CMD_BUFFER;
|
|
break;
|
|
case 3:
|
|
if (UAP_FAILURE == ishexstring(argv[2]) ||
|
|
A2HEXDECIMAL(argv[2]) != 0) {
|
|
printf("ERR: Mask value should be 0 to clear IEBuffers.\n");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (atoi(argv[1]) == -1) {
|
|
printf("ERR: Buffer should be provided for automatic deletion.\n");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie);
|
|
break;
|
|
case 4:
|
|
/* This is to check negative numbers and special symbols */
|
|
if (UAP_FAILURE == IS_HEX_OR_DIGIT(argv[2])) {
|
|
printf("ERR:Mask value must be 0 or hex digits\n");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
/* If above check is passed and mask is not hex, then it must be 0 */
|
|
if ((ISDIGIT(argv[2]) == UAP_SUCCESS) && atoi(argv[2])) {
|
|
printf("ERR:Mask value must be 0 or hex digits\n ");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
if (UAP_FAILURE == ishexstring(argv[3])) {
|
|
printf("ERR:Only hex digits are allowed\n");
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
ie_buf_len = strlen(argv[3]);
|
|
if (!strncasecmp("0x", argv[3], 2)) {
|
|
ie_len = (ie_buf_len - 2 + 1) / 2;
|
|
argv[3] += 2;
|
|
} else
|
|
ie_len = (ie_buf_len + 1) / 2;
|
|
if (ie_len > MAX_IE_BUFFER_LEN) {
|
|
printf("ERR:Incorrect IE length %d\n", ie_buf_len);
|
|
print_sys_cfg_custom_ie_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
mgmt_subtype_mask = (t_u16)A2HEXDECIMAL(argv[2]);
|
|
buf_len = sizeof(tlvbuf_custom_ie) + sizeof(custom_ie) + ie_len;
|
|
break;
|
|
}
|
|
|
|
/* Initialize the command buffer */
|
|
buffer = (t_u8 *)malloc(buf_len);
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(buffer, 0, buf_len);
|
|
tlv = (tlvbuf_custom_ie *)buffer;
|
|
tlv->tag = MRVL_MGMT_IE_LIST_TLV_ID;
|
|
if (argc == 1 || argc == 2) {
|
|
if (argc == 1)
|
|
tlv->length = 0;
|
|
else {
|
|
tlv->length = sizeof(t_u16);
|
|
ie_ptr = (custom_ie *)(tlv->ie_data);
|
|
ie_ptr->ie_index = (t_u16)(atoi(argv[1]));
|
|
}
|
|
} else {
|
|
/* Locate headers */
|
|
ie_ptr = (custom_ie *)(tlv->ie_data);
|
|
/* Set TLV fields */
|
|
tlv->length = sizeof(custom_ie) + ie_len;
|
|
ie_ptr->ie_index = atoi(argv[1]);
|
|
ie_ptr->mgmt_subtype_mask = mgmt_subtype_mask;
|
|
ie_ptr->ie_length = ie_len;
|
|
if (argc == 4)
|
|
string2raw(argv[3], ie_ptr->ie_buffer);
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
if (buffer)
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (argc != 1) {
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)buffer;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) {
|
|
if (errno < 0) {
|
|
perror("ioctl[UAP_CUSTOM_IE]");
|
|
printf("ERR:Command sending failed!\n");
|
|
} else {
|
|
printf("custom IE configuration failed!\n");
|
|
}
|
|
close(sockfd);
|
|
if (buffer)
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Print response */
|
|
if (argc > 2) {
|
|
printf("custom IE setting successful\n");
|
|
} else {
|
|
printf("Querying custom IE successful\n");
|
|
tlv = (tlvbuf_custom_ie *)buffer;
|
|
ie_len = tlv->length;
|
|
ie_ptr = (custom_ie *)(tlv->ie_data);
|
|
if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
|
|
while ((unsigned int)ie_len >=
|
|
sizeof(custom_ie)) {
|
|
printf("Index [%d]\n",
|
|
ie_ptr->ie_index);
|
|
if (ie_ptr->ie_length)
|
|
printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask);
|
|
else
|
|
printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask);
|
|
hexdump_data("IE Buffer",
|
|
(void *)ie_ptr->ie_buffer,
|
|
(ie_ptr->ie_length), ' ');
|
|
ie_len -=
|
|
sizeof(custom_ie) +
|
|
ie_ptr->ie_length;
|
|
ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
|
|
sizeof(custom_ie)
|
|
+
|
|
ie_ptr->
|
|
ie_length);
|
|
}
|
|
}
|
|
max_mgmt_ie_tlv =
|
|
(tlvbuf_max_mgmt_ie *)(buffer +
|
|
sizeof(tlvbuf_custom_ie)
|
|
+ tlv->length);
|
|
if (max_mgmt_ie_tlv) {
|
|
if (max_mgmt_ie_tlv->tag ==
|
|
MRVL_MAX_MGMT_IE_TLV_ID) {
|
|
for (i = 0; i < max_mgmt_ie_tlv->count;
|
|
i++) {
|
|
printf("buf%d_size = %d\n", i,
|
|
max_mgmt_ie_tlv->info[i].
|
|
buf_size);
|
|
printf("number of buffers = %d\n", max_mgmt_ie_tlv->info[i].buf_count);
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Special handling for all indices: Get all IEs one-by-one */
|
|
if (argc == 1) {
|
|
for (i = 0; i < max_mgmt_ie; i++) {
|
|
|
|
tlv->length = sizeof(t_u16);
|
|
ie_ptr = (custom_ie *)(tlv->ie_data);
|
|
ie_ptr->ie_index = (t_u16)(i);
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)buffer;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, UAP_CUSTOM_IE, &ifr)) {
|
|
if (errno < 0) {
|
|
perror("ioctl[UAP_CUSTOM_IE]");
|
|
printf("ERR:Command sending failed!\n");
|
|
} else {
|
|
printf("custom IE configuration failed!\n");
|
|
}
|
|
close(sockfd);
|
|
if (buffer)
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Print response */
|
|
tlv = (tlvbuf_custom_ie *)buffer;
|
|
ie_len = tlv->length;
|
|
ie_ptr = (custom_ie *)(tlv->ie_data);
|
|
if (tlv->tag == MRVL_MGMT_IE_LIST_TLV_ID) {
|
|
while ((unsigned int)ie_len >=
|
|
sizeof(custom_ie)) {
|
|
printf("Index [%d]\n",
|
|
ie_ptr->ie_index);
|
|
if (ie_ptr->ie_length)
|
|
printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : ie_ptr->mgmt_subtype_mask);
|
|
else
|
|
printf("Management Subtype Mask = 0x%02x\n", ie_ptr->mgmt_subtype_mask);
|
|
hexdump_data("IE Buffer",
|
|
(void *)ie_ptr->ie_buffer,
|
|
(ie_ptr->ie_length), ' ');
|
|
ie_len -=
|
|
sizeof(custom_ie) +
|
|
ie_ptr->ie_length;
|
|
ie_ptr = (custom_ie *)((t_u8 *)ie_ptr +
|
|
sizeof(custom_ie)
|
|
+
|
|
ie_ptr->
|
|
ie_length);
|
|
}
|
|
}
|
|
}
|
|
printf("Querying custom IE successful\n");
|
|
}
|
|
|
|
if (buffer)
|
|
free(buffer);
|
|
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the dfstesting command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_dfstesting_usage(void)
|
|
{
|
|
printf("\nUsage : dfstesting [USER_CAC_PD USER_NOP_PD NO_CHAN_CHANGE FIXED_CHAN_NUM]\n");
|
|
printf("\n empty - Get all dfstesting settings\n");
|
|
printf("\n USER_CAC_PD: user configured Channel Availability Check period");
|
|
printf("\n 0 - disable, use default (60000)");
|
|
printf("\n 1-65535 - CAC period in msec");
|
|
printf("\n USER_NOP_PD: user configured Non-Occupancy Period");
|
|
printf("\n 0 - disable, use default (1800)");
|
|
printf("\n 1-65535 - NOP period in sec");
|
|
printf("\n NO_CHAN_CHANGE: user setting, don't change channel on radar");
|
|
printf("\n 0 - disable, default behavior");
|
|
printf("\n non-zero - enable, overrides below setting");
|
|
printf("\n FIXED_CHAN_NUM: user fixed channel to change to on radar");
|
|
printf("\n 0 - disable, use random channel [default]");
|
|
printf("\n 1-255 - set fixed channel (not checked for validity)\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief user configuration of dfs testing settings
|
|
*
|
|
* Usage: "dfstesting [USER_CAC_PD USER_NOP_PD NO_CHAN_CHANGE FIXED_CHAN_NUM]"
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_dfstesting(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u32 val;
|
|
dfs_testing_para dfs_test;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_dfstesting_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
memset(&dfs_test, 0x00, sizeof(dfs_test));
|
|
|
|
/* Check arguments */
|
|
if (argc == 0) {
|
|
dfs_test.action = ACTION_GET;
|
|
} else if (argc == 4) {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) ||
|
|
(IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE) ||
|
|
(IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE) ||
|
|
(IS_HEX_OR_DIGIT(argv[3]) == UAP_FAILURE)) {
|
|
printf("ERR: Only Number values are allowed\n");
|
|
print_dfstesting_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
val = A2HEXDECIMAL(argv[0]);
|
|
if (val > 0xfffff) {
|
|
printf("ERR: invalid user_cac_pd value!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
dfs_test.usr_cac_period = (t_u32)val;
|
|
|
|
val = A2HEXDECIMAL(argv[1]);
|
|
if (val > 0xffff) {
|
|
printf("ERR: invalid user_nop_pd value!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
dfs_test.usr_nop_period = (t_u16)val;
|
|
|
|
val = A2HEXDECIMAL(argv[2]);
|
|
dfs_test.no_chan_change = (t_u8)(val ? 1 : 0);
|
|
|
|
val = A2HEXDECIMAL(argv[3]);
|
|
if (val > 0xff) {
|
|
printf("ERR: invalid fixed_chan_num value!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
dfs_test.fixed_new_chan = (t_u8)val;
|
|
dfs_test.action = ACTION_SET;
|
|
} else {
|
|
printf("ERR: invalid number of arguments! Must be 0 or 4.\n");
|
|
print_dfstesting_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
dfs_test.subcmd = UAP_DFS_TESTING;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&dfs_test;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: UAP_DFS_TESTING is not supported by %s\n",
|
|
dev_name);
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc)
|
|
printf("DFS testing setting successful!\n");
|
|
else
|
|
printf("DFS testing settings:\n"
|
|
" user_cac_period = %d msec\n"
|
|
" user_nop_period = %d sec\n"
|
|
" no_channel_change = %d\n"
|
|
" fixed_channel_num = %d\n",
|
|
dfs_test.usr_cac_period, dfs_test.usr_nop_period,
|
|
dfs_test.no_chan_change, dfs_test.fixed_new_chan);
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the cscount_cfg
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_cscount_cfg_usage(void)
|
|
{
|
|
printf("\nUsage : cscount [<n>]");
|
|
printf("\n Where <n> ");
|
|
printf("\n 5-20: No of beacons with Channel Switch Count IE\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Set/get cs_count configuration
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_cscount_cfg(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
cscount_cfg_t cscount_cfg;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_cscount_cfg_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
|
|
memset(&cscount_cfg, 0, sizeof(cscount_cfg));
|
|
if (argc == 0) {
|
|
cscount_cfg.action = ACTION_GET;
|
|
} else if (argc == 1) {
|
|
if ((t_u32)A2HEXDECIMAL(argv[0]) < 5
|
|
&& (t_u32)A2HEXDECIMAL(argv[0]) > 20) {
|
|
printf("ERR:Invalid Channel switch count value\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
cscount_cfg.action = ACTION_SET;
|
|
cscount_cfg.cs_count = (t_u32)A2HEXDECIMAL(argv[0]);
|
|
} else {
|
|
print_cscount_cfg_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
cscount_cfg.subcmd = UAP_CHAN_SWITCH_COUNT_CFG;
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)&cscount_cfg;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: Channel switch count configuration failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Handle response */
|
|
if (cscount_cfg.action == ACTION_GET) {
|
|
printf("Channel Switch count = %d\n", cscount_cfg.cs_count);
|
|
}
|
|
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the mgmtframectrl command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_mgmtframectrl_usage(void)
|
|
{
|
|
printf("\nUsage : mgmtframectrl [MASK]\n");
|
|
printf(" empty - Get management frame control mask\n");
|
|
printf(" MASK - Set management frame control mask\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Creates management frame control request and send to driver
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
apcmd_mgmt_frame_control(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
mgmt_frame_ctrl param; /* Action =0, Mask =0 */
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_mgmtframectrl_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if (argc > 1) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_mgmtframectrl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if ((argc) && (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) {
|
|
printf("ERR: Invalid argument %s\n", argv[0]);
|
|
print_mgmtframectrl_usage();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
memset(¶m, 0, sizeof(mgmt_frame_ctrl));
|
|
param.subcmd = UAP_MGMT_FRAME_CONTROL;
|
|
if (argc) {
|
|
param.action = ACTION_SET;
|
|
param.mask = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
} else {
|
|
param.action = ACTION_GET;
|
|
}
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)¶m;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:UAP_IOCTL_CMD failed\n");
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
if (!argc) {
|
|
printf("Management Frame control mask = 0x%02x\n",
|
|
(int)param.mask);
|
|
}
|
|
/* Close socket */
|
|
close(sockfd);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for the sys_cfg_pmf command
|
|
* command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_sys_cfg_pmf(void)
|
|
{
|
|
printf("\nUsage : uaputl.exe sys_cfg_pmf [MFPC] [MFPR]\n");
|
|
printf("\nSet/Get PMF capabilities");
|
|
printf("\n empty - Get PMF capabilites\n");
|
|
printf("\n MFPC: Management frames protection capable");
|
|
printf("\n 0 - Not capable");
|
|
printf("\n 1 - capable");
|
|
printf("\n MFPR: Management frames protection required");
|
|
printf("\n don't care if MFPC is set to 0");
|
|
printf("\n 0 - Not required");
|
|
printf("\n 1 - required\n");
|
|
return;
|
|
}
|
|
|
|
int
|
|
apcmd_sys_cfg_pmf(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
apcmdbuf_pmf_params *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;
|
|
t_u8 mfpc = 0;
|
|
t_u8 mfpr = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_sys_cfg_pmf();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
/* Check arguments */
|
|
if ((argc > 2)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_sys_cfg_pmf();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc > 0)
|
|
mfpc = atoi(argv[0]);
|
|
|
|
if (mfpc && (argc == 1)) {
|
|
printf("ERR:wrong arguments.\n");
|
|
print_sys_cfg_pmf();
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (mfpc && (argc == 2))
|
|
mfpr = atoi(argv[1]);
|
|
|
|
/* Alloc buf for command */
|
|
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_len = sizeof(apcmdbuf_pmf_params);
|
|
cmd_buf = (apcmdbuf_pmf_params *) buf;
|
|
|
|
/* Fill the command buffer */
|
|
cmd_buf->size = cmd_len - BUF_HEADER_SIZE;
|
|
cmd_buf->seq_num = 0;
|
|
cmd_buf->result = 0;
|
|
cmd_buf->cmd_code = HostCmd_CMD_PMF_PARAMS;
|
|
if (argc == 0)
|
|
cmd_buf->action = ACTION_GET;
|
|
else
|
|
cmd_buf->action = ACTION_SET;
|
|
cmd_buf->action = uap_cpu_to_le16(cmd_buf->action);
|
|
cmd_buf->params.mfpc = mfpc;
|
|
cmd_buf->params.mfpr = mfpr;
|
|
|
|
/* Send the command */
|
|
ret = uap_ioctl((t_u8 *)cmd_buf, &cmd_len, buf_len);
|
|
|
|
/* Process response */
|
|
if (ret == UAP_SUCCESS) {
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
printf("Successfully executed the command\n");
|
|
printf("mfpc: %d, mfpr: %d\n",
|
|
cmd_buf->params.mfpc, cmd_buf->params.mfpr);
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
} else {
|
|
printf("ERR:Command sending failed!\n");
|
|
free(buf);
|
|
return UAP_FAILURE;
|
|
}
|
|
free(buf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show usage information for uap operation control command
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_uap_oper_ctrl_usage(void)
|
|
{
|
|
printf("\nUsage : uap_oper_ctrl <control> <chanopt> <bandcfg> <channel> ");
|
|
printf("\n set/get uap operation when in-STA disconnected from ext-AP if multi channel is disabled");
|
|
printf("\n control: 0: default, do nothing");
|
|
printf("\n 2: uap stops and restart automatically");
|
|
printf("\n chanopt : specify which channel should be used when uap restarts automatically");
|
|
printf("\n 1: uap restarts on default 2.4G/channel 6");
|
|
printf("\n 2: uap restart on band/channel configured by driver previously");
|
|
printf("\n 3: uap restart on band/channel configured by parameter bandcfg/channel");
|
|
printf("\n bandcfg : This parameter specifies the bandwidth (BW)");
|
|
printf("\n 0: 20Mhz");
|
|
printf("\n 2: 40Mhz");
|
|
printf("\n 3: 80Mhz");
|
|
printf("\n channel : This parameter specifies the channel will be used when chanopt is 3.");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Set/Get uap operation when in-STA disconnected from ext-AP
|
|
* @param argc Number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
apcmd_uap_oper_ctrl(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
uap_operation_ctrl param;
|
|
struct eth_priv_uap_oper_ctrl *uap_oper = NULL;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 *respbuf = NULL;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
while ((opt = getopt_long(argc, argv, "+", cmd_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
default:
|
|
print_uap_oper_ctrl_usage();
|
|
return UAP_SUCCESS;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
respbuf = (t_u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
if (!respbuf) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
memset(respbuf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
|
|
/* Check arguments */
|
|
if (argc > 4) {
|
|
printf("ERR: Invalid number of arguments.\n");
|
|
print_uap_oper_ctrl_usage();
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (argc > 0) {
|
|
param.uap_oper.ctrl = (t_u16)A2HEXDECIMAL(argv[0]);
|
|
if (param.uap_oper.ctrl == 2)
|
|
param.uap_oper.chan_opt = (t_u16)A2HEXDECIMAL(argv[1]);
|
|
|
|
if (argc == 4 && param.uap_oper.chan_opt == 3) {
|
|
param.uap_oper.bandcfg = (t_u8)A2HEXDECIMAL(argv[2]);
|
|
param.uap_oper.channel = (t_u8)A2HEXDECIMAL(argv[3]);
|
|
}
|
|
param.action = ACTION_SET;
|
|
} else {
|
|
param.action = ACTION_GET;
|
|
}
|
|
param.subcmd = UAP_OPERATION_CTRL;
|
|
|
|
memcpy(respbuf, ¶m, sizeof(uap_operation_ctrl));
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)respbuf;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR: uap operation control set/get failed\n");
|
|
close(sockfd);
|
|
free(respbuf);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Handle response */
|
|
if (param.action == ACTION_GET) {
|
|
/* Process result */
|
|
uap_oper =
|
|
(struct eth_priv_uap_oper_ctrl *)(respbuf +
|
|
2 * sizeof(t_u32));
|
|
printf(" uap operation control %x\n", uap_oper->ctrl);
|
|
printf(" uap channel operation %x\n", uap_oper->chan_opt);
|
|
if (uap_oper->chan_opt == 3) {
|
|
printf(" uap bandwidth %s\n",
|
|
uap_oper->
|
|
bandcfg ? ((uap_oper->bandcfg == 2) ? "40Mhz" :
|
|
"80Mhz") : "20Mhz");
|
|
printf(" uap channel %d\n", uap_oper->channel);
|
|
}
|
|
} else
|
|
printf("uap operation control set success!\n");
|
|
/* Close socket */
|
|
close(sockfd);
|
|
if (respbuf)
|
|
free(respbuf);
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/** Structure of command table*/
|
|
typedef struct {
|
|
/** Command name */
|
|
char *cmd;
|
|
/** Command function pointer */
|
|
int (*func) (int argc, char *argv[]);
|
|
/** Command usuage */
|
|
char *help;
|
|
} command_table;
|
|
|
|
/** AP command table */
|
|
static command_table ap_command[] = {
|
|
{"sys_config", apcmd_sys_config, "\tSet/get uAP's profile"},
|
|
{"sys_info", apcmd_sys_info, "\tDisplay system info"},
|
|
{"sys_reset", apcmd_sys_reset, "\tReset uAP"},
|
|
{"bss_start", apcmd_bss_start, "\tStart the BSS"},
|
|
{"bss_stop", apcmd_bss_stop, "\tStop the BSS"},
|
|
{"skip_cac", apcmd_skip_cac, "\tSkip the CAC"},
|
|
{"sta_deauth", apcmd_sta_deauth, "\tDeauth client"},
|
|
{"sta_list", apcmd_sta_list, "\tDisplay list of clients"},
|
|
{"sys_cfg_ap_mac_address", apcmd_sys_cfg_ap_mac_address,
|
|
"Set/get uAP mac address"},
|
|
{"sys_cfg_ssid", apcmd_sys_cfg_ssid, "\tSet/get uAP ssid"},
|
|
{"sys_cfg_beacon_period", apcmd_sys_cfg_beacon_period,
|
|
"Set/get uAP beacon period"},
|
|
{"sys_cfg_dtim_period", apcmd_sys_cfg_dtim_period,
|
|
"Set/get uAP dtim period"},
|
|
{"sys_cfg_bss_status", apcmd_sys_cfg_bss_status, "Get BSS status"},
|
|
{"sys_cfg_channel", apcmd_sys_cfg_channel,
|
|
"\tSet/get uAP radio channel"},
|
|
{"sys_cfg_channel_ext", apcmd_sys_cfg_channel_ext,
|
|
"\tSet/get uAP radio channel, band and mode"},
|
|
{"sys_cfg_scan_channels", apcmd_sys_cfg_scan_channels,
|
|
"Set/get uAP radio channel list"},
|
|
{"sys_cfg_rates", apcmd_sys_cfg_rates, "\tSet/get uAP rates"},
|
|
{"sys_cfg_rates_ext", apcmd_sys_cfg_rates_ext, "\tSet/get uAP rates"},
|
|
{"sys_cfg_tx_power", apcmd_sys_cfg_tx_power, "Set/get uAP tx power"},
|
|
{"sys_cfg_bcast_ssid_ctl", apcmd_sys_cfg_bcast_ssid_ctl,
|
|
"Set/get uAP broadcast ssid"},
|
|
{"sys_cfg_preamble_ctl", apcmd_sys_cfg_preamble_ctl,
|
|
"Get uAP preamble"},
|
|
{"antcfg", apcmd_antcfg, "Set/get uAP tx/rx antenna"},
|
|
{"htstreamcfg", apcmd_htstreamcfg,
|
|
"Set/get uAP HT stream configurations"},
|
|
{"sys_cfg_rts_threshold", apcmd_sys_cfg_rts_threshold,
|
|
"Set/get uAP rts threshold"},
|
|
{"sys_cfg_frag_threshold", apcmd_sys_cfg_frag_threshold,
|
|
"Set/get uAP frag threshold"},
|
|
{"radioctrl", apcmd_radio_ctl, "Set/get uAP radio on/off"},
|
|
{"sys_cfg_tx_beacon_rate", apcmd_sys_cfg_tx_beacon_rate,
|
|
"Set/get uAP tx beacon rate"},
|
|
{"txratecfg", apcmd_tx_rate_cfg, "Set/get trasnmit data rate"},
|
|
{"sys_cfg_mcbc_data_rate", apcmd_sys_cfg_mcbc_data_rate,
|
|
"Set/get uAP MCBC rate"},
|
|
{"sys_cfg_rsn_replay_prot", apcmd_sys_cfg_rsn_replay_prot,
|
|
"Set/get RSN replay protection"},
|
|
{"sys_cfg_pkt_fwd_ctl", apcmd_sys_cfg_pkt_fwd_ctl,
|
|
"Set/get uAP packet forwarding"},
|
|
{"sys_cfg_sta_ageout_timer", apcmd_sys_cfg_sta_ageout_timer,
|
|
"Set/get station ageout timer"},
|
|
{"sys_cfg_ps_sta_ageout_timer", apcmd_sys_cfg_ps_sta_ageout_timer,
|
|
"Set/get PS station ageout timer"},
|
|
{"sys_cfg_auth", apcmd_sys_cfg_auth,
|
|
"\tSet/get uAP authentication mode"},
|
|
{"sys_cfg_protocol", apcmd_sys_cfg_protocol,
|
|
"Set/get uAP security protocol"},
|
|
{"sys_cfg_wep_key", apcmd_sys_cfg_wep_key, "\tSet/get uAP wep key"},
|
|
{"sys_cfg_cipher", apcmd_sys_cfg_cipher,
|
|
"\tSet/get uAP WPA/WPA2 cipher"},
|
|
{"sys_cfg_pwk_cipher", apcmd_sys_cfg_pwk_cipher,
|
|
"\tSet/get uAP WPA/WPA2 pairwise cipher"},
|
|
{"sys_cfg_gwk_cipher", apcmd_sys_cfg_gwk_cipher,
|
|
"\tSet/get uAP WPA/WPA2 group cipher"},
|
|
{"sys_cfg_wpa_passphrase", apcmd_sys_cfg_wpa_passphrase,
|
|
"Set/get uAP WPA or WPA2 passphrase"},
|
|
{"sys_cfg_wpa3_sae_password", apcmd_sys_cfg_wpa3_sae_password,
|
|
"Set/get uAP WPA3 SAE password"},
|
|
{"sys_cfg_group_rekey_timer", apcmd_sys_cfg_group_rekey_timer,
|
|
"Set/get uAP group re-key time"},
|
|
{"sys_cfg_max_sta_num", apcmd_sys_cfg_max_sta_num,
|
|
"Set/get uAP max station number"},
|
|
{"sys_cfg_retry_limit", apcmd_sys_cfg_retry_limit,
|
|
"Set/get uAP retry limit number"},
|
|
{"sys_cfg_sticky_tim_config", apcmd_sys_cfg_sticky_tim_config,
|
|
"Set/get uAP sticky TIM configuration"},
|
|
{"sys_cfg_sticky_tim_sta_mac_addr",
|
|
apcmd_sys_cfg_sticky_tim_sta_mac_addr,
|
|
"Set/get uAP sticky TIM sta MAC address"},
|
|
{"sys_cfg_eapol_pwk_hsk", apcmd_sys_cfg_eapol_pwk_hsk,
|
|
"Set/getuAP pairwise Handshake timeout value and retries"},
|
|
{"sys_cfg_eapol_gwk_hsk", apcmd_sys_cfg_eapol_gwk_hsk,
|
|
"Set/getuAP groupwise Handshake timeout value and retries"},
|
|
{"sys_cfg_custom_ie", apcmd_sys_cfg_custom_ie,
|
|
"\tSet/get custom IE configuration"},
|
|
{"sta_filter_table", apcmd_sta_filter_table, "Set/get uAP mac filter"},
|
|
{"regrdwr", apcmd_regrdwr, "\t\tRead/Write register command"},
|
|
{"memaccess", apcmd_memaccess,
|
|
"\tRead/Write to a memory address command"},
|
|
{"rdeeprom", apcmd_read_eeprom, "\tRead EEPROM "},
|
|
{"cfg_data", apcmd_cfg_data,
|
|
"\tGet/Set configuration file from/to firmware"},
|
|
{"sys_cfg_80211d", apcmd_cfg_80211d, "\tSet/Get 802.11D info"},
|
|
{"uap_stats", apcmd_uap_stats, "\tGet uAP stats"},
|
|
{"pscfg", apcmd_pscfg, "\t\tSet/get uAP power mode"},
|
|
{"bss_config", apcmd_bss_config, "\tSet/get BSS configuration"},
|
|
{"sta_deauth_ext", apcmd_sta_deauth_ext, "\tDeauth client"},
|
|
{"mic_err", apcmd_mic_err, "\t\tReport station mic error"},
|
|
{"key_material", apcmd_set_key, "\tSet key"},
|
|
{"coex_config", apcmd_coex_config,
|
|
"\tSet/get uAP BT coex configuration"},
|
|
{"hscfg", apcmd_hscfg, "\t\tSet/get uAP host sleep parameters."},
|
|
{"hssetpara", apcmd_hssetpara,
|
|
"\t\tSet/get uAP host sleep parameters."},
|
|
{"addbapara", apcmd_addbapara, "\tSet/get uAP ADDBA parameters."},
|
|
{"aggrpriotbl", apcmd_aggrpriotbl,
|
|
"\tSet/get uAP priority table for AMPDU/AMSDU."},
|
|
{"addbareject", apcmd_addbareject, "\tSet/get uAP addbareject table."},
|
|
{"sys_cfg_11n", apcmd_sys_cfg_11n, "\tSet/get uAP 802.11n parameters."},
|
|
#ifdef RX_PACKET_COALESCE
|
|
{"rxpktcoal_cfg", apcmd_rx_pkt_coalesce,
|
|
"\tSet/get RX Packet coalesing paramterts."},
|
|
#endif
|
|
{"httxbfcfg", apcmd_sys_cfg_tx_bf, "\tSet/get uAP TX BF parameters."},
|
|
{"httxcfg", apcmd_sys_cfg_ht_tx, "\t\tSet/get uAP HT Tx parameters."},
|
|
{"vhtcfg", apcmd_sys_cfg_vht, "\t\tSet/get uAP VHT parameters."},
|
|
{"sys_cfg_wmm", apcmd_sys_cfg_wmm,
|
|
"\tSet/get uAP beacon wmm parameters."},
|
|
{"sys_cfg_ap_wmm", apcmd_sys_cfg_ap_wmm,
|
|
"\tSet/get uAP hardware wmm parameters."},
|
|
{"deepsleep", apcmd_deepsleep, "\tSet/get deepsleep mode."},
|
|
{"hostcmd", apcmd_hostcmd, "\t\tSet/get hostcmd"},
|
|
{"tx_data_pause", apcmd_txdatapause,
|
|
"\tSet/get Tx data pause settings."},
|
|
#ifdef SDIO
|
|
{"sdcmd52rw", apcmd_cmd52_readwrite,
|
|
"\tRead or write using sdio command 52."},
|
|
#endif
|
|
{"sys_cfg_2040_coex", apcmd_sys_cfg_2040_coex,
|
|
"\tSet/get 20/40 coex settings."},
|
|
{"dfstesting", apcmd_dfstesting, "\tConfigure DFS Testing settings."},
|
|
{"cscount", apcmd_cscount_cfg, "\tConfigure DFS Channel Switch Count."},
|
|
{"mgmtframectrl", apcmd_mgmt_frame_control,
|
|
"\tSpecifies mask indicating management frames to be sent from host."},
|
|
{"sys_cfg_restrict_client_mode", apcmd_sys_cfg_restrict_client_mode,
|
|
"\tSet/get the mode in which client stations can connect to the uAP."},
|
|
{"sys_cfg_pmf", apcmd_sys_cfg_pmf, "\tSet/get PMF capabilities."},
|
|
{"uap_oper_ctrl", apcmd_uap_oper_ctrl,
|
|
"\tSet/get uap operation control value."},
|
|
{"band_steering_cfg", apcmd_band_steering,
|
|
"\tConfigure Band Steering."},
|
|
{NULL, NULL, 0}
|
|
};
|
|
|
|
/**
|
|
* @brief Prints usage information of uaputl
|
|
*
|
|
* @return N/A
|
|
*/
|
|
static void
|
|
print_tool_usage(void)
|
|
{
|
|
int i;
|
|
printf("uaputl.exe - uAP utility ver %s\n", UAP_VERSION);
|
|
printf("Usage:\n"
|
|
"\tuaputl.exe [options] <command> [command parameters]\n");
|
|
printf("Options:\n"
|
|
"\t--help\tDisplay help\n"
|
|
"\t-v\tDisplay version\n"
|
|
"\t-i <interface>\n" "\t-d <debug_level=0|1|2>\n");
|
|
printf("Commands:\n");
|
|
for (i = 0; ap_command[i].cmd; i++)
|
|
printf("\t%-4s\t\t%s\n", ap_command[i].cmd, ap_command[i].help);
|
|
printf("\n"
|
|
"For more information on the usage of each command use:\n"
|
|
"\tuaputl.exe <command> --help\n");
|
|
}
|
|
|
|
/****************************************************************************
|
|
Global functions
|
|
****************************************************************************/
|
|
/** Option parameter*/
|
|
static struct option ap_options[] = {
|
|
{"help", 0, NULL, 'h'},
|
|
{"interface", 1, NULL, 'i'},
|
|
{"debug", 1, NULL, 'd'},
|
|
{"version", 0, NULL, 'v'},
|
|
{NULL, 0, NULL, '\0'}
|
|
};
|
|
|
|
/**
|
|
* @brief Checks if given channel in 'a' band is valid or not.
|
|
*
|
|
* @param channel Channel number
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_valid_a_band_channel(int channel)
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
switch (channel) {
|
|
case 16:
|
|
case 34:
|
|
case 36:
|
|
case 38:
|
|
case 40:
|
|
case 42:
|
|
case 44:
|
|
case 46:
|
|
case 48:
|
|
case 52:
|
|
case 56:
|
|
case 60:
|
|
case 64:
|
|
case 100:
|
|
case 104:
|
|
case 108:
|
|
case 112:
|
|
case 116:
|
|
case 120:
|
|
case 124:
|
|
case 128:
|
|
case 132:
|
|
case 136:
|
|
case 140:
|
|
case 144:
|
|
case 149:
|
|
case 153:
|
|
case 157:
|
|
case 161:
|
|
case 165:
|
|
break;
|
|
default:
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if secondary channel can be set above given primary channel in 'a' band or not.
|
|
*
|
|
* @param channel Channel number
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_valid_a_band_channel_above(int channel)
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
switch (channel) {
|
|
case 36:
|
|
case 44:
|
|
case 52:
|
|
case 60:
|
|
case 100:
|
|
case 108:
|
|
case 116:
|
|
case 124:
|
|
case 132:
|
|
case 140:
|
|
case 149:
|
|
case 157:
|
|
break;
|
|
default:
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if secondary channel can be set below given primary channel in 'a' band or not.
|
|
*
|
|
* @param channel Channel number
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_valid_a_band_channel_below(int channel)
|
|
{
|
|
int ret = UAP_SUCCESS;
|
|
switch (channel) {
|
|
case 40:
|
|
case 48:
|
|
case 56:
|
|
case 64:
|
|
case 104:
|
|
case 112:
|
|
case 120:
|
|
case 128:
|
|
case 136:
|
|
case 153:
|
|
case 161:
|
|
break;
|
|
default:
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Checkes a particular input for validatation.
|
|
*
|
|
* @param cmd Type of input
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_input_valid(valid_inputs cmd, int argc, char *argv[])
|
|
{
|
|
int i;
|
|
int chan_number = 0;
|
|
int band = 0;
|
|
int ch;
|
|
int ret = UAP_SUCCESS;
|
|
if (argc == 0)
|
|
return UAP_FAILURE;
|
|
switch (cmd) {
|
|
case RDEEPROM:
|
|
if (argc != 2) {
|
|
printf(" ERR: Argument count mismatch\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
|
|
|| (A2HEXDECIMAL(argv[0]) & 0x03) ||
|
|
((int)(A2HEXDECIMAL(argv[0])) < 0) ||
|
|
(A2HEXDECIMAL(argv[1]) & 0x03) ||
|
|
(A2HEXDECIMAL(argv[1]) < 4) ||
|
|
(A2HEXDECIMAL(argv[1]) > 20)) {
|
|
printf(" ERR: Invalid inputs for Read EEPROM\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case SCANCHANNELS:
|
|
if (argc > MAX_CHANNELS) {
|
|
printf("ERR: Invalid List of Channels\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
for (i = 0; i < argc; i++) {
|
|
chan_number = -1;
|
|
band = -1;
|
|
sscanf(argv[i], "%d.%d", &chan_number, &band);
|
|
if ((chan_number == -1) || (chan_number < 1) ||
|
|
(chan_number > MAX_CHANNELS)) {
|
|
printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if ((chan_number > MAX_CHANNELS_BG) &&
|
|
!(is_valid_a_band_channel(chan_number))) {
|
|
printf("ERR: Invalid Channel in 'a' band!\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if ((band < -1) || (band > 1)) {
|
|
printf("ERR:Band must be either 0 or 1\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
} else {
|
|
if (((chan_number < MAX_CHANNELS_BG) &&
|
|
(chan_number != 8) &&
|
|
(chan_number != 12) && (band == 1))
|
|
|| ((chan_number > MAX_CHANNELS_BG)
|
|
&& (band == 0))) {
|
|
printf("ERR:Invalid band for given channel\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ((ret != UAP_FAILURE) &&
|
|
(has_dup_channel(argc, argv) != UAP_SUCCESS)) {
|
|
printf("ERR: Duplicate channel values entered\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((ret != UAP_FAILURE) &&
|
|
(has_diff_band(argc, argv) != UAP_SUCCESS)) {
|
|
printf("ERR: Scan channel list should contain channels from only one band\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case TXPOWER:
|
|
if ((argc > 1) || (ISDIGIT(argv[0]) == 0)) {
|
|
printf("ERR:Invalid Transmit power\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((atoi(argv[0]) < MIN_TX_POWER) ||
|
|
(atoi(argv[0]) > MAX_TX_POWER)) {
|
|
printf("ERR: TX Powar must be in the rage of %d to %d. \n", MIN_TX_POWER, MAX_TX_POWER);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case PROTOCOL:
|
|
if ((argc > 2) || (ISDIGIT(argv[0]) == 0)) {
|
|
printf("ERR:Invalid Protocol\n");
|
|
ret = UAP_FAILURE;
|
|
} else
|
|
ret = is_protocol_valid(atoi(argv[0]));
|
|
break;
|
|
case AKM_SUITE:
|
|
if (argc == 2) {
|
|
if (A2HEXDECIMAL(argv[1]) &
|
|
~(KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256 | KEY_MGMT_EAP
|
|
| KEY_MGMT_NONE | KEY_MGMT_SAE)) {
|
|
printf("ERR: Invalid AKM suite\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case CHANNEL:
|
|
if ((argc != 1) && (argc != 2)) {
|
|
printf("ERR: Incorrect arguments for channel.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (argc == 2) {
|
|
if ((ISDIGIT(argv[1]) == 0) ||
|
|
(atoi(argv[1]) & ~CHANNEL_MODE_MASK)) {
|
|
printf("ERR: Invalid Mode\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[1]) & BITMAP_ACS_MODE) &&
|
|
(atoi(argv[0]) != 0)) {
|
|
printf("ERR: Channel must be 0 for ACS; MODE = 1.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[1]) & BITMAP_CHANNEL_ABOVE) &&
|
|
(atoi(argv[1]) & BITMAP_CHANNEL_BELOW)) {
|
|
printf("ERR: secondary channel above and below both are enabled\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((argc == 1) || (!(atoi(argv[1]) & BITMAP_ACS_MODE))) {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < 1) ||
|
|
(atoi(argv[0]) > MAX_CHANNELS)) {
|
|
printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[0]) > MAX_CHANNELS_BG) &&
|
|
!(is_valid_a_band_channel(atoi(argv[0])))) {
|
|
printf("ERR: Invalid Channel in 'a' band!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
ch = atoi(argv[0]);
|
|
if (ch <= MAX_CHANNELS_BG) {
|
|
if ((argc == 2) &&
|
|
(atoi(argv[1]) &
|
|
BITMAP_CHANNEL_ABOVE) &&
|
|
(atoi(argv[0]) >
|
|
MAX_CHANNEL_ABOVE)) {
|
|
printf("ERR: only allow channel 1-9 for secondary channel above\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((argc == 2) &&
|
|
(atoi(argv[1]) &
|
|
BITMAP_CHANNEL_BELOW) &&
|
|
((atoi(argv[0]) < MIN_CHANNEL_BELOW)
|
|
|| (atoi(argv[0]) == 14))) {
|
|
printf("ERR: only allow channel 5-13 for secondary channel below\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
if (argc == 2) {
|
|
if ((atoi(argv[1]) &
|
|
BITMAP_CHANNEL_BELOW) &&
|
|
!is_valid_a_band_channel_below
|
|
(atoi(argv[0]))) {
|
|
printf("ERR: For given primary channel secondary channel can not be set below\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[1]) &
|
|
BITMAP_CHANNEL_ABOVE) &&
|
|
!is_valid_a_band_channel_above
|
|
(atoi(argv[0]))) {
|
|
printf("ERR: For given primary channel secondary channel can not be set above\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case CHANNEL_EXT:
|
|
if (argc > 3) {
|
|
printf("ERR: Incorrect arguments for channel_ext.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (argc == 3) {
|
|
if ((ISDIGIT(argv[2]) == 0) ||
|
|
(atoi(argv[2]) & ~CHANNEL_MODE_MASK)) {
|
|
printf("ERR: Invalid Mode\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[2]) & BITMAP_ACS_MODE) &&
|
|
(atoi(argv[0]) != 0)) {
|
|
printf("ERR: Channel must be 0 for ACS; MODE = 1.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[2]) & BITMAP_CHANNEL_ABOVE) &&
|
|
(atoi(argv[2]) & BITMAP_CHANNEL_BELOW)) {
|
|
printf("ERR: secondary channel above and below both are enabled\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((argc == 2) &&
|
|
((ISDIGIT(argv[1]) == 0) || (atoi(argv[1]) < 0) ||
|
|
atoi(argv[1]) > 1)) {
|
|
printf("ERR:Invalid band\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((argc == 1) ||
|
|
((argc == 3) &&
|
|
!(atoi(argv[2]) & BITMAP_ACS_MODE))) {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < 1) ||
|
|
(atoi(argv[0]) > MAX_CHANNELS)) {
|
|
printf("ERR: Channel must be in the range of 1 to %d\n", MAX_CHANNELS);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[0]) > MAX_CHANNELS_BG) &&
|
|
!(is_valid_a_band_channel(atoi(argv[0])))) {
|
|
printf("ERR: Invalid Channel in 'a' band!\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
ch = atoi(argv[0]);
|
|
if (ch <= MAX_CHANNELS_BG) {
|
|
if ((argc == 3) &&
|
|
(atoi(argv[2]) &
|
|
BITMAP_CHANNEL_ABOVE) &&
|
|
(atoi(argv[0]) >
|
|
MAX_CHANNEL_ABOVE)) {
|
|
printf("ERR: only allow channel 1-9 for secondary channel above\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((argc == 3) &&
|
|
(atoi(argv[2]) &
|
|
BITMAP_CHANNEL_BELOW) &&
|
|
((atoi(argv[0]) < MIN_CHANNEL_BELOW)
|
|
|| (atoi(argv[0]) == 14))) {
|
|
printf("ERR: only allow channel 5-13 for secondary channel below\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
if (argc == 3) {
|
|
if ((atoi(argv[2]) &
|
|
BITMAP_CHANNEL_BELOW) &&
|
|
!is_valid_a_band_channel_below
|
|
(atoi(argv[0]))) {
|
|
printf("ERR: For given primary channel secondary channel can not be set below\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[2]) &
|
|
BITMAP_CHANNEL_ABOVE) &&
|
|
!is_valid_a_band_channel_above
|
|
(atoi(argv[0]))) {
|
|
printf("ERR: For given primary channel secondary channel can not be set above\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case BAND:
|
|
if (argc > 1) {
|
|
printf("ERR: Incorrect number of BAND arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1)) {
|
|
printf("ERR: Invalid band.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case RATE:
|
|
if (argc > MAX_RATES) {
|
|
printf("ERR: Incorrect number of RATES arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
for (i = 0; i < argc; i++) {
|
|
if ((IS_HEX_OR_DIGIT(argv[i]) == UAP_FAILURE) ||
|
|
(is_rate_valid
|
|
(A2HEXDECIMAL(argv[i]) &
|
|
~BASIC_RATE_SET_BIT)
|
|
!= UAP_SUCCESS)) {
|
|
printf("ERR:Unsupported rate.\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
if ((ret != UAP_FAILURE) &&
|
|
(has_dup_rate(argc, argv) != UAP_SUCCESS)) {
|
|
printf("ERR: Duplicate rate values entered\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if (check_mandatory_rates(argc, argv) != UAP_SUCCESS) {
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case BROADCASTSSID:
|
|
if (argc != 1) {
|
|
printf("ERR:wrong BROADCASTSSID arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
((atoi(argv[0]) != 0) && (atoi(argv[0]) != 1) &&
|
|
(atoi(argv[0]) != 2))) {
|
|
printf("ERR:Illegal parameter %s for BROADCASTSSID. Must be either '0', '1' or '2'.\n", argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case RTSTHRESH:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for RTSTHRESHOLD\n");
|
|
ret = UAP_FAILURE;
|
|
} else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > MAX_RTS_THRESHOLD)) {
|
|
printf("ERR:Illegal RTSTHRESHOLD %s. The value must between 0 and %d\n", argv[0], MAX_RTS_THRESHOLD);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
break;
|
|
case FRAGTHRESH:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for FRAGTHRESH\n");
|
|
ret = UAP_FAILURE;
|
|
} else if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < MIN_FRAG_THRESHOLD) ||
|
|
(atoi(argv[0]) > MAX_FRAG_THRESHOLD)) {
|
|
printf("ERR:Illegal FRAGTHRESH %s. The value must between %d and %d\n", argv[0], MIN_FRAG_THRESHOLD, MAX_FRAG_THRESHOLD);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
break;
|
|
case DTIMPERIOD:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for DTIMPERIOD\n");
|
|
ret = UAP_FAILURE;
|
|
} else if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 1) ||
|
|
(atoi(argv[0]) > MAX_DTIM_PERIOD)) {
|
|
printf("ERR: DTIMPERIOD Value must be in range of 1 to %d\n", MAX_DTIM_PERIOD);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
break;
|
|
case RSNREPLAYPROT:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for RSNREPLAYPROT\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1)) {
|
|
printf("ERR:Illegal RSNREPLAYPROT parameter %s. Must be either '0' or '1'.\n", argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case RADIOCONTROL:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for RADIOCONTROL\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1)) {
|
|
printf("ERR:Illegal RADIOCONTROL parameter %s. Must be either '0' or '1'.\n", argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case TXRATECFG:
|
|
if (argc > 3) {
|
|
printf("ERR:Incorrect number of arguments for DATARATE\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (((argc >= 1) &&
|
|
(IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE)) ||
|
|
((argc >= 2) &&
|
|
(IS_HEX_OR_DIGIT(argv[1]) == UAP_FAILURE))
|
|
|| ((argc >= 3) &&
|
|
(IS_HEX_OR_DIGIT(argv[2]) == UAP_FAILURE))
|
|
) {
|
|
printf("ERR: invalid Tx data rate\n");
|
|
ret = UAP_FAILURE;
|
|
} else if (argc >= 1) {
|
|
if (A2HEXDECIMAL(argv[0]) == 0xFF) {
|
|
if (argc != 1) {
|
|
printf("ERR: invalid auto rate input\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
} else {
|
|
if ((A2HEXDECIMAL(argv[0]) > 3)
|
|
) {
|
|
printf("ERR: invalid format\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if (argc >= 2) {
|
|
if (((A2HEXDECIMAL(argv[0]) ==
|
|
0) &&
|
|
(A2HEXDECIMAL(argv[1]) >
|
|
11)) ||
|
|
((A2HEXDECIMAL(argv[0]) ==
|
|
1) &&
|
|
(A2HEXDECIMAL(argv[1]) !=
|
|
32) &&
|
|
(A2HEXDECIMAL(argv[1]) >
|
|
15)
|
|
)) {
|
|
printf("ERR:Incorrect TxRate %s.\n", argv[1]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
if (argc == 3) {
|
|
if (((A2HEXDECIMAL(argv[0]) !=
|
|
2) &&
|
|
(A2HEXDECIMAL(argv[0]) !=
|
|
3)) ||
|
|
((A2HEXDECIMAL(argv[2]) < 1)
|
|
|| (A2HEXDECIMAL(argv[2]) >
|
|
2))) {
|
|
printf("ERR:Incorrect nss.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MCBCDATARATE:
|
|
case TXBEACONRATE:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for DATARATE\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (IS_HEX_OR_DIGIT(argv[0]) == UAP_FAILURE) {
|
|
printf("ERR: invalid data rate\n");
|
|
ret = UAP_FAILURE;
|
|
} else if ((A2HEXDECIMAL(argv[0]) != 0) &&
|
|
(is_rate_valid
|
|
(A2HEXDECIMAL(argv[0]) &
|
|
~BASIC_RATE_SET_BIT) != UAP_SUCCESS)) {
|
|
printf("ERR: invalid data rate\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case PKTFWD:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for PKTFWD.\n");
|
|
ret = UAP_FAILURE;
|
|
} else if ((ISDIGIT(argv[0]) == 0) ||
|
|
((atoi(argv[0]) < 0) || (atoi(argv[0]) > 15))) {
|
|
printf("ERR:Illegal PKTFWD parameter %s. Must be within '0' and '15'.\n", argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
break;
|
|
case STAAGEOUTTIMER:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for STAAGEOUTTIMER.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
|
|
((atoi(argv[0]) <
|
|
MIN_STAGE_OUT_TIME) ||
|
|
(atoi(argv[0]) >
|
|
MAX_STAGE_OUT_TIME))))
|
|
{
|
|
printf("ERR:Illegal STAAGEOUTTIMER %s. Must be between %d and %d.\n", argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case PSSTAAGEOUTTIMER:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for PSSTAAGEOUTTIMER.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
|
|
((atoi(argv[0]) <
|
|
MIN_STAGE_OUT_TIME) ||
|
|
(atoi(argv[0]) >
|
|
MAX_STAGE_OUT_TIME))))
|
|
{
|
|
printf("ERR:Illegal PSSTAAGEOUTTIMER %s. Must be between %d and %d.\n", argv[0], MIN_STAGE_OUT_TIME, MAX_STAGE_OUT_TIME);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case AUTHMODE:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for AUTHMODE\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || ((atoi(argv[0]) != 0) &&
|
|
(atoi(argv[0]) != 1)
|
|
&& (atoi(argv[0]) != 3)
|
|
&& (atoi(argv[0]) !=
|
|
255))) {
|
|
printf("ERR:Illegal AUTHMODE parameter %s. Must be either '0','1','3' or 255''.\n", argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case GROUPREKEYTIMER:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for GROUPREKEYTIMER.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > MAX_GRP_TIMER)) {
|
|
printf("ERR: GROUPREKEYTIMER range is [0:%d] (0 for disable)\n", MAX_GRP_TIMER);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case MAXSTANUM:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for MAXSTANUM\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) <= 0)) {
|
|
printf("ERR:Invalid STA_NUM argument %s.\n",
|
|
argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case BEACONPERIOD:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of argument for BEACONPERIOD.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < MIN_BEACON_PERIOD)
|
|
|| (atoi(argv[0]) > MAX_BEACON_PERIOD)) {
|
|
printf("ERR: BEACONPERIOD must be in range of %d to %d.\n", MIN_BEACON_PERIOD, MAX_BEACON_PERIOD);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case RETRYLIMIT:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for RETRY LIMIT\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) > MAX_RETRY_LIMIT) ||
|
|
(atoi(argv[0]) < 0)) {
|
|
printf("ERR:RETRY_LIMIT must be in the range of [0:%d]. The input was %s.\n", MAX_RETRY_LIMIT, argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case STICKYTIMCONFIG:
|
|
if ((argc != 1) && (argc != 3)) {
|
|
printf("ERR:Incorrect number of arguments for STICKY_TIM_CONFIG\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 2)) {
|
|
printf("ERR:Enable parameter must be 0, 1 or 2\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if (((atoi(argv[0]) != 1) && (argc > 1))) {
|
|
printf("ERR: Invalid arguments\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if ((atoi(argv[0]) == 1) && (argc != 3)) {
|
|
printf("ERR: Both duration and sticky bit mask must be provided for ENABLE = 1\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if (argc > 1) {
|
|
if ((ISDIGIT(argv[1]) == 0)) {
|
|
printf("ERR: Invalid duration\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
if ((ISDIGIT(argv[2]) == 0) ||
|
|
(atoi(argv[2]) < 1) ||
|
|
(atoi(argv[2]) > 3)) {
|
|
printf("ERR:Invalid sticky bit mask\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case STICKYTIMSTAMACADDR:
|
|
if ((argc != 1) && (argc != 2)) {
|
|
printf("ERR:Incorrect number of STICKY_TIM_STA_MAC_ADDR arguments\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((argc == 2) &&
|
|
((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1))) {
|
|
printf("ERR:Invalid control parameter\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case COEX2040CONFIG:
|
|
if (argc != 1) {
|
|
printf("ERR: Incorrect number of 2040 COEX CONFIG arguments\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1)) {
|
|
printf("ERR:Invalid enable parameter\n");
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case EAPOL_PWK_HSK:
|
|
if (argc != 2) {
|
|
printf("ERR:Incorrect number of EAPOL_PWK_HSK arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
|
|
|| (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) {
|
|
printf("ERR:Illegal parameters for EAPOL_PWK_HSK. Must be digits greater than equal to zero.\n");
|
|
}
|
|
}
|
|
break;
|
|
case EAPOL_GWK_HSK:
|
|
if (argc != 2) {
|
|
printf("ERR:Incorrect number of EAPOL_GWK_HSK arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (ISDIGIT(argv[1]) == 0)
|
|
|| (atoi(argv[0]) < 0) || (atoi(argv[1]) < 0)) {
|
|
printf("ERR:Illegal parameters for EAPOL_GWK_HSK. Must be digits greater than equal to zero.\n");
|
|
}
|
|
}
|
|
break;
|
|
case PREAMBLETYPE:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for PREAMBLE TYPE\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) > MAX_PREAMBLE_TYPE) ||
|
|
(atoi(argv[0]) < 0)) {
|
|
printf("ERR:PREAMBLE TYPE must be in the range of [0:%d]. The input was %s.\n", MAX_PREAMBLE_TYPE, argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case COEX_COMM_BITMAP:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of argument for Bitmap.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
/* Only bit 0 is supported now, hence check for 1 or 0 */
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) {
|
|
printf("ERR: Bitmap must have value of 1 or 0.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case COEX_COMM_AP_COEX:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of argument for APBTCoex.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((IS_HEX_OR_DIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) < 0) || (atoi(argv[0]) > 1)) {
|
|
printf("ERR: APBTCoex must have value of 1 or 0.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case COEX_SCO_ACL_FREQ:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for aclFrequency.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (ISDIGIT(argv[0]) == 0) {
|
|
printf("ERR: Incorrect value for aclFrequency.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case COEX_ACL_ENABLED:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for (acl) enabled.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || (atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) > 1)) {
|
|
printf("ERR: (acl) enabled must have value of 1 or 0.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case COEX_ACL_BT_TIME:
|
|
case COEX_ACL_WLAN_TIME:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for bt/wlan time.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (ISDIGIT(argv[0]) == 0) {
|
|
printf("ERR: Incorrect value for bt/wlan time.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case COEX_PROTECTION:
|
|
if (argc != 2) {
|
|
printf("ERR:Incorrect number of arguments for %s.\n",
|
|
argv[0]);
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if (ISDIGIT(argv[1]) == 0) {
|
|
printf("ERR: Incorrect value for %s.\n",
|
|
argv[0]);
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case PWK_CIPHER:
|
|
if ((argc != 1) && (argc != 2)) {
|
|
printf("ERR:Incorrect number of arguments for pwk_cipher.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) & ~PROTOCOL_BITMAP)) {
|
|
printf("Invalid Protocol paramter.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if (argc == 2) {
|
|
if ((ISDIGIT(argv[1]) == 0) ||
|
|
(atoi(argv[1]) & ~CIPHER_BITMAP)) {
|
|
printf("Invalid pairwise cipher.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case GWK_CIPHER:
|
|
if (argc != 1) {
|
|
printf("ERR:Incorrect number of arguments for gwk_cipher.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) ||
|
|
(atoi(argv[0]) & ~CIPHER_BITMAP) ||
|
|
(atoi(argv[0]) == AES_CCMP_TKIP)) {
|
|
printf("Invalid group cipher.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
case RESTRICT_CLIENT_MODE:
|
|
if ((argc != 1) && (argc != 2)) {
|
|
printf("ERR: Incorrect number of arguments.\n");
|
|
ret = UAP_FAILURE;
|
|
} else {
|
|
if ((ISDIGIT(argv[0]) == 0) || ((argc == 2) &&
|
|
((IS_HEX_OR_DIGIT
|
|
(argv[1]) == 0) ||
|
|
((atoi(argv[0]) < 0) ||
|
|
(atoi(argv[0]) >
|
|
1))))) {
|
|
printf("ERR: Invalid arguments\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((atoi(argv[0]) == 1) && (argc == 1)) {
|
|
printf("ERR: Mode_config parameter must be provided to enable this feature.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
if ((argc == 2) &&
|
|
(((A2HEXDECIMAL(argv[1]) << 8) != B_ONLY_MASK) &&
|
|
((A2HEXDECIMAL(argv[1]) << 8) != G_ONLY_MASK) &&
|
|
((A2HEXDECIMAL(argv[1]) << 8) != A_ONLY_MASK) &&
|
|
((A2HEXDECIMAL(argv[1]) << 8) != N_ONLY_MASK) &&
|
|
((A2HEXDECIMAL(argv[1]) << 8) != AC_ONLY_MASK))) {
|
|
printf("ERR: Exactly one mode can be enabled at a time.\n");
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
ret = UAP_FAILURE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Converts colon separated MAC address to hex value
|
|
*
|
|
* @param mac A pointer to the colon separated MAC string
|
|
* @param raw A pointer to the hex data buffer
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
* UAP_RET_MAC_BROADCAST - if broadcast mac
|
|
* UAP_RET_MAC_MULTICAST - if multicast mac
|
|
*/
|
|
int
|
|
mac2raw(char *mac, t_u8 *raw)
|
|
{
|
|
unsigned int temp_raw[ETH_ALEN];
|
|
int num_tokens = 0;
|
|
int i;
|
|
if (strlen(mac) != ((2 * ETH_ALEN) + (ETH_ALEN - 1))) {
|
|
return UAP_FAILURE;
|
|
}
|
|
num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x",
|
|
temp_raw + 0, temp_raw + 1, temp_raw + 2,
|
|
temp_raw + 3, temp_raw + 4, temp_raw + 5);
|
|
if (num_tokens != ETH_ALEN) {
|
|
return UAP_FAILURE;
|
|
}
|
|
for (i = 0; i < num_tokens; i++)
|
|
raw[i] = (t_u8)temp_raw[i];
|
|
|
|
if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
|
|
return UAP_RET_MAC_BROADCAST;
|
|
} else if (raw[0] & 0x01) {
|
|
return UAP_RET_MAC_MULTICAST;
|
|
}
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Converts a string to hex value
|
|
*
|
|
* @param str A pointer to the string
|
|
* @param raw A pointer to the raw data buffer
|
|
* @return Number of bytes read
|
|
*/
|
|
int
|
|
string2raw(char *str, unsigned char *raw)
|
|
{
|
|
int len = (strlen(str) + 1) / 2;
|
|
|
|
do {
|
|
if (!isxdigit(*str)) {
|
|
return -1;
|
|
}
|
|
*str = toupper(*str);
|
|
*raw = CHAR2INT(*str) << 4;
|
|
++str;
|
|
*str = toupper(*str);
|
|
if (*str == '\0')
|
|
break;
|
|
*raw |= CHAR2INT(*str);
|
|
++raw;
|
|
} while (*++str != '\0');
|
|
return len;
|
|
}
|
|
|
|
/**
|
|
* @brief Prints a MAC address in colon separated form from hex data
|
|
*
|
|
* @param raw A pointer to the hex data buffer
|
|
* @return N/A
|
|
*/
|
|
void
|
|
print_mac(t_u8 *raw)
|
|
{
|
|
printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
|
|
(unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
|
|
(unsigned int)raw[4], (unsigned int)raw[5]);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Check hex string
|
|
*
|
|
* @param hex A pointer to hex string
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
ishexstring(void *hex)
|
|
{
|
|
int i, a;
|
|
char *p = hex;
|
|
int len = strlen(p);
|
|
if (!strncasecmp("0x", p, 2)) {
|
|
p += 2;
|
|
len -= 2;
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
a = hex2num(*p);
|
|
if (a < 0)
|
|
return UAP_FAILURE;
|
|
p++;
|
|
}
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Show auth tlv
|
|
*
|
|
* @param tlv Pointer to auth tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_auth(tlvbuf_auth_mode *tlv)
|
|
{
|
|
switch (tlv->auth_mode) {
|
|
case 0:
|
|
printf("AUTHMODE = Open authentication\n");
|
|
break;
|
|
case 1:
|
|
printf("AUTHMODE = Shared key authentication\n");
|
|
break;
|
|
case 3:
|
|
printf("AUTHMODE = WPA3 SAE\n");
|
|
break;
|
|
case 255:
|
|
printf("AUTHMODE = Auto (open and shared key)\n");
|
|
break;
|
|
default:
|
|
printf("ERR: Invalid authmode=%d\n", tlv->auth_mode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief Show cipher tlv
|
|
*
|
|
* @param tlv Pointer to cipher tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_cipher(tlvbuf_cipher *tlv)
|
|
{
|
|
switch (tlv->pairwise_cipher) {
|
|
case CIPHER_TKIP:
|
|
printf("PairwiseCipher = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("PairwiseCipher = AES CCMP\n");
|
|
break;
|
|
case CIPHER_TKIP | CIPHER_AES_CCMP:
|
|
printf("PairwiseCipher = TKIP + AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("PairwiseCipher = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown Pairwise cipher 0x%x\n", tlv->pairwise_cipher);
|
|
break;
|
|
}
|
|
switch (tlv->group_cipher) {
|
|
case CIPHER_TKIP:
|
|
printf("GroupCipher = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("GroupCipher = AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("GroupCipher = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown Group cipher 0x%x\n", tlv->group_cipher);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Show pairwise cipher tlv
|
|
*
|
|
* @param tlv Pointer to pairwise cipher tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_pwk_cipher(tlvbuf_pwk_cipher *tlv)
|
|
{
|
|
switch (tlv->protocol) {
|
|
case PROTOCOL_WPA:
|
|
printf("Protocol WPA : ");
|
|
break;
|
|
case PROTOCOL_WPA2:
|
|
printf("Protocol WPA2 : ");
|
|
break;
|
|
case PROTOCOL_WPA3_SAE:
|
|
printf("Protocol WPA3_SAE : ");
|
|
break;
|
|
default:
|
|
printf("Unknown Protocol 0x%x\n", tlv->protocol);
|
|
break;
|
|
}
|
|
|
|
switch (tlv->pairwise_cipher) {
|
|
case CIPHER_TKIP:
|
|
printf("PairwiseCipher = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("PairwiseCipher = AES CCMP\n");
|
|
break;
|
|
case CIPHER_TKIP | CIPHER_AES_CCMP:
|
|
printf("PairwiseCipher = TKIP + AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("PairwiseCipher = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown Pairwise cipher 0x%x\n", tlv->pairwise_cipher);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Show group cipher tlv
|
|
*
|
|
* @param tlv Pointer to group cipher tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_gwk_cipher(tlvbuf_gwk_cipher *tlv)
|
|
{
|
|
switch (tlv->group_cipher) {
|
|
case CIPHER_TKIP:
|
|
printf("GroupCipher = TKIP\n");
|
|
break;
|
|
case CIPHER_AES_CCMP:
|
|
printf("GroupCipher = AES CCMP\n");
|
|
break;
|
|
case CIPHER_NONE:
|
|
printf("GroupCipher = None\n");
|
|
break;
|
|
default:
|
|
printf("Unknown Group cipher 0x%x\n", tlv->group_cipher);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Show mac filter tlv
|
|
*
|
|
* @param tlv Pointer to filter tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_mac_filter(tlvbuf_sta_mac_addr_filter *tlv)
|
|
{
|
|
int i;
|
|
switch (tlv->filter_mode) {
|
|
case 0:
|
|
printf("Filter Mode = Filter table is disabled\n");
|
|
return;
|
|
case 1:
|
|
if (!tlv->count) {
|
|
printf("No mac address is allowed to connect\n");
|
|
} else {
|
|
printf("Filter Mode = Allow mac address specified in the allowed list\n");
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!tlv->count) {
|
|
printf("No mac address is blocked\n");
|
|
} else {
|
|
printf("Filter Mode = Block MAC addresses specified in the banned list\n");
|
|
}
|
|
break;
|
|
}
|
|
for (i = 0; i < tlv->count; i++) {
|
|
printf("MAC_%d = ", i);
|
|
print_mac(&tlv->mac_address[i * ETH_ALEN]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Show rate tlv
|
|
*
|
|
* @param tlv Pointer to rate tlv
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_rate(tlvbuf_rates *tlv)
|
|
{
|
|
int flag = 0;
|
|
int i;
|
|
t_u16 tlv_len;
|
|
|
|
tlv_len = *(t_u8 *)&tlv->length;
|
|
tlv_len |= (*((t_u8 *)&tlv->length + 1) << 8);
|
|
|
|
printf("Basic Rates =");
|
|
for (i = 0; i < tlv_len; i++) {
|
|
if (tlv->operational_rates[i] > (BASIC_RATE_SET_BIT - 1)) {
|
|
flag = flag ? : 1;
|
|
printf(" 0x%x", tlv->operational_rates[i]);
|
|
}
|
|
}
|
|
printf("%s\nNon-Basic Rates =", flag ? "" : " ( none ) ");
|
|
for (flag = 0, i = 0; i < tlv_len; i++) {
|
|
if (tlv->operational_rates[i] < BASIC_RATE_SET_BIT) {
|
|
flag = flag ? : 1;
|
|
printf(" 0x%x", tlv->operational_rates[i]);
|
|
}
|
|
}
|
|
printf("%s\n", flag ? "" : " ( none ) ");
|
|
}
|
|
|
|
/**
|
|
* @brief Show all the tlv in the buf
|
|
*
|
|
* @param buf Pointer to tlv buffer
|
|
* @param len Tlv buffer len
|
|
*
|
|
* $return N/A
|
|
*/
|
|
void
|
|
print_tlv(t_u8 *buf, t_u16 len)
|
|
{
|
|
tlvbuf_header *pcurrent_tlv = (tlvbuf_header *)buf;
|
|
int tlv_buf_left = len;
|
|
t_u16 tlv_type;
|
|
t_u16 tlv_len;
|
|
t_u16 tlv_val_16;
|
|
t_u32 tlv_val_32;
|
|
t_u8 ssid[33];
|
|
int i = 0;
|
|
tlvbuf_ap_mac_address *mac_tlv;
|
|
tlvbuf_ssid *ssid_tlv;
|
|
tlvbuf_beacon_period *beacon_tlv;
|
|
tlvbuf_dtim_period *dtim_tlv;
|
|
tlvbuf_rates *rates_tlv;
|
|
tlvbuf_tx_power *txpower_tlv;
|
|
tlvbuf_bcast_ssid_ctl *bcast_tlv;
|
|
tlvbuf_preamble_ctl *preamble_tlv;
|
|
tlvbuf_bss_status *bss_status_tlv;
|
|
tlvbuf_rts_threshold *rts_tlv;
|
|
tlvbuf_mcbc_data_rate *mcbcrate_tlv;
|
|
tlvbuf_pkt_fwd_ctl *pkt_fwd_tlv;
|
|
tlvbuf_sta_ageout_timer *ageout_tlv;
|
|
tlvbuf_ps_sta_ageout_timer *ps_ageout_tlv;
|
|
tlvbuf_auth_mode *auth_tlv;
|
|
tlvbuf_protocol *proto_tlv;
|
|
tlvbuf_akmp *akmp_tlv;
|
|
tlvbuf_cipher *cipher_tlv;
|
|
tlvbuf_pwk_cipher *pwk_cipher_tlv;
|
|
tlvbuf_gwk_cipher *gwk_cipher_tlv;
|
|
tlvbuf_group_rekey_timer *rekey_tlv;
|
|
tlvbuf_wpa_passphrase *psk_tlv;
|
|
tlvbuf_coex_common_cfg *coex_common_tlv;
|
|
tlvbuf_coex_sco_cfg *coex_sco_tlv;
|
|
tlvbuf_coex_acl_cfg *coex_acl_tlv;
|
|
tlvbuf_coex_stats *coex_stats_tlv;
|
|
tlvbuf_wep_key *wep_tlv;
|
|
tlvbuf_frag_threshold *frag_tlv;
|
|
tlvbuf_sta_mac_addr_filter *filter_tlv;
|
|
tlvbuf_max_sta_num *max_sta_tlv;
|
|
tlvbuf_retry_limit *retry_limit_tlv;
|
|
tlvbuf_eapol_pwk_hsk_timeout *pwk_timeout_tlv;
|
|
tlvbuf_eapol_pwk_hsk_retries *pwk_retries_tlv;
|
|
tlvbuf_eapol_gwk_hsk_timeout *gwk_timeout_tlv;
|
|
tlvbuf_eapol_gwk_hsk_retries *gwk_retries_tlv;
|
|
tlvbuf_channel_config *channel_tlv;
|
|
tlvbuf_channel_list *chnlist_tlv;
|
|
channel_list *pchan_list;
|
|
t_u16 custom_ie_len;
|
|
tlvbuf_rsn_replay_prot *replay_prot_tlv;
|
|
tlvbuf_custom_ie *custom_ie_tlv;
|
|
custom_ie *custom_ie_ptr;
|
|
tlvbuf_max_mgmt_ie *max_mgmt_ie_tlv;
|
|
tlvbuf_wmm_para_t *wmm_para_tlv;
|
|
int flag = 0;
|
|
tlvbuf_htcap_t *ht_cap_tlv;
|
|
tlvbuf_htinfo_t *ht_info_tlv;
|
|
tlvbuf_2040_coex *coex_2040_tlv;
|
|
|
|
#ifdef RX_PACKET_COALESCE
|
|
tlvbuf_rx_pkt_coal_t *rx_pkt_coal_tlv;
|
|
#endif
|
|
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "tlv total len=%d\n", len);
|
|
#endif
|
|
while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
|
|
tlv_type = *(t_u8 *)&pcurrent_tlv->type;
|
|
tlv_type |= (*((t_u8 *)&pcurrent_tlv->type + 1) << 8);
|
|
tlv_len = *(t_u8 *)&pcurrent_tlv->len;
|
|
tlv_len |= (*((t_u8 *)&pcurrent_tlv->len + 1) << 8);
|
|
if ((sizeof(tlvbuf_header) + tlv_len) >
|
|
(unsigned int)tlv_buf_left) {
|
|
printf("wrong tlv: tlv_len=%d, tlv_buf_left=%d\n",
|
|
tlv_len, tlv_buf_left);
|
|
break;
|
|
}
|
|
switch (tlv_type) {
|
|
case MRVL_AP_MAC_ADDRESS_TLV_ID:
|
|
mac_tlv = (tlvbuf_ap_mac_address *)pcurrent_tlv;
|
|
printf("AP MAC address = ");
|
|
print_mac(mac_tlv->ap_mac_addr);
|
|
printf("\n");
|
|
break;
|
|
case MRVL_SSID_TLV_ID:
|
|
memset(ssid, 0, sizeof(ssid));
|
|
ssid_tlv = (tlvbuf_ssid *)pcurrent_tlv;
|
|
|
|
strncpy((char *)ssid, (char *)ssid_tlv->ssid,
|
|
sizeof(ssid) - 1);
|
|
|
|
printf("SSID = %s\n", ssid);
|
|
break;
|
|
case MRVL_BEACON_PERIOD_TLV_ID:
|
|
beacon_tlv = (tlvbuf_beacon_period *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&beacon_tlv->beacon_period_ms;
|
|
tlv_val_16 |=
|
|
(*((t_u8 *)&beacon_tlv->beacon_period_ms + 1) <<
|
|
8);
|
|
printf("Beacon period = %d\n", tlv_val_16);
|
|
break;
|
|
case MRVL_DTIM_PERIOD_TLV_ID:
|
|
dtim_tlv = (tlvbuf_dtim_period *)pcurrent_tlv;
|
|
printf("DTIM period = %d\n", dtim_tlv->dtim_period);
|
|
break;
|
|
case MRVL_CHANNELCONFIG_TLV_ID:
|
|
channel_tlv = (tlvbuf_channel_config *)pcurrent_tlv;
|
|
printf("Channel = %d\n", channel_tlv->chan_number);
|
|
printf("Band = %s\n",
|
|
(channel_tlv->bandcfg.chanBand ==
|
|
BAND_5GHZ) ? "5GHz" : "2.4GHz");
|
|
printf("Channel Select Mode = %s\n",
|
|
(channel_tlv->bandcfg.scanMode ==
|
|
SCAN_MODE_ACS) ? "ACS" : "Manual");
|
|
if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
|
|
printf("no secondary channel\n");
|
|
else if (channel_tlv->bandcfg.chan2Offset ==
|
|
SEC_CHAN_ABOVE)
|
|
printf("secondary channel is above primary channel\n");
|
|
else if (channel_tlv->bandcfg.chan2Offset ==
|
|
SEC_CHAN_BELOW)
|
|
printf("secondary channel is below primary channel\n");
|
|
break;
|
|
case MRVL_CHANNELLIST_TLV_ID:
|
|
chnlist_tlv = (tlvbuf_channel_list *)pcurrent_tlv;
|
|
printf("Channels List = ");
|
|
pchan_list =
|
|
(channel_list *) & (chnlist_tlv->chan_list);
|
|
if (tlv_len % sizeof(channel_list)) {
|
|
break;
|
|
}
|
|
for (i = 0;
|
|
(unsigned int)i < (tlv_len / 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");
|
|
break;
|
|
case MRVL_RSN_REPLAY_PROT_TLV_ID:
|
|
replay_prot_tlv =
|
|
(tlvbuf_rsn_replay_prot *)pcurrent_tlv;
|
|
printf("RSN replay protection = %s\n",
|
|
replay_prot_tlv->
|
|
rsn_replay_prot ? "enabled" : "disabled");
|
|
break;
|
|
case MRVL_RATES_TLV_ID:
|
|
rates_tlv = (tlvbuf_rates *)pcurrent_tlv;
|
|
print_rate(rates_tlv);
|
|
break;
|
|
case MRVL_TX_POWER_TLV_ID:
|
|
txpower_tlv = (tlvbuf_tx_power *)pcurrent_tlv;
|
|
printf("Tx power = %d dBm\n",
|
|
txpower_tlv->tx_power_dbm);
|
|
break;
|
|
case MRVL_BCAST_SSID_CTL_TLV_ID:
|
|
bcast_tlv = (tlvbuf_bcast_ssid_ctl *)pcurrent_tlv;
|
|
printf("SSID broadcast = %s\n",
|
|
(bcast_tlv->bcast_ssid_ctl ==
|
|
1) ? "enabled" : "disabled");
|
|
break;
|
|
case MRVL_PREAMBLE_CTL_TLV_ID:
|
|
preamble_tlv = (tlvbuf_preamble_ctl *)pcurrent_tlv;
|
|
printf("Preamble type = %s\n",
|
|
(preamble_tlv->preamble_type ==
|
|
0) ? "auto" : ((preamble_tlv->preamble_type ==
|
|
1) ? "short" : "long"));
|
|
break;
|
|
case MRVL_BSS_STATUS_TLV_ID:
|
|
bss_status_tlv = (tlvbuf_bss_status *)pcurrent_tlv;
|
|
printf("BSS status = %s\n",
|
|
(bss_status_tlv->bss_status ==
|
|
0) ? "stopped" : "started");
|
|
break;
|
|
case MRVL_RTS_THRESHOLD_TLV_ID:
|
|
rts_tlv = (tlvbuf_rts_threshold *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&rts_tlv->rts_threshold;
|
|
tlv_val_16 |=
|
|
(*((t_u8 *)&rts_tlv->rts_threshold + 1) << 8);
|
|
printf("RTS threshold = %d\n", tlv_val_16);
|
|
break;
|
|
case MRVL_FRAG_THRESHOLD_TLV_ID:
|
|
frag_tlv = (tlvbuf_frag_threshold *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&frag_tlv->frag_threshold;
|
|
tlv_val_16 |=
|
|
(*((t_u8 *)&frag_tlv->frag_threshold + 1) << 8);
|
|
printf("Fragmentation threshold = %d\n", tlv_val_16);
|
|
break;
|
|
case MRVL_MCBC_DATA_RATE_TLV_ID:
|
|
mcbcrate_tlv = (tlvbuf_mcbc_data_rate *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&mcbcrate_tlv->mcbc_datarate;
|
|
tlv_val_16 |=
|
|
(*((t_u8 *)&mcbcrate_tlv->mcbc_datarate + 1) <<
|
|
8);
|
|
if (mcbcrate_tlv->mcbc_datarate == 0)
|
|
printf("MCBC data rate = auto\n");
|
|
else
|
|
printf("MCBC data rate = 0x%x\n", tlv_val_16);
|
|
break;
|
|
case MRVL_PKT_FWD_CTL_TLV_ID:
|
|
pkt_fwd_tlv = (tlvbuf_pkt_fwd_ctl *)pcurrent_tlv;
|
|
printf("%s handles packet forwarding -\n",
|
|
((pkt_fwd_tlv->pkt_fwd_ctl & PKT_FWD_FW_BIT) ==
|
|
0) ? "Host" : "Firmware");
|
|
printf("\tIntra-BSS broadcast packets are %s\n",
|
|
((pkt_fwd_tlv->
|
|
pkt_fwd_ctl & PKT_FWD_INTRA_BCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
printf("\tIntra-BSS unicast packets are %s\n",
|
|
((pkt_fwd_tlv->
|
|
pkt_fwd_ctl & PKT_FWD_INTRA_UCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
printf("\tInter-BSS unicast packets are %s\n",
|
|
((pkt_fwd_tlv->
|
|
pkt_fwd_ctl & PKT_FWD_INTER_UCAST) ==
|
|
0) ? "allowed" : "denied");
|
|
break;
|
|
case MRVL_STA_AGEOUT_TIMER_TLV_ID:
|
|
ageout_tlv = (tlvbuf_sta_ageout_timer *)pcurrent_tlv;
|
|
tlv_val_32 = *(t_u8 *)&ageout_tlv->sta_ageout_timer_ms;
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 1)
|
|
<< 8);
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 2)
|
|
<< 16);
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&ageout_tlv->sta_ageout_timer_ms + 3)
|
|
<< 24);
|
|
printf("STA ageout timer = %d\n", (int)tlv_val_32);
|
|
break;
|
|
case MRVL_PS_STA_AGEOUT_TIMER_TLV_ID:
|
|
ps_ageout_tlv =
|
|
(tlvbuf_ps_sta_ageout_timer *)pcurrent_tlv;
|
|
tlv_val_32 =
|
|
*(t_u8 *)&ps_ageout_tlv->ps_sta_ageout_timer_ms;
|
|
tlv_val_32 |=
|
|
(*
|
|
((t_u8 *)&ps_ageout_tlv->
|
|
ps_sta_ageout_timer_ms + 1) << 8);
|
|
tlv_val_32 |=
|
|
(*
|
|
((t_u8 *)&ps_ageout_tlv->
|
|
ps_sta_ageout_timer_ms + 2) << 16);
|
|
tlv_val_32 |=
|
|
(*
|
|
((t_u8 *)&ps_ageout_tlv->
|
|
ps_sta_ageout_timer_ms + 3) << 24);
|
|
printf("PS STA ageout timer = %d\n", (int)tlv_val_32);
|
|
break;
|
|
case MRVL_AUTH_TLV_ID:
|
|
auth_tlv = (tlvbuf_auth_mode *)pcurrent_tlv;
|
|
print_auth(auth_tlv);
|
|
break;
|
|
case MRVL_PROTOCOL_TLV_ID:
|
|
proto_tlv = (tlvbuf_protocol *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&proto_tlv->protocol;
|
|
tlv_val_16 |=
|
|
(*((t_u8 *)&proto_tlv->protocol + 1) << 8);
|
|
print_protocol(tlv_val_16);
|
|
break;
|
|
case MRVL_AKMP_TLV_ID:
|
|
akmp_tlv = (tlvbuf_akmp *)pcurrent_tlv;
|
|
tlv_val_16 = *(t_u8 *)&akmp_tlv->key_mgmt;
|
|
tlv_val_16 |= (*((t_u8 *)&akmp_tlv->key_mgmt + 1) << 8);
|
|
if (tlv_val_16 & (KEY_MGMT_PSK | KEY_MGMT_PSK_SHA256)) {
|
|
if (tlv_val_16 & KEY_MGMT_PSK)
|
|
printf("KeyMgmt = PSK\n");
|
|
if (tlv_val_16 & KEY_MGMT_PSK_SHA256)
|
|
printf("KeyMgmt = PSK_SHA256\n");
|
|
tlv_val_16 =
|
|
*(t_u8 *)&akmp_tlv->key_mgmt_operation;
|
|
if (tlv_len > sizeof(t_u16)) {
|
|
tlv_val_16 |=
|
|
(*
|
|
((t_u8 *)&akmp_tlv->
|
|
key_mgmt_operation + 1) << 8);
|
|
printf("Key Exchange on : %s.\n",
|
|
(tlv_val_16 & 0x01) ? "Host" :
|
|
"Device");
|
|
printf("1x Authentication on : %s.\n",
|
|
(tlv_val_16 & 0x10) ? "Host" :
|
|
"Device");
|
|
}
|
|
}
|
|
if (tlv_val_16 & KEY_MGMT_EAP)
|
|
printf("KeyMgmt = EAP");
|
|
if (tlv_val_16 & KEY_MGMT_NONE)
|
|
printf("KeyMgmt = NONE");
|
|
break;
|
|
case MRVL_CIPHER_TLV_ID:
|
|
cipher_tlv = (tlvbuf_cipher *)pcurrent_tlv;
|
|
print_cipher(cipher_tlv);
|
|
break;
|
|
case MRVL_CIPHER_PWK_TLV_ID:
|
|
pwk_cipher_tlv = (tlvbuf_pwk_cipher *)pcurrent_tlv;
|
|
pwk_cipher_tlv->protocol =
|
|
uap_le16_to_cpu(pwk_cipher_tlv->protocol);
|
|
print_pwk_cipher(pwk_cipher_tlv);
|
|
break;
|
|
case MRVL_CIPHER_GWK_TLV_ID:
|
|
gwk_cipher_tlv = (tlvbuf_gwk_cipher *)pcurrent_tlv;
|
|
print_gwk_cipher(gwk_cipher_tlv);
|
|
break;
|
|
case MRVL_GRP_REKEY_TIME_TLV_ID:
|
|
rekey_tlv = (tlvbuf_group_rekey_timer *)pcurrent_tlv;
|
|
tlv_val_32 = *(t_u8 *)&rekey_tlv->group_rekey_time_sec;
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 1)
|
|
<< 8);
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 2)
|
|
<< 16);
|
|
tlv_val_32 |=
|
|
(*((t_u8 *)&rekey_tlv->group_rekey_time_sec + 3)
|
|
<< 24);
|
|
if (tlv_val_32 == 0)
|
|
printf("Group re-key time = disabled\n");
|
|
else
|
|
printf("Group re-key time = %d second\n",
|
|
tlv_val_32);
|
|
break;
|
|
case MRVL_WPA_PASSPHRASE_TLV_ID:
|
|
psk_tlv = (tlvbuf_wpa_passphrase *)pcurrent_tlv;
|
|
if (tlv_len > 0) {
|
|
printf("WPA passphrase = ");
|
|
for (i = 0; i < tlv_len; i++)
|
|
printf("%c", psk_tlv->passphrase[i]);
|
|
printf("\n");
|
|
} else
|
|
printf("WPA passphrase = None\n");
|
|
break;
|
|
case MRVL_WEP_KEY_TLV_ID:
|
|
wep_tlv = (tlvbuf_wep_key *)pcurrent_tlv;
|
|
print_wep_key(wep_tlv);
|
|
break;
|
|
case MRVL_STA_MAC_ADDR_FILTER_TLV_ID:
|
|
filter_tlv = (tlvbuf_sta_mac_addr_filter *)pcurrent_tlv;
|
|
print_mac_filter(filter_tlv);
|
|
break;
|
|
case MRVL_MAX_STA_CNT_TLV_ID:
|
|
max_sta_tlv = (tlvbuf_max_sta_num *)pcurrent_tlv;
|
|
tlv_val_16 =
|
|
*(t_u8 *)&max_sta_tlv->max_sta_num_configured;
|
|
tlv_val_16 |=
|
|
(*
|
|
((t_u8 *)&max_sta_tlv->max_sta_num_configured +
|
|
1) << 8);
|
|
printf("Max Station Number configured = %d\n",
|
|
tlv_val_16);
|
|
if (max_sta_tlv->length == 4) {
|
|
tlv_val_16 =
|
|
*(t_u8 *)&max_sta_tlv->
|
|
max_sta_num_supported;
|
|
tlv_val_16 |=
|
|
(*
|
|
((t_u8 *)&max_sta_tlv->
|
|
max_sta_num_supported + 1) << 8);
|
|
printf("Max Station Number supported = %d\n",
|
|
tlv_val_16);
|
|
}
|
|
break;
|
|
case MRVL_RETRY_LIMIT_TLV_ID:
|
|
retry_limit_tlv = (tlvbuf_retry_limit *)pcurrent_tlv;
|
|
printf("Retry Limit = %d\n",
|
|
retry_limit_tlv->retry_limit);
|
|
break;
|
|
case MRVL_EAPOL_PWK_HSK_TIMEOUT_TLV_ID:
|
|
pwk_timeout_tlv =
|
|
(tlvbuf_eapol_pwk_hsk_timeout *)pcurrent_tlv;
|
|
pwk_timeout_tlv->pairwise_update_timeout =
|
|
uap_le32_to_cpu(pwk_timeout_tlv->
|
|
pairwise_update_timeout);
|
|
printf("Pairwise handshake timeout = %d\n",
|
|
pwk_timeout_tlv->pairwise_update_timeout);
|
|
break;
|
|
case MRVL_EAPOL_PWK_HSK_RETRIES_TLV_ID:
|
|
pwk_retries_tlv =
|
|
(tlvbuf_eapol_pwk_hsk_retries *)pcurrent_tlv;
|
|
pwk_retries_tlv->pwk_retries =
|
|
uap_le32_to_cpu(pwk_retries_tlv->pwk_retries);
|
|
printf("Pairwise handshake retries = %d\n",
|
|
pwk_retries_tlv->pwk_retries);
|
|
break;
|
|
case MRVL_EAPOL_GWK_HSK_TIMEOUT_TLV_ID:
|
|
gwk_timeout_tlv =
|
|
(tlvbuf_eapol_gwk_hsk_timeout *)pcurrent_tlv;
|
|
gwk_timeout_tlv->groupwise_update_timeout =
|
|
uap_le32_to_cpu(gwk_timeout_tlv->
|
|
groupwise_update_timeout);
|
|
printf("Groupwise handshake timeout = %d\n",
|
|
gwk_timeout_tlv->groupwise_update_timeout);
|
|
break;
|
|
case MRVL_EAPOL_GWK_HSK_RETRIES_TLV_ID:
|
|
gwk_retries_tlv =
|
|
(tlvbuf_eapol_gwk_hsk_retries *)pcurrent_tlv;
|
|
gwk_retries_tlv->gwk_retries =
|
|
uap_le32_to_cpu(gwk_retries_tlv->gwk_retries);
|
|
printf("Groupwise handshake retries = %d\n",
|
|
gwk_retries_tlv->gwk_retries);
|
|
break;
|
|
case MRVL_MGMT_IE_LIST_TLV_ID:
|
|
custom_ie_tlv = (tlvbuf_custom_ie *)pcurrent_tlv;
|
|
custom_ie_len = tlv_len;
|
|
custom_ie_ptr = (custom_ie *)(custom_ie_tlv->ie_data);
|
|
while (custom_ie_len >= sizeof(custom_ie)) {
|
|
custom_ie_ptr->ie_index =
|
|
uap_le16_to_cpu(custom_ie_ptr->
|
|
ie_index);
|
|
custom_ie_ptr->ie_length =
|
|
uap_le16_to_cpu(custom_ie_ptr->
|
|
ie_length);
|
|
custom_ie_ptr->mgmt_subtype_mask =
|
|
uap_le16_to_cpu(custom_ie_ptr->
|
|
mgmt_subtype_mask);
|
|
printf("Index [%d]\n", custom_ie_ptr->ie_index);
|
|
if (custom_ie_ptr->ie_length)
|
|
printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask == 0 ? UAP_CUSTOM_IE_AUTO_MASK : custom_ie_ptr->mgmt_subtype_mask);
|
|
else
|
|
printf("Management Subtype Mask = 0x%02x\n", custom_ie_ptr->mgmt_subtype_mask);
|
|
hexdump_data("IE Buffer",
|
|
(void *)custom_ie_ptr->ie_buffer,
|
|
(custom_ie_ptr->ie_length), ' ');
|
|
custom_ie_len -=
|
|
sizeof(custom_ie) +
|
|
custom_ie_ptr->ie_length;
|
|
custom_ie_ptr =
|
|
(custom_ie *)((t_u8 *)custom_ie_ptr +
|
|
sizeof(custom_ie) +
|
|
custom_ie_ptr->ie_length);
|
|
}
|
|
custom_ie_present = 1;
|
|
break;
|
|
case MRVL_MAX_MGMT_IE_TLV_ID:
|
|
max_mgmt_ie_tlv = (tlvbuf_max_mgmt_ie *)pcurrent_tlv;
|
|
max_mgmt_ie_tlv->count =
|
|
uap_le16_to_cpu(max_mgmt_ie_tlv->count);
|
|
for (i = 0; i < max_mgmt_ie_tlv->count; i++) {
|
|
max_mgmt_ie_tlv->info[i].buf_size =
|
|
uap_le16_to_cpu(max_mgmt_ie_tlv->
|
|
info[i].buf_size);
|
|
max_mgmt_ie_tlv->info[i].buf_count =
|
|
uap_le16_to_cpu(max_mgmt_ie_tlv->
|
|
info[i].buf_count);
|
|
printf("buf%d_size = %d\n", i,
|
|
max_mgmt_ie_tlv->info[i].buf_size);
|
|
printf("number of buffers = %d\n",
|
|
max_mgmt_ie_tlv->info[i].buf_count);
|
|
printf("\n");
|
|
}
|
|
max_mgmt_ie_print = 1;
|
|
break;
|
|
case MRVL_BT_COEX_COMMON_CFG_TLV_ID:
|
|
printf("Coex common configuration:\n");
|
|
coex_common_tlv =
|
|
(tlvbuf_coex_common_cfg *)pcurrent_tlv;
|
|
printf("\tConfig Bitmap = 0x%02x\n",
|
|
uap_le32_to_cpu(coex_common_tlv->config_bitmap));
|
|
printf("\tAP Coex Enabled = %d\n",
|
|
uap_le32_to_cpu(coex_common_tlv->ap_bt_coex));
|
|
break;
|
|
|
|
case MRVL_BT_COEX_SCO_CFG_TLV_ID:
|
|
printf("Coex sco configuration:\n");
|
|
coex_sco_tlv = (tlvbuf_coex_sco_cfg *)pcurrent_tlv;
|
|
for (i = 0; i < 4; i++)
|
|
printf("\tQtime protection [%d] = %d usecs\n",
|
|
i,
|
|
uap_le16_to_cpu(coex_sco_tlv->
|
|
protection_qtime[i]));
|
|
printf("\tProtection frame rate = %d\n",
|
|
uap_le16_to_cpu(coex_sco_tlv->protection_rate));
|
|
printf("\tACL frequency = %d\n",
|
|
uap_le16_to_cpu(coex_sco_tlv->acl_frequency));
|
|
break;
|
|
|
|
case MRVL_BT_COEX_ACL_CFG_TLV_ID:
|
|
printf("Coex acl configuration: ");
|
|
coex_acl_tlv = (tlvbuf_coex_acl_cfg *)pcurrent_tlv;
|
|
coex_acl_tlv->enabled =
|
|
uap_le16_to_cpu(coex_acl_tlv->enabled);
|
|
printf("%s\n",
|
|
(coex_acl_tlv->
|
|
enabled) ? "enabled" : "disabled");
|
|
if (coex_acl_tlv->enabled) {
|
|
printf("\tBT time = %d usecs\n",
|
|
uap_le16_to_cpu(coex_acl_tlv->bt_time));
|
|
printf("\tWLan time = %d usecs\n",
|
|
uap_le16_to_cpu(coex_acl_tlv->
|
|
wlan_time));
|
|
printf("\tProtection frame rate = %d\n",
|
|
uap_le16_to_cpu(coex_acl_tlv->
|
|
protection_rate));
|
|
}
|
|
break;
|
|
|
|
case MRVL_BT_COEX_STATS_TLV_ID:
|
|
printf("Coex statistics: \n");
|
|
coex_stats_tlv = (tlvbuf_coex_stats *)pcurrent_tlv;
|
|
printf("\tNull not sent = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->null_not_sent));
|
|
printf("\tNull queued = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->null_queued));
|
|
printf("\tNull not queued = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->
|
|
null_not_queued));
|
|
printf("\tCF End queued = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->cf_end_queued));
|
|
printf("\tCF End not queued = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->
|
|
cf_end_not_queued));
|
|
printf("\tNull allocation failures = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->
|
|
null_alloc_fail));
|
|
printf("\tCF End allocation failures = %d\n",
|
|
uap_le32_to_cpu(coex_stats_tlv->
|
|
cf_end_alloc_fail));
|
|
break;
|
|
case HT_CAPABILITY_TLV_ID:
|
|
printf("\nHT Capability Info: \n");
|
|
ht_cap_tlv = (tlvbuf_htcap_t *)pcurrent_tlv;
|
|
if (!ht_cap_tlv->ht_cap.supported_mcs_set[0]) {
|
|
printf("802.11n is disabled\n");
|
|
} else {
|
|
printf("802.11n is enabled\n");
|
|
printf("ht_cap_info=0x%x, ampdu_param=0x%x tx_bf_cap=%#x\n", uap_le16_to_cpu(ht_cap_tlv->ht_cap.ht_cap_info), ht_cap_tlv->ht_cap.ampdu_param, uap_le32_to_cpu(ht_cap_tlv->ht_cap.tx_bf_cap));
|
|
printf("supported MCS set:\n");
|
|
for (i = 0; i < MCS_SET_LEN; i++) {
|
|
printf("0x%x ",
|
|
ht_cap_tlv->ht_cap.
|
|
supported_mcs_set[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
break;
|
|
case HT_INFO_TLV_ID:
|
|
ht_info_tlv = (tlvbuf_htinfo_t *)pcurrent_tlv;
|
|
if (ht_info_tlv->length) {
|
|
printf("\nHT Information Element: \n");
|
|
printf("Primary channel = %d\n",
|
|
ht_info_tlv->ht_info.pri_chan);
|
|
printf("Secondary channel offset = %d\n",
|
|
(int)GET_SECONDARY_CHAN(ht_info_tlv->
|
|
ht_info.field2));
|
|
printf("STA channel width = %dMHz\n",
|
|
IS_CHANNEL_WIDTH_40(ht_info_tlv->ht_info.
|
|
field2) ? 40 : 20);
|
|
printf("RIFS %s\n",
|
|
IS_RIFS_ALLOWED(ht_info_tlv->ht_info.
|
|
field2) ? "Allowed" :
|
|
"Prohibited");
|
|
ht_info_tlv->ht_info.field3 =
|
|
uap_le16_to_cpu(ht_info_tlv->ht_info.
|
|
field3);
|
|
ht_info_tlv->ht_info.field4 =
|
|
uap_le16_to_cpu(ht_info_tlv->ht_info.
|
|
field4);
|
|
printf("HT Protection = %d\n",
|
|
(int)GET_HT_PROTECTION(ht_info_tlv->
|
|
ht_info.field3));
|
|
printf("Non-Greenfield HT STAs present: %s\n",
|
|
NONGF_STA_PRESENT(ht_info_tlv->ht_info.
|
|
field3) ? "Yes" :
|
|
"No");
|
|
printf("OBSS Non-HT STAs present: %s\n",
|
|
OBSS_NONHT_STA_PRESENT(ht_info_tlv->
|
|
ht_info.
|
|
field3) ? "Yes" :
|
|
"No");
|
|
for (i = 0; i < MCS_SET_LEN; i++) {
|
|
if (ht_info_tlv->ht_info.
|
|
basic_mcs_set[i]) {
|
|
printf("Basic_mcs_set: \n");
|
|
flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (flag) {
|
|
for (i = 0; i < MCS_SET_LEN; i++)
|
|
printf("%x ",
|
|
ht_info_tlv->ht_info.
|
|
basic_mcs_set[i]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
break;
|
|
case MRVL_2040_BSS_COEX_CONTROL_TLV_ID:
|
|
coex_2040_tlv = (tlvbuf_2040_coex *)pcurrent_tlv;
|
|
printf("20/40 coex = %s\n",
|
|
(coex_2040_tlv->
|
|
enable) ? "enabled" : "disabled");
|
|
break;
|
|
case VENDOR_SPECIFIC_IE_TLV_ID:
|
|
wmm_para_tlv = (tlvbuf_wmm_para_t *)pcurrent_tlv;
|
|
printf("wmm parameters:\n");
|
|
printf("\tqos_info = 0x%x\n",
|
|
wmm_para_tlv->wmm_para.qos_info);
|
|
printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BE].
|
|
aci_aifsn.aifsn,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw.
|
|
ecw_max,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BE].ecw.
|
|
ecw_min,
|
|
uap_le16_to_cpu(wmm_para_tlv->wmm_para.
|
|
ac_params[AC_BE].tx_op_limit));
|
|
printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BK].
|
|
aci_aifsn.aifsn,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw.
|
|
ecw_max,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_BK].ecw.
|
|
ecw_min,
|
|
uap_le16_to_cpu(wmm_para_tlv->wmm_para.
|
|
ac_params[AC_BK].tx_op_limit));
|
|
printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VI].
|
|
aci_aifsn.aifsn,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw.
|
|
ecw_max,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VI].ecw.
|
|
ecw_min,
|
|
uap_le16_to_cpu(wmm_para_tlv->wmm_para.
|
|
ac_params[AC_VI].tx_op_limit));
|
|
printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VO].
|
|
aci_aifsn.aifsn,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw.
|
|
ecw_max,
|
|
wmm_para_tlv->wmm_para.ac_params[AC_VO].ecw.
|
|
ecw_min,
|
|
uap_le16_to_cpu(wmm_para_tlv->wmm_para.
|
|
ac_params[AC_VO].tx_op_limit));
|
|
break;
|
|
#ifdef RX_PACKET_COALESCE
|
|
case MRVL_RX_PKT_COAL_TLV_ID:
|
|
rx_pkt_coal_tlv = (tlvbuf_rx_pkt_coal_t *)pcurrent_tlv;
|
|
printf("RX packet coalesce threshold=%d\n",
|
|
uap_le32_to_cpu(rx_pkt_coal_tlv->rx_pkt_count));
|
|
printf("RX packet coalesce timeout in msec=%d\n",
|
|
uap_le16_to_cpu(rx_pkt_coal_tlv->delay));
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
|
|
pcurrent_tlv = (tlvbuf_header *)(pcurrent_tlv->data + tlv_len);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if command requires driver handling, and if so,
|
|
* repackage and send as regular command, instead of hostcmd.
|
|
*
|
|
* @param cmd Pointer to the command buffer
|
|
* @param size Pointer to the command size. This value is
|
|
* overwritten by the function with the size of the
|
|
* received response.
|
|
* @param buf_size Size of the allocated command buffer
|
|
* @param reroute_ret Pointer to return value of rerouted command
|
|
* @return UAP_SUCCESS (handled here, further processing not needed)
|
|
* or UAP_FAILURE (not handled here, proceed as usual)
|
|
*/
|
|
static int
|
|
uap_ioctl_reroute(t_u8 *cmd, t_u16 *size, t_u16 buf_size, int *reroute_ret)
|
|
{
|
|
t_u8 reroute = 0;
|
|
t_u16 cmd_code = 0;
|
|
t_u16 cmd_action = 0;
|
|
apcmdbuf_cfg_80211d *hcmd_domain = NULL;
|
|
apcmdbuf_snmp_mib *hcmd_snmp = NULL;
|
|
tlvbuf_header *tlv = NULL;
|
|
struct ifreq ifr;
|
|
t_s32 sockfd;
|
|
t_u8 *buf = NULL;
|
|
t_u16 buf_len = 0;
|
|
snmp_mib_param *snmp_param = NULL;
|
|
domain_info_param *domain_param = NULL;
|
|
|
|
/* assume input is a hostcmd */
|
|
cmd_code = ((apcmdbuf *)(cmd))->cmd_code;
|
|
|
|
/* just check if we need to re-route right now */
|
|
switch (cmd_code) {
|
|
case HostCmd_SNMP_MIB:
|
|
hcmd_snmp = (apcmdbuf_snmp_mib *)cmd;
|
|
tlv = (tlvbuf_header *)(cmd + sizeof(apcmdbuf_snmp_mib));
|
|
cmd_action = uap_le16_to_cpu(hcmd_snmp->action);
|
|
/* reroute CMD_SNMP_MIB: SET */
|
|
if (cmd_action == ACTION_SET) {
|
|
reroute = 1;
|
|
buf_len =
|
|
sizeof(snmp_mib_param) +
|
|
uap_le16_to_cpu(tlv->len);
|
|
}
|
|
break;
|
|
case HostCmd_CMD_802_11D_DOMAIN_INFO:
|
|
hcmd_domain = (apcmdbuf_cfg_80211d *)cmd;
|
|
cmd_action = uap_le16_to_cpu(hcmd_domain->action);
|
|
/* reroute CMD_DOMAIN_INFO: SET */
|
|
if (cmd_action == ACTION_SET) {
|
|
reroute = 1;
|
|
buf_len = sizeof(domain_info_param) + (*size
|
|
-
|
|
sizeof
|
|
(apcmdbuf_cfg_80211d)
|
|
+
|
|
sizeof
|
|
(domain_param_t));
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Exit early if not re-routing */
|
|
if (!reroute || uap_ioctl_no_reroute)
|
|
return UAP_FAILURE;
|
|
|
|
/* Prepare buffer */
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "DBG: rerouting CMD 0x%04x\n", cmd_code);
|
|
#endif
|
|
buf = (t_u8 *)malloc(buf_len);
|
|
if (!buf) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
goto done_no_socket;
|
|
}
|
|
memset(buf, 0, buf_len);
|
|
|
|
/* Prepare param */
|
|
switch (cmd_code) {
|
|
case HostCmd_SNMP_MIB:
|
|
snmp_param = (snmp_mib_param *)buf;
|
|
snmp_param->subcmd = UAP_SNMP_MIB;
|
|
snmp_param->action = cmd_action;
|
|
snmp_param->oid = uap_le16_to_cpu(tlv->type);
|
|
snmp_param->oid_val_len = uap_le16_to_cpu(tlv->len);
|
|
memcpy(snmp_param->oid_value, tlv->data,
|
|
MIN(sizeof(t_u32), snmp_param->oid_val_len));
|
|
break;
|
|
case HostCmd_CMD_802_11D_DOMAIN_INFO:
|
|
domain_param = (domain_info_param *)buf;
|
|
domain_param->subcmd = UAP_DOMAIN_INFO;
|
|
domain_param->action = cmd_action;
|
|
memcpy(domain_param->tlv, &hcmd_domain->domain,
|
|
buf_len - sizeof(domain_info_param));
|
|
tlv = (tlvbuf_header *)domain_param->tlv;
|
|
tlv->type = uap_le16_to_cpu(tlv->type);
|
|
tlv->len = uap_le16_to_cpu(tlv->len);
|
|
|
|
break;
|
|
}
|
|
#if DEBUG
|
|
/* Dump request buffer */
|
|
hexdump("Reroute Request buffer", buf, buf_len, ' ');
|
|
#endif
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
goto done_no_socket;
|
|
}
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)buf;
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, UAP_IOCTL_CMD, &ifr)) {
|
|
*reroute_ret = UAP_FAILURE;
|
|
perror("");
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "ERR: reroute of CMD 0x%04x failed\n",
|
|
cmd_code);
|
|
#endif
|
|
goto done;
|
|
}
|
|
*reroute_ret = UAP_SUCCESS;
|
|
|
|
done:
|
|
/* Close socket */
|
|
close(sockfd);
|
|
done_no_socket:
|
|
if (buf)
|
|
free(buf);
|
|
|
|
return UAP_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Performs the ioctl operation to send the command to
|
|
* the driver.
|
|
*
|
|
* @param cmd Pointer to the command buffer
|
|
* @param size Pointer to the command size. This value is
|
|
* overwritten by the function with the size of the
|
|
* received response.
|
|
* @param buf_size Size of the allocated command buffer
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
uap_ioctl(t_u8 *cmd, t_u16 *size, t_u16 buf_size)
|
|
{
|
|
struct ifreq ifr;
|
|
apcmdbuf *header = NULL;
|
|
t_s32 sockfd;
|
|
int reroute_ret = 0;
|
|
mrvl_priv_cmd *mrvl_cmd = NULL;
|
|
t_u8 *buf = NULL, *temp = NULL;
|
|
t_u16 mrvl_header_len = 0;
|
|
int ret = UAP_SUCCESS;
|
|
|
|
#ifdef WIFI_DIRECT_SUPPORT
|
|
if (strncmp(dev_name, "wfd", 3))
|
|
#endif
|
|
if (uap_ioctl_reroute(cmd, size, buf_size, &reroute_ret) ==
|
|
UAP_SUCCESS) {
|
|
return reroute_ret;
|
|
}
|
|
|
|
if (buf_size < *size) {
|
|
printf("buf_size should not less than cmd buffer size\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/* Open socket */
|
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
printf("ERR:Cannot open socket\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
*(t_u32 *)cmd = buf_size - BUF_HEADER_SIZE;
|
|
|
|
mrvl_header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_HOSTCMD);
|
|
buf = (unsigned char *)malloc(buf_size + sizeof(mrvl_priv_cmd) +
|
|
mrvl_header_len);
|
|
if (buf == NULL) {
|
|
close(sockfd);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
memset(buf, 0, buf_size + sizeof(mrvl_priv_cmd) + mrvl_header_len);
|
|
/* Fill up buffer */
|
|
mrvl_cmd = (mrvl_priv_cmd *)buf;
|
|
mrvl_cmd->buf = buf + sizeof(mrvl_priv_cmd);
|
|
mrvl_cmd->used_len = 0;
|
|
mrvl_cmd->total_len = buf_size + mrvl_header_len;
|
|
/* Copy NXP command string */
|
|
temp = mrvl_cmd->buf;
|
|
strncpy((char *)temp, CMD_NXP, strlen(CMD_NXP));
|
|
temp += (strlen(CMD_NXP));
|
|
/* Insert command string */
|
|
strncpy((char *)temp, PRIV_CMD_HOSTCMD, strlen(PRIV_CMD_HOSTCMD));
|
|
temp += (strlen(PRIV_CMD_HOSTCMD));
|
|
|
|
memcpy(temp, (t_u8 *)cmd, *size);
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, IFNAMSIZ - 1);
|
|
ifr.ifr_ifru.ifru_data = (void *)mrvl_cmd;
|
|
header = (apcmdbuf *)(buf + sizeof(mrvl_priv_cmd) + mrvl_header_len);
|
|
header->size = *size - BUF_HEADER_SIZE;
|
|
if (header->cmd_code == APCMD_SYS_CONFIGURE) {
|
|
apcmdbuf_sys_configure *sys_cfg;
|
|
sys_cfg = (apcmdbuf_sys_configure *)header;
|
|
sys_cfg->action = uap_cpu_to_le16(sys_cfg->action);
|
|
}
|
|
endian_convert_request_header(header);
|
|
#if DEBUG
|
|
/* Dump request buffer */
|
|
hexdump("Request buffer", mrvl_cmd,
|
|
*size + sizeof(mrvl_priv_cmd) + mrvl_header_len, ' ');
|
|
#endif
|
|
/* Perform ioctl */
|
|
errno = 0;
|
|
if (ioctl(sockfd, MRVLPRIVCMD, &ifr)) {
|
|
perror("");
|
|
printf("ERR:MRVLPRIVCMD is not supported by %s\n", dev_name);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
endian_convert_response_header(header);
|
|
header->cmd_code &= HostCmd_CMD_ID_MASK;
|
|
header->cmd_code |= APCMD_RESP_CHECK;
|
|
*size = header->size;
|
|
|
|
/* Validate response size */
|
|
if (*size > (buf_size - BUF_HEADER_SIZE)) {
|
|
printf("ERR:Response size (%d) greater than buffer size (%d)! Aborting!\n", *size, buf_size);
|
|
ret = UAP_FAILURE;
|
|
goto done;
|
|
}
|
|
memcpy(cmd, (t_u8 *)header, *size + BUF_HEADER_SIZE);
|
|
#if DEBUG
|
|
/* Dump respond buffer */
|
|
hexdump("Respond buffer", mrvl_cmd,
|
|
*size + BUF_HEADER_SIZE + sizeof(mrvl_priv_cmd) +
|
|
mrvl_header_len, ' ');
|
|
#endif
|
|
|
|
done:
|
|
/* Close socket */
|
|
close(sockfd);
|
|
if (buf)
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Get protocol from the firmware
|
|
*
|
|
* @param proto A pointer to protocol var
|
|
* @return UAP_SUCCESS/UAP_FAILURE
|
|
*/
|
|
int
|
|
get_sys_cfg_protocol(t_u16 *proto)
|
|
{
|
|
apcmdbuf_sys_configure *cmd_buf = NULL;
|
|
tlvbuf_protocol *tlv = NULL;
|
|
t_u8 *buffer = NULL;
|
|
t_u16 cmd_len;
|
|
int ret = UAP_FAILURE;
|
|
|
|
cmd_len = sizeof(apcmdbuf_sys_configure) + sizeof(tlvbuf_protocol);
|
|
/* Initialize the command buffer */
|
|
buffer = (t_u8 *)malloc(cmd_len);
|
|
if (!buffer) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
return ret;
|
|
}
|
|
memset(buffer, 0, cmd_len);
|
|
/* Locate headers */
|
|
cmd_buf = (apcmdbuf_sys_configure *)buffer;
|
|
tlv = (tlvbuf_protocol *)(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;
|
|
cmd_buf->action = ACTION_GET;
|
|
tlv->tag = MRVL_PROTOCOL_TLV_ID;
|
|
tlv->length = 2;
|
|
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)) {
|
|
printf("ERR:Corrupted response! cmd_code=%x, Tlv->tag=%x\n", cmd_buf->cmd_code, tlv->tag);
|
|
free(buffer);
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
if (cmd_buf->result == CMD_SUCCESS) {
|
|
tlv->protocol = uap_le16_to_cpu(tlv->protocol);
|
|
memcpy(proto, &tlv->protocol, sizeof(tlv->protocol));
|
|
} else {
|
|
ret = UAP_FAILURE;
|
|
}
|
|
}
|
|
if (buffer)
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Check cipher is valid or not
|
|
*
|
|
* @param pairwisecipher Pairwise cipher
|
|
* @param groupcipher Group cipher
|
|
* @param protocol Protocol
|
|
* @param enable_11n 11n enabled or not.
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_cipher_valid_with_11n(int pairwisecipher, int groupcipher,
|
|
int protocol, int enable_11n)
|
|
{
|
|
if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
|
|
return UAP_SUCCESS;
|
|
if (pairwisecipher == CIPHER_TKIP) {
|
|
/* Ok to have TKIP in mixed mode */
|
|
if (enable_11n && protocol != PROTOCOL_WPA2_MIXED) {
|
|
printf("ERR: WPA/TKIP cannot be used when AP operates in 802.11n mode.\n");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) &&
|
|
(groupcipher == CIPHER_AES_CCMP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* @brief Check cipher is valid or not based on proto
|
|
*
|
|
* @param pairwisecipher Pairwise cipher
|
|
* @param groupcipher Group cipher
|
|
* @param protocol Protocol
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_cipher_valid_with_proto(int pairwisecipher, int groupcipher, int protocol)
|
|
{
|
|
HTCap_t htcap;
|
|
|
|
if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
|
|
return UAP_SUCCESS;
|
|
if (pairwisecipher == CIPHER_TKIP) {
|
|
/* Ok to have TKIP in mixed mode */
|
|
if (protocol != 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");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) &&
|
|
(groupcipher == CIPHER_AES_CCMP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* @brief Check cipher is valid or not
|
|
*
|
|
* @param pairwisecipher Pairwise cipher
|
|
* @param groupcipher Group cipher
|
|
* @return UAP_SUCCESS or UAP_FAILURE
|
|
*/
|
|
int
|
|
is_cipher_valid(int pairwisecipher, int groupcipher)
|
|
{
|
|
HTCap_t htcap;
|
|
t_u16 proto = 0;
|
|
|
|
if ((pairwisecipher == CIPHER_NONE) && (groupcipher == CIPHER_NONE))
|
|
return UAP_SUCCESS;
|
|
if (pairwisecipher == 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");
|
|
return UAP_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((pairwisecipher == CIPHER_TKIP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) &&
|
|
(groupcipher == CIPHER_AES_CCMP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_AES_CCMP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
if ((pairwisecipher == CIPHER_BITMAP) && (groupcipher == CIPHER_TKIP))
|
|
return UAP_SUCCESS;
|
|
return UAP_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* @brief The main function
|
|
*
|
|
* @param argc Number of arguments
|
|
* @param argv Pointer to the arguments
|
|
* @return 0 or 1
|
|
*/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int opt, i;
|
|
int ret = 0;
|
|
memset(dev_name, 0, sizeof(dev_name));
|
|
strcpy(dev_name, DEFAULT_DEV_NAME);
|
|
|
|
/* Parse arguments */
|
|
while ((opt =
|
|
getopt_long(argc, argv, "+hi:d:v", ap_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
case 'i':
|
|
if (strlen(optarg) < IFNAMSIZ) {
|
|
memset(dev_name, 0, sizeof(dev_name));
|
|
strncpy(dev_name, optarg, strlen(optarg));
|
|
}
|
|
printf("dev_name:%s\n", dev_name);
|
|
break;
|
|
case 'v':
|
|
printf("uaputl.exe - uAP utility ver %s\n",
|
|
UAP_VERSION);
|
|
exit(0);
|
|
case 'd':
|
|
debug_level = strtoul(optarg, NULL, 10);
|
|
#if DEBUG
|
|
uap_printf(MSG_DEBUG, "debug_level=%x\n", debug_level);
|
|
#endif
|
|
break;
|
|
case 'h':
|
|
default:
|
|
print_tool_usage();
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
optind = 0;
|
|
|
|
if (argc < 1) {
|
|
print_tool_usage();
|
|
exit(1);
|
|
}
|
|
|
|
/* Process command */
|
|
for (i = 0; ap_command[i].cmd; i++) {
|
|
if (strncmp
|
|
(ap_command[i].cmd, argv[0], strlen(ap_command[i].cmd)))
|
|
continue;
|
|
if (strlen(ap_command[i].cmd) != strlen(argv[0]))
|
|
continue;
|
|
ret = ap_command[i].func(argc, argv);
|
|
break;
|
|
}
|
|
if (!ap_command[i].cmd) {
|
|
printf("ERR: %s is not supported\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
if (ret == UAP_FAILURE)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|