mwifiex/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.c

5231 lines
135 KiB
C

/** @file mlanutl.c
*
* @brief Program to control parameters in the mlandriver
*
* Usage: mlanutl mlanX cmd [...]
*
*
* Copyright 2011-2022 NXP
*
* NXP CONFIDENTIAL
* The source code contained or described herein and all documents related to
* the source code (Materials) are owned by NXP, its
* suppliers and/or its licensors. Title to the Materials remains with NXP,
* its suppliers and/or its licensors. The Materials contain
* trade secrets and proprietary and confidential information of NXP, its
* suppliers and/or its licensors. The Materials are protected by worldwide
* copyright and trade secret laws and treaty provisions. No part of the
* Materials may be used, copied, reproduced, modified, published, uploaded,
* posted, transmitted, distributed, or disclosed in any way without NXP's prior
* express written permission.
*
* No license under any patent, copyright, trade secret or other intellectual
* property right is granted to or conferred upon you by disclosure or delivery
* of the Materials, either expressly, by implication, inducement, estoppel or
* otherwise. Any license under such intellectual property rights must be
* express and approved by NXP in writing.
*
*/
/************************************************************************
Change log:
11/04/2011: initial version
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <getopt.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include <sys/stat.h>
#include <net/ethernet.h>
#include "mlanutl.h"
/** Supported stream modes */
#define HT_STREAM_MODE_1X1 0x11
#define HT_STREAM_MODE_2X2 0x22
/** mlanutl version number */
#define MLANUTL_VER "M1.3.02"
/** Termination flag */
int terminate_flag = 0;
/** Termination flag */
boolean mcast_debug_flag = 0;
/********************************************************
Local Variables
********************************************************/
#define BAND_B (1U << 0)
#define BAND_G (1U << 1)
#define BAND_A (1U << 2)
#define BAND_GN (1U << 3)
#define BAND_AN (1U << 4)
#define BAND_GAC (1U << 5)
#define BAND_AAC (1U << 6)
#define BAND_GAX (1U << 8)
#define BAND_AAX (1U << 9)
/** Stringification of rateId enumeration */
const char *rateIdStr[] = {"1", "2", "5.5", "11", "--", "6", "9", "12",
"18", "24", "36", "48", "54", "--", "M0", "M1",
"M2", "M3", "M4", "M5", "M6", "M7", "H0", "H1",
"H2", "H3", "H4", "H5", "H6", "H7"};
char mod_conv_bg_1x1[10][35] = {
"CCK (1,2,5.5,11 Mbps)", "OFDM_PSK (6,9,12,18 Mbps)",
"OFDM_QAM16 (24,36 Mbps)", "OFDM_QAM64 (48,54 Mbps)",
"HT_20_PSK (MCS 0,1,2)", "HT_20_QAM16 (MCS 3,4)",
"HT_20_QAM64 (MCS 5,6,7)", "HT_40_PSK (MCS 0,1,2)",
"HT_40_QAM16 (MCS 3,4)", "HT_40_QAM64 (MCS 5,6,7)"};
char mod_conv_a_1x1[6][35] = {
"VHT_20_QAM256 (MCS 8)", "VHT_40_QAM256 (MCS 8,9)",
"VHT_80_PSK (MCS 0,1,2)", "VHT_80_QAM16 (MCS 3,4)",
"VHT_80_QAM64 (MCS 5,6,7)", "VHT_80_QAM256 (MCS 8,9)"};
char mod_conv_bg_2x2[6][35] = {
"HT2_20_PSK (MCS 8,9,10)", "HT2_20_QAM16 (MCS 11,12)",
"HT2_20_QAM64 (MCS 13,14,15)", "HT2_40_PSK (MCS 8,9,10)",
"HT2_40_QAM16 (MCS 11,12)", "HT2_40_QAM64 (MCS 13,14,15)"};
char mod_conv_a_2x2[6][35] = {
"VHT2_20_QAM256 (MCS 8)", "VHT2_40_QAM256 (MCS 8,9)",
"VHT2_80_PSK (MCS 0,1,2)", "VHT2_80_QAM16 (MCS 3,4)",
"VHT2_80_QAM64 (MCS 5,6,7)", "VHT2_80_QAM256 (MCS 8,9)"};
#ifdef DEBUG_LEVEL1
#define MMSG MBIT(0)
#define MFATAL MBIT(1)
#define MERROR MBIT(2)
#define MDATA MBIT(3)
#define MCMND MBIT(4)
#define MEVENT MBIT(5)
#define MINTR MBIT(6)
#define MIOCTL MBIT(7)
#define MREG_D MBIT(9)
#define MMPA_D MBIT(15)
#define MDAT_D MBIT(16)
#define MCMD_D MBIT(17)
#define MEVT_D MBIT(18)
#define MFW_D MBIT(19)
#define MIF_D MBIT(20)
#ifdef DEBUG_LEVEL2
#define MENTRY MBIT(28)
#define MWARN MBIT(29)
#define MINFO MBIT(30)
#endif
#endif
static int process_version(int argc, char *argv[]);
static int process_verext(int argc, char *argv[]);
static int process_hostcmd(int argc, char *argv[]);
#ifdef DEBUG_LEVEL1
static int process_drvdbg(int argc, char *argv[]);
#endif
static int process_datarate(int argc, char *argv[]);
static int process_getlog(int argc, char *argv[]);
static int process_get_txpwrlimit(int argc, char *argv[]);
#ifdef STA_SUPPORT
static int process_get_signal(int argc, char *argv[]);
static int process_get_signal_ext(int argc, char *argv[]);
static int process_signalext_cfg(int argc, char *argv[]);
#endif
static int process_vhtcfg(int argc, char *argv[]);
static int process_dyn_bw(int argc, char *argv[]);
static int process_11axcfg(int argc, char *argv[]);
static int process_11axcmdcfg(int argc, char *argv[]);
static int process_txratecfg(int argc, char *argv[]);
static int process_httxcfg(int argc, char *argv[]);
static int process_htcapinfo(int argc, char *argv[]);
static int process_addbapara(int argc, char *argv[]);
static int process_aggrpriotbl(int argc, char *argv[]);
static int process_addbareject(int argc, char *argv[]);
static int process_hssetpara(int argc, char *argv[]);
static int process_mefcfg(int argc, char *argv[]);
static int process_cloud_keep_alive(int argc, char *argv[]);
static int process_min_ba_threshold_cfg(int argc, char *argv[]);
struct command_node command_list[] = {
{"version", process_version},
{"verext", process_verext},
{"hostcmd", process_hostcmd},
#ifdef DEBUG_LEVEL1
{"drvdbg", process_drvdbg},
#endif
{"getdatarate", process_datarate},
{"getlog", process_getlog},
{"get_txpwrlimit", process_get_txpwrlimit},
#ifdef STA_SUPPORT
{"getsignal", process_get_signal},
{"getsignalext", process_get_signal_ext},
{"getsignalextv2", process_get_signal_ext},
{"signalextcfg", process_signalext_cfg},
#endif
{"vhtcfg", process_vhtcfg},
{"dyn_bw", process_dyn_bw},
{"11axcfg", process_11axcfg},
{"11axcmd", process_11axcmdcfg},
{"txratecfg", process_txratecfg},
{"addbapara", process_addbapara},
{"aggrpriotbl", process_aggrpriotbl},
{"addbareject", process_addbareject},
{"httxcfg", process_httxcfg},
{"htcapinfo", process_htcapinfo},
{"hssetpara", process_hssetpara},
{"mefcfg", process_mefcfg},
{"cloud_keep_alive", process_cloud_keep_alive},
{"min_ba_threshold", process_min_ba_threshold_cfg},
};
static char *usage[] = {
"Usage: ",
" mlanutl -v (version)",
" mlanutl <ifname> <cmd> [...]",
" where",
" ifname : wireless network interface name, such as mlanX or uapX",
" cmd :",
" version",
" verext",
" hostcmd",
#ifdef DEBUG_LEVEL1
" drvdbg",
#endif
" getdatarate",
" getlog",
" get_txpwrlimit",
#ifdef STA_SUPPORT
" getsignal",
" signalextcfg",
" getsignalext",
" getsignalextv2",
#endif
" vhtcfg",
" dyn_bw",
" 11axcfg",
" 11axcmd",
" txratecfg",
" httxcfg",
" htcapinfo",
" aggrpriotbl",
" addbapara",
" addbareject",
" hssetpara",
" mefcfg",
" cloud_keep_alive",
" min_ba_threshold",
};
/** Socket */
t_s32 sockfd;
/** Device name */
char dev_name[IFNAMSIZ + 1];
#define HOSTCMD "hostcmd"
char *config_get_line(char *s, int size, FILE *stream, int *line, char **_pos);
#define BSSID_FILTER 1
#define SSID_FILTER 2
/********************************************************
Global Variables
********************************************************/
int setuserscan_filter = 0;
int num_ssid_filter = 0;
/********************************************************
Local Functions
********************************************************/
/**
* @brief Convert char to hex integer
*
* @param chr Char to convert
* @return Hex integer or 0
*/
static int hexval(t_s32 chr)
{
if (chr >= '0' && chr <= '9')
return chr - '0';
if (chr >= 'A' && chr <= 'F')
return chr - 'A' + 10;
if (chr >= 'a' && chr <= 'f')
return chr - 'a' + 10;
return 0;
}
/**
* @brief Hump hex data
*
* @param prompt A pointer prompt buffer
* @param p A pointer to data buffer
* @param len The len of data buffer
* @param delim Delim char
* @return Hex integer
*/
t_void hexdump(char *prompt, t_void *p, t_s32 len, char delim)
{
t_s32 i;
t_u8 *s = p;
if (prompt) {
printf("%s: len=%d\n", prompt, (int)len);
}
for (i = 0; i < len; i++) {
if (i != len - 1)
printf("%02x%c", *s++, delim);
else
printf("%02x\n", *s);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
}
/**
* @brief Convert char to hex integer
*
* @param chr Char
* @return Hex integer
*/
t_u8 hexc2bin(char chr)
{
if (chr >= '0' && chr <= '9')
chr -= '0';
else if (chr >= 'A' && chr <= 'F')
chr -= ('A' - 10);
else if (chr >= 'a' && chr <= 'f')
chr -= ('a' - 10);
return chr;
}
/**
* @brief Convert string to hex integer
*
* @param s A pointer string buffer
* @return Hex integer
*/
t_u32 a2hex(char *s)
{
t_u32 val = 0;
if (!strncasecmp("0x", s, 2)) {
s += 2;
}
while (*s && isxdigit((unsigned char)*s)) {
val = (val << 4) + hexc2bin(*s++);
}
return val;
}
/*
* @brief Convert String to integer
*
* @param value A pointer to string
* @return Integer
*/
t_u32 a2hex_or_atoi(char *value)
{
if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
return a2hex(value + 2);
} else {
return (t_u32)atoi(value);
}
}
/**
* @brief Convert string to hex
*
* @param ptr A pointer to data buffer
* @param chr A pointer to return integer
* @return A pointer to next data field
*/
static char *convert2hex(char *ptr, t_u8 *chr)
{
t_u8 val;
for (val = 0; *ptr && isxdigit((unsigned char)*ptr); ptr++) {
val = (val * 16) + hexval(*ptr);
}
*chr = val;
return ptr;
}
/**
* @brief Display usage
*
* @return NA
*/
static t_void display_usage(t_void)
{
t_u32 i;
for (i = 0; i < NELEMENTS(usage); i++)
fprintf(stderr, "%s\n", usage[i]);
}
/**
* @brief Find and execute command
*
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS for success, otherwise failure
*/
static int process_command(int argc, char *argv[])
{
int i = 0, ret = MLAN_STATUS_NOTFOUND;
struct command_node *node = NULL;
for (i = 0; i < (int)NELEMENTS(command_list); i++) {
node = &command_list[i];
if (!strcasecmp(node->name, argv[2])) {
ret = node->handler(argc, argv);
break;
}
}
return ret;
}
/**
* @brief Prepare command buffer
* @param buffer Command buffer to be filled
* @param cmd Command id
* @param num Number of arguments
* @param args Arguments list
* @return MLAN_STATUS_SUCCESS
*/
static int prepare_buffer(t_u8 *buffer, char *cmd, t_u32 num, char *args[])
{
t_u8 *pos = NULL;
unsigned int i = 0;
memset(buffer, 0, BUFFER_LENGTH);
/* Flag it for our use */
pos = buffer;
memcpy((char *)pos, CMD_NXP, strlen(CMD_NXP));
pos += (strlen(CMD_NXP));
/* Insert command */
strncpy((char *)pos, (char *)cmd, strlen(cmd));
pos += (strlen(cmd));
/* Insert arguments */
for (i = 0; i < num; i++) {
strncpy((char *)pos, args[i], strlen(args[i]));
pos += strlen(args[i]);
if (i < (num - 1)) {
memcpy((char *)pos, " ", strlen(" "));
pos += 1;
}
}
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Trims leading and traling spaces only
* @param str A pointer to argument string
* @return pointer to trimmed string
*/
static char *trim_spaces(char *str)
{
char *str_end = NULL;
if (!str)
return NULL;
/* Trim leading spaces */
while (!*str && isspace((unsigned char)*str))
str++;
if (*str == 0) /* All spaces? */
return str;
/* Trim trailing spaces */
str_end = str + strlen(str) - 1;
while (str_end > str && isspace((unsigned char)*str_end))
str_end--;
/* null terminate the string */
*(str_end + 1) = '\0';
return str;
}
/**
* @brief read current command
* @param ptr A pointer to data
* @param curCmd A pointer to the buf which will hold current command
* @return NULL or the pointer to the left command buf
*/
static t_s8 *readCurCmd(t_s8 *ptr, t_s8 *curCmd)
{
t_s32 i = 0;
#define MAX_CMD_SIZE 64 /**< Max command size */
while (*ptr != ']' && i < (MAX_CMD_SIZE - 1))
curCmd[i++] = *(++ptr);
if (*ptr != ']')
return NULL;
curCmd[i - 1] = '\0';
return ++ptr;
}
/**
* @brief parse command and hex data
* @param fp A pointer to FILE stream
* @param dst A pointer to the dest buf
* @param cmd A pointer to command buf for search
* @return Length of hex data or MLAN_STATUS_FAILURE
*/
static int fparse_for_cmd_and_hex(FILE *fp, t_u8 *dst, t_u8 *cmd)
{
t_s8 *ptr;
t_u8 *dptr;
t_s8 buf[256], curCmd[64] = {0};
t_s32 isCurCmd = 0;
dptr = dst;
while (fgets((char *)buf, sizeof(buf), fp)) {
ptr = buf;
while (*ptr) {
/* skip leading spaces */
while (*ptr && isspace((unsigned char)*ptr))
ptr++;
/* skip blank lines and lines beginning with '#' */
if (*ptr == '\0' || *ptr == '#')
break;
if (*ptr == '[' && *(ptr + 1) != '/') {
ptr = readCurCmd(ptr, curCmd);
if (!ptr)
return MLAN_STATUS_FAILURE;
if (strcasecmp((char *)curCmd,
(char *)cmd)) /* Not equal */
isCurCmd = 0;
else
isCurCmd = 1;
}
/* Ignore the rest if it is not correct cmd */
if (!isCurCmd)
break;
if (*ptr == '[' && *(ptr + 1) == '/')
return dptr - dst;
if (isxdigit((unsigned char)*ptr)) {
ptr = (t_s8 *)convert2hex((char *)ptr, dptr++);
} else {
/* Invalid character on data line */
ptr++;
}
}
}
return MLAN_STATUS_FAILURE;
}
/**
* @brief Process version
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_version(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], 0, NULL);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: version fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
printf("Version string received: %s\n", buffer);
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process extended version
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_verext(int argc, char *argv[])
{
int ret = 0;
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Sanity tests */
if (argc < 3 || argc > 4) {
printf("Error: invalid no of arguments\n");
printf("mlanutl mlanX verext [#]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: verext fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Process result */
if (cmd->used_len)
printf("Extended Version string received: %s\n", buffer);
done:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
int process_host_cmd_resp(char *cmd_name, t_u8 *buf);
/**
* @brief Get one line from the File
*
* @param fp File handler
* @param str Storage location for data.
* @param size Maximum number of characters to read.
* @param lineno A pointer to return current line number
* @return returns string or NULL
*/
char *mlan_config_get_line(FILE *fp, char *str, t_s32 size, int *lineno)
{
char *start, *end;
int out, next_line;
if (!fp || !str)
return NULL;
do {
read_line:
if (!fgets(str, size, fp))
break;
start = str;
start[size - 1] = '\0';
end = start + strlen(str);
(*lineno)++;
out = 1;
while (out && (start < end)) {
next_line = 0;
/* Remove empty lines and lines starting with # */
switch (start[0]) {
case ' ': /* White space */
case '\t': /* Tab */
start++;
break;
case '#':
case '\n':
case '\0':
next_line = 1;
break;
case '\r':
if (start[1] == '\n')
next_line = 1;
else
start++;
break;
default:
out = 0;
break;
}
if (next_line)
goto read_line;
}
/* Remove # comments unless they are within a double quoted
* string. Remove trailing white space. */
end = strstr(start, "\"");
if (end) {
end = strstr(end + 1, "\"");
if (!end)
end = start;
} else
end = start;
end = strstr(end + 1, "#");
if (end)
*end-- = '\0';
else
end = start + strlen(start) - 1;
out = 1;
while (out && (start < end)) {
switch (*end) {
case ' ': /* White space */
case '\t': /* Tab */
case '\n':
case '\r':
*end = '\0';
end--;
break;
default:
out = 0;
break;
}
}
if (*start == '\0')
continue;
return start;
} while (1);
return NULL;
}
/**
* @brief Parse function for a configuration line
*
* @param s Storage buffer for data
* @param size Maximum size of data
* @param stream File stream pointer
* @param line Pointer to current line within the file
* @param _pos Output string or NULL
* @return String or NULL
*/
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 get hostcmd data
*
* @param ln A pointer to line number
* @param buf A pointer to hostcmd data
* @param size A pointer to the return size of hostcmd buffer
* @return MLAN_STATUS_SUCCESS
*/
static int mlan_get_hostcmd_data(FILE *fp, int *ln, t_u8 *buf, t_u16 *size)
{
t_s32 errors = 0, i;
char line[512], *pos, *pos1, *pos2, *pos3;
t_u16 len;
while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
(*ln)++;
if (strcmp(pos, "}") == 0) {
break;
}
pos1 = strchr(pos, ':');
if (pos1 == NULL) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos1++ = '\0';
pos2 = strchr(pos1, '=');
if (pos2 == NULL) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos2++ = '\0';
len = a2hex_or_atoi(pos1);
if (len < 1 || len > BUFFER_LENGTH) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*size += len;
if (*pos2 == '"') {
pos2++;
pos3 = strchr(pos2, '"');
if (pos3 == NULL) {
printf("Line %d: invalid quotation '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos3 = '\0';
memset(buf, 0, len);
memmove(buf, pos2, MIN(strlen(pos2), len));
buf += len;
} else if (*pos2 == '\'') {
pos2++;
pos3 = strchr(pos2, '\'');
if (pos3 == NULL) {
printf("Line %d: invalid quotation '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos3 = ',';
for (i = 0; i < len; i++) {
pos3 = strchr(pos2, ',');
if (pos3 != NULL) {
*pos3 = '\0';
*buf++ = (t_u8)a2hex_or_atoi(pos2);
pos2 = pos3 + 1;
} else
*buf++ = 0;
}
} else if (*pos2 == '{') {
t_u16 tlvlen = 0, tmp_tlvlen;
mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
tmp_tlvlen = tlvlen;
while (len--) {
*buf++ = (t_u8)(tmp_tlvlen & 0xff);
tmp_tlvlen >>= 8;
}
*size += tlvlen;
buf += tlvlen;
} else {
t_u32 value = a2hex_or_atoi(pos2);
while (len--) {
*buf++ = (t_u8)(value & 0xff);
value >>= 8;
}
}
}
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Prepare host-command buffer
* @param fp File handler
* @param cmd_name Command name
* @param buf A pointer to comand buffer
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int prepare_host_cmd_buffer(FILE *fp, char *cmd_name, t_u8 *buf)
{
char line[256], cmdname[256], *pos, cmdcode[10];
HostCmd_DS_GEN *hostcmd;
t_u32 hostcmd_size = 0;
int ln = 0;
int cmdname_found = 0, cmdcode_found = 0;
hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32));
hostcmd->command = 0xffff;
snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
cmdname_found = 0;
while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
if (strcmp(pos, cmdname) == 0) {
cmdname_found = 1;
snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
cmdcode_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdcode, strlen(cmdcode)) ==
0) {
t_u16 len = 0;
cmdcode_found = 1;
hostcmd->command = a2hex_or_atoi(
pos + strlen(cmdcode));
hostcmd->size = S_DS_GEN;
mlan_get_hostcmd_data(
fp, &ln,
buf + sizeof(t_u32) +
hostcmd->size,
&len);
hostcmd->size += len;
break;
}
}
if (!cmdcode_found) {
fprintf(stderr,
"mlanutl: CmdCode not found in conf file\n");
return MLAN_STATUS_FAILURE;
}
break;
}
}
if (!cmdname_found) {
fprintf(stderr,
"mlanutl: cmdname '%s' is not found in conf file\n",
cmd_name);
return MLAN_STATUS_FAILURE;
}
hostcmd->seq_num = 0;
hostcmd->result = 0;
hostcmd->command = cpu_to_le16(hostcmd->command);
hostcmd->size = cpu_to_le16(hostcmd->size);
hostcmd_size = (t_u32)(hostcmd->size);
memcpy(buf, (t_u8 *)&hostcmd_size, sizeof(t_u32));
return MLAN_STATUS_SUCCESS;
}
#define CMDCODE_OFFSET 0
#define SUBID_OFFSET (S_DS_GEN + 2)
static const t_u16 debug_cmd = 0x008b;
static t_u16 supported_cmd[] = {0x0130, 0x0016, 0x00e0};
/* If the hostcmd CmdCode is 0x008b (debug cmd), then below SUBIDs will be
* allowed */
static t_u16 supported_8b_subcmd[] = {0x104, 0x111, 0x11b, 0x11e, 0x27, 0x101};
static int check_if_hostcmd_allowed(t_u8 *buf)
{
t_u32 maxcnt_cmd = sizeof(supported_cmd) / sizeof(supported_cmd[0]);
t_u32 maxcnt_subcmd =
sizeof(supported_8b_subcmd) / sizeof(supported_8b_subcmd[0]);
/* Check if CmdCode is 0x008b (debug cmd from debug.conf) */
if (!memcmp(buf + CMDCODE_OFFSET, &debug_cmd, sizeof(t_u16))) {
for (int i = 0; i < maxcnt_subcmd; i++) {
/* Check if SUBID matches with allowed subcmd */
if (!memcmp(buf + SUBID_OFFSET,
(supported_8b_subcmd + i), sizeof(t_u16)))
return MLAN_STATUS_SUCCESS;
}
return MLAN_STATUS_NOTFOUND;
}
for (int i = 0; i < maxcnt_cmd; i++) {
/* If CmdCode is other than 0x008b, then only check the CmdCode
*/
if (!memcmp(buf + CMDCODE_OFFSET, (supported_cmd + i),
sizeof(t_u16)))
return MLAN_STATUS_SUCCESS;
}
return MLAN_STATUS_NOTFOUND;
}
/**
* @brief Process hostcmd command
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_hostcmd(int argc, char *argv[])
{
t_u8 *buffer = NULL, *raw_buf = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
FILE *fp = NULL;
FILE *fp_raw = NULL;
FILE *fp_dtsi = NULL;
char cmdname[256];
boolean call_ioctl = TRUE;
t_u32 buf_len = 0, i, j, k;
char *line = NULL, *pos = NULL;
int li = 0, blk_count = 0, ob = 0;
int ret = MLAN_STATUS_SUCCESS;
struct cmd_node {
char cmd_string[256];
struct cmd_node *next;
};
struct cmd_node *command = NULL, *header = NULL, *new_node = NULL;
if (argc < 5) {
printf("Error: invalid no of arguments\n");
printf("Syntax: ./mlanutl mlanX hostcmd <hostcmd.conf> <cmdname>\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
snprintf(cmdname, sizeof(cmdname), "%s", argv[4]);
if (!strcmp(cmdname, "generate_raw")) {
call_ioctl = FALSE;
}
if (!call_ioctl && argc != 6) {
printf("Error: invalid no of arguments\n");
printf("Syntax: ./mlanutl mlanX hostcmd <hostcmd.conf> %s <raw_data_file>\n",
cmdname);
ret = MLAN_STATUS_FAILURE;
goto done;
}
fp = fopen(argv[3], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s\n", argv[3]);
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
fclose(fp);
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
if (call_ioctl) {
/* Prepare the hostcmd buffer */
prepare_buffer(buffer, argv[2], 0, NULL);
if (MLAN_STATUS_FAILURE ==
prepare_host_cmd_buffer(fp, cmdname,
buffer + strlen(CMD_NXP) +
strlen(argv[2]))) {
fclose(fp);
ret = MLAN_STATUS_FAILURE;
goto done;
}
fclose(fp);
} else {
line = (char *)malloc(MAX_CONFIG_LINE);
if (!line) {
printf("ERR:Cannot allocate memory for line\n");
fclose(fp);
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(line, 0, MAX_CONFIG_LINE);
while (config_get_line(line, MAX_CONFIG_LINE, fp, &li, &pos)) {
line = trim_spaces(line);
if (line[strlen(line) - 1] == '{') {
if (ob == 0) {
new_node = (struct cmd_node *)malloc(
sizeof(struct cmd_node));
if (!new_node) {
printf("ERR:Cannot allocate memory for cmd_node\n");
fclose(fp);
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(new_node, 0,
sizeof(struct cmd_node));
new_node->next = NULL;
if (blk_count == 0) {
header = new_node;
command = new_node;
} else {
command->next = new_node;
command = new_node;
}
strncpy(command->cmd_string, line,
(strchr(line, '=') - line));
memmove(command->cmd_string,
trim_spaces(
command->cmd_string),
strlen(trim_spaces(
command->cmd_string)) +
1);
}
ob++;
continue; /* goto while() */
}
if (line[strlen(line) - 1] == '}') {
ob--;
if (ob == 0)
blk_count++;
continue; /* goto while() */
}
}
rewind(fp); /* Set the source file pointer to the beginning
again */
command = header; /* Set 'command' at the beginning of the
command list */
fp_raw = fopen(argv[5], "w");
if (fp_raw == NULL) {
fprintf(stderr,
"Cannot open the destination raw_data file %s\n",
argv[5]);
fclose(fp);
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* prepare .dtsi output */
snprintf(cmdname, sizeof(cmdname), "%s.dtsi", argv[5]);
fp_dtsi = fopen(cmdname, "w");
if (fp_dtsi == NULL) {
fprintf(stderr, "Cannot open the destination file %s\n",
cmdname);
fclose(fp);
fclose(fp_raw);
ret = MLAN_STATUS_FAILURE;
goto done;
}
for (k = 0; k < (t_u32)blk_count && command != NULL; k++) {
if (MLAN_STATUS_FAILURE ==
prepare_host_cmd_buffer(fp, command->cmd_string,
buffer))
memset(buffer, 0, BUFFER_LENGTH);
memcpy(&buf_len, buffer, sizeof(t_u32));
if (buf_len) {
raw_buf = buffer + sizeof(t_u32); /* raw_buf
points to
start of
actual <raw
data> */
printf("buf_len = %d\n", (int)buf_len);
if (k > 0)
fprintf(fp_raw, "\n\n");
fprintf(fp_raw, "%s={\n", command->cmd_string);
fprintf(fp_dtsi,
"/ {\n\tmarvell_cfgdata {\n\t\tmarvell,%s = /bits/ 8 <\n",
command->cmd_string);
i = j = 0;
while (i < buf_len) {
for (j = 0; j < 16; j++) {
fprintf(fp_raw, "%02x ",
*(raw_buf + i));
if (i >= 8) {
fprintf(fp_dtsi,
"0x%02x",
*(raw_buf + i));
if ((j < 16 - 1) &&
(i < buf_len - 1))
fprintf(fp_dtsi,
" ");
}
if (++i >= buf_len)
break;
}
fputc('\n', fp_raw);
fputc('\n', fp_dtsi);
}
fprintf(fp_raw, "}");
fprintf(fp_dtsi, "\t\t>;\n\t};\n};\n");
}
command = command->next;
rewind(fp);
}
fclose(fp_dtsi);
fclose(fp_raw);
fclose(fp);
}
if (call_ioctl) {
/* raw_buf points to start of command id */
raw_buf = buffer + strlen(CMD_NXP) + strlen(argv[2]) +
sizeof(t_u32);
if (check_if_hostcmd_allowed(raw_buf) != MLAN_STATUS_SUCCESS) {
printf("ERR:Entered hostcmd not allowed!\n");
goto done;
}
cmd = (struct eth_priv_cmd *)malloc(
sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: hostcmd fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Process result */
process_host_cmd_resp(argv[2], buffer);
}
done:
while (header) {
command = header;
header = header->next;
free(command);
}
if (line)
free(line);
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
#ifdef DEBUG_LEVEL1
/**
* @brief Process driver debug configuration
* @param argc number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_drvdbg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
t_u32 drvdbg;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: drvdbg config fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
if (argc == 3) {
memcpy(&drvdbg, buffer, sizeof(drvdbg));
printf("drvdbg: 0x%08x\n", drvdbg);
#ifdef DEBUG_LEVEL2
printf("MINFO (%08x) %s\n", MINFO,
(drvdbg & MINFO) ? "X" : "");
printf("MWARN (%08x) %s\n", MWARN,
(drvdbg & MWARN) ? "X" : "");
printf("MENTRY (%08x) %s\n", MENTRY,
(drvdbg & MENTRY) ? "X" : "");
#endif
printf("MMPA_D (%08x) %s\n", MMPA_D,
(drvdbg & MMPA_D) ? "X" : "");
printf("MIF_D (%08x) %s\n", MIF_D,
(drvdbg & MIF_D) ? "X" : "");
printf("MFW_D (%08x) %s\n", MFW_D,
(drvdbg & MFW_D) ? "X" : "");
printf("MEVT_D (%08x) %s\n", MEVT_D,
(drvdbg & MEVT_D) ? "X" : "");
printf("MCMD_D (%08x) %s\n", MCMD_D,
(drvdbg & MCMD_D) ? "X" : "");
printf("MDAT_D (%08x) %s\n", MDAT_D,
(drvdbg & MDAT_D) ? "X" : "");
printf("MREG_D (%08x) %s\n", MREG_D,
(drvdbg & MREG_D) ? "X" : "");
printf("MIOCTL (%08x) %s\n", MIOCTL,
(drvdbg & MIOCTL) ? "X" : "");
printf("MINTR (%08x) %s\n", MINTR,
(drvdbg & MINTR) ? "X" : "");
printf("MEVENT (%08x) %s\n", MEVENT,
(drvdbg & MEVENT) ? "X" : "");
printf("MCMND (%08x) %s\n", MCMND,
(drvdbg & MCMND) ? "X" : "");
printf("MDATA (%08x) %s\n", MDATA,
(drvdbg & MDATA) ? "X" : "");
printf("MERROR (%08x) %s\n", MERROR,
(drvdbg & MERROR) ? "X" : "");
printf("MFATAL (%08x) %s\n", MFATAL,
(drvdbg & MFATAL) ? "X" : "");
printf("MMSG (%08x) %s\n", MMSG, (drvdbg & MMSG) ? "X" : "");
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
#endif
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 Process Get data rate
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_datarate(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct eth_priv_data_rate *datarate = NULL;
struct ifreq ifr;
char *bw[] = {"20 MHz", "40 MHz", "80 MHz", "160 MHz"};
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], 0, NULL);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: getdatarate fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
datarate = (struct eth_priv_data_rate *)buffer;
printf("Data Rate:\n");
printf(" TX: \n");
if (datarate->tx_rate_format <= 3) {
printf(" Type: %s\n", rate_format[datarate->tx_rate_format]);
if ((datarate->tx_rate_format == 0) &&
datarate->tx_data_rate <= 11)
/* LG */
printf(" Rate: %s\n",
lg_rate[datarate->tx_data_rate]);
else {
/* HT and VHT*/
if (datarate->tx_bw <= 3)
printf(" BW: %s\n", bw[datarate->tx_bw]);
if (datarate->tx_rate_format < 3) {
if (datarate->tx_gi == 0)
printf(" GI: Long\n");
else
printf(" GI: Short\n");
} else if (datarate->tx_rate_format == 3) {
switch (datarate->tx_gi) {
case 0:
printf(" GI: 1xHELTF + GI 0.8us \n");
break;
case 1:
printf(" GI: 2xHELTF + GI 0.8us \n");
break;
case 2:
printf(" GI: 2xHELTF + GI 1.6us \n");
break;
case 3:
printf(" GI: 4xHELTF + GI 0.8us DCM=0 and STBC=0 or\n"
" 4xHELTF + GI 3.2us Otherwise \n");
break;
}
}
if (datarate->tx_rate_format >= 2)
printf(" NSS: %d\n", datarate->tx_nss + 1);
if (datarate->tx_mcs_index != 0xFF)
printf(" MCS: MCS %d\n",
(int)datarate->tx_mcs_index);
else
printf(" MCS: Auto\n");
if (datarate->tx_rate_format < 3)
printf(" Rate: %f Mbps\n",
(float)datarate->tx_data_rate / 2);
}
}
printf(" RX: \n");
if (datarate->rx_rate_format <= 3) {
printf(" Type: %s\n", rate_format[datarate->rx_rate_format]);
if ((datarate->rx_rate_format == 0) &&
datarate->rx_data_rate <= 11)
/* LG */
printf(" Rate: %s\n",
lg_rate[datarate->rx_data_rate]);
else {
/* HT and VHT*/
if (datarate->rx_bw <= 3)
printf(" BW: %s\n", bw[datarate->rx_bw]);
if (datarate->rx_rate_format < 3) {
if (datarate->rx_gi == 0)
printf(" GI: Long\n");
else
printf(" GI: Short\n");
} else if (datarate->rx_rate_format == 3) {
switch (datarate->rx_gi) {
case 0:
printf(" GI: 1xHELTF + GI 0.8us \n");
break;
case 1:
printf(" GI: 2xHELTF + GI 0.8us \n");
break;
case 2:
printf(" GI: 2xHELTF + GI 1.6us \n");
break;
case 3:
printf(" GI: 4xHELTF + GI 0.8us DCM=0 and STBC=0 or\n"
" 4xHELTF + GI 3.2us Otherwise \n");
break;
}
}
if (datarate->rx_rate_format >= 2)
printf(" NSS: %d\n", datarate->rx_nss + 1);
if (datarate->rx_mcs_index != 0xFF)
printf(" MCS: MCS %d\n",
(int)datarate->rx_mcs_index);
else
printf(" MCS: Auto\n");
if (datarate->rx_rate_format < 3)
printf(" Rate: %f Mbps\n",
(float)datarate->rx_data_rate / 2);
}
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process get wireless stats
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_getlog(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct eth_priv_get_log *stats = NULL;
struct ifreq ifr;
struct timeval tv;
int i = 0;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: getlog fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
gettimeofday(&tv, NULL);
/* Process results */
stats = (struct eth_priv_get_log *)buffer;
printf("Get log: timestamp %d.%06d sec\n", (int)tv.tv_sec,
(int)tv.tv_usec);
printf("dot11GroupTransmittedFrameCount %u\n"
"dot11FailedCount %u\n"
"dot11RetryCount %u\n"
"dot11MultipleRetryCount %u\n"
"dot11FrameDuplicateCount %u\n"
"dot11RTSSuccessCount %u\n"
"dot11RTSFailureCount %u\n"
"dot11ACKFailureCount %u\n"
"dot11ReceivedFragmentCount %u\n"
"dot11GroupReceivedFrameCount %u\n"
"dot11FCSErrorCount %u\n"
"dot11TransmittedFrameCount %u\n"
"wepicverrcnt-1 %u\n"
"wepicverrcnt-2 %u\n"
"wepicverrcnt-3 %u\n"
"wepicverrcnt-4 %u\n"
"beaconReceivedCount %u\n"
"beaconMissedCount %u\n",
stats->mcast_tx_frame, stats->failed, stats->retry,
stats->multi_retry, stats->frame_dup, stats->rts_success,
stats->rts_failure, stats->ack_failure, stats->rx_frag,
stats->mcast_rx_frame, stats->fcs_error, stats->tx_frame,
stats->wep_icv_error[0], stats->wep_icv_error[1],
stats->wep_icv_error[2], stats->wep_icv_error[3],
stats->bcn_rcv_cnt, stats->bcn_miss_cnt);
if (argc == 4 && !(strcmp(argv[3], "ext"))) {
printf("rxStuckIssueCount-1 %u\n"
"rxStuckIssueCount-2 %u\n"
"rxStuckRecoveryCount %u\n"
"rxStuckTsf-1 %llu\n"
"rxStuckTsf-2 %llu\n"
"txWatchdogRecoveryCount %u\n"
"txWatchdogTsf-1 %llu\n"
"txWatchdogTsf-2 %llu\n"
"channelSwitchAnnouncementSent %u\n"
"channelSwitchState %u\n"
"registerClass %u\n"
"channelNumber %u\n"
"channelSwitchMode %u\n"
"RxResetRecoveryCount %u\n"
"RxIsr2NotDoneCnt %u\n"
"gdmaAbortCnt %u\n"
"gResetRxMacCnt %u\n"
"gOwnrshpCtlErrCnt %u\n"
"gOwnrshpBcnErrCnt %u\n"
"gOwnrshpMgtErrCnt %u\n"
"gOwnrshpDatErrCnt %u\n"
"bigtk_mmeGoodCnt %u\n"
"bigtk_replayErrCnt %u\n"
"bigtk_micErrCnt %u\n"
"bigtk_mmeNotFoundCnt %u\n",
stats->rx_stuck_issue_cnt[0],
stats->rx_stuck_issue_cnt[1],
stats->rx_stuck_recovery_cnt, stats->rx_stuck_tsf[0],
stats->rx_stuck_tsf[1], stats->tx_watchdog_recovery_cnt,
stats->tx_watchdog_tsf[0], stats->tx_watchdog_tsf[1],
stats->channel_switch_ann_sent,
stats->channel_switch_state, stats->reg_class,
stats->channel_number, stats->channel_switch_mode,
stats->rx_reset_mac_recovery_cnt,
stats->rx_Isr2_NotDone_Cnt, stats->gdma_abort_cnt,
stats->g_reset_rx_mac_cnt, stats->dwCtlErrCnt,
stats->dwBcnErrCnt, stats->dwMgtErrCnt,
stats->dwDatErrCnt, stats->bigtk_mmeGoodCnt,
stats->bigtk_replayErrCnt, stats->bigtk_micErrCnt,
stats->bigtk_mmeNotFoundCnt);
}
if (cmd->used_len == sizeof(struct eth_priv_get_log)) {
printf("dot11TransmittedFragmentCount %u\n",
stats->tx_frag_cnt);
printf("dot11QosTransmittedFragmentCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_tx_frag_cnt[i]);
}
printf("\ndot11QosFailedCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_failed_cnt[i]);
}
printf("\ndot11QosRetryCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_retry_cnt[i]);
}
printf("\ndot11QosMultipleRetryCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_multi_retry_cnt[i]);
}
printf("\ndot11QosFrameDuplicateCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_frm_dup_cnt[i]);
}
printf("\ndot11QosRTSSuccessCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_rts_suc_cnt[i]);
}
printf("\ndot11QosRTSFailureCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_rts_failure_cnt[i]);
}
printf("\ndot11QosACKFailureCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_ack_failure_cnt[i]);
}
printf("\ndot11QosReceivedFragmentCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_rx_frag_cnt[i]);
}
printf("\ndot11QosTransmittedFrameCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_tx_frm_cnt[i]);
}
printf("\ndot11QosDiscardedFrameCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_discarded_frm_cnt[i]);
}
printf("\ndot11QosMPDUsReceivedCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_mpdus_rx_cnt[i]);
}
printf("\ndot11QosRetriesReceivedCount ");
for (i = 0; i < 8; i++) {
printf("%u ", stats->qos_retries_rx_cnt[i]);
}
printf("\ndot11RSNAStatsCMACICVErrors %u\n"
"dot11RSNAStatsCMACReplays %u\n"
"dot11RSNAStatsRobustMgmtCCMPReplays %u\n"
"dot11RSNAStatsTKIPICVErrors %u\n"
"dot11RSNAStatsTKIPReplays %u\n"
"dot11RSNAStatsCCMPDecryptErrors %u\n"
"dot11RSNAstatsCCMPReplays %u\n"
"dot11TransmittedAMSDUCount %u\n"
"dot11FailedAMSDUCount %u\n"
"dot11RetryAMSDUCount %u\n"
"dot11MultipleRetryAMSDUCount %u\n"
"dot11TransmittedOctetsInAMSDUCount %llu\n"
"dot11AMSDUAckFailureCount %u\n"
"dot11ReceivedAMSDUCount %u\n"
"dot11ReceivedOctetsInAMSDUCount %llu\n"
"dot11TransmittedAMPDUCount %u\n"
"dot11TransmittedMPDUsInAMPDUCount %u\n"
"dot11TransmittedOctetsInAMPDUCount %llu\n"
"dot11AMPDUReceivedCount %u\n"
"dot11MPDUInReceivedAMPDUCount %u\n"
"dot11ReceivedOctetsInAMPDUCount %llu\n"
"dot11AMPDUDelimiterCRCErrorCount %u\n",
stats->cmacicv_errors, stats->cmac_replays,
stats->mgmt_ccmp_replays, stats->tkipicv_errors,
stats->tkip_replays, stats->ccmp_decrypt_errors,
stats->ccmp_replays, stats->tx_amsdu_cnt,
stats->failed_amsdu_cnt, stats->retry_amsdu_cnt,
stats->multi_retry_amsdu_cnt,
stats->tx_octets_in_amsdu_cnt,
stats->amsdu_ack_failure_cnt, stats->rx_amsdu_cnt,
stats->rx_octets_in_amsdu_cnt, stats->tx_ampdu_cnt,
stats->tx_mpdus_in_ampdu_cnt,
stats->tx_octets_in_ampdu_cnt, stats->ampdu_rx_cnt,
stats->mpdu_in_rx_ampdu_cnt,
stats->rx_octets_in_ampdu_cnt,
stats->ampdu_delimiter_crc_error_cnt);
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
#ifdef STA_SUPPORT
/**
* @brief Get signal
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_get_signal(int argc, char *argv[])
{
#define DATA_SIZE 12
int ret = 0, data[DATA_SIZE], i = 0, copy_size = 0;
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
memset(data, 0, sizeof(data));
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Sanity tests */
if (argc < 3 || argc > 5) {
printf("Error: invalid no of arguments\n");
printf("mlanutl mlanX getsignal [m] [n]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: getsignal fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Process result */
copy_size =
(int)MIN((int)cmd->used_len, (int)(DATA_SIZE * sizeof(int)));
if (copy_size > 0)
memcpy(&data, buffer, copy_size);
printf("Get signal output is\t");
for (i = 0; i < (int)(copy_size / sizeof(int)); i++)
printf("%d\t", data[i]);
printf("\n");
done:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/**
* @brief Set signalext cfg
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_signalext_cfg(int argc, char *argv[])
{
int ret = 0;
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Sanity tests */
if (argc != 4) {
printf("Error: invalid no of arguments\n");
printf("mlanutl mlanX signalextcfg [#]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: signalext cfg fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
done:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/**
* @brief Get signal
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_get_signal_ext(int argc, char *argv[])
{
#define MAX_NUM_PATH 3
#define PATH_SIZE 13
#define PATH_A 1
#define PATH_B 2
#define PATH_AB 3
int ret = 0, data[PATH_SIZE * MAX_NUM_PATH] = {0};
int i = 0, copy_size = 0;
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
t_u8 num_path = 0;
memset(data, 0, sizeof(data));
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Sanity tests */
if (argc != 3 && argc != 4) {
printf("Error: invalid no of arguments\n");
if (strncmp(argv[2], "getsignalextv2",
strlen("getsignalextv2")) == 0)
printf("mlanutl mlanX getsignalextv2 [m]\n");
else if (strncmp(argv[2], "getsignalext",
strlen("getsignalext")) == 0)
printf("mlanutl mlanX getsignalext [m]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: getsignal fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Process result */
copy_size = cmd->used_len;
if (copy_size > 0)
memcpy(&data, (int *)buffer, copy_size);
num_path = copy_size / sizeof(int) / PATH_SIZE;
for (i = 0; i < num_path; i++) {
if (data[i * PATH_SIZE] == PATH_A)
printf("PATH A: %d %d %d %d %d %d %d %d %d %d %d %d\n",
data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2],
data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4],
data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6],
data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8],
data[i * PATH_SIZE + 9],
data[i * PATH_SIZE + 10],
data[i * PATH_SIZE + 11],
data[i * PATH_SIZE + 12]);
else if (data[i * PATH_SIZE] == PATH_B)
printf("PATH B: %d %d %d %d %d %d %d %d %d %d %d %d\n",
data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2],
data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4],
data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6],
data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8],
data[i * PATH_SIZE + 9],
data[i * PATH_SIZE + 10],
data[i * PATH_SIZE + 11],
data[i * PATH_SIZE + 12]);
else if (data[i * PATH_SIZE] == PATH_AB)
printf("PATH A+B: %d %d %d %d %d %d %d %d %d %d %d %d\n",
data[i * PATH_SIZE + 1], data[i * PATH_SIZE + 2],
data[i * PATH_SIZE + 3], data[i * PATH_SIZE + 4],
data[i * PATH_SIZE + 5], data[i * PATH_SIZE + 6],
data[i * PATH_SIZE + 7], data[i * PATH_SIZE + 8],
data[i * PATH_SIZE + 9],
data[i * PATH_SIZE + 10],
data[i * PATH_SIZE + 11],
data[i * PATH_SIZE + 12]);
}
printf("\n");
done:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
#endif /* #ifdef STA_SUPPORT */
/**
* @brief Get txpwrlimit
*
* @param argc Number of arguments
* @param argv Pointer to the arguments array
*
* @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
*/
static int get_txpwrlimit(FILE *fp_raw, char *argv[], t_u16 sub_band,
t_u8 *buffer, t_u16 len, struct eth_priv_cmd *cmd)
{
struct ifreq ifr;
mlan_ds_misc_chan_trpc_cfg *trcp_cfg = NULL;
MrvlIETypes_ChanTRPCConfig_t *trpc_tlv = NULL;
MrvlIEtypes_Data_t *pTlvHdr;
int left_len;
int mod_num = 0;
int i = 0;
int j = 0;
t_u8 *pByte = NULL;
memset(buffer, 0, len);
/* Insert command */
strncpy((char *)buffer, argv[2], strlen(argv[2]));
trcp_cfg = (mlan_ds_misc_chan_trpc_cfg *)(buffer + strlen(argv[2]));
trcp_cfg->sub_band = sub_band;
if (cmd) {
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = len;
}
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: get_txpwrlimit fail\n");
return MLAN_STATUS_FAILURE;
}
/* Process result */
printf("------------------------------------------------------------------------------------\n");
printf("Get txpwrlimit: sub_band=0x%x len=%d\n", trcp_cfg->sub_band,
trcp_cfg->length);
pByte = trcp_cfg->trpc_buf + S_DS_GEN + 4;
left_len = trcp_cfg->length - S_DS_GEN - 4;
while (left_len >= (int)sizeof(pTlvHdr->header)) {
pTlvHdr = (MrvlIEtypes_Data_t *)pByte;
pTlvHdr->header.len = le16_to_cpu(pTlvHdr->header.len);
switch (le16_to_cpu(pTlvHdr->header.type)) {
case TLV_TYPE_CHAN_TRPC_CONFIG:
trpc_tlv = (MrvlIETypes_ChanTRPCConfig_t *)pTlvHdr;
printf("StartFreq: %d\n", trpc_tlv->start_freq);
printf("ChanWidth: %d\n", trpc_tlv->width);
printf("ChanNum: %d\n", trpc_tlv->chan_num);
mod_num = (pTlvHdr->header.len - 4) /
sizeof(mod_group_setting);
printf("Pwr:");
for (i = 0; i < mod_num; i++) {
if (i == (mod_num - 1))
printf("%d,%d",
trpc_tlv->mod_group[i].mod_group,
trpc_tlv->mod_group[i].power);
else
printf("%d,%d,",
trpc_tlv->mod_group[i].mod_group,
trpc_tlv->mod_group[i].power);
}
printf("\n");
break;
default:
break;
}
left_len -= (pTlvHdr->header.len + sizeof(pTlvHdr->header));
pByte += pTlvHdr->header.len + sizeof(pTlvHdr->header);
}
if (fp_raw) {
switch (sub_band) {
case 0:
fprintf(fp_raw, "txpwrlimit_2g_get={\n");
break;
case 0x10:
fprintf(fp_raw, "txpwrlimit_5g_sub0_get={\n");
break;
case 0x11:
fprintf(fp_raw, "txpwrlimit_5g_sub1_get={\n");
break;
case 0x12:
fprintf(fp_raw, "txpwrlimit_5g_sub2_get={\n");
break;
case 0x13:
fprintf(fp_raw, "txpwrlimit_5g_sub3_get={\n");
break;
default:
break;
}
i = j = 0;
while (i < trcp_cfg->length) {
for (j = 0; j < 16; j++) {
fprintf(fp_raw, "%02x ", trcp_cfg->trpc_buf[i]);
if (++i >= trcp_cfg->length)
break;
}
fputc('\n', fp_raw);
}
fprintf(fp_raw, "}\n\n");
}
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Get txpwrlimit
*
* @param argc Number of arguments
* @param argv Pointer to the arguments array
*
* @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
*/
static int process_get_txpwrlimit(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
int ret = MLAN_STATUS_SUCCESS;
t_u16 sub_band = 0;
FILE *fp_raw = NULL;
/* Initialize buffer */
buffer = (t_u8 *)malloc(sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]));
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, sizeof(mlan_ds_misc_chan_trpc_cfg) + strlen(argv[2]));
/* Sanity tests */
if (argc < 4) {
printf("Error: invalid no of arguments\n");
printf("mlanutl mlanX/uapX get_txpwrlimit [0/0x10/0x11/0x12/0x13/0x1f/0xff]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
sub_band = a2hex_or_atoi(argv[3]);
if (argc == 5) {
fp_raw = fopen(argv[4], "w");
if (fp_raw == NULL) {
fprintf(stderr,
"Cannot open the destination raw_data file %s\n",
argv[4]);
ret = MLAN_STATUS_FAILURE;
goto done;
}
}
switch (sub_band) {
case 0:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
ret = get_txpwrlimit(fp_raw, argv, sub_band, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
break;
case 0x1f:
ret = get_txpwrlimit(fp_raw, argv, 0x10, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x11, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x12, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x13, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
break;
case 0xff:
ret = get_txpwrlimit(fp_raw, argv, 0, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x10, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x11, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x12, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
ret = get_txpwrlimit(fp_raw, argv, 0x13, buffer,
sizeof(mlan_ds_misc_chan_trpc_cfg) +
strlen(argv[2]),
cmd);
break;
default:
printf("Error: invalid arguments\n");
printf("mlanutl mlanX/uapX get_txpwrlimit [0/0x10/0x11/0x12/0x13/0x1f/0xff]\n");
break;
}
done:
if (fp_raw)
fclose(fp_raw);
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/**
* @brief Process VHT configuration
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_vhtcfg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct eth_priv_vhtcfg vhtcfg;
struct ifreq ifr;
t_u8 i, num = 0;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
/* Sanity tests */
if (argc < 5) {
printf("Insufficient parameters\n");
printf("For STA interface: mlanutl mlanX vhtcfg <band> <txrx> [bwcfg] [vhtcap]\n");
printf("For uAP interface: mlanutl uapX vhtcfg <band> <txrx> [bwcfg] [vhtcap] [vht_tx_mcs] [vht_rx_mcs]\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: vhtcfg fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
/* the first attribute is the number of vhtcfg entries */
num = *buffer;
if (argc == 5) {
/* GET operation */
printf("11AC VHT Configuration: \n");
for (i = 0; i < num; i++) {
memcpy(&vhtcfg, buffer + 1 + i * sizeof(vhtcfg),
sizeof(vhtcfg));
/* Band */
if (vhtcfg.band == 1)
printf("Band: 2.4G\n");
else
printf("Band: 5G\n");
/* BW confi9 */
if (vhtcfg.bwcfg == 0)
printf(" BW config: Follow BW in the 11N config\n");
else
printf(" BW config: Follow BW in VHT Capabilities\n");
/* Tx/Rx */
if (vhtcfg.txrx & 0x1)
printf(" VHT operation for Tx: 0x%08x\n",
vhtcfg.vht_cap_info);
if (vhtcfg.txrx & 0x2)
/* VHT capabilities */
printf(" VHT Capabilities Info: 0x%08x\n",
vhtcfg.vht_cap_info);
/* MCS */
if (vhtcfg.txrx & 0x2) {
printf(" Tx MCS set: 0x%04x\n",
vhtcfg.vht_tx_mcs);
printf(" Rx MCS set: 0x%04x\n",
vhtcfg.vht_rx_mcs);
}
}
} else {
/* SET operation */
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process dynamic bandwidth set/get
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_dyn_bw(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
int dyn_bw = 0;
/* Check arguments */
if (argc < 3 || argc > 4) {
printf("ERR:Incorrect number of arguments!\n");
printf("Syntax: ./mlanutl mlanX dyn_bw <bw>\n");
return MLAN_STATUS_FAILURE;
}
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: dyn_bw fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
dyn_bw = *(int *)buffer;
printf("Dynamic bandwidth: 0x%02x\n", dyn_bw);
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process HT Tx configuration
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_httxcfg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
t_u32 *data = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: httxcfg fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
if (argc == 3) {
/* Get result */
data = (t_u32 *)buffer;
printf("HT Tx cfg: \n");
printf(" BG band: 0x%08x\n", data[0]);
printf(" A band: 0x%08x\n", data[1]);
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process HT capability configuration
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_htcapinfo(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct eth_priv_htcapinfo *ht_cap = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: htcapinfo fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
if (argc == 3) {
ht_cap = (struct eth_priv_htcapinfo *)buffer;
printf("HT cap info: \n");
printf(" BG band: 0x%08x\n", ht_cap->ht_cap_info_bg);
printf(" A band: 0x%08x\n", ht_cap->ht_cap_info_a);
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process HT Add BA parameters
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_addbapara(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
struct eth_priv_addba *addba = NULL;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: addbapara fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
if (argc == 3) {
/* Get */
addba = (struct eth_priv_addba *)buffer;
printf("Add BA configuration: \n");
printf(" Time out : %d\n", addba->time_out);
printf(" TX window: %d\n", addba->tx_win_size);
printf(" RX window: %d\n", addba->rx_win_size);
printf(" TX AMSDU : %d\n", addba->tx_amsdu);
printf(" RX AMSDU : %d\n", addba->rx_amsdu);
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process Aggregation priority table parameters
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_aggrpriotbl(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
int i;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: aggrpriotbl fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
if (argc == 3) {
/* Get */
printf("Aggregation priority table cfg: \n");
printf(" TID AMPDU AMSDU \n");
for (i = 0; i < MAX_NUM_TID; i++) {
printf(" %d %3d %3d \n", i,
buffer[2 * i], buffer[2 * i + 1]);
}
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process HT Add BA reject configurations
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_addbareject(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
int i;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: addbareject fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
if (argc == 3) {
/* Get */
printf("Add BA reject configuration: \n");
printf(" TID Reject \n");
for (i = 0; i < MAX_NUM_TID; i++) {
printf(" %d %d\n", i, buffer[i]);
}
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
#define MASK_11AX_OM_CONTROL 0xFFF
/**
* @brief 11ax HE capability and operation configure
*
* @param argc Number of arguments
* @param argv Pointer to the arguments array
*
* @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
*/
static int process_11axcfg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd;
struct ifreq ifr;
int id_len = 0;
FILE *fp = NULL;
int ret = 0, cmd_header_len = 0;
char config_id[20];
char filename[256];
if (argc != 3 && argc != 4) {
printf("Err: Invalid number of arguments\n");
printf("Usage: ./mlanutl <interface> 11axcfg [11axcfg.conf]\n");
return MLAN_STATUS_FAILURE;
}
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
cmd_header_len = strlen(CMD_NXP) + strlen(argv[2]);
prepare_buffer(buffer, argv[2], 0, NULL);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = cmd_header_len;
cmd->total_len = BUFFER_LENGTH;
if (argc == 4) {
memset(filename, 0, sizeof(filename));
strncpy(filename, argv[3], sizeof(filename) - 1);
fp = fopen(filename, "r");
if (fp == NULL) {
perror("fopen");
fprintf(stderr, "Cannot open file %s\n", argv[3]);
ret = -EFAULT;
;
goto done;
}
snprintf(config_id, sizeof(config_id), "Band");
id_len = fparse_for_cmd_and_hex(fp, buffer + cmd_header_len,
(t_u8 *)config_id);
snprintf(config_id, sizeof(config_id), "HECap");
id_len +=
fparse_for_cmd_and_hex(fp,
buffer + cmd_header_len + id_len,
(t_u8 *)config_id);
hexdump("Set 11axcfg", buffer + cmd_header_len,
sizeof(mlan_ds_11ax_he_cfg), ' ');
cmd->used_len = cmd_header_len + sizeof(mlan_ds_11ax_he_cfg);
}
/* Initialize the ifr structure */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl: 11axcfg");
ret = -EFAULT;
goto done;
}
hexdump("11axcfg", buffer + cmd_header_len, sizeof(mlan_ds_11ax_he_cfg),
' ');
done:
if (fp)
fclose(fp);
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/**
* @brief Process 11ax command
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_11axcmdcfg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
mlan_ds_11ax_cmd_cfg *axcmd = NULL;
t_u32 action = 0;
t_u32 prefix_len = 0;
if (strcmp(argv[3], "tx_omi") == 0) {
sprintf(argv[3], "%d", MLAN_11AXCMD_CFG_ID_TX_OMI);
} else if (strcmp(argv[3], "obssnbru_toltime") == 0) {
sprintf(argv[3], "%d", MLAN_11AXCMD_CFG_ID_OBSSNBRU_TOLTIME);
} else {
printf("ERR:unknown command %s!\n", argv[3]);
return MLAN_STATUS_FAILURE;
}
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = strlen((char *)buffer);
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: 11axcmd fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
prefix_len += strlen(CMD_NXP) + strlen(argv[2]);
action = *(t_u32 *)(buffer + prefix_len);
if (action == MLAN_ACT_SET) {
if (argv[4] == 0) {
printf("Invalid OBSSNBRU tolerance time: Valid range[1..3600]\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
}
if (action == MLAN_ACT_GET) {
axcmd = (mlan_ds_11ax_cmd_cfg *)(buffer + prefix_len +
sizeof(t_u32));
switch (axcmd->sub_id) {
case MLAN_11AXCMD_TXOMI_SUBID:
printf("tx OMI: 0x%x\n", axcmd->param.txomi_cfg.omi &
MASK_11AX_OM_CONTROL);
break;
case MLAN_11AXCMD_OBSS_TOLTIME_SUBID:
if (axcmd->param.toltime_cfg.tol_time > 3600 ||
!axcmd->param.toltime_cfg.tol_time)
printf("OBSS Narrow Bandwidth RU tolerance Time: disabled\n");
else
printf("OBSS Narrow Bandwidth RU Tolerance Time: %d sec\n",
axcmd->param.toltime_cfg.tol_time);
break;
default:
printf("Unknown sub_command 0x%x\n", axcmd->sub_id);
break;
}
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process tx rate configuration
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_txratecfg(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct eth_priv_tx_rate_cfg *txratecfg = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: txratecfg fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
txratecfg = (struct eth_priv_tx_rate_cfg *)buffer;
if (argc == 3) {
/* GET operation */
printf("Tx Rate Configuration: \n");
/* format */
if (txratecfg->rate_format == 0xFF) {
printf(" Type: 0xFF (Auto)\n");
} else if (txratecfg->rate_format <= 3) {
printf(" Type: %d (%s)\n",
txratecfg->rate_format,
rate_format[txratecfg->rate_format]);
if (txratecfg->rate_format == 0)
printf(" Rate Index: %d (%s)\n",
txratecfg->rate_index,
lg_rate[txratecfg->rate_index]);
else if (txratecfg->rate_format >= 1)
printf(" MCS Index: %d\n",
(int)txratecfg->rate_index);
if (txratecfg->rate_format == 2 ||
txratecfg->rate_format == 3)
printf(" NSS: %d\n",
(int)txratecfg->nss);
if (txratecfg->rate_setting == 0xffff)
printf("Rate setting :Preamble type/BW/GI/STBC/.. : auto \n");
else {
printf("Preamble type: %x\n",
(txratecfg->rate_setting & 0x0003));
printf("BW: %x\n",
(txratecfg->rate_setting & 0x001C) >> 2);
printf("LTF + GI size %x\n",
(txratecfg->rate_setting & 0x0060) >> 5);
printf("STBC %x\n",
(txratecfg->rate_setting & 0x0080) >> 7);
printf("DCM %x\n",
(txratecfg->rate_setting & 0x0100) >> 8);
printf("Coding %x\n",
(txratecfg->rate_setting & 0x0200) >> 9);
printf("maxPE %x\n",
(txratecfg->rate_setting & 0x3000) >>
12);
}
} else {
printf(" Unknown rate format.\n");
}
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Process host_cmd response
* @param cmd_name Command name
* @param buf A pointer to the response buffer
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
int process_host_cmd_resp(char *cmd_name, t_u8 *buf)
{
t_u32 hostcmd_size = 0;
HostCmd_DS_GEN *hostcmd = NULL;
int ret = MLAN_STATUS_SUCCESS;
buf += strlen(CMD_NXP) + strlen(cmd_name);
memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32));
buf += sizeof(t_u32);
hostcmd = (HostCmd_DS_GEN *)buf;
hostcmd->command = le16_to_cpu(hostcmd->command);
hostcmd->size = le16_to_cpu(hostcmd->size);
hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num);
hostcmd->result = le16_to_cpu(hostcmd->result);
hostcmd->command &= ~HostCmd_RET_BIT;
if (!hostcmd->result) {
switch (hostcmd->command) {
case HostCmd_CMD_CFG_DATA: {
HostCmd_DS_802_11_CFG_DATA *pstcfgData =
(HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN);
pstcfgData->data_len =
le16_to_cpu(pstcfgData->data_len);
pstcfgData->action = le16_to_cpu(pstcfgData->action);
if (pstcfgData->action == HostCmd_ACT_GEN_GET) {
hexdump("cfgdata", pstcfgData->data,
pstcfgData->data_len, ' ');
}
break;
}
case HostCmd_CMD_802_11_TPC_ADAPT_REQ: {
mlan_ioctl_11h_tpc_resp *tpcIoctlResp =
(mlan_ioctl_11h_tpc_resp *)(buf + S_DS_GEN);
if (tpcIoctlResp->status_code == 0) {
printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n",
tpcIoctlResp->tx_power,
tpcIoctlResp->link_margin,
tpcIoctlResp->rssi);
} else {
printf("tpcrequest: failure, status = %d\n",
tpcIoctlResp->status_code);
}
break;
}
case HostCmd_CMD_802_11_CRYPTO: {
t_u16 alg = le16_to_cpu(
(t_u16) * (buf + S_DS_GEN + sizeof(t_u16)));
if (alg == CIPHER_TEST_AES_CCM ||
alg == CIPHER_TEST_GCMP) {
HostCmd_DS_802_11_CRYPTO_AES_CCM *cmd_aes_ccm =
(HostCmd_DS_802_11_CRYPTO_AES_CCM
*)(buf + S_DS_GEN);
cmd_aes_ccm->encdec =
le16_to_cpu(cmd_aes_ccm->encdec);
cmd_aes_ccm->algorithm =
le16_to_cpu(cmd_aes_ccm->algorithm);
cmd_aes_ccm->key_length =
le16_to_cpu(cmd_aes_ccm->key_length);
cmd_aes_ccm->nonce_length =
le16_to_cpu(cmd_aes_ccm->nonce_length);
cmd_aes_ccm->AAD_length =
le16_to_cpu(cmd_aes_ccm->AAD_length);
cmd_aes_ccm->data.header.type = le16_to_cpu(
cmd_aes_ccm->data.header.type);
cmd_aes_ccm->data.header.len = le16_to_cpu(
cmd_aes_ccm->data.header.len);
printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d,"
" NonceLen=%d,AADLen=%d,dataLen=%d\n",
cmd_aes_ccm->encdec,
cmd_aes_ccm->algorithm,
cmd_aes_ccm->key_length,
cmd_aes_ccm->nonce_length,
cmd_aes_ccm->AAD_length,
cmd_aes_ccm->data.header.len);
hexdump("Key", cmd_aes_ccm->key,
cmd_aes_ccm->key_length, ' ');
hexdump("Nonce", cmd_aes_ccm->nonce,
cmd_aes_ccm->nonce_length, ' ');
hexdump("AAD", cmd_aes_ccm->AAD,
cmd_aes_ccm->AAD_length, ' ');
hexdump("Data", cmd_aes_ccm->data.data,
cmd_aes_ccm->data.header.len, ' ');
} else if (alg == CIPHER_TEST_WAPI) {
HostCmd_DS_802_11_CRYPTO_WAPI *cmd_wapi =
(HostCmd_DS_802_11_CRYPTO_WAPI
*)(buf + S_DS_GEN);
cmd_wapi->encdec =
le16_to_cpu(cmd_wapi->encdec);
cmd_wapi->algorithm =
le16_to_cpu(cmd_wapi->algorithm);
cmd_wapi->key_length =
le16_to_cpu(cmd_wapi->key_length);
cmd_wapi->nonce_length =
le16_to_cpu(cmd_wapi->nonce_length);
cmd_wapi->AAD_length =
le16_to_cpu(cmd_wapi->AAD_length);
printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d,"
" NonceLen=%d,AADLen=%d,dataLen=%d\n",
cmd_wapi->encdec, cmd_wapi->algorithm,
cmd_wapi->key_length,
cmd_wapi->nonce_length,
cmd_wapi->AAD_length,
cmd_wapi->data_length);
hexdump("Key", cmd_wapi->key,
cmd_wapi->key_length, ' ');
hexdump("Nonce", cmd_wapi->nonce,
cmd_wapi->nonce_length, ' ');
hexdump("AAD", cmd_wapi->AAD,
cmd_wapi->AAD_length, ' ');
} else {
HostCmd_DS_802_11_CRYPTO *cmd =
(HostCmd_DS_802_11_CRYPTO *)(buf +
S_DS_GEN);
cmd->encdec = le16_to_cpu(cmd->encdec);
cmd->algorithm = le16_to_cpu(cmd->algorithm);
cmd->key_IV_length =
le16_to_cpu(cmd->key_IV_length);
cmd->key_length = le16_to_cpu(cmd->key_length);
cmd->data.header.type =
le16_to_cpu(cmd->data.header.type);
cmd->data.header.len =
le16_to_cpu(cmd->data.header.len);
printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d,"
" KeyLen=%d,dataLen=%d\n",
cmd->encdec, cmd->algorithm,
cmd->key_IV_length, cmd->key_length,
cmd->data.header.len);
hexdump("KeyIV", cmd->keyIV, cmd->key_IV_length,
' ');
hexdump("Key", cmd->key, cmd->key_length, ' ');
hexdump("Data", cmd->data.data,
cmd->data.header.len, ' ');
}
break;
}
case HostCmd_CMD_802_11_AUTO_TX: {
HostCmd_DS_802_11_AUTO_TX *at =
(HostCmd_DS_802_11_AUTO_TX *)(buf + S_DS_GEN);
if (le16_to_cpu(at->action) == HostCmd_ACT_GEN_GET) {
if (S_DS_GEN + sizeof(at->action) ==
hostcmd->size) {
printf("auto_tx not configured\n");
} else {
MrvlIEtypesHeader_t *header =
&at->auto_tx.header;
header->type =
le16_to_cpu(header->type);
header->len = le16_to_cpu(header->len);
if ((S_DS_GEN + sizeof(at->action) +
sizeof(MrvlIEtypesHeader_t) +
header->len ==
hostcmd->size) &&
(header->type ==
TLV_TYPE_AUTO_TX)) {
AutoTx_MacFrame_t *atmf =
&at->auto_tx
.auto_tx_mac_frame;
printf("Interval: %d second(s)\n",
le16_to_cpu(
atmf->interval));
printf("Priority: %#x\n",
atmf->priority);
printf("Frame Length: %d\n",
le16_to_cpu(
atmf->frame_len));
printf("Dest Mac Address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
atmf->dest_mac_addr[0],
atmf->dest_mac_addr[1],
atmf->dest_mac_addr[2],
atmf->dest_mac_addr[3],
atmf->dest_mac_addr[4],
atmf->dest_mac_addr[5]);
printf("Src Mac Address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
atmf->src_mac_addr[0],
atmf->src_mac_addr[1],
atmf->src_mac_addr[2],
atmf->src_mac_addr[3],
atmf->src_mac_addr[4],
atmf->src_mac_addr[5]);
hexdump("Frame Payload",
atmf->payload,
le16_to_cpu(
atmf->frame_len) -
MLAN_MAC_ADDR_LENGTH *
2,
' ');
} else {
printf("incorrect auto_tx command response\n");
}
}
}
break;
}
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: {
HostCmd_DS_802_11_SUBSCRIBE_EVENT *se =
(HostCmd_DS_802_11_SUBSCRIBE_EVENT *)(buf +
S_DS_GEN);
if (le16_to_cpu(se->action) == HostCmd_ACT_GEN_GET) {
int len =
S_DS_GEN +
sizeof(HostCmd_DS_802_11_SUBSCRIBE_EVENT);
printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
while (len < hostcmd->size) {
MrvlIEtypesHeader_t *header =
(MrvlIEtypesHeader_t *)(buf +
len);
switch (le16_to_cpu(header->type)) {
case TLV_TYPE_RSSI_LOW: {
MrvlIEtypes_RssiThreshold_t *low_rssi =
(MrvlIEtypes_RssiThreshold_t
*)(buf + len);
printf("Beacon Low RSSI\t%d\t%d\t%s\n",
low_rssi->RSSI_value,
low_rssi->RSSI_freq,
(le16_to_cpu(se->events) &
0x0001) ?
"yes" :
"no");
break;
}
case TLV_TYPE_SNR_LOW: {
MrvlIEtypes_SnrThreshold_t *low_snr =
(MrvlIEtypes_SnrThreshold_t
*)(buf + len);
printf("Beacon Low SNR\t%d\t%d\t%s\n",
low_snr->SNR_value,
low_snr->SNR_freq,
(le16_to_cpu(se->events) &
0x0002) ?
"yes" :
"no");
break;
}
case TLV_TYPE_FAILCOUNT: {
MrvlIEtypes_FailureCount_t
*failure_count =
(MrvlIEtypes_FailureCount_t
*)(buf +
len);
printf("Failure Count\t%d\t%d\t%s\n",
failure_count->fail_value,
failure_count->fail_freq,
(le16_to_cpu(se->events) &
0x0004) ?
"yes" :
"no");
break;
}
case TLV_TYPE_BCNMISS: {
MrvlIEtypes_BeaconsMissed_t
*bcn_missed =
(MrvlIEtypes_BeaconsMissed_t
*)(buf +
len);
printf("Beacon Missed\t%d\tN/A\t%s\n",
bcn_missed->beacon_missed,
(le16_to_cpu(se->events) &
0x0008) ?
"yes" :
"no");
break;
}
case TLV_TYPE_RSSI_HIGH: {
MrvlIEtypes_RssiThreshold_t
*high_rssi =
(MrvlIEtypes_RssiThreshold_t
*)(buf +
len);
printf("Bcn High RSSI\t%d\t%d\t%s\n",
high_rssi->RSSI_value,
high_rssi->RSSI_freq,
(le16_to_cpu(se->events) &
0x0010) ?
"yes" :
"no");
break;
}
case TLV_TYPE_SNR_HIGH: {
MrvlIEtypes_SnrThreshold_t *high_snr =
(MrvlIEtypes_SnrThreshold_t
*)(buf + len);
printf("Beacon High SNR\t%d\t%d\t%s\n",
high_snr->SNR_value,
high_snr->SNR_freq,
(le16_to_cpu(se->events) &
0x0020) ?
"yes" :
"no");
break;
}
case TLV_TYPE_RSSI_LOW_DATA: {
MrvlIEtypes_RssiThreshold_t *low_rssi =
(MrvlIEtypes_RssiThreshold_t
*)(buf + len);
printf("Data Low RSSI\t%d\t%d\t%s\n",
low_rssi->RSSI_value,
low_rssi->RSSI_freq,
(le16_to_cpu(se->events) &
0x0040) ?
"yes" :
"no");
break;
}
case TLV_TYPE_SNR_LOW_DATA: {
MrvlIEtypes_SnrThreshold_t *low_snr =
(MrvlIEtypes_SnrThreshold_t
*)(buf + len);
printf("Data Low SNR\t%d\t%d\t%s\n",
low_snr->SNR_value,
low_snr->SNR_freq,
(le16_to_cpu(se->events) &
0x0080) ?
"yes" :
"no");
break;
}
case TLV_TYPE_RSSI_HIGH_DATA: {
MrvlIEtypes_RssiThreshold_t
*high_rssi =
(MrvlIEtypes_RssiThreshold_t
*)(buf +
len);
printf("Data High RSSI\t%d\t%d\t%s\n",
high_rssi->RSSI_value,
high_rssi->RSSI_freq,
(le16_to_cpu(se->events) &
0x0100) ?
"yes" :
"no");
break;
}
case TLV_TYPE_SNR_HIGH_DATA: {
MrvlIEtypes_SnrThreshold_t *high_snr =
(MrvlIEtypes_SnrThreshold_t
*)(buf + len);
printf("Data High SNR\t%d\t%d\t%s\n",
high_snr->SNR_value,
high_snr->SNR_freq,
(le16_to_cpu(se->events) &
0x0200) ?
"yes" :
"no");
break;
}
case TLV_TYPE_LINK_QUALITY: {
MrvlIEtypes_LinkQuality_t *link_qual =
(MrvlIEtypes_LinkQuality_t
*)(buf + len);
printf("Link Quality Parameters:\n");
printf("------------------------\n");
printf("Link Quality Event Subscribed\t%s\n",
(le16_to_cpu(se->events) &
0x0400) ?
"yes" :
"no");
printf("Link SNR Threshold = %d\n",
le16_to_cpu(
link_qual
->link_SNR_thrs));
printf("Link SNR Frequency = %d\n",
le16_to_cpu(
link_qual
->link_SNR_freq));
printf("Min Rate Value = %d\n",
le16_to_cpu(
link_qual
->min_rate_val));
printf("Min Rate Frequency = %d\n",
le16_to_cpu(
link_qual
->min_rate_freq));
printf("Tx Latency Value = %d\n",
le32_to_cpu(
link_qual
->tx_latency_val));
printf("Tx Latency Threshold = %d\n",
le32_to_cpu(
link_qual
->tx_latency_thrs));
break;
}
case TLV_TYPE_PRE_BEACON_LOST: {
MrvlIEtypes_PreBeaconLost_t
*pre_bcn_lost =
(MrvlIEtypes_PreBeaconLost_t
*)(buf +
len);
printf("------------------------\n");
printf("Pre-Beacon Lost Event Subscribed\t%s\n",
(le16_to_cpu(se->events) &
0x0800) ?
"yes" :
"no");
printf("Pre-Beacon Lost: %d\n",
pre_bcn_lost
->pre_beacon_lost);
break;
}
default:
printf("Unknown subscribed event TLV Type=%#x,"
" Len=%d\n",
le16_to_cpu(
header->type),
le16_to_cpu(
header->len));
break;
}
len += (sizeof(MrvlIEtypesHeader_t) +
le16_to_cpu(header->len));
}
}
break;
}
case HostCmd_CMD_MAC_REG_ACCESS:
case HostCmd_CMD_BBP_REG_ACCESS:
case HostCmd_CMD_RF_REG_ACCESS:
case HostCmd_CMD_CAU_REG_ACCESS: {
HostCmd_DS_REG *preg =
(HostCmd_DS_REG *)(buf + S_DS_GEN);
preg->action = le16_to_cpu(preg->action);
if (preg->action == HostCmd_ACT_GEN_GET) {
preg->value = le32_to_cpu(preg->value);
printf("value = 0x%08x\n", preg->value);
}
break;
}
case HostCmd_CMD_MEM_ACCESS: {
HostCmd_DS_MEM *pmem =
(HostCmd_DS_MEM *)(buf + S_DS_GEN);
pmem->action = le16_to_cpu(pmem->action);
if (pmem->action == HostCmd_ACT_GEN_GET) {
pmem->value = le32_to_cpu(pmem->value);
printf("value = 0x%08x\n", pmem->value);
}
break;
}
case HostCmd_CMD_LINK_STATS_SUMMARY: {
HostCmd_DS_LINK_STATS_SUMMARY *linkstats =
(HostCmd_DS_LINK_STATS_SUMMARY *)(buf +
S_DS_GEN);
/* GET operation */
printf("Link Statistics: \n");
/* format */
printf("Duration: %u\n",
(int)le32_to_cpu(
linkstats->timeSinceLastQuery_ms));
printf("Beacon count: %u\n",
le16_to_cpu(linkstats->bcnCnt));
printf("Beacon missing: %u\n",
le16_to_cpu(linkstats->bcnMiss));
printf("Beacon RSSI avg: %d\n",
le16_to_cpu(linkstats->bcnRssiAvg));
printf("Beacon SNR avg: %d\n",
le16_to_cpu(linkstats->bcnSnrAvg));
printf("Rx packets: %u\n",
(int)le32_to_cpu(linkstats->rxPkts));
printf("Rx RSSI avg: %d\n",
le16_to_cpu(linkstats->rxRssiAvg));
printf("Rx SNR avg: %d\n",
le16_to_cpu(linkstats->rxSnrAvg));
printf("Tx packets: %u\n",
(int)le32_to_cpu(linkstats->txPkts));
printf("Tx Attempts: %u\n",
(int)le32_to_cpu(linkstats->txAttempts));
printf("Tx Failures: %u\n",
(int)le32_to_cpu(linkstats->txFailures));
printf("Tx Initial Rate: %s\n",
rateIdStr[linkstats->txInitRate]);
printf("Tx AC VO: %u [ %u ]\n",
le16_to_cpu(linkstats->txQueuePktCnt[WMM_AC_VO]),
(int)le32_to_cpu(
linkstats->txQueueDelay[WMM_AC_VO]) /
1000);
printf("Tx AC VI: %u [ %u ]\n",
le16_to_cpu(linkstats->txQueuePktCnt[WMM_AC_VI]),
(int)le32_to_cpu(
linkstats->txQueueDelay[WMM_AC_VI]) /
1000);
printf("Tx AC BE: %u [ %u ]\n",
le16_to_cpu(linkstats->txQueuePktCnt[WMM_AC_BE]),
(int)le32_to_cpu(
linkstats->txQueueDelay[WMM_AC_BE]) /
1000);
printf("Tx AC BK: %u [ %u ]\n",
le16_to_cpu(linkstats->txQueuePktCnt[WMM_AC_BK]),
(int)le32_to_cpu(
linkstats->txQueueDelay[WMM_AC_BK]) /
1000);
break;
}
case HostCmd_CMD_WMM_PARAM_CONFIG: {
HostCmd_DS_WMM_PARAM_CONFIG *wmm_param =
(HostCmd_DS_WMM_PARAM_CONFIG *)(buf + S_DS_GEN);
printf("WMM Params: \n");
printf("\tBE: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
wmm_param->ac_params[AC_BE].aci_aifsn.aifsn,
wmm_param->ac_params[AC_BE].ecw.ecw_max,
wmm_param->ac_params[AC_BE].ecw.ecw_min,
le16_to_cpu(
wmm_param->ac_params[AC_BE].tx_op_limit));
printf("\tBK: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
wmm_param->ac_params[AC_BK].aci_aifsn.aifsn,
wmm_param->ac_params[AC_BK].ecw.ecw_max,
wmm_param->ac_params[AC_BK].ecw.ecw_min,
le16_to_cpu(
wmm_param->ac_params[AC_BK].tx_op_limit));
printf("\tVI: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
wmm_param->ac_params[AC_VI].aci_aifsn.aifsn,
wmm_param->ac_params[AC_VI].ecw.ecw_max,
wmm_param->ac_params[AC_VI].ecw.ecw_min,
le16_to_cpu(
wmm_param->ac_params[AC_VI].tx_op_limit));
printf("\tVO: AIFSN=%d, CW_MAX=%d CW_MIN=%d, TXOP=%d\n",
wmm_param->ac_params[AC_VO].aci_aifsn.aifsn,
wmm_param->ac_params[AC_VO].ecw.ecw_max,
wmm_param->ac_params[AC_VO].ecw.ecw_min,
le16_to_cpu(
wmm_param->ac_params[AC_VO].tx_op_limit));
break;
}
case HostCmd_ROBUST_COEX: {
host_RobustCoexLteStats_t *RobustCoexLteStat =
(host_RobustCoexLteStats_t *)(buf + S_DS_GEN);
if (RobustCoexLteStat->ResponseType ==
EXT_LTE_RESP_GETSTAT) {
printf("==============LTE COEX STATS================\n");
printf("Responsetype: %d \n",
RobustCoexLteStat->ResponseType);
printf("Count_LTE_TX_NOTIFY: %d \n",
(unsigned int)le32_to_cpu(
RobustCoexLteStat
->Count_LTE_TX_NOTIFY));
printf("Count_LTE_RX_PROTECT: %d \n",
(unsigned int)le32_to_cpu(
RobustCoexLteStat
->Count_LTE_RX_PROTECT));
printf("Count_LTE_TX_SUSPEND: %d \n",
(unsigned int)le32_to_cpu(
RobustCoexLteStat
->Count_LTE_TX_SUSPEND));
printf("Count_LTE_RX_NOTIFY: %d \n",
(unsigned int)le32_to_cpu(
RobustCoexLteStat
->Count_LTE_RX_NOTIFY));
} else if (RobustCoexLteStat->ResponseType ==
EXT_LTE_RESP_RSTSTAT) {
printf("LTE STAT Counters cleared \n");
} else // else print default cmdresp
{
printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
" SeqNum=%#04x, Result=%#04x\n",
hostcmd->command, hostcmd->size,
hostcmd->seq_num, hostcmd->result);
hexdump("payload", (t_void *)(buf + S_DS_GEN),
hostcmd->size - S_DS_GEN, ' ');
}
} break;
default:
printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
" SeqNum=%#04x, Result=%#04x\n",
hostcmd->command, hostcmd->size,
hostcmd->seq_num, hostcmd->result);
hexdump("payload", (t_void *)(buf + S_DS_GEN),
hostcmd->size - S_DS_GEN, ' ');
break;
}
} else {
printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x,"
" SeqNum=%#04x, Result=%#04x\n",
hostcmd->command, hostcmd->size, hostcmd->seq_num,
hostcmd->result);
}
return ret;
}
/**
* @brief Process hssetpara configuration
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_hssetpara(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return MLAN_STATUS_FAILURE;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: hssetpara fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_SUCCESS;
}
#define STACK_NBYTES 100 /**< Number of bytes in stack */
#define MAX_BYTESEQ 6 /**< Maximum byte sequence */
#define TYPE_DNUM 1 /**< decimal number */
#define TYPE_BYTESEQ 2 /**< byte sequence */
#define MAX_OPERAND 0x40 /**< Maximum operands */
#define TYPE_EQ (MAX_OPERAND + 1) /**< byte comparison: == operator */
#define TYPE_EQ_DNUM (MAX_OPERAND + 2) /**< decimal comparison: =d operator */
#define TYPE_EQ_BIT (MAX_OPERAND + 3) /**< bit comparison: =b operator */
#define TYPE_AND (MAX_OPERAND + 4) /**< && operator */
#define TYPE_OR (MAX_OPERAND + 5) /**< || operator */
typedef struct {
t_u16 sp; /**< Stack pointer */
t_u8 byte[STACK_NBYTES]; /**< Stack */
} mstack_t;
typedef struct {
t_u8 type; /**< Type */
t_u8 reserve[3]; /**< so 4-byte align val array */
/* byte sequence is the largest among all the operands and operators. */
/* byte sequence format: 1 byte of num of bytes, then variable num bytes
*/
t_u8 val[MAX_BYTESEQ + 1]; /**< Value */
} op_t;
/**
* @brief push data to stack
*
* @param s a pointer to mstack_t structure
*
* @param nbytes number of byte to push to stack
*
* @param val a pointer to data buffer
*
* @return TRUE-- sucess , FALSE -- fail
*
*/
static int push_n(mstack_t *s, t_u8 nbytes, t_u8 *val)
{
if ((s->sp + nbytes) < STACK_NBYTES) {
memcpy((void *)(s->byte + s->sp), (const void *)val,
(size_t)nbytes);
s->sp += nbytes;
/* printf("push: n %d sp %d\n", nbytes, s->sp); */
return TRUE;
} else /* stack full */
return FALSE;
}
/**
* @brief push data to stack
*
* @param s a pointer to mstack_t structure
*
* @param op a pointer to op_t structure
*
* @return TRUE-- sucess , FALSE -- fail
*
*/
static int push(mstack_t *s, op_t *op)
{
t_u8 nbytes;
switch (op->type) {
case TYPE_DNUM:
if (push_n(s, 4, op->val))
return push_n(s, 1, &op->type);
return FALSE;
case TYPE_BYTESEQ:
nbytes = op->val[0];
if (push_n(s, nbytes, op->val + 1) && push_n(s, 1, op->val) &&
push_n(s, 1, &op->type))
return TRUE;
return FALSE;
default:
return push_n(s, 1, &op->type);
}
}
/**
* @brief parse RPN string
*
* @param s a pointer to Null-terminated string to scan.
*
* @param first_time a pointer to return first_time
*
* @return A pointer to the last token found in string.
* NULL is returned when there are no more tokens to be
* found.
*
*/
static char *getop(char *s, int *first_time)
{
const char delim[] = " \t\n";
char *p;
if (*first_time) {
p = strtok(s, delim);
*first_time = FALSE;
} else {
p = strtok(NULL, delim);
}
return p;
}
/**
* @brief Verify hex digit.
*
* @param c input ascii char
* @param h a pointer to return integer value of the digit
* char.
* @return TURE -- c is hex digit, FALSE -- c is not hex
* digit.
*/
static int ishexdigit(char c, t_u8 *h)
{
if (c >= '0' && c <= '9') {
*h = c - '0';
return TRUE;
} else if (c >= 'a' && c <= 'f') {
*h = c - 'a' + 10;
return TRUE;
} else if (c >= 'A' && c <= 'F') {
*h = c - 'A' + 10;
return TRUE;
}
return FALSE;
}
/**
* @brief convert hex string to integer.
*
* @param s A pointer to hex string, string length up to 2
* digits.
* @return integer value.
*/
static t_u8 hex_atoi(char *s)
{
int i;
t_u8 digit; /* digital value */
t_u8 t = 0; /* total value */
for (i = 0, t = 0; ishexdigit(s[i], &digit) && i < 2; i++)
t = 16 * t + digit;
return t;
}
/**
* @brief Parse byte sequence in hex format string to a byte sequence.
*
* @param opstr A pointer to byte sequence in hex format string, with
* ':' as delimiter between two byte.
* @param val A pointer to return byte sequence string
* @return NA
*/
static void parse_hex(char *opstr, t_u8 *val)
{
char delim = ':';
char *p;
char *q;
t_u8 i;
/* +1 is for skipping over the preceding h character. */
p = opstr + 1;
/* First byte */
val[1] = hex_atoi(p++);
/* Parse subsequent bytes. */
/* Each byte is preceded by the : character. */
for (i = 1; *p; i++) {
q = strchr(p, delim);
if (!q)
break;
p = q + 1;
val[i + 1] = hex_atoi(p);
}
/* Set num of bytes */
val[0] = i;
}
/**
* @brief str2bin, convert RPN string to binary format
*
* @param str A pointer to rpn string
* @param stack A pointer to mstack_t structure
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int str2bin(char *str, mstack_t *stack)
{
int first_time;
char *opstr;
op_t op; /* operator/operand */
int dnum;
int ret = MLAN_STATUS_SUCCESS;
memset(stack, 0, sizeof(mstack_t));
first_time = TRUE;
while ((opstr = getop(str, &first_time)) != NULL) {
if (isdigit((unsigned char)*opstr)) {
op.type = TYPE_DNUM;
dnum = cpu_to_le32(atoi(opstr));
memcpy((t_u8 *)op.val, &dnum, sizeof(dnum));
if (!push(stack, &op)) {
printf("push decimal number failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (*opstr == 'h') {
op.type = TYPE_BYTESEQ;
parse_hex(opstr, op.val);
if (!push(stack, &op)) {
printf("push byte sequence failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (!strcmp(opstr, "==")) {
op.type = TYPE_EQ;
if (!push(stack, &op)) {
printf("push byte cmp operator failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (!strcmp(opstr, "=d")) {
op.type = TYPE_EQ_DNUM;
if (!push(stack, &op)) {
printf("push decimal cmp operator failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (!strcmp(opstr, "=b")) {
op.type = TYPE_EQ_BIT;
if (!push(stack, &op)) {
printf("push bit cmp operator failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (!strcmp(opstr, "&&")) {
op.type = TYPE_AND;
if (!push(stack, &op)) {
printf("push AND operator failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else if (!strcmp(opstr, "||")) {
op.type = TYPE_OR;
if (!push(stack, &op)) {
printf("push OR operator failed\n");
ret = MLAN_STATUS_FAILURE;
break;
}
} else {
printf("Unknown operand\n");
ret = MLAN_STATUS_FAILURE;
break;
}
}
return ret;
}
#define FILTER_BYTESEQ TYPE_EQ /**< byte sequence */
#define FILTER_DNUM TYPE_EQ_DNUM /**< decimal number */
#define FILTER_BITSEQ TYPE_EQ_BIT /**< bit sequence */
#define FILTER_TEST (FILTER_BITSEQ + 1) /**< test */
#define NAME_TYPE 1 /**< Field name 'type' */
#define NAME_PATTERN 2 /**< Field name 'pattern' */
#define NAME_OFFSET 3 /**< Field name 'offset' */
#define NAME_NUMBYTE 4 /**< Field name 'numbyte' */
#define NAME_REPEAT 5 /**< Field name 'repeat' */
#define NAME_BYTE 6 /**< Field name 'byte' */
#define NAME_MASK 7 /**< Field name 'mask' */
#define NAME_DEST 8 /**< Field name 'dest' */
static struct mef_fields {
char *name; /**< Name */
t_s8 nameid; /**< Name Id. */
} mef_fields[] = {{"type", NAME_TYPE}, {"pattern", NAME_PATTERN},
{"offset", NAME_OFFSET}, {"numbyte", NAME_NUMBYTE},
{"repeat", NAME_REPEAT}, {"byte", NAME_BYTE},
{"mask", NAME_MASK}, {"dest", NAME_DEST}};
/**
* @brief get filter data
*
* @param fp A pointer to file stream
* @param ln A pointer to line number
* @param buf A pointer to hostcmd data
* @param size A pointer to the return size of hostcmd buffer
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int mlan_get_filter_data(FILE *fp, int *ln, t_u8 *buf, t_u16 *size)
{
t_s32 errors = 0, i;
char line[256], *pos = NULL, *pos1 = NULL;
t_u16 type = 0;
t_u32 pattern = 0;
t_u16 repeat = 0;
t_u16 offset = 0;
char byte_seq[50];
char mask_seq[50];
t_u16 numbyte = 0;
t_s8 type_find = 0;
t_s8 pattern_find = 0;
t_s8 offset_find = 0;
t_s8 numbyte_find = 0;
t_s8 repeat_find = 0;
t_s8 byte_find = 0;
t_s8 mask_find = 0;
t_s8 dest_find = 0;
char dest_seq[50];
*size = 0;
while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
if (strcmp(pos, "}") == 0) {
break;
}
pos1 = strchr(pos, '=');
if (pos1 == NULL) {
printf("Line %d: Invalid mef_filter line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos1++ = '\0';
for (i = 0; (t_u32)i < NELEMENTS(mef_fields); i++) {
if (strncmp(pos, mef_fields[i].name,
strlen(mef_fields[i].name)) == 0) {
switch (mef_fields[i].nameid) {
case NAME_TYPE:
type = a2hex_or_atoi(pos1);
if ((type != FILTER_DNUM) &&
(type != FILTER_BYTESEQ) &&
(type != FILTER_BITSEQ) &&
(type != FILTER_TEST)) {
printf("Invalid filter type:%d\n",
type);
return MLAN_STATUS_FAILURE;
}
type_find = 1;
break;
case NAME_PATTERN:
pattern = a2hex_or_atoi(pos1);
pattern_find = 1;
break;
case NAME_OFFSET:
offset = a2hex_or_atoi(pos1);
offset_find = 1;
break;
case NAME_NUMBYTE:
numbyte = a2hex_or_atoi(pos1);
numbyte_find = 1;
break;
case NAME_REPEAT:
repeat = a2hex_or_atoi(pos1);
repeat_find = 1;
break;
case NAME_BYTE:
memset(byte_seq, 0, sizeof(byte_seq));
strncpy(byte_seq, pos1,
(sizeof(byte_seq) - 1));
byte_find = 1;
break;
case NAME_MASK:
memset(mask_seq, 0, sizeof(mask_seq));
strncpy(mask_seq, pos1,
(sizeof(mask_seq) - 1));
mask_find = 1;
break;
case NAME_DEST:
memset(dest_seq, 0, sizeof(dest_seq));
strncpy(dest_seq, pos1,
(sizeof(dest_seq) - 1));
dest_find = 1;
break;
}
break;
}
}
if (i == NELEMENTS(mef_fields)) {
printf("Line %d: unknown mef field '%s'.\n", *line,
pos);
errors++;
}
}
if (type_find == 0) {
printf("Can not find filter type\n");
return MLAN_STATUS_FAILURE;
}
switch (type) {
case FILTER_DNUM:
if (!pattern_find || !offset_find || !numbyte_find) {
printf("Missing field for FILTER_DNUM: pattern=%d,offset=%d,numbyte=%d\n",
pattern_find, offset_find, numbyte_find);
return MLAN_STATUS_FAILURE;
}
memset(line, 0, sizeof(line));
snprintf(line, sizeof(line), "%d %d %d =d ", pattern, offset,
numbyte);
break;
case FILTER_BYTESEQ:
if (!byte_find || !offset_find || !repeat_find) {
printf("Missing field for FILTER_BYTESEQ: byte=%d,offset=%d,repeat=%d\n",
byte_find, offset_find, repeat_find);
return MLAN_STATUS_FAILURE;
}
memset(line, 0, sizeof(line));
snprintf(line, sizeof(line), "%d h%s %d == ", repeat, byte_seq,
offset);
break;
case FILTER_BITSEQ:
if (!byte_find || !offset_find || !mask_find) {
printf("Missing field for FILTER_BITSEQ: byte=%d,offset=%d,mask_find=%d\n",
byte_find, offset_find, mask_find);
return MLAN_STATUS_FAILURE;
}
if (strlen(byte_seq) != strlen(mask_seq)) {
printf("byte string's length is different with mask's length!\n");
return MLAN_STATUS_FAILURE;
}
memset(line, 0, sizeof(line));
snprintf(line, sizeof(line), "h%s %d h%s =b ", byte_seq, offset,
mask_seq);
break;
case FILTER_TEST:
if (!byte_find || !offset_find || !repeat_find || !dest_find) {
printf("Missing field for FILTER_TEST: byte=%d,offset=%d,repeat=%d,dest=%d\n",
byte_find, offset_find, repeat_find, dest_find);
return MLAN_STATUS_FAILURE;
}
memset(line, 0, sizeof(line));
snprintf(line, sizeof(line), "h%s %d h%s %d ", dest_seq, repeat,
byte_seq, offset);
break;
}
memcpy(buf, line, strlen(line));
*size = strlen(line);
return MLAN_STATUS_SUCCESS;
}
#define NAME_MODE 1 /**< Field name 'mode' */
#define NAME_ACTION 2 /**< Field name 'action' */
#define NAME_FILTER_NUM 3 /**< Field name 'filter_num' */
#define NAME_RPN 4 /**< Field name 'RPN' */
static struct mef_entry_fields {
char *name; /**< Name */
t_s8 nameid; /**< Name id */
} mef_entry_fields[] = {
{"mode", NAME_MODE},
{"action", NAME_ACTION},
{"filter_num", NAME_FILTER_NUM},
{"RPN", NAME_RPN},
};
typedef struct _MEF_ENTRY {
/** Mode */
t_u8 Mode;
/** Size */
t_u8 Action;
/** Size of expression */
t_u16 ExprSize;
} MEF_ENTRY;
/**
* @brief get mef_entry data
*
* @param fp A pointer to file stream
* @param ln A pointer to line number
* @param buf A pointer to hostcmd data
* @param size A pointer to the return size of hostcmd buffer
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int mlan_get_mef_entry_data(FILE *fp, int *ln, t_u8 *buf, t_u16 *size)
{
char line[256], *pos = NULL, *pos1 = NULL;
t_u8 mode, action, filter_num = 0;
char rpn[256];
t_s8 mode_find = 0;
t_s8 action_find = 0;
t_s8 filter_num_find = 0;
t_s8 rpn_find = 0;
char rpn_str[256];
int rpn_len = 0;
char filter_name[50];
t_s8 name_found = 0;
t_u16 len = 0;
int i;
int first_time = TRUE;
char *opstr = NULL;
char filter_action[10];
t_s32 errors = 0;
MEF_ENTRY *pMefEntry = (MEF_ENTRY *)buf;
mstack_t stack;
while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
if (strcmp(pos, "}") == 0) {
break;
}
pos1 = strchr(pos, '=');
if (pos1 == NULL) {
printf("Line %d: Invalid mef_entry line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos1++ = '\0';
if (!mode_find || !action_find || !filter_num_find ||
!rpn_find) {
for (i = 0;
(unsigned int)i < NELEMENTS(mef_entry_fields);
i++) {
if (strncmp(pos, mef_entry_fields[i].name,
strlen(mef_entry_fields[i].name)) ==
0) {
switch (mef_entry_fields[i].nameid) {
case NAME_MODE:
mode = a2hex_or_atoi(pos1);
if (mode & ~0x7) {
printf("invalid mode=%d\n",
mode);
return MLAN_STATUS_FAILURE;
}
pMefEntry->Mode = mode;
mode_find = 1;
break;
case NAME_ACTION:
action = a2hex_or_atoi(pos1);
if (action & ~0xff) {
printf("invalid action=%d\n",
action);
return MLAN_STATUS_FAILURE;
}
pMefEntry->Action = action;
action_find = 1;
break;
case NAME_FILTER_NUM:
filter_num =
a2hex_or_atoi(pos1);
filter_num_find = 1;
break;
case NAME_RPN:
memset(rpn, 0, sizeof(rpn));
strncpy(rpn, pos1,
(sizeof(rpn) - 1));
rpn_find = 1;
break;
}
break;
}
}
if (i == NELEMENTS(mef_fields)) {
printf("Line %d: unknown mef_entry field '%s'.\n",
*line, pos);
return MLAN_STATUS_FAILURE;
}
}
if (mode_find && action_find && filter_num_find && rpn_find) {
for (i = 0; i < filter_num; i++) {
opstr = getop(rpn, &first_time);
if (opstr == NULL)
break;
snprintf(filter_name, sizeof(filter_name),
"%s={", opstr);
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), ln))) {
if (strncmp(pos, filter_name,
strlen(filter_name)) == 0) {
name_found = 1;
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: %s not found in file\n",
filter_name);
return MLAN_STATUS_FAILURE;
}
if (MLAN_STATUS_FAILURE ==
mlan_get_filter_data(
fp, ln, (t_u8 *)(rpn_str + rpn_len),
&len))
break;
rpn_len += len;
if (i > 0) {
memcpy(rpn_str + rpn_len, filter_action,
strlen(filter_action));
rpn_len += strlen(filter_action);
}
opstr = getop(rpn, &first_time);
if (opstr == NULL)
break;
memset(filter_action, 0, sizeof(filter_action));
snprintf(filter_action, sizeof(filter_action),
"%s ", opstr);
}
/* Remove the last space */
if (rpn_len > 0) {
rpn_len--;
rpn_str[rpn_len] = 0;
}
if (MLAN_STATUS_FAILURE == str2bin(rpn_str, &stack)) {
printf("Fail on str2bin!\n");
return MLAN_STATUS_FAILURE;
}
*size = sizeof(MEF_ENTRY);
pMefEntry->ExprSize = cpu_to_le16(stack.sp);
memmove(buf + sizeof(MEF_ENTRY), stack.byte, stack.sp);
*size += stack.sp;
break;
} else if (mode_find && action_find && filter_num_find &&
(filter_num == 0)) {
pMefEntry->ExprSize = 0;
*size = sizeof(MEF_ENTRY);
break;
}
}
return MLAN_STATUS_SUCCESS;
}
#define MEFCFG_CMDCODE 0x009a
/**
* @brief Process mefcfg command
* @param argc number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_mefcfg(int argc, char *argv[])
{
char line[256], cmdname[256], *pos = NULL;
int cmdname_found = 0, name_found = 0;
int ln = 0;
int ret = MLAN_STATUS_SUCCESS;
int i;
t_u8 *buffer = NULL;
t_u16 len = 0;
HostCmd_DS_MEF_CFG *mefcmd = NULL;
HostCmd_DS_GEN *hostcmd = NULL;
FILE *fp = NULL;
t_u32 cmd_len = 0, cmd_header_len;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
if (argc < 4) {
printf("Error: invalid no of arguments\n");
printf("Syntax: ./mlanutl mlan0 mefcfg <mef.conf>\n");
exit(1);
}
cmd_header_len = strlen(CMD_NXP) + strlen("HOSTCMD");
cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(HostCmd_DS_MEF_CFG);
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
return -ENOMEM;
}
memset(buffer, 0, BUFFER_LENGTH);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* buf = MRVL_CMD<cmd> */
prepare_buffer(buffer, HOSTCMD, 0, NULL);
/* buf = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN> */
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
hostcmd->command = cpu_to_le16(MEFCFG_CMDCODE);
hostcmd->seq_num = 0;
hostcmd->result = 0;
/* buf = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><HostCmd_DS_MEF_CFG>
*/
mefcmd = (HostCmd_DS_MEF_CFG *)(buffer + cmd_header_len +
sizeof(t_u32) + S_DS_GEN);
/* Host Command Population */
snprintf(cmdname, sizeof(cmdname), "%s={", argv[2]);
cmdname_found = 0;
fp = fopen(argv[3], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s\n", argv[4]);
exit(1);
}
while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
if (strcmp(pos, cmdname) == 0) {
cmdname_found = 1;
snprintf(cmdname, sizeof(cmdname), "Criteria=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname, strlen(cmdname)) ==
0) {
name_found = 1;
mefcmd->Criteria = a2hex_or_atoi(
pos + strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: criteria not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname), "NumEntries=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname, strlen(cmdname)) ==
0) {
name_found = 1;
mefcmd->NumEntries = a2hex_or_atoi(
pos + strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: NumEntries not found in file '%s'\n",
argv[3]);
break;
}
for (i = 0; i < mefcmd->NumEntries; i++) {
snprintf(cmdname, sizeof(cmdname),
"mef_entry_%d={", i);
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: %s not found in file '%s'\n",
cmdname, argv[3]);
break;
}
if (MLAN_STATUS_FAILURE ==
mlan_get_mef_entry_data(
fp, &ln, (t_u8 *)hostcmd + cmd_len,
&len)) {
ret = MLAN_STATUS_FAILURE;
break;
}
cmd_len += len;
}
break;
}
}
fclose(fp);
/* buf = MRVL_CMD<cmd><hostcmd_size> */
memcpy(buffer + cmd_header_len, (t_u8 *)&cmd_len, sizeof(t_u32));
if (!cmdname_found)
fprintf(stderr,
"mlanutl: cmdname '%s' not found in file '%s'\n",
argv[4], argv[3]);
if (!cmdname_found || !name_found) {
ret = MLAN_STATUS_FAILURE;
goto mef_exit;
}
hostcmd->size = cpu_to_le16(cmd_len);
mefcmd->Criteria = cpu_to_le32(mefcmd->Criteria);
mefcmd->NumEntries = cpu_to_le16(mefcmd->NumEntries);
hexdump("mefcfg", buffer + cmd_header_len, cmd_len, ' ');
/* Initialize the ifr structure */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
/* Perform ioctl */
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("ioctl[MEF_CFG]");
printf("ERR:Command sending failed!\n");
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return MLAN_STATUS_FAILURE;
}
ret = process_host_cmd_resp(HOSTCMD, buffer);
mef_exit:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/**
* @brief Check the Hex String
* @param s A pointer to the string
* @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not
* HexString
*/
static int ishexstring(char *s)
{
int ret = MLAN_STATUS_FAILURE;
t_s32 tmp;
if (!strncasecmp("0x", s, 2)) {
s += 2;
}
while (*s) {
tmp = toupper((unsigned char)*s);
if (((tmp >= 'A') && (tmp <= 'F')) ||
((tmp >= '0') && (tmp <= '9'))) {
ret = MLAN_STATUS_SUCCESS;
} else {
ret = MLAN_STATUS_FAILURE;
break;
}
s++;
}
return ret;
}
/**
* @brief Converts colon separated MAC address to hex value
*
* @param mac A pointer to the colon separated MAC string
* @param raw A pointer to the hex data buffer
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
* MAC_BROADCAST - if broadcast mac
* 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 MLAN_STATUS_FAILURE;
}
num_tokens = sscanf(mac, "%2x:%2x:%2x:%2x:%2x:%2x", temp_raw + 0,
temp_raw + 1, temp_raw + 2, temp_raw + 3,
temp_raw + 4, temp_raw + 5);
if (num_tokens != ETH_ALEN) {
return MLAN_STATUS_FAILURE;
}
for (i = 0; i < num_tokens; i++)
raw[i] = (t_u8)temp_raw[i];
if (memcmp(raw, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) {
return MAC_BROADCAST;
} else if (raw[0] & 0x01) {
return MAC_MULTICAST;
}
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Convert String to Integer
* @param buf A pointer to the string
* @return Integer
*/
static int atoval(char *buf)
{
if (!strncasecmp(buf, "0x", 2))
return a2hex(buf + 2);
else if (!ishexstring(buf))
return a2hex(buf);
else
return atoi(buf);
}
/**
* @brief Parses a command line
*
* @param line The line to parse
* @param args Pointer to the argument buffer to be filled in
* @param args_count Max number of elements which can be filled in buffer
* 'args'
* @return Number of arguments in the line or EOF
*/
int parse_line(char *line, char *args[], t_u16 args_count)
{
int arg_num = 0;
int is_start = 0;
int is_quote = 0;
int length = 0;
int i = 0;
arg_num = 0;
length = strlen(line);
/* Process line */
/* Find number of arguments */
is_start = 0;
is_quote = 0;
for (i = 0; (i < length) && (arg_num < args_count); i++) {
/* Ignore leading spaces */
if (is_start == 0) {
if (line[i] == ' ') {
continue;
} else if (line[i] == '\t') {
continue;
} else if (line[i] == '\n') {
break;
} else {
is_start = 1;
args[arg_num] = &line[i];
arg_num++;
}
}
if (is_start == 1) {
/* Ignore comments */
if (line[i] == '#') {
if (is_quote == 0) {
line[i] = '\0';
arg_num--;
}
break;
}
/* Separate by '=' */
if (line[i] == '=') {
line[i] = '\0';
is_start = 0;
continue;
}
/* Separate by ',' */
if (line[i] == ',') {
line[i] = '\0';
is_start = 0;
continue;
}
/* Change ',' to ' ', but not inside quotes */
if ((line[i] == ',') && (is_quote == 0)) {
line[i] = ' ';
continue;
}
}
/* Remove newlines */
if (line[i] == '\n') {
line[i] = '\0';
}
/* Check for quotes */
if (line[i] == '"') {
is_quote = (is_quote == 1) ? 0 : 1;
continue;
}
if (((line[i] == ' ') || (line[i] == '\t')) &&
(is_quote == 0)) {
line[i] = '\0';
is_start = 0;
continue;
}
}
return arg_num;
}
/**
* @brief Process cloud keep alive command
* @param argc number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_cloud_keep_alive(int argc, char *argv[])
{
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
FILE *fp = NULL;
int ret = MLAN_STATUS_SUCCESS;
char line[256], cmdname[256], *pos = NULL;
int cmdname_found = 0, name_found = 0, arg_num = 0;
int ln = 0, i = 0;
char *args[256];
cloud_keep_alive *keep_alive = NULL;
if (argc < 5) {
printf("Error: invalid no of arguments\n");
printf("Syntax: ./mlanutl mlanX cloud_keep_alive <keep_alive.conf> <start/stop/reset>\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Insert command */
strncpy((char *)buffer, argv[2], strlen(argv[2]));
keep_alive = (cloud_keep_alive *)(buffer + strlen(argv[2]));
cmdname_found = 0;
snprintf(cmdname, sizeof(cmdname), "%s={", argv[4]);
fp = fopen(argv[3], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s\n", argv[3]);
ret = MLAN_STATUS_FAILURE;
if (buffer)
free(buffer);
goto done;
}
while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
if (strcmp(pos, cmdname) == 0) {
cmdname_found = 1;
snprintf(cmdname, sizeof(cmdname), "mkeep_alive_id=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname, strlen(cmdname)) ==
0) {
name_found = 1;
keep_alive->mkeep_alive_id =
a2hex_or_atoi(pos +
strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: keep alive id not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname), "enable=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname, strlen(cmdname)) ==
0) {
name_found = 1;
keep_alive->enable = a2hex_or_atoi(
pos + strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: enable not found in file '%s'\n",
argv[3]);
break;
}
if (strcmp(argv[4], "reset") == 0) {
snprintf(cmdname, sizeof(cmdname), "reset=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
keep_alive
->reset = a2hex_or_atoi(
pos + strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: reset not found in file '%s'\n",
argv[3]);
break;
}
}
if (strcmp(argv[4], "start") == 0) {
snprintf(cmdname, sizeof(cmdname),
"sendInterval=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
keep_alive->sendInterval =
a2hex_or_atoi(
pos +
strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: sendInterval not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname),
"retryInterval=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
keep_alive->retryInterval =
a2hex_or_atoi(
pos +
strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: retryInterval not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname),
"retryCount=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
keep_alive->retryCount =
a2hex_or_atoi(
pos +
strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: retryCount not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname),
"destMacAddr=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
mac2raw(pos + strlen(cmdname),
keep_alive->dst_mac);
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: destination MAC address not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname),
"srcMacAddr=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
mac2raw(pos + strlen(cmdname),
keep_alive->src_mac);
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: source MAC address not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname), "pktLen=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
keep_alive->pkt_len =
a2hex_or_atoi(
pos +
strlen(cmdname));
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: ip packet length not found in file '%s'\n",
argv[3]);
break;
}
snprintf(cmdname, sizeof(cmdname), "ipPkt=");
name_found = 0;
while ((pos = mlan_config_get_line(
fp, line, sizeof(line), &ln))) {
if (strncmp(pos, cmdname,
strlen(cmdname)) == 0) {
name_found = 1;
arg_num = parse_line(line, args,
256);
if (arg_num <
keep_alive->pkt_len) {
fprintf(stderr,
"Invalid ipPkt or pkt_len in '%s'\n",
argv[3]);
break;
}
for (i = 0;
i < keep_alive->pkt_len;
i++)
keep_alive->pkt[i] =
(t_u8)atoval(
args[i +
1]);
break;
}
}
if (!name_found) {
fprintf(stderr,
"mlanutl: ipPkt data not found in file '%s'\n",
argv[3]);
break;
}
}
}
}
if (!cmdname_found) {
fprintf(stderr, "mlanutl: ipPkt data not found in file '%s'\n",
argv[3]);
free(buffer);
if (fp)
fclose(fp);
return MLAN_STATUS_FAILURE;
}
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: cloud keep alive fail\n");
if (cmd)
free(cmd);
if (buffer)
free(buffer);
return MLAN_STATUS_FAILURE;
}
/* Process result */
keep_alive = (cloud_keep_alive *)(buffer + strlen(argv[2]));
if (strcmp(argv[4], "start") != 0) {
hexdump("Last cloud keep alive packet info", keep_alive->pkt,
keep_alive->pkt_len, ' ');
}
if (buffer)
free(buffer);
if (cmd)
free(cmd);
done:
return ret;
}
/**
* @brief Implement Minimum BA Threshold command
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
static int process_min_ba_threshold_cfg(int argc, char *argv[])
{
int ret = 0;
t_u8 min_ba_thres = 0;
t_u8 *buffer = NULL;
struct eth_priv_cmd *cmd = NULL;
struct ifreq ifr;
/* Initialize buffer */
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
if (!buffer) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(buffer, 0, BUFFER_LENGTH);
/* Sanity tests */
if (argc < 3 || argc > 4) {
printf("Error: invalid no of arguments\n");
printf("mlanutl mlanX min_ba_threshold [#]\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
prepare_buffer(buffer, argv[2], (argc - 3), &argv[3]);
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
if (!cmd) {
printf("ERR:Cannot allocate buffer for command!\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Fill up buffer */
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
memset(cmd, 0, sizeof(struct eth_priv_cmd));
memcpy(&cmd->buf, &buffer, sizeof(buffer));
#else
cmd->buf = buffer;
#endif
cmd->used_len = 0;
cmd->total_len = BUFFER_LENGTH;
/* Perform IOCTL */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
ifr.ifr_ifru.ifru_data = (void *)cmd;
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
perror("mlanutl");
fprintf(stderr, "mlanutl: min_ba_threshold fail\n");
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* Process result */
if (argc == 3) {
memcpy(&min_ba_thres, buffer, sizeof(min_ba_thres));
printf("Min Tx BA Threshold: %d\n", min_ba_thres);
}
done:
if (buffer)
free(buffer);
if (cmd)
free(cmd);
return ret;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief Entry function for mlanutl
* @param argc Number of arguments
* @param argv A pointer to arguments array
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
*/
int main(int argc, char *argv[])
{
int ret = MLAN_STATUS_SUCCESS;
if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) {
fprintf(stdout, "NXP mlanutl version %s\n", MLANUTL_VER);
exit(0);
}
if (argc < 3) {
fprintf(stderr, "Invalid number of parameters!\n");
display_usage();
exit(1);
}
strncpy(dev_name, argv[1], IFNAMSIZ - 1);
/*
* Create a socket
*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr, "mlanutl: Cannot open socket.\n");
exit(1);
}
ret = process_command(argc, argv);
if (ret == MLAN_STATUS_NOTFOUND) {
if (ret) {
fprintf(stderr, "Invalid command specified!\n");
display_usage();
ret = 1;
}
}
close(sockfd);
return ret;
}