blob: d5f3f30111aca788395ff695e6064f168b7f1b31 [file] [log] [blame]
// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include <optional>
#include <string_view>
#include "pw_bluetooth/controller.h"
#include "pw_bluetooth/gatt/client.h"
#include "pw_bluetooth/gatt/server.h"
#include "pw_bluetooth/low_energy/bond_data.h"
#include "pw_bluetooth/low_energy/central.h"
#include "pw_bluetooth/low_energy/peripheral.h"
#include "pw_bluetooth/low_energy/security_mode.h"
#include "pw_bluetooth/pairing_delegate.h"
#include "pw_bluetooth/peer.h"
#include "pw_bluetooth/types.h"
#include "pw_function/function.h"
#include "pw_span/span.h"
#include "pw_status/status.h"
namespace pw::bluetooth {
/// Host is the entrypoint API for interacting with a Bluetooth host stack. Host
/// is an abstract class that is implemented by a host stack implementation.
class Host {
public:
/// Represents the persistent configuration of a single Host instance. This is
/// used for identity representation in advertisements & bonding secrets
/// recall.
struct PersistentData {
/// The local Identity Resolving Key used by a Host to generate Resolvable
/// Private Addresses when privacy is enabled. May be absent for hosts that
/// do not use LE privacy, or that only use Non-Resolvable Private
/// Addresses.
///
/// NOTE: This key is distributed to LE peers during pairing procedures. The
/// client must take care to assign an IRK that consistent with the local
/// Host identity.
std::optional<Key> identity_resolving_key;
/// All bonds that use a public identity address must contain the same local
/// address.
span<const low_energy::BondData> bonds;
};
/// The security level required for this pairing. This corresponds to the
/// security levels defined in the Security Manager Protocol in Core spec
/// v5.3, Vol 3, Part H, Section 2.3.1
enum class PairingSecurityLevel : uint8_t {
/// Encrypted without person-in-the-middle protection (unauthenticated)
kEncrypted,
/// Encrypted with person-in-the-middle protection (authenticated), although
/// this level of security does not fully protect against passive
/// eavesdroppers
kAuthenticated,
/// Encrypted with person-in-the-middle protection (authenticated).
/// This level of security fully protects against eavesdroppers.
kLeSecureConnections,
};
/// Whether or not the device should form a bluetooth bond during the pairing
/// prodecure. As described in Core Spec v5.2, Vol 3, Part C, Sec 4.3
enum class BondableMode : uint8_t {
/// The device will form a bond during pairing with peers
kBondable,
/// The device will not form a bond during pairing with peers
kNonBondable,
};
/// Parameters that give a caller more fine-grained control over the pairing
/// process.
struct PairingOptions {
/// Determines the Security Manager security level to pair with.
PairingSecurityLevel security_level = PairingSecurityLevel::kAuthenticated;
/// Indicated whether the device should form a bond or not during pairing.
/// If not present, interpreted as bondable mode.
BondableMode bondable_mode = BondableMode::kBondable;
};
/// `Close()` should complete before `Host` is destroyed.
virtual ~Host() = default;
/// Initializes the host stack. Vendor specific controller initialization
/// (e.g. loading firmware) must be done before initializing `Host`.
///
/// @param controller Pointer to a concrete `Controller` that the host stack
/// should use to communicate with the controller.
/// @param data Data to persist from a previous instance of `Host`.
/// @param on_initialization_complete Called when initialization is complete.
/// Other methods should not be called until initialization completes.
virtual void Initialize(
Controller* controller,
PersistentData data,
Function<void(Status)>&& on_initialization_complete) = 0;
/// Safely shuts down the host, ending all active Bluetooth procedures:
/// - All objects/pointers associated with this host are destroyed/invalidated
/// and all connections disconnected.
/// - All scanning and advertising procedures are stopped.
///
/// The Host may send events or call callbacks as procedures get terminated.
/// @param callback Will be called once all procedures have terminated.
virtual void Close(Closure callback) = 0;
/// Returns a pointer to the Central API, which is used to scan and connect to
/// peers.
virtual low_energy::Central* Central() = 0;
/// Returns a pointer to the Peripheral API, which is used to advertise and
/// accept connections from peers.
virtual low_energy::Peripheral* Peripheral() = 0;
/// Returns a pointer to the GATT Server API, which is used to publish GATT
/// services.
virtual gatt::Server* GattServer() = 0;
/// Deletes a peer from the Bluetooth host. If the peer is connected, it will
/// be disconnected. `peer_id` will no longer refer to any peer.
///
/// Returns `OK` after no peer exists that's identified by `peer_id` (even
/// if it didn't exist), `ABORTED` if the peer could not be disconnected or
/// deleted and still exists.
virtual Status ForgetPeer(PeerId peer_id) = 0;
/// Enable or disable the LE privacy feature. When enabled, the host will use
/// a private device address in all LE procedures. When disabled, the public
/// identity address will be used instead (which is the default).
virtual void EnablePrivacy(bool enabled) = 0;
/// Set the GAP LE Security Mode of the host. Only encrypted,
/// connection-based security modes are supported, i.e. Mode 1 and Secure
/// Connections Only mode. If the security mode is set to Secure Connections
/// Only, any existing encrypted connections which do not meet the security
/// requirements of Secure Connections Only mode will be disconnected.
virtual void SetSecurityMode(low_energy::SecurityMode security_mode) = 0;
/// Assigns the pairing delegate that will respond to authentication
/// challenges using the given I/O capabilities. Calling this method cancels
/// any on-going pairing procedure started using a previous delegate. Pairing
/// requests will be rejected if no PairingDelegate has been assigned.
virtual void SetPairingDelegate(InputCapability input,
OutputCapability output,
PairingDelegate* pairing_delegate) = 0;
/// NOTE: This is intended to satisfy test scenarios that require pairing
/// procedures to be initiated without relying on service access. In normal
/// operation, Bluetooth security is enforced during service access.
///
/// Initiates pairing to the peer with the supplied `peer_id` and `options`.
/// Returns an error if no connected peer with `peer_id` is found or the
/// pairing procedure fails.
///
/// If `options` specifies a higher security level than the current pairing,
/// this method attempts to raise the security level. Otherwise this method
/// has no effect and returns success.
///
/// Returns the following errors via `callback`:
/// `NOT_FOUND` - The peer `peer_id` was not found.
/// `ABORTED` - The pairing procedure failed.
virtual void Pair(PeerId peer_id,
PairingOptions options,
Function<void(Status)>&& callback) = 0;
/// Configures a callback to be called when new bond data for a peer has been
/// created. This data should be persisted and used to initialize Host in the
/// future. New bond data may be received for an already bonded peer, in which
/// case the new data should overwrite the old data.
virtual void SetBondDataCallback(
Function<void(low_energy::BondData)>&& callback) = 0;
/// Looks up the `PeerId` corresponding to `address`. If `address` does not
/// correspond to a known peer, a new `PeerId` will be generated for the
/// address. If a `PeerId` cannot be generated, std::nullopt will be returned.
virtual std::optional<PeerId> PeerIdFromAddress(Address address) = 0;
/// Looks up the Address corresponding to `peer_id`. Returns null if `peer_id`
/// does not correspond to a known peer.
virtual std::optional<Address> DeviceAddressFromPeerId(PeerId peer_id) = 0;
};
} // namespace pw::bluetooth