Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f58e3b9 authored by Sarvesh Kalwit's avatar Sarvesh Kalwit Committed by Gerrit Code Review
Browse files

Merge changes I355be197,I6a5de7a3 into main

* changes:
  floss: Support adding/removing/clearing GATT Services in btclient
  floss: Support GATT Server connection/disconnection in btclient
parents 29d18947 134fe61c
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -50,3 +50,17 @@ impl GattClientContext {
        self.auth_req
    }
}

/// User preference of GATT server operations
pub(crate) struct GattServerContext {
    /// Is connection going to be directed?
    pub(crate) is_connect_direct: bool,
    /// Transport of connection
    pub(crate) connect_transport: BtTransport,
}

impl GattServerContext {
    pub(crate) fn new() -> Self {
        GattServerContext { is_connect_direct: false, connect_transport: BtTransport::Le }
    }
}
+97 −2
Original line number Diff line number Diff line
@@ -9,13 +9,15 @@ use crate::bt_gatt::AuthReq;
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, INVALID_RSSI};
use bt_topshim::btif::{BtConnectionState, BtDiscMode, BtStatus, BtTransport, Uuid, INVALID_RSSI};
use bt_topshim::profiles::hid_host::BthhReportType;
use bt_topshim::profiles::sdp::{BtSdpMpsRecord, BtSdpRecord};
use bt_topshim::profiles::{gatt::LePhy, ProfileConnectionState};
use btstack::battery_manager::IBatteryManager;
use btstack::bluetooth::{BluetoothDevice, IBluetooth};
use btstack::bluetooth_gatt::{GattWriteType, IBluetoothGatt};
use btstack::bluetooth_gatt::{
    BluetoothGattService, GattDbElementType, GattWriteType, IBluetoothGatt,
};
use btstack::bluetooth_media::{IBluetoothMedia, IBluetoothTelephony};
use btstack::bluetooth_qa::IBluetoothQA;
use btstack::socket_manager::{IBluetoothSocketManager, SocketResult};
@@ -28,6 +30,7 @@ const BAR2_CHAR: &str = "-";
const MAX_MENU_CHAR_WIDTH: usize = 72;
const GATT_CLIENT_APP_UUID: &str = "12345678123456781234567812345678";
const GATT_SERVER_APP_UUID: &str = "12345678123456781234567812345679";
const HEART_RATE_SERVICE_UUID: &str = "0000180D-0000-1000-8000-00805F9B34FB";

enum CommandError {
    // Command not handled due to invalid arguments.
@@ -221,6 +224,13 @@ fn build_commands() -> HashMap<String, CommandOption> {
                ),
                String::from("gatt register-notification <address> <handle> <enable|disable>"),
                String::from("gatt register-server"),
                String::from("gatt server-connect <server_id> <client_address>"),
                String::from("gatt server-disconnect <server_id> <client_address>"),
                String::from("gatt server-add-heartrate-service <server_id>"),
                String::from("gatt server-remove-service <server_id> <service_handle>"),
                String::from("gatt server-clear-all-services <server_id>"),
                String::from("gatt server-set-direct-connect <true|false>"),
                String::from("gatt server-set-connect-transport <Bredr|LE|Auto>"),
            ],
            description: String::from("GATT tools"),
            function_pointer: CommandHandler::cmd_gatt,
@@ -1315,6 +1325,91 @@ impl CommandHandler {
                    false,
                );
            }
            "server-connect" => {
                let server_id = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse server_id"))?;
                let client_addr = String::from(get_arg(args, 2)?);
                let is_direct = self.lock_context().gatt_server_context.is_connect_direct;
                let transport = self.lock_context().gatt_server_context.connect_transport;

                if !self.lock_context().gatt_dbus.as_mut().unwrap().server_connect(
                    server_id,
                    client_addr.clone(),
                    is_direct,
                    transport,
                ) {
                    return Err("Connection was unsuccessful".into());
                }
            }
            "server-disconnect" => {
                let server_id = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse server_id"))?;
                let client_addr = String::from(get_arg(args, 2)?);

                if !self
                    .lock_context()
                    .gatt_dbus
                    .as_mut()
                    .unwrap()
                    .server_disconnect(server_id, client_addr.clone())
                {
                    return Err("Disconnection was unsuccessful".into());
                }
            }
            "server-add-heartrate-service" => {
                let uuid = Uuid::from(UuidHelper::from_string(HEART_RATE_SERVICE_UUID).unwrap());

                let server_id = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse server_id"))?;
                let service = BluetoothGattService::new(
                    uuid.into(),
                    0, // libbluetooth assigns this handle once the service is added
                    GattDbElementType::PrimaryService.into(),
                );

                self.lock_context().gatt_dbus.as_mut().unwrap().add_service(server_id, service);
            }
            "server-remove-service" => {
                let server_id = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse server_id"))?;
                let service_handle = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse service handle"))?;

                self.lock_context()
                    .gatt_dbus
                    .as_mut()
                    .unwrap()
                    .remove_service(server_id, service_handle);
            }
            "server-clear-all-services" => {
                let server_id = String::from(get_arg(args, 1)?)
                    .parse::<i32>()
                    .or(Err("Failed to parse server_id"))?;
                self.lock_context().gatt_dbus.as_mut().unwrap().clear_services(server_id);
            }
            "server-set-direct-connect" => {
                let is_direct = String::from(get_arg(args, 1)?)
                    .parse::<bool>()
                    .or(Err("Failed to parse is_direct"))?;

                self.lock_context().gatt_server_context.is_connect_direct = is_direct;
            }
            "server-set-connect-transport" => {
                let transport = match &get_arg(args, 1)?[..] {
                    "Bredr" => BtTransport::Bredr,
                    "LE" => BtTransport::Le,
                    "Auto" => BtTransport::Auto,
                    _ => {
                        return Err("Failed to parse transport".into());
                    }
                };
                self.lock_context().gatt_server_context.connect_transport = transport;
            }
            _ => return Err(CommandError::InvalidArgs),
        }
        Ok(())
+5 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ use tokio::sync::mpsc;
use tokio::time::{sleep, timeout};

use crate::bt_adv::AdvSet;
use crate::bt_gatt::GattClientContext;
use crate::bt_gatt::{GattClientContext, GattServerContext};
use crate::callbacks::{
    AdminCallback, AdvertisingSetCallback, BatteryManagerCallback, BtCallback,
    BtConnectionCallback, BtManagerCallback, BtSocketManagerCallback, MediaCallback, QACallback,
@@ -141,6 +141,9 @@ pub(crate) struct ClientContext {
    /// Data of GATT client preference.
    gatt_client_context: GattClientContext,

    /// Data of GATT server preference.
    gatt_server_context: GattServerContext,

    /// The schedule when a socket is connected.
    socket_test_schedule: Option<SocketSchedule>,

@@ -199,6 +202,7 @@ impl ClientContext {
            qa_callback_id: None,
            is_restricted,
            gatt_client_context: GattClientContext::new(),
            gatt_server_context: GattServerContext::new(),
            socket_test_schedule: None,
            mps_sdp_handle: None,
            client_commands_with_callbacks,
+2 −6
Original line number Diff line number Diff line
@@ -782,11 +782,7 @@ pub struct BluetoothGattService {
}

impl BluetoothGattService {
    pub(crate) fn new(
        uuid: Uuid128Bit,
        instance_id: i32,
        service_type: i32,
    ) -> BluetoothGattService {
    pub fn new(uuid: Uuid128Bit, instance_id: i32, service_type: i32) -> BluetoothGattService {
        BluetoothGattService {
            uuid,
            instance_id,
@@ -1133,7 +1129,7 @@ pub trait IScannerCallback: RPCProxy {
#[derive(Debug, FromPrimitive, ToPrimitive)]
#[repr(u8)]
/// GATT write type.
pub(crate) enum GattDbElementType {
pub enum GattDbElementType {
    PrimaryService = 0,
    SecondaryService = 1,
    IncludedService = 2,