blob: 3dde031c64d43c428057ca192fef689620f354cb [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.
#pragma once
#include <zircon/types.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/bt-gatt-svc.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include "garnet/drivers/bluetooth/lib/gatt/gatt.h"
#include "lib/fxl/macros.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(zx_device_t* parent_device,
const std::string& peer_id,
fbl::RefPtr<btlib::gatt::RemoteService> service);
~GattRemoteServiceDevice();
zx_status_t Bind();
private:
static bt_gatt_svc_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 zx_status_t OpConnect(void* ctx, void* cookie,
bt_gatt_connect_cb connect_cb) {
return static_cast<GattRemoteServiceDevice*>(ctx)->Connect(cookie,
connect_cb);
}
static void OpStop(void* ctx) {
static_cast<GattRemoteServiceDevice*>(ctx)->Stop();
}
static zx_status_t OpReadCharacteristic(
void* ctx, bt_gatt_id_t id, void* cookie,
bt_gatt_read_characteristic_cb read_cb) {
return static_cast<GattRemoteServiceDevice*>(ctx)->ReadCharacteristic(
id, cookie, read_cb);
}
static zx_status_t OpReadLongCharacteristic(
void* ctx, bt_gatt_id_t id, void* cookie, uint16_t offset,
size_t max_bytes, bt_gatt_read_characteristic_cb read_cb) {
return static_cast<GattRemoteServiceDevice*>(ctx)->ReadLongCharacteristic(
id, cookie, offset, max_bytes, read_cb);
}
static zx_status_t OpWriteCharacteristic(void* ctx, bt_gatt_id_t id,
void* cookie, const uint8_t* buf,
size_t len,
bt_gatt_status_cb status_cb) {
return static_cast<GattRemoteServiceDevice*>(ctx)->WriteCharacteristic(
id, cookie, buf, len, status_cb);
}
static zx_status_t OpEnableNotifications(
void* ctx, bt_gatt_id_t id, void* cookie, bt_gatt_status_cb status_cb,
bt_gatt_notification_value_cb value_cb) {
return static_cast<GattRemoteServiceDevice*>(ctx)->EnableNotifications(
id, cookie, status_cb, value_cb);
}
// DDK device ops.
void Unbind();
void Release();
// bt-gatt-svc ops.
zx_status_t Connect(void* cookie, bt_gatt_connect_cb connect_cb);
void Stop();
zx_status_t ReadCharacteristic(bt_gatt_id_t id, void* cookie,
bt_gatt_read_characteristic_cb read_cb);
zx_status_t ReadLongCharacteristic(bt_gatt_id_t id, void* cookie,
uint16_t offset, size_t max_bytes,
bt_gatt_read_characteristic_cb read_cb);
zx_status_t WriteCharacteristic(bt_gatt_id_t id, void* cookie,
const uint8_t* buff, size_t len,
bt_gatt_status_cb write_cb);
zx_status_t EnableNotifications(bt_gatt_id_t id, void* cookie,
bt_gatt_status_cb status_cb,
bt_gatt_notification_value_cb value_cb);
// All device protocol messages are dispatched on this loop to not block the
// gatt or host thread.
async::Loop loop_;
zx_device_t* parent_device_; // The BT Host device
zx_device_t* dev_; // The child we are creating.
const std::string& peer_id_;
fbl::RefPtr<btlib::gatt::RemoteService> service_;
// The base DDK device ops.
zx_protocol_device_t dev_proto_ = {};
FXL_DISALLOW_COPY_AND_ASSIGN(GattRemoteServiceDevice);
};
} // namespace bthost