blob: 127e17e1291a90ecb29592036b5c9173c515f427 [file]
// 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_GENERIC_ATTRIBUTE_SERVICE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_GENERIC_ATTRIBUTE_SERVICE_H_
#include <lib/fit/function.h>
#include <unordered_set>
#include "src/connectivity/bluetooth/core/bt-host/att/att.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/local_service_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/persisted_data.h"
namespace bt::gatt {
constexpr IdType kServiceChangedChrcId = 0u;
// Callback to send an indication. Used to inject the GATT object's update-sending ability without
// requiring this service to carry a reference to GATT or Server.
// |chrc_id|: the service-defined ID of the characteristic to indicate
// |svc_id|: the gatt::GATT-defined ID of the service containing |chrc_id|.
// For example, to indicate a new service to a peer via the Service Changed chrc, one would invoke
// this with svc_id = the GenericAttributeService's service_id_, chrc_id = kServiceChangedChrcId,
// peer_id of the peer, and value = the att::Handle range of the new service.
using SendIndicationCallback =
fit::function<void(IdType svc_id, IdType chrc_id, PeerId peer_id, BufferView value)>;
// Implements the "Generic Attribute Profile Service" containing the "Service
// Changed" characteristic that is "...used to indicate to connected devices
// that services have changed (Vol 3, Part G, 7)."
class GenericAttributeService final {
public:
// Registers this service and makes this service the callee of the Service
// Changed callback. GATT remote clients must still request that they be sent
// indications for the Service Changed characteristic. Holds the
// LocalServiceManager pointer for this object's lifetime. Do not register
// multiple instances of this service in a single bt-host.
GenericAttributeService(fxl::WeakPtr<LocalServiceManager> local_service_manager,
SendIndicationCallback send_indication_callback);
~GenericAttributeService();
// This callback is called when a client changes the CCC for the service changed
// characteristic to inform the upper layers of the stack to persist this value.
void SetPersistServiceChangedCCCCallback(PersistServiceChangedCCCCallback callback) {
persist_service_changed_ccc_callback_ = std::move(callback);
}
// Set the service changed indication subscription for a given peer.
void SetServiceChangedIndicationSubscription(PeerId peer_id, bool indicate);
inline IdType service_id() const { return service_id_; }
private:
void Register();
// Send indications to subscribed clients when a service has changed.
void OnServiceChanged(IdType service_id, att::Handle start, att::Handle end);
// Data store against which to register and unregister this service. It must
// outlive this instance.
fxl::WeakPtr<LocalServiceManager> local_service_manager_;
const SendIndicationCallback send_indication_callback_;
// Peers that have subscribed to indications.
std::unordered_set<PeerId> subscribed_peers_;
// Handle for the Service Changed characteristic that is read when it is first
// configured for indications.
att::Handle svc_changed_handle_ = att::kInvalidHandle;
// Local service ID; hidden because registration is tied to instance lifetime.
IdType service_id_ = kInvalidId;
// Callback to inform uper stack layers to persist service changed CCC.
PersistServiceChangedCCCCallback persist_service_changed_ccc_callback_;
};
} // namespace bt::gatt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_GENERIC_ATTRIBUTE_SERVICE_H_