Pigweed
 
Loading...
Searching...
No Matches
peripheral.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/peripheral2.h"
18#include "pw_bluetooth_sapphire/internal/host/gap/adapter.h"
19
20namespace pw::bluetooth_sapphire {
21
24 public:
25 // TODO: https://pwbug.dev/377301546 - Don't expose Adapter in public API.
27 Peripheral(bt::gap::Adapter::WeakPtr adapter,
28 pw::async::Dispatcher& dispatcher);
29
31 ~Peripheral() override;
32
36 const AdvertisingParameters& parameters) override
37 PW_LOCKS_EXCLUDED(lock());
38
39 static pw::sync::Mutex& lock();
40
41 private:
42 class Advertisement;
43
44 // Thin client handle for an active advertisement.
45 // Thread safe.
46 class AdvertisedPeripheralImpl final
48 public:
49 AdvertisedPeripheralImpl(bt::gap::AdvertisementId id,
50 Peripheral* peripheral)
51 : id_(id), peripheral_(peripheral) {}
52 ~AdvertisedPeripheralImpl() override {
53 std::lock_guard lock(Peripheral::lock());
54 if (peripheral_) {
55 peripheral_->OnAdvertisedPeripheralDestroyedLocked(id_);
56 }
57 }
58
59 // AdvertisedPeripheral2 overrides:
60 async2::Poll<pw::bluetooth::low_energy::Connection2::Ptr> PendConnection(
61 [[maybe_unused]] async2::Context& cx) override {
62 // TODO: https://pwbug.dev/377301546 - Implement connection handling.
63 return async2::Pending();
64 }
65 void StopAdvertising() override;
66 async2::Poll<pw::Status> PendStop(async2::Context& cx) override;
67 void Release() override { delete this; }
68
69 private:
70 friend class Advertisement;
71
72 const bt::gap::AdvertisementId id_;
73
74 // Set to null if the advertisement is stopped or Peripheral is destroyed.
75 Peripheral* peripheral_ PW_GUARDED_BY(lock());
76
77 std::optional<pw::Status> stop_status_ PW_GUARDED_BY(lock());
78
79 // Waker shared by PendConnection() and PendStop().
80 async2::Waker waker_ PW_GUARDED_BY(lock());
81 };
82
83 // Active advertisement state. Must only be destroyed on the Bluetooth thread.
84 class Advertisement final {
85 public:
86 Advertisement(bt::gap::AdvertisementInstance&& instance,
87 AdvertisedPeripheralImpl* advertised_peripheral)
88 : advertised_peripheral_(advertised_peripheral),
89 instance_(std::move(instance)) {}
90
91 // Must only be destroyed on Bluetooth thread.
92 ~Advertisement();
93
94 void OnAdvertisedPeripheralDestroyedLocked()
95 PW_EXCLUSIVE_LOCKS_REQUIRED(lock()) {
96 advertised_peripheral_ = nullptr;
97 }
98
99 void OnStopLocked(pw::Status status) PW_EXCLUSIVE_LOCKS_REQUIRED(lock());
100
101 private:
102 friend class AdvertisedPeripheralImpl;
103
104 AdvertisedPeripheralImpl* advertised_peripheral_;
105
106 // Must only be modified/destroyed on the Bluetooth thread.
107 bt::gap::AdvertisementInstance instance_;
108 };
109
110 // Thread safe.
111 void OnAdvertisedPeripheralDestroyedLocked(
112 bt::gap::AdvertisementId advertisement_id)
113 PW_EXCLUSIVE_LOCKS_REQUIRED(lock());
114
115 // Thread safe. The lock may be held when calling this function as the stop
116 // message is immediately posted to the Bluetooth thread.
117 void StopAdvertising(bt::gap::AdvertisementId advertisement_id);
118
119 // Always called on Bluetooth thread.
120 void OnAdvertiseResult(bt::gap::AdvertisementInstance instance,
121 bt::hci::Result<> result,
122 async2::OnceSender<AdvertiseResult> result_sender);
123
124 // Always called on Bluetooth thread.
125 void OnConnection(bt::gap::AdvertisementId advertisement_id,
126 bt::gap::Adapter::LowEnergy::ConnectionResult result);
127
128 // Dispatcher for Bluetooth thread. Thread safe.
129 pw::async::HeapDispatcher dispatcher_;
130
131 // Must only be used on the Bluetooth thread.
132 bt::gap::Adapter::WeakPtr adapter_;
133
134 std::unordered_map<bt::gap::AdvertisementId, Advertisement> advertisements_
135 PW_GUARDED_BY(lock());
136
137 // Must only be used on the Bluetooth thread.
138 WeakSelf<Peripheral> weak_factory_{this};
139
140 // Thread safe to copy and destroy, but WeakPtr should only be used
141 // or dereferenced on the Bluetooth thread (WeakRef is not thread safe).
142 WeakSelf<Peripheral>::WeakPtr self_{weak_factory_.GetWeakPtr()};
143};
144
145} // namespace pw::bluetooth_sapphire
Definition: status.h:85
Definition: once_sender.h:41
Definition: dispatcher.h:45
Definition: heap_dispatcher.h:23
AdvertisedPeripheral instances are valid for the duration of advertising.
Definition: peripheral2.h:32
Represents the LE Peripheral role, which advertises and is connected to.
Definition: peripheral2.h:91
Must only be constructed and destroyed on the Bluetooth thread.
Definition: peripheral.h:23
async2::OnceReceiver< AdvertiseResult > Advertise(const AdvertisingParameters &parameters) override
~Peripheral() override
Must only be destroyed on the Bluetooth thread.
Peripheral(bt::gap::Adapter::WeakPtr adapter, pw::async::Dispatcher &dispatcher)
Must only be constructed on the Bluetooth thread.
Definition: mutex.h:42
Represents the parameters for configuring advertisements.
Definition: peripheral2.h:161