diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs b/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs index cd10ca8d61..eeeac7aaf6 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs @@ -496,6 +496,232 @@ pub enum MldError { InvalidArgument, } +// ── Firmware command structures (Linux fw/api/mac-cfg.h) ────────── +// +// These are #[repr(C, packed)] to match the firmware's expected byte +// layout exactly. They are the payloads sent via the transport's +// command ring (HCMD DMA) when the mac80211 callbacks fire. +// +// Reference: Linux include/net/mac80211.h + fw/api/mac-cfg.h + +// MAC_CONTEXT_CONFIG_CMD (MAC_CONF group, 0x08) +// Linux struct iwl_mac_config_cmd (VER_4) — bounded to the fields +// the driver actually sets; union variants omitted (client mode only). +#[repr(C, packed)] +#[derive(Clone, Copy)] +pub struct MacConfigCmd { + pub id_and_color: u32, + pub action: u32, + pub mac_type: u32, + pub local_mld_addr: [u8; 6], + pub reserved_for_local_mld_addr: u16, + pub filter_flags: u32, + pub nic_not_ack_enabled: u32, +} + +// MAC_CONTEXT_TYPE values (Linux fw/api/mac-cfg.h enum iwl_mac_types) +pub const MAC_TYPE_BSS: u32 = 5; +pub const MAC_TYPE_PIBSS: u32 = 6; +pub const MAC_TYPE_STA: u32 = 7; +pub const MAC_TYPE_GO: u32 = 8; +pub const MAC_TYPE_P2P_DEVICE: u32 = 10; +pub const MAC_TYPE_NAN: u32 = 12; + +// LINK_CONFIG_CMD (MAC_CONF group, 0x09) +// Linux struct iwl_link_config_cmd — bounded subset. +#[repr(C, packed)] +#[derive(Clone, Copy)] +pub struct LinkConfigCmd { + pub action: u32, + pub link_id: u32, + pub mac_id: u32, + pub phy_id: u32, + pub local_link_addr: [u8; 6], + pub reserved_for_local_link_addr: u16, + pub modify_mask: u32, + pub active: u32, + pub cck_rates: u32, + pub ofdm_rates: u32, + pub cck_short_preamble: u32, + pub short_slot: u32, + pub protection_flags: u32, + pub qos_flags: u32, +} + +pub const LINK_CTX_MODIFY_ACTIVE: u32 = 1 << 0; +pub const LINK_CTX_MODIFY_RATES_INFO: u32 = 1 << 1; +pub const LINK_CTX_MODIFY_PROTECT_FLAGS: u32 = 1 << 2; +pub const LINK_CTX_MODIFY_QOS_PARAMS: u32 = 1 << 3; + +// STA_CONFIG_CMD (MAC_CONF group, 0x0a) +// Linux struct iwl_sta_cfg_cmd (VER_3) +#[repr(C, packed)] +#[derive(Clone, Copy)] +pub struct StaCfgCmd { + pub sta_id: u32, + pub link_mask: u32, + pub peer_mld_address: [u8; 6], + pub reserved_for_peer_mld_address: u16, + pub peer_link_address: [u8; 6], + pub reserved_for_peer_link_address: u16, + pub station_type: u32, + pub assoc_id: u32, + pub beamform_flags: u32, + pub mfp: u32, + pub mimo: u32, + pub mimo_protection: u32, + pub ack_enabled: u32, + pub trig_rnd_alloc: u32, + pub tx_ampdu_spacing: u32, + pub tx_ampdu_max_size: u32, + pub sp_length: u32, + pub uapsd_acs: u32, +} + +// STA_REMOVE_CMD (MAC_CONF group, 0x0c) +#[repr(C, packed)] +#[derive(Clone, Copy, Default)] +pub struct RemoveStaCmd { + pub sta_id: u32, +} + +// AUX_STA_CMD (MAC_CONF group, 0x0b) +#[repr(C, packed)] +#[derive(Clone, Copy)] +pub struct AuxStaCmd { + pub sta_id: u32, + pub lmac_id: u32, + pub mac_addr: [u8; 6], + pub reserved_for_mac_addr: u16, +} + +// STA_DISABLE_TX_CMD (MAC_CONF group, 0x0d) +#[repr(C, packed)] +#[derive(Clone, Copy, Default)] +pub struct StaDisableTxCmd { + pub sta_id: u32, + pub disable: u32, +} + +// ── Command builder functions ───────────────────────────────────── +// +// These construct the firmware command payloads from mac80211-level +// parameters. The transport (linux_port.c) sends the resulting bytes +// over the HCMD DMA ring. + +pub fn build_mac_config_client( + mac_id: u32, + mld_addr: &[u8; 6], + mac_type: u32, + assoc_bssid: Option<[u8; 6]>, +) -> MacConfigCmd { + let filter_flags = if assoc_bssid.is_some() { + 0x0000_000f // FILT_FRAME_BSS | accept other bits + } else { + 0x0000_0000 + }; + MacConfigCmd { + id_and_color: mac_id, + action: 0x03, // ADD + CHANGE (FW_CTXT_ACTION_ADD_HW) + mac_type, + local_mld_addr: *mld_addr, + reserved_for_local_mld_addr: 0, + filter_flags, + nic_not_ack_enabled: 1, + } +} + +pub fn build_mac_config_remove(mac_id: u32) -> MacConfigCmd { + MacConfigCmd { + id_and_color: mac_id, + action: 0x02, // REMOVE (FW_CTXT_ACTION_REMOVE) + mac_type: 0, + local_mld_addr: [0; 6], + reserved_for_local_mld_addr: 0, + filter_flags: 0, + nic_not_ack_enabled: 0, + } +} + +pub fn build_link_config( + link_id: u32, + mac_id: u32, + phy_id: u32, + link_addr: &[u8; 6], + active: bool, + cck_rates: u32, + ofdm_rates: u32, +) -> LinkConfigCmd { + LinkConfigCmd { + action: 0x01, // FW_CTXT_ACTION_ADD + link_id, + mac_id, + phy_id, + local_link_addr: *link_addr, + reserved_for_local_link_addr: 0, + modify_mask: LINK_CTX_MODIFY_ACTIVE + | LINK_CTX_MODIFY_RATES_INFO + | LINK_CTX_MODIFY_PROTECT_FLAGS + | LINK_CTX_MODIFY_QOS_PARAMS, + active: if active { 1 } else { 0 }, + cck_rates, + ofdm_rates, + cck_short_preamble: 1, + short_slot: 1, + protection_flags: 0, + qos_flags: 0, + } +} + +pub fn build_sta_config( + sta_id: u32, + mld_addr: &[u8; 6], + link_addr: &[u8; 6], + aid: u16, + mfp: bool, +) -> StaCfgCmd { + StaCfgCmd { + sta_id, + link_mask: 0x01, // link 0 active + peer_mld_address: *mld_addr, + reserved_for_peer_mld_address: 0, + peer_link_address: *link_addr, + reserved_for_peer_link_address: 0, + station_type: 0, // STA_TYPE_BSS + assoc_id: aid as u32, + beamform_flags: 0, + mfp: if mfp { 1 } else { 0 }, + mimo: 0, + mimo_protection: 0, + ack_enabled: 1, + trig_rnd_alloc: 0, + tx_ampdu_spacing: 0, + tx_ampdu_max_size: 0, + sp_length: 0, + uapsd_acs: 0, + } +} + +pub fn build_remove_sta(sta_id: u32) -> RemoveStaCmd { + RemoveStaCmd { sta_id } +} + +pub fn build_disable_tx(sta_id: u32, disable: bool) -> StaDisableTxCmd { + StaDisableTxCmd { + sta_id, + disable: if disable { 1 } else { 0 }, + } +} + +pub fn build_aux_sta(sta_id: u32, mac_addr: &[u8; 6]) -> AuxStaCmd { + AuxStaCmd { + sta_id, + lmac_id: 0, + mac_addr: *mac_addr, + reserved_for_mac_addr: 0, + } +} + // ── Init result (Linux mld/fw.c) ────────────────────────────────── #[derive(Clone, Copy, Default)]