blob: 1d663933a7c8a9311051fe165a23ad1124e36904 [file] [log] [blame]
use crate::ClientContext;
use crate::{console_yellow, print_info};
use bt_topshim::btif::{BtBondState, BtSspVariant};
use bt_topshim::profiles::gatt::GattStatus;
use btstack::bluetooth::{
BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
use btstack::bluetooth_gatt::{BluetoothGattService, IBluetoothGattCallback, LePhy};
use btstack::RPCProxy;
use manager_service::iface_bluetooth_manager::IBluetoothManagerCallback;
use std::sync::{Arc, Mutex};
/// Callback context for manager interface callbacks.
pub(crate) struct BtManagerCallback {
objpath: String,
context: Arc<Mutex<ClientContext>>,
}
impl BtManagerCallback {
pub(crate) fn new(objpath: String, context: Arc<Mutex<ClientContext>>) -> Self {
Self { objpath, context }
}
}
impl IBluetoothManagerCallback for BtManagerCallback {
fn on_hci_device_changed(&self, hci_interface: i32, present: bool) {
print_info!("hci{} present = {}", hci_interface, present);
if present {
self.context.lock().unwrap().adapters.entry(hci_interface).or_insert(false);
} else {
self.context.lock().unwrap().adapters.remove(&hci_interface);
}
}
fn on_hci_enabled_changed(&self, hci_interface: i32, enabled: bool) {
self.context.lock().unwrap().set_adapter_enabled(hci_interface, enabled);
}
}
impl manager_service::RPCProxy for BtManagerCallback {
fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
0
}
fn get_object_id(&self) -> String {
self.objpath.clone()
}
fn unregister(&mut self, _id: u32) -> bool {
false
}
}
/// Callback container for adapter interface callbacks.
pub(crate) struct BtCallback {
objpath: String,
context: Arc<Mutex<ClientContext>>,
}
impl BtCallback {
pub(crate) fn new(objpath: String, context: Arc<Mutex<ClientContext>>) -> Self {
Self { objpath, context }
}
}
impl IBluetoothCallback for BtCallback {
fn on_address_changed(&self, addr: String) {
print_info!("Address changed to {}", &addr);
self.context.lock().unwrap().adapter_address = Some(addr);
}
fn on_device_found(&self, remote_device: BluetoothDevice) {
self.context
.lock()
.unwrap()
.found_devices
.entry(remote_device.address.clone())
.or_insert(remote_device.clone());
print_info!("Found device: {:?}", remote_device);
}
fn on_discovering_changed(&self, discovering: bool) {
self.context.lock().unwrap().discovering_state = discovering;
if discovering {
self.context.lock().unwrap().found_devices.clear();
}
print_info!("Discovering: {}", discovering);
}
fn on_ssp_request(
&self,
remote_device: BluetoothDevice,
_cod: u32,
variant: BtSspVariant,
passkey: u32,
) {
match variant {
BtSspVariant::PasskeyNotification => {
print_info!(
"Device [{}: {}] would like to pair, enter passkey on remote device: {:06}",
&remote_device.address,
&remote_device.name,
passkey
);
}
BtSspVariant::Consent => {
let rd = remote_device.clone();
self.context.lock().unwrap().run_callback(Box::new(move |context| {
// Auto-confirm bonding attempts that were locally initiated.
// Ignore all other bonding attempts.
let bonding_device = context.lock().unwrap().bonding_attempt.as_ref().cloned();
match bonding_device {
Some(bd) => {
if bd.address == rd.address {
context
.lock()
.unwrap()
.adapter_dbus
.as_ref()
.unwrap()
.set_pairing_confirmation(rd.clone(), true);
}
}
None => (),
}
}));
}
BtSspVariant::PasskeyEntry => {
println!("Got PasskeyEntry but it is not supported...");
}
BtSspVariant::PasskeyConfirmation => {
println!("Got PasskeyConfirmation but there's nothing to do...");
}
}
}
fn on_bond_state_changed(&self, status: u32, address: String, state: u32) {
print_info!("Bonding state changed: [{}] state: {}, Status = {}", address, state, status);
// Clear bonding attempt if bonding fails or succeeds
match BtBondState::from(state) {
BtBondState::NotBonded | BtBondState::Bonded => {
let bonding_attempt =
self.context.lock().unwrap().bonding_attempt.as_ref().cloned();
match bonding_attempt {
Some(bd) => {
if &address == &bd.address {
self.context.lock().unwrap().bonding_attempt = None;
}
}
None => (),
}
}
BtBondState::Bonding => (),
}
// If bonded, we should also automatically connect all enabled profiles
if BtBondState::Bonded == state.into() {
self.context.lock().unwrap().connect_all_enabled_profiles(BluetoothDevice {
address,
name: String::from("Classic device"),
});
}
}
}
impl RPCProxy for BtCallback {
fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
0
}
fn get_object_id(&self) -> String {
self.objpath.clone()
}
fn unregister(&mut self, _id: u32) -> bool {
false
}
}
pub(crate) struct BtConnectionCallback {
objpath: String,
_context: Arc<Mutex<ClientContext>>,
}
impl BtConnectionCallback {
pub(crate) fn new(objpath: String, _context: Arc<Mutex<ClientContext>>) -> Self {
Self { objpath, _context }
}
}
impl IBluetoothConnectionCallback for BtConnectionCallback {
fn on_device_connected(&self, remote_device: BluetoothDevice) {
print_info!("Connected: [{}]: {}", remote_device.address, remote_device.name);
}
fn on_device_disconnected(&self, remote_device: BluetoothDevice) {
print_info!("Disconnected: [{}]: {}", remote_device.address, remote_device.name);
}
}
impl RPCProxy for BtConnectionCallback {
fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
0
}
fn get_object_id(&self) -> String {
self.objpath.clone()
}
fn unregister(&mut self, _id: u32) -> bool {
false
}
}
pub(crate) struct BtGattCallback {
objpath: String,
context: Arc<Mutex<ClientContext>>,
}
impl BtGattCallback {
pub(crate) fn new(objpath: String, context: Arc<Mutex<ClientContext>>) -> Self {
Self { objpath, context }
}
}
impl IBluetoothGattCallback for BtGattCallback {
fn on_client_registered(&self, status: i32, client_id: i32) {
print_info!("GATT Client registered status = {}, client_id = {}", status, client_id);
self.context.lock().unwrap().gatt_client_id = Some(client_id);
}
fn on_client_connection_state(
&self,
status: i32,
client_id: i32,
connected: bool,
addr: String,
) {
print_info!(
"GATT Client connection state = {}, client_id = {}, connected = {}, addr = {}",
status,
client_id,
connected,
addr
);
}
fn on_phy_update(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus) {
print_info!(
"Phy updated: addr = {}, tx_phy = {:?}, rx_phy = {:?}, status = {:?}",
addr,
tx_phy,
rx_phy,
status
);
}
fn on_phy_read(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus) {
print_info!(
"Phy read: addr = {}, tx_phy = {:?}, rx_phy = {:?}, status = {:?}",
addr,
tx_phy,
rx_phy,
status
);
}
fn on_search_complete(&self, addr: String, services: Vec<BluetoothGattService>, status: i32) {
print_info!(
"GATT DB Search complete: addr = {}, services = {:?}, status = {}",
addr,
services,
status
);
}
fn on_characteristic_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>) {
print_info!(
"GATT Characteristic read: addr = {}, status = {}, handle = {}, value = {:?}",
addr,
status,
handle,
value
);
}
fn on_characteristic_write(&self, addr: String, status: i32, handle: i32) {
print_info!(
"GATT Characteristic write: addr = {}, status = {}, handle = {}",
addr,
status,
handle
);
}
fn on_execute_write(&self, addr: String, status: i32) {
print_info!("GATT execute write addr = {}, status = {}", addr, status);
}
fn on_descriptor_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>) {
print_info!(
"GATT Descriptor read: addr = {}, status = {}, handle = {}, value = {:?}",
addr,
status,
handle,
value
);
}
fn on_descriptor_write(&self, addr: String, status: i32, handle: i32) {
print_info!(
"GATT Descriptor write: addr = {}, status = {}, handle = {}",
addr,
status,
handle
);
}
fn on_notify(&self, addr: String, handle: i32, value: Vec<u8>) {
print_info!("GATT Notification: addr = {}, handle = {}, value = {:?}", addr, handle, value);
}
fn on_read_remote_rssi(&self, addr: String, rssi: i32, status: i32) {
print_info!("Remote RSSI read: addr = {}, rssi = {}, status = {}", addr, rssi, status);
}
fn on_configure_mtu(&self, addr: String, mtu: i32, status: i32) {
print_info!("MTU configured: addr = {}, mtu = {}, status = {}", addr, mtu, status);
}
fn on_connection_updated(
&self,
addr: String,
interval: i32,
latency: i32,
timeout: i32,
status: i32,
) {
print_info!(
"Connection updated: addr = {}, interval = {}, latency = {}, timeout = {}, status = {}",
addr,
interval,
latency,
timeout,
status
);
}
fn on_service_changed(&self, addr: String) {
print_info!("Service changed for {}", addr,);
}
}
impl RPCProxy for BtGattCallback {
fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
0
}
fn get_object_id(&self) -> String {
self.objpath.clone()
}
fn unregister(&mut self, _id: u32) -> bool {
false
}
}