1 // Copyright 2025 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/connection.h"
16
17 namespace pw::bluetooth_sapphire::internal {
18
19 namespace {
20 // This lock has to be global rather than a member variable so that dispatcher
21 // tasks can lock the mutex before dereferencing their weak pointers.
22 pw::sync::Mutex g_connection_lock;
23 } // namespace
24
lock()25 pw::sync::Mutex& Connection::lock() { return g_connection_lock; }
26
Connection(bt::PeerId peer_id,std::unique_ptr<bt::gap::LowEnergyConnectionHandle> handle,pw::async::Dispatcher & dispatcher)27 Connection::Connection(
28 bt::PeerId peer_id,
29 std::unique_ptr<bt::gap::LowEnergyConnectionHandle> handle,
30 pw::async::Dispatcher& dispatcher)
31 : peer_id_(peer_id), dispatcher_(dispatcher), handle_(std::move(handle)) {
32 // This is safe because the constructor is only called on the Bluetooth
33 // thread.
34 handle_->set_closed_callback([self = self_]() PW_NO_LOCK_SAFETY_ANALYSIS {
35 std::lock_guard guard(g_connection_lock);
36 if (!self.is_alive()) {
37 return;
38 }
39 // TODO: https://pwbug.dev/396449684 - Update set_closed_callback with
40 // disconnect reason.
41 self->disconnect_reason_ = DisconnectReason::kFailure;
42 std::move(self->waker_).Wake();
43 });
44 }
45
~Connection()46 Connection::~Connection() {
47 std::lock_guard guard(lock());
48 // This will destroy handle_ on the Bluetooth thread.
49 Status post_status =
50 dispatcher_.Post([handle = std::move(handle_)](auto, auto) {});
51 PW_CHECK_OK(post_status);
52
53 weak_factory_.InvalidatePtrs();
54 }
55
56 async2::Poll<pw::bluetooth::low_energy::Connection2::DisconnectReason>
PendDisconnect(async2::Context & cx)57 Connection::PendDisconnect(async2::Context& cx) {
58 std::lock_guard guard(lock());
59 if (disconnect_reason_) {
60 return async2::Ready(*disconnect_reason_);
61 }
62 PW_ASYNC_STORE_WAKER(cx, waker_, "bt-disconnect");
63 return async2::Pending();
64 }
65
GattClient()66 pw::bluetooth::gatt::Client2* Connection::GattClient() {
67 // TODO: https://pwbug.dev/396449684 - Return Client2
68 return nullptr;
69 }
70
AttMtu()71 uint16_t Connection::AttMtu() {
72 // TODO: https://pwbug.dev/396449684 - Return actual MTU
73 return 0u;
74 }
75
PendAttMtuChange(async2::Context &)76 async2::Poll<uint16_t> Connection::PendAttMtuChange(async2::Context&) {
77 // TODO: https://pwbug.dev/396449684 - Wire up MTU change logic.
78 return async2::Pending();
79 }
80
81 pw::bluetooth::low_energy::Connection2::ConnectionParameters
Parameters()82 Connection::Parameters() {
83 // TODO: https://pwbug.dev/396449684 - Get the actual connection parameters.
84 return pw::bluetooth::low_energy::Connection2::ConnectionParameters();
85 }
86
87 async2::OnceReceiver<pw::expected<
88 void,
89 pw::bluetooth::low_energy::Connection2::ConnectionParameterUpdateError>>
RequestParameterUpdate(RequestedConnectionParameters)90 Connection::RequestParameterUpdate(RequestedConnectionParameters) {
91 // TODO: https://pwbug.dev/396449684 - Update the parameters.
92 return async2::OnceReceiver<
93 pw::expected<void,
94 pw::bluetooth::low_energy::Connection2::
95 ConnectionParameterUpdateError>>();
96 }
97
98 async2::OnceReceiver<pw::Result<pw::bluetooth::low_energy::Channel::Ptr>>
ConnectL2cap(ConnectL2capParameters)99 Connection::ConnectL2cap(ConnectL2capParameters) {
100 // TODO: https://pwbug.dev/396449684 - Open an L2CAP channel.
101 return async2::OnceReceiver<
102 pw::Result<pw::bluetooth::low_energy::Channel::Ptr>>(
103 pw::Status::Unimplemented());
104 }
105
106 } // namespace pw::bluetooth_sapphire::internal
107