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

Commit 8cab37dc authored by Rahul Arya's avatar Rahul Arya
Browse files

[Private GATT] Add support for GATT write requests

Bug: 255880936
Test: unit
Change-Id: Iec10e55b720729bd88e8a3889d9f47150fb693ee
parent e59a4b6e
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ pub use callback_transaction_manager::{CallbackResponseError, CallbackTransactio

use async_trait::async_trait;

use crate::packets::{AttAttributeDataChild, AttErrorCode};
use crate::packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode};

use super::ids::{AttHandle, ConnectionId, TransactionId};

@@ -25,6 +25,20 @@ pub trait GattCallbacks {
        offset: u32,
        is_long: bool,
    );

    /// Invoked when a client tries to write a characteristic. Expects a
    /// response using bluetooth::gatt::send_response();
    #[allow(clippy::too_many_arguments)] // needed to match the C++ interface
    fn on_server_write_characteristic(
        &self,
        conn_id: ConnectionId,
        trans_id: TransactionId,
        handle: AttHandle,
        offset: u32,
        need_response: bool,
        is_prepare: bool,
        value: AttAttributeDataView,
    );
}

/// This interface is an "async" version of the above, and is passed directly
@@ -44,4 +58,12 @@ pub trait GattDatastore {
        conn_id: ConnectionId,
        handle: AttHandle,
    ) -> Result<AttAttributeDataChild, AttErrorCode>;

    /// Write data to a given characteristic on the specified connection.
    async fn write_characteristic(
        &self,
        conn_id: ConnectionId,
        handle: AttHandle,
        data: AttAttributeDataView<'_>,
    ) -> Result<(), AttErrorCode>;
}
+22 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ use crate::{
        ids::{AttHandle, ConnectionId, TransactionId},
        GattCallbacks,
    },
    packets::{AttAttributeDataChild, AttErrorCode},
    packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode},
};

use super::GattDatastore;
@@ -138,4 +138,25 @@ impl GattDatastore for CallbackTransactionManager {
            Err(AttErrorCode::UNLIKELY_ERROR)
        }
    }

    async fn write_characteristic(
        &self,
        conn_id: ConnectionId,
        handle: AttHandle,
        data: AttAttributeDataView<'_>,
    ) -> Result<(), AttErrorCode> {
        let (trans_id, rx) =
            self.pending_transactions.borrow_mut().start_new_transaction(conn_id)?;

        self.callbacks
            .on_server_write_characteristic(conn_id, trans_id, handle, 0, true, false, data);

        if let Ok(value) = rx.await {
            value.map(|_| ()) // the data passed back is irrelevant for write
                              // requests
        } else {
            warn!("sender side of {trans_id:?} dropped while handling request - most likely this response will not be sent over the air");
            Err(AttErrorCode::UNLIKELY_ERROR)
        }
    }
}
+39 −1
Original line number Diff line number Diff line
@@ -11,7 +11,10 @@ use log::{error, info, warn};

use crate::{
    do_in_rust_thread,
    packets::{AttAttributeDataChild, AttBuilder, AttErrorCode, Serializable, SerializeError},
    packets::{
        AttAttributeDataChild, AttAttributeDataView, AttBuilder, AttErrorCode, Serializable,
        SerializeError,
    },
};

use super::{
@@ -54,6 +57,20 @@ mod inner {
            offset: u32,
            is_long: bool,
        );

        /// This callback is invoked when writing a characteristic - the client
        /// must reply using SendResponse
        #[cxx_name = "OnServerWriteCharacteristic"]
        fn on_server_write_characteristic(
            self: &GattServerCallbacks,
            conn_id: u16,
            trans_id: u32,
            attr_handle: u16,
            offset: u32,
            need_response: bool,
            is_prepare: bool,
            value: &[u8],
        );
    }

    /// What action the arbiter should take in response to an incoming packet
@@ -143,6 +160,27 @@ impl GattCallbacks for GattCallbacksImpl {
            .unwrap()
            .on_server_read_characteristic(conn_id.0, trans_id.0, handle.0, offset, is_long);
    }

    fn on_server_write_characteristic(
        &self,
        conn_id: ConnectionId,
        trans_id: TransactionId,
        handle: AttHandle,
        offset: u32,
        need_response: bool,
        is_prepare: bool,
        value: AttAttributeDataView,
    ) {
        self.0.as_ref().unwrap().on_server_write_characteristic(
            conn_id.0,
            trans_id.0,
            handle.0,
            offset,
            need_response,
            is_prepare,
            &value.get_raw_payload().collect::<Vec<_>>(),
        );
    }
}

/// Implementation of AttTransport wrapping the corresponding C++ method
+22 −0
Original line number Diff line number Diff line
@@ -69,5 +69,27 @@ void GattServerCallbacks::OnServerReadCharacteristic(uint16_t conn_id,
                 addr.value(), attr_handle, offset, is_long));
}

void GattServerCallbacks::OnServerWriteCharacteristic(
    uint16_t conn_id, uint32_t trans_id, uint16_t attr_handle, uint32_t offset,
    bool need_response, bool is_prepare,
    ::rust::Slice<const uint8_t> value) const {
  auto addr = AddressOfConnection(conn_id);
  if (!addr.has_value()) {
    LOG_WARN(
        "Dropping server write characteristic since connection %d not found",
        conn_id);
    return;
  }

  auto buf = new uint8_t[value.size()];
  std::copy(value.begin(), value.end(), buf);

  do_in_jni_thread(
      FROM_HERE,
      base::Bind(callbacks.request_write_characteristic_cb, conn_id, trans_id,
                 addr.value(), attr_handle, offset, need_response, is_prepare,
                 base::Owned(buf), value.size()));
}

}  // namespace gatt
}  // namespace bluetooth
+5 −0
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@ class GattServerCallbacks {
                                  uint16_t attr_handle, uint32_t offset,
                                  bool is_long) const;

  void OnServerWriteCharacteristic(uint16_t conn_id, uint32_t trans_id,
                                   uint16_t attr_handle, uint32_t offset,
                                   bool need_response, bool is_prepare,
                                   ::rust::Slice<const uint8_t> value) const;

 private:
  const btgatt_server_callbacks_t& callbacks;
};
Loading