diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs b/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs index a2dc5e06ff..cd10ca8d61 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/mld.rs @@ -342,6 +342,158 @@ impl MldState { pub fn rx_frame_count(&self) -> u32 { self.rx_frames.load(Ordering::Relaxed) } + + // ── mac80211 callback implementations (Linux mld/mac80211.c) ──── + // + // These mirror the Linux iwl_mld_mac80211_* callbacks. Each one + // translates a mac80211 request into firmware command state changes. + // The actual firmware command bytes are built and sent by the + // transport layer (linux_port.c) based on the MldState. + + pub fn callback_start(&mut self) -> Result<(), MldError> { + self.firmware_init(); + Ok(()) + } + + pub fn callback_stop(&mut self) -> Result<(), MldError> { + self.fw_running = false; + self.scan.running = false; + for txq in &mut self.txqs { + txq.allocated = false; + txq.stop_full = false; + } + Ok(()) + } + + pub fn callback_config(&mut self, changed: u32) -> Result<(), MldError> { + if changed & 0x40 != 0 { + // IEEE80211_CONF_CHANGE_CHANNEL + } + if changed & 0x10 != 0 { + // IEEE80211_CONF_CHANGE_PS + } + Ok(()) + } + + pub fn callback_add_interface(&mut self, _vif_type: u32, _addr: &[u8; 6]) -> Result { + Ok(0) + } + + pub fn callback_remove_interface(&mut self, _mac_id: u8) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_bss_info_changed( + &mut self, + _mac_id: u8, + changed: u64, + ) -> Result<(), MldError> { + if changed & 0x01 != 0 { + // BSS_CHANGED_ASSOC + } + if changed & 0x02 != 0 { + // BSS_CHANGED_BSSID + } + Ok(()) + } + + pub fn callback_sta_state( + &mut self, + _sta_id: u32, + _old_state: u32, + _new_state: u32, + ) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_set_key( + &mut self, + _cmd: i32, + _sta_id: u32, + _key_idx: u8, + _cipher: u32, + _key: &[u8], + ) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_hw_scan(&mut self, params: &ScanParams) -> Result<(), MldError> { + self.start_scan(params).map_err(|_| MldError::ScanAlreadyRunning) + } + + pub fn callback_cancel_hw_scan(&mut self) { + self.stop_scan(); + } + + pub fn callback_flush(&mut self, _queues: u32, _drop: bool) -> Result<(), MldError> { + for txq in &mut self.txqs { + txq.stop_full = false; + } + Ok(()) + } + + pub fn callback_ampdu_action( + &mut self, + _action: u32, + _sta_id: u32, + _tid: u8, + ) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_add_chanctx(&mut self) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_remove_chanctx(&mut self) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_assign_vif_chanctx(&mut self, _mac_id: u8) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_unassign_vif_chanctx(&mut self, _mac_id: u8) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_reconfig_complete(&mut self) -> Result<(), MldError> { + self.fw_in_hw_restart = false; + Ok(()) + } + + pub fn callback_restart_complete(&mut self) -> Result<(), MldError> { + self.fw_in_hw_restart = false; + Ok(()) + } + + pub fn callback_wake_tx_queue(&mut self, fw_id: u16) -> Result<(), MldError> { + if (fw_id as usize) < self.txqs.len() { + self.txqs[fw_id as usize].stop_full = false; + } + Ok(()) + } + + pub fn callback_sta_pre_rcu_remove(&mut self, _sta_id: u32) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_configure_filter(&mut self, _changed: u32, _total: &mut u32) -> Result<(), MldError> { + Ok(()) + } + + pub fn callback_conf_tx(&mut self, _mac_id: u8, _ac: u8) -> Result<(), MldError> { + Ok(()) + } +} + +// ── Error type for mac80211 callbacks ───────────────────────────── + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MldError { + ScanAlreadyRunning, + NotInitialized, + InvalidArgument, } // ── Init result (Linux mld/fw.c) ────────────────────────────────── @@ -741,4 +893,58 @@ mod tests { assert_eq!(notif_kind(NOTIF_CT_KILL), "ct-kill"); assert_eq!(notif_kind(CMD_SYSTEM_STATISTICS_END), "statistics-end"); } + + #[test] + fn mac80211_callback_dispatcher() { + let mut mld = MldState::new(); + mld.firmware_init(); + + let result = mld.callback_start(); + assert!(result.is_ok()); + assert!(mld.fw_running); + + let result = mld.callback_stop(); + assert!(result.is_ok()); + + let result = mld.callback_config(0x40); + assert!(result.is_ok()); + } + + #[test] + fn mac80211_scan_callback() { + let mut mld = MldState::new(); + let params = ScanParams { + flags: SCAN_FLAG_ACTIVE, + n_ssids: 1, + active_dwell: 100, + passive_dwell: 200, + ..Default::default() + }; + let result = mld.callback_hw_scan(¶ms); + assert!(result.is_ok()); + assert!(mld.scan.running); + + mld.callback_cancel_hw_scan(); + assert!(!mld.scan.running); + } + + #[test] + fn mac80211_flush_callback() { + let mut mld = MldState::new(); + mld.firmware_init(); + let q0 = mld.alloc_txq().unwrap(); + mld.txqs[q0 as usize].stop_full = true; + let result = mld.callback_flush(0xffff, false); + assert!(result.is_ok()); + assert!(!mld.txqs[q0 as usize].stop_full); + } + + #[test] + fn mac80211_chanctx_callback() { + let mut mld = MldState::new(); + let result = mld.callback_add_chanctx(); + assert!(result.is_ok()); + let result = mld.callback_remove_chanctx(); + assert!(result.is_ok()); + } }