Loading system/gd/rust/linux/client/src/callbacks.rs +50 −5 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ use crate::dbus_iface::{ export_qa_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, }; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use crate::{ClientContext, GattRequest}; use bt_topshim::btif::{BtBondState, BtPropertyType, BtSspVariant, BtStatus, Uuid128Bit}; use bt_topshim::profiles::gatt::{AdvertisingStatus, GattStatus, LePhy}; use bt_topshim::profiles::hfp::HfpCodecId; Loading Loading @@ -841,7 +841,7 @@ impl RPCProxy for BtGattCallback { pub(crate) struct BtGattServerCallback { objpath: String, _context: Arc<Mutex<ClientContext>>, context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, Loading @@ -850,11 +850,11 @@ pub(crate) struct BtGattServerCallback { impl BtGattServerCallback { pub(crate) fn new( objpath: String, _context: Arc<Mutex<ClientContext>>, context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, ) -> Self { Self { objpath, _context, dbus_connection, dbus_crossroads } Self { objpath, context, dbus_connection, dbus_crossroads } } } Loading Loading @@ -890,12 +890,21 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { ) { print_info!( "GATT characteristic read request for addr = {}, trans_id = {}, offset = {}, is_long = {}, handle = {}", addr, addr.clone(), trans_id, offset, is_long, handle ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: vec![] }); } fn on_descriptor_read_request( Loading @@ -914,6 +923,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { is_long, handle ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: vec![] }); } fn on_characteristic_write_request( Loading @@ -939,6 +957,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { handle, value ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: value }); } fn on_descriptor_write_request( Loading @@ -964,6 +991,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { handle, value ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: value }); } fn on_execute_write(&mut self, addr: String, trans_id: i32, exec_write: bool) { Loading @@ -973,6 +1009,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { trans_id, exec_write ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: 0, value: vec![] }); } fn on_notification_sent(&mut self, addr: String, status: GattStatus) { Loading system/gd/rust/linux/client/src/command_handler.rs +37 −10 Original line number Diff line number Diff line Loading @@ -10,9 +10,10 @@ use crate::callbacks::{BtGattCallback, BtGattServerCallback}; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use bt_topshim::btif::{BtConnectionState, BtDiscMode, BtStatus, BtTransport, Uuid, INVALID_RSSI}; use bt_topshim::profiles::gatt::{GattStatus, LePhy}; use bt_topshim::profiles::hid_host::BthhReportType; use bt_topshim::profiles::sdp::{BtSdpMpsRecord, BtSdpRecord}; use bt_topshim::profiles::{gatt::LePhy, ProfileConnectionState}; use bt_topshim::profiles::ProfileConnectionState; use btstack::battery_manager::IBatteryManager; use btstack::bluetooth::{BluetoothDevice, IBluetooth}; use btstack::bluetooth_gatt::{ Loading @@ -38,11 +39,6 @@ const GENERIC_UUID: &str = "00000000-0000-1000-8000-00805F9B34FB"; const CCC_DESCRIPTOR_UUID: &str = "00002902-0000-1000-8000-00805F9B34FB"; const BATTERY_SERVICE_UUID: &str = "0000180F-0000-1000-8000-00805F9B34FB"; const PROPERTY_WRITE: i32 = 1 << 3; const PROPERTY_NOTIFY: i32 = 1 << 4; const PERMISSION_READ: i32 = 1 << 0; const PERMISSION_WRITE: i32 = 1 << 1; enum CommandError { // Command not handled due to invalid arguments. InvalidArgs, Loading Loading @@ -242,6 +238,7 @@ fn build_commands() -> HashMap<String, CommandOption> { String::from("gatt server-add-service <server_id> <incl_service_instance_id>"), String::from("gatt server-remove-service <server_id> <service_handle>"), String::from("gatt server-clear-all-services <server_id>"), String::from("gatt server-send-response <server_id> <success|fail>"), String::from("gatt server-set-direct-connect <true|false>"), String::from("gatt server-set-connect-transport <Bredr|LE|Auto>"), ], Loading Loading @@ -1432,18 +1429,23 @@ impl CommandHandler { let mut characteristic = BluetoothGattCharacteristic::new( characteristic_uuid.into(), 0, PROPERTY_WRITE + PROPERTY_NOTIFY, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PROPERTY_READ | BluetoothGattCharacteristic::PROPERTY_WRITE | BluetoothGattCharacteristic::PROPERTY_NOTIFY, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); let descriptor = BluetoothGattDescriptor::new( descriptor_uuid.into(), 0, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); let ccc_descriptor = BluetoothGattDescriptor::new( ccc_descriptor_uuid.into(), 0, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); service.included_services.push(included_service); Loading Loading @@ -1473,6 +1475,31 @@ impl CommandHandler { .or(Err("Failed to parse server_id"))?; self.lock_context().gatt_dbus.as_mut().unwrap().clear_services(server_id); } "server-send-response" => { let server_id = String::from(get_arg(args, 1)?) .parse::<i32>() .or(Err("Failed to parse server_id"))?; let status = match String::from(get_arg(args, 2)?).as_str() { "success" => GattStatus::Success, "fail" => GattStatus::Error, _ => return Err("{} is not one of the following: `success`, `fail`".into()), }; let request = match self.lock_context().pending_gatt_request.clone() { None => return Err("No pending request to send response to".into()), Some(r) => r, }; self.lock_context().gatt_dbus.as_mut().unwrap().send_response( server_id, request.address.clone(), request.id, status, request.offset, request.value.clone(), ); self.lock_context().pending_gatt_request = None; } "server-set-direct-connect" => { let is_direct = String::from(get_arg(args, 1)?) .parse::<bool>() Loading system/gd/rust/linux/client/src/main.rs +12 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,14 @@ mod dbus_arg; mod dbus_iface; mod editor; #[derive(Clone)] pub(crate) struct GattRequest { address: String, id: i32, offset: i32, value: Vec<u8>, } /// Context structure for the client. Used to keep track details about the active adapter and its /// state. pub(crate) struct ClientContext { Loading Loading @@ -155,6 +163,9 @@ pub(crate) struct ClientContext { /// A set of addresses whose battery changes are being tracked. pub(crate) battery_address_filter: HashSet<String>, /// A request from a GATT client that is still being processed. pending_gatt_request: Option<GattRequest>, } impl ClientContext { Loading Loading @@ -207,6 +218,7 @@ impl ClientContext { mps_sdp_handle: None, client_commands_with_callbacks, battery_address_filter: HashSet::new(), pending_gatt_request: None, } } Loading Loading
system/gd/rust/linux/client/src/callbacks.rs +50 −5 Original line number Diff line number Diff line Loading @@ -8,8 +8,8 @@ use crate::dbus_iface::{ export_qa_callback_dbus_intf, export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf, }; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use crate::{ClientContext, GattRequest}; use bt_topshim::btif::{BtBondState, BtPropertyType, BtSspVariant, BtStatus, Uuid128Bit}; use bt_topshim::profiles::gatt::{AdvertisingStatus, GattStatus, LePhy}; use bt_topshim::profiles::hfp::HfpCodecId; Loading Loading @@ -841,7 +841,7 @@ impl RPCProxy for BtGattCallback { pub(crate) struct BtGattServerCallback { objpath: String, _context: Arc<Mutex<ClientContext>>, context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, Loading @@ -850,11 +850,11 @@ pub(crate) struct BtGattServerCallback { impl BtGattServerCallback { pub(crate) fn new( objpath: String, _context: Arc<Mutex<ClientContext>>, context: Arc<Mutex<ClientContext>>, dbus_connection: Arc<SyncConnection>, dbus_crossroads: Arc<Mutex<Crossroads>>, ) -> Self { Self { objpath, _context, dbus_connection, dbus_crossroads } Self { objpath, context, dbus_connection, dbus_crossroads } } } Loading Loading @@ -890,12 +890,21 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { ) { print_info!( "GATT characteristic read request for addr = {}, trans_id = {}, offset = {}, is_long = {}, handle = {}", addr, addr.clone(), trans_id, offset, is_long, handle ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: vec![] }); } fn on_descriptor_read_request( Loading @@ -914,6 +923,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { is_long, handle ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: vec![] }); } fn on_characteristic_write_request( Loading @@ -939,6 +957,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { handle, value ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: value }); } fn on_descriptor_write_request( Loading @@ -964,6 +991,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { handle, value ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: offset, value: value }); } fn on_execute_write(&mut self, addr: String, trans_id: i32, exec_write: bool) { Loading @@ -973,6 +1009,15 @@ impl IBluetoothGattServerCallback for BtGattServerCallback { trans_id, exec_write ); if self.context.lock().unwrap().pending_gatt_request.is_some() { print_info!( "This request will be dropped because the previous one has not been responded to" ); return; } self.context.lock().unwrap().pending_gatt_request = Some(GattRequest { address: addr, id: trans_id, offset: 0, value: vec![] }); } fn on_notification_sent(&mut self, addr: String, status: GattStatus) { Loading
system/gd/rust/linux/client/src/command_handler.rs +37 −10 Original line number Diff line number Diff line Loading @@ -10,9 +10,10 @@ use crate::callbacks::{BtGattCallback, BtGattServerCallback}; use crate::ClientContext; use crate::{console_red, console_yellow, print_error, print_info}; use bt_topshim::btif::{BtConnectionState, BtDiscMode, BtStatus, BtTransport, Uuid, INVALID_RSSI}; use bt_topshim::profiles::gatt::{GattStatus, LePhy}; use bt_topshim::profiles::hid_host::BthhReportType; use bt_topshim::profiles::sdp::{BtSdpMpsRecord, BtSdpRecord}; use bt_topshim::profiles::{gatt::LePhy, ProfileConnectionState}; use bt_topshim::profiles::ProfileConnectionState; use btstack::battery_manager::IBatteryManager; use btstack::bluetooth::{BluetoothDevice, IBluetooth}; use btstack::bluetooth_gatt::{ Loading @@ -38,11 +39,6 @@ const GENERIC_UUID: &str = "00000000-0000-1000-8000-00805F9B34FB"; const CCC_DESCRIPTOR_UUID: &str = "00002902-0000-1000-8000-00805F9B34FB"; const BATTERY_SERVICE_UUID: &str = "0000180F-0000-1000-8000-00805F9B34FB"; const PROPERTY_WRITE: i32 = 1 << 3; const PROPERTY_NOTIFY: i32 = 1 << 4; const PERMISSION_READ: i32 = 1 << 0; const PERMISSION_WRITE: i32 = 1 << 1; enum CommandError { // Command not handled due to invalid arguments. InvalidArgs, Loading Loading @@ -242,6 +238,7 @@ fn build_commands() -> HashMap<String, CommandOption> { String::from("gatt server-add-service <server_id> <incl_service_instance_id>"), String::from("gatt server-remove-service <server_id> <service_handle>"), String::from("gatt server-clear-all-services <server_id>"), String::from("gatt server-send-response <server_id> <success|fail>"), String::from("gatt server-set-direct-connect <true|false>"), String::from("gatt server-set-connect-transport <Bredr|LE|Auto>"), ], Loading Loading @@ -1432,18 +1429,23 @@ impl CommandHandler { let mut characteristic = BluetoothGattCharacteristic::new( characteristic_uuid.into(), 0, PROPERTY_WRITE + PROPERTY_NOTIFY, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PROPERTY_READ | BluetoothGattCharacteristic::PROPERTY_WRITE | BluetoothGattCharacteristic::PROPERTY_NOTIFY, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); let descriptor = BluetoothGattDescriptor::new( descriptor_uuid.into(), 0, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); let ccc_descriptor = BluetoothGattDescriptor::new( ccc_descriptor_uuid.into(), 0, PERMISSION_READ + PERMISSION_WRITE, BluetoothGattCharacteristic::PERMISSION_READ | BluetoothGattCharacteristic::PERMISSION_WRITE, ); service.included_services.push(included_service); Loading Loading @@ -1473,6 +1475,31 @@ impl CommandHandler { .or(Err("Failed to parse server_id"))?; self.lock_context().gatt_dbus.as_mut().unwrap().clear_services(server_id); } "server-send-response" => { let server_id = String::from(get_arg(args, 1)?) .parse::<i32>() .or(Err("Failed to parse server_id"))?; let status = match String::from(get_arg(args, 2)?).as_str() { "success" => GattStatus::Success, "fail" => GattStatus::Error, _ => return Err("{} is not one of the following: `success`, `fail`".into()), }; let request = match self.lock_context().pending_gatt_request.clone() { None => return Err("No pending request to send response to".into()), Some(r) => r, }; self.lock_context().gatt_dbus.as_mut().unwrap().send_response( server_id, request.address.clone(), request.id, status, request.offset, request.value.clone(), ); self.lock_context().pending_gatt_request = None; } "server-set-direct-connect" => { let is_direct = String::from(get_arg(args, 1)?) .parse::<bool>() Loading
system/gd/rust/linux/client/src/main.rs +12 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,14 @@ mod dbus_arg; mod dbus_iface; mod editor; #[derive(Clone)] pub(crate) struct GattRequest { address: String, id: i32, offset: i32, value: Vec<u8>, } /// Context structure for the client. Used to keep track details about the active adapter and its /// state. pub(crate) struct ClientContext { Loading Loading @@ -155,6 +163,9 @@ pub(crate) struct ClientContext { /// A set of addresses whose battery changes are being tracked. pub(crate) battery_address_filter: HashSet<String>, /// A request from a GATT client that is still being processed. pending_gatt_request: Option<GattRequest>, } impl ClientContext { Loading Loading @@ -207,6 +218,7 @@ impl ClientContext { mps_sdp_handle: None, client_commands_with_callbacks, battery_address_filter: HashSet::new(), pending_gatt_request: None, } } Loading