• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::btif::{BluetoothInterface, RawAddress, ToggleableProfile, Uuid};
2 use crate::topstack::get_dispatchers;
3 
4 use std::fmt::{Debug, Formatter};
5 use std::sync::{Arc, Mutex};
6 use topshim_macros::{cb_variant, log_args, profile_enabled_or};
7 
8 use log::warn;
9 
10 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
11 pub mod ffi {
12     unsafe extern "C++" {
13         include!("types/raw_address.h");
14         include!("types/bluetooth/uuid.h");
15         #[namespace = ""]
16         type RawAddress = crate::btif::RawAddress;
17         #[namespace = "bluetooth"]
18         type Uuid = crate::btif::Uuid;
19     }
20 
21     #[derive(Debug, Copy, Clone)]
22     pub enum BtCsisConnectionState {
23         Disconnected = 0,
24         Connecting,
25         Connected,
26         Disconnecting,
27     }
28 
29     #[derive(Debug, Copy, Clone)]
30     pub enum BtCsisGroupLockStatus {
31         Success = 0,
32         FailedInvalidGroup,
33         FailedGroupEmpty,
34         FailedGroupNotConnected,
35         FailedLockedByOther,
36         FailedOtherReason,
37         LockedGroupMemberLost,
38     }
39 
40     unsafe extern "C++" {
41         include!("csis/csis_shim.h");
42 
43         type CsisClientIntf;
44 
GetCsisClientProfile(btif: *const u8) -> UniquePtr<CsisClientIntf>45         unsafe fn GetCsisClientProfile(btif: *const u8) -> UniquePtr<CsisClientIntf>;
46 
init(self: Pin<&mut CsisClientIntf>)47         fn init(self: Pin<&mut CsisClientIntf>);
connect(self: Pin<&mut CsisClientIntf>, addr: RawAddress)48         fn connect(self: Pin<&mut CsisClientIntf>, addr: RawAddress);
disconnect(self: Pin<&mut CsisClientIntf>, addr: RawAddress)49         fn disconnect(self: Pin<&mut CsisClientIntf>, addr: RawAddress);
lock_group(self: Pin<&mut CsisClientIntf>, group_id: i32, lock: bool)50         fn lock_group(self: Pin<&mut CsisClientIntf>, group_id: i32, lock: bool);
remove_device(self: Pin<&mut CsisClientIntf>, addr: RawAddress)51         fn remove_device(self: Pin<&mut CsisClientIntf>, addr: RawAddress);
cleanup(self: Pin<&mut CsisClientIntf>)52         fn cleanup(self: Pin<&mut CsisClientIntf>);
53     }
54 
55     extern "Rust" {
csis_connection_state_callback(addr: RawAddress, state: BtCsisConnectionState)56         fn csis_connection_state_callback(addr: RawAddress, state: BtCsisConnectionState);
csis_device_available_callback( addr: RawAddress, group_id: i32, group_size: i32, rank: i32, uuid: Uuid, )57         fn csis_device_available_callback(
58             addr: RawAddress,
59             group_id: i32,
60             group_size: i32,
61             rank: i32,
62             uuid: Uuid,
63         );
csis_set_member_available_callback(addr: RawAddress, group_id: i32)64         fn csis_set_member_available_callback(addr: RawAddress, group_id: i32);
csis_group_lock_changed_callback( group_id: i32, locked: bool, status: BtCsisGroupLockStatus, )65         fn csis_group_lock_changed_callback(
66             group_id: i32,
67             locked: bool,
68             status: BtCsisGroupLockStatus,
69         );
70     }
71 }
72 
73 pub type BtCsisConnectionState = ffi::BtCsisConnectionState;
74 pub type BtCsisGroupLockStatus = ffi::BtCsisGroupLockStatus;
75 
76 #[derive(Debug)]
77 pub enum CsisClientCallbacks {
78     ConnectionState(RawAddress, BtCsisConnectionState),
79     DeviceAvailable(RawAddress, i32, i32, i32, Uuid),
80     SetMemberAvailable(RawAddress, i32),
81     GroupLockChanged(i32, bool, BtCsisGroupLockStatus),
82 }
83 
84 pub struct CsisClientCallbacksDispatcher {
85     pub dispatch: Box<dyn Fn(CsisClientCallbacks) + Send>,
86 }
87 
88 impl Debug for CsisClientCallbacksDispatcher {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error>89     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
90         write!(f, "CsisClientCallbacksDispatcher {{}}")
91     }
92 }
93 
94 type CsisClientCb = Arc<Mutex<CsisClientCallbacksDispatcher>>;
95 
96 cb_variant!(CsisClientCb,
97             csis_connection_state_callback -> CsisClientCallbacks::ConnectionState,
98             RawAddress, BtCsisConnectionState);
99 
100 cb_variant!(CsisClientCb,
101             csis_device_available_callback -> CsisClientCallbacks::DeviceAvailable,
102             RawAddress, i32, i32, i32, Uuid);
103 
104 cb_variant!(CsisClientCb,
105             csis_set_member_available_callback -> CsisClientCallbacks::SetMemberAvailable,
106             RawAddress, i32);
107 
108 cb_variant!(CsisClientCb,
109             csis_group_lock_changed_callback -> CsisClientCallbacks::GroupLockChanged,
110             i32, bool, BtCsisGroupLockStatus);
111 
112 pub struct CsisClient {
113     internal: cxx::UniquePtr<ffi::CsisClientIntf>,
114     is_init: bool,
115     is_enabled: bool,
116 }
117 
118 // For *const u8 opaque btif
119 // SAFETY: `CsisClientIntf` is thread-safe to make calls from.
120 unsafe impl Send for CsisClient {}
121 
122 impl ToggleableProfile for CsisClient {
is_enabled(&self) -> bool123     fn is_enabled(&self) -> bool {
124         self.is_enabled
125     }
126 
enable(&mut self) -> bool127     fn enable(&mut self) -> bool {
128         if self.is_enabled {
129             warn!("CsisClient is already enabled.");
130             return false;
131         }
132 
133         self.internal.pin_mut().init();
134         self.is_enabled = true;
135         true
136     }
137 
138     #[profile_enabled_or(false)]
disable(&mut self) -> bool139     fn disable(&mut self) -> bool {
140         if !self.is_enabled {
141             warn!("CsisClient is already disabled.");
142             return false;
143         }
144 
145         self.internal.pin_mut().cleanup();
146         self.is_enabled = false;
147         true
148     }
149 }
150 
151 impl CsisClient {
152     #[log_args]
new(intf: &BluetoothInterface) -> CsisClient153     pub fn new(intf: &BluetoothInterface) -> CsisClient {
154         // SAFETY: `intf.as_raw_ptr()` is a valid pointer to a `BluetoothInterface`
155         let csis_if: cxx::UniquePtr<ffi::CsisClientIntf> =
156             unsafe { ffi::GetCsisClientProfile(intf.as_raw_ptr()) };
157 
158         CsisClient { internal: csis_if, is_init: false, is_enabled: false }
159     }
160 
161     #[log_args]
is_initialized(&self) -> bool162     pub fn is_initialized(&self) -> bool {
163         self.is_init
164     }
165 
166     // `internal.init` is invoked during `ToggleableProfile::enable`
167     #[log_args]
initialize(&mut self, callbacks: CsisClientCallbacksDispatcher) -> bool168     pub fn initialize(&mut self, callbacks: CsisClientCallbacksDispatcher) -> bool {
169         if self.is_init {
170             warn!("CsisClient has already been initialized");
171             return false;
172         }
173 
174         if get_dispatchers().lock().unwrap().set::<CsisClientCb>(Arc::new(Mutex::new(callbacks))) {
175             panic!("Tried to set dispatcher for CsisClient callbacks while it already exists");
176         }
177 
178         self.is_init = true;
179 
180         true
181     }
182 
183     #[log_args]
184     #[profile_enabled_or]
cleanup(&mut self)185     pub fn cleanup(&mut self) {
186         self.internal.pin_mut().cleanup();
187     }
188 
189     #[log_args]
190     #[profile_enabled_or]
connect(&mut self, addr: RawAddress)191     pub fn connect(&mut self, addr: RawAddress) {
192         self.internal.pin_mut().connect(addr);
193     }
194 
195     #[log_args]
196     #[profile_enabled_or]
disconnect(&mut self, addr: RawAddress)197     pub fn disconnect(&mut self, addr: RawAddress) {
198         self.internal.pin_mut().disconnect(addr);
199     }
200 
201     #[log_args]
202     #[profile_enabled_or]
lock_group(&mut self, group_id: i32, lock: bool)203     pub fn lock_group(&mut self, group_id: i32, lock: bool) {
204         self.internal.pin_mut().lock_group(group_id, lock);
205     }
206 
207     #[log_args]
208     #[profile_enabled_or]
remove_device(&mut self, addr: RawAddress)209     pub fn remove_device(&mut self, addr: RawAddress) {
210         self.internal.pin_mut().remove_device(addr);
211     }
212 }
213