mirror of
https://github.com/nxp-imx/mwifiex.git
synced 2024-11-15 03:25:35 +00:00
33d9f8e4f3
Add initial MxM (multi-chip-multi-interface) wifi driver. The driver target is to support 88w8987/88w8997/88w9098, currently it only supports 88w8987. The MxM wifi driver is merged from below repo and applied some patches for block and build issues. ssh://git@bitbucket.sw.nxp.com/wcswrel/ rel-nxp-wifi-fp92-bt-fp85-linux-android-mxm4x17169-gpl.git The sdk only includes application, the driver already is merged into linux kernel. Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
3675 lines
96 KiB
C
3675 lines
96 KiB
C
/** @file mlanroamagent.c
|
|
*
|
|
* @brief This files contains mlanutl roamagent command handling.
|
|
*
|
|
*
|
|
* Copyright 2014-2020 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:
|
|
08/11/2009: initial version
|
|
************************************************************************/
|
|
|
|
#include "mlanutl.h"
|
|
#include "mlanhostcmd.h"
|
|
#include "mlanoffload.h"
|
|
#include "mlanroamagent.h"
|
|
|
|
/********************************************************
|
|
Local Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Global Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Local Functions
|
|
********************************************************/
|
|
|
|
/**
|
|
* @brief Issue getra failcnt command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetFailureCount(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int failCount, failTimeThresh, state, i;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_FailureCount_t *pFailureCount;
|
|
MrvlIEtypesHeader_t *pTlvHdr;
|
|
t_u8 *tlvptr;
|
|
const char *states[] =
|
|
{ "Stable", "Degrading", "Unacceptable", "Hardroam" };
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
cmd_len =
|
|
(S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
|
|
- sizeof(statsthreshold->TlvBuffer));
|
|
|
|
/* Can be extended to all states later */
|
|
for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) {
|
|
statsthreshold->State = state + 1;
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamstatistics]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
i = le16_to_cpu(hostcmd->size);
|
|
i -= cmd_len;
|
|
tlvptr = statsthreshold->TlvBuffer;
|
|
|
|
while (i > 2) {
|
|
pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr;
|
|
|
|
switch (le16_to_cpu(pTlvHdr->type)) {
|
|
case TLV_TYPE_FAILCOUNT:
|
|
pFailureCount =
|
|
(MrvlIEtypes_FailureCount_t *)pTlvHdr;
|
|
failCount = pFailureCount->fail_value;
|
|
failTimeThresh =
|
|
le16_to_cpu(pFailureCount->
|
|
fail_min_thresh_time_millisecs);
|
|
break;
|
|
}
|
|
|
|
tlvptr += (le16_to_cpu(pTlvHdr->len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu(pTlvHdr->len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
}
|
|
|
|
printf("State: %-8s. FailCount = %d, FailTimeThresh(ms) = %d\n",
|
|
states[state], failCount, failTimeThresh);
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra bcnmiss command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetPreBeaconMiss(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int bcnmiss, state = STATE_HARDROAM, i;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_BeaconsMissed_t *pBeaconMissed;
|
|
MrvlIEtypesHeader_t *pTlvHdr;
|
|
t_u8 *tlvptr;
|
|
const char *states[] =
|
|
{ "Stable", "Degrading", "Unacceptable", "Hardroam" };
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
cmd_len =
|
|
(S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
|
|
- sizeof(statsthreshold->TlvBuffer));
|
|
|
|
/* Can be extended to all states later */
|
|
for (state = STATE_HARDROAM - 1; state < STATE_HARDROAM; state++) {
|
|
statsthreshold->State = state + 1;
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[beacon miss]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
i = le16_to_cpu(hostcmd->size);
|
|
i -= cmd_len;
|
|
tlvptr = statsthreshold->TlvBuffer;
|
|
|
|
while (i > 2) {
|
|
pTlvHdr = (MrvlIEtypesHeader_t *)tlvptr;
|
|
|
|
switch (le16_to_cpu(pTlvHdr->type)) {
|
|
|
|
case TLV_TYPE_PRE_BEACON_LOST:
|
|
pBeaconMissed =
|
|
(MrvlIEtypes_BeaconsMissed_t *)pTlvHdr;
|
|
bcnmiss = pBeaconMissed->beacon_missed;
|
|
}
|
|
|
|
tlvptr += (le16_to_cpu(pTlvHdr->len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu(pTlvHdr->len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
}
|
|
|
|
printf("State: %-8s. Pre Beacon missed threshold %d\n",
|
|
states[state], bcnmiss);
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra rssi/snr command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param type RSSI/SNR threshold type
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetStatsThreshold(int argc, char *argv[], int type)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int state = 0, i = 0, profile = 1;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_BeaconHighRssiThreshold_t *pHighRssiThreshold;
|
|
MrvlIEtypes_BeaconLowRssiThreshold_t *pLowRssiThreshold;
|
|
MrvlIEtypes_BeaconHighSnrThreshold_t *pHighSnrThreshold;
|
|
MrvlIEtypes_BeaconLowSnrThreshold_t *pLowSnrThreshold;
|
|
t_s8 high, low;
|
|
t_u8 *tlvptr;
|
|
t_u16 tlv;
|
|
const char *states[] = { "Stable", "Degrading", "Unacceptable" };
|
|
|
|
if (argc) {
|
|
if (strncmp(argv[0], "configured", strlen("config")) == 0) {
|
|
profile = 0;
|
|
} else if (strncmp(argv[0], "active", strlen("active"))) {
|
|
printf("\nIncorrect parameter %s for getra command\n\n",
|
|
argv[0]);
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
cmd_len =
|
|
(S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
|
|
- sizeof(statsthreshold->TlvBuffer));
|
|
|
|
printf("---------------------------------------------\n");
|
|
if (type == RSSI_THRESHOLD) {
|
|
printf(" RSSI Thresholds\n");
|
|
} else {
|
|
printf(" SNR Thresholds\n");
|
|
}
|
|
printf("---------------------------------------------\n");
|
|
|
|
for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) {
|
|
statsthreshold->State = state + 1;
|
|
statsthreshold->Profile = profile;
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamstatistics]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n", le16_to_cpu(hostcmd->command), le16_to_cpu(hostcmd->result));
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
i = le16_to_cpu(hostcmd->size);
|
|
i -= cmd_len;
|
|
tlvptr = statsthreshold->TlvBuffer;
|
|
while (i > 2) {
|
|
/*
|
|
* ENDIANNESS for Response
|
|
*/
|
|
tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
|
|
|
|
switch (tlv) {
|
|
case TLV_TYPE_RSSI_HIGH:
|
|
high = *(t_s8 *)(tlvptr + sizeof(t_u16) +
|
|
sizeof(t_u16));
|
|
pHighRssiThreshold =
|
|
(MrvlIEtypes_BeaconHighRssiThreshold_t
|
|
*)(tlvptr);
|
|
tlvptr +=
|
|
(le16_to_cpu
|
|
(pHighRssiThreshold->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu
|
|
(pHighRssiThreshold->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
|
|
case TLV_TYPE_RSSI_LOW:
|
|
low = *(t_s8 *)(tlvptr + sizeof(t_u16) +
|
|
sizeof(t_u16));
|
|
pLowRssiThreshold =
|
|
(MrvlIEtypes_BeaconLowRssiThreshold_t
|
|
*)(tlvptr);
|
|
tlvptr +=
|
|
(le16_to_cpu
|
|
(pLowRssiThreshold->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu(pLowRssiThreshold->Header.len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
|
|
case TLV_TYPE_SNR_HIGH:
|
|
high = *(t_s8 *)(tlvptr + sizeof(t_u16) +
|
|
sizeof(t_u16));
|
|
pHighSnrThreshold =
|
|
(MrvlIEtypes_BeaconHighSnrThreshold_t
|
|
*)(tlvptr);
|
|
tlvptr +=
|
|
(le16_to_cpu
|
|
(pHighSnrThreshold->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu(pHighSnrThreshold->Header.len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
|
|
case TLV_TYPE_SNR_LOW:
|
|
low = *(t_s8 *)(tlvptr + sizeof(t_u16) +
|
|
sizeof(t_u16));
|
|
pLowSnrThreshold =
|
|
(MrvlIEtypes_BeaconLowSnrThreshold_t
|
|
*)(tlvptr);
|
|
tlvptr +=
|
|
(le16_to_cpu
|
|
(pLowSnrThreshold->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
i -= (le16_to_cpu(pLowSnrThreshold->Header.len)
|
|
+ sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("%-13s| High = %4d | Low = %4d |\n",
|
|
states[state], high, low);
|
|
}
|
|
puts("");
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra rssi/snr command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetRssiStatsThreshold(int argc, char *argv[])
|
|
{
|
|
return roamGetStatsThreshold(argc, argv, RSSI_THRESHOLD);
|
|
}
|
|
|
|
/**
|
|
* @brief Coverts ms to exactTime
|
|
*
|
|
* @param ms number of milliseconds
|
|
* @param t converted into this structure
|
|
*
|
|
* @return none
|
|
*/
|
|
static void
|
|
ms2exactTime(t_u32 ms, ExactTime_t *t)
|
|
{
|
|
memset(t, 0, sizeof(ExactTime_t));
|
|
|
|
t->msecs = ms % 1000;
|
|
if (ms >= 1000) {
|
|
ms = (ms - t->msecs) / 1000;
|
|
t->secs = ms % 60;
|
|
if (ms >= 60) {
|
|
ms = (ms - t->secs) / 60;
|
|
t->mins = ms % 60;
|
|
if (ms >= 60) {
|
|
ms = (ms - t->mins) / 60;
|
|
t->hrs = ms;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra neighbor assessment command
|
|
*
|
|
* @pNborAssessment neighbour assessment struct
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
getNborAssessment(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT
|
|
*pNborAssessmentParam)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment;
|
|
|
|
/*
|
|
* NEIGHBOR_ASSESSMENT
|
|
*/
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(pNborAssessment->action);
|
|
pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[GetNeibhorAssesinfo]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
/*
|
|
* ENDIANNESS for Response
|
|
*/
|
|
pNborAssessment->QualifyingNumNeighbor =
|
|
le16_to_cpu(pNborAssessment->QualifyingNumNeighbor);
|
|
pNborAssessment->ShortBlacklistPeriod =
|
|
le32_to_cpu(pNborAssessment->ShortBlacklistPeriod);
|
|
pNborAssessment->LongBlacklistPeriod =
|
|
le32_to_cpu(pNborAssessment->LongBlacklistPeriod);
|
|
pNborAssessment->StaleCount = le16_to_cpu(pNborAssessment->StaleCount);
|
|
pNborAssessment->StalePeriod =
|
|
le32_to_cpu(pNborAssessment->StalePeriod);
|
|
|
|
memcpy((void *)pNborAssessmentParam, (void *)pNborAssessment,
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT));
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Display exactTime structure elements
|
|
*
|
|
* @param t ExactTime_t struct
|
|
*
|
|
* @return None
|
|
*/
|
|
static void
|
|
printExactTime2stdout(ExactTime_t *t)
|
|
{
|
|
int flag = 0;
|
|
if (t->hrs) {
|
|
printf("%dh ", t->hrs);
|
|
flag = 1;
|
|
}
|
|
if (t->mins) {
|
|
printf("%dm ", t->mins);
|
|
flag = 1;
|
|
}
|
|
if (t->secs) {
|
|
printf("%ds ", t->secs);
|
|
flag = 1;
|
|
}
|
|
if (t->msecs) {
|
|
printf("%dms", t->msecs);
|
|
flag = 1;
|
|
}
|
|
if (!flag) {
|
|
printf(" 0");
|
|
}
|
|
}
|
|
|
|
static int
|
|
printNeighborAssessmentConfig(void)
|
|
{
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT nborAssessment;
|
|
int idx;
|
|
int threshDisp = FALSE;
|
|
|
|
if (getNborAssessment(&nborAssessment) != MLAN_STATUS_SUCCESS) {
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
printf("----------------------------------------------------------\n");
|
|
printf(" Neighbor Threshold Parameters\n");
|
|
printf("----------------------------------------------------------\n");
|
|
printf(" Neighbors needed for tracking mode = %d\n",
|
|
nborAssessment.QualifyingNumNeighbor);
|
|
printf(" Config RSSI qualification offset = %d dB\n",
|
|
nborAssessment.ConfQualSignalStrength);
|
|
printf(" Active RSSI qualification offset = %d dB\n",
|
|
nborAssessment.ActiveQualSignalStrength);
|
|
printf(" Short black list period = %d ms\n",
|
|
(int)nborAssessment.ShortBlacklistPeriod);
|
|
printf(" Long black list period = %d ms\n",
|
|
(int)nborAssessment.LongBlacklistPeriod);
|
|
printf(" Stale count = %d\n",
|
|
(int)nborAssessment.StaleCount);
|
|
printf(" Stale period = %d ms\n",
|
|
(int)nborAssessment.StalePeriod);
|
|
printf(" Proactive Roaming Thresholds =");
|
|
for (idx = 0; idx < NELEMENTS(nborAssessment.RoamThresh); idx++) {
|
|
if (nborAssessment.RoamThresh[idx].RssiNborDiff) {
|
|
if (threshDisp) {
|
|
printf(" ");
|
|
}
|
|
|
|
threshDisp = TRUE;
|
|
printf("%3d to %4d [%d]\n",
|
|
nborAssessment.RoamThresh[idx].RssiHighLevel,
|
|
nborAssessment.RoamThresh[idx].RssiLowLevel,
|
|
nborAssessment.RoamThresh[idx].RssiNborDiff);
|
|
}
|
|
}
|
|
|
|
if (!threshDisp) {
|
|
puts(" < None >");
|
|
}
|
|
puts("");
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra neighbors command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetNborList(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int cmdresplen, i;
|
|
struct ifreq ifr;
|
|
char neighflag[6];
|
|
ExactTime_t t;
|
|
t_u16 tlv;
|
|
t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *pNborList;
|
|
MrvlIEtypes_NeighborEntry_t *pNeighbor;
|
|
|
|
/*
|
|
* NEIGHBOR_LIST
|
|
*/
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
pNborList = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(pNborList->action);
|
|
pNborList->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamneighborlist]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
cmdresplen = le16_to_cpu(hostcmd->size);
|
|
cmdresplen -= cmd_len + sizeof(pNborList->Reserved);
|
|
tlvptr = pNborList->TlvBuffer;
|
|
|
|
printf("----------------------------------------------------"
|
|
"--------------\n");
|
|
printf(" BSSID | RSSI | Age | Qualified |"
|
|
" Blacklist Duration\n");
|
|
printf("----------------------------------------------------"
|
|
"--------------\n");
|
|
|
|
i = 0;
|
|
|
|
while (cmdresplen > 2) {
|
|
i++;
|
|
/*
|
|
* ENDIANNESS for Response
|
|
*/
|
|
tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
|
|
switch (tlv) {
|
|
case TLV_TYPE_NEIGHBOR_ENTRY:
|
|
pNeighbor = (MrvlIEtypes_NeighborEntry_t *)(tlvptr);
|
|
pNeighbor->SignalStrength =
|
|
le16_to_cpu(pNeighbor->SignalStrength);
|
|
pNeighbor->Age = le16_to_cpu(pNeighbor->Age);
|
|
pNeighbor->QualifiedNeighborBitmap =
|
|
le32_to_cpu(pNeighbor->QualifiedNeighborBitmap);
|
|
|
|
pNeighbor->BlackListDuration =
|
|
le32_to_cpu(pNeighbor->BlackListDuration);
|
|
ms2exactTime(pNeighbor->BlackListDuration, &t);
|
|
neighflag[0] = '\0';
|
|
|
|
if ((pNeighbor->QualifiedNeighborBitmap
|
|
& (BIT_NEIGHFLAG_RSSI
|
|
| BIT_NEIGHFLAG_AGE
|
|
| BIT_NEIGHFLAG_BLACKLIST
|
|
| BIT_NEIGHFLAG_ADMISSION_CAP
|
|
| BIT_NEIGHFLAG_UPLINK_RSSI))
|
|
== (BIT_NEIGHFLAG_RSSI
|
|
| BIT_NEIGHFLAG_AGE
|
|
| BIT_NEIGHFLAG_BLACKLIST
|
|
| BIT_NEIGHFLAG_ADMISSION_CAP
|
|
| BIT_NEIGHFLAG_UPLINK_RSSI)) {
|
|
strcat(neighflag, "Yes");
|
|
} else {
|
|
strcat(neighflag, "No: ");
|
|
if (!
|
|
(pNeighbor->
|
|
QualifiedNeighborBitmap &
|
|
BIT_NEIGHFLAG_RSSI)) {
|
|
strcat(neighflag, "R");
|
|
}
|
|
if (!
|
|
(pNeighbor->
|
|
QualifiedNeighborBitmap &
|
|
BIT_NEIGHFLAG_AGE)) {
|
|
strcat(neighflag, "S");
|
|
}
|
|
if (!(pNeighbor->QualifiedNeighborBitmap
|
|
& BIT_NEIGHFLAG_BLACKLIST)) {
|
|
strcat(neighflag, "B");
|
|
}
|
|
if (!(pNeighbor->QualifiedNeighborBitmap
|
|
& BIT_NEIGHFLAG_ADMISSION_CAP)) {
|
|
strcat(neighflag, "A");
|
|
}
|
|
if (!(pNeighbor->QualifiedNeighborBitmap
|
|
& BIT_NEIGHFLAG_UPLINK_RSSI)) {
|
|
strcat(neighflag, "U");
|
|
}
|
|
}
|
|
printf(" %02x:%02x:%02x:%02x:%02x:%02x | %3d | %5d | %9s | ", pNeighbor->Bssid[0], pNeighbor->Bssid[1], pNeighbor->Bssid[2], pNeighbor->Bssid[3], pNeighbor->Bssid[4], pNeighbor->Bssid[5], pNeighbor->SignalStrength, pNeighbor->Age, neighflag);
|
|
|
|
if (pNeighbor->BlackListDuration) {
|
|
printExactTime2stdout(&t);
|
|
} else {
|
|
printf("Not Blacklisted");
|
|
}
|
|
printf("\n");
|
|
|
|
tlvptr += (le16_to_cpu(pNeighbor->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
cmdresplen -= (le16_to_cpu(pNeighbor->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
|
|
default:
|
|
printf("\nIncorrect response.\n\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == 0) {
|
|
printf("< Empty >\n");
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra neighbor params command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetNborParams(int argc, char *argv[])
|
|
{
|
|
printNeighborAssessmentConfig();
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra metrics command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetMetrics(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int i;
|
|
t_u16 Metrics = 0;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd;
|
|
|
|
const char *metricslist[] = { "beacon", "data", "per", "fer" };
|
|
|
|
if (argc != 0) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(metricscmd->action);
|
|
metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roam set matrics]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
Metrics = le16_to_cpu(metricscmd->Metrics);
|
|
|
|
if (le16_to_cpu(hostcmd->result) == MLAN_STATUS_SUCCESS) {
|
|
printf("\n Metrics Activated: ");
|
|
for (i = 0; (unsigned int)i < NELEMENTS(metricslist); i++) {
|
|
if (Metrics & BIT(i)) {
|
|
printf(" %s ", metricslist[i]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
if (Metrics & BIT(3)) {
|
|
printf("FER Threshold : %u %% \n",
|
|
metricscmd->UcFerThresholdValue);
|
|
printf("FER Packet Threshold: %d \n",
|
|
le32_to_cpu(metricscmd->UiFerPktThreshold));
|
|
printf("FER period. Stable : %d ms, Degrading : %d ms, "
|
|
"Unacceptable : %d ms\n",
|
|
le32_to_cpu(metricscmd->StableFERPeriod_ms),
|
|
le32_to_cpu(metricscmd->DegradingFERPeriod_ms),
|
|
le32_to_cpu(metricscmd->
|
|
UnacceptableFERPeriod_ms));
|
|
}
|
|
|
|
if (Metrics & BIT(2)) {
|
|
printf("PER Threshold : %u %% \n",
|
|
metricscmd->UcPerThresholdValue);
|
|
printf("PER Packet Threshold: %d \n",
|
|
le32_to_cpu(metricscmd->UiPerPktThreshold));
|
|
printf("PER period. Stable : %d ms, Degrading : %d ms, "
|
|
"Unacceptable : %d ms\n",
|
|
le32_to_cpu(metricscmd->StablePERPeriod_ms),
|
|
le32_to_cpu(metricscmd->DegradingPERPeriod_ms),
|
|
le32_to_cpu(metricscmd->
|
|
UnacceptablePERPeriod_ms));
|
|
}
|
|
|
|
if (Metrics & BIT(1)) {
|
|
printf("Data Packet Threshold: %d \n",
|
|
le32_to_cpu(metricscmd->UiRxPktThreshold));
|
|
}
|
|
|
|
if ((Metrics & BIT(1)) || (Metrics & BIT(2)) ||
|
|
(Metrics & BIT(3))) {
|
|
|
|
printf("Inactivity Period: %d ms \n",
|
|
le32_to_cpu(metricscmd->
|
|
InactivityPeriodThreshold_ms));
|
|
}
|
|
} else {
|
|
printf("command response failure %d.\n",
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra scanperiod command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetScanPeriod(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int state = 0, scanmode = 0, cmdresplen;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL, *tlvptr = NULL;
|
|
t_u16 tlv;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *scanPeriodInfo;
|
|
MrvlIEtypes_NeighborScanPeriod_t *pscanperiod;
|
|
const char *states[] = { "Stable", "Degrading", "Unacceptable" };
|
|
const char *scanmodes[] = { "Discovery", "Tracking" };
|
|
/* scanperiodValues[state][scanmode] */
|
|
t_u32 values[3][2];
|
|
|
|
/*
|
|
* NEIGHBOR_SCANPERIOD
|
|
*/
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
scanPeriodInfo =
|
|
(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD_RSP *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(scanPeriodInfo->action);
|
|
scanPeriodInfo->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamscanperiod]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
cmdresplen = le16_to_cpu(hostcmd->size);
|
|
cmdresplen -= cmd_len + sizeof(scanPeriodInfo->Reserved);
|
|
tlvptr = scanPeriodInfo->TlvBuffer;
|
|
while (cmdresplen > 2) {
|
|
/*
|
|
* ENDIANNESS for Response
|
|
*/
|
|
tlv = le16_to_cpu(*((t_u16 *)(tlvptr)));
|
|
switch (tlv) {
|
|
case TLV_TYPE_NEIGHBOR_SCANPERIOD:
|
|
pscanperiod =
|
|
(MrvlIEtypes_NeighborScanPeriod_t *)(tlvptr);
|
|
pscanperiod->SearchMode =
|
|
le16_to_cpu(pscanperiod->SearchMode);
|
|
pscanperiod->State = le16_to_cpu(pscanperiod->State);
|
|
pscanperiod->ScanPeriod =
|
|
le32_to_cpu(pscanperiod->ScanPeriod);
|
|
state = pscanperiod->State;
|
|
scanmode = pscanperiod->SearchMode;
|
|
if ((state < STATE_STABLE) ||
|
|
(state > STATE_UNACCEPTABLE)) {
|
|
puts("\nIncorrect state in response.\n");
|
|
}
|
|
if ((scanmode < DISCOVERY_MODE) ||
|
|
(scanmode > TRACKING_MODE)) {
|
|
puts("\nIncorrect scanmode in response.\n");
|
|
}
|
|
values[state - 1][scanmode - 1] =
|
|
pscanperiod->ScanPeriod;
|
|
tlvptr +=
|
|
(le16_to_cpu(pscanperiod->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
cmdresplen -=
|
|
(le16_to_cpu(pscanperiod->Header.len) +
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
break;
|
|
|
|
default:
|
|
puts("\nIncorrect response.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (state = STATE_STABLE - 1; state < STATE_UNACCEPTABLE; state++) {
|
|
printf("\nState: %-14s ", states[state]);
|
|
for (scanmode = DISCOVERY_MODE - 1;
|
|
scanmode < TRACKING_MODE; scanmode++) {
|
|
printf("%s = %6d ms\t",
|
|
scanmodes[scanmode],
|
|
(int)values[state][scanmode]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra command
|
|
*
|
|
* @param pcontrol control struct to return
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
getControl(HostCmd_DS_CMD_ROAMAGENT_CONTROL *pcontrol)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd = NULL;
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
cmd_len = S_DS_GEN + sizeof(roamcontrolcmd->action);
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos;
|
|
|
|
roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamcontrol]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
memcpy((void *)pcontrol,
|
|
(void *)roamcontrolcmd,
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL));
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param control roma control indicator value
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetEventBitmap(int argc, char *argv[])
|
|
{
|
|
t_u8 hostevent;
|
|
HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd;
|
|
|
|
if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
hostevent = roamcontrolcmd.HostEvent;
|
|
if (!(hostevent | 0)) {
|
|
puts("\nHost events are disabled.\n");
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
printf("\nHost events enabled: ");
|
|
if (hostevent & HOST_EVENT_NBOR_ENABLE)
|
|
printf("neighbor ");
|
|
|
|
if (hostevent & HOST_EVENT_ROAM_ENABLE)
|
|
printf("roam ");
|
|
|
|
if (hostevent & HOST_EVENT_STATE_ENABLE)
|
|
printf("state");
|
|
|
|
printf("\n");
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param control roma control indicator value
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetControl(int argc, char *argv[])
|
|
{
|
|
t_u8 control;
|
|
HostCmd_DS_CMD_ROAMAGENT_CONTROL roamcontrolcmd;
|
|
|
|
if (getControl(&roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
control = roamcontrolcmd.Control;
|
|
printf("\nGlobal roaming agent state: ");
|
|
if (control & ROAM_CONTROL_ENABLE) {
|
|
printf("enabled, ");
|
|
if (control & ROAM_CONTROL_SUSPEND)
|
|
printf("suspend.\n");
|
|
else
|
|
printf("resume.\n");
|
|
} else
|
|
printf("disabled.\n");
|
|
|
|
printf("Crossband: ");
|
|
if (control & CROSSBAND_ENABLE)
|
|
printf("enabled.\n");
|
|
else
|
|
printf("disabled.\n");
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Internal funtion to issue getra backoff
|
|
*
|
|
* @param roambackoffcmd Backoff command structure
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
getBackOff(HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmdParam)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd;
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
free(buffer);
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(roambackoffcmd->action);
|
|
roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_GET);
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roambackoff]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* ENDIANNESS for Response
|
|
*/
|
|
roambackoffcmd->Scans = le16_to_cpu(roambackoffcmd->Scans);
|
|
roambackoffcmd->Period = le32_to_cpu(roambackoffcmd->Period);
|
|
|
|
memcpy((void *)roambackoffcmdParam, (void *)roambackoffcmd,
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF));
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue getra backoff command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param control roma control indicator value
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamGetBackOff(int argc, char *argv[])
|
|
{
|
|
HostCmd_DS_CMD_ROAMAGENT_BACKOFF backoffcmd;
|
|
|
|
if (getBackOff(&backoffcmd) != MLAN_STATUS_SUCCESS) {
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
puts("");
|
|
printf("----------------------------------------------------\n");
|
|
printf(" Scanning Backoff Parameters \n");
|
|
printf("----------------------------------------------------\n");
|
|
printf(" Backoff period (max time in tracking) = %d ms\n",
|
|
backoffcmd.Period);
|
|
printf(" # of discovery scans before backoff = %d\n",
|
|
backoffcmd.Scans);
|
|
puts("");
|
|
|
|
if (backoffcmd.Scans) {
|
|
printf(" - Discovery backoff mode is enabled.\n"
|
|
" After %d discovery scans without a change in the number\n"
|
|
" of neighbors, the RA will only track the existing\n"
|
|
" neighbors until the backoff period expires.\n",
|
|
backoffcmd.Scans);
|
|
} else {
|
|
printf(" - Discovery backoff mode is disabled.\n"
|
|
" The RA will only move to tracking mode if a minimum\n"
|
|
" number of good neighbors have been found. See the\n"
|
|
" getra neighbor command for the current min setting.\n");
|
|
}
|
|
puts("");
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
printGetNeighborDeprecation(int argc, char *argv[])
|
|
{
|
|
printf("\nInfo: getra neighbor replaced with:\n"
|
|
" - getra nlist (display neighbor list)\n"
|
|
" - getra nparams (display neighbor assessment params)\n\n");
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the Roaming agent configuration parameters from FW.
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
process_get_ra_config(int argc, char *argv[])
|
|
{
|
|
if (argc == 3) {
|
|
return roamGetControl(argc, argv);
|
|
}
|
|
|
|
sub_cmd_exec_t subCmds[] = {
|
|
{"rssi", 1, 1, roamGetRssiStatsThreshold},
|
|
{"prebcnmiss", 1, 1, roamGetPreBeaconMiss},
|
|
{"failcnt", 1, 1, roamGetFailureCount},
|
|
{"backoff", 1, 1, roamGetBackOff},
|
|
{"neighbor", 2, 0, printGetNeighborDeprecation},
|
|
{"nlist", 2, 1, roamGetNborList},
|
|
{"nparams", 2, 1, roamGetNborParams},
|
|
{"scanperiod", 1, 1, roamGetScanPeriod},
|
|
{"metrics", 1, 1, roamGetMetrics},
|
|
{"event", 1, 1, roamGetEventBitmap}
|
|
};
|
|
|
|
return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv);
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra bcnmiss command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetPreBeaconLoss(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int bcnmiss;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_BeaconsMissed_t *beaconmiss;
|
|
|
|
if (argc != 1) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
bcnmiss = atoi(argv[0]);
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
cmd_len = sizeof(HostCmd_DS_GEN) + sizeof(statsthreshold->action) +
|
|
sizeof(statsthreshold->State) +
|
|
sizeof(statsthreshold->Profile) +
|
|
sizeof(MrvlIEtypes_BeaconsMissed_t);
|
|
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
statsthreshold->State = STATE_HARDROAM;
|
|
|
|
beaconmiss = (MrvlIEtypes_BeaconsMissed_t *)&statsthreshold->TlvBuffer;
|
|
beaconmiss->beacon_missed = bcnmiss;
|
|
beaconmiss->header.type = cpu_to_le16(TLV_TYPE_PRE_BEACON_LOST);
|
|
beaconmiss->header.len =
|
|
cpu_to_le16(sizeof(MrvlIEtypes_BeaconsMissed_t) -
|
|
sizeof(MrvlIEtypesHeader_t));
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[setra]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
roamGetPreBeaconMiss(argc, argv);
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra failurecnt command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetFailureCount(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int failCount, failTimeThresh;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_FailureCount_t *failcnt;
|
|
|
|
if (argc != 2) {
|
|
puts("\n2 arguments required: FailCnt, FailTimeThresh(ms)\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
failCount = atoi(argv[0]);
|
|
failTimeThresh = atoi(argv[1]);
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
|
|
cmd_len = (S_DS_GEN +
|
|
sizeof(statsthreshold->action) +
|
|
sizeof(statsthreshold->State) +
|
|
sizeof(statsthreshold->Profile) +
|
|
sizeof(MrvlIEtypes_FailureCount_t));
|
|
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
statsthreshold->State = STATE_HARDROAM;
|
|
|
|
failcnt = (MrvlIEtypes_FailureCount_t *)&statsthreshold->TlvBuffer;
|
|
failcnt->fail_value = failCount;
|
|
failcnt->fail_min_thresh_time_millisecs = cpu_to_le16(failTimeThresh);
|
|
failcnt->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
|
|
failcnt->header.len = cpu_to_le16(sizeof(MrvlIEtypes_FailureCount_t)
|
|
- sizeof(MrvlIEtypesHeader_t));
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[setra]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
roamGetFailureCount(argc, argv);
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra rssi/snr command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param type RSSI/SNR threshold type
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetStatsThreshold(int argc, char *argv[], int type)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int i, state = 0, low = 0, high = 0, lowval, highval;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *statsthreshold;
|
|
MrvlIEtypes_BeaconHighRssiThreshold_t *bcnhighrssi;
|
|
MrvlIEtypes_BeaconLowRssiThreshold_t *bcnlowrssi;
|
|
MrvlIEtypes_BeaconHighSnrThreshold_t *bcnhighsnr;
|
|
MrvlIEtypes_BeaconLowSnrThreshold_t *bcnlowsnr;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nInsufficient arguments.. \n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) {
|
|
state = STATE_STABLE;
|
|
/* degrad[ing] */
|
|
} else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) {
|
|
state = STATE_DEGRADING;
|
|
/* unaccep[table] */
|
|
} else if (argv[0]
|
|
&& strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) {
|
|
state = STATE_UNACCEPTABLE;
|
|
} else {
|
|
puts("\nUnknown state. Use stable/degrading/unacceptable\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
if (argc != 3 && argc != 5) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
if (argv[1] && strncmp(argv[1], "low", strlen("low")) == 0) {
|
|
low = 1;
|
|
lowval = atoi(argv[2]);
|
|
/* TODO validation check on lowval */
|
|
}
|
|
if (argv[1 + (2 * low)]
|
|
&& strncmp(argv[1 + (2 * low)], "high", strlen("high")) == 0) {
|
|
high = 1;
|
|
highval = atoi(argv[2 + (2 * low)]);
|
|
/* TODO validation check on highval */
|
|
}
|
|
/* check if low is specified after high */
|
|
if ((low == 0) && (argc == 5)) {
|
|
if (argv[1 + (2 * high)]
|
|
&& strncmp(argv[1 + (2 * high)], "low", strlen("low")) == 0) {
|
|
low = 1;
|
|
lowval = atoi(argv[2 + 2 * (high)]);
|
|
/* TODO validation check on lowval */
|
|
}
|
|
}
|
|
|
|
if (!low && !high) {
|
|
puts("\nIncorrect argument. Use low <low val>/high <high val>\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
statsthreshold = (HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD *)pos;
|
|
cmd_len =
|
|
(S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_STATISTICS_THRESHOLD)
|
|
- sizeof(statsthreshold->TlvBuffer));
|
|
if (type == RSSI_THRESHOLD) {
|
|
if (high) {
|
|
cmd_len +=
|
|
sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
|
|
}
|
|
if (low) {
|
|
cmd_len += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
|
|
}
|
|
} else {
|
|
if (high) {
|
|
cmd_len += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
|
|
}
|
|
if (low) {
|
|
cmd_len += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
|
|
}
|
|
}
|
|
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_STATISTICS_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
statsthreshold->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
statsthreshold->State = state;
|
|
|
|
/*
|
|
* TLV buffer start pointer initialization
|
|
*/
|
|
i = 0;
|
|
if (type == RSSI_THRESHOLD) {
|
|
if (high) {
|
|
bcnhighrssi = (MrvlIEtypes_BeaconHighRssiThreshold_t *)
|
|
(((t_u8 *)&statsthreshold->TlvBuffer) + i);
|
|
bcnhighrssi->Header.type = TLV_TYPE_RSSI_HIGH;
|
|
bcnhighrssi->Header.len =
|
|
(sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t)
|
|
- sizeof(MrvlIEtypesHeader_t));
|
|
bcnhighrssi->Value = highval;
|
|
i += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
bcnhighrssi->Header.type =
|
|
cpu_to_le16(bcnhighrssi->Header.type);
|
|
bcnhighrssi->Header.len =
|
|
cpu_to_le16(bcnhighrssi->Header.len);
|
|
}
|
|
|
|
if (low) {
|
|
bcnlowrssi = (MrvlIEtypes_BeaconLowRssiThreshold_t *)
|
|
(((t_u8 *)&statsthreshold->TlvBuffer) + i);
|
|
bcnlowrssi->Header.type = TLV_TYPE_RSSI_LOW;
|
|
bcnlowrssi->Header.len =
|
|
(sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t)
|
|
- sizeof(MrvlIEtypesHeader_t));
|
|
bcnlowrssi->Value = lowval;
|
|
i += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
bcnlowrssi->Header.type =
|
|
cpu_to_le16(bcnlowrssi->Header.type);
|
|
bcnlowrssi->Header.len =
|
|
cpu_to_le16(bcnlowrssi->Header.len);
|
|
}
|
|
} else {
|
|
if (high) {
|
|
bcnhighsnr = (MrvlIEtypes_BeaconHighSnrThreshold_t *)
|
|
(((t_u8 *)&statsthreshold->TlvBuffer) + i);
|
|
bcnhighsnr->Header.type = TLV_TYPE_SNR_HIGH;
|
|
bcnhighsnr->Header.len =
|
|
(sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t)
|
|
- sizeof(MrvlIEtypesHeader_t));
|
|
bcnhighsnr->Value = highval;
|
|
i += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
bcnhighsnr->Header.type =
|
|
cpu_to_le16(bcnhighsnr->Header.type);
|
|
bcnhighsnr->Header.len =
|
|
cpu_to_le16(bcnhighsnr->Header.len);
|
|
}
|
|
if (low) {
|
|
bcnlowsnr = (MrvlIEtypes_BeaconLowSnrThreshold_t *)
|
|
(((t_u8 *)&statsthreshold->TlvBuffer) + i);
|
|
bcnlowsnr->Header.type = TLV_TYPE_SNR_LOW;
|
|
bcnlowsnr->Header.len =
|
|
(sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t)
|
|
- sizeof(MrvlIEtypesHeader_t));
|
|
bcnlowsnr->Value = lowval;
|
|
i += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
bcnlowsnr->Header.type =
|
|
cpu_to_le16(bcnlowsnr->Header.type);
|
|
bcnlowsnr->Header.len =
|
|
cpu_to_le16(bcnlowsnr->Header.len);
|
|
}
|
|
}
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[setra]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra rssi command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetRssiStatsThreshold(int argc, char *argv[])
|
|
{
|
|
if (roamSetStatsThreshold(argc, argv, RSSI_THRESHOLD)
|
|
== MLAN_STATUS_SUCCESS) {
|
|
roamGetStatsThreshold(0, argv, RSSI_THRESHOLD);
|
|
}
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra scanperiod command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetScanPeriod(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int scanmode = 0, period = 0, state = 0;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *scanPeriodInfo;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nInsufficient arguments.. \n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* scanperiod */
|
|
if (argc != 3) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argv[0] && strncmp(argv[0], "stable", strlen("stable")) == 0) {
|
|
state = STATE_STABLE;
|
|
/* degrad[ing] */
|
|
} else if (argv[0] && strncmp(argv[0], "degrad", strlen("degrad")) == 0) {
|
|
state = STATE_DEGRADING;
|
|
/* unaccep[table] */
|
|
} else if (argv[0]
|
|
&& strncmp(argv[0], "unaccep", strlen("unaccep")) == 0) {
|
|
state = STATE_UNACCEPTABLE;
|
|
} else {
|
|
puts("\nUnknown state. Use stable/degrading/unacceptable\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argv[1] && strncmp(argv[1], "disc", strlen("disc")) == 0) {
|
|
scanmode = DISCOVERY_MODE;
|
|
/* track[ing] */
|
|
} else if (argv[1] && strncmp(argv[1], "track", strlen("track")) == 0) {
|
|
scanmode = TRACKING_MODE;
|
|
} else {
|
|
puts("\nUnknown scamode. Use discovery/ tracking\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
period = atoi(argv[2]);
|
|
/* TODO validation check on period */
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
scanPeriodInfo = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD *)pos;
|
|
cmd_len =
|
|
S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_SCANPERIOD);
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_SCAN_PERIOD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
scanPeriodInfo->action = HostCmd_ACT_GEN_SET;
|
|
scanPeriodInfo->scanPeriod.Header.type = TLV_TYPE_NEIGHBOR_SCANPERIOD;
|
|
scanPeriodInfo->scanPeriod.Header.len =
|
|
sizeof(MrvlIEtypes_NeighborScanPeriod_t) -
|
|
sizeof(MrvlIEtypesHeader_t);
|
|
scanPeriodInfo->scanPeriod.SearchMode = scanmode;
|
|
scanPeriodInfo->scanPeriod.State = state;
|
|
scanPeriodInfo->scanPeriod.ScanPeriod = period;
|
|
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
scanPeriodInfo->action = cpu_to_le16(scanPeriodInfo->action);
|
|
scanPeriodInfo->scanPeriod.Header.type = cpu_to_le16
|
|
(scanPeriodInfo->scanPeriod.Header.type);
|
|
scanPeriodInfo->scanPeriod.Header.len = cpu_to_le16
|
|
(scanPeriodInfo->scanPeriod.Header.len);
|
|
scanPeriodInfo->scanPeriod.SearchMode = cpu_to_le16
|
|
(scanPeriodInfo->scanPeriod.SearchMode);
|
|
scanPeriodInfo->scanPeriod.State = cpu_to_le16
|
|
(scanPeriodInfo->scanPeriod.State);
|
|
scanPeriodInfo->scanPeriod.ScanPeriod = cpu_to_le32
|
|
(scanPeriodInfo->scanPeriod.ScanPeriod);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[neighborlist maintain]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Check it string contains digits
|
|
* @param str string to check for digits
|
|
* @return same as isdigit(char)
|
|
*/
|
|
static inline int
|
|
isdigitstr(char *str)
|
|
{
|
|
unsigned int i = 0;
|
|
for (i = 0; i < strlen(str); i++) {
|
|
if (!isdigit((str)[i]))
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Process sub command
|
|
*
|
|
* @param valid_cmds valid commands array
|
|
* @param count number of valid commands
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param param argc parameter counter
|
|
* @param value values to update back
|
|
*
|
|
* @return command index--success, otherwise--fail
|
|
*/
|
|
static int
|
|
process_subcmd(char *valid_cmds[], int count, int argc, char *argv[],
|
|
int *param, int *value)
|
|
{
|
|
int ret = 0;
|
|
int j = *param;
|
|
int k;
|
|
while (1) {
|
|
for (k = 0; k < count; k++)
|
|
if (argv[j] &&
|
|
!strncmp(valid_cmds[k], argv[j],
|
|
strlen(valid_cmds[k])))
|
|
break;
|
|
if (k >= count) {
|
|
break;
|
|
} else {
|
|
/* special case */
|
|
if (!strncmp
|
|
(valid_cmds[k], "perperiod", strlen("perperiod")) ||
|
|
!strncmp(valid_cmds[k], "ferperiod",
|
|
strlen("ferperiod"))) {
|
|
*param = j;
|
|
return ret | 1 << k;
|
|
}
|
|
if (!argv[j + 1] || !isdigitstr(argv[j + 1]))
|
|
return -1;
|
|
value[k] = atoi(argv[j + 1]);
|
|
j = j + 2;
|
|
ret |= (1 << k);
|
|
}
|
|
|
|
if (j >= argc) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*param == j) {
|
|
return -1;
|
|
}
|
|
|
|
*param = j;
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
printSetNeighborDeprecation(int argc, char *argv[])
|
|
{
|
|
printf("\nInfo: setra neighbor replaced with:\n"
|
|
" - setra nparams (config neighbor assessment params)\n\n");
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra neighbor command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetNborParams(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
int trackcount = 0, i = 0, j = 0;
|
|
int blist[2] = { 0, 0 }; /* blacklist short and long: 0-short 1-long */
|
|
int qualoffset[1] = { 0 }; /* rssi */
|
|
int stalecount = ~0;
|
|
int staleperiod = ~0;
|
|
signed char temp;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
char *valid_cmds[] = { "trackcount", "qualoffset", "blacklistdur",
|
|
"stalecount", "staleperiod", "roamthresh"
|
|
};
|
|
|
|
/** blacklistdur sub commands */
|
|
char *valid_blcmds[] = { "short", "long" };
|
|
|
|
/** qualoffset sub commands */
|
|
char *valid_bfcmds[] = { "rssi" };
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *pNborAssessment;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nUnknown setra nparams subcmd. Valid subcmds:");
|
|
for (i = 0; i < NELEMENTS(valid_cmds); i++) {
|
|
printf(" - %s\n", valid_cmds[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argc < 2 || argc > 18) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
pNborAssessment = (HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT *)pos;
|
|
cmd_len =
|
|
S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
|
|
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBOR_ASSESSMENT);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
/* Get parameters unspecified on command line */
|
|
if (getNborAssessment(pNborAssessment) != MLAN_STATUS_SUCCESS) {
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
while (argc - j) {
|
|
for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++) {
|
|
if (!strncmp
|
|
(valid_cmds[i], argv[j], strlen(valid_cmds[i])))
|
|
break;
|
|
}
|
|
|
|
if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
|
|
printf("\nInvalid argument to \"%s\"\n\n", argv[0]);
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
/** trackcount */
|
|
trackcount = atoi(argv[j + 1]);
|
|
pNborAssessment->QualifyingNumNeighbor = trackcount;
|
|
j = j + 2;
|
|
break;
|
|
|
|
case 1:
|
|
/** qualoffset */
|
|
j++;
|
|
ret = process_subcmd(valid_bfcmds,
|
|
NELEMENTS(valid_bfcmds), argc,
|
|
argv, &j, qualoffset);
|
|
if (ret == -1) {
|
|
printf("\nInvalid argument to \"%s\"\n\n",
|
|
argv[j - 1]);
|
|
ret = ret;
|
|
goto done;
|
|
}
|
|
pNborAssessment->ConfQualSignalStrength = qualoffset[0];
|
|
break;
|
|
|
|
case 2:
|
|
/** blacklistdur */
|
|
j++;
|
|
ret = process_subcmd(valid_blcmds,
|
|
NELEMENTS(valid_blcmds), argc,
|
|
argv, &j, blist);
|
|
if (ret == -1) {
|
|
printf("\nInvalid argument to \"%s\"\n\n",
|
|
argv[j - 1]);
|
|
ret = ret;
|
|
goto done;
|
|
} else {
|
|
if (ret & 0x01) {
|
|
pNborAssessment->ShortBlacklistPeriod =
|
|
blist[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
pNborAssessment->LongBlacklistPeriod =
|
|
blist[1];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
/** stalecount */
|
|
stalecount = atoi(argv[j + 1]);
|
|
pNborAssessment->StaleCount = stalecount;
|
|
j = j + 2;
|
|
break;
|
|
|
|
case 4:
|
|
/** staleperiod */
|
|
staleperiod = atoi(argv[j + 1]);
|
|
pNborAssessment->StalePeriod = staleperiod;
|
|
j = j + 2;
|
|
break;
|
|
|
|
case 5:
|
|
/** roamthresh */
|
|
j++;
|
|
temp = 0;
|
|
for (i = 0; j + i < argc; i++) {
|
|
if (isdigit(*argv[j + i]) ||
|
|
(*argv[j + i] == '-')) {
|
|
temp++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((temp % 3 != 0) || (temp > 12)) {
|
|
puts("");
|
|
printf("Error: %d numeric arguments detected for roamthresh.\n" " Roam threhold values must be specified in\n" " multiples of 3 (low, high, diff triplets) up\n" " to a maximum of 4 sets (12 numbers max).\n", temp);
|
|
puts("");
|
|
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
for (i = 0; (i < 12); i++) {
|
|
if ((j >= argc) ||
|
|
(!isdigit(*argv[j]) && *argv[j] != '-')) {
|
|
temp = 0;
|
|
} else {
|
|
temp = atoi(argv[j]);
|
|
j++;
|
|
}
|
|
|
|
switch (i % 3) {
|
|
case 0:
|
|
pNborAssessment->RoamThresh[i /
|
|
3].
|
|
RssiHighLevel = temp;
|
|
break;
|
|
|
|
case 1:
|
|
pNborAssessment->RoamThresh[i /
|
|
3].
|
|
RssiLowLevel = temp;
|
|
break;
|
|
|
|
case 2:
|
|
pNborAssessment->RoamThresh[i /
|
|
3].
|
|
RssiNborDiff = temp;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
pNborAssessment->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
|
|
/* Both stalecount, staleperiod can not be zero */
|
|
if ((pNborAssessment->StaleCount == 0) &&
|
|
(pNborAssessment->StalePeriod == 0)) {
|
|
|
|
puts("\nstalecount and staleperiod both can not be zero\n");
|
|
ret = (MLAN_STATUS_FAILURE);
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
pNborAssessment->QualifyingNumNeighbor =
|
|
cpu_to_le16(pNborAssessment->QualifyingNumNeighbor);
|
|
pNborAssessment->ShortBlacklistPeriod =
|
|
cpu_to_le32(pNborAssessment->ShortBlacklistPeriod);
|
|
pNborAssessment->LongBlacklistPeriod =
|
|
cpu_to_le32(pNborAssessment->LongBlacklistPeriod);
|
|
pNborAssessment->StaleCount = cpu_to_le16(pNborAssessment->StaleCount);
|
|
pNborAssessment->StalePeriod =
|
|
cpu_to_le16(pNborAssessment->StalePeriod);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roam neighbor assessment]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printNeighborAssessmentConfig();
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra metrics command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetMetrics(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *metricscmd;
|
|
|
|
int perlist[3] = { 0, 0, 0 }; /* 0=inactivity,
|
|
1=perthreshold,
|
|
2=packetthreshold */
|
|
int ferlist[3] = { 0, 0, 0 }; /* 0=inactivity,
|
|
1=ferthreshold,
|
|
2=framethreshold */
|
|
int perstate[3] = { 0, 0, 0 }; /* 0=stable, 1=degrading, 2=unacceptable */
|
|
int ferstate[3] = { 0, 0, 0 }; /* 0=stable, 1=degrading, 2=unacceptable */
|
|
int datalist[2] = { 0, 0 }; /* 0=inactivity, 1=datathreshold */
|
|
char *valid_cmds[] = { "Beacon", "Data", "PER", "FER" };
|
|
|
|
/** PER sub commands */
|
|
char *valid_percmds[] = { "inactivity", "perthreshold",
|
|
"packetthreshold", "perperiod"
|
|
};
|
|
|
|
char *valid_fercmds[] = { "inactivity", "ferthreshold",
|
|
"framethreshold", "ferperiod"
|
|
};
|
|
|
|
/** PER period states */
|
|
char *per_states[] = { "stable", "degrading", "unacceptable" };
|
|
|
|
/** Data sub commands */
|
|
char *valid_datacmds[] = { "inactivity", "datathreshold" };
|
|
|
|
int i = 0, j = 0;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nInsufficient arguments.. \n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argc < 1 || argc > 38) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
cmd_len =
|
|
S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
|
|
|
|
hostcmd->command =
|
|
cpu_to_le16(HostCmd_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
metricscmd = (HostCmd_DS_CMD_ROAMAGENT_ADV_METRIC_THRESHOLD *)pos;
|
|
metricscmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
|
|
/* clear [ Beacon/Data/PER ] */
|
|
if (!strncmp("clear", argv[j], strlen("clear"))) {
|
|
if (argc == 1) {
|
|
puts("\nInvalid number of argument");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
while (1) {
|
|
j++;
|
|
for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds);
|
|
i++) {
|
|
if (!strncmp
|
|
(valid_cmds[i], argv[j],
|
|
strlen(valid_cmds[i])))
|
|
break;
|
|
}
|
|
if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
|
|
printf("\nInvalid argument \"%s\"\n\n",
|
|
argv[j]);
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
} else {
|
|
metricscmd->Metrics |= BIT(i);
|
|
}
|
|
|
|
if (j >= (argc - 1)) {
|
|
break;
|
|
}
|
|
}
|
|
metricscmd->action = HostCmd_ACT_GEN_REMOVE;
|
|
} else { /* set [ Beacon/Data/PER ] */
|
|
|
|
while (argc - j) {
|
|
for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds);
|
|
i++) {
|
|
if (!strncmp
|
|
(valid_cmds[i], argv[j],
|
|
strlen(valid_cmds[i])))
|
|
break;
|
|
}
|
|
if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
|
|
printf("\nInvalid argument to \"%s\"\n\n",
|
|
argv[j]);
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
switch (i) {
|
|
case 0:
|
|
/** Beacon */
|
|
j++;
|
|
metricscmd->Metrics |= 0x01;
|
|
break;
|
|
|
|
case 1:
|
|
/** Data*/
|
|
j++;
|
|
ret = process_subcmd(valid_datacmds,
|
|
NELEMENTS(valid_datacmds),
|
|
argc, argv, &j, datalist);
|
|
if (ret > 0) {
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
InactivityPeriodThreshold_ms
|
|
= datalist[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->UiRxPktThreshold =
|
|
datalist[1];
|
|
}
|
|
}
|
|
metricscmd->Metrics |= 0x02;
|
|
break;
|
|
|
|
case 2:
|
|
/** PER */
|
|
j++;
|
|
ret = process_subcmd(valid_percmds,
|
|
NELEMENTS(valid_percmds),
|
|
argc, argv, &j, perlist);
|
|
if (ret > 0) {
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
InactivityPeriodThreshold_ms
|
|
= perlist[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
UcPerThresholdValue =
|
|
perlist[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->UiPerPktThreshold =
|
|
perlist[2];
|
|
}
|
|
if (ret & 0x08) {
|
|
j++;
|
|
ret = process_subcmd(per_states,
|
|
NELEMENTS
|
|
(per_states),
|
|
argc, argv,
|
|
&j,
|
|
perstate);
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
StablePERPeriod_ms
|
|
= perstate[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
DegradingPERPeriod_ms
|
|
= perstate[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->
|
|
UnacceptablePERPeriod_ms
|
|
= perstate[2];
|
|
}
|
|
if (j < argc) {
|
|
ret = process_subcmd
|
|
(valid_percmds,
|
|
NELEMENTS
|
|
(valid_percmds),
|
|
argc, argv, &j,
|
|
perlist);
|
|
if (ret > 0) {
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
InactivityPeriodThreshold_ms
|
|
=
|
|
perlist
|
|
[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
UcPerThresholdValue
|
|
=
|
|
perlist
|
|
[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->
|
|
UiPerPktThreshold
|
|
=
|
|
perlist
|
|
[2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
metricscmd->Metrics |= 0x04;
|
|
break;
|
|
|
|
case 3:
|
|
/** FER */
|
|
j++;
|
|
ret = process_subcmd(valid_fercmds,
|
|
NELEMENTS(valid_fercmds),
|
|
argc, argv, &j, ferlist);
|
|
if (ret > 0) {
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
InactivityPeriodThreshold_ms
|
|
= ferlist[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
UcFerThresholdValue =
|
|
ferlist[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->UiFerPktThreshold =
|
|
ferlist[2];
|
|
}
|
|
if (ret & 0x08) {
|
|
j++;
|
|
ret = process_subcmd(per_states,
|
|
NELEMENTS
|
|
(per_states),
|
|
argc, argv,
|
|
&j,
|
|
ferstate);
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
StableFERPeriod_ms
|
|
= ferstate[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
DegradingFERPeriod_ms
|
|
= ferstate[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->
|
|
UnacceptableFERPeriod_ms
|
|
= ferstate[2];
|
|
}
|
|
if (j < argc) {
|
|
ret = process_subcmd
|
|
(valid_fercmds,
|
|
NELEMENTS
|
|
(valid_fercmds),
|
|
argc, argv, &j,
|
|
ferlist);
|
|
if (ret > 0) {
|
|
if (ret & 0x01) {
|
|
metricscmd->
|
|
InactivityPeriodThreshold_ms
|
|
=
|
|
ferlist
|
|
[0];
|
|
}
|
|
if (ret & 0x02) {
|
|
metricscmd->
|
|
UcFerThresholdValue
|
|
=
|
|
ferlist
|
|
[1];
|
|
}
|
|
if (ret & 0x04) {
|
|
metricscmd->
|
|
UiFerPktThreshold
|
|
=
|
|
ferlist
|
|
[2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
metricscmd->Metrics |= 0x08;
|
|
break;
|
|
}
|
|
metricscmd->action = HostCmd_ACT_GEN_SET;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ENDIANNESS
|
|
*/
|
|
metricscmd->action = cpu_to_le16(metricscmd->action);
|
|
metricscmd->Metrics = cpu_to_le16(metricscmd->Metrics);
|
|
metricscmd->UiPerPktThreshold =
|
|
cpu_to_le32(metricscmd->UiPerPktThreshold);
|
|
metricscmd->StablePERPeriod_ms =
|
|
cpu_to_le32(metricscmd->StablePERPeriod_ms);
|
|
metricscmd->DegradingPERPeriod_ms =
|
|
cpu_to_le32(metricscmd->DegradingPERPeriod_ms);
|
|
metricscmd->UnacceptablePERPeriod_ms =
|
|
cpu_to_le32(metricscmd->UnacceptablePERPeriod_ms);
|
|
metricscmd->InactivityPeriodThreshold_ms =
|
|
cpu_to_le32(metricscmd->InactivityPeriodThreshold_ms);
|
|
metricscmd->UiRxPktThreshold =
|
|
cpu_to_le32(metricscmd->UiRxPktThreshold);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[neighborlist maintain]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Process maintenance of Neighbor list
|
|
*
|
|
* @param argc # arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
*/
|
|
static int
|
|
roamSetNborMaintenance(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
char *valid_cmds[] = { "blacklist", "clear" };
|
|
int i = 0, j = 0, k = 0;
|
|
unsigned int mac[ETH_ALEN];
|
|
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *pNborMaintainance;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nInsufficient arguments.. \n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
if (argc != 2) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
for (i = 0; (unsigned int)i < NELEMENTS(valid_cmds); i++)
|
|
if (!strncmp(valid_cmds[i], argv[j], strlen(valid_cmds[i])))
|
|
break;
|
|
if ((unsigned int)i >= NELEMENTS(valid_cmds)) {
|
|
printf("\nInvalid argument \"%s\"\n\n", argv[0]);
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
switch (i) {
|
|
case 0:
|
|
/** blacklist */
|
|
j++;
|
|
sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x",
|
|
mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
|
|
for (k = 0; k < ETH_ALEN; k++) {
|
|
if (*(mac + k) != 0xFF) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (k == ETH_ALEN) {
|
|
puts("\nBlacklisting a Broadcast address is not allowed");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
/** clear */
|
|
j++;
|
|
if (!strncmp("all", argv[j], strlen("all"))) {
|
|
for (k = 0; k < ETH_ALEN; k++) {
|
|
*(mac + k) = 0xFF;
|
|
}
|
|
} else {
|
|
sscanf(argv[j], "%2x:%2x:%2x:%2x:%2x:%2x",
|
|
mac, mac + 1, mac + 2, mac + 3, mac + 4,
|
|
mac + 5);
|
|
}
|
|
break;
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
pNborMaintainance
|
|
= (HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE *)pos;
|
|
|
|
cmd_len = S_DS_GEN +
|
|
sizeof(HostCmd_DS_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE);
|
|
|
|
hostcmd->command
|
|
= cpu_to_le16(HostCmd_CMD_ROAMAGENT_NEIGHBORLIST_MAINTENANCE);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
pNborMaintainance->action = ((i == 0) ? HostCmd_ACT_ADD_TO_BLACKLIST :
|
|
HostCmd_ACT_REMOVE_FROM_BLACKLIST);
|
|
pNborMaintainance->action = cpu_to_le16(pNborMaintainance->action);
|
|
for (k = 0; k < ETH_ALEN; k++) {
|
|
pNborMaintainance->BSSID[k] = *(mac + k);
|
|
}
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[neighborlist maintain]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra backoff command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetBackOff(int argc, char *argv[])
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
int spflag[2] = { 0, 0 }; /*scan,priod */
|
|
t_u16 minscan;
|
|
t_u32 bperiod;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_BACKOFF *roambackoffcmd;
|
|
int i;
|
|
|
|
if (argv[0] == NULL) {
|
|
puts("\nInsufficient arguments.. \n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
/* BackOff */
|
|
if ((argc != 2) && (argc != 4)) {
|
|
puts("\nIncorrect number of arguments.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (argv[i + 0] &&
|
|
strncmp(argv[i + 0], "scans", strlen("scans")) == 0) {
|
|
minscan = atoi(argv[i + 1]);
|
|
i++;
|
|
spflag[0] = 1;
|
|
/* TODO validation check on minscan */
|
|
}
|
|
if (argv[i + 0] &&
|
|
strncmp(argv[i + 0], "period", strlen("period")) == 0) {
|
|
bperiod = atoi(argv[i + 1]);
|
|
i++;
|
|
spflag[1] = 1;
|
|
/* TODO validation check on bperiod */
|
|
}
|
|
}
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
roambackoffcmd = (HostCmd_DS_CMD_ROAMAGENT_BACKOFF *)pos;
|
|
cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_BACKOFF);
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_BACKOFF);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
switch (spflag[0] + spflag[1]) {
|
|
case 0:
|
|
/* error */
|
|
puts("\nIncorrect arguments for setra backoff command.\n");
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
|
|
case 1:
|
|
/* get missing parameter */
|
|
if (getBackOff(roambackoffcmd) != MLAN_STATUS_SUCCESS) {
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
if (spflag[0] == 0) {
|
|
minscan = roambackoffcmd->Scans;
|
|
} else {
|
|
bperiod = roambackoffcmd->Period;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
roambackoffcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
roambackoffcmd->Scans = cpu_to_le16(minscan);
|
|
roambackoffcmd->Period = cpu_to_le16(bperiod);
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roambackoff]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra enable/disable/resume/suspend command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param set/reset set/reset flag
|
|
* @param value roam control/ host event bitmap value
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetControl(int argc, char *argv[], int setreset, t_u8 value)
|
|
{
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
struct ifreq ifr;
|
|
t_u8 *buffer = NULL, *pos = NULL;
|
|
t_u32 cmd_len = 0, cmd_header_len;
|
|
struct eth_priv_cmd *cmd = NULL;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_CMD_ROAMAGENT_CONTROL *roamcontrolcmd;
|
|
|
|
cmd_header_len = strlen(CMD_NXP) + strlen(HOSTCMD);
|
|
|
|
buffer = (t_u8 *)malloc(BUFFER_LENGTH);
|
|
if (buffer == NULL) {
|
|
fprintf(stderr, "Cannot alloc memory\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
memset(buffer, 0, BUFFER_LENGTH);
|
|
|
|
cmd = (struct eth_priv_cmd *)malloc(sizeof(struct eth_priv_cmd));
|
|
if (!cmd) {
|
|
printf("ERR:Cannot allocate buffer for command!\n");
|
|
ret = ENOMEM;
|
|
goto done;
|
|
}
|
|
|
|
/* Fill up buffer */
|
|
#ifdef USERSPACE_32BIT_OVER_KERNEL_64BIT
|
|
memset(cmd, 0, sizeof(struct eth_priv_cmd));
|
|
memcpy(&cmd->buf, &buffer, sizeof(buffer));
|
|
#else
|
|
cmd->buf = buffer;
|
|
#endif
|
|
cmd->used_len = 0;
|
|
cmd->total_len = BUFFER_LENGTH;
|
|
|
|
/* buffer = MRVL_CMD<cmd> */
|
|
strncpy((char *)buffer, CMD_NXP, strlen(CMD_NXP));
|
|
strncpy((char *)buffer + strlen(CMD_NXP), HOSTCMD, strlen(HOSTCMD));
|
|
|
|
/* buffer = MRVL_CMD<cmd><hostcmd_size><HostCmd_DS_GEN><CMD_DS> */
|
|
hostcmd = (HostCmd_DS_GEN *)(buffer + cmd_header_len + sizeof(t_u32));
|
|
|
|
/* Point after host command header */
|
|
pos = (t_u8 *)hostcmd + S_DS_GEN;
|
|
|
|
cmd_len = S_DS_GEN + sizeof(HostCmd_DS_CMD_ROAMAGENT_CONTROL);
|
|
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_ROAMAGENT_CONTROL);
|
|
hostcmd->size = cpu_to_le16(cmd_len);
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
roamcontrolcmd = (HostCmd_DS_CMD_ROAMAGENT_CONTROL *)pos;
|
|
|
|
/* get current value */
|
|
if (getControl(roamcontrolcmd) != MLAN_STATUS_SUCCESS) {
|
|
ret = MLAN_STATUS_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
roamcontrolcmd->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
|
|
switch (setreset) {
|
|
case 0:
|
|
roamcontrolcmd->Control &= value;
|
|
break;
|
|
case 1:
|
|
roamcontrolcmd->Control |= value;
|
|
break;
|
|
case 2:
|
|
roamcontrolcmd->HostEvent &= value;
|
|
break;
|
|
case 3:
|
|
roamcontrolcmd->HostEvent |= value;
|
|
break;
|
|
}
|
|
|
|
/* Put buffer length */
|
|
memcpy(buffer + cmd_header_len, &cmd_len, sizeof(t_u32));
|
|
|
|
/* Initialize the ifr structure */
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
strncpy(ifr.ifr_ifrn.ifrn_name, dev_name, strlen(dev_name));
|
|
ifr.ifr_ifru.ifru_data = (void *)cmd;
|
|
/* Perform ioctl */
|
|
if (ioctl(sockfd, MLAN_ETH_PRIV, &ifr)) {
|
|
perror("ioctl[roamcontrol]");
|
|
printf("ERR:Command sending failed!\n");
|
|
ret = -EFAULT;
|
|
goto done;
|
|
}
|
|
|
|
if (le16_to_cpu(hostcmd->result)) {
|
|
printf("\nHostCmd Error: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
} else {
|
|
printf("\nHostCmd Success: ReturnCode=%#04x, Result=%#04x\n\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
}
|
|
|
|
done:
|
|
if (buffer)
|
|
free(buffer);
|
|
if (cmd)
|
|
free(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra enable command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetEnableControl(int argc, char *argv[])
|
|
{
|
|
return roamSetControl(argc, argv, 1, ROAM_CONTROL_ENABLE);
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra disable command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetDisableControl(int argc, char *argv[])
|
|
{
|
|
return roamSetControl(argc, argv, 0, ROAM_CONTROL_DISABLE);
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra suspend command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetSuspendControl(int argc, char *argv[])
|
|
{
|
|
return roamSetControl(argc, argv, 1, ROAM_CONTROL_SUSPEND);
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra resume command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetResumeControl(int argc, char *argv[])
|
|
{
|
|
return roamSetControl(argc, argv, 0, ROAM_CONTROL_RESUME);
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra crossband command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to argument array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetCrossband(int argc, char *argv[])
|
|
{
|
|
if (argc != 1) {
|
|
printf("Invalid Usage \n");
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
if (strncmp(argv[0], "enable", strlen("enable")) == 0) {
|
|
return roamSetControl(argc, argv, 1, CROSSBAND_ENABLE);
|
|
} else if (strncmp(argv[0], "disable", strlen("disable")) == 0) {
|
|
return roamSetControl(argc, argv, 0, CROSSBAND_DISABLE);
|
|
}
|
|
|
|
printf("Invalid Usage \n");
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue setra event command
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to argument array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
static int
|
|
roamSetEventBitmap(int argc, char *argv[])
|
|
{
|
|
int i, enableFlag, found = 0;
|
|
t_u8 value;
|
|
if (argc > 4 || argc < 2) {
|
|
printf("Invalid Usage \n");
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
if (strncmp(argv[0], "enable", strlen("enable")) == 0) {
|
|
enableFlag = 3;
|
|
value = HOST_EVENT_NBOR_DISABLE & HOST_EVENT_ROAM_DISABLE
|
|
& HOST_EVENT_STATE_DISABLE;
|
|
} else if (strncmp(argv[0], "disable", strlen("disable")) == 0) {
|
|
enableFlag = 2;
|
|
value = HOST_EVENT_NBOR_ENABLE | HOST_EVENT_ROAM_ENABLE
|
|
| HOST_EVENT_STATE_ENABLE;
|
|
} else {
|
|
printf("Invalid parameter %s \n", argv[0]);
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
found = 0;
|
|
if (strncmp(argv[i], "neighbor", strlen("neighbor")) == 0) {
|
|
found = 1;
|
|
if (enableFlag == 3) {
|
|
value |= HOST_EVENT_NBOR_ENABLE;
|
|
} else {
|
|
value &= HOST_EVENT_NBOR_DISABLE;
|
|
}
|
|
}
|
|
if (strncmp(argv[i], "roam", strlen("roam")) == 0) {
|
|
found = 1;
|
|
if (enableFlag == 3) {
|
|
value |= HOST_EVENT_ROAM_ENABLE;
|
|
} else {
|
|
value &= HOST_EVENT_ROAM_DISABLE;
|
|
}
|
|
}
|
|
if (strncmp(argv[i], "state", strlen("state")) == 0) {
|
|
found = 1;
|
|
if (enableFlag == 3) {
|
|
value |= HOST_EVENT_STATE_ENABLE;
|
|
} else {
|
|
value &= HOST_EVENT_STATE_DISABLE;
|
|
}
|
|
}
|
|
if (found == 0) {
|
|
printf("Invalid parameter %s \n", argv[i]);
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
}
|
|
|
|
return roamSetControl(argc, argv, enableFlag, value);
|
|
}
|
|
|
|
/**
|
|
* @brief Set the Roaming agent configuration parameters to FW.
|
|
*
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
process_set_ra_config(int argc, char *argv[])
|
|
{
|
|
sub_cmd_exec_t subCmds[] = {
|
|
{"rssi", 2, 1, roamSetRssiStatsThreshold},
|
|
{"prebcnmiss", 2, 1, roamSetPreBeaconLoss},
|
|
{"failcnt", 2, 1, roamSetFailureCount},
|
|
{"neighbor", 2, 0, printSetNeighborDeprecation},
|
|
{"nparams", 2, 1, roamSetNborParams},
|
|
{"maintain", 2, 1, roamSetNborMaintenance},
|
|
{"scanperiod", 2, 1, roamSetScanPeriod},
|
|
{"backoff", 2, 1, roamSetBackOff},
|
|
{"enable", 2, 1, roamSetEnableControl},
|
|
{"disable", 2, 1, roamSetDisableControl},
|
|
{"suspend", 2, 1, roamSetSuspendControl},
|
|
{"resume", 2, 1, roamSetResumeControl},
|
|
{"metrics", 2, 1, roamSetMetrics},
|
|
{"crossband", 2, 1, roamSetCrossband},
|
|
{"event", 2, 1, roamSetEventBitmap}
|
|
};
|
|
|
|
return process_sub_cmd(subCmds, NELEMENTS(subCmds), argc, argv);
|
|
}
|