blob: 367b6487edb7c0df602ca5e1d08ceccd6e6182e5 [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_CHARACTERISTIC_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_REMOTE_CHARACTERISTIC_H_
#include <lib/fit/function.h>
#include <map>
#include <queue>
#include <unordered_map>
#include <fbl/macros.h>
#include "src/connectivity/bluetooth/core/bt-host/att/error.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt_defs.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt::gatt {
class Client;
// Used by a RemoteService to represent one of its characteristics. This object
// maintains information about a characteristic (such as its descriptors, known
// permissions, etc) and is responsible for routing notifications to subscribed
// clients.
//
// Instances are created and owned by a RemoteService.
//
// ID SCHEME:
//
// The ID that gets assigned to a RemoteCharacteristic is its value_handle
// The ID that gets assigned to a Descriptor is its handle. Looking up a descriptor by id from the
// service is logarithmic in the number of descriptors.
class RemoteCharacteristic final {
public:
using ValueCallback = fit::function<void(const ByteBuffer&, bool maybe_truncated)>;
using NotifyStatusCallback = fit::function<void(att::Result<>, IdType handler_id)>;
// We use an ordered map so that the Descriptors are exposed to the world in order
using DescriptorMap = std::map<DescriptorHandle, DescriptorData>;
RemoteCharacteristic(fxl::WeakPtr<Client> client, const CharacteristicData& info);
~RemoteCharacteristic();
// The properties for this characteristic.
Properties properties() const { return info_.properties; }
// The extended properties for this characteristic.
std::optional<ExtendedProperties> extended_properties() const {
return info_.extended_properties;
}
// ATT declaration data for this characteristic.
const CharacteristicData& info() const { return info_; }
// Descriptors of this characteristic.
const DescriptorMap& descriptors() const { return descriptors_; }
private:
friend class RemoteService;
// The following private methods can only be called by a RemoteService.
// `service_changed` indicates whether destruction will occur due to a Service Changed
// notification, in which case this characteristic may no longer exist or may have been changed.
void set_service_changed(bool service_changed) { service_changed_ = service_changed; }
// Updates the CharacteristicData |info_| with the Extended Properties that are read from the
// descriptors discovered in |DiscoverDescriptors|.
void UpdateDataWithExtendedProperties(ExtendedProperties ext_props);
// Discovers the descriptors of this characteristic and reports the status in
// |callback|.
//
// NOTE: The owning RemoteService is responsible for ensuring that this object
// outlives the discovery procedure.
void DiscoverDescriptors(att::Handle range_end, att::ResultFunction<> callback);
// (See RemoteService::EnableNotifications in remote_service.h).
void EnableNotifications(ValueCallback value_callback, NotifyStatusCallback status_callback);
bool DisableNotifications(IdType handler_id);
// Sends a request to disable notifications and indications. Called by
// DisableNotifications and destructor.
void DisableNotificationsInternal();
// Resolves all pending notification subscription requests. Called by
// EnableNotifications().
void ResolvePendingNotifyRequests(att::Result<> status);
// Called when a notification is received for this characteristic.
void HandleNotification(const ByteBuffer& value, bool maybe_truncated);
CharacteristicData info_;
DescriptorMap descriptors_;
bool discovery_error_;
// If true, this characteristic was in a service that has been changed. Values should not be
// read/written after a service is changed.
bool service_changed_ = false;
// Handle of the Client Characteristic Configuration descriptor, or 0 if none.
att::Handle ccc_handle_;
// Handle of the Characteristic Extended Properties descriptor, or 0 if none.
att::Handle ext_prop_handle_;
// Represents a pending request to subscribe to notifications or indications.
struct PendingNotifyRequest {
PendingNotifyRequest(ValueCallback value_callback, NotifyStatusCallback status_callback);
PendingNotifyRequest() = default;
PendingNotifyRequest(PendingNotifyRequest&&) = default;
ValueCallback value_callback;
NotifyStatusCallback status_callback;
};
std::queue<PendingNotifyRequest> pending_notify_reqs_;
// Active notification handlers.
std::unordered_map<IdType, ValueCallback> notify_handlers_;
// Set to true while handlers in notify_handlers_ are being notified.
bool notifying_handlers_ = false;
std::vector<IdType> handlers_pending_disable_;
// The next available notification handler ID.
size_t next_notify_handler_id_;
// The GATT client bearer used for ATT requests.
fxl::WeakPtr<Client> client_;
fxl::WeakPtrFactory<RemoteCharacteristic> weak_ptr_factory_;
DISALLOW_COPY_ASSIGN_AND_MOVE(RemoteCharacteristic);
};
} // namespace bt::gatt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_REMOTE_CHARACTERISTIC_H_