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>
900 lines
24 KiB
C
900 lines
24 KiB
C
/** @file mlanhostcmd.c
|
|
*
|
|
* @brief This file contains mlanutl helper functions
|
|
*
|
|
*
|
|
* 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:
|
|
11/26/2008: initial version
|
|
************************************************************************/
|
|
|
|
#include "mlanhostcmd.h"
|
|
|
|
#ifndef MIN
|
|
/** Find minimum value */
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#endif /* MIN */
|
|
|
|
/********************************************************
|
|
Local Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Global Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Local Functions
|
|
********************************************************/
|
|
/**
|
|
* @brief get hostcmd data
|
|
*
|
|
* @param ln A pointer to line number
|
|
* @param buf A pointer to hostcmd data
|
|
* @param size A pointer to the return size of hostcmd buffer
|
|
* @return MLAN_STATUS_SUCCESS
|
|
*/
|
|
static int
|
|
mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
|
|
{
|
|
t_s32 errors = 0, i;
|
|
t_s8 line[512], *pos, *pos1, *pos2, *pos3;
|
|
t_u16 len;
|
|
|
|
while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
|
|
(*ln)++;
|
|
if (strcmp(pos, "}") == 0) {
|
|
break;
|
|
}
|
|
|
|
pos1 = strchr(pos, ':');
|
|
if (pos1 == NULL) {
|
|
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
|
|
pos);
|
|
errors++;
|
|
continue;
|
|
}
|
|
*pos1++ = '\0';
|
|
|
|
pos2 = strchr(pos1, '=');
|
|
if (pos2 == NULL) {
|
|
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
|
|
pos);
|
|
errors++;
|
|
continue;
|
|
}
|
|
*pos2++ = '\0';
|
|
|
|
len = a2hex_or_atoi(pos1);
|
|
if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
|
|
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
|
|
pos);
|
|
errors++;
|
|
continue;
|
|
}
|
|
|
|
*size += len;
|
|
|
|
if (*pos2 == '"') {
|
|
pos2++;
|
|
pos3 = strchr(pos2, '"');
|
|
if (pos3 == NULL) {
|
|
printf("Line %d: invalid quotation '%s'\n", *ln,
|
|
pos);
|
|
errors++;
|
|
continue;
|
|
}
|
|
*pos3 = '\0';
|
|
memset(buf, 0, len);
|
|
memmove(buf, pos2, MIN(strlen(pos2), len));
|
|
buf += len;
|
|
} else if (*pos2 == '\'') {
|
|
pos2++;
|
|
pos3 = strchr(pos2, '\'');
|
|
if (pos3 == NULL) {
|
|
printf("Line %d: invalid quotation '%s'\n", *ln,
|
|
pos);
|
|
errors++;
|
|
continue;
|
|
}
|
|
*pos3 = ',';
|
|
for (i = 0; i < len; i++) {
|
|
pos3 = strchr(pos2, ',');
|
|
if (pos3 != NULL) {
|
|
*pos3 = '\0';
|
|
*buf++ = (t_u8)a2hex_or_atoi(pos2);
|
|
pos2 = pos3 + 1;
|
|
} else
|
|
*buf++ = 0;
|
|
}
|
|
} else if (*pos2 == '{') {
|
|
t_u16 tlvlen = 0, tmp_tlvlen;
|
|
mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
|
|
tmp_tlvlen = tlvlen;
|
|
while (len--) {
|
|
*buf++ = (t_u8)(tmp_tlvlen & 0xff);
|
|
tmp_tlvlen >>= 8;
|
|
}
|
|
*size += tlvlen;
|
|
buf += tlvlen;
|
|
} else {
|
|
t_u32 value = a2hex_or_atoi(pos2);
|
|
while (len--) {
|
|
*buf++ = (t_u8)(value & 0xff);
|
|
value >>= 8;
|
|
}
|
|
}
|
|
}
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/********************************************************
|
|
Global Functions
|
|
********************************************************/
|
|
/**
|
|
* @brief convert char to hex integer
|
|
*
|
|
* @param chr char to convert
|
|
* @return hex integer or 0
|
|
*/
|
|
int
|
|
hexval(t_s32 chr)
|
|
{
|
|
if (chr >= '0' && chr <= '9')
|
|
return chr - '0';
|
|
if (chr >= 'A' && chr <= 'F')
|
|
return chr - 'A' + 10;
|
|
if (chr >= 'a' && chr <= 'f')
|
|
return chr - 'a' + 10;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Hump hex data
|
|
*
|
|
* @param prompt A pointer prompt buffer
|
|
* @param p A pointer to data buffer
|
|
* @param len the len of data buffer
|
|
* @param delim delim char
|
|
* @return hex integer
|
|
*/
|
|
t_void
|
|
hexdump(t_s8 *prompt, t_void *p, t_s32 len, t_s8 delim)
|
|
{
|
|
t_s32 i;
|
|
t_u8 *s = p;
|
|
|
|
if (prompt) {
|
|
printf("%s: len=%d\n", prompt, (int)len);
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
if (i != len - 1)
|
|
printf("%02x%c", *s++, delim);
|
|
else
|
|
printf("%02x\n", *s);
|
|
if ((i + 1) % 16 == 0)
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/**
|
|
* @brief convert char to hex integer
|
|
*
|
|
* @param chr char
|
|
* @return hex integer
|
|
*/
|
|
t_u8
|
|
hexc2bin(t_s8 chr)
|
|
{
|
|
if (chr >= '0' && chr <= '9')
|
|
chr -= '0';
|
|
else if (chr >= 'A' && chr <= 'F')
|
|
chr -= ('A' - 10);
|
|
else if (chr >= 'a' && chr <= 'f')
|
|
chr -= ('a' - 10);
|
|
|
|
return chr;
|
|
}
|
|
|
|
/**
|
|
* @brief convert string to hex integer
|
|
*
|
|
* @param s A pointer string buffer
|
|
* @return hex integer
|
|
*/
|
|
t_u32
|
|
a2hex(t_s8 *s)
|
|
{
|
|
t_u32 val = 0;
|
|
|
|
if (!strncasecmp("0x", s, 2)) {
|
|
s += 2;
|
|
}
|
|
|
|
while (*s && isxdigit(*s)) {
|
|
val = (val << 4) + hexc2bin(*s++);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
/*
|
|
* @brief convert String to integer
|
|
*
|
|
* @param value A pointer to string
|
|
* @return integer
|
|
*/
|
|
t_u32
|
|
a2hex_or_atoi(t_s8 *value)
|
|
{
|
|
if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
|
|
return a2hex(value + 2);
|
|
} else if (isdigit(*value)) {
|
|
return atoi(value);
|
|
} else {
|
|
return *value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief convert string to hex
|
|
*
|
|
* @param ptr A pointer to data buffer
|
|
* @param chr A pointer to return integer
|
|
* @return A pointer to next data field
|
|
*/
|
|
t_s8 *
|
|
convert2hex(t_s8 *ptr, t_u8 *chr)
|
|
{
|
|
t_u8 val;
|
|
|
|
for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
|
|
val = (val * 16) + hexval(*ptr);
|
|
}
|
|
|
|
*chr = val;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
/**
|
|
* @brief Check the Hex String
|
|
* @param s A pointer to the string
|
|
* @return MLAN_STATUS_SUCCESS --HexString, MLAN_STATUS_FAILURE --not HexString
|
|
*/
|
|
int
|
|
ishexstring(t_s8 *s)
|
|
{
|
|
int ret = MLAN_STATUS_FAILURE;
|
|
t_s32 tmp;
|
|
|
|
if (!strncasecmp("0x", s, 2)) {
|
|
s += 2;
|
|
}
|
|
while (*s) {
|
|
tmp = toupper(*s);
|
|
if (((tmp >= 'A') && (tmp <= 'F')) ||
|
|
((tmp >= '0') && (tmp <= '9'))) {
|
|
ret = MLAN_STATUS_SUCCESS;
|
|
} else {
|
|
ret = MLAN_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
s++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert String to Integer
|
|
* @param buf A pointer to the string
|
|
* @return Integer
|
|
*/
|
|
int
|
|
atoval(t_s8 *buf)
|
|
{
|
|
if (!strncasecmp(buf, "0x", 2))
|
|
return a2hex(buf + 2);
|
|
else if (!ishexstring(buf))
|
|
return a2hex(buf);
|
|
else
|
|
return atoi(buf);
|
|
}
|
|
|
|
/**
|
|
* @brief Prepare host-command buffer
|
|
* @param fp File handler
|
|
* @param cmd_name Command name
|
|
* @param buf A pointer to comand buffer
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
prepare_host_cmd_buffer(FILE * fp, char *cmd_name, t_u8 *buf)
|
|
{
|
|
t_s8 line[256], cmdname[256], *pos, cmdcode[10];
|
|
HostCmd_DS_GEN *hostcmd;
|
|
int ln = 0;
|
|
int cmdname_found = 0, cmdcode_found = 0;
|
|
|
|
memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
hostcmd = (HostCmd_DS_GEN *)buf;
|
|
hostcmd->command = 0xffff;
|
|
|
|
snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
|
|
cmdname_found = 0;
|
|
while ((pos = mlan_config_get_line(fp, line, sizeof(line), &ln))) {
|
|
if (strcmp(pos, cmdname) == 0) {
|
|
t_u16 len = 0;
|
|
cmdname_found = 1;
|
|
snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
|
|
cmdcode_found = 0;
|
|
while ((pos =
|
|
mlan_config_get_line(fp, line, sizeof(line),
|
|
&ln))) {
|
|
if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
|
|
cmdcode_found = 1;
|
|
hostcmd->command =
|
|
a2hex_or_atoi(pos +
|
|
strlen(cmdcode));
|
|
hostcmd->size = S_DS_GEN;
|
|
mlan_get_hostcmd_data(fp, &ln,
|
|
buf +
|
|
hostcmd->size,
|
|
&len);
|
|
hostcmd->size += len;
|
|
break;
|
|
}
|
|
}
|
|
if (!cmdcode_found) {
|
|
fprintf(stderr,
|
|
"mlanutl: CmdCode not found in conf file\n");
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!cmdname_found) {
|
|
fprintf(stderr,
|
|
"mlanutl: cmdname '%s' is not found in conf file\n",
|
|
cmd_name);
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
hostcmd->command = cpu_to_le16(hostcmd->command);
|
|
hostcmd->size = cpu_to_le16(hostcmd->size);
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/** Config data header length */
|
|
#define CFG_DATA_HEADER_LEN 6
|
|
|
|
/**
|
|
* @brief Prepare cfg-data buffer
|
|
* @param argc number of arguments
|
|
* @param argv A pointer to arguments array
|
|
* @param fp File handler
|
|
* @param buf A pointer to comand buffer
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
prepare_cfg_data_buffer(int argc, char *argv[], FILE * fp, t_u8 *buf)
|
|
{
|
|
int ln = 0, type;
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_802_11_CFG_DATA *pcfg_data;
|
|
|
|
memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
|
|
hostcmd = (HostCmd_DS_GEN *)buf;
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA);
|
|
pcfg_data = (HostCmd_DS_802_11_CFG_DATA *)(buf + S_DS_GEN);
|
|
pcfg_data->action =
|
|
(argc == 4) ? HostCmd_ACT_GEN_GET : HostCmd_ACT_GEN_SET;
|
|
type = atoi(argv[3]);
|
|
if ((type < 1) || (type > 2)) {
|
|
fprintf(stderr, "mlanutl: Invalid register type\n");
|
|
return MLAN_STATUS_FAILURE;
|
|
} else {
|
|
pcfg_data->type = type;
|
|
}
|
|
if (argc == 5) {
|
|
ln = fparse_for_hex(fp, pcfg_data->data);
|
|
}
|
|
pcfg_data->data_len = ln;
|
|
hostcmd->size =
|
|
cpu_to_le16(pcfg_data->data_len + S_DS_GEN +
|
|
CFG_DATA_HEADER_LEN);
|
|
pcfg_data->data_len = cpu_to_le16(pcfg_data->data_len);
|
|
pcfg_data->type = cpu_to_le16(pcfg_data->type);
|
|
pcfg_data->action = cpu_to_le16(pcfg_data->action);
|
|
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Process host_cmd response
|
|
* @param buf A pointer to the response buffer
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
process_host_cmd_resp(t_u8 *buf)
|
|
{
|
|
HostCmd_DS_GEN *hostcmd = (HostCmd_DS_GEN *)buf;
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
|
|
hostcmd->command = le16_to_cpu(hostcmd->command);
|
|
hostcmd->size = le16_to_cpu(hostcmd->size);
|
|
hostcmd->seq_num = le16_to_cpu(hostcmd->seq_num);
|
|
hostcmd->result = le16_to_cpu(hostcmd->result);
|
|
|
|
hostcmd->command &= ~HostCmd_RET_BIT;
|
|
if (!hostcmd->result) {
|
|
switch (hostcmd->command) {
|
|
case HostCmd_CMD_CFG_DATA:
|
|
{
|
|
HostCmd_DS_802_11_CFG_DATA *pstcfgData =
|
|
(HostCmd_DS_802_11_CFG_DATA *)(buf +
|
|
S_DS_GEN);
|
|
pstcfgData->data_len =
|
|
le16_to_cpu(pstcfgData->data_len);
|
|
pstcfgData->action =
|
|
le16_to_cpu(pstcfgData->action);
|
|
|
|
if (pstcfgData->action == HostCmd_ACT_GEN_GET) {
|
|
hexdump("cfgdata", pstcfgData->data,
|
|
pstcfgData->data_len, ' ');
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
|
|
{
|
|
mlan_ioctl_11h_tpc_resp *tpcIoctlResp =
|
|
(mlan_ioctl_11h_tpc_resp *)(buf +
|
|
S_DS_GEN);
|
|
if (tpcIoctlResp->status_code == 0) {
|
|
printf("tpcrequest: txPower(%d), linkMargin(%d), rssi(%d)\n", tpcIoctlResp->tx_power, tpcIoctlResp->link_margin, tpcIoctlResp->rssi);
|
|
} else {
|
|
printf("tpcrequest: failure, status = %d\n", tpcIoctlResp->status_code);
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_802_11_CRYPTO:
|
|
{
|
|
t_u16 alg =
|
|
le16_to_cpu((t_u16)
|
|
*(buf + S_DS_GEN +
|
|
sizeof(t_u16)));
|
|
if (alg != CIPHER_TEST_AES_CCM &&
|
|
alg != CIPHER_TEST_GCMP) {
|
|
HostCmd_DS_802_11_CRYPTO *cmd =
|
|
(HostCmd_DS_802_11_CRYPTO *)(buf
|
|
+
|
|
S_DS_GEN);
|
|
cmd->encdec = le16_to_cpu(cmd->encdec);
|
|
cmd->algorithm =
|
|
le16_to_cpu(cmd->algorithm);
|
|
cmd->key_IV_length =
|
|
le16_to_cpu(cmd->key_IV_length);
|
|
cmd->key_length =
|
|
le16_to_cpu(cmd->key_length);
|
|
cmd->data.header.type =
|
|
le16_to_cpu(cmd->data.header.
|
|
type);
|
|
cmd->data.header.len =
|
|
le16_to_cpu(cmd->data.header.
|
|
len);
|
|
|
|
printf("crypto_result: encdec=%d algorithm=%d,KeyIVLen=%d," " KeyLen=%d,dataLen=%d\n", cmd->encdec, cmd->algorithm, cmd->key_IV_length, cmd->key_length, cmd->data.header.len);
|
|
hexdump("KeyIV", cmd->keyIV,
|
|
cmd->key_IV_length, ' ');
|
|
hexdump("Key", cmd->key,
|
|
cmd->key_length, ' ');
|
|
hexdump("Data", cmd->data.data,
|
|
cmd->data.header.len, ' ');
|
|
} else {
|
|
HostCmd_DS_802_11_CRYPTO_AES_CCM
|
|
*cmd_aes_ccm =
|
|
(HostCmd_DS_802_11_CRYPTO_AES_CCM
|
|
*)(buf + S_DS_GEN);
|
|
|
|
cmd_aes_ccm->encdec
|
|
=
|
|
le16_to_cpu(cmd_aes_ccm->
|
|
encdec);
|
|
cmd_aes_ccm->algorithm =
|
|
le16_to_cpu(cmd_aes_ccm->
|
|
algorithm);
|
|
cmd_aes_ccm->key_length =
|
|
le16_to_cpu(cmd_aes_ccm->
|
|
key_length);
|
|
cmd_aes_ccm->nonce_length =
|
|
le16_to_cpu(cmd_aes_ccm->
|
|
nonce_length);
|
|
cmd_aes_ccm->AAD_length =
|
|
le16_to_cpu(cmd_aes_ccm->
|
|
AAD_length);
|
|
cmd_aes_ccm->data.header.type =
|
|
le16_to_cpu(cmd_aes_ccm->data.
|
|
header.type);
|
|
cmd_aes_ccm->data.header.len =
|
|
le16_to_cpu(cmd_aes_ccm->data.
|
|
header.len);
|
|
|
|
printf("crypto_result: encdec=%d algorithm=%d, KeyLen=%d," " NonceLen=%d,AADLen=%d,dataLen=%d\n", cmd_aes_ccm->encdec, cmd_aes_ccm->algorithm, cmd_aes_ccm->key_length, cmd_aes_ccm->nonce_length, cmd_aes_ccm->AAD_length, cmd_aes_ccm->data.header.len);
|
|
|
|
hexdump("Key", cmd_aes_ccm->key,
|
|
cmd_aes_ccm->key_length, ' ');
|
|
hexdump("Nonce", cmd_aes_ccm->nonce,
|
|
cmd_aes_ccm->nonce_length, ' ');
|
|
hexdump("AAD", cmd_aes_ccm->AAD,
|
|
cmd_aes_ccm->AAD_length, ' ');
|
|
hexdump("Data", cmd_aes_ccm->data.data,
|
|
cmd_aes_ccm->data.header.len,
|
|
' ');
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_802_11_AUTO_TX:
|
|
{
|
|
HostCmd_DS_802_11_AUTO_TX *at =
|
|
(HostCmd_DS_802_11_AUTO_TX *)(buf +
|
|
S_DS_GEN);
|
|
|
|
if (le16_to_cpu(at->action) ==
|
|
HostCmd_ACT_GEN_GET) {
|
|
if (S_DS_GEN + sizeof(at->action) ==
|
|
hostcmd->size) {
|
|
printf("auto_tx not configured\n");
|
|
|
|
} else {
|
|
MrvlIEtypesHeader_t *header =
|
|
&at->auto_tx.header;
|
|
|
|
header->type =
|
|
le16_to_cpu(header->
|
|
type);
|
|
header->len =
|
|
le16_to_cpu(header->
|
|
len);
|
|
|
|
if ((S_DS_GEN +
|
|
sizeof(at->action)
|
|
+
|
|
sizeof(MrvlIEtypesHeader_t)
|
|
+ header->len ==
|
|
hostcmd->size) &&
|
|
(header->type ==
|
|
TLV_TYPE_AUTO_TX)) {
|
|
|
|
AutoTx_MacFrame_t *atmf
|
|
=
|
|
&at->auto_tx.
|
|
auto_tx_mac_frame;
|
|
|
|
printf("Interval: %d second(s)\n", le16_to_cpu(atmf->interval));
|
|
printf("Priority: %#x\n", atmf->priority);
|
|
printf("Frame Length: %d\n", le16_to_cpu(atmf->frame_len));
|
|
printf("Dest Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->dest_mac_addr[0], atmf->dest_mac_addr[1], atmf->dest_mac_addr[2], atmf->dest_mac_addr[3], atmf->dest_mac_addr[4], atmf->dest_mac_addr[5]);
|
|
printf("Src Mac Address: " "%02x:%02x:%02x:%02x:%02x:%02x\n", atmf->src_mac_addr[0], atmf->src_mac_addr[1], atmf->src_mac_addr[2], atmf->src_mac_addr[3], atmf->src_mac_addr[4], atmf->src_mac_addr[5]);
|
|
|
|
hexdump("Frame Payload",
|
|
atmf->payload,
|
|
le16_to_cpu
|
|
(atmf->
|
|
frame_len)
|
|
-
|
|
MLAN_MAC_ADDR_LENGTH
|
|
* 2, ' ');
|
|
} else {
|
|
printf("incorrect auto_tx command response\n");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
|
|
{
|
|
HostCmd_DS_802_11_SUBSCRIBE_EVENT *se =
|
|
(HostCmd_DS_802_11_SUBSCRIBE_EVENT
|
|
*)(buf + S_DS_GEN);
|
|
if (le16_to_cpu(se->action) ==
|
|
HostCmd_ACT_GEN_GET) {
|
|
int len =
|
|
S_DS_GEN +
|
|
sizeof
|
|
(HostCmd_DS_802_11_SUBSCRIBE_EVENT);
|
|
printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
|
|
while (len < hostcmd->size) {
|
|
MrvlIEtypesHeader_t *header =
|
|
(MrvlIEtypesHeader_t
|
|
*)(buf + len);
|
|
switch (le16_to_cpu
|
|
(header->type)) {
|
|
case TLV_TYPE_RSSI_LOW:
|
|
{
|
|
MrvlIEtypes_RssiThreshold_t
|
|
*low_rssi
|
|
=
|
|
(MrvlIEtypes_RssiThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Beacon Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0001) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_SNR_LOW:
|
|
{
|
|
MrvlIEtypes_SnrThreshold_t
|
|
*low_snr
|
|
=
|
|
(MrvlIEtypes_SnrThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Beacon Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0002) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_FAILCOUNT:
|
|
{
|
|
MrvlIEtypes_FailureCount_t
|
|
*failure_count
|
|
=
|
|
(MrvlIEtypes_FailureCount_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Failure Count\t%d\t%d\t%s\n", failure_count->fail_value, failure_count->fail_freq, (le16_to_cpu(se->events) & 0x0004) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_BCNMISS:
|
|
{
|
|
MrvlIEtypes_BeaconsMissed_t
|
|
*bcn_missed
|
|
=
|
|
(MrvlIEtypes_BeaconsMissed_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Beacon Missed\t%d\tN/A\t%s\n", bcn_missed->beacon_missed, (le16_to_cpu(se->events) & 0x0008) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_RSSI_HIGH:
|
|
{
|
|
MrvlIEtypes_RssiThreshold_t
|
|
*high_rssi
|
|
=
|
|
(MrvlIEtypes_RssiThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Bcn High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0010) ? "yes" : "no");
|
|
break;
|
|
}
|
|
|
|
case TLV_TYPE_SNR_HIGH:
|
|
{
|
|
MrvlIEtypes_SnrThreshold_t
|
|
*high_snr
|
|
=
|
|
(MrvlIEtypes_SnrThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Beacon High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0020) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_RSSI_LOW_DATA:
|
|
{
|
|
MrvlIEtypes_RssiThreshold_t
|
|
*low_rssi
|
|
=
|
|
(MrvlIEtypes_RssiThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Data Low RSSI\t%d\t%d\t%s\n", low_rssi->RSSI_value, low_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0040) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_SNR_LOW_DATA:
|
|
{
|
|
MrvlIEtypes_SnrThreshold_t
|
|
*low_snr
|
|
=
|
|
(MrvlIEtypes_SnrThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Data Low SNR\t%d\t%d\t%s\n", low_snr->SNR_value, low_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0080) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_RSSI_HIGH_DATA:
|
|
{
|
|
MrvlIEtypes_RssiThreshold_t
|
|
*high_rssi
|
|
=
|
|
(MrvlIEtypes_RssiThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Data High RSSI\t%d\t%d\t%s\n", high_rssi->RSSI_value, high_rssi->RSSI_freq, (le16_to_cpu(se->events) & 0x0100) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_SNR_HIGH_DATA:
|
|
{
|
|
MrvlIEtypes_SnrThreshold_t
|
|
*high_snr
|
|
=
|
|
(MrvlIEtypes_SnrThreshold_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Data High SNR\t%d\t%d\t%s\n", high_snr->SNR_value, high_snr->SNR_freq, (le16_to_cpu(se->events) & 0x0200) ? "yes" : "no");
|
|
break;
|
|
}
|
|
case TLV_TYPE_LINK_QUALITY:
|
|
{
|
|
MrvlIEtypes_LinkQuality_t
|
|
*link_qual
|
|
=
|
|
(MrvlIEtypes_LinkQuality_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("Link Quality Parameters:\n");
|
|
printf("------------------------\n");
|
|
printf("Link Quality Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0400) ? "yes" : "no");
|
|
printf("Link SNR Threshold = %d\n", le16_to_cpu(link_qual->link_SNR_thrs));
|
|
printf("Link SNR Frequency = %d\n", le16_to_cpu(link_qual->link_SNR_freq));
|
|
printf("Min Rate Value = %d\n", le16_to_cpu(link_qual->min_rate_val));
|
|
printf("Min Rate Frequency = %d\n", le16_to_cpu(link_qual->min_rate_freq));
|
|
printf("Tx Latency Value = %d\n", le32_to_cpu(link_qual->tx_latency_val));
|
|
printf("Tx Latency Threshold = %d\n", le32_to_cpu(link_qual->tx_latency_thrs));
|
|
|
|
break;
|
|
}
|
|
case TLV_TYPE_PRE_BEACON_LOST:
|
|
{
|
|
MrvlIEtypes_PreBeaconLost_t
|
|
*pre_bcn_lost
|
|
=
|
|
(MrvlIEtypes_PreBeaconLost_t
|
|
*)(buf
|
|
+
|
|
len);
|
|
printf("------------------------\n");
|
|
printf("Pre-Beacon Lost Event Subscribed\t%s\n", (le16_to_cpu(se->events) & 0x0800) ? "yes" : "no");
|
|
printf("Pre-Beacon Lost: %d\n", pre_bcn_lost->pre_beacon_lost);
|
|
break;
|
|
}
|
|
default:
|
|
printf("Unknown subscribed event TLV Type=%#x," " Len=%d\n", le16_to_cpu(header->type), le16_to_cpu(header->len));
|
|
break;
|
|
}
|
|
|
|
len += (sizeof
|
|
(MrvlIEtypesHeader_t)
|
|
+
|
|
le16_to_cpu(header->
|
|
len));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_MAC_REG_ACCESS:
|
|
case HostCmd_CMD_BBP_REG_ACCESS:
|
|
case HostCmd_CMD_RF_REG_ACCESS:
|
|
case HostCmd_CMD_CAU_REG_ACCESS:
|
|
{
|
|
HostCmd_DS_REG *preg =
|
|
(HostCmd_DS_REG *)(buf + S_DS_GEN);
|
|
preg->action = le16_to_cpu(preg->action);
|
|
if (preg->action == HostCmd_ACT_GEN_GET) {
|
|
preg->value = le32_to_cpu(preg->value);
|
|
printf("value = 0x%08x\n", preg->value);
|
|
}
|
|
break;
|
|
}
|
|
case HostCmd_CMD_MEM_ACCESS:
|
|
{
|
|
HostCmd_DS_MEM *pmem =
|
|
(HostCmd_DS_MEM *)(buf + S_DS_GEN);
|
|
pmem->action = le16_to_cpu(pmem->action);
|
|
if (pmem->action == HostCmd_ACT_GEN_GET) {
|
|
pmem->value = le32_to_cpu(pmem->value);
|
|
printf("value = 0x%08x\n", pmem->value);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
printf("HOSTCMD_RESP: CmdCode=%#04x, Size=%#04x,"
|
|
" SeqNum=%#04x, Result=%#04x\n",
|
|
hostcmd->command, hostcmd->size,
|
|
hostcmd->seq_num, hostcmd->result);
|
|
hexdump("payload",
|
|
(t_void *)(buf + S_DS_GEN),
|
|
hostcmd->size - S_DS_GEN, ' ');
|
|
break;
|
|
}
|
|
} else {
|
|
printf("HOSTCMD failed: CmdCode=%#04x, Size=%#04x,"
|
|
" SeqNum=%#04x, Result=%#04x\n",
|
|
hostcmd->command, hostcmd->size,
|
|
hostcmd->seq_num, hostcmd->result);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Prepare the hostcmd for register access
|
|
* @param type Register type
|
|
* @param offset Register offset
|
|
* @param value Pointer to value (NULL for read)
|
|
* @param buf Pointer to hostcmd buffer
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
prepare_hostcmd_regrdwr(t_u32 type, t_u32 offset, t_u32 *value, t_u8 *buf)
|
|
{
|
|
HostCmd_DS_GEN *hostcmd;
|
|
HostCmd_DS_REG *preg;
|
|
|
|
hostcmd = (HostCmd_DS_GEN *)buf;
|
|
switch (type) {
|
|
case 1:
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_MAC_REG_ACCESS);
|
|
break;
|
|
case 2:
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_BBP_REG_ACCESS);
|
|
break;
|
|
case 3:
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_RF_REG_ACCESS);
|
|
break;
|
|
case 5:
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_CAU_REG_ACCESS);
|
|
break;
|
|
default:
|
|
printf("Invalid register set specified\n");
|
|
return -EINVAL;
|
|
}
|
|
preg = (HostCmd_DS_REG *)(buf + S_DS_GEN);
|
|
preg->action = (value) ? HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET;
|
|
preg->action = cpu_to_le16(preg->action);
|
|
preg->offset = cpu_to_le16((t_u16)offset);
|
|
if (value)
|
|
preg->value = cpu_to_le32(*value);
|
|
else
|
|
preg->value = 0;
|
|
hostcmd->size = cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_REG));
|
|
hostcmd->seq_num = 0;
|
|
hostcmd->result = 0;
|
|
|
|
return MLAN_STATUS_SUCCESS;
|
|
}
|