blob: 0a94365d91158ce0f03839b8cfaaa6648f8f5a5f [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_TRANSPORT_TRANSPORT_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TRANSPORT_TRANSPORT_H_
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.h>
#include <lib/async/dispatcher.h>
#include <lib/fit/thread_checker.h>
#include <lib/fpromise/result.h>
#include <lib/sys/inspect/cpp/component.h>
#include <atomic>
#include <memory>
#include <thread>
#include <fbl/macros.h>
#include "lib/inspect/cpp/vmo/types.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/acl_data_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/command_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/hci_wrapper.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/sco_data_channel.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt::hci {
class DeviceWrapper;
// Represents the HCI transport layer. This object owns the HCI command, ACL,
// and SCO channels and provides the necessary control-flow mechanisms to send
// and receive HCI packets from the underlying Bluetooth controller.
//
// TODO(armansito): This object has become too heavy-weight. I think it will be
// cleaner to have CommandChannel and ACLDataChannel each be owned directly by
// the main and L2CAP domains. Transport should go away as part of the HCI layer
// clean up (and also fxbug.dev/721).
class Transport final {
public:
// Initializes the command channel.
//
// NOTE: AclDataChannel and ScoDataChannel will be left uninitialized. They must be
// initialized after available data buffer information has been obtained from
// the controller (via HCI_Read_Buffer_Size and HCI_LE_Read_Buffer_Size).
static fpromise::result<std::unique_ptr<Transport>> Create(std::unique_ptr<HciWrapper> hci);
// TODO(armansito): hci::Transport::~Transport() should send a shutdown message
// to the bt-hci device, which would be responsible for sending HCI_Reset upon
// exit.
~Transport();
// Initializes the ACL data channel with the given parameters. Returns false
// if an error occurs during initialization. Initialize() must have been
// called successfully prior to calling this method.
bool InitializeACLDataChannel(const DataBufferInfo& bredr_buffer_info,
const DataBufferInfo& le_buffer_info);
// Initializes the SCO data channel with the given parameters. Returns false
// if an error occurs during initialization.
bool InitializeScoDataChannel(const DataBufferInfo& buffer_info);
VendorFeaturesBits GetVendorFeatures();
// Returns a pointer to the HCI command and event flow control handler.
CommandChannel* command_channel() const { return command_channel_.get(); }
// Returns a pointer to the HCI ACL data flow control handler.
AclDataChannel* acl_data_channel() const { return acl_data_channel_.get(); }
// Returns a pointer to the HCI SCO data flow control handler.
ScoDataChannel* sco_data_channel() const { return sco_data_channel_.get(); }
// Set a callback that should be invoked when any one of the underlying
// channels gets closed for any reason (e.g. the HCI device has disappeared)
// and the dispatcher on which the callback should be posted.
//
// When this callback is called the channels will be in an invalid state and
// packet processing is no longer guaranteed to work. It is the responsibility
// of the callback implementation to clean up this Transport instance by
// calling ShutDown() and/or deleting it.
void SetTransportClosedCallback(fit::closure callback);
// Attach hci transport inspect node as a child node of |parent|.
static constexpr const char* kInspectNodeName = "hci";
void AttachInspect(inspect::Node& parent, const std::string& name = kInspectNodeName);
fxl::WeakPtr<Transport> WeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
private:
explicit Transport(std::unique_ptr<HciWrapper> hci);
// Notifies the closed callback.
void NotifyClosedCallback();
// Callback called by CommandChannel or ACLDataChannel on errors.
void OnChannelError();
void ResetChannels();
// Used to assert that certain public functions are only called on the
// creation thread.
fit::thread_checker thread_checker_;
std::unique_ptr<HciWrapper> hci_;
// The ACL data flow control handler.
std::unique_ptr<AclDataChannel> acl_data_channel_;
// The SCO data flow control handler.
std::unique_ptr<ScoDataChannel> sco_data_channel_;
// The HCI command and event flow control handler.
std::unique_ptr<CommandChannel> command_channel_;
// Callback invoked when the transport is closed (due to a channel error).
fit::closure closed_cb_;
// HCI inspect node.
inspect::Node hci_node_;
fxl::WeakPtrFactory<Transport> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Transport);
};
} // namespace bt::hci
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TRANSPORT_TRANSPORT_H_