use alloc::{sync::Arc, vec, vec::Vec};
use crate::{
common::ChipVariant,
fdrv::{
core::bus::WifiBus,
protocol::{cmd::send_cmd, lmac_msg::*},
},
};
pub fn send_set_stack_start_req(
bus: &Arc<WifiBus>,
chip: ChipVariant,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let set_vendor_info: u8 = if matches!(chip, ChipVariant::Aic8800D80 | ChipVariant::Aic8800D80X2)
{
0x20
} else {
0x00
};
let param: [u8; 4] = [0x01, 0x00, set_vendor_info, 0x00];
send_cmd(bus, MM_SET_STACK_START_REQ, TASK_MM, ¶m, timeout_ms)
}
pub fn send_reset_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<Vec<u8>, CmdError> {
send_cmd(bus, MM_RESET_REQ, TASK_MM, &[], timeout_ms)
}
pub fn send_txpwr_idx_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<(), CmdError> {
let mut param = [0u8; 6];
param[0] = 0;
param[1] = 0;
param[2] = 0;
send_cmd(bus, MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, ¶m, timeout_ms)?;
Ok(())
}
pub fn send_txpwr_ofst_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<(), CmdError> {
let param = [0u8; 6];
send_cmd(bus, MM_SET_TXPWR_OFST_REQ, TASK_MM, ¶m, timeout_ms)?;
Ok(())
}
pub fn send_rf_calib_req(
bus: &Arc<WifiBus>,
chip: ChipVariant,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let mut param = [0u8; MM_SET_RF_CALIB_REQ_SIZE];
let (cal_24g, cal_5g) = match chip {
ChipVariant::Aic8800D80 | ChipVariant::Aic8800D80X2 => (0x0f8fu32, 0x0f0fu32),
_ => (AIC8801_RF_CAL_CFG_24G, AIC8801_RF_CAL_CFG_5G),
};
param[0..4].copy_from_slice(&cal_24g.to_le_bytes());
param[4..8].copy_from_slice(&cal_5g.to_le_bytes());
param[8..12].copy_from_slice(&AIC8801_RF_PARAM_ALPHA.to_le_bytes());
param[16..20].copy_from_slice(&AIC8801_RF_BT_CALIB_PARAM.to_le_bytes());
send_cmd(bus, MM_SET_RF_CALIB_REQ, TASK_MM, ¶m, timeout_ms)
}
pub fn send_me_config_req(
bus: &Arc<WifiBus>,
chip: ChipVariant,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let mut param = vec![0u8; ME_CONFIG_REQ_SIZE];
param[0..2].copy_from_slice(&HT_CAPA_INFO_LDPC.to_le_bytes());
param[2] = HT_AMPDU_FACTOR_MAX | (HT_AMPDU_DENSITY_MAX << 2);
param[3] = HT_MCS_RATE_1SS;
let tail = MAC_HT_CAPABILITY_SIZE + MAC_VHT_CAPABILITY_SIZE + MAC_HE_CAPABILITY_SIZE; let phy_bw = if matches!(chip, ChipVariant::Aic8800D80 | ChipVariant::Aic8800D80X2) {
PHY_CHNL_BW_80
} else {
PHY_CHNL_BW_20
};
param[tail + ME_CONFIG_TAIL_PHY_BW_OFF] = phy_bw;
param[tail + ME_CONFIG_TAIL_HT_SUPP_OFF] = 1;
send_cmd(bus, ME_CONFIG_REQ, TASK_ME, ¶m, timeout_ms)
}
pub fn send_me_chan_config_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<Vec<u8>, CmdError> {
let total_size = ME_CHAN_MAX_2G4 * MAC_CHAN_DEF_SIZE + ME_CHAN_MAX_5G * MAC_CHAN_DEF_SIZE + 2;
let mut param = vec![0u8; total_size];
let chan_cnt = CHAN_2G4_FREQS.len().min(ME_CHAN_MAX_2G4);
for i in 0..chan_cnt {
let off = i * MAC_CHAN_DEF_SIZE;
param[off..off + 2].copy_from_slice(&CHAN_2G4_FREQS[i].to_le_bytes());
param[off + 2] = 0; param[off + 3] = 0; param[off + 4] = ME_CHAN_TX_POWER_DEFAULT as u8;
}
let cnt_offset = ME_CHAN_MAX_2G4 * MAC_CHAN_DEF_SIZE + ME_CHAN_MAX_5G * MAC_CHAN_DEF_SIZE;
param[cnt_offset] = chan_cnt as u8;
send_cmd(bus, ME_CHAN_CONFIG_REQ, TASK_ME, ¶m, timeout_ms)
}
pub fn send_mm_start_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<Vec<u8>, CmdError> {
let mut param = [0u8; MM_START_REQ_SIZE];
param[MM_START_PHY_CFG_SIZE..MM_START_PHY_CFG_SIZE + 4]
.copy_from_slice(&MM_START_UAPSD_TIMEOUT_MS.to_le_bytes());
param[MM_START_PHY_CFG_SIZE + 4..MM_START_PHY_CFG_SIZE + 6]
.copy_from_slice(&MM_START_LP_CLK_ACCURACY_PPM.to_le_bytes());
send_cmd(bus, MM_START_REQ, TASK_MM, ¶m, timeout_ms)
}
pub fn send_mm_set_filter_req(
bus: &Arc<WifiBus>,
filter: u32,
timeout_ms: u64,
) -> Result<(), CmdError> {
let mut param = [0u8; 4];
param[0..4].copy_from_slice(&filter.to_le_bytes());
send_cmd(bus, MM_SET_FILTER_REQ, TASK_MM, ¶m, timeout_ms)?;
Ok(())
}
pub fn send_mm_set_idle_req(
bus: &Arc<WifiBus>,
idle: bool,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let param = [if idle { 1u8 } else { 0u8 }];
send_cmd(bus, MM_SET_IDLE_REQ, TASK_MM, ¶m, timeout_ms)
}
pub fn send_set_control_port_req(
bus: &Arc<WifiBus>,
sta_idx: u8,
open: bool,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let param = [sta_idx, if open { 1 } else { 0 }];
send_cmd(bus, ME_SET_CONTROL_PORT_REQ, TASK_ME, ¶m, timeout_ms)
}
pub fn send_me_set_ps_mode_req(
bus: &Arc<WifiBus>,
ps_mode: u8,
timeout_ms: u64,
) -> Result<Vec<u8>, CmdError> {
let param = [ps_mode];
send_cmd(bus, ME_SET_PS_MODE_REQ, TASK_ME, ¶m, timeout_ms)
}
pub fn send_get_mac_addr_req(bus: &Arc<WifiBus>, timeout_ms: u64) -> Result<[u8; 6], CmdError> {
let param = MM_GET_MAC_ADDR_REQ_GET.to_le_bytes();
let rsp = send_cmd(bus, MM_GET_MAC_ADDR_REQ, TASK_MM, ¶m, timeout_ms)?;
if rsp.len() >= 6 {
let mut mac = [0u8; 6];
mac.copy_from_slice(&rsp[..6]);
Ok(mac)
} else {
log::error!(
"[cmd_mgr] MM_GET_MAC_ADDR_CFM too short: {} bytes",
rsp.len()
);
Err(CmdError::InvalidResponse)
}
}