Pigweed
 
Loading...
Searching...
No Matches
central.h
1// Copyright 2024 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#pragma once
16
17#include "pw_bluetooth/low_energy/central2.h"
18#include "pw_bluetooth_sapphire/internal/connection.h"
19#include "pw_bluetooth_sapphire/internal/host/gap/adapter.h"
20#include "pw_multibuf/allocator.h"
21
22namespace pw::bluetooth_sapphire {
23
26 public:
27 // The maximum number of scan results to queue in each ScanHandle
28 static constexpr uint8_t kMaxScanResultsQueueSize = 10;
29
30 // TODO: https://pwbug.dev/377301546 - Don't expose Adapter in public API.
33 Central(bt::gap::Adapter::WeakPtr adapter,
34 pw::async::Dispatcher& dispatcher,
36 ~Central() override;
37
39 pw::bluetooth::PeerId peer_id,
41 PW_LOCKS_EXCLUDED(lock());
42
44 const ScanOptions& options) override PW_LOCKS_EXCLUDED(lock());
45
46 static pw::sync::Mutex& lock();
47
48 private:
49 class ScanHandleImpl final : public ScanHandle {
50 public:
51 explicit ScanHandleImpl(uint16_t scan_id, Central* central)
52 : scan_id_(scan_id), central_(central) {}
53
54 // Synchronously clears ScanState's pointer to this object and
55 // asynchronously stops the scan procedure.
56 ~ScanHandleImpl() override;
57
58 void QueueScanResultLocked(ScanResult&& result)
59 PW_EXCLUSIVE_LOCKS_REQUIRED(lock());
60
61 void WakeLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(lock()) {
62 std::move(waker_).Wake();
63 }
64
65 void OnScanErrorLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(lock()) {
66 central_ = nullptr;
67 WakeLocked();
68 }
69
70 private:
71 async2::Poll<pw::Result<ScanResult>> PendResult(
72 async2::Context& cx) override;
73
74 // std::unique_ptr custom Deleter
75 void Release() override { delete this; }
76
77 const uint16_t scan_id_;
78
79 // Set to null when Central is destroyed or scanning has stopped.
80 Central* central_ PW_GUARDED_BY(lock());
81
82 // PendResult() waker. Set when Pending was returned.
83 async2::Waker waker_ PW_GUARDED_BY(lock());
84 std::queue<ScanResult> results_ PW_GUARDED_BY(lock());
85 };
86
87 // Created and destroyed on the Bluetooth thread.
88 class ScanState {
89 public:
90 // Must be run on Bluetooth thread. Not thread safe.
91 explicit ScanState(
92 std::unique_ptr<bt::gap::LowEnergyDiscoverySession> session,
93 ScanHandleImpl* scan_handle,
94 uint16_t scan_id,
95 Central* central);
96
97 ~ScanState();
98
99 void OnScanHandleDestroyedLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(lock()) {
100 scan_handle_ = nullptr;
101 }
102
103 private:
104 // Must be run on Bluetooth thread. Not thread safe.
105 void OnScanResult(const bt::gap::Peer& peer) PW_LOCKS_EXCLUDED(lock());
106
107 // Must be run on Bluetooth thread. Not thread safe.
108 void OnError() PW_LOCKS_EXCLUDED(lock());
109
110 const uint16_t scan_id_;
111
112 // Set to null synchronously when ScanHandleImpl is destroyed.
113 ScanHandleImpl* scan_handle_ PW_GUARDED_BY(lock());
114
115 // Members must only be accessed on Bluetooth thread.
116 Central* const central_;
117 std::unique_ptr<bt::gap::LowEnergyDiscoverySession> session_;
118 };
119
120 // Asynchronously stops the scan corresponding to `scan_id` and synchronously
121 // clears `ScanState.scan_handle_`.
122 void StopScanLocked(uint16_t scan_id) PW_EXCLUSIVE_LOCKS_REQUIRED(lock());
123
124 void OnConnectionResult(bt::PeerId peer_id,
125 bt::gap::Adapter::LowEnergy::ConnectionResult result,
126 async2::OnceSender<ConnectResult> result_sender)
127 PW_LOCKS_EXCLUDED(lock());
128
129 std::unordered_map<uint16_t, ScanState> scans_ PW_GUARDED_BY(lock());
130
131 // Must only be used on the Bluetooth thread.
132 bt::gap::Adapter::WeakPtr adapter_;
133
134 // Dispatcher for Bluetooth thread. Thread safe.
135 pw::async::Dispatcher& dispatcher_;
136 pw::async::HeapDispatcher heap_dispatcher_;
137
138 pw::multibuf::MultiBufAllocator& allocator_;
139
140 // Must only be used on the Bluetooth thread.
141 WeakSelf<Central> weak_factory_{this};
142
143 // Thread safe to copy and destroy, but WeakPtr should only be used
144 // or dereferenced on the Bluetooth thread (WeakRef is not thread safe).
145 WeakSelf<Central>::WeakPtr self_{weak_factory_.GetWeakPtr()};
146};
147
148} // namespace pw::bluetooth_sapphire
Definition: once_sender.h:41
Definition: dispatcher.h:45
Represents an ongoing LE scan.
Definition: central2.h:146
Represents the LE central role. Used to scan and connect to peripherals.
Definition: central2.h:29
pw::expected< Connection2::Ptr, ConnectError > ConnectResult
The result type returned by Connect().
Definition: central2.h:204
Must only be constructed and destroyed on the Bluetooth thread.
Definition: central.h:25
async2::OnceReceiver< ScanStartResult > Scan(const ScanOptions &options) override
Central(bt::gap::Adapter::WeakPtr adapter, pw::async::Dispatcher &dispatcher, pw::multibuf::MultiBufAllocator &allocator)
Definition: allocator.h:54
Definition: mutex.h:42
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Parameters used during a scan.
Definition: central2.h:87
Represents parameters that are set on a per-connection basis.
Definition: connection2.h:109