mwifiex/mxm_wifiex/wlan_src/mapp/mlan2040coex/mlan2040misc.c
Fugang Duan 33d9f8e4f3 mxm_wifiex: add nxp mxm_wifiex sdk
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>
2020-04-20 00:54:27 +08:00

287 lines
9.1 KiB
C

/** @file mlan2040misc.c
*
* @brief This file contains helper functions for coex application
*
*
* 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:
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_NXP) + strlen(cmd_name);
memcpy((t_u8 *)&hostcmd_size, buf, sizeof(t_u32));
buf += sizeof(t_u32);
hostcmd = (HostCmd_DS_GEN *)buf;
hostcmd->command = le16_to_cpu(hostcmd->command);
hostcmd->size = le16_to_cpu(hostcmd->size);
hostcmd->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;
}