mbed-os/connectivity/FEATURE_BLE/include/ble/GattServer.h

729 lines
27 KiB
C++

/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_GATT_SERVER_H__
#define MBED_GATT_SERVER_H__
#include "platform/mbed_toolchain.h"
#include "ble/common/CallChainOfFunctionPointersWithContext.h"
#include "ble/common/blecommon.h"
#include "ble/gatt/GattService.h"
#include "ble/gatt/GattAttribute.h"
#include "ble/gatt/GattCallbackParamTypes.h"
namespace ble {
#if !defined(DOXYGEN_ONLY)
namespace impl {
class GattServer;
}
#endif // !defined(DOXYGEN_ONLY)
/**
* @addtogroup ble
* @{
* @addtogroup gatt
* @{
* @addtogroup server
* @{
*/
/**
* Construct and operates a GATT server.
*
* A Gatt server is a collection of GattService; these services contain
* characteristics that a peer connected to the device may read or write.
* These characteristics may also emit updates to subscribed clients when their
* values change.
*
* @p Server Layout
*
* Application code can add a GattService object to the server with the help of
* the function addService(). That function registers all the GattCharacteristic
* enclosed in the service, as well as all the characteristics descriptors (see
* GattAttribute) these characteristics contain. Service registration assigns
* a unique handle to the various attributes being part of the service; this
* handle should be used for subsequent read or write of these components.
*
* There are no primitives defined to remove a single service; however, a call to
* the function reset() removes all services previously registered in the
* GattServer.
*
* @p Characteristic and attributes access
*
* Values of the characteristic and the characteristic descriptor present in the
* GattServer must be accessed through the handle assigned to them when the service
* has been registered; the GattServer class offers several flavors of read()
* and write() functions that retrieve or mutate an attribute value.
*
* Application code can query if a client has subscribed to a given
* characteristic's value update by invoking the function areUpdatesEnabled().
*
* @p Events
*
* The GattServer allows application code to register several event handlers that
* can be used to monitor client and server activities:
* - onDataSent(): Register an event handler that is called when a
* characteristic value update has been sent to a client.
* - onDataWriten(): Register an event handler that is called when a
* client has written an attribute of the server.
* - onDataRead(): Register an event handler that is called when a
* client has read an attribute of the server.
* - onUpdatesEnabled: Register an event handler that is called when a
* client subscribes to updates of a characteristic.
* - onUpdatesDisabled: Register an event handler that is called when a
* client unsubscribes from updates of a characteristic.
* - onConfimationReceived: Register an event handler that is called
* when a client acknowledges a characteristic value notification.
*
* @note The term characteristic value update is used to represent
* Characteristic Value Notification and Characteristic Value Indication when
* the nature of the server initiated is not relevant.
*/
class GattServer {
public:
/**
* Definition of the general handler of GattServer related events.
*/
struct EventHandler {
/**
* Function invoked when the connections changes the ATT_MTU which controls
* the maximum size of an attribute that can be read in a single L2CAP packet
* which might be fragmented across multiple packets.
*
* @param connectionHandle The handle of the connection that changed the size.
* @param attMtuSize
*/
virtual void onAttMtuChange(
ble::connection_handle_t connectionHandle,
uint16_t attMtuSize
) {
(void)connectionHandle;
(void)attMtuSize;
}
/**
* Function invoked when the server has sent data to a client as
* part of a notification/indication.
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*/
virtual void onDataSent(const GattDataSentCallbackParams &params) {
(void)params;
}
/**
* Function invoked when a client writes an attribute
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*/
virtual void onDataWritten(const GattWriteCallbackParams &params) {
(void)params;
}
/**
* Function invoked when a client reads an attribute
*
* @note This functionality may not be available on all underlying stacks.
* Application code may work around that limitation by monitoring read
* requests instead of read events.
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*
* @see GattCharacteristic::setReadAuthorizationCallback()
* @see isOnDataReadAvailable().
*/
virtual void onDataRead(const GattReadCallbackParams &params) {
(void)params;
}
/**
* Function invoked when the GattServer instance is about
* to be shut down. This can result in a call to reset() or BLE::reset().
*/
virtual void onShutdown(const GattServer &server) {
(void)server;
}
/**
* Function invoked when the client has subscribed to characteristic updates
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*/
virtual void onUpdatesEnabled(const GattUpdatesEnabledCallbackParams &params) {
(void)params;
}
/**
* Function invoked when the client has unsubscribed to characteristic updates
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*/
virtual void onUpdatesDisabled(const GattUpdatesDisabledCallbackParams &params) {
(void)params;
}
/**
* Function invoked when an ACK has been received for an
* indication sent to the client.
*
* @note params has a temporary scope and should be copied by the
* application if needed later
*/
virtual void onConfirmationReceived(const GattConfirmationReceivedCallbackParams &params) {
(void)params;
}
protected:
/**
* Prevent polymorphic deletion and avoid unnecessary virtual destructor
* as the GattServer class will never delete the instance it contains.
*/
~EventHandler() = default;
};
/**
* Event handler invoked when the server has sent data to a client.
*
* @see onDataSent().
*/
typedef FunctionPointerWithContext<unsigned> DataSentCallback_t;
/**
* Callchain of DataSentCallback_t objects.
*
* @see onDataSent().
*/
typedef CallChainOfFunctionPointersWithContext<unsigned>
DataSentCallbackChain_t;
/**
* Event handler invoked when the client has written an attribute of the
* server.
*
* @see onDataWritten().
*/
typedef FunctionPointerWithContext<const GattWriteCallbackParams*>
DataWrittenCallback_t;
/**
* Callchain of DataWrittenCallback_t objects.
*
* @see onDataWritten().
*/
typedef CallChainOfFunctionPointersWithContext<const GattWriteCallbackParams*>
DataWrittenCallbackChain_t;
/**
* Event handler invoked when the client has read an attribute of the server.
*
* @see onDataRead().
*/
typedef FunctionPointerWithContext<const GattReadCallbackParams*>
DataReadCallback_t;
/**
* Callchain of DataReadCallback_t.
*
* @see onDataRead().
*/
typedef CallChainOfFunctionPointersWithContext<const GattReadCallbackParams*>
DataReadCallbackChain_t;
/**
* Event handler invoked when the GattServer is reset.
*
* @see onShutdown() reset()
*/
typedef FunctionPointerWithContext<const GattServer *>
GattServerShutdownCallback_t;
/**
* Callchain of GattServerShutdownCallback_t.
*
* @see onShutdown() reset()
*/
typedef CallChainOfFunctionPointersWithContext<const GattServer*>
GattServerShutdownCallbackChain_t;
/**
* Event handler that handles subscription to characteristic updates,
* unsubscription from characteristic updates and notification confirmation.
*
* @see onUpdatesEnabled() onUpdateDisabled() onConfirmationReceived()
*/
typedef FunctionPointerWithContext<GattAttribute::Handle_t> EventCallback_t;
public:
/**
* Assign the event handler implementation that will be used by the
* module to signal events back to the application.
*
* @param handler Application implementation of an EventHandler.
*
* @note Multiple discrete EventHandler instances may be used by adding them
* to a ChainableGattServerEventHandler and then setting the chain as the primary
* GattServer EventHandler using this function.
*
* @see ChainableGattServerEventHandler
*/
void setEventHandler(EventHandler *handler);
/**
* Shut down the GattServer instance.
*
* This function notifies all event handlers listening for shutdown events
* that the GattServer is about to be shut down; then it clears all
* GattServer state.
*
* @note This function is meant to be overridden in the platform-specific
* subclass. Overides must call the parent function before any cleanup.
*
* @return BLE_ERROR_NONE on success.
*/
ble_error_t reset();
/**
* Add a service declaration to the local attribute server table.
*
* This functions inserts a service declaration in the attribute table
* followed by the characteristic declarations (including characteristic
* descriptors) present in @p service.
*
* The process assigns a unique attribute handle to all the elements added
* into the attribute table. This handle is an ID that must be used for
* subsequent interractions with the elements.
*
* @note There is no mirror function that removes a single service.
* Application code can remove all the registered services by calling
* reset().
*
* @attention Service, characteristics and descriptors objects registered
* within the GattServer must remain reachable until reset() is called.
*
* @param[in] service The service to be added; attribute handle of services,
* characteristic and characteristic descriptors are updated by the
* process.
*
* @return BLE_ERROR_NONE if the service was successfully added.
*/
ble_error_t addService(GattService &service);
/**
* Read the value of an attribute present in the local GATT server.
*
* @param[in] attributeHandle Handle of the attribute to read.
* @param[out] buffer A buffer to hold the value being read.
* @param[in,out] lengthP Length of the buffer being supplied. If the
* attribute value is longer than the size of the supplied buffer, this
* variable holds upon return the total attribute value length (excluding
* offset). The application may use this information to allocate a suitable
* buffer size.
*
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
*
* @attention read(ble::connection_handle_t, GattAttribute::Handle_t, uint8_t *, uint16_t *)
* must be used to read Client Characteristic Configuration Descriptor (CCCD)
* because the value of this type of attribute depends on the connection.
*/
ble_error_t read(
GattAttribute::Handle_t attributeHandle,
uint8_t buffer[],
uint16_t *lengthP
);
/**
* Read the value of an attribute present in the local GATT server.
*
* The connection handle allows application code to read the value of a
* Client Characteristic Configuration Descriptor for a given connection.
*
* @param[in] connectionHandle Connection handle.
* @param[in] attributeHandle Attribute handle for the value attribute of
* the characteristic.
* @param[out] buffer A buffer to hold the value being read.
* @param[in,out] lengthP Length of the buffer being supplied. If the
* attribute value is longer than the size of the supplied buffer, this
* variable holds upon return the total attribute value length (excluding
* offset). The application may use this information to allocate a suitable
* buffer size.
*
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
*/
ble_error_t read(
ble::connection_handle_t connectionHandle,
GattAttribute::Handle_t attributeHandle,
uint8_t *buffer,
uint16_t *lengthP
);
/**
* Update the value of an attribute present in the local GATT server.
*
* @param[in] attributeHandle Handle of the attribute to write.
* @param[in] value A pointer to a buffer holding the new value.
* @param[in] size Size in bytes of the new value (in bytes).
* @param[in] localOnly If this flag is false and the attribute handle
* written is a characteristic value, then the server sends an update
* containing the new value to all clients that have subscribed to the
* characteristic's notifications or indications. Otherwise, the update does
* not generate a single server initiated event.
*
* @return BLE_ERROR_NONE if the attribute value has been successfully
* updated.
*/
ble_error_t write(
GattAttribute::Handle_t attributeHandle,
const uint8_t *value,
uint16_t size,
bool localOnly = false
);
/**
* Update the value of an attribute present in the local GATT server.
*
* The connection handle parameter allows application code to direct
* notification or indication resulting from the update to a specific client.
*
* @param[in] connectionHandle Connection handle.
* @param[in] attributeHandle Handle for the value attribute of the
* characteristic.
* @param[in] value A pointer to a buffer holding the new value.
* @param[in] size Size of the new value (in bytes).
* @param[in] localOnly If this flag is false and the attribute handle
* written is a characteristic value, then the server sends an update
* containing the new value to the client identified by the parameter
* @p connectionHandle if it is subscribed to the characteristic's
* notifications or indications. Otherwise, the update does not generate a
* single server initiated event.
*
* @return BLE_ERROR_NONE if the attribute value has been successfully
* updated.
*/
ble_error_t write(
ble::connection_handle_t connectionHandle,
GattAttribute::Handle_t attributeHandle,
const uint8_t *value,
uint16_t size,
bool localOnly = false
);
/**
* Determine if one of the connected clients has subscribed to notifications
* or indications of the characteristic in input.
*
* @param[in] characteristic The characteristic.
* @param[out] enabledP Upon return, *enabledP is true if updates are
* enabled for a connected client; otherwise, *enabledP is false.
*
* @return BLE_ERROR_NONE if the connection and handle are found. False
* otherwise.
*/
ble_error_t areUpdatesEnabled(
const GattCharacteristic &characteristic,
bool *enabledP
);
/**
* Determine if an identified client has subscribed to notifications or
* indications of a given characteristic.
*
* @param[in] connectionHandle The connection handle.
* @param[in] characteristic The characteristic.
* @param[out] enabledP Upon return, *enabledP is true if the client
* identified by @p connectionHandle has subscribed to notifications or
* indications of @p characteristic; otherwise, *enabledP is false.
*
* @return BLE_ERROR_NONE if the connection and handle are found. False
* otherwise.
*/
ble_error_t areUpdatesEnabled(
ble::connection_handle_t connectionHandle,
const GattCharacteristic &characteristic,
bool *enabledP
);
/**
* Indicate if the underlying stack emit events when an attribute is read by
* a client.
*
* @attention This function should be overridden to return true if
* applicable.
*
* @return true if onDataRead is supported; false otherwise.
*/
bool isOnDataReadAvailable() const;
/**
* Add an event handler that monitors emission of characteristic value
* updates.
*
* @param[in] callback Event handler being registered.
*
* @note It is possible to chain together multiple onDataSent callbacks
* (potentially from different modules of an application).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onDataSent(const DataSentCallback_t &callback);
/**
* Add an event handler that monitors emission of characteristic value
* updates.
*
* @param[in] objPtr Pointer to the instance that is used to invoke the
* event handler.
* @param[in] memberPtr Event handler being registered. It is a member
* function.
*/
template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count))
{
onDataSent({objPtr, memberPtr});
}
/**
* Access the callchain of data sent event handlers.
*
* @return A reference to the DATA_SENT event callback chain.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
DataSentCallbackChain_t &onDataSent();
/**
* Set an event handler that is called after
* a connected peer has written an attribute.
*
* @param[in] callback The event handler being registered.
*
* @attention It is possible to set multiple event handlers. Registered
* handlers may be removed with onDataWritten().detach(callback).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onDataWritten(const DataWrittenCallback_t &callback);
/**
* Set an event handler that is called after
* a connected peer has written an attribute.
*
* @param[in] objPtr Pointer to the instance that is used to invoke the
* event handler (@p memberPtr).
* @param[in] memberPtr Event handler being registered. It is a member
* function.
*/
template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onDataWritten(
T *objPtr,
void (T::*memberPtr)(const GattWriteCallbackParams *context)
)
{
onDataWritten({objPtr, memberPtr});
}
/**
* Access the callchain of data written event handlers.
*
* @return A reference to the data written event callbacks chain.
*
* @note It is possible to register callbacks using
* onDataWritten().add(callback).
*
* @note It is possible to unregister callbacks using
* onDataWritten().detach(callback).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
DataWrittenCallbackChain_t &onDataWritten();
/**
* Set an event handler that monitors attribute reads from connected clients.
*
* @param[in] callback Event handler being registered.
*
* @return BLE_ERROR_NOT_IMPLEMENTED if this functionality isn't available;
* else BLE_ERROR_NONE.
*
* @note This functionality may not be available on all underlying stacks.
* Application code may work around that limitation by monitoring read
* requests instead of read events.
*
* @see GattCharacteristic::setReadAuthorizationCallback()
* @see isOnDataReadAvailable().
*
* @attention It is possible to set multiple event handlers. Registered
* handlers may be removed with onDataRead().detach(callback).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
ble_error_t onDataRead(const DataReadCallback_t &callback);
/**
* Set an event handler that monitors attribute reads from connected clients.
*
* @param[in] objPtr Pointer to the instance that is used to invoke the
* event handler (@p memberPtr).
* @param[in] memberPtr Event handler being registered. It is a member
* function.
*/
template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
ble_error_t onDataRead(
T *objPtr,
void (T::*memberPtr)(const GattReadCallbackParams *context)
)
{
return onDataRead({objPtr, memberPtr});
}
/**
* Access the callchain of data read event handlers.
*
* @return A reference to the data read event callbacks chain.
*
* @note It is possible to register callbacks using
* onDataRead().add(callback).
*
* @note It is possible to unregister callbacks using
* onDataRead().detach(callback).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
DataReadCallbackChain_t &onDataRead();
/**
* Set an event handler that monitors shutdown or reset of the GattServer.
*
* The event handler is invoked when the GattServer instance is about
* to be shut down. This can result in a call to reset() or BLE::reset().
*
* @param[in] callback Event handler being registered.
*
* @note It is possible to set up multiple shutdown event handlers.
*
* @note It is possible to unregister a callback using
* onShutdown().detach(callback)
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onShutdown(const GattServerShutdownCallback_t &callback);
/**
* Set an event handler that monitors shutdown or reset of the GattServer.
*
* The event handler is invoked when the GattServer instance is about
* to be shut down. This can result of a call to reset() or BLE::reset().
*
* @param[in] objPtr Pointer to the instance that is used to invoke the
* event handler (@p memberPtr).
* @param[in] memberPtr Event handler being registered. It is a member
* function.
*/
template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattServer *))
{
onShutdown({objPtr, memberPtr});
}
/**
* Access the callchain of shutdown event handlers.
*
* @return A reference to the shutdown event callbacks chain.
*
* @note It is possible to register callbacks using
* onShutdown().add(callback).
*
* @note It is possible to unregister callbacks using
* onShutdown().detach(callback).
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
GattServerShutdownCallbackChain_t& onShutdown();
/**
* Set up an event handler that monitors subscription to characteristic
* updates.
*
* @param[in] callback Event handler being registered.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onUpdatesEnabled(EventCallback_t callback);
/**
* Set up an event handler that monitors unsubscription from characteristic
* updates.
*
* @param[in] callback Event handler being registered.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onUpdatesDisabled(EventCallback_t callback);
/**
* Set up an event handler that monitors notification acknowledgment.
*
* The event handler is called when a client sends a confirmation that it has
* correctly received a notification from the server.
*
* @param[in] callback Event handler being registered.
*/
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
"been replaced by GattServer::setEventHandler. Use that function instead.")
void onConfirmationReceived(EventCallback_t callback);
#if !defined(DOXYGEN_ONLY)
GattServer(impl::GattServer* impl) : impl(impl) {}
GattServer(const GattServer&) = delete;
GattServer& operator=(const GattServer&) = delete;
#endif // !defined(DOXYGEN_ONLY)
private:
impl::GattServer *impl;
};
/**
* @}
* @}
* @}
*/
} // ble
/** @deprecated Use the namespaced ble::GattServer instead of the global GattServer. */
using ble::GattServer;
#endif /* ifndef MBED_GATT_SERVER_H__ */