From 95fcf3e3a194336c59c5c78ae4ccf7ab1dc13628 Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Sun, 19 Jul 2026 20:44:20 -0400 Subject: [PATCH] cecd: recover CEC and guard inactive source --- cecd/src/device.rs | 77 +++++++++++++++++++++++------------------ cecd/src/testing/mod.rs | 2 +- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/cecd/src/device.rs b/cecd/src/device.rs index b591688..2a4ed9b 100644 --- a/cecd/src/device.rs +++ b/cecd/src/device.rs @@ -33,7 +33,10 @@ use crate::{ArcDevice, AsyncDevicePoller}; const LOG_ADDR_RETRIES: i32 = 20; const WAKE_TRIES: i32 = 2; +const ACTIVE_SOURCE_DELAY: Duration = Duration::from_millis(100); const WAKE_DELAY: Duration = Duration::from_millis(1000); +const RESUME_TRIES: i32 = 5; +const RESUME_DELAY: Duration = Duration::from_millis(1000); const REPLY_RETRIES: i32 = 4; type CallbackFut<'a> = Box> + Send + 'a>; @@ -465,6 +468,7 @@ impl DeviceTask { async fn wake(&mut self) -> Result<()> { self.device.lock().await.wake(false, false).await?; self.awaiting_wake = true; + sleep(ACTIVE_SOURCE_DELAY).await; for _ in 0..WAKE_TRIES { let result = self.device.lock().await.set_active_source(None).await; match result { @@ -505,6 +509,38 @@ impl DeviceTask { Ok(()) } + async fn recover_after_resume(&mut self) { + for attempt in 1..=RESUME_TRIES { + match self + .system + .lock() + .await + .configure_dev(self.device.clone(), self.connector.as_ref()) + .await + { + Ok(connector) => { + self.connector = connector; + if self + .device + .lock() + .await + .poll_address(LogicalAddress::Tv) + .await + .is_ok() + { + return; + } + } + Err(err) => { + warn!("Failed to recover device after resume (attempt {attempt}): {err}") + } + } + if attempt < RESUME_TRIES { + sleep(RESUME_DELAY).await; + } + } + } + async fn handle_system_message(&mut self, message: SystemMessage) -> Result<()> { match message { SystemMessage::Wake { @@ -512,6 +548,7 @@ impl DeviceTask { from_standby, } => { if from_standby { + self.recover_after_resume().await; let device = self.device.clone(); self.with_logical_address(Box::new(|_| { Box::new(async move { @@ -550,10 +587,10 @@ impl DeviceTask { } SystemMessage::Standby { standby_tv, force } => { let device = self.device.lock().await; - let address = device.get_physical_address().await?; if force || (self.active && standby_tv) { device.standby(LogicalAddress::Tv).await?; - } else { + } else if self.active { + let address = device.get_physical_address().await?; device .tx_message(&Message::InactiveSource { address }, LogicalAddress::Tv) .await?; @@ -987,15 +1024,6 @@ mod test { .await .unwrap(); } - assert_eq!( - rx_message(&test.dev).await.unwrap(), - ( - Message::InactiveSource { - address: PhysicalAddress::from(0x1000) - }, - LogicalAddress::Tv - ) - ); assert!(rx_message(&test.dev).await.is_none()); } @@ -1798,7 +1826,7 @@ mod test { } #[tokio::test] - async fn test_wake_from_standby_deferred() { + async fn test_wake_from_standby_reconfigures() { let test = setup_basic_test().await.unwrap(); let interface: InterfaceRef = test @@ -1832,27 +1860,6 @@ mod test { .unwrap(); } - assert_eq!(rx_message(&test.dev).await, None); - - { - let dev = interface.get_mut().await; - dev.device - .lock() - .await - .set_logical_addresses(&[LogicalAddressType::Playback]) - .await - .unwrap(); - assert_eq!( - dev.device - .lock() - .await - .get_logical_addresses() - .await - .unwrap(), - &[LogicalAddress::PlaybackDevice1] - ); - } - assert_eq!( rx_message(&test.dev).await.unwrap(), ( @@ -1862,6 +1869,10 @@ mod test { LogicalAddress::Broadcast ) ); + assert_eq!( + test.dev.lock().await.get_logical_addresses().await.unwrap(), + &[LogicalAddress::PlaybackDevice1] + ); } #[test] diff --git a/cecd/src/testing/mod.rs b/cecd/src/testing/mod.rs index af767d7..cd3aaad 100644 --- a/cecd/src/testing/mod.rs +++ b/cecd/src/testing/mod.rs @@ -343,7 +343,7 @@ impl AsyncDevice { } pub async fn poll_address(&self, _destination: LogicalAddress) -> Result<()> { - todo!(); + Ok(()) } pub async fn handle_status(&self, status: PollStatus) -> Result> {