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

Commit 6a66f472 authored by Chienyuan Huang's avatar Chienyuan Huang Committed by Gerrit Code Review
Browse files

Merge "CS: Handle vendor specific reply" into main

parents b74367aa 8eedc5b5
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -28,15 +28,28 @@ namespace ras {
struct VendorSpecificCharacteristic {
  bluetooth::Uuid characteristicUuid_;
  std::vector<uint8_t> value_;
  std::vector<uint8_t> reply_value_;
};

class RasServerCallbacks {
 public:
  virtual ~RasServerCallbacks() = default;
  virtual void OnVendorSpecificReply(
      const RawAddress& address,
      const std::vector<VendorSpecificCharacteristic>&
          vendor_specific_reply) = 0;
};

class RasServer {
 public:
  virtual ~RasServer() = default;
  virtual void Initialize() = 0;
  virtual void RegisterCallbacks(RasServerCallbacks* callbacks) = 0;
  virtual void SetVendorSpecificCharacteristic(
      const std::vector<VendorSpecificCharacteristic>&
          vendor_specific_characteristics) = 0;
  virtual void HandleVendorSpecificReplyComplete(RawAddress address,
                                                 bool success) = 0;
  virtual void PushProcedureData(RawAddress address, uint16_t procedure_count,
                                 bool is_last, std::vector<uint8_t> data) = 0;
};
@@ -49,6 +62,8 @@ class RasClientCallbacks {
  virtual void OnConnected(const RawAddress& address, uint16_t att_handle,
                           const std::vector<VendorSpecificCharacteristic>&
                               vendor_specific_characteristics) = 0;
  virtual void OnWriteVendorSpecificReplyComplete(const RawAddress& address,
                                                  bool success) = 0;
  virtual void OnRemoteData(const RawAddress& address,
                            const std::vector<uint8_t>& data) = 0;
};
+64 −7
Original line number Diff line number Diff line
@@ -34,8 +34,14 @@ namespace {
class RasClientImpl;
RasClientImpl* instance;

enum CallbackDataType { VENDOR_SPECIFIC_REPLY };

class RasClientImpl : public bluetooth::ras::RasClient {
 public:
  struct GattWriteCallbackData {
    const CallbackDataType type_;
  };

  struct RasTracker {
    RasTracker(const RawAddress& address, const RawAddress& address_for_cs)
        : address_(address), address_for_cs_(address_for_cs) {}
@@ -47,6 +53,8 @@ class RasClientImpl : public bluetooth::ras::RasClient {
    uint16_t latest_ranging_counter_ = 0;
    bool handling_on_demand_data_ = false;
    std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics_;
    uint8_t writeReplyCounter_ = 0;
    uint8_t writeReplySuccessCounter_ = 0;

    const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) {
      for (auto& characteristic : service_->characteristics) {
@@ -97,10 +105,9 @@ class RasClientImpl : public bluetooth::ras::RasClient {
  }

  void Connect(const RawAddress& address) override {
    log::info("{}", address);
    tBLE_BD_ADDR ble_bd_addr;
    ResolveAddress(ble_bd_addr, address);
    log::info("resolve {}", ble_bd_addr.bda);
    log::info("address {}, resolve {}", address, ble_bd_addr.bda);

    auto tracker = FindTrackerByAddress(ble_bd_addr.bda);
    if (tracker == nullptr) {
@@ -118,7 +125,6 @@ class RasClientImpl : public bluetooth::ras::RasClient {
    log::info("address {}, resolve {}", address, ble_bd_addr.bda);
    auto tracker = FindTrackerByAddress(ble_bd_addr.bda);

    uint8_t index = 1;
    for (auto& vendor_specific_characteristic : vendor_specific_data) {
      auto characteristic = tracker->FindCharacteristicByUuid(
          vendor_specific_characteristic.characteristicUuid_);
@@ -130,10 +136,10 @@ class RasClientImpl : public bluetooth::ras::RasClient {
      log::debug("write to remote, uuid {}, len {}",
                 vendor_specific_characteristic.characteristicUuid_,
                 vendor_specific_characteristic.value_.size());
      BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle,
                               GATT_WRITE,
                               vendor_specific_characteristic.value_,
                               GATT_AUTH_REQ_MITM, GattWriteCallback, nullptr);
      BTA_GATTC_WriteCharValue(
          tracker->conn_id_, characteristic->value_handle, GATT_WRITE,
          vendor_specific_characteristic.value_, GATT_AUTH_REQ_MITM,
          GattWriteCallback, &gatt_write_callback_data_);
    }
  }

@@ -372,6 +378,46 @@ class RasClientImpl : public bluetooth::ras::RasClient {
    }
  }

  void GattWriteCallbackForVendorSpecificData(uint16_t conn_id,
                                              tGATT_STATUS status,
                                              uint16_t handle,
                                              const uint8_t* value,
                                              GattWriteCallbackData* data) {
    if (data != nullptr) {
      GattWriteCallbackData* structPtr =
          static_cast<GattWriteCallbackData*>(data);
      if (structPtr->type_ == CallbackDataType::VENDOR_SPECIFIC_REPLY) {
        log::info("Write vendor specific reply complete");
        auto tracker = FindTrackerByHandle(conn_id);
        tracker->writeReplyCounter_++;
        if (status == GATT_SUCCESS) {
          tracker->writeReplySuccessCounter_++;
        } else {
          log::error(
              "Fail to write vendor specific reply conn_id {}, status {}, "
              "handle {}",
              conn_id, gatt_status_text(status), handle);
        }
        // All reply complete
        if (tracker->writeReplyCounter_ ==
            tracker->vendor_specific_characteristics_.size()) {
          log::info(
              "All vendor specific reply write complete, size {} "
              "successCounter {}",
              tracker->vendor_specific_characteristics_.size(),
              tracker->writeReplySuccessCounter_);
          bool success = tracker->writeReplySuccessCounter_ ==
                         tracker->vendor_specific_characteristics_.size();
          tracker->writeReplyCounter_ = 0;
          tracker->writeReplySuccessCounter_ = 0;
          callbacks_->OnWriteVendorSpecificReplyComplete(
              tracker->address_for_cs_, success);
        }
        return;
      }
    }
  }

  void GattWriteCallback(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
                         const uint8_t* value) {
    if (status != GATT_SUCCESS) {
@@ -400,6 +446,15 @@ class RasClientImpl : public bluetooth::ras::RasClient {
                                uint16_t handle, uint16_t len,
                                const uint8_t* value, void* data) {
    if (instance != nullptr) {
      if (data != nullptr) {
        GattWriteCallbackData* structPtr =
            static_cast<GattWriteCallbackData*>(data);
        if (structPtr->type_ == CallbackDataType::VENDOR_SPECIFIC_REPLY) {
          instance->GattWriteCallbackForVendorSpecificData(
              conn_id, status, handle, value, structPtr);
          return;
        }
      }
      instance->GattWriteCallback(conn_id, status, handle, value);
    }
  }
@@ -605,6 +660,8 @@ class RasClientImpl : public bluetooth::ras::RasClient {
  uint16_t gatt_if_;
  std::list<std::shared_ptr<RasTracker>> trackers_;
  bluetooth::ras::RasClientCallbacks* callbacks_;
  GattWriteCallbackData gatt_write_callback_data_{
      CallbackDataType::VENDOR_SPECIFIC_REPLY};
};

}  // namespace
+83 −4
Original line number Diff line number Diff line
@@ -55,11 +55,19 @@ class RasServerImpl : public bluetooth::ras::RasServer {
    std::vector<std::vector<uint8_t>> segments_;
  };

  struct PendingWriteResponse {
    uint16_t conn_id_;
    uint32_t trans_id_;
    uint16_t write_req_handle_;
  };

  struct ClientTracker {
    uint16_t conn_id_;
    std::unordered_map<Uuid, uint16_t> ccc_values_;
    std::vector<DataBuffer> buffers_;
    bool handling_control_point_command_ = false;
    uint8_t vendor_specific_reply_counter_ = 0;
    PendingWriteResponse pending_write_response_;
  };

  void Initialize() {
@@ -74,12 +82,31 @@ class RasServerImpl : public bluetooth::ras::RasServer {
        false);
  }

  void RegisterCallbacks(bluetooth::ras::RasServerCallbacks* callbacks) {
    callbacks_ = callbacks;
  }

  void SetVendorSpecificCharacteristic(
      const std::vector<VendorSpecificCharacteristic>&
          vendor_specific_characteristics) {
    vendor_specific_characteristics_ = vendor_specific_characteristics;
  }

  void HandleVendorSpecificReplyComplete(RawAddress address, bool success) {
    log::info("address:{}, success:{}", address, success);
    tBLE_BD_ADDR ble_bd_addr;
    ResolveAddress(ble_bd_addr, address);
    if (trackers_.find(ble_bd_addr.bda) == trackers_.end()) {
      log::warn("Can't find tracker for address {}", address);
      return;
    };
    auto response = trackers_[ble_bd_addr.bda].pending_write_response_;
    tGATTS_RSP p_msg;
    p_msg.attr_value.handle = response.write_req_handle_;
    GattStatus status = success ? GATT_SUCCESS : GATT_ERROR;
    BTA_GATTS_SendRsp(response.conn_id_, response.trans_id_, status, &p_msg);
  }

  void PushProcedureData(RawAddress address, uint16_t procedure_counter,
                         bool is_last, std::vector<uint8_t> data) {
    log::debug("{}, counter:{}, is_last:{}, with size {}", address,
@@ -386,8 +413,10 @@ class RasServerImpl : public bluetooth::ras::RasServer {
    uint16_t conn_id = p_data->req_data.conn_id;
    uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle;
    uint16_t len = p_data->req_data.p_data->write_req.len;
    log::info("conn_id:{}, write_req_handle:{}, len:{}", conn_id,
              write_req_handle, len);
    bool need_rsp = p_data->req_data.p_data->write_req.need_rsp;
    RawAddress remote_bda = p_data->req_data.remote_bda;
    log::info("conn_id:{}, write_req_handle:0x{:04x}, need_rsp{}, len:{}",
              conn_id, write_req_handle, need_rsp, len);

    tGATTS_RSP p_msg;
    p_msg.handle = write_req_handle;
@@ -399,6 +428,12 @@ class RasServerImpl : public bluetooth::ras::RasServer {
    }

    auto uuid = characteristics_[write_req_handle].uuid_;
    auto vendor_specific_characteristic = GetVendorSpecificCharacteristic(uuid);
    if (vendor_specific_characteristic != nullptr) {
      WriteVendorSpecificCharacteristic(vendor_specific_characteristic, p_data,
                                        p_msg);
      return;
    }
    log::info("Write uuid, {}", getUuidName(uuid));

    // Check Characteristic UUID
@@ -417,8 +452,10 @@ class RasServerImpl : public bluetooth::ras::RasServer {
                            GATT_PRC_IN_PROGRESS, &p_msg);
          return;
        }
        if (need_rsp) {
          BTA_GATTS_SendRsp(conn_id, p_data->req_data.trans_id, GATT_SUCCESS,
                            &p_msg);
        }
        HandleControlPoint(tracker, &p_data->req_data.p_data->write_req);
      } break;
      default:
@@ -429,6 +466,47 @@ class RasServerImpl : public bluetooth::ras::RasServer {
    }
  }

  void WriteVendorSpecificCharacteristic(
      VendorSpecificCharacteristic* vendor_specific_characteristic,
      tBTA_GATTS* p_data, tGATTS_RSP& p_msg) {
    log::debug("uuid {}", vendor_specific_characteristic->characteristicUuid_);
    uint16_t len = p_data->req_data.p_data->write_req.len;
    RawAddress remote_bda = p_data->req_data.remote_bda;

    if (trackers_.find(remote_bda) == trackers_.end()) {
      BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
                        GATT_INVALID_HANDLE, &p_msg);
      log::warn("Can't find tracker for remote_bda {}", remote_bda);
      return;
    }

    // Update reply value
    auto& tracker = trackers_[remote_bda];
    auto value = p_data->req_data.p_data->write_req.value;
    vendor_specific_characteristic->reply_value_.clear();
    vendor_specific_characteristic->reply_value_.reserve(len);
    vendor_specific_characteristic->reply_value_.assign(value, value + len);
    tracker.vendor_specific_reply_counter_++;

    if (tracker.vendor_specific_reply_counter_ ==
        vendor_specific_characteristics_.size()) {
      log::info("All vendor specific characteristics written");
      tBLE_BD_ADDR ble_bd_addr;
      ble_bd_addr.bda = remote_bda;
      ble_bd_addr.type = BLE_ADDR_RANDOM;
      btm_random_pseudo_to_identity_addr(&ble_bd_addr.bda, &ble_bd_addr.type);
      tracker.vendor_specific_reply_counter_ = 0;
      tracker.pending_write_response_.conn_id_ = p_data->req_data.conn_id;
      tracker.pending_write_response_.trans_id_ = p_data->req_data.trans_id;
      tracker.pending_write_response_.write_req_handle_ = p_msg.handle;
      callbacks_->OnVendorSpecificReply(ble_bd_addr.bda,
                                        vendor_specific_characteristics_);
    } else {
      BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id,
                        GATT_SUCCESS, &p_msg);
    }
  }

  void OnWriteDescriptor(tBTA_GATTS* p_data) {
    uint16_t conn_id = p_data->req_data.conn_id;
    uint16_t write_req_handle = p_data->req_data.p_data->write_req.handle;
@@ -648,6 +726,7 @@ class RasServerImpl : public bluetooth::ras::RasServer {
  std::unordered_map<uint16_t, RasCharacteristic> characteristics_;
  // A map to client trackers with address
  std::unordered_map<RawAddress, ClientTracker> trackers_;
  bluetooth::ras::RasServerCallbacks* callbacks_;
  std::mutex on_demand_ranging_mutex_;
  std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics_;
};
+3 −0
Original line number Diff line number Diff line
@@ -134,6 +134,9 @@ std::string GetResponseOpcodeValueText(ResponseCodeValue response_code_value) {
}

bool IsRangingServiceCharacteristic(const bluetooth::Uuid& uuid) {
  if (!uuid.Is16Bit()) {
    return false;
  }
  switch (uuid.As16Bit()) {
    case kRangingService16Bit:
    case kRasFeaturesCharacteristic16bit:
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ class RangingHalCallback {
      uint16_t connection_handle,
      const std::vector<VendorSpecificCharacteristic>& vendor_specific_reply) = 0;
  virtual void OnOpenFailed(uint16_t connection_handle) = 0;
  virtual void OnHandleVendorSpecificReplyComplete(uint16_t connection_handle, bool success) = 0;
};

class RangingHal : public ::bluetooth::Module {
@@ -47,6 +48,9 @@ class RangingHal : public ::bluetooth::Module {
      uint16_t connection_handle,
      uint16_t att_handle,
      const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_data) = 0;
  virtual void HandleVendorSpecificReply(
      uint16_t connection_handle,
      const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_reply) = 0;
};

}  // namespace hal
Loading