From cda2c8bb8dbadc8b9256a35034bccd192094e632 Mon Sep 17 00:00:00 2001 From: George Beckstein Date: Thu, 8 Oct 2020 11:58:33 -0400 Subject: [PATCH] Introduce ChainableGapEventHandler subclass of ChainableEventHandler The ChainableGapEventHandler enables chaining together Gap::EventHandlers so separate parts of an application can be notified of Gap events as needed. The application can register multiple Gap::EventHandler objects to one ChainableGapEventHandler and then set the global Gap::EventHandler to the ChainableGapEventHandler. All registered EventHandlers will then be called when a Gap Event occurs. --- connectivity/FEATURE_BLE/include/ble/Gap.h | 6 + .../FEATURE_BLE/include/ble/GattServer.h | 6 + .../ble/common/ChainableEventHandler.h | 17 ++- .../ble/gap/ChainableGapEventHandler.h | 117 ++++++++++++++++++ .../gatt/ChainableGattServerEventHandler.h | 59 +-------- 5 files changed, 141 insertions(+), 64 deletions(-) create mode 100644 connectivity/FEATURE_BLE/include/ble/gap/ChainableGapEventHandler.h diff --git a/connectivity/FEATURE_BLE/include/ble/Gap.h b/connectivity/FEATURE_BLE/include/ble/Gap.h index ed8cfe2c72..c54814bc52 100644 --- a/connectivity/FEATURE_BLE/include/ble/Gap.h +++ b/connectivity/FEATURE_BLE/include/ble/Gap.h @@ -598,6 +598,12 @@ public: * 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 ChainableGapEventHandler and then setting the chain as the primary + * Gap EventHandler using this function. + * + * @see ChainableGapEventHandler */ void setEventHandler(EventHandler *handler); diff --git a/connectivity/FEATURE_BLE/include/ble/GattServer.h b/connectivity/FEATURE_BLE/include/ble/GattServer.h index 6b1261f1f5..a2f0a9d737 100644 --- a/connectivity/FEATURE_BLE/include/ble/GattServer.h +++ b/connectivity/FEATURE_BLE/include/ble/GattServer.h @@ -204,6 +204,12 @@ public: * 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); diff --git a/connectivity/FEATURE_BLE/include/ble/common/ChainableEventHandler.h b/connectivity/FEATURE_BLE/include/ble/common/ChainableEventHandler.h index 79a2ca2136..7e3f06237d 100644 --- a/connectivity/FEATURE_BLE/include/ble/common/ChainableEventHandler.h +++ b/connectivity/FEATURE_BLE/include/ble/common/ChainableEventHandler.h @@ -33,7 +33,7 @@ public: ChainableEventHandler() { } - virtual ~ChainableEventHandler() { + ~ChainableEventHandler() { // Clean up all nodes auto it = head; while(it) { @@ -45,13 +45,15 @@ public: /** * Add an EventHandler to be notified of events sent to - * this ChainableGattServerEventHandler + * this ChainableEventHandler * * @param[in] event_handler Handler to add to chain + * + * @retval true if adding EventHandler was successful, false otherwise */ - void addEventHandler(T* event_handler) { + bool addEventHandler(T* event_handler) { auto eh = new (std::nothrow) node_t { event_handler, nullptr }; - if(!eh) { return; } + if(!eh) { return false; } if(!head) { head = eh; } else { @@ -61,6 +63,7 @@ public: } it->next = eh; } + return true; } /** @@ -93,10 +96,12 @@ public: protected: - template - void execute_on_all(void (T::*fn)(Args...), Args&... args) { + template + void execute_on_all(void (T::*fn)(FnArgs...), Args&&... args) { auto it = head; while(it) { + // we do not use std::forward, args have to remain lvalues + // as they are passed to multiple handlers (it->eh->*fn)(args...); it = it->next; } diff --git a/connectivity/FEATURE_BLE/include/ble/gap/ChainableGapEventHandler.h b/connectivity/FEATURE_BLE/include/ble/gap/ChainableGapEventHandler.h new file mode 100644 index 0000000000..820655aa87 --- /dev/null +++ b/connectivity/FEATURE_BLE/include/ble/gap/ChainableGapEventHandler.h @@ -0,0 +1,117 @@ +/* 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_CHAINABLEGAPEVENTHANDLER_H_ +#define MBED_CHAINABLEGAPEVENTHANDLER_H_ + +#include "ble/Gap.h" +#include "ble/common/ChainableEventHandler.h" + +/** + * Gap::EventHandler implementation that allows the application + * to register multiple separate EventHandlers to be called when + * Gap events happen. + */ +class ChainableGapEventHandler : public ble::Gap::EventHandler, + public ChainableEventHandler +{ + +public: + + ChainableGapEventHandler() { } + + ~ChainableGapEventHandler() { } + + void onScanRequestReceived(const ble::ScanRequestEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onScanRequestReceived, event); + } + + void onAdvertisingEnd(const ble::AdvertisingEndEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onAdvertisingEnd, event); + } + + void onAdvertisingReport(const ble::AdvertisingReportEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onAdvertisingReport, event); + } + + void onScanTimeout(const ble::ScanTimeoutEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onScanTimeout, event); + } + + void onPeriodicAdvertisingSyncEstablished( + const ble::PeriodicAdvertisingSyncEstablishedEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onPeriodicAdvertisingSyncEstablished, event); + } + + void onPeriodicAdvertisingReport( + const ble::PeriodicAdvertisingReportEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onPeriodicAdvertisingReport, event); + } + + void onPeriodicAdvertisingSyncLoss( + const ble::PeriodicAdvertisingSyncLoss &event) override { + execute_on_all(&ble::Gap::EventHandler::onPeriodicAdvertisingSyncLoss, event); + } + + void onConnectionComplete(const ble::ConnectionCompleteEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onConnectionComplete, event); + } + + void onUpdateConnectionParametersRequest( + const ble::UpdateConnectionParametersRequestEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onUpdateConnectionParametersRequest, event); + } + + void onConnectionParametersUpdateComplete( + const ble::ConnectionParametersUpdateCompleteEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onConnectionParametersUpdateComplete, event); + } + + void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &event) override { + execute_on_all(&ble::Gap::EventHandler::onDisconnectionComplete, event); + } + + void onReadPhy( + ble_error_t status, + ble::connection_handle_t connectionHandle, + ble::phy_t txPhy, + ble::phy_t rxPhy) override { + execute_on_all(&ble::Gap::EventHandler::onReadPhy, status, + connectionHandle, txPhy, rxPhy); + } + + void onPhyUpdateComplete( + ble_error_t status, + ble::connection_handle_t connectionHandle, + ble::phy_t txPhy, + ble::phy_t rxPhy) override { + execute_on_all(&ble::Gap::EventHandler::onPhyUpdateComplete, status, + connectionHandle, txPhy, rxPhy); + } + + void onDataLengthChange( + ble::connection_handle_t connectionHandle, + uint16_t txSize, + uint16_t rxSize) override { + execute_on_all(&ble::Gap::EventHandler::onDataLengthChange, + connectionHandle, txSize, rxSize); + } + +}; + +#endif /* MBED_CHAINABLEGAPEVENTHANDLER_H_ */ diff --git a/connectivity/FEATURE_BLE/include/ble/gatt/ChainableGattServerEventHandler.h b/connectivity/FEATURE_BLE/include/ble/gatt/ChainableGattServerEventHandler.h index 51de27e961..75bde43bc7 100644 --- a/connectivity/FEATURE_BLE/include/ble/gatt/ChainableGattServerEventHandler.h +++ b/connectivity/FEATURE_BLE/include/ble/gatt/ChainableGattServerEventHandler.h @@ -35,94 +35,37 @@ public: ChainableGattServerEventHandler() { } - virtual ~ChainableGattServerEventHandler() { } + ~ChainableGattServerEventHandler() { } - /** - * 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 - */ void onAttMtuChange(ble::connection_handle_t connectionHandle, uint16_t attMtuSize) override { execute_on_all(&ble::GattServer::EventHandler::onAttMtuChange, connectionHandle, 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 - */ void onDataSent(const GattDataSentCallbackParams* params) override { execute_on_all(&ble::GattServer::EventHandler::onDataSent, 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 - */ void onDataWritten(const GattWriteCallbackParams *params) override { execute_on_all(&ble::GattServer::EventHandler::onDataWritten, 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(). - */ void onDataRead(const GattReadCallbackParams *params) override { execute_on_all(&ble::GattServer::EventHandler::onDataRead, params); } - /** - * Function invoked when the GattServer instance is about - * to be shut down. This can result in a call to reset() or BLE::reset(). - */ void onShutdown(const GattServer *server) override { execute_on_all(&ble::GattServer::EventHandler::onShutdown, 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 - */ void onUpdatesEnabled(const GattUpdatesEnabledCallbackParams* params) override { execute_on_all(&ble::GattServer::EventHandler::onUpdatesEnabled, 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 - */ void onUpdatesDisabled(const GattUpdatesDisabledCallbackParams* params) override { execute_on_all(&ble::GattServer::EventHandler::onUpdatesDisabled, 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 - */ void onConfirmationReceived(const GattConfirmationReceivedCallbackParams* params) override { execute_on_all(&ble::GattServer::EventHandler::onConfirmationReceived, params); }