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

Commit 0fd12f83 authored by Chienyuan Huang's avatar Chienyuan Huang Committed by Automerger Merge Worker
Browse files

Merge "RAS: create server module" into main am: 5419e23c

parents 7ef9082b 5419e23c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@ cc_library_static {
        "pan/bta_pan_api.cc",
        "pan/bta_pan_ci.cc",
        "pan/bta_pan_main.cc",
        "ras/ras_server.cc",
        "ras/ras_utils.cc",
        "vc/device.cc",
        "vc/vc.cc",
    ],
+2 −0
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ static_library("bta") {
    "pan/bta_pan_api.cc",
    "pan/bta_pan_ci.cc",
    "pan/bta_pan_main.cc",
    "ras/ras_server.cc",
    "ras/ras_utils.cc",
    "rfcomm/bta_rfcomm_scn.cc",
    "sdp/bta_sdp.cc",
    "sdp/bta_sdp_act.cc",
+27 −0
Original line number Diff line number Diff line
@@ -299,6 +299,33 @@ typedef void(tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);

typedef uint8_t tBTA_GATTS_EVT;

inline std::string gatt_server_event_text(const tBTA_GATTS_EVT& event) {
  switch (event) {
    CASE_RETURN_TEXT(BTA_GATTS_REG_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_READ_CHARACTERISTIC_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_READ_DESCRIPTOR_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_WRITE_CHARACTERISTIC_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_WRITE_DESCRIPTOR_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_EXEC_WRITE_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_MTU_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CONF_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_DEREG_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_DELELTE_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_STOP_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CONNECT_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_DISCONNECT_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_OPEN_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CANCEL_OPEN_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CLOSE_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CONGEST_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_PHY_UPDATE_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_CONN_UPDATE_EVT);
    CASE_RETURN_TEXT(BTA_GATTS_SUBRATE_CHG_EVT);
    default:
      return base::StringPrintf("UNKNOWN[%hhu]", event);
  }
}

#define BTA_GATTS_INVALID_APP 0xff

#define BTA_GATTS_INVALID_IF 0
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <vector>

#include "types/raw_address.h"

namespace bluetooth {
namespace ras {

class RasServer {
 public:
  virtual ~RasServer() = default;
  virtual void Initialize() = 0;
};

RasServer* GetRasServer();

}  // namespace ras
}  // namespace bluetooth
+197 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <base/functional/bind.h>
#include <bluetooth/log.h>

#include <unordered_map>

#include "bta/include/bta_gatt_api.h"
#include "bta/include/bta_ras_api.h"
#include "bta/ras/ras_types.h"

using namespace bluetooth;
using namespace ::ras;
using namespace ::ras::uuid;

namespace {

class RasServerImpl;
RasServerImpl* instance;

class RasServerImpl : public bluetooth::ras::RasServer {
 public:
  struct RasCharacteristic {
    bluetooth::Uuid uuid_;
    uint16_t attribute_handle_;
    uint16_t attribute_handle_ccc_;
  };

  void Initialize() {
    app_uuid_ = bluetooth::Uuid::GetRandom();
    log::info("Register server with uuid:{}", app_uuid_.ToString());

    BTA_GATTS_AppRegister(
        app_uuid_,
        [](tBTA_GATTS_EVT event, tBTA_GATTS* p_data) {
          if (instance && p_data) instance->GattsCallback(event, p_data);
        },
        false);
  }

  void GattsCallback(tBTA_GATTS_EVT event, tBTA_GATTS* p_data) {
    log::info("event: {}", gatt_server_event_text(event));
    switch (event) {
      case BTA_GATTS_REG_EVT: {
        OnGattServerRegister(p_data);
      } break;
      default:
        log::warn("Unhandled event {}", event);
    }
  }

  void OnGattServerRegister(tBTA_GATTS* p_data) {
    tGATT_STATUS status = p_data->reg_oper.status;
    log::info("status: {}", gatt_status_text(p_data->reg_oper.status));

    if (status != tGATT_STATUS::GATT_SUCCESS) {
      log::warn("Register Server fail");
      return;
    }
    server_if_ = p_data->reg_oper.server_if;

    uint16_t key_mask = ((16 - 7) << 12);
    std::vector<btgatt_db_element_t> service;
    // RAS service
    btgatt_db_element_t ranging_service;
    ranging_service.uuid = kRangingService;
    ranging_service.type = BTGATT_DB_PRIMARY_SERVICE;
    service.push_back(ranging_service);

    // RAS Features
    btgatt_db_element_t features_characteristic;
    features_characteristic.uuid = kRasFeaturesCharacteristic;
    features_characteristic.type = BTGATT_DB_CHARACTERISTIC;
    features_characteristic.properties = GATT_CHAR_PROP_BIT_READ;
    features_characteristic.permissions = GATT_PERM_READ_ENCRYPTED | key_mask;
    service.push_back(features_characteristic);

    // Real-time Ranging Data (Optional)
    btgatt_db_element_t real_time_ranging_data_characteristic;
    real_time_ranging_data_characteristic.uuid =
        kRasRealTimeRangingDataCharacteristic;
    real_time_ranging_data_characteristic.type = BTGATT_DB_CHARACTERISTIC;
    real_time_ranging_data_characteristic.properties =
        GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_INDICATE;
    real_time_ranging_data_characteristic.permissions =
        GATT_PERM_READ_ENCRYPTED | key_mask;
    service.push_back(real_time_ranging_data_characteristic);
    btgatt_db_element_t ccc_descriptor;
    ccc_descriptor.uuid = kClientCharacteristicConfiguration;
    ccc_descriptor.type = BTGATT_DB_DESCRIPTOR;
    ccc_descriptor.permissions = GATT_PERM_WRITE | GATT_PERM_READ | key_mask;
    service.push_back(ccc_descriptor);

    // On-demand Ranging Data
    btgatt_db_element_t on_demand_ranging_data_characteristic;
    on_demand_ranging_data_characteristic.uuid = kRasOnDemandDataCharacteristic;
    on_demand_ranging_data_characteristic.type = BTGATT_DB_CHARACTERISTIC;
    on_demand_ranging_data_characteristic.properties =
        GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_INDICATE;
    on_demand_ranging_data_characteristic.permissions =
        GATT_PERM_READ_ENCRYPTED | key_mask;
    service.push_back(on_demand_ranging_data_characteristic);
    service.push_back(ccc_descriptor);

    // RAS Control Point (RAS-CP)
    btgatt_db_element_t ras_control_point;
    ras_control_point.uuid = kRasControlPointCharacteristic;
    ras_control_point.type = BTGATT_DB_CHARACTERISTIC;
    ras_control_point.properties =
        GATT_CHAR_PROP_BIT_WRITE | GATT_CHAR_PROP_BIT_INDICATE;
    ras_control_point.permissions = GATT_PERM_WRITE_ENCRYPTED | key_mask;
    service.push_back(ras_control_point);
    service.push_back(ccc_descriptor);

    // Ranging Data Ready
    btgatt_db_element_t ranging_data_ready_characteristic;
    ranging_data_ready_characteristic.uuid = kRasRangingDataReadyCharacteristic;
    ranging_data_ready_characteristic.type = BTGATT_DB_CHARACTERISTIC;
    ranging_data_ready_characteristic.properties =
        GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_INDICATE;
    ranging_data_ready_characteristic.permissions =
        GATT_PERM_READ_ENCRYPTED | key_mask;
    service.push_back(ranging_data_ready_characteristic);
    service.push_back(ccc_descriptor);

    // Ranging Data Overwritten
    btgatt_db_element_t ranging_data_overwritten_characteristic;
    ranging_data_overwritten_characteristic.uuid =
        kRasRangingDataOverWrittenCharacteristic;
    ranging_data_overwritten_characteristic.type = BTGATT_DB_CHARACTERISTIC;
    ranging_data_overwritten_characteristic.properties =
        GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_INDICATE;
    ranging_data_overwritten_characteristic.permissions =
        GATT_PERM_READ_ENCRYPTED | key_mask;
    service.push_back(ranging_data_overwritten_characteristic);
    service.push_back(ccc_descriptor);

    BTA_GATTS_AddService(
        server_if_, service,
        base::BindRepeating([](tGATT_STATUS status, int server_if,
                               std::vector<btgatt_db_element_t> service) {
          if (instance) instance->OnServiceAdded(status, server_if, service);
        }));
  }

  void OnServiceAdded(tGATT_STATUS status, int server_if,
                      std::vector<btgatt_db_element_t> service) {
    log::info("status: {}, server_if: {}", gatt_status_text(status), server_if);
    RasCharacteristic* current_characteristic;
    for (uint16_t i = 0; i < service.size(); i++) {
      uint16_t attribute_handle = service[i].attribute_handle;
      Uuid uuid = service[i].uuid;
      if (service[i].type == BTGATT_DB_CHARACTERISTIC) {
        log::info("Characteristic uuid: 0x{:04x}, handle:0x{:04x}, {}",
                  uuid.As16Bit(), attribute_handle, getUuidName(uuid));
        characteristics_[attribute_handle].attribute_handle_ = attribute_handle;
        characteristics_[attribute_handle].uuid_ = uuid;
        current_characteristic = &characteristics_[attribute_handle];
      } else if (service[i].type == BTGATT_DB_DESCRIPTOR) {
        log::info("\tDescriptor uuid: 0x{:04x}, handle: 0x{:04x}, {}",
                  uuid.As16Bit(), attribute_handle, getUuidName(uuid));
        if (service[i].uuid == kClientCharacteristicConfiguration) {
          current_characteristic->attribute_handle_ccc_ = attribute_handle;
        }
      }
    }
  }

 private:
  bluetooth::Uuid app_uuid_;
  uint16_t server_if_;
  // A map to associate characteristics with handles
  std::unordered_map<uint16_t, RasCharacteristic> characteristics_;
};

}  // namespace

bluetooth::ras::RasServer* bluetooth::ras::GetRasServer() {
  if (instance == nullptr) {
    instance = new RasServerImpl();
  }
  return instance;
};
Loading