mirror of
https://github.com/pine64/bl_iot_sdk.git
synced 2024-09-15 15:14:03 +00:00
1072 lines
37 KiB
C
1072 lines
37 KiB
C
/*
|
|
* Copyright (c) 2020 Bouffalolab.
|
|
*
|
|
* This file is part of
|
|
* *** Bouffalolab Software Dev Kit ***
|
|
* (see www.bouffalolab.com).
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <string.h>
|
|
#include <utils_log.h>
|
|
#include <utils_tlv_bl.h>
|
|
#include <bl60x_fw_api.h>
|
|
|
|
#include "errno.h"
|
|
#include "bl_msg_tx.h"
|
|
#include "bl_utils.h"
|
|
|
|
// field definitions
|
|
#define NXMAC_EN_DUPLICATE_DETECTION_BIT ((uint32_t)0x80000000)
|
|
#define NXMAC_EN_DUPLICATE_DETECTION_POS 31
|
|
#define NXMAC_ACCEPT_UNKNOWN_BIT ((uint32_t)0x40000000)
|
|
#define NXMAC_ACCEPT_UNKNOWN_POS 30
|
|
#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT ((uint32_t)0x20000000)
|
|
#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_POS 29
|
|
#define NXMAC_ACCEPT_QO_S_NULL_BIT ((uint32_t)0x10000000)
|
|
#define NXMAC_ACCEPT_QO_S_NULL_POS 28
|
|
#define NXMAC_ACCEPT_QCFWO_DATA_BIT ((uint32_t)0x08000000)
|
|
#define NXMAC_ACCEPT_QCFWO_DATA_POS 27
|
|
#define NXMAC_ACCEPT_Q_DATA_BIT ((uint32_t)0x04000000)
|
|
#define NXMAC_ACCEPT_Q_DATA_POS 26
|
|
#define NXMAC_ACCEPT_CFWO_DATA_BIT ((uint32_t)0x02000000)
|
|
#define NXMAC_ACCEPT_CFWO_DATA_POS 25
|
|
#define NXMAC_ACCEPT_DATA_BIT ((uint32_t)0x01000000)
|
|
#define NXMAC_ACCEPT_DATA_POS 24
|
|
#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT ((uint32_t)0x00800000)
|
|
#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_POS 23
|
|
#define NXMAC_ACCEPT_CF_END_BIT ((uint32_t)0x00400000)
|
|
#define NXMAC_ACCEPT_CF_END_POS 22
|
|
#define NXMAC_ACCEPT_ACK_BIT ((uint32_t)0x00200000)
|
|
#define NXMAC_ACCEPT_ACK_POS 21
|
|
#define NXMAC_ACCEPT_CTS_BIT ((uint32_t)0x00100000)
|
|
#define NXMAC_ACCEPT_CTS_POS 20
|
|
#define NXMAC_ACCEPT_RTS_BIT ((uint32_t)0x00080000)
|
|
#define NXMAC_ACCEPT_RTS_POS 19
|
|
#define NXMAC_ACCEPT_PS_POLL_BIT ((uint32_t)0x00040000)
|
|
#define NXMAC_ACCEPT_PS_POLL_POS 18
|
|
#define NXMAC_ACCEPT_BA_BIT ((uint32_t)0x00020000)
|
|
#define NXMAC_ACCEPT_BA_POS 17
|
|
#define NXMAC_ACCEPT_BAR_BIT ((uint32_t)0x00010000)
|
|
#define NXMAC_ACCEPT_BAR_POS 16
|
|
#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT ((uint32_t)0x00008000)
|
|
#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_POS 15
|
|
#define NXMAC_ACCEPT_ALL_BEACON_BIT ((uint32_t)0x00002000)
|
|
#define NXMAC_ACCEPT_ALL_BEACON_POS 13
|
|
#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT ((uint32_t)0x00001000)
|
|
#define NXMAC_ACCEPT_NOT_EXPECTED_BA_POS 12
|
|
#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT ((uint32_t)0x00000800)
|
|
#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_POS 11
|
|
#define NXMAC_ACCEPT_BEACON_BIT ((uint32_t)0x00000400)
|
|
#define NXMAC_ACCEPT_BEACON_POS 10
|
|
#define NXMAC_ACCEPT_PROBE_RESP_BIT ((uint32_t)0x00000200)
|
|
#define NXMAC_ACCEPT_PROBE_RESP_POS 9
|
|
#define NXMAC_ACCEPT_PROBE_REQ_BIT ((uint32_t)0x00000100)
|
|
#define NXMAC_ACCEPT_PROBE_REQ_POS 8
|
|
#define NXMAC_ACCEPT_MY_UNICAST_BIT ((uint32_t)0x00000080)
|
|
#define NXMAC_ACCEPT_MY_UNICAST_POS 7
|
|
#define NXMAC_ACCEPT_UNICAST_BIT ((uint32_t)0x00000040)
|
|
#define NXMAC_ACCEPT_UNICAST_POS 6
|
|
#define NXMAC_ACCEPT_ERROR_FRAMES_BIT ((uint32_t)0x00000020)
|
|
#define NXMAC_ACCEPT_ERROR_FRAMES_POS 5
|
|
#define NXMAC_ACCEPT_OTHER_BSSID_BIT ((uint32_t)0x00000010)
|
|
#define NXMAC_ACCEPT_OTHER_BSSID_POS 4
|
|
#define NXMAC_ACCEPT_BROADCAST_BIT ((uint32_t)0x00000008)
|
|
#define NXMAC_ACCEPT_BROADCAST_POS 3
|
|
#define NXMAC_ACCEPT_MULTICAST_BIT ((uint32_t)0x00000004)
|
|
#define NXMAC_ACCEPT_MULTICAST_POS 2
|
|
#define NXMAC_DONT_DECRYPT_BIT ((uint32_t)0x00000002)
|
|
#define NXMAC_DONT_DECRYPT_POS 1
|
|
#define NXMAC_EXC_UNENCRYPTED_BIT ((uint32_t)0x00000001)
|
|
#define NXMAC_EXC_UNENCRYPTED_POS 0
|
|
|
|
static const struct mac_addr mac_addr_bcst = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
|
|
static const struct mac_addr mac_addr_zero = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
|
|
|
static const struct ieee80211_channel bl_channels_24_JP[] = {
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, .max_power=16},
|
|
};
|
|
|
|
static const struct ieee80211_channel bl_channels_24_CN[] = {
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, .max_power=16},
|
|
};
|
|
|
|
static const struct ieee80211_channel bl_channels_24_US[] = {
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power=16},
|
|
};
|
|
|
|
static const struct ieee80211_channel bl_channels_24_ER[] = {
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, .max_power=16},
|
|
{ .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, .max_power=16},
|
|
};
|
|
|
|
static const struct ieee80211_dot_d country_list[] =
|
|
{
|
|
{
|
|
.code = "CN",
|
|
.channel_num = sizeof(bl_channels_24_CN)/sizeof(bl_channels_24_CN[0]),
|
|
.channels = bl_channels_24_CN,
|
|
},
|
|
{
|
|
.code = "JP",
|
|
.channel_num = sizeof(bl_channels_24_JP)/sizeof(bl_channels_24_JP[0]),
|
|
.channels = bl_channels_24_JP,
|
|
},
|
|
{
|
|
.code = "US",
|
|
.channel_num = sizeof(bl_channels_24_US)/sizeof(bl_channels_24_US[0]),
|
|
.channels = bl_channels_24_US,
|
|
},
|
|
{
|
|
.code = "EU",
|
|
.channel_num = sizeof(bl_channels_24_ER)/sizeof(bl_channels_24_ER[0]),
|
|
.channels = bl_channels_24_ER,
|
|
},
|
|
};
|
|
static int channel_num_default;
|
|
static const struct ieee80211_channel *channels_default;
|
|
|
|
static int cfg80211_get_channel_list(const char *code, int *channel_num, const struct ieee80211_channel **channels)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(country_list)/sizeof(country_list[0]); i++) {
|
|
if (0 == strcmp(country_list[i].code, code)) {
|
|
if (channel_num) {
|
|
*channel_num = country_list[i].channel_num;
|
|
}
|
|
if (channels) {
|
|
*channels = country_list[i].channels;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
/*NOT found code*/
|
|
return -1;
|
|
}
|
|
|
|
void bl_msg_update_channel_cfg(const char *code)
|
|
{
|
|
if (cfg80211_get_channel_list(code, &channel_num_default, &channels_default)) {
|
|
/*get channel list failed, so we set the default one*/
|
|
channel_num_default = sizeof(bl_channels_24_JP)/sizeof(bl_channels_24_JP[0]);
|
|
channels_default = bl_channels_24_JP;
|
|
printf("[WF] %s NOT found, using JP instead, num of channel %d\r\n", code, channel_num_default);
|
|
} else {
|
|
printf("[WF] country code %s used, num of channel %d\r\n", code, channel_num_default);
|
|
}
|
|
|
|
}
|
|
|
|
int bl_msg_get_channel_nums()
|
|
{
|
|
return channel_num_default;
|
|
}
|
|
|
|
static inline uint16_t phy_channel_to_freq(uint8_t band, int channel)
|
|
{
|
|
uint16_t freq = 0xFFFF;
|
|
|
|
do
|
|
{
|
|
//2.4.GHz
|
|
if (band == PHY_BAND_2G4)
|
|
{
|
|
// Check if the channel number is in the expected range
|
|
if ((channel < 1) || (channel > 14))
|
|
break;
|
|
|
|
// Compute the channel number
|
|
if (channel == 14)
|
|
freq = 2484;
|
|
else
|
|
freq = 2407 + channel * 5;
|
|
}
|
|
//5 GHz
|
|
else if (band == PHY_BAND_5G)
|
|
{
|
|
// Check if frequency is in the expected range
|
|
if ((channel < 1) || (channel > 165))
|
|
break;
|
|
|
|
// Compute the channel number
|
|
freq = 5000 + channel * 5;
|
|
}
|
|
} while(0);
|
|
|
|
return (freq);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************
|
|
*
|
|
* @file bl_msg_tx.c
|
|
* Copyright (C) Bouffalo Lab 2016-2018
|
|
*
|
|
****************************************************************************************
|
|
*/
|
|
|
|
static inline void *bl_msg_zalloc(lmac_msg_id_t const id,
|
|
lmac_task_id_t const dest_id,
|
|
lmac_task_id_t const src_id,
|
|
uint16_t const param_len)
|
|
{
|
|
struct lmac_msg *msg;
|
|
|
|
msg = (struct lmac_msg *)os_malloc(sizeof(struct lmac_msg) + param_len);
|
|
if (msg == NULL) {
|
|
os_printf("%s: msg allocation failed\n", __func__);
|
|
return NULL;
|
|
}
|
|
memset(msg, 0, sizeof(struct lmac_msg) + param_len);
|
|
|
|
msg->id = id;
|
|
msg->dest_id = dest_id;
|
|
msg->src_id = src_id;
|
|
msg->param_len = param_len;
|
|
|
|
return msg->param;
|
|
}
|
|
|
|
static inline bool is_non_blocking_msg(int id) {
|
|
return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) ||
|
|
(id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ) ||
|
|
(id == MESH_PATH_CREATE_REQ) || (id == MESH_PROXY_ADD_REQ));
|
|
}
|
|
|
|
#define BITS_PER_LONG 32
|
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
|
/**
|
|
* test_bit - Determine whether a bit is set
|
|
* @nr: bit number to test
|
|
* @addr: Address to start counting from
|
|
*/
|
|
static inline int test_bit(int nr, const volatile unsigned long *addr)
|
|
{
|
|
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
|
}
|
|
|
|
static int bl_send_msg(struct bl_hw *bl_hw, const void *msg_params,
|
|
int reqcfm, lmac_msg_id_t reqid, void *cfm)
|
|
{
|
|
struct lmac_msg *msg;
|
|
struct bl_cmd *cmd;
|
|
bool nonblock;
|
|
int ret;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
msg = container_of((void *)msg_params, struct lmac_msg, param);
|
|
|
|
if (!test_bit(RWNX_DEV_STARTED, &bl_hw->drv_flags) &&
|
|
reqid != MM_RESET_CFM && reqid != MM_VERSION_CFM &&
|
|
reqid != MM_START_CFM && reqid != MM_SET_IDLE_CFM &&
|
|
reqid != ME_CONFIG_CFM && reqid != MM_SET_PS_MODE_CFM &&
|
|
reqid != ME_CHAN_CONFIG_CFM) {
|
|
os_printf("%s: bypassing (RWNX_DEV_RESTARTING set) 0x%02x\n", __func__, reqid);
|
|
os_free(msg);
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return -EBUSY;
|
|
} else if (!bl_hw->ipc_env) {
|
|
os_printf("%s: bypassing (restart must have failed)\r\n", __func__);
|
|
os_free(msg);
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return -EBUSY;
|
|
}
|
|
|
|
nonblock = is_non_blocking_msg(msg->id);
|
|
|
|
cmd = os_malloc(sizeof(struct bl_cmd));
|
|
if (NULL == cmd) {
|
|
os_free(msg);
|
|
os_printf("%s: failed to allocate mem for cmd, size is %d\r\n", __func__, sizeof(struct bl_cmd));
|
|
return -ENOMEM;
|
|
}
|
|
memset(cmd, 0, sizeof(struct bl_cmd));
|
|
cmd->result = EINTR;
|
|
cmd->id = msg->id;
|
|
cmd->reqid = reqid;
|
|
cmd->a2e_msg = msg;
|
|
cmd->e2a_msg = cfm;
|
|
if (nonblock)
|
|
cmd->flags = RWNX_CMD_FLAG_NONBLOCK;
|
|
if (reqcfm)
|
|
cmd->flags |= RWNX_CMD_FLAG_REQ_CFM;
|
|
ret = bl_hw->cmd_mgr.queue(&bl_hw->cmd_mgr, cmd);
|
|
|
|
if (!nonblock) {
|
|
os_free(cmd);
|
|
} else {
|
|
ret = cmd->result;
|
|
}
|
|
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return ret;
|
|
}
|
|
|
|
int bl_send_reset(struct bl_hw *bl_hw)
|
|
{
|
|
void *void_param;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* RESET REQ has no parameter */
|
|
void_param = bl_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0);
|
|
if (!void_param)
|
|
return -ENOMEM;
|
|
|
|
return bl_send_msg(bl_hw, void_param, 1, MM_RESET_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_monitor_enable(struct bl_hw *bl_hw, struct mm_monitor_cfm *cfm)
|
|
{
|
|
struct mm_monitor_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
req = bl_msg_zalloc(MM_MONITOR_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_monitor_req));
|
|
if (!req)
|
|
return -ENOMEM;
|
|
|
|
req->enable = 1;
|
|
|
|
return bl_send_msg(bl_hw, req, 1, MM_MONITOR_CFM, cfm);
|
|
}
|
|
|
|
//TODO we only support 2.4GHz
|
|
int bl_send_monitor_channel_set(struct bl_hw *bl_hw, struct mm_monitor_channel_cfm *cfm, int channel, int use_40Mhz)
|
|
{
|
|
struct mm_monitor_channel_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
req = bl_msg_zalloc(MM_MONITOR_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_monitor_channel_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
req->freq = phy_channel_to_freq(PHY_BAND_2G4, channel);
|
|
if (use_40Mhz) {
|
|
req->use_40Mhz = 1;
|
|
if (1 == use_40Mhz) {
|
|
req->higher_band = 0;
|
|
} else {
|
|
req->higher_band = 1;
|
|
}
|
|
} else {
|
|
req->use_40Mhz = 0;
|
|
req->higher_band = 0;
|
|
}
|
|
|
|
return bl_send_msg(bl_hw, req, 1, MM_MONITOR_CHANNEL_CFM, cfm);
|
|
}
|
|
|
|
int bl_send_version_req(struct bl_hw *bl_hw, struct mm_version_cfm *cfm)
|
|
{
|
|
int ret;
|
|
void *void_param;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* VERSION REQ has no parameter */
|
|
void_param = bl_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0);
|
|
if (!void_param) {
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return -ENOMEM;
|
|
}
|
|
ret = bl_send_msg(bl_hw, void_param, 1, MM_VERSION_CFM, cfm);
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return ret;
|
|
}
|
|
|
|
int bl_send_me_config_req(struct bl_hw *bl_hw)
|
|
{
|
|
struct me_config_req *req;
|
|
uint8_t *ht_mcs = (uint8_t *)&(bl_hw->ht_cap.mcs);
|
|
int i, ret;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the ME_CONFIG_REQ message */
|
|
req = bl_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
|
|
sizeof(struct me_config_req));
|
|
if (!req) {
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the ME_CONFIG_REQ message */
|
|
os_printf("[ME] HT supp %d, VHT supp %d\r\n", 1, 0);
|
|
|
|
req->ht_supp = 1;
|
|
req->vht_supp = 0;
|
|
req->ht_cap.ht_capa_info = cpu_to_le16(bl_hw->ht_cap.cap);
|
|
req->ht_cap.a_mpdu_param = bl_hw->ht_cap.ampdu_factor |
|
|
(bl_hw->ht_cap.ampdu_density <<
|
|
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
|
|
for (i = 0; i < sizeof(bl_hw->ht_cap.mcs); i++) {
|
|
req->ht_cap.mcs_rate[i] = ht_mcs[i];
|
|
}
|
|
req->ht_cap.ht_extended_capa = 0;
|
|
req->ht_cap.tx_beamforming_capa = 0;
|
|
req->ht_cap.asel_capa = 0;
|
|
|
|
//TODO talk with firmware guys
|
|
#if 0
|
|
req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap);
|
|
req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest);
|
|
req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map);
|
|
req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest);
|
|
req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map);
|
|
#endif
|
|
|
|
req->ps_on = bl_hw->mod_params->ps_on;
|
|
req->tx_lft = bl_hw->mod_params->tx_lft;
|
|
|
|
/* Send the ME_CONFIG_REQ message to LMAC FW */
|
|
ret = bl_send_msg(bl_hw, req, 1, ME_CONFIG_CFM, NULL);
|
|
RWNX_DBG(RWNX_FN_LEAVE_STR);
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t passive_scan_flag(uint32_t flags) {
|
|
if (flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
|
|
return SCAN_PASSIVE_BIT;
|
|
return 0;
|
|
}
|
|
|
|
int bl_send_me_chan_config_req(struct bl_hw *bl_hw)
|
|
{
|
|
struct me_chan_config_req *req;
|
|
int i;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the ME_CHAN_CONFIG_REQ message */
|
|
req = bl_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
|
|
sizeof(struct me_chan_config_req));
|
|
if (!req)
|
|
return -ENOMEM;
|
|
|
|
req->chan2G4_cnt = 0;
|
|
for (i = 0; i < channel_num_default; i++) {
|
|
req->chan2G4[req->chan2G4_cnt].flags = 0;
|
|
if (channels_default[i].flags & IEEE80211_CHAN_DISABLED)
|
|
req->chan2G4[req->chan2G4_cnt].flags |= SCAN_DISABLED_BIT;
|
|
req->chan2G4[req->chan2G4_cnt].flags |= passive_scan_flag(channels_default[i].flags);
|
|
req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ;
|
|
req->chan2G4[req->chan2G4_cnt].freq = channels_default[i].center_freq;
|
|
req->chan2G4[req->chan2G4_cnt].tx_power = channels_default[i].max_power;
|
|
req->chan2G4_cnt++;
|
|
if (req->chan2G4_cnt == SCAN_CHANNEL_2G4)
|
|
break;
|
|
}
|
|
|
|
req->chan5G_cnt = 0;
|
|
/* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_me_rate_config_req(struct bl_hw *bl_hw, uint8_t sta_idx, uint16_t fixed_rate_cfg)
|
|
{
|
|
struct me_rc_set_rate_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the ME_RC_SET_RATE_REQ message */
|
|
req = bl_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID, sizeof(struct me_rc_set_rate_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
req->sta_idx = sta_idx;
|
|
req->fixed_rate_cfg = fixed_rate_cfg;
|
|
|
|
return bl_send_msg(bl_hw, req, 0, 0, NULL);
|
|
}
|
|
|
|
int bl_send_start(struct bl_hw *bl_hw)
|
|
{
|
|
struct mm_start_req *start_req_param;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the START REQ message */
|
|
start_req_param = bl_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID,
|
|
sizeof(struct mm_start_req));
|
|
if (!start_req_param)
|
|
return -ENOMEM;
|
|
|
|
//TODO where get the phy_cfg ?
|
|
//FIXME we use magic here, since we know the first u32 is cal_en
|
|
bl_hw->phy_config.parameters[0] = 0x01;
|
|
/* Set parameters for the START message */
|
|
memcpy(&start_req_param->phy_cfg, &bl_hw->phy_config, sizeof(bl_hw->phy_config));
|
|
start_req_param->uapsd_timeout = (u32_l)bl_hw->mod_params->uapsd_timeout;
|
|
start_req_param->lp_clk_accuracy = (u16_l)bl_hw->mod_params->lp_clk_ppm;
|
|
|
|
/* Send the START REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, start_req_param, 1, MM_START_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_add_if(struct bl_hw *bl_hw, const unsigned char *mac,
|
|
enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm)
|
|
{
|
|
struct mm_add_if_req *add_if_req_param;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the ADD_IF_REQ message */
|
|
add_if_req_param = bl_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID,
|
|
sizeof(struct mm_add_if_req));
|
|
if (!add_if_req_param)
|
|
return -ENOMEM;
|
|
|
|
/* Set parameters for the ADD_IF_REQ message */
|
|
memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN);
|
|
switch (iftype) {
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
|
add_if_req_param->p2p = true;
|
|
__attribute__((fallthrough));
|
|
// no break
|
|
case NL80211_IFTYPE_STATION:
|
|
add_if_req_param->type = MM_STA;
|
|
break;
|
|
|
|
case NL80211_IFTYPE_ADHOC:
|
|
add_if_req_param->type = MM_IBSS;
|
|
break;
|
|
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
add_if_req_param->p2p = true;
|
|
__attribute__((fallthrough));
|
|
// no break
|
|
case NL80211_IFTYPE_AP:
|
|
add_if_req_param->type = MM_AP;
|
|
break;
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
add_if_req_param->type = MM_MESH_POINT;
|
|
break;
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
return -1;
|
|
default:
|
|
add_if_req_param->type = MM_STA;
|
|
break;
|
|
}
|
|
|
|
/* Send the ADD_IF_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm);
|
|
}
|
|
|
|
int bl_send_remove_if(struct bl_hw *bl_hw, uint8_t inst_nbr)
|
|
{
|
|
struct mm_remove_if_req *remove_if_req_param;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
remove_if_req_param = bl_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_remove_if_req));
|
|
if (!remove_if_req_param) {
|
|
return -ENOMEM;
|
|
}
|
|
remove_if_req_param->inst_nbr = inst_nbr;
|
|
|
|
return bl_send_msg(bl_hw, remove_if_req_param, 1, MM_REMOVE_IF_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_scanu_req(struct bl_hw *bl_hw)
|
|
{
|
|
struct scanu_start_req *req;
|
|
int i;
|
|
uint8_t chan_flags = 0;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the SCANU_START_REQ message */
|
|
req = bl_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID,
|
|
sizeof(struct scanu_start_req));
|
|
if (!req)
|
|
return -ENOMEM;
|
|
|
|
/* Set parameters */
|
|
//FIXME should we use vif_index_sta when NO sta is added or just use 0?
|
|
req->vif_idx = bl_hw->vif_index_sta;
|
|
req->chan_cnt = channel_num_default;
|
|
req->ssid_cnt = 0;
|
|
req->bssid = mac_addr_bcst;
|
|
req->no_cck = true;//FIXME params? talk with firmware guys
|
|
|
|
if (req->ssid_cnt == 0) {
|
|
chan_flags |= SCAN_PASSIVE_BIT;
|
|
}
|
|
#if 0
|
|
for (i = 0; i < req->ssid_cnt; i++) {
|
|
int j;
|
|
for (j = 0; j < param->ssids[i].ssid_len; j++)
|
|
req->ssid[i].array[j] = param->ssids[i].ssid[j];
|
|
req->ssid[i].length = param->ssids[i].ssid_len;
|
|
}
|
|
#endif
|
|
|
|
//XXX custom ie can be added
|
|
req->add_ie_len = 0;
|
|
req->add_ies = 0;
|
|
|
|
for (i = 0; i < req->chan_cnt; i++) {
|
|
const struct ieee80211_channel *chan = &(channels_default[i]);
|
|
|
|
req->chan[i].band = chan->band;
|
|
req->chan[i].freq = chan->center_freq;
|
|
req->chan[i].flags = chan_flags | passive_scan_flag(chan->flags);
|
|
req->chan[i].tx_power = chan->max_reg_power;
|
|
}
|
|
|
|
/* Send the SCANU_START_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 0, 0, NULL);
|
|
}
|
|
|
|
int bl_send_scanu_raw_send(struct bl_hw *bl_hw, uint8_t *pkt, int len)
|
|
{
|
|
struct scanu_raw_send_req *req;
|
|
struct scanu_raw_send_cfm cfm;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the SCANU_RAW_SEND_REQ message */
|
|
req = bl_msg_zalloc(SCANU_RAW_SEND_REQ, TASK_SCANU, DRV_TASK_ID, sizeof(struct scanu_raw_send_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters */
|
|
req->pkt = pkt;
|
|
req->len = len;
|
|
|
|
/* Send the SCANU_RAW_SEND_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, SCANU_RAW_SEND_CFM, &cfm);
|
|
}
|
|
|
|
static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto)
|
|
{
|
|
if ((crypto->cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
|
|
(crypto->cipher_group == WLAN_CIPHER_SUITE_WEP104))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
int bl_send_sm_connect_req(struct bl_hw *bl_hw, struct cfg80211_connect_params *sme, struct sm_connect_cfm *cfm)
|
|
{
|
|
struct sm_connect_req *req;
|
|
int i;
|
|
u32_l flags = 0;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the SM_CONNECT_REQ message */
|
|
req = bl_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID,
|
|
sizeof(struct sm_connect_req));
|
|
if (!req)
|
|
return -ENOMEM;
|
|
|
|
/* Set parameters for the SM_CONNECT_REQ message */
|
|
if (sme->crypto.n_ciphers_pairwise &&
|
|
((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) ||
|
|
(sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) ||
|
|
(sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)))
|
|
flags |= DISABLE_HT;
|
|
|
|
if (sme->crypto.control_port)
|
|
flags |= CONTROL_PORT_HOST;
|
|
|
|
if (sme->crypto.control_port_no_encrypt)
|
|
flags |= CONTROL_PORT_NO_ENC;
|
|
|
|
if (use_pairwise_key(&sme->crypto))
|
|
flags |= WPA_WPA2_IN_USE;
|
|
|
|
if (sme->mfp == NL80211_MFP_REQUIRED)
|
|
flags |= MFP_IN_USE;
|
|
|
|
if (sme->crypto.control_port_ethertype)
|
|
req->ctrl_port_ethertype = sme->crypto.control_port_ethertype;
|
|
else
|
|
req->ctrl_port_ethertype = ETH_P_PAE;
|
|
|
|
if (sme->bssid && !MAC_ADDR_CMP(sme->bssid, mac_addr_bcst.array) && !MAC_ADDR_CMP(sme->bssid, mac_addr_zero.array)) {
|
|
for (i=0;i<ETH_ALEN;i++)
|
|
req->bssid.array[i] = sme->bssid[i];
|
|
}
|
|
else
|
|
req->bssid = mac_addr_bcst;
|
|
req->vif_idx = bl_hw->vif_index_sta;
|
|
if (sme->channel.center_freq) {
|
|
req->chan.band = sme->channel.band;
|
|
req->chan.freq = sme->channel.center_freq;
|
|
req->chan.flags = passive_scan_flag(sme->channel.flags);
|
|
} else {
|
|
req->chan.freq = (u16_l)-1;
|
|
}
|
|
for (i = 0; i < sme->ssid_len; i++)
|
|
req->ssid.array[i] = sme->ssid[i];
|
|
req->ssid.length = sme->ssid_len;
|
|
req->flags = flags;
|
|
if (WARN_ON(sme->ie_len > sizeof(req->ie_buf)))
|
|
return -EINVAL;
|
|
if (sme->ie_len)
|
|
memcpy(req->ie_buf, sme->ie, sme->ie_len);
|
|
req->ie_len = sme->ie_len;
|
|
req->listen_interval = bl_mod_params.listen_itv;
|
|
req->dont_wait_bcmc = !bl_mod_params.listen_bcmc;
|
|
|
|
/* Set auth_type */
|
|
if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC)
|
|
req->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
|
else
|
|
req->auth_type = sme->auth_type;
|
|
|
|
/* Set UAPSD queues */
|
|
req->uapsd_queues = bl_mod_params.uapsd_queues;
|
|
req->is_supplicant_enabled = 1;
|
|
if (sme->key_len) {
|
|
memcpy(req->phrase, sme->key, sme->key_len);
|
|
}
|
|
if (sme->pmk_len) {
|
|
memcpy(req->phrase_pmk, sme->pmk, sme->pmk_len);
|
|
}
|
|
|
|
/* Send the SM_CONNECT_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, SM_CONNECT_CFM, cfm);
|
|
}
|
|
|
|
int bl_send_sm_disconnect_req(struct bl_hw *bl_hw, u16 reason)
|
|
{
|
|
struct sm_disconnect_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the SM_DISCONNECT_REQ message */
|
|
req = bl_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID, sizeof(struct sm_disconnect_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the SM_DISCONNECT_REQ message */
|
|
req->reason_code = reason;
|
|
req->vif_idx = bl_hw->vif_index_sta;
|
|
|
|
/* Send the SM_DISCONNECT_REQ message to LMAC FW */
|
|
//return bl_send_msg(bl_hw, req, 1, SM_DISCONNECT_IND, NULL);
|
|
return bl_send_msg(bl_hw, req, 1, SM_DISCONNECT_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_mm_powersaving_req(struct bl_hw *bl_hw, int mode)
|
|
{
|
|
struct mm_set_ps_mode_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the MM_SET_PS_MODE_REQ message */
|
|
req = bl_msg_zalloc(MM_SET_PS_MODE_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_ps_mode_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the MM_SET_PS_MODE_REQ message */
|
|
req->new_state = mode;
|
|
|
|
/* Send the MM_SET_PS_MODE_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, MM_SET_PS_MODE_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_mm_denoise_req(struct bl_hw *bl_hw, int mode)
|
|
{
|
|
struct mm_set_denoise_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the MM_DENOISE_REQ message */
|
|
req = bl_msg_zalloc(MM_DENOISE_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_denoise_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the MM_SET_PS_MODE_REQ message */
|
|
req->denoise_mode = mode;
|
|
|
|
/* Send the MM_SET_PS_MODE_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, MM_SET_PS_MODE_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_apm_start_req(struct bl_hw *bl_hw, struct apm_start_cfm *cfm, char *ssid, char *password, int channel, uint8_t vif_index, uint8_t hidden_ssid)
|
|
{
|
|
struct apm_start_req *req;
|
|
uint8_t rate[] = {0x82,0x84,0x8b,0x96,0x12,0x24,0x48,0x6c,0x0c,0x18,0x30,0x60};
|
|
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the APM_START_REQ message */
|
|
req = bl_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_start_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
req->chan.band = NL80211_BAND_2GHZ;
|
|
req->chan.freq = phy_channel_to_freq(req->chan.band, channel);
|
|
req->chan.flags = 0;
|
|
req->chan.tx_power = 0;
|
|
|
|
/* Set parameters for the APM_START_REQ message */
|
|
req->center_freq1 = req->chan.freq;
|
|
req->center_freq2 = 0;
|
|
req->ch_width = PHY_CHNL_BW_20;
|
|
req->hidden_ssid = hidden_ssid;
|
|
req->bcn_addr = 0;
|
|
req->bcn_len = 0;
|
|
req->tim_oft = 0;
|
|
req->bcn_int = 0x64;
|
|
req->flags = 0x08;
|
|
//req->ctrl_port_ethertype = ETH_P_PAE;
|
|
req->ctrl_port_ethertype = 0x8e88;
|
|
req->tim_len = 0x6;
|
|
req->vif_idx = vif_index;
|
|
|
|
/*added for EMBEDED*/
|
|
#if 0
|
|
/// Enable APM Embedded
|
|
bool apm_emb_enabled;
|
|
/// rate set
|
|
struct mac_rateset rate_set;
|
|
/// Beacon dtim period
|
|
uint8_t beacon_period;
|
|
/// Qos is supported
|
|
uint8_t qos_supported;
|
|
/// SSID of the AP
|
|
struct mac_ssid ssid;
|
|
/// AP Security type
|
|
uint8_t ap_sec_type;
|
|
/// AP Passphrase
|
|
uint8_t phrase[MAX_PSK_PASS_PHRASE_LEN];
|
|
#else
|
|
if (strlen(password)) {
|
|
req->ap_sec_type = 1;
|
|
} else {
|
|
req->ap_sec_type = 0;
|
|
}
|
|
req->apm_emb_enabled = 1;
|
|
memcpy(req->ssid.array, ssid, strlen(ssid));//FIXME potential buffer overflow
|
|
memcpy(req->phrase, password, strlen(password));//FIXME potential buffer overflow
|
|
req->ssid.length = strlen(ssid);
|
|
req->rate_set.length = 12;
|
|
memcpy(req->rate_set.array, rate, req->rate_set.length);
|
|
req->beacon_period = 0x1; //force AP DTIM period
|
|
req->qos_supported = 1;
|
|
#endif
|
|
|
|
/* Send the APM_START_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, APM_START_CFM, cfm);
|
|
}
|
|
|
|
int bl_send_apm_stop_req(struct bl_hw *bl_hw, uint8_t vif_idx)
|
|
{
|
|
struct apm_stop_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the APM_STOP_REQ message */
|
|
req = bl_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_stop_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the APM_STOP_REQ message */
|
|
req->vif_idx = vif_idx;
|
|
|
|
/* Send the APM_STOP_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, APM_STOP_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_apm_sta_del_req(struct bl_hw *bl_hw, struct apm_sta_del_cfm *cfm, uint8_t sta_idx, uint8_t vif_idx)
|
|
{
|
|
struct apm_sta_del_req *req;
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
/* Build the APM_STOP_REQ message */
|
|
req = bl_msg_zalloc(APM_STA_DEL_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_sta_del_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the APM_STA_DEL_REQ message */
|
|
req->vif_idx = vif_idx;
|
|
req->sta_idx = sta_idx;
|
|
|
|
/* Send the APM_STA_DEL_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, APM_STA_DEL_CFM, cfm);
|
|
}
|
|
|
|
int bl_send_apm_conf_max_sta_req(struct bl_hw *bl_hw, uint8_t max_sta_supported)
|
|
{
|
|
struct apm_conf_max_sta_req *req;
|
|
|
|
/* Build the APM_STOP_REQ message */
|
|
req = bl_msg_zalloc(APM_CONF_MAX_STA_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_conf_max_sta_req));
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the APM_STOP_REQ message */
|
|
req->max_sta_supported = max_sta_supported;
|
|
|
|
/* Send the APM_STOP_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, APM_CONF_MAX_STA_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_cfg_task_req(struct bl_hw *bl_hw, uint32_t ops, uint32_t task, uint32_t element, uint32_t type, void *arg1, void *arg2)
|
|
{
|
|
struct cfg_start_req *req;
|
|
#define ENTRY_BUF_SIZE (8)
|
|
|
|
/* Build the APM_STOP_REQ message */
|
|
//FIXME static allocated size
|
|
req = bl_msg_zalloc(CFG_START_REQ, TASK_CFG, DRV_TASK_ID, sizeof(struct cfg_start_req) + 32);
|
|
if (!req) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Set parameters for the APM_STOP_REQ message */
|
|
req->ops = ops;
|
|
switch (req->ops) {
|
|
case CFG_ELEMENT_TYPE_OPS_SET:
|
|
{
|
|
req->u.set[0].task = task;
|
|
req->u.set[0].element = element;
|
|
req->u.set[0].type = type;
|
|
req->u.set[0].length = utils_tlv_bl_pack_auto(
|
|
req->u.set[0].buf,
|
|
ENTRY_BUF_SIZE,
|
|
type,
|
|
arg1
|
|
);
|
|
}
|
|
break;
|
|
case CFG_ELEMENT_TYPE_OPS_GET:
|
|
{
|
|
//TODO
|
|
}
|
|
break;
|
|
case CFG_ELEMENT_TYPE_OPS_RESET:
|
|
{
|
|
//TODO
|
|
}
|
|
break;
|
|
case CFG_ELEMENT_TYPE_OPS_DUMP_DEBUG:
|
|
{
|
|
req->u.set[0].task = task;
|
|
req->u.set[0].element = element;
|
|
req->u.set[0].length = 0;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
/*empty here*/
|
|
BL_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
/* Send the APM_STOP_REQ message to LMAC FW */
|
|
return bl_send_msg(bl_hw, req, 1, CFG_START_CFM, NULL);
|
|
}
|
|
|
|
int bl_send_channel_set_req(struct bl_hw *bl_hw, int channel)
|
|
{
|
|
struct mm_set_channel_req *param;
|
|
struct mm_set_channel_cfm cfm;
|
|
|
|
|
|
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
|
|
|
param = bl_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_channel_req));
|
|
if (!param) {
|
|
return -ENOMEM;
|
|
}
|
|
memset(&cfm, 0, sizeof(struct mm_set_channel_cfm));
|
|
|
|
param->band = PHY_BAND_2G4;
|
|
param->type = PHY_CHNL_BW_20;
|
|
param->prim20_freq = phy_channel_to_freq(param->band, channel);
|
|
param->center1_freq = phy_channel_to_freq(param->band, channel);//useless when bandwidth bigger than 20MHZ?
|
|
param->center2_freq = phy_channel_to_freq(param->band, channel);//useless when bandwidth bigger than 20MHZ?
|
|
param->index = 0;
|
|
param->tx_power = 15;//FIXME which value should be tx_power set?
|
|
|
|
return bl_send_msg(bl_hw, param, 1, MM_SET_CHANNEL_CFM, &cfm);
|
|
}
|
|
|