xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/low_energy/peripheral.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 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 #pragma once
15 
16 #include <cstdint>
17 #include <memory>
18 
19 #include "pw_bluetooth/internal/raii_ptr.h"
20 #include "pw_bluetooth/low_energy/advertising_data.h"
21 #include "pw_bluetooth/low_energy/connection.h"
22 #include "pw_bluetooth/result.h"
23 #include "pw_bluetooth/types.h"
24 #include "pw_function/function.h"
25 #include "pw_status/status.h"
26 
27 namespace pw::bluetooth::low_energy {
28 
29 /// `AdvertisedPeripheral` instances are valid for the duration of advertising.
30 class AdvertisedPeripheral {
31  public:
32   virtual ~AdvertisedPeripheral() = default;
33 
34   /// Set a callback that will be called when an error occurs and advertising
35   /// has been stopped (invalidating this object). It is OK to destroy the
36   /// `AdvertisedPeripheral::Ptr` object from within `callback`.
37   virtual void SetErrorCallback(Closure callback) = 0;
38 
39   /// For connectable advertisements, this callback will be called when an LE
40   /// central connects to the advertisement. It is recommended to set this
41   /// callback immediately after advertising starts to avoid dropping
42   /// connections.
43   ///
44   /// The returned Connection can be used to interact with the peer. It also
45   /// represents a peripheral's ownership over the connection: the client can
46   /// drop the object to request a disconnection. Similarly, the Connection
47   /// error handler is called by the system to indicate that the connection to
48   /// the peer has been lost. While connections are exclusive among peripherals,
49   /// they may be shared with centrals.
50   ///
51   /// If advertising is not stopped, this callback may be called with multiple
52   /// connections over the lifetime of an advertisement. It is OK to destroy
53   /// the `AdvertisedPeripheral::Ptr` object from within `callback` in order to
54   /// stop advertising.
55   virtual void SetConnectionCallback(
56       Function<void(Connection::Ptr)>&& callback) = 0;
57 
58  private:
59   /// Stop advertising. This method is called by the
60   /// ~AdvertisedPeripheral::Ptr() when it goes out of scope, the API client
61   /// should never call this method.
62   virtual void StopAdvertising() = 0;
63 
64  public:
65   /// Movable AdvertisedPeripheral smart pointer. The peripheral will continue
66   /// advertising until the returned AdvertisedPeripheral::Ptr is destroyed.
67   using Ptr = internal::RaiiPtr<AdvertisedPeripheral,
68                                 &AdvertisedPeripheral::StopAdvertising>;
69 };
70 
71 /// Represents the LE Peripheral role, which advertises and is connected to.
72 class Peripheral {
73  public:
74   /// The range of the time interval between advertisements. Shorter intervals
75   /// result in faster discovery at the cost of higher power consumption. The
76   /// exact interval used is determined by the Bluetooth controller.
77   /// - Time = N * 0.625ms.
78   /// - Time range: 0x0020 (20ms) - 0x4000 (10.24s)
79   struct AdvertisingIntervalRange {
80     /// Default: 1.28s
81     uint16_t min = 0x0800;
82     /// Default: 1.28s
83     uint16_t max = 0x0800;
84   };
85 
86   /// Represents the parameters for configuring advertisements.
87   struct AdvertisingParameters {
88     /// The fields that will be encoded in the data section of advertising
89     /// packets.
90     AdvertisingData data;
91 
92     /// The fields that are to be sent in a scan response packet. Clients may
93     /// use this to send additional data that does not fit inside an advertising
94     /// packet on platforms that do not support the advertising data length
95     /// extensions.
96     ///
97     /// If present advertisements will be configured to be scannable.
98     std::optional<AdvertisingData> scan_response;
99 
100     /// See `AdvertisingIntervalRange` documentation.
101     AdvertisingIntervalRange interval_range;
102 
103     /// If present, the controller will broadcast connectable advertisements
104     /// which allow peers to initiate connections to the Peripheral. The fields
105     /// of `ConnectionOptions` will configure any connections set up from
106     /// advertising.
107     std::optional<ConnectionOptions> connection_options;
108   };
109 
110   /// Errors returned by `Advertise`.
111   enum class AdvertiseError {
112     /// The operation or parameters requested are not supported on the current
113     /// hardware.
114     kNotSupported = 1,
115 
116     /// The provided advertising data exceeds the maximum allowed length when
117     /// encoded.
118     kAdvertisingDataTooLong = 2,
119 
120     /// The provided scan response data exceeds the maximum allowed length when
121     /// encoded.
122     kScanResponseDataTooLong = 3,
123 
124     /// The requested parameters are invalid.
125     kInvalidParameters = 4,
126 
127     /// This may be called if the maximum number of simultaneous advertisements
128     /// has already been reached.
129     kNotEnoughAdvertisingSlots = 5,
130 
131     /// Advertising could not be initiated due to a hardware or system error.
132     kFailed = 6,
133   };
134 
135   /// Callback for `Advertise()` method.
136   using AdvertiseCallback =
137       Function<void(Result<AdvertiseError, AdvertisedPeripheral::Ptr>)>;
138 
139   virtual ~Peripheral() = default;
140 
141   /// Start advertising continuously as a LE peripheral. If advertising cannot
142   /// be initiated then `result_callback` will be called with an error. Once
143   /// started, advertising can be stopped by destroying the returned
144   /// `AdvertisedPeripheral::Ptr`.
145   ///
146   /// If the system supports multiple advertising, this may be called as many
147   /// times as there are advertising slots. To reconfigure an advertisement,
148   /// first close the original advertisement and then initiate a new
149   /// advertisement.
150   ///
151   /// @param parameters Parameters used while configuring the advertising
152   /// instance.
153   /// @param result_callback Called once advertising has started or failed. On
154   /// success, called with an `AdvertisedPeripheral` that models the lifetime of
155   /// the advertisement. Destroying it will stop advertising.
156   virtual void Advertise(const AdvertisingParameters& parameters,
157                          AdvertiseCallback&& result_callback) = 0;
158 };
159 
160 }  // namespace pw::bluetooth::low_energy
161