blob: cd9091c39e54014af1e7503fa06354485d38b1e9 [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/gatt/client.h"
#include "pw_bluetooth/gatt/server.h"
#include "pw_bluetooth/hci.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_containers/vector.h"
#include "pw_function/function.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.
Vector<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`.
//
// Parameters:
// `hci` - Pointer to a concrete `Hci` that the host stack should use to
// communicate with the controller.
// `data` - Data to persist from a previous instance of `Host`.
// `on_initialization_complete` - Called when initialization is complete.
// Other methods should not be called until initialization completes.
virtual void Initialize(
Hci* hci,
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.
// `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