blob: e7e94e01a43924547f6849c4a5d2f3ec85226588 [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 GARNET_DRIVERS_BLUETOOTH_LIB_HCI_PACKET_H_
#define GARNET_DRIVERS_BLUETOOTH_LIB_HCI_PACKET_H_
#include <memory>
#include <zircon/assert.h>
#include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
#include "garnet/drivers/bluetooth/lib/common/linked_list.h"
#include "garnet/drivers/bluetooth/lib/common/packet_view.h"
#include "lib/fxl/macros.h"
namespace btlib {
namespace hci {
// A Packet is a move-only object that can be used to hold sent and received HCI
// packets. The Packet template is parameterized over the protocol packet header
// type.
//
// Instances of Packet cannot be created directly as the template does not
// specify the backing buffer, which should be provided by a subclass.
//
// Header-type-specific functionality can be provided in specializations of the
// Packet template.
//
// USAGE:
//
// Each Packet consists of a PacketView into a buffer that actually stores the
// data. A buffer should be provided in a subclass implementation. While the
// buffer must be sufficiently large to store the packet, the packet contents
// can be much smaller.
//
// template <typename HeaderType, size_t BufferSize>
// class FixedBufferPacket : public Packet<HeaderType> {
// public:
// void Init(size_t payload_size) {
// this->init_view(common::MutablePacketView<HeaderType>(&buffer_,
// payload_size));
// }
//
// private:
// common::StaticByteBuffer<BufferSize> buffer_;
// };
//
// std::unique_ptr<Packet<MyHeaderType>> packet =
// std::make_unique<FixedBufferPacket<MyHeaderType, 255>>(payload_size);
//
// Use Packet::view() to obtain a read-only view into the packet contents:
//
// auto foo = packet->view().header().some_header_field;
//
// Use Packet::mutable_view() to obtain a mutable view into the packet, which
// allows the packet contents and the size of the packet to be modified:
//
// packet->mutable_view()->mutable_header()->some_header_field = foo;
// packet->mutable_view()->set_payload_size(my_new_size);
//
// // Copy data directly into the buffer.
// auto mutable_bytes = packet->mutable_view()->mutable_bytes();
// std::memcpy(mutable_bytes.mutable_data(), data, mutable_bytes.size());
//
// SPECIALIZATIONS:
//
// Additional functionality that is specific to a protocol header type can be
// provided in a specialization of the Packet template.
//
// using MagicPacket = Packet<MagicHeader>;
//
// template <>
// class Packet<MagicHeader> : public PacketBase<MagicHeader, MagicPacket> {
// public:
// // Initializes packet with pancakes.
// void InitPancakes();
// };
//
// // Create an instance of FixedBufferPacket declared above.
// std::unique_ptr<MagicPacket> packet =
// std::make_unique<FixedBufferPacket<MagicHeader, 255>>();
// packet->InitPancakes();
//
// This pattern is used by the CommandPacket, EventPacket, and ACLDataPacket
// classes (see control_packets.h and acl_data_packet.h).
//
// THREAD-SAFETY:
//
// Packet is NOT thread-safe without external locking.
// PacketBase provides basic view functionality and intrusively
// linked-listability. Intended to be inherited by the Packet template and all
// of its specializations.
template <typename HeaderType, typename T>
class PacketBase : public common::LinkedListable<T> {
public:
virtual ~PacketBase() = default;
const common::PacketView<HeaderType>& view() const { return view_; }
common::MutablePacketView<HeaderType>* mutable_view() { return &view_; }
protected:
PacketBase() = default;
// Called by derived classes to initialize |view_| after initializing the
// corresponding buffer.
void init_view(const common::MutablePacketView<HeaderType>& view) {
ZX_DEBUG_ASSERT(!view_.is_valid());
ZX_DEBUG_ASSERT(view.is_valid());
view_ = view;
}
private:
common::MutablePacketView<HeaderType> view_;
FXL_DISALLOW_COPY_AND_ASSIGN(PacketBase);
};
// The basic Packet template. See control_packets.h and acl_data_packet.h for
// specializations that add functionality beyond that of PacketBase.
template <typename HeaderType>
class Packet : public PacketBase<HeaderType, Packet<HeaderType>> {
protected:
Packet() = default;
};
} // namespace hci
} // namespace btlib
#endif // GARNET_DRIVERS_BLUETOOTH_LIB_HCI_PACKET_H_