blob: 24037f4f7bb8f0787d7964ddf80e8f065d1c719d [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HCI_CONNECTION_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HCI_CONNECTION_H_
#include <lib/fit/function.h>
#include <lib/fit/thread_checker.h>
#include <zircon/assert.h>
#include <fbl/macros.h>
#include "src/connectivity/bluetooth/core/bt-host/common/device_address.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/command_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/control_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/error.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/link_type.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt::hci {
class Transport;
// A Connection represents a logical link connection to a peer. It maintains link-specific
// configuration parameters (such as the connection handle) and state (e.g
// kConnected/kDisconnected). Controller procedures that are related to managing a logical link are
// performed by a Connection, e.g. disconnecting the link.
//
// Connection instances are intended to be uniquely owned. The owner of an instance is also the
// owner of the underlying link and the lifetime of a Connection determines the lifetime of the
// link.
//
// Connection is not expected to be constructed directly. Users should instead construct a
// specialization based on the link type: LowEnergyConnection, BrEdrConnection, or ScoConnection,
class Connection {
public:
enum class State {
// Default state of a newly created Connection. This is the only connection state that is
// considered "open".
kConnected,
// HCI Disconnect command has been sent, but HCI Disconnection Complete event has not yet been
// received. This state is skipped when the disconnection is initiated by the peer.
kWaitingForDisconnectionComplete,
// HCI Disconnection Complete event has been received.
kDisconnected
};
// The destructor closes this connection.
virtual ~Connection();
// Returns a string representation.
virtual std::string ToString() const;
// Returns the 12-bit connection handle of this connection. This handle is
// used to identify an individual logical link maintained by the controller.
hci_spec::ConnectionHandle handle() const { return handle_; }
// The local device address used while establishing the connection.
const DeviceAddress& local_address() const { return local_address_; }
// The peer address used while establishing the connection.
const DeviceAddress& peer_address() const { return peer_address_; }
State state() const { return conn_state_; }
// Assigns a callback that will be run when the peer disconnects.
using PeerDisconnectCallback =
fit::function<void(const Connection* connection, hci_spec::StatusCode reason)>;
void set_peer_disconnect_callback(PeerDisconnectCallback callback) {
peer_disconnect_callback_ = std::move(callback);
}
// Send HCI Disconnect and set state to closed. Must not be called on an already disconnected
// connection.
virtual void Disconnect(hci_spec::StatusCode reason);
protected:
// |on_disconnection_complete| will be called when the disconnection complete event is received,
// which may be after this object is destroyed (which is why this isn't a virtual method).
Connection(hci_spec::ConnectionHandle handle, const DeviceAddress& local_address,
const DeviceAddress& peer_address, const fxl::WeakPtr<Transport>& hci,
fit::callback<void()> on_disconnection_complete);
const fxl::WeakPtr<Transport>& hci() { return hci_; }
PeerDisconnectCallback& peer_disconnect_callback() { return peer_disconnect_callback_; }
private:
// Checks |event|, unregisters link, and clears pending packets count.
// If the disconnection was initiated by the peer, call |peer_disconnect_callback|.
// Returns true if event was valid and for this connection.
// This method is static so that it can be called in an event handler
// after this object has been destroyed.
static CommandChannel::EventCallbackResult OnDisconnectionComplete(
fxl::WeakPtr<Connection> self, hci_spec::ConnectionHandle handle, const EventPacket& event,
fit::callback<void()> on_disconnection_complete);
hci_spec::ConnectionHandle handle_;
// Addresses used while creating the link.
DeviceAddress local_address_;
DeviceAddress peer_address_;
PeerDisconnectCallback peer_disconnect_callback_;
State conn_state_;
fxl::WeakPtr<Transport> hci_;
fxl::WeakPtrFactory<Connection> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Connection);
};
} // namespace bt::hci
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HCI_CONNECTION_H_