Skip to content

Commit b242be1

Browse files
authored
Merge pull request #13734 from AGlass0fMilk/chainable-event-handler
BLE: Introduce ChainableEventHandler and subclasses
2 parents e439ad9 + 9a6d207 commit b242be1

File tree

9 files changed

+521
-6
lines changed

9 files changed

+521
-6
lines changed

connectivity/FEATURE_BLE/include/ble/Gap.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,12 @@ class Gap {
617617
* module to signal events back to the application.
618618
*
619619
* @param handler Application implementation of an EventHandler.
620+
*
621+
* @note Multiple discrete EventHandler instances may be used by adding them
622+
* to a ChainableGapEventHandler and then setting the chain as the primary
623+
* Gap EventHandler using this function.
624+
*
625+
* @see ChainableGapEventHandler
620626
*/
621627
void setEventHandler(EventHandler *handler);
622628

connectivity/FEATURE_BLE/include/ble/GattServer.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#ifndef MBED_GATT_SERVER_H__
2121
#define MBED_GATT_SERVER_H__
2222

23+
#include "platform/mbed_toolchain.h"
24+
2325
#include "ble/common/CallChainOfFunctionPointersWithContext.h"
2426
#include "ble/common/blecommon.h"
2527

@@ -118,6 +120,84 @@ class GattServer {
118120
(void)connectionHandle;
119121
(void)attMtuSize;
120122
}
123+
124+
/**
125+
* Function invoked when the server has sent data to a client as
126+
* part of a notification/indication.
127+
*
128+
* @note params has a temporary scope and should be copied by the
129+
* application if needed later
130+
*/
131+
virtual void onDataSent(const GattDataSentCallbackParams &params) {
132+
(void)params;
133+
}
134+
135+
/**
136+
* Function invoked when a client writes an attribute
137+
*
138+
* @note params has a temporary scope and should be copied by the
139+
* application if needed later
140+
*/
141+
virtual void onDataWritten(const GattWriteCallbackParams &params) {
142+
(void)params;
143+
}
144+
145+
/**
146+
* Function invoked when a client reads an attribute
147+
*
148+
* @note This functionality may not be available on all underlying stacks.
149+
* Application code may work around that limitation by monitoring read
150+
* requests instead of read events.
151+
*
152+
* @note params has a temporary scope and should be copied by the
153+
* application if needed later
154+
*
155+
* @see GattCharacteristic::setReadAuthorizationCallback()
156+
* @see isOnDataReadAvailable().
157+
*/
158+
virtual void onDataRead(const GattReadCallbackParams &params) {
159+
(void)params;
160+
}
161+
162+
/**
163+
* Function invoked when the GattServer instance is about
164+
* to be shut down. This can result in a call to reset() or BLE::reset().
165+
*/
166+
virtual void onShutdown(const GattServer &server) {
167+
(void)server;
168+
}
169+
170+
/**
171+
* Function invoked when the client has subscribed to characteristic updates
172+
*
173+
* @note params has a temporary scope and should be copied by the
174+
* application if needed later
175+
*/
176+
virtual void onUpdatesEnabled(const GattUpdatesEnabledCallbackParams &params) {
177+
(void)params;
178+
}
179+
180+
/**
181+
* Function invoked when the client has unsubscribed to characteristic updates
182+
*
183+
* @note params has a temporary scope and should be copied by the
184+
* application if needed later
185+
*/
186+
virtual void onUpdatesDisabled(const GattUpdatesDisabledCallbackParams &params) {
187+
(void)params;
188+
}
189+
190+
/**
191+
* Function invoked when an ACK has been received for an
192+
* indication sent to the client.
193+
*
194+
* @note params has a temporary scope and should be copied by the
195+
* application if needed later
196+
*/
197+
virtual void onConfirmationReceived(const GattConfirmationReceivedCallbackParams &params) {
198+
(void)params;
199+
}
200+
121201
protected:
122202
/**
123203
* Prevent polymorphic deletion and avoid unnecessary virtual destructor
@@ -204,6 +284,12 @@ class GattServer {
204284
* module to signal events back to the application.
205285
*
206286
* @param handler Application implementation of an EventHandler.
287+
*
288+
* @note Multiple discrete EventHandler instances may be used by adding them
289+
* to a ChainableGattServerEventHandler and then setting the chain as the primary
290+
* GattServer EventHandler using this function.
291+
*
292+
* @see ChainableGattServerEventHandler
207293
*/
208294
void setEventHandler(EventHandler *handler);
209295

@@ -401,6 +487,8 @@ class GattServer {
401487
* @note It is possible to chain together multiple onDataSent callbacks
402488
* (potentially from different modules of an application).
403489
*/
490+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
491+
"been replaced by GattServer::setEventHandler. Use that function instead.")
404492
void onDataSent(const DataSentCallback_t &callback);
405493

406494
/**
@@ -413,6 +501,8 @@ class GattServer {
413501
* function.
414502
*/
415503
template <typename T>
504+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
505+
"been replaced by GattServer::setEventHandler. Use that function instead.")
416506
void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count))
417507
{
418508
onDataSent({objPtr, memberPtr});
@@ -423,6 +513,8 @@ class GattServer {
423513
*
424514
* @return A reference to the DATA_SENT event callback chain.
425515
*/
516+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
517+
"been replaced by GattServer::setEventHandler. Use that function instead.")
426518
DataSentCallbackChain_t &onDataSent();
427519

428520
/**
@@ -434,6 +526,8 @@ class GattServer {
434526
* @attention It is possible to set multiple event handlers. Registered
435527
* handlers may be removed with onDataWritten().detach(callback).
436528
*/
529+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
530+
"been replaced by GattServer::setEventHandler. Use that function instead.")
437531
void onDataWritten(const DataWrittenCallback_t &callback);
438532

439533
/**
@@ -446,6 +540,8 @@ class GattServer {
446540
* function.
447541
*/
448542
template <typename T>
543+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
544+
"been replaced by GattServer::setEventHandler. Use that function instead.")
449545
void onDataWritten(
450546
T *objPtr,
451547
void (T::*memberPtr)(const GattWriteCallbackParams *context)
@@ -465,6 +561,8 @@ class GattServer {
465561
* @note It is possible to unregister callbacks using
466562
* onDataWritten().detach(callback).
467563
*/
564+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
565+
"been replaced by GattServer::setEventHandler. Use that function instead.")
468566
DataWrittenCallbackChain_t &onDataWritten();
469567

470568
/**
@@ -485,6 +583,8 @@ class GattServer {
485583
* @attention It is possible to set multiple event handlers. Registered
486584
* handlers may be removed with onDataRead().detach(callback).
487585
*/
586+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
587+
"been replaced by GattServer::setEventHandler. Use that function instead.")
488588
ble_error_t onDataRead(const DataReadCallback_t &callback);
489589

490590
/**
@@ -496,6 +596,8 @@ class GattServer {
496596
* function.
497597
*/
498598
template <typename T>
599+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
600+
"been replaced by GattServer::setEventHandler. Use that function instead.")
499601
ble_error_t onDataRead(
500602
T *objPtr,
501603
void (T::*memberPtr)(const GattReadCallbackParams *context)
@@ -515,6 +617,8 @@ class GattServer {
515617
* @note It is possible to unregister callbacks using
516618
* onDataRead().detach(callback).
517619
*/
620+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
621+
"been replaced by GattServer::setEventHandler. Use that function instead.")
518622
DataReadCallbackChain_t &onDataRead();
519623

520624
/**
@@ -530,6 +634,8 @@ class GattServer {
530634
* @note It is possible to unregister a callback using
531635
* onShutdown().detach(callback)
532636
*/
637+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
638+
"been replaced by GattServer::setEventHandler. Use that function instead.")
533639
void onShutdown(const GattServerShutdownCallback_t &callback);
534640

535641
/**
@@ -544,6 +650,8 @@ class GattServer {
544650
* function.
545651
*/
546652
template <typename T>
653+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
654+
"been replaced by GattServer::setEventHandler. Use that function instead.")
547655
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattServer *))
548656
{
549657
onShutdown({objPtr, memberPtr});
@@ -560,6 +668,8 @@ class GattServer {
560668
* @note It is possible to unregister callbacks using
561669
* onShutdown().detach(callback).
562670
*/
671+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
672+
"been replaced by GattServer::setEventHandler. Use that function instead.")
563673
GattServerShutdownCallbackChain_t& onShutdown();
564674

565675
/**
@@ -568,6 +678,8 @@ class GattServer {
568678
*
569679
* @param[in] callback Event handler being registered.
570680
*/
681+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
682+
"been replaced by GattServer::setEventHandler. Use that function instead.")
571683
void onUpdatesEnabled(EventCallback_t callback);
572684

573685
/**
@@ -576,6 +688,8 @@ class GattServer {
576688
*
577689
* @param[in] callback Event handler being registered.
578690
*/
691+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
692+
"been replaced by GattServer::setEventHandler. Use that function instead.")
579693
void onUpdatesDisabled(EventCallback_t callback);
580694

581695
/**
@@ -586,6 +700,8 @@ class GattServer {
586700
*
587701
* @param[in] callback Event handler being registered.
588702
*/
703+
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "Individual callback-registering functions have"
704+
"been replaced by GattServer::setEventHandler. Use that function instead.")
589705
void onConfirmationReceived(EventCallback_t callback);
590706

591707
#if !defined(DOXYGEN_ONLY)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2020 ARM Limited
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef MBED_CHAINABLEEVENTHANDLER_H_
19+
#define MBED_CHAINABLEEVENTHANDLER_H_
20+
21+
#include <new>
22+
23+
/**
24+
* Base class for chainable EventHandlers. Acts as a collection
25+
* of discrete EventHandlers that can be linked together and
26+
* notified when relevant events happen
27+
*/
28+
template<typename T>
29+
class ChainableEventHandler
30+
{
31+
32+
public:
33+
34+
ChainableEventHandler() { }
35+
36+
~ChainableEventHandler() {
37+
// Clean up all nodes
38+
auto it = head;
39+
while(it) {
40+
node_t* temp = it;
41+
it = it->next;
42+
delete temp;
43+
}
44+
}
45+
46+
/**
47+
* Add an EventHandler to be notified of events sent to
48+
* this ChainableEventHandler
49+
*
50+
* @param[in] event_handler Handler to add to chain
51+
*
52+
* @retval true if adding EventHandler was successful, false otherwise
53+
*/
54+
bool addEventHandler(T* event_handler) {
55+
auto eh = new (std::nothrow) node_t { event_handler, nullptr };
56+
if(!eh) { return false; }
57+
if(!head) {
58+
head = eh;
59+
} else {
60+
auto *it = head;
61+
while(it->next) {
62+
it = it->next;
63+
}
64+
it->next = eh;
65+
}
66+
return true;
67+
}
68+
69+
/**
70+
* Remove an EventHandler previously added with addEventHandler.
71+
*
72+
* @param[in] event_handler Pointer to event handler to remove
73+
*/
74+
void removeEventHandler(T* target) {
75+
node_t* to_remove = head;
76+
if(head->eh == target) {
77+
head = head->next;
78+
} else {
79+
auto* it = head;
80+
while(it->next) {
81+
if(it->next->eh == target) {
82+
to_remove = it->next;
83+
break;
84+
}
85+
it = it->next;
86+
}
87+
if(it->next) {
88+
it->next = to_remove->next;
89+
} else {
90+
to_remove = nullptr;
91+
}
92+
}
93+
94+
delete to_remove;
95+
}
96+
97+
protected:
98+
99+
template<typename... FnArgs, typename... Args>
100+
void execute_on_all(void (T::*fn)(FnArgs...), Args&&... args) {
101+
auto it = head;
102+
while(it) {
103+
// we do not use std::forward, args have to remain lvalues
104+
// as they are passed to multiple handlers
105+
(it->eh->*fn)(args...);
106+
it = it->next;
107+
}
108+
}
109+
110+
private:
111+
112+
struct node_t {
113+
T* eh;
114+
node_t* next = nullptr;
115+
};
116+
117+
node_t *head = nullptr;
118+
119+
};
120+
121+
#endif /* MBED_CHAINABLEEVENTHANDLER_H_ */

0 commit comments

Comments
 (0)