blob: f9bf85b621b062482da584613987d84c603c5f0f [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_TOOLS_BT_INTEL_TOOL_COMMAND_CHANNEL_H_
#define SRC_CONNECTIVITY_BLUETOOTH_TOOLS_BT_INTEL_TOOL_COMMAND_CHANNEL_H_
#include <fbl/unique_fd.h>
#include <fuchsia/hardware/bluetooth/c/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/fit/function.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
#include "src/connectivity/bluetooth/core/bt-host/hci/control_packets.h"
// Sends and receives events from a command channel that it retrieves from a
// Zircon Bluetooth HCI device. It parses the incoming event packets, only
// returning complete and valid event packets on to the event handler set.
class CommandChannel {
public:
// |hcidev_path| is a path to the hci device (e.g. /dev/class/bt-hci/000)
CommandChannel(std::string hcidev_path);
~CommandChannel();
// Indicates whether this channel is valid. This should be checked after
// construction.
bool is_valid() { return valid_; }
// Sets the event callback to be called when an HCI Event arrives on the
// channel.
using EventCallback =
fit::function<void(const ::bt::hci::EventPacket& event_packet)>;
void SetEventCallback(EventCallback callback);
// Sends the command in |command| to the controller. The channel must
// be Ready when this is called.
void SendCommand(const ::bt::PacketView<::bt::hci::CommandHeader>& command);
// Sends the command in |command| to the controller and waits for
// an Event, which is delivered to |callback| before this function
// returns.
void SendCommandSync(
const ::bt::PacketView<::bt::hci::CommandHeader>& command,
EventCallback callback);
private:
// Common read handler implemntation
void HandleChannelReady(const zx::channel& channel,
async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal);
// Read ready handler for |cmd_channel_|
void OnCmdChannelReady(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal);
// Read ready handler for |acl_channel_|
void OnAclChannelReady(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal);
bool valid_;
EventCallback event_callback_;
fbl::unique_fd hci_fd_;
zx::channel cmd_channel_;
async::WaitMethod<CommandChannel, &CommandChannel::OnCmdChannelReady>
cmd_channel_wait_{this};
zx::channel acl_channel_;
async::WaitMethod<CommandChannel, &CommandChannel::OnAclChannelReady>
acl_channel_wait_{this};
};
#endif // SRC_CONNECTIVITY_BLUETOOTH_TOOLS_BT_INTEL_TOOL_COMMAND_CHANNEL_H_