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 <optional> 17 #include <string_view> 18 19 #include "pw_bluetooth/controller.h" 20 #include "pw_bluetooth/gatt/client.h" 21 #include "pw_bluetooth/gatt/server.h" 22 #include "pw_bluetooth/low_energy/bond_data.h" 23 #include "pw_bluetooth/low_energy/central.h" 24 #include "pw_bluetooth/low_energy/peripheral.h" 25 #include "pw_bluetooth/low_energy/security_mode.h" 26 #include "pw_bluetooth/pairing_delegate.h" 27 #include "pw_bluetooth/peer.h" 28 #include "pw_bluetooth/types.h" 29 #include "pw_function/function.h" 30 #include "pw_span/span.h" 31 #include "pw_status/status.h" 32 33 namespace pw::bluetooth { 34 35 /// Host is the entrypoint API for interacting with a Bluetooth host stack. Host 36 /// is an abstract class that is implemented by a host stack implementation. 37 class Host { 38 public: 39 /// Represents the persistent configuration of a single Host instance. This is 40 /// used for identity representation in advertisements & bonding secrets 41 /// recall. 42 struct PersistentData { 43 /// The local Identity Resolving Key used by a Host to generate Resolvable 44 /// Private Addresses when privacy is enabled. May be absent for hosts that 45 /// do not use LE privacy, or that only use Non-Resolvable Private 46 /// Addresses. 47 /// 48 /// NOTE: This key is distributed to LE peers during pairing procedures. The 49 /// client must take care to assign an IRK that consistent with the local 50 /// Host identity. 51 std::optional<Key> identity_resolving_key; 52 53 /// All bonds that use a public identity address must contain the same local 54 /// address. 55 span<const low_energy::BondData> bonds; 56 }; 57 58 /// The security level required for this pairing. This corresponds to the 59 /// security levels defined in the Security Manager Protocol in Core spec 60 /// v5.3, Vol 3, Part H, Section 2.3.1 61 enum class PairingSecurityLevel : uint8_t { 62 /// Encrypted without person-in-the-middle protection (unauthenticated) 63 kEncrypted, 64 /// Encrypted with person-in-the-middle protection (authenticated), although 65 /// this level of security does not fully protect against passive 66 /// eavesdroppers 67 kAuthenticated, 68 /// Encrypted with person-in-the-middle protection (authenticated). 69 /// This level of security fully protects against eavesdroppers. 70 kLeSecureConnections, 71 }; 72 73 /// Whether or not the device should form a bluetooth bond during the pairing 74 /// prodecure. As described in Core Spec v5.2, Vol 3, Part C, Sec 4.3 75 enum class BondableMode : uint8_t { 76 /// The device will form a bond during pairing with peers 77 kBondable, 78 /// The device will not form a bond during pairing with peers 79 kNonBondable, 80 }; 81 82 /// Parameters that give a caller more fine-grained control over the pairing 83 /// process. 84 struct PairingOptions { 85 /// Determines the Security Manager security level to pair with. 86 PairingSecurityLevel security_level = PairingSecurityLevel::kAuthenticated; 87 88 /// Indicated whether the device should form a bond or not during pairing. 89 /// If not present, interpreted as bondable mode. 90 BondableMode bondable_mode = BondableMode::kBondable; 91 }; 92 93 /// `Close()` should complete before `Host` is destroyed. 94 virtual ~Host() = default; 95 96 /// Initializes the host stack. Vendor specific controller initialization 97 /// (e.g. loading firmware) must be done before initializing `Host`. 98 /// 99 /// @param controller Pointer to a concrete `Controller` that the host stack 100 /// should use to communicate with the controller. 101 /// @param data Data to persist from a previous instance of `Host`. 102 /// @param on_initialization_complete Called when initialization is complete. 103 /// Other methods should not be called until initialization completes. 104 virtual void Initialize( 105 Controller* controller, 106 PersistentData data, 107 Function<void(Status)>&& on_initialization_complete) = 0; 108 109 /// Safely shuts down the host, ending all active Bluetooth procedures: 110 /// - All objects/pointers associated with this host are destroyed/invalidated 111 /// and all connections disconnected. 112 /// - All scanning and advertising procedures are stopped. 113 /// 114 /// The Host may send events or call callbacks as procedures get terminated. 115 /// @param callback Will be called once all procedures have terminated. 116 virtual void Close(Closure callback) = 0; 117 118 /// Returns a pointer to the Central API, which is used to scan and connect to 119 /// peers. 120 virtual low_energy::Central* Central() = 0; 121 122 /// Returns a pointer to the Peripheral API, which is used to advertise and 123 /// accept connections from peers. 124 virtual low_energy::Peripheral* Peripheral() = 0; 125 126 /// Returns a pointer to the GATT Server API, which is used to publish GATT 127 /// services. 128 virtual gatt::Server* GattServer() = 0; 129 130 /// Deletes a peer from the Bluetooth host. If the peer is connected, it will 131 /// be disconnected. `peer_id` will no longer refer to any peer. 132 /// 133 /// Returns `OK` after no peer exists that's identified by `peer_id` (even 134 /// if it didn't exist), `ABORTED` if the peer could not be disconnected or 135 /// deleted and still exists. 136 virtual Status ForgetPeer(PeerId peer_id) = 0; 137 138 /// Enable or disable the LE privacy feature. When enabled, the host will use 139 /// a private device address in all LE procedures. When disabled, the public 140 /// identity address will be used instead (which is the default). 141 virtual void EnablePrivacy(bool enabled) = 0; 142 143 /// Set the GAP LE Security Mode of the host. Only encrypted, 144 /// connection-based security modes are supported, i.e. Mode 1 and Secure 145 /// Connections Only mode. If the security mode is set to Secure Connections 146 /// Only, any existing encrypted connections which do not meet the security 147 /// requirements of Secure Connections Only mode will be disconnected. 148 virtual void SetSecurityMode(low_energy::SecurityMode security_mode) = 0; 149 150 /// Assigns the pairing delegate that will respond to authentication 151 /// challenges using the given I/O capabilities. Calling this method cancels 152 /// any on-going pairing procedure started using a previous delegate. Pairing 153 /// requests will be rejected if no PairingDelegate has been assigned. 154 virtual void SetPairingDelegate(InputCapability input, 155 OutputCapability output, 156 PairingDelegate* pairing_delegate) = 0; 157 158 /// NOTE: This is intended to satisfy test scenarios that require pairing 159 /// procedures to be initiated without relying on service access. In normal 160 /// operation, Bluetooth security is enforced during service access. 161 /// 162 /// Initiates pairing to the peer with the supplied `peer_id` and `options`. 163 /// Returns an error if no connected peer with `peer_id` is found or the 164 /// pairing procedure fails. 165 /// 166 /// If `options` specifies a higher security level than the current pairing, 167 /// this method attempts to raise the security level. Otherwise this method 168 /// has no effect and returns success. 169 /// 170 /// Returns the following errors via `callback`: 171 /// `NOT_FOUND` - The peer `peer_id` was not found. 172 /// `ABORTED` - The pairing procedure failed. 173 virtual void Pair(PeerId peer_id, 174 PairingOptions options, 175 Function<void(Status)>&& callback) = 0; 176 177 /// Configures a callback to be called when new bond data for a peer has been 178 /// created. This data should be persisted and used to initialize Host in the 179 /// future. New bond data may be received for an already bonded peer, in which 180 /// case the new data should overwrite the old data. 181 virtual void SetBondDataCallback( 182 Function<void(low_energy::BondData)>&& callback) = 0; 183 184 /// Looks up the `PeerId` corresponding to `address`. If `address` does not 185 /// correspond to a known peer, a new `PeerId` will be generated for the 186 /// address. If a `PeerId` cannot be generated, std::nullopt will be returned. 187 virtual std::optional<PeerId> PeerIdFromAddress(Address address) = 0; 188 189 /// Looks up the Address corresponding to `peer_id`. Returns null if `peer_id` 190 /// does not correspond to a known peer. 191 virtual std::optional<Address> DeviceAddressFromPeerId(PeerId peer_id) = 0; 192 }; 193 194 } // namespace pw::bluetooth 195