Skip to content

Commit 0c4032b

Browse files
committed
Merge branch 'quick-reconnect'
2 parents f3a5527 + 7842b75 commit 0c4032b

File tree

5 files changed

+152
-55
lines changed

5 files changed

+152
-55
lines changed

src/bluetooth.rs

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::btle;
2+
use crate::config::Action;
23
use crate::config::WifiConfig;
34
use crate::config::IDENTITY_NAME;
45
use crate::config_types::BluetoothAddressList;
@@ -11,10 +12,13 @@ use bluer::{
1112
};
1213
use futures::StreamExt;
1314
use simplelog::*;
15+
use std::sync::atomic::AtomicBool;
16+
use std::sync::atomic::Ordering;
1417
use std::sync::Arc;
1518
use std::time::{Duration, Instant};
1619
use tokio::io::AsyncReadExt;
1720
use tokio::io::AsyncWriteExt;
21+
use tokio::sync::broadcast::Receiver as BroadcastReceiver;
1822
use tokio::sync::Notify;
1923
use tokio::time::timeout;
2024

@@ -514,25 +518,12 @@ impl Bluetooth {
514518
Ok(())
515519
}
516520

517-
pub async fn aa_handshake(
518-
&mut self,
519-
dongle_mode: bool,
520-
connect: BluetoothAddressList,
521-
wifi_config: WifiConfig,
522-
tcp_start: Arc<Notify>,
523-
bt_timeout: Duration,
524-
stopped: bool,
525-
) -> Result<()> {
521+
async fn send_params(wifi_config: WifiConfig, stream: &mut Stream) -> Result<()> {
526522
use WifiInfoResponse::WifiInfoResponse;
527523
use WifiStartRequest::WifiStartRequest;
528524
let mut stage = 1;
529525
let mut started;
530526

531-
// Use the provided session and adapter instead of creating new ones
532-
let (address, mut stream) = self
533-
.get_aa_profile_connection(dongle_mode, connect, bt_timeout, stopped)
534-
.await?;
535-
536527
info!("{} 📲 Sending parameters via bluetooth to phone...", NAME);
537528
let mut start_req = WifiStartRequest::new();
538529
info!(
@@ -541,10 +532,10 @@ impl Bluetooth {
541532
);
542533
start_req.set_ip_address(wifi_config.ip_addr);
543534
start_req.set_port(wifi_config.port);
544-
send_message(&mut stream, stage, MessageId::WifiStartRequest, start_req).await?;
535+
send_message(stream, stage, MessageId::WifiStartRequest, start_req).await?;
545536
stage += 1;
546537
started = Instant::now();
547-
read_message(&mut stream, stage, MessageId::WifiInfoRequest, started).await?;
538+
read_message(stream, stage, MessageId::WifiInfoRequest, started).await?;
548539

549540
let mut info = WifiInfoResponse::new();
550541
info!(
@@ -557,19 +548,81 @@ impl Bluetooth {
557548
info.set_security_mode(SecurityMode::WPA2_PERSONAL);
558549
info.set_access_point_type(AccessPointType::DYNAMIC);
559550
stage += 1;
560-
send_message(&mut stream, stage, MessageId::WifiInfoResponse, info).await?;
551+
send_message(stream, stage, MessageId::WifiInfoResponse, info).await?;
561552
stage += 1;
562553
started = Instant::now();
563-
read_message(&mut stream, stage, MessageId::WifiStartResponse, started).await?;
554+
read_message(stream, stage, MessageId::WifiStartResponse, started).await?;
564555
stage += 1;
565556
started = Instant::now();
566-
read_message(&mut stream, stage, MessageId::WifiConnectStatus, started).await?;
557+
read_message(stream, stage, MessageId::WifiConnectStatus, started).await?;
558+
559+
Ok(())
560+
}
561+
562+
pub async fn aa_handshake(
563+
&mut self,
564+
dongle_mode: bool,
565+
connect: BluetoothAddressList,
566+
wifi_config: WifiConfig,
567+
tcp_start: Arc<Notify>,
568+
bt_timeout: Duration,
569+
stopped: bool,
570+
quick_reconnect: bool,
571+
mut need_restart: BroadcastReceiver<Option<Action>>,
572+
profile_connected: Arc<AtomicBool>,
573+
) -> Result<()> {
574+
// Use the provided session and adapter instead of creating new ones
575+
let (address, mut stream) = self
576+
.get_aa_profile_connection(dongle_mode, connect, bt_timeout, stopped)
577+
.await?;
578+
Self::send_params(wifi_config.clone(), &mut stream).await?;
567579
tcp_start.notify_one();
568580

569-
// handshake complete, now disconnect the device so it should
570-
// connect to real HU for calls
571-
let device = self.adapter.device(bluer::Address(*address))?;
572-
let _ = device.disconnect().await;
581+
if quick_reconnect {
582+
// keep the bluetooth profile connection alive
583+
// and use it in a loop to restart handshake when necessary
584+
let adapter_cloned = self.adapter.clone();
585+
let _ = Some(tokio::spawn(async move {
586+
profile_connected.store(true, Ordering::Relaxed);
587+
loop {
588+
// wait for restart notification from main loop (eg when HU disconnected)
589+
let action = need_restart.recv().await;
590+
if let Ok(Some(action)) = action {
591+
// check if we need to stop now
592+
if action == Action::Stop {
593+
// disconnect and break
594+
if let Ok(device) = adapter_cloned.device(bluer::Address(*address)) {
595+
let _ = device.disconnect().await;
596+
}
597+
break;
598+
}
599+
}
600+
601+
// now restart handshake with the same params
602+
match Self::send_params(wifi_config.clone(), &mut stream).await {
603+
Ok(_) => {
604+
tcp_start.notify_one();
605+
continue;
606+
}
607+
Err(e) => {
608+
error!(
609+
"{} handshake restart error: {}, doing full restart!",
610+
NAME, e
611+
);
612+
// this break should end this task
613+
break;
614+
}
615+
}
616+
}
617+
// we are now disconnected, redo bluetooth connection
618+
profile_connected.store(false, Ordering::Relaxed);
619+
}));
620+
} else {
621+
// handshake complete, now disconnect the device so it should
622+
// connect to real HU for calls
623+
let device = self.adapter.device(bluer::Address(*address))?;
624+
let _ = device.disconnect().await;
625+
}
573626

574627
info!("{} 🚀 Bluetooth launch sequence completed", NAME);
575628

src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub struct AppConfig {
8484
pub hexdump_level: HexdumpLevel,
8585
pub disable_console_debug: bool,
8686
pub legacy: bool,
87+
pub quick_reconnect: bool,
8788
pub connect: BluetoothAddressList,
8889
pub logfile: PathBuf,
8990
pub stats_interval: u16,
@@ -224,6 +225,7 @@ impl Default for AppConfig {
224225
hexdump_level: HexdumpLevel::Disabled,
225226
disable_console_debug: false,
226227
legacy: true,
228+
quick_reconnect: false,
227229
connect: BluetoothAddressList::default(),
228230
logfile: "/var/log/aa-proxy-rs.log".into(),
229231
stats_interval: 0,
@@ -315,6 +317,7 @@ impl AppConfig {
315317
doc["hexdump_level"] = value(format!("{:?}", self.hexdump_level));
316318
doc["disable_console_debug"] = value(self.disable_console_debug);
317319
doc["legacy"] = value(self.legacy);
320+
doc["quick_reconnect"] = value(self.quick_reconnect);
318321
doc["connect"] = value(self.connect.to_string());
319322
doc["logfile"] = value(self.logfile.display().to_string());
320323
doc["stats_interval"] = value(self.stats_interval as i64);

src/io_uring.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use simplelog::*;
44
use std::cell::RefCell;
55
use std::marker::PhantomData;
66
use std::rc::Rc;
7-
use std::sync::atomic::{AtomicUsize, Ordering};
7+
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
88
use std::sync::Arc;
99
use std::time::{Duration, Instant};
1010
use tokio::io::copy_bidirectional;
1111
use tokio::net::TcpStream as TokioTcpStream;
12+
use tokio::sync::broadcast::Sender as BroadcastSender;
1213
use tokio::sync::mpsc::{Receiver, Sender};
1314
use tokio::sync::{mpsc, Mutex, Notify};
1415
use tokio::task::JoinHandle;
@@ -284,11 +285,12 @@ async fn tcp_wait_for_connection(listener: &mut TcpListener) -> Result<TcpStream
284285
}
285286

286287
pub async fn io_loop(
287-
need_restart: Arc<Notify>,
288+
need_restart: BroadcastSender<Option<Action>>,
288289
tcp_start: Arc<Notify>,
289290
config: SharedConfig,
290291
tx: Arc<Mutex<Option<Sender<Packet>>>>,
291292
sensor_channel: Arc<Mutex<Option<u8>>>,
293+
profile_connected: Arc<AtomicBool>,
292294
) -> Result<()> {
293295
let shared_config = config.clone();
294296
#[allow(unused_variables)]
@@ -331,7 +333,9 @@ pub async fn io_loop(
331333
Err(e) => {
332334
error!("{} 🔴 Enabling Android Auto: {}", NAME, e);
333335
// notify main loop to restart
334-
need_restart.notify_one();
336+
if !profile_connected.load(Ordering::Relaxed) {
337+
let _ = need_restart.send(None);
338+
}
335339
continue;
336340
}
337341
Ok(s) => {
@@ -350,7 +354,9 @@ pub async fn io_loop(
350354
md_tcp = Some(s);
351355
} else {
352356
// notify main loop to restart
353-
need_restart.notify_one();
357+
if !profile_connected.load(Ordering::Relaxed) {
358+
let _ = need_restart.send(None);
359+
}
354360
continue;
355361
}
356362
}
@@ -364,7 +370,9 @@ pub async fn io_loop(
364370
hu_tcp = Some(s);
365371
} else {
366372
// notify main loop to restart
367-
need_restart.notify_one();
373+
if !profile_connected.load(Ordering::Relaxed) {
374+
let _ = need_restart.send(None);
375+
}
368376
continue;
369377
}
370378
} else {
@@ -383,7 +391,9 @@ pub async fn io_loop(
383391
Err(e) => {
384392
error!("{} 🔴 Error opening USB accessory: {}", NAME, e);
385393
// notify main loop to restart
386-
need_restart.notify_one();
394+
if !profile_connected.load(Ordering::Relaxed) {
395+
let _ = need_restart.send(None);
396+
}
387397
continue;
388398
}
389399
}
@@ -542,8 +552,10 @@ pub async fn io_loop(
542552
NAME,
543553
format_duration(started.elapsed()).to_string()
544554
);
555+
// obtain action for passing it to broadcast sender
556+
let action = shared_config.read().await.action_requested.clone();
545557
// stream(s) closed, notify main loop to restart
546-
need_restart.notify_one();
558+
let _ = need_restart.send(action);
547559
}
548560

549561
#[allow(unreachable_code)]

0 commit comments

Comments
 (0)