blob: c70ea64627e34df531470d661bc76cce6567b299 [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 SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HOST_DEVICE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HOST_DEVICE_H_
#include <ddk/device.h>
#include <ddk/driver.h>
#include <fbl/macros.h>
#include <fuchsia/hardware/bluetooth/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include <mutex>
#include "src/connectivity/bluetooth/core/bt-host/gatt_remote_service_device.h"
#include "src/connectivity/bluetooth/core/bt-host/host.h"
namespace bthost {
class Host;
// Represents a bt-host device. This object relays device events to the host
// thread's event loop to be processed by the Host.
class HostDevice final {
public:
explicit HostDevice(zx_device_t* device);
zx_status_t Bind();
private:
// Protocol trampolines.
static void DdkUnbind(void* ctx) { static_cast<HostDevice*>(ctx)->Unbind(); }
static void DdkRelease(void* ctx) { static_cast<HostDevice*>(ctx)->Release(); }
// Route ddk fidl messages to the dispatcher function
static zx_status_t DdkMessage(void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) {
// Struct containing function pointers for all fidl ops to be dispatched on
static constexpr fuchsia_hardware_bluetooth_Host_ops_t fidl_ops = {
.Open = OpenFidlOp,
};
bt_log(TRACE, "bt-host", "fidl message");
return fuchsia_hardware_bluetooth_Host_dispatch(ctx, txn, msg, &fidl_ops);
}
// Fidl trampolines.
static zx_status_t OpenFidlOp(void* ctx, zx_handle_t channel) {
return static_cast<HostDevice*>(ctx)->OpenHostChannel(zx::channel(channel));
}
void Unbind();
void Release();
// Open a new channel to the host. Send that channel to the fidl client
// or respond with an error if the channel could not be opened.
// Returns the status of the fidl send operation.
zx_status_t OpenHostChannel(zx::channel channel);
// Called when a new remote GATT service has been found.
void OnRemoteGattServiceAdded(bt::gatt::PeerId peer_id,
fbl::RefPtr<bt::gatt::RemoteService> service);
void CleanUp() __TA_REQUIRES(mtx_);
zx_device_t* dev_; // The bt-host device we published.
zx_device_t* parent_; // The parent bt-hci device.
// The base DDK device ops.
zx_protocol_device_t dev_proto_ = {};
// Guards access to members below.
std::mutex mtx_;
// Contains the context objects for the bt-gatt-svc devices that are published for remote GATT
// services. These are maintained as weak/raw references and managed as part of the DDK lifecycle
// events. The following invariants are assumed:
//
// 1. This HostDevice strictly outlives all members that are referenced from |gatt_devices_|.
// 2. Each member is created and added to this list when a remote GATT service is detected AND
// GattRemoteServiceDevice::Bind() returns success.
// 3. A member is explicitly unbound and removed from this list when the associated GATT
// service is removed or when this HostDevice gets unbound.
// 4. The actual object destruction is expected to be performed via DDK events.
std::unordered_set<GattRemoteServiceDevice*> gatt_devices_ __TA_GUARDED(mtx_);
// Host processes all its messages on |loop_|. |loop_| is initialized to run
// in its own thread.
//
// This is necessary as Host owns FIDL bindings which require a
// single-threaded dispatcher.
async::Loop loop_;
fxl::RefPtr<Host> host_ __TA_GUARDED(mtx_);
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(HostDevice);
};
} // namespace bthost
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HOST_DEVICE_H_