blob: 7272959540c6b25a265c23ddc267124afd523d6c [file] [log] [blame]
// Copyright 2018 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 GARNET_DRIVERS_BLUETOOTH_LIB_RFCOMM_CHANNEL_H_
#define GARNET_DRIVERS_BLUETOOTH_LIB_RFCOMM_CHANNEL_H_
#include <queue>
#include <fbl/ref_counted.h>
#include <lib/async/dispatcher.h>
#include <lib/fit/function.h>
#include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
#include "garnet/drivers/bluetooth/lib/hci/connection.h"
#include "garnet/drivers/bluetooth/lib/rfcomm/frames.h"
#include "garnet/drivers/bluetooth/lib/rfcomm/rfcomm.h"
#include "garnet/public/lib/fxl/macros.h"
namespace btlib {
namespace rfcomm {
class Session; // Break mutual dependency.
class Channel : public fbl::RefCounted<Channel> {
public:
using UniqueId = uint64_t;
using PacketType = common::ByteBufferPtr;
virtual ~Channel() = default;
DLCI id() const { return dlci_; }
size_t tx_mtu() const;
// TODO(quiche): Provide lower-layer ID info for debugging purposes.
hci::ConnectionHandle link_handle() const { return 0; }
// TODO(NET-1763): Make this identifier unique across L2CAP channels and HCI
// connections.
UniqueId unique_id() const { return dlci_; }
using RxCallback = fit::function<void(PacketType)>;
using ClosedCallback = fit::closure;
// Activates this channel assigning |dispatcher| to execute |rx_callback| and
// |closed_callback|. Returns true on success.
virtual bool Activate(RxCallback rx_callback, ClosedCallback closed_callback,
async_dispatcher_t* dispatcher) = 0;
// Cleans up resources associated with this channel.
// TODO(NET-1756): Implement cleanup.
void Deactivate() {}
// Send a buffer of user data. Takes ownership of |data|. This method is
// asynchronous, and there is no notification of delivery. We operate under
// the assumption that the underlying transport is reliable. The channel must
// be activated prior to sending. Returns true if the data was successfully
// queued.
virtual bool Send(PacketType data) = 0;
protected:
friend class Session;
Channel(DLCI dlci, Session* session);
RxCallback rx_callback_;
ClosedCallback closed_callback_;
async_dispatcher_t* dispatcher_;
const DLCI dlci_;
// The Session owning this Channel. |session_| will always outlive |this|.
Session* session_;
// True if the channel is established (DLC Establishment has taken place)
bool established_;
// The negotiation state of this channel
ParameterNegotiationState negotiation_state_;
// The number of local and remote credits available on this channel.
Credits local_credits_;
Credits remote_credits_;
// Frames waiting on this channel to receive credits to be sent (and
// sent callbacks)
std::queue<std::pair<std::unique_ptr<Frame>, fit::closure>> wait_queue_;
// Called by |session_| when a new frame is received for this channel. If an
// |rx_callback_| is registered, the frame is forwarded to the callback;
// otherwise, the frame is buffered and is forwarded once a callback gets
// registered.
virtual void Receive(PacketType data) = 0;
FXL_DISALLOW_COPY_AND_ASSIGN(Channel);
};
namespace internal {
class ChannelImpl : public Channel {
public:
// Channel overrides
bool Activate(RxCallback rx_callback, ClosedCallback closed_callback,
async_dispatcher_t* dispatcher) override;
bool Send(PacketType data) override;
private:
friend class rfcomm::Session;
// This should only be called from Session.
ChannelImpl(DLCI dlci, Session* session);
// This should only be called from Session.
void Receive(PacketType data) override;
std::queue<PacketType> pending_rxed_frames_;
};
} // namespace internal
} // namespace rfcomm
} // namespace btlib
#endif // GARNET_DRIVERS_BLUETOOTH_LIB_RFCOMM_CHANNEL_H_