blob: 9bb57d3f7ace77a5935606eaf198f17411cc4f7c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "low_energy_connection_server.h"
#include "src/connectivity/bluetooth/core/bt-host/fidl/helpers.h"
namespace bthost {
namespace fbg = fuchsia::bluetooth::gatt2;
LowEnergyConnectionServer::LowEnergyConnectionServer(
bt::gap::Adapter::WeakPtr adapter, bt::gatt::GATT::WeakPtr gatt,
std::unique_ptr<bt::gap::LowEnergyConnectionHandle> connection, zx::channel handle,
fit::callback<void()> closed_cb)
: ServerBase(this, std::move(handle)),
conn_(std::move(connection)),
closed_handler_(std::move(closed_cb)),
peer_id_(conn_->peer_identifier()),
adapter_(std::move(adapter)),
gatt_(std::move(gatt)) {
BT_DEBUG_ASSERT(conn_);
set_error_handler([this](zx_status_t) { OnClosed(); });
conn_->set_closed_callback(fit::bind_member<&LowEnergyConnectionServer::OnClosed>(this));
}
void LowEnergyConnectionServer::OnClosed() {
if (closed_handler_) {
binding()->Close(ZX_ERR_CONNECTION_RESET);
closed_handler_();
}
}
void LowEnergyConnectionServer::RequestGattClient(fidl::InterfaceRequest<fbg::Client> client) {
if (gatt_client_server_.has_value()) {
bt_log(INFO, "fidl", "%s: gatt client server already bound (peer: %s)", __FUNCTION__,
bt_str(peer_id_));
client.Close(ZX_ERR_ALREADY_BOUND);
return;
}
fit::callback<void()> server_error_cb = [this] {
bt_log(TRACE, "fidl", "gatt client server error (peer: %s)", bt_str(peer_id_));
gatt_client_server_.reset();
};
gatt_client_server_.emplace(peer_id_, gatt_, std::move(client), std::move(server_error_cb));
}
void LowEnergyConnectionServer::AcceptCis(
fuchsia::bluetooth::le::ConnectionAcceptCisRequest parameters) {}
void LowEnergyConnectionServer::GetCodecLocalDelayRange(
::fuchsia::bluetooth::le::CodecDelayGetCodecLocalDelayRangeRequest parameters,
GetCodecLocalDelayRangeCallback callback) {
bt_log(INFO, "fidl", "request received to read controller supported delay");
if (!parameters.has_logical_transport_type()) {
bt_log(WARN, "fidl", "request to read controller delay missing logical_transport_type");
callback(fpromise::error(ZX_ERR_INVALID_ARGS));
return;
}
if (!parameters.has_data_direction()) {
bt_log(WARN, "fidl", "request to read controller delay missing data_direction");
callback(fpromise::error(ZX_ERR_INVALID_ARGS));
return;
}
if (!parameters.has_codec_attributes()) {
bt_log(WARN, "fidl", "request to read controller delay missing codec_attributes");
callback(fpromise::error(ZX_ERR_INVALID_ARGS));
return;
}
if (!parameters.codec_attributes().has_codec_id()) {
bt_log(WARN, "fidl", "request to read controller delay missing codec_id");
callback(fpromise::error(ZX_ERR_INVALID_ARGS));
return;
}
// Process required parameters
pw::bluetooth::emboss::LogicalTransportType transport_type =
fidl_helpers::LogicalTransportTypeFromFidl(parameters.logical_transport_type());
pw::bluetooth::emboss::DataPathDirection direction =
fidl_helpers::DataPathDirectionFromFidl(parameters.data_direction());
bt::StaticPacket<pw::bluetooth::emboss::CodecIdWriter> codec_id =
fidl_helpers::CodecIdFromFidl(parameters.codec_attributes().codec_id());
// Codec configuration is optional
std::optional<std::vector<uint8_t>> codec_configuration;
if (parameters.codec_attributes().has_codec_configuration()) {
codec_configuration = parameters.codec_attributes().codec_configuration();
} else {
codec_configuration = std::nullopt;
}
adapter_->GetSupportedDelayRange(
codec_id, transport_type, direction, codec_configuration,
[callback = std::move(callback)](zx_status_t status, uint32_t min_delay_us,
uint32_t max_delay_us) {
if (status != ZX_OK) {
bt_log(WARN, "fidl", "failed to get controller supported delay");
callback(fpromise::error(ZX_ERR_INTERNAL));
return;
}
bt_log(INFO, "fidl", "controller supported delay [%d, %d] microseconds", min_delay_us,
max_delay_us);
fuchsia::bluetooth::le::CodecDelay_GetCodecLocalDelayRange_Response response;
zx::duration min_delay = zx::usec(min_delay_us);
zx::duration max_delay = zx::usec(max_delay_us);
response.set_min_controller_delay(min_delay.get());
response.set_max_controller_delay(max_delay.get());
callback(fuchsia::bluetooth::le::CodecDelay_GetCodecLocalDelayRange_Result::WithResponse(
std::move(response)));
});
}
} // namespace bthost