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

Commit 48d8f04b authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

floss: Implement read and write characteristic methods

This implements the following IBluteoothGatt methods:
* ReadCharacteristic
* ReadUsingCharacteristicUuid
* WriteCharacteristic

Bug: 193685325
Tag: #floss
Test: Build floss and Linux and AOSP

Change-Id: Ie7105b7a147b6616f87d20b32fc0eb57fa674971
parent 8e5d5569
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -592,6 +592,7 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {
        impl DirectDBus for u32 {}
        impl DirectDBus for i64 {}
        impl DirectDBus for u64 {}
        impl DirectDBus for u8 {}
        impl DirectDBus for String {}
        impl<T: DirectDBus> DBusArg for T {
            type DBusType = T;
+31 −2
Original line number Diff line number Diff line
use bt_topshim::profiles::gatt::GattStatus;

use btstack::bluetooth_gatt::{
    IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, LePhy, RSSISettings, ScanFilter,
    ScanSettings, ScanType,
    GattWriteRequestStatus, IBluetoothGatt, IBluetoothGattCallback, IScannerCallback, LePhy,
    RSSISettings, ScanFilter, ScanSettings, ScanType,
};
use btstack::RPCProxy;

@@ -71,6 +71,7 @@ struct ScanSettingsDBus {
}

impl_dbus_arg_enum!(GattStatus);
impl_dbus_arg_enum!(GattWriteRequestStatus);
impl_dbus_arg_enum!(LePhy);
impl_dbus_arg_enum!(ScanType);

@@ -143,4 +144,32 @@ impl IBluetoothGatt for IBluetoothGattDBus {

    #[dbus_method("DiscoverServiceByUuid")]
    fn discover_service_by_uuid(&self, client_id: i32, addr: String, uuid: String) {}

    #[dbus_method("ReadCharacteristic")]
    fn read_characteristic(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {}

    #[dbus_method("ReadUsingCharacteristicUuid")]
    fn read_using_characteristic_uuid(
        &self,
        client_id: i32,
        addr: String,
        uuid: String,
        start_handle: i32,
        end_handle: i32,
        auth_req: i32,
    ) {
    }

    #[dbus_method("WriteCharacteristic")]
    fn write_characteristic(
        &self,
        client_id: i32,
        addr: String,
        handle: i32,
        write_type: i32,
        auth_req: i32,
        value: Vec<u8>,
    ) -> GattWriteRequestStatus {
        GattWriteRequestStatus::Success
    }
}
+110 −0
Original line number Diff line number Diff line
@@ -160,6 +160,31 @@ pub trait IBluetoothGatt {

    /// Search a GATT service on a connected device based on a UUID.
    fn discover_service_by_uuid(&self, client_id: i32, addr: String, uuid: String);

    /// Reads a characteristic on a remote device.
    fn read_characteristic(&self, client_id: i32, addr: String, handle: i32, auth_req: i32);

    /// Reads a characteristic on a remote device.
    fn read_using_characteristic_uuid(
        &self,
        client_id: i32,
        addr: String,
        uuid: String,
        start_handle: i32,
        end_handle: i32,
        auth_req: i32,
    );

    /// Writes a remote characteristic.
    fn write_characteristic(
        &self,
        client_id: i32,
        addr: String,
        handle: i32,
        write_type: i32,
        auth_req: i32,
        value: Vec<u8>,
    ) -> GattWriteRequestStatus;
}

/// Callback for GATT Client API.
@@ -293,6 +318,15 @@ fn parse_uuid_string<T: Into<String>>(uuid: T) -> Option<Uuid> {
    Some(Uuid { uu: raw })
}

#[derive(Debug, FromPrimitive, ToPrimitive)]
#[repr(u8)]
/// Status of WriteCharacteristic methods.
pub enum GattWriteRequestStatus {
    Success = 0,
    Fail = 1,
    Busy = 2,
}

impl IBluetoothGatt for BluetoothGatt {
    fn register_scanner(&self, _callback: Box<dyn IScannerCallback + Send>) {
        // TODO: implement
@@ -423,6 +457,82 @@ impl IBluetoothGatt for BluetoothGatt {

        self.gatt.as_ref().unwrap().client.search_service(conn_id.unwrap(), uuid);
    }

    fn read_characteristic(&self, client_id: i32, addr: String, handle: i32, auth_req: i32) {
        let conn_id = self.context_map.get_conn_id_from_address(client_id, &addr);
        if conn_id.is_none() {
            return;
        }

        // TODO(b/193685325): Perform check on restricted handles.

        self.gatt.as_ref().unwrap().client.read_characteristic(
            conn_id.unwrap(),
            handle as u16,
            auth_req,
        );
    }

    fn read_using_characteristic_uuid(
        &self,
        client_id: i32,
        addr: String,
        uuid: String,
        start_handle: i32,
        end_handle: i32,
        auth_req: i32,
    ) {
        let conn_id = self.context_map.get_conn_id_from_address(client_id, &addr);
        if conn_id.is_none() {
            return;
        }

        let uuid = parse_uuid_string(uuid);
        if uuid.is_none() {
            return;
        }

        // TODO(b/193685325): Perform check on restricted handles.

        self.gatt.as_ref().unwrap().client.read_using_characteristic_uuid(
            conn_id.unwrap(),
            &uuid.unwrap(),
            start_handle as u16,
            end_handle as u16,
            auth_req,
        );
    }

    fn write_characteristic(
        &self,
        client_id: i32,
        addr: String,
        handle: i32,
        write_type: i32,
        auth_req: i32,
        value: Vec<u8>,
    ) -> GattWriteRequestStatus {
        let conn_id = self.context_map.get_conn_id_from_address(client_id, &addr);
        if conn_id.is_none() {
            return GattWriteRequestStatus::Fail;
        }

        // TODO(b/193685325): Check for reliable write type.

        // TODO(b/193685325): Perform check on restricted handles.

        // TODO(b/193685325): Lock the thread until onCharacteristicWrite callback comes back?

        self.gatt.as_ref().unwrap().client.write_characteristic(
            conn_id.unwrap(),
            handle as u16,
            write_type,
            auth_req,
            &value,
        );

        return GattWriteRequestStatus::Success;
    }
}

#[btif_callbacks_dispatcher(BluetoothGatt, dispatch_gatt_client_callbacks, GattClientCallbacks)]