mirror of
https://github.com/nxp-imx/mwifiex.git
synced 2024-11-20 09:01:44 +00:00
bd8827d169
The sdk release is from NXP offial web: https://www.nxp.com/products/wireless/wi-fi-plus-bluetooth/ 88w8997-wi-fi-dual-band-with-bluetooth-5-for-a-v-streaming-and-digital-tv:88W8997?tab=Design_Tools_Tab The release file is: PCIE-WLAN-UART-BT-8997-U16-X86-W16.68.10.p16-16.26.10.p16-C4X16640_V4-MGPL The sdk version is: W16.68.10.p16 Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
280 lines
8.9 KiB
C
Executable file
280 lines
8.9 KiB
C
Executable file
/** @file mlan2040misc.c
|
|
*
|
|
* @brief This file contains helper functions for coex application
|
|
*
|
|
* Copyright (C) 2009-2019, Marvell International Ltd.
|
|
*
|
|
* This software file (the "File") is distributed by Marvell International
|
|
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
|
* (the "License"). You may use, redistribute and/or modify this File in
|
|
* accordance with the terms and conditions of the License, a copy of which
|
|
* is available by writing to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
|
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
|
*
|
|
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
|
* this warranty disclaimer.
|
|
*
|
|
*/
|
|
/************************************************************************
|
|
Change log:
|
|
06/24/2009: initial version
|
|
************************************************************************/
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "mlan2040coex.h"
|
|
#include "mlan2040misc.h"
|
|
|
|
/********************************************************
|
|
Local Variables
|
|
********************************************************/
|
|
/** Regulatory class and Channel mapping for various regions */
|
|
static class_chan_t us_class_chan_t[] = {
|
|
{32, {1, 2, 3, 4, 5, 6, 7}, 7},
|
|
{33, {5, 6, 7, 8, 9, 10, 11}, 7}
|
|
};
|
|
|
|
static class_chan_t europe_class_chan_t[] = {
|
|
{11, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9},
|
|
{12, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9}
|
|
};
|
|
|
|
static class_chan_t japan_class_chan_t[] = {
|
|
{56, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 9},
|
|
{57, {5, 6, 7, 8, 9, 10, 11, 12, 13}, 9},
|
|
{58, {14}, 1}
|
|
};
|
|
|
|
/** Region-code(Regulatory domain) and Class-channel table mapping */
|
|
static region_class_chan_t region_class_chan_table[] = {
|
|
{0x10, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)} /* US */
|
|
,
|
|
{0x20, us_class_chan_t, sizeof(us_class_chan_t) / sizeof(class_chan_t)} /* CANADA */
|
|
,
|
|
{0x30, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* EUROPE */
|
|
,
|
|
{0x32, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* FRANCE */
|
|
,
|
|
{0x40, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)} /* JAPAN */
|
|
,
|
|
{0x41, japan_class_chan_t, sizeof(japan_class_chan_t) / sizeof(class_chan_t)} /* JAPAN */
|
|
,
|
|
{0x50, europe_class_chan_t, sizeof(europe_class_chan_t) / sizeof(class_chan_t)} /* CHINA */
|
|
};
|
|
|
|
/********************************************************
|
|
Global Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Local Functions
|
|
********************************************************/
|
|
/**
|
|
* @brief This function prepares the channel list for a particular
|
|
* regulatory class from channel number for legacy AP
|
|
* @param cur_class_chan_table A pointer to the class_chan_t
|
|
* @param num_entry Number of entry in cur_class_chan_table table
|
|
* @param chan_list A pointer to the output channel list
|
|
* @param chan_num total number of channel in output channel list
|
|
* @param reg_domain regulatory domain
|
|
* @param reg_class regulatory class
|
|
* @param is_intol_ap_present It sets TRUE when 40MHz intolerant AP is found
|
|
* otherwise FALSE
|
|
* @return None
|
|
*/
|
|
static void
|
|
get_channels_for_specified_reg_class(class_chan_t *cur_class_chan_table,
|
|
int num_entry, t_u8 *chan_list,
|
|
t_u8 *chan_num, t_u8 reg_domain,
|
|
t_u8 reg_class, t_u8 *is_intol_ap_present)
|
|
{
|
|
int i, j, k, idx = 0;
|
|
|
|
*is_intol_ap_present = FALSE;
|
|
|
|
/* For each regulatory class */
|
|
for (i = 0; i < num_entry; i++) {
|
|
if (cur_class_chan_table[i].reg_class == reg_class) {
|
|
/* For each channel of the regulatory class */
|
|
for (j = 0; j < cur_class_chan_table[i].total_chan; j++) {
|
|
for (k = 0; k < num_leg_ap_chan; k++) {
|
|
|
|
if (cur_class_chan_table[i].
|
|
channels[j] ==
|
|
leg_ap_chan_list[k].chan_num) {
|
|
*(chan_list + idx) =
|
|
leg_ap_chan_list[k].
|
|
chan_num;
|
|
idx++;
|
|
if (leg_ap_chan_list[k].
|
|
is_intol_set)
|
|
*is_intol_ap_present =
|
|
TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* update the total number of channel */
|
|
*chan_num = idx--;
|
|
return;
|
|
}
|
|
|
|
/********************************************************
|
|
Global Functions
|
|
********************************************************/
|
|
/**
|
|
* @brief Prepare 2040 coex command buffer
|
|
* @param buf A pointer to the command buffer
|
|
* @param chan_list Channel list
|
|
* @param num_of_chan Number of channel present in channel list
|
|
* @param reg_class Regulatory class
|
|
* @param is_intol_ap_present Flag: is any 40 MHz intolerant AP
|
|
* is present in these chaanel set
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
void
|
|
prepare_coex_cmd_buff(t_u8 *buf, t_u8 *chan_list, t_u8 num_of_chan,
|
|
t_u8 reg_class, t_u8 is_intol_ap_present)
|
|
{
|
|
HostCmd_DS_GEN *hostcmd;
|
|
MrvlIETypes_2040COEX_t *coex_ie = NULL;
|
|
MrvlIETypes_2040BssIntolerantChannelReport_t *bss_intol_ie = NULL;
|
|
t_u8 *pos = NULL;
|
|
int intol;
|
|
|
|
hostcmd = (HostCmd_DS_GEN *)(buf + sizeof(t_u32));
|
|
hostcmd->command = cpu_to_le16(HostCmd_CMD_11N_2040COEX);
|
|
hostcmd->size = S_DS_GEN;
|
|
pos = buf + sizeof(t_u32) + S_DS_GEN;
|
|
{
|
|
coex_ie = (MrvlIETypes_2040COEX_t *)pos;
|
|
coex_ie->header.element_id = TLV_ID_2040COEX;
|
|
coex_ie->header.len = sizeof(coex_ie->coex_elem);
|
|
/* Check STA is 40 MHz intolerant or not */
|
|
is_intolerant_sta(&intol);
|
|
if (intol)
|
|
coex_ie->coex_elem |= MBIT(1);
|
|
|
|
if (is_intol_ap_present)
|
|
coex_ie->coex_elem |= MBIT(2);
|
|
pos += sizeof(MrvlIETypes_2040COEX_t);
|
|
hostcmd->size += sizeof(MrvlIETypes_2040COEX_t);
|
|
}
|
|
{
|
|
bss_intol_ie =
|
|
(MrvlIETypes_2040BssIntolerantChannelReport_t *)pos;
|
|
bss_intol_ie->header.element_id =
|
|
TLV_ID_2040BSS_INTOL_CHAN_REPORT;
|
|
hostcmd->size +=
|
|
sizeof(MrvlIETypes_2040BssIntolerantChannelReport_t) -
|
|
sizeof(bss_intol_ie->chan_num);
|
|
bss_intol_ie->reg_class = reg_class;
|
|
memcpy(bss_intol_ie->chan_num, chan_list, num_of_chan);
|
|
bss_intol_ie->header.len =
|
|
sizeof(bss_intol_ie->reg_class) + num_of_chan;
|
|
hostcmd->size += num_of_chan;
|
|
}
|
|
hostcmd->size = cpu_to_le16(hostcmd->size);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief Invoke multiple 2040Coex commands for multiple regulatory classes
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
invoke_coex_command(void)
|
|
{
|
|
int cur_reg_domain;
|
|
t_u8 chan_list[MAX_CHAN], is_intol_ap_present;
|
|
t_u8 num_of_chan;
|
|
int i, num_entry, ret = MLAN_STATUS_SUCCESS;
|
|
class_chan_t *cur_class_chan_table = NULL;
|
|
|
|
/** get region code */
|
|
ret = get_region_code(&cur_reg_domain);
|
|
if (ret != MLAN_STATUS_SUCCESS)
|
|
return ret;
|
|
/** Find region_class_chan_table for this region */
|
|
for (i = 0;
|
|
(unsigned int)i <
|
|
(sizeof(region_class_chan_table) / sizeof(region_class_chan_t));
|
|
i++) {
|
|
if (region_class_chan_table[i].reg_domain == cur_reg_domain) {
|
|
cur_class_chan_table =
|
|
region_class_chan_table[i].class_chan_list;
|
|
num_entry =
|
|
region_class_chan_table[i].num_class_chan_entry;
|
|
break;
|
|
}
|
|
}
|
|
if (cur_class_chan_table == NULL) {
|
|
printf("No region_class_chan table found for this region\n");
|
|
return MLAN_STATUS_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < num_entry; i++) {
|
|
/** Get channels for the specified regulatory class */
|
|
get_channels_for_specified_reg_class(cur_class_chan_table,
|
|
num_entry, chan_list,
|
|
&num_of_chan,
|
|
cur_reg_domain,
|
|
cur_class_chan_table[i].
|
|
reg_class,
|
|
&is_intol_ap_present);
|
|
|
|
/** If any channel found for this regulatory class, then invoke the 2040coex command */
|
|
if (num_of_chan > 0) {
|
|
ret = process_host_cmd(CMD_2040COEX, chan_list,
|
|
num_of_chan,
|
|
cur_class_chan_table[i].
|
|
reg_class, is_intol_ap_present);
|
|
if (ret)
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Process host_cmd response
|
|
*
|
|
* @param cmd_name The command string
|
|
* @param buf A pointer to the response buffer
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS--success, otherwise--fail
|
|
*/
|
|
int
|
|
process_host_cmd_resp(char *cmd_name, t_u8 *buf)
|
|
{
|
|
t_u32 hostcmd_size = 0;
|
|
HostCmd_DS_GEN *hostcmd = NULL;
|
|
int ret = MLAN_STATUS_SUCCESS;
|
|
|
|
buf += strlen(CMD_MARVELL) + strlen(cmd_name);
|
|
memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32));
|
|
buf += sizeof(t_u32);
|
|
|
|
hostcmd = (HostCmd_DS_GEN *)buf;
|
|
hostcmd->command = le16_to_cpu(hostcmd->command);
|
|
hostcmd->size = le16_to_cpu(hostcmd->size);
|
|
|
|
hostcmd->command &= ~HostCmd_RET_BIT;
|
|
if (!le16_to_cpu(hostcmd->result)) {
|
|
switch (hostcmd->command) {
|
|
}
|
|
} else {
|
|
printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",
|
|
le16_to_cpu(hostcmd->command),
|
|
le16_to_cpu(hostcmd->result));
|
|
ret = MLAN_STATUS_FAILURE;
|
|
}
|
|
return ret;
|
|
}
|