blob: 409924ceb2bff654a773955f40f8c6481d131664 [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_GATT_REMOTE_SERVICE_DEVICE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_REMOTE_SERVICE_DEVICE_H_
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/bt/gattsvc.h>
#include <fbl/macros.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 <zircon/types.h>
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt.h"
namespace bthost {
// This class is responsible for bridging remote GATT services to the DDK so
// GATT services can be implimented as drivers (eg HID over GATT as HIDBUS
// device)
class GattRemoteServiceDevice final {
public:
GattRemoteServiceDevice(bt::gatt::PeerId peer_id, fbl::RefPtr<bt::gatt::RemoteService> service);
~GattRemoteServiceDevice() = default;
// Publish a bt-gatt-svc device as a child of |parent|.
zx_status_t Bind(zx_device_t* parent);
// Unpublishes any associated bt-gatt-svc and stops processing GATT callbacks. This will be called
// by the DDK as part of regular device lifecycle but it can also be called directly to remove a
// device.
void Unbind();
private:
static bt_gatt_svc_protocol_ops_t proto_ops_;
// Protocol trampolines.
static void DdkUnbind(void* ctx) { static_cast<GattRemoteServiceDevice*>(ctx)->Unbind(); }
static void DdkRelease(void* ctx) { static_cast<GattRemoteServiceDevice*>(ctx)->Release(); }
static void OpConnect(void* ctx, bt_gatt_svc_connect_callback connect_cb, void* cookie) {
static_cast<GattRemoteServiceDevice*>(ctx)->Connect(connect_cb, cookie);
}
static void OpStop(void* ctx) { static_cast<GattRemoteServiceDevice*>(ctx)->Stop(); }
static void OpReadCharacteristic(void* ctx, bt_gatt_id_t id,
bt_gatt_svc_read_characteristic_callback read_cb, void* cookie) {
static_cast<GattRemoteServiceDevice*>(ctx)->ReadCharacteristic(id, read_cb, cookie);
}
static void OpReadLongCharacteristic(void* ctx, bt_gatt_id_t id, uint16_t offset,
size_t max_bytes,
bt_gatt_svc_read_characteristic_callback read_cb,
void* cookie) {
static_cast<GattRemoteServiceDevice*>(ctx)->ReadLongCharacteristic(id, offset, max_bytes,
read_cb, cookie);
}
static void OpWriteCharacteristic(void* ctx, bt_gatt_id_t id, const void* buf, size_t len,
bt_gatt_svc_write_characteristic_callback status_cb,
void* cookie) {
static_cast<GattRemoteServiceDevice*>(ctx)->WriteCharacteristic(id, buf, len, status_cb,
cookie);
}
static void OpEnableNotifications(void* ctx, bt_gatt_id_t id,
const bt_gatt_notification_value_t* value_cb,
bt_gatt_svc_enable_notifications_callback status_cb,
void* cookie) {
static_cast<GattRemoteServiceDevice*>(ctx)->EnableNotifications(id, value_cb, status_cb,
cookie);
}
// DDK device ops.
void Release();
// bt-gatt-svc ops.
void Connect(bt_gatt_svc_connect_callback connect_cb, void* cookie);
void Stop();
void ReadCharacteristic(bt_gatt_id_t id, bt_gatt_svc_read_characteristic_callback read_cb,
void* cookie);
void ReadLongCharacteristic(bt_gatt_id_t id, uint16_t offset, size_t max_bytes,
bt_gatt_svc_read_characteristic_callback read_cb, void* cookie);
void WriteCharacteristic(bt_gatt_id_t id, const void* buff, size_t len,
bt_gatt_svc_write_characteristic_callback write_cb, void* cookie);
void EnableNotifications(bt_gatt_id_t id, const bt_gatt_notification_value_t* value_cb,
bt_gatt_svc_enable_notifications_callback status_cb, void* cookie);
// All device protocol messages are dispatched on this loop to not block the
// gatt or host thread.
async::Loop loop_;
std::mutex mtx_;
// The bt-gatt-svc device that is managed by this object. This member is null if no device has
// been published.
zx_device_t* dev_ __TA_GUARDED(mtx_);
const bt::gatt::PeerId peer_id_;
const fbl::RefPtr<bt::gatt::RemoteService> service_;
// The base DDK device ops.
zx_protocol_device_t dev_proto_ = {};
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(GattRemoteServiceDevice);
};
} // namespace bthost
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_REMOTE_SERVICE_DEVICE_H_