blob: 631062e6701ff1278c4e44cc43387dea2e869783 [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.
#pragma once
#include <thread>
#include <async/wait.h>
#include <zx/channel.h>
#include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
#include "garnet/drivers/bluetooth/lib/common/packet_view.h"
#include "garnet/drivers/bluetooth/lib/hci/hci.h"
#include "lib/fsl/tasks/message_loop.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/synchronization/thread_checker.h"
namespace bluetooth {
namespace testing {
// Abstract base for implementing a fake HCI controller endpoint. This can
// directly send ACL data and event packets on request and forward outgoing ACL
// data packets to subclass implementations.
class FakeControllerBase {
public:
FakeControllerBase(zx::channel cmd_channel, zx::channel acl_data_channel);
virtual ~FakeControllerBase();
// Kicks off the FakeController thread and message loop and starts processing
// transactions. |debug_name| will be assigned as the name of the thread.
void Start();
// Stops the message loop and thread.
void Stop();
// Sends the given packet over this FakeController's command channel endpoint.
void SendCommandChannelPacket(const common::ByteBuffer& packet);
// Sends the given packet over this FakeController's ACL data channel
// endpoint.
void SendACLDataChannelPacket(const common::ByteBuffer& packet);
// Immediately closes the command channel endpoint.
void CloseCommandChannel();
// Immediately closes the ACL data channel endpoint.
void CloseACLDataChannel();
// Returns true if Start() has been called without a call to Stop().
bool IsStarted() const { return static_cast<bool>(task_runner_); }
protected:
fxl::RefPtr<fxl::TaskRunner> task_runner() const { return task_runner_; }
// Getters for our channel endpoints.
const zx::channel& command_channel() const { return cmd_channel_; }
const zx::channel& acl_data_channel() const { return acl_channel_; }
// Called when there is an incoming command packet.
virtual void OnCommandPacketReceived(
const common::PacketView<hci::CommandHeader>& command_packet) = 0;
// Called when there is an outgoing ACL data packet.
virtual void OnACLDataPacketReceived(
const common::ByteBuffer& acl_data_packet) = 0;
private:
// Read and handle packets received over the channels.
async_wait_result_t HandleCommandPacket(async_t* async,
zx_status_t wait_status,
const zx_packet_signal_t* signal);
async_wait_result_t HandleACLPacket(async_t* async,
zx_status_t wait_status,
const zx_packet_signal_t* signal);
// Cleans up the channel handles. This must be run on |task_runner_|'s thread.
void CloseCommandChannelInternal();
void CloseACLDataChannelInternal();
// Used to assert that certain public functions are only called on the
// creation thread.
fxl::ThreadChecker thread_checker_;
zx::channel cmd_channel_;
zx::channel acl_channel_;
std::thread thread_;
fxl::RefPtr<fxl::TaskRunner> task_runner_;
async::Wait cmd_channel_wait_;
async::Wait acl_channel_wait_;
FXL_DISALLOW_COPY_AND_ASSIGN(FakeControllerBase);
};
} // namespace testing
} // namespace bluetooth