fix: resolve display stuck after disconnect and radio task deadlock

- Set disconnected flag on DisplayCommand::Reset to block stale radio
  status updates from re-rendering dashboard over splash screen
- Send StopRx to radio when USB DTR drops so radio stops generating
  packets after host disconnects
- Use try_send for unsolicited responses (RxPacket, error recovery,
  StopRx Ok) to prevent radio task deadlock on full response channel
- Fall back to LED-only event loop when display init fails instead of
  returning early and orphaning the LED

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
swaitsandClaude Opus 4.6 committed 2026-04-07 19:49:15 -06:00
1 parent 0c9094dcbd
commit de38278d7b
6 files changed
+114 -12

No files matched your search

+11 -6
View File
@@ -113,19 +113,22 @@ pub async fn radio_task(
// copy_len <= MAX_PAYLOAD == Vec capacity, so this cannot fail.
let _ = payload.extend_from_slice(&rx_buf[..copy_len]);
responses
.send(Response::RxPacket {
if responses
.try_send(Response::RxPacket {
rssi: pkt_status.rssi,
snr: pkt_status.snr,
payload,
})
.await;
.is_err()
{
warn!("RX packet dropped: response channel full");
}
if let Err(e) = start_rx(&mut lora, &cfg).await {
warn!("restart RX failed: {}", e);
state.state = RadioState::Idle;
status.sender().send(state.clone());
responses.send(Response::Error(ErrorCode::RadioBusy)).await;
let _ = responses.try_send(Response::Error(ErrorCode::RadioBusy));
}
}
Err(e) => {
@@ -133,7 +136,7 @@ pub async fn radio_task(
if start_rx(&mut lora, &cfg).await.is_err() {
state.state = RadioState::Idle;
status.sender().send(state.clone());
responses.send(Response::Error(ErrorCode::RadioBusy)).await;
let _ = responses.try_send(Response::Error(ErrorCode::RadioBusy));
}
}
},
@@ -210,7 +213,9 @@ async fn handle_cmd(
let _ = lora.enter_standby().await;
state.state = RadioState::Idle;
status.sender().send(state.clone());
responses.send(Response::Ok).await;
// try_send: StopRx may be sent internally on USB disconnect
// when the host isn't draining responses.
let _ = responses.try_send(Response::Ok);
}
Command::DisplayOn | Command::DisplayOff | Command::GetMac => {}
Command::Transmit { config, payload } => {