blob: ab568d78f6a33aa4c888a39d5de652cda60599c5 [file] [log] [blame] [edit]
// Copyright 2025 The Pigweed Authors
//
// 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
//
// https://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 "pw_bluetooth_sapphire/internal/connection.h"
namespace pw::bluetooth_sapphire::internal {
namespace {
// This lock has to be global rather than a member variable so that dispatcher
// tasks can lock the mutex before dereferencing their weak pointers.
pw::sync::Mutex g_connection_lock;
} // namespace
pw::sync::Mutex& Connection::lock() { return g_connection_lock; }
Connection::Connection(
bt::PeerId peer_id,
std::unique_ptr<bt::gap::LowEnergyConnectionHandle> handle,
pw::async::Dispatcher& dispatcher)
: peer_id_(peer_id), dispatcher_(dispatcher), handle_(std::move(handle)) {
// This is safe because the constructor is only called on the Bluetooth
// thread.
handle_->set_closed_callback([self = self_]() PW_NO_LOCK_SAFETY_ANALYSIS {
std::lock_guard guard(g_connection_lock);
if (!self.is_alive()) {
return;
}
// TODO: https://pwbug.dev/396449684 - Update set_closed_callback with
// disconnect reason.
self->disconnect_reason_ = DisconnectReason::kFailure;
std::move(self->waker_).Wake();
});
}
Connection::~Connection() {
std::lock_guard guard(lock());
// This will destroy handle_ on the Bluetooth thread.
Status post_status =
dispatcher_.Post([handle = std::move(handle_)](auto, auto) {});
PW_CHECK_OK(post_status);
weak_factory_.InvalidatePtrs();
}
async2::Poll<pw::bluetooth::low_energy::Connection2::DisconnectReason>
Connection::PendDisconnect(async2::Context& cx) {
std::lock_guard guard(lock());
if (disconnect_reason_) {
return async2::Ready(*disconnect_reason_);
}
PW_ASYNC_STORE_WAKER(cx, waker_, "bt-disconnect");
return async2::Pending();
}
pw::bluetooth::gatt::Client2* Connection::GattClient() {
// TODO: https://pwbug.dev/396449684 - Return Client2
return nullptr;
}
uint16_t Connection::AttMtu() {
// TODO: https://pwbug.dev/396449684 - Return actual MTU
return 0u;
}
async2::Poll<uint16_t> Connection::PendAttMtuChange(async2::Context&) {
// TODO: https://pwbug.dev/396449684 - Wire up MTU change logic.
return async2::Pending();
}
pw::bluetooth::low_energy::Connection2::ConnectionParameters
Connection::Parameters() {
// TODO: https://pwbug.dev/396449684 - Get the actual connection parameters.
return pw::bluetooth::low_energy::Connection2::ConnectionParameters();
}
async2::OnceReceiver<pw::expected<
void,
pw::bluetooth::low_energy::Connection2::ConnectionParameterUpdateError>>
Connection::RequestParameterUpdate(RequestedConnectionParameters) {
// TODO: https://pwbug.dev/396449684 - Update the parameters.
return async2::OnceReceiver<
pw::expected<void,
pw::bluetooth::low_energy::Connection2::
ConnectionParameterUpdateError>>();
}
async2::OnceReceiver<pw::Result<pw::bluetooth::low_energy::Channel::Ptr>>
Connection::ConnectL2cap(ConnectL2capParameters) {
// TODO: https://pwbug.dev/396449684 - Open an L2CAP channel.
return async2::OnceReceiver<
pw::Result<pw::bluetooth::low_energy::Channel::Ptr>>(
pw::Status::Unimplemented());
}
} // namespace pw::bluetooth_sapphire::internal