fix(openwrt): enable radio0 and run wifi up before scanning
On a freshly-flashed OpenWrt router, radio0 is disabled by default so iw dev returns empty. Detect the PHY via /sys/class/ieee80211/, enable radio0, run `wifi up`, then poll up to 8s for netifd to create the virtual interface before handing it to iwinfo scan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ddc839400a
commit
9dc2343b60
@ -73,6 +73,7 @@ pub(super) fn sanitize_error_message(msg: &str) -> String {
|
||||
"apk update failed",
|
||||
"No wireless interface",
|
||||
"No wireless radio",
|
||||
"WiFi radio enabled but",
|
||||
"Missing required field",
|
||||
];
|
||||
for prefix in &user_facing_prefixes {
|
||||
|
||||
@ -19,22 +19,33 @@ pub fn scan_networks(router: &Router) -> Result<Vec<ScannedNetwork>> {
|
||||
}
|
||||
|
||||
fn find_wireless_iface(router: &Router) -> Result<String> {
|
||||
// `iw dev` works on any mac80211 system and handles new-style interface names
|
||||
// (phy0-ap0, phy0-sta0, etc.) used by OpenWrt 25.x mt76 drivers.
|
||||
// Fast path: interface already up (radio was previously enabled)
|
||||
let (out, _) = router.run("iw dev 2>/dev/null | awk '/Interface/{print $2}' | head -1")?;
|
||||
let iface = out.trim().to_string();
|
||||
if !iface.is_empty() {
|
||||
return Ok(iface);
|
||||
if !out.trim().is_empty() {
|
||||
return Ok(out.trim().to_string());
|
||||
}
|
||||
// Fallback: any entry in /sys/class/net with a wireless subdir
|
||||
let (out2, _) = router.run(
|
||||
"for i in /sys/class/net/*/wireless; do [ -d \"$i\" ] && basename $(dirname $i) && break; done 2>/dev/null",
|
||||
)?;
|
||||
let iface2 = out2.trim().to_string();
|
||||
if !iface2.is_empty() {
|
||||
return Ok(iface2);
|
||||
|
||||
// No interface yet — common on a freshly-flashed OpenWrt where radio0 is
|
||||
// disabled by default. Verify the radio PHY exists at all.
|
||||
let (phy_out, _) = router.run("ls /sys/class/ieee80211/ 2>/dev/null | head -1")?;
|
||||
if phy_out.trim().is_empty() {
|
||||
anyhow::bail!("No wireless radio found on this router");
|
||||
}
|
||||
anyhow::bail!("No wireless interface found on this router")
|
||||
|
||||
// Enable radio0 and bring wifi up so netifd creates the virtual interface.
|
||||
tracing::info!("[{}] Radio present but no interface — enabling radio0 and running wifi up", router.host);
|
||||
router.run_ok("uci set wireless.radio0.disabled=0 && uci commit wireless && wifi up 2>&1")?;
|
||||
|
||||
// Wait up to 8s for netifd to create the interface (it's asynchronous)
|
||||
for _ in 0..8 {
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
let (out2, _) = router.run("iw dev 2>/dev/null | awk '/Interface/{print $2}' | head -1")?;
|
||||
if !out2.trim().is_empty() {
|
||||
return Ok(out2.trim().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::bail!("WiFi radio enabled but no interface appeared — check OpenWrt wireless config")
|
||||
}
|
||||
|
||||
fn parse_iwinfo_scan(output: &str) -> Result<Vec<ScannedNetwork>> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user