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