11use crate :: btle;
2+ use crate :: config:: Action ;
23use crate :: config:: WifiConfig ;
34use crate :: config:: IDENTITY_NAME ;
45use crate :: config_types:: BluetoothAddressList ;
@@ -11,10 +12,13 @@ use bluer::{
1112} ;
1213use futures:: StreamExt ;
1314use simplelog:: * ;
15+ use std:: sync:: atomic:: AtomicBool ;
16+ use std:: sync:: atomic:: Ordering ;
1417use std:: sync:: Arc ;
1518use std:: time:: { Duration , Instant } ;
1619use tokio:: io:: AsyncReadExt ;
1720use tokio:: io:: AsyncWriteExt ;
21+ use tokio:: sync:: broadcast:: Receiver as BroadcastReceiver ;
1822use tokio:: sync:: Notify ;
1923use 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
0 commit comments