diff --git a/src/device.rs b/src/device.rs index c66a13b7..68de5be5 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,9 +1,24 @@ -use std::{sync::atomic::Ordering, time::Duration}; +use std::{ + sync::{atomic::Ordering, Mutex}, + time::Duration, +}; use crate::{muxer::STARTED, Errors, Res}; -use log::{error, info}; +use log::{error, info, warn}; +use once_cell::sync::Lazy; use rusty_libimobiledevice::idevice::{self, Device}; +/// Cached UDID from the pairing file — fallback when C library can't detect device (iOS 26+) +pub static PAIRING_UDID: Lazy>> = Lazy::new(|| Mutex::new(None)); + +/// Called by muxer after parsing the pairing file to cache the UDID +pub fn set_pairing_udid(udid: String) { + if let Ok(mut cache) = PAIRING_UDID.lock() { + *cache = Some(udid); + info!("Cached pairing UDID for fallback"); + } +} + #[swift_bridge::bridge] mod ffi { #[swift_bridge(already_declared, swift_name = "MinimuxerError")] @@ -22,6 +37,10 @@ mod ffi { /// Returns an error once the timeout expires /// /// Timeout is 5 seconds, 250 ms sleep between attempts +/// +/// On iOS 26+, the C library may fail to detect the device even when the +/// pairing file is valid. This function falls back to constructing a Device +/// from the cached pairing UDID when the C library returns no devices. pub fn fetch_first_device() -> Res { const TIMEOUT: u16 = 5000; const SLEEP: u16 = 250; @@ -30,16 +49,28 @@ pub fn fetch_first_device() -> Res { loop { match idevice::get_first_device() { Ok(d) => return Ok(d), - Err(e) => { + Err(_e) => { t -= SLEEP; if t == 0 { - error!("Couldn't fetch first device: {:?}", e); - return Err(Errors::NoDevice); + break; } } } std::thread::sleep(Duration::from_millis(SLEEP.into())); } + + // C library failed — try the pairing file UDID fallback (iOS 26 fix) + warn!("C library could not find device, trying pairing file UDID fallback"); + if let Ok(cache) = PAIRING_UDID.lock() { + if let Some(ref udid) = *cache { + info!("Using cached pairing UDID: {}", udid); + let ip = Some(std::net::IpAddr::V4(std::net::Ipv4Addr::new(10, 7, 0, 1))); + return Ok(Device::new(udid.clone(), ip, 420)); + } + } + + error!("No device found via C library or pairing file fallback"); + Err(Errors::NoDevice) } /// Tests if the device is on and listening without jumping through hoops diff --git a/src/muxer.rs b/src/muxer.rs index e972a8ce..b875eabb 100644 --- a/src/muxer.rs +++ b/src/muxer.rs @@ -335,9 +335,13 @@ pub fn startWithLogger( } }; - match pairing_file.get("UDID") { + let udid_str = match pairing_file.get("UDID") { Some(u) => match u.as_string() { - Some(_) => {} + Some(s) => { + // Cache UDID for iOS 26 fallback + crate::device::set_pairing_udid(s.to_string()); + s.to_string() + } None => { error!("Couldn't convert UDID to string"); return Err(Errors::PairingFile); @@ -349,6 +353,7 @@ pub fn startWithLogger( } }; + info!("Pairing UDID cached: {}", udid_str); listen(pairing_file); start_beat();