blob: 33c0d403806fe3c7a8b6d238f15bd5bf40644dad [file] [log] [blame]
// Copyright 2020 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_SCO_SCO_CONNECTION_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SCO_SCO_CONNECTION_H_
#include <lib/fit/function.h>
#include <queue>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/sco_data_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/sco_data_packet.h"
namespace bt::sco {
// ScoConnection is a wrapper around an owned SCO hci::Connection. It provides a
// high-level interface to the underlying connection. This class implements the required ChannelT
// template parameter methods of SocketChannelRelay and SocketFactory.
//
// This class is intended to be owned by a ScoConnectionManager.
class ScoConnection final : public hci::ScoDataChannel::ConnectionInterface,
public fbl::RefCounted<ScoConnection> {
public:
// |connection| is the underlying connection and must have the link type kSCO or kESCO.
// |deactivated_cb| will be called when the connection has been Deactivated and should be
// destroyed.
static fbl::RefPtr<ScoConnection> Create(std::unique_ptr<hci::Connection> connection,
fit::closure deactivated_cb,
hci_spec::SynchronousConnectionParameters parameters,
hci::ScoDataChannel* channel);
hci_spec::ConnectionHandle handle() const override { return handle_; }
// Called by ScoConnectionManager to notify a connection it can no longer process data and its
// hci::Connection should be closed.
void Close();
// Returns a value that's unique for any SCO connection on this device.
using UniqueId = hci_spec::ConnectionHandle;
UniqueId unique_id() const;
UniqueId id() const;
// Activates this channel. |rx_callback| and |closed_callback| are called as data is received and
// the channel is closed, respectively. `Deactivate` should be called in `closed_callback`.
//
// Returns false if the channel could not be activated.
bool Activate(fit::closure rx_callback, fit::closure closed_callback);
// Deactivates this channel. No more packets can be sent or received after
// this is called. |rx_callback| may still be called if it has been already
// dispatched to its task runner.
void Deactivate();
// Maximum outbound SDU payload size that will be accepted by |Send()|.
uint16_t max_tx_sdu_size() const;
// Queue the given SCO payload for transmission over this channel, taking
// ownership of |payload|. Returns true if the payload was queued successfully, and
// false otherwise.
bool Send(ByteBufferPtr payload);
// If an inbound packet is ready to be read, returns the packet. Otherwise, returns nullptr.
std::unique_ptr<hci::ScoDataPacket> Read();
// ScoDataChannel overrides:
hci_spec::SynchronousConnectionParameters parameters() override;
std::unique_ptr<hci::ScoDataPacket> GetNextOutboundPacket() override;
void ReceiveInboundPacket(std::unique_ptr<hci::ScoDataPacket> packet) override;
void OnHciError() override;
private:
friend class fbl::RefPtr<ScoConnection>;
explicit ScoConnection(std::unique_ptr<hci::Connection> connection, fit::closure deactivated_cb,
hci_spec::SynchronousConnectionParameters parameters,
hci::ScoDataChannel* channel);
// Destroying this object will disconnect the underlying HCI connection.
~ScoConnection() = default;
// Common clean up logic for Close() and Deactivate(). Marks connection as inactive and closes the
// underlying connection.
void CleanUp();
// True if Activate() has been called and neither Close() or Deactivate() has been called yet.
bool active_;
hci_spec::ConnectionHandle handle_;
std::unique_ptr<hci::Connection> connection_;
// Called to notify the caller of Activate() that the connection was closed.
fit::closure activator_closed_cb_;
// Called to notify the owner that the connection was deactivated.
fit::closure deactivated_cb_;
// Notify caller of Activate() that an inbound packet has been received and may be read.
fit::closure rx_callback_ = nullptr;
// Contains outbound SCO payloads.
std::queue<ByteBufferPtr> outbound_queue_;
// Contains inbound SCO payloads.
std::queue<std::unique_ptr<hci::ScoDataPacket>> inbound_queue_;
// This will be null if HCI SCO is not supported.
hci::ScoDataChannel* channel_ = nullptr;
hci_spec::SynchronousConnectionParameters parameters_;
fxl::WeakPtrFactory<ScoConnection> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ScoConnection);
};
} // namespace bt::sco
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SCO_SCO_CONNECTION_H_