Skip to content

Commit b13f6f3

Browse files
author
Rohit Grover
committed
Release 0.2.0
============= Highlights: Introducing standard services to simplify applications. Add support for over-the-air firmware updates. Features ~~~~~~~~ - This release introduces 'templates' for common services such as heart-rate, battery-level, device-info, UART, device-firmware-update etc. These services take the shape of class declarations within header files aggregated under a new folder called 'services/'. These service-classes provide a high-level API hopefully easing the burden of developing BLE applications. The underlying APIs to work with characteristics and services are still available to allow greater control if needed. We expect to grow the supported services to include all SIG defined BLE profiles. - WriteCallbackParams now includes the characteristic's value-attribute handle; this changes the signature of onDataWritten(). - BLEDevice::onDataWritten() now allows chaining of callbacks--this means that it is possible to chain together multiple onDataWritten callbacks (potentially from different modules of an application) to receive updates to characteristics. Many services, such as DFU and UART add their own onDataWritten callbacks behind the scenes to trap interesting events. It is also possible to chain callbacks to functions within objects. - Added the following expectation for GattCharacteristic: If valuePtr == NULL, initialLength == 0, and properties == READ for the value attribute of a characteristic, then that particular characteristic may be considered optional and dropped while instantiating the service with the underlying BLE stack. - Introducing the typedef GattAttribute::Handle_t to capture Attribute handles. Bugfixes ~~~~~~~~ None. Compatibility ~~~~~~~~~~~~~ The signature of onDataWritten() has seen a change; so application programs using this new version of the BLE API will need minor modifications. Please refer to sample programs under BLE team page.
1 parent b134b51 commit b13f6f3

15 files changed

+1212
-16
lines changed

public/BLEDevice.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,18 @@ class BLEDevice
213213
/**
214214
* Setup a callback for when a characteristic has its value updated by a
215215
* client.
216+
*
217+
* @Note: it is possible to chain together multiple onDataWritten callbacks
218+
* (potentially from different modules of an application) to receive updates
219+
* to characteristics. Many services, such as DFU and UART add their own
220+
* onDataWritten callbacks behind the scenes to trap interesting events.
221+
*
222+
* @Note: it is also possible to setup a callback into a member function of
223+
* some object.
216224
*/
217-
void onDataWritten(GattServer::WriteEventCallback_t callback);
225+
void onDataWritten(void (*callback)(const GattCharacteristicWriteCBParams *eventDataP));
226+
template <typename T> void onDataWritten(T *objPtr, void (T::*memberPtr)(const GattCharacteristicWriteCBParams *context));
227+
218228
void onUpdatesEnabled(GattServer::EventCallback_t callback);
219229
void onUpdatesDisabled(GattServer::EventCallback_t callback);
220230
void onConfirmationReceived(GattServer::EventCallback_t callback);
@@ -227,7 +237,17 @@ class BLEDevice
227237

228238
Gap::GapState_t getGapState(void) const;
229239

240+
/**
241+
* @param[in/out] lengthP
242+
* input: Length in bytes to be read,
243+
* output: Total length of attribute value upon successful return.
244+
*/
230245
ble_error_t readCharacteristicValue(uint16_t handle, uint8_t *const buffer, uint16_t *const lengthP);
246+
247+
/**
248+
* @param localOnly
249+
* Only update the characteristic locally regardless of notify/indicate flags in the CCCD.
250+
*/
231251
ble_error_t updateCharacteristicValue(uint16_t handle, const uint8_t* value, uint16_t size, bool localOnly = false);
232252

233253
/**
@@ -473,11 +493,16 @@ BLEDevice::onDataSent(GattServer::ServerEventCallbackWithCount_t callback)
473493
}
474494

475495
inline void
476-
BLEDevice::onDataWritten(GattServer::WriteEventCallback_t callback)
477-
{
496+
BLEDevice::onDataWritten(void (*callback)(const GattCharacteristicWriteCBParams *eventDataP)) {
478497
transport->getGattServer().setOnDataWritten(callback);
479498
}
480499

500+
template <typename T> inline void
501+
BLEDevice::onDataWritten(T *objPtr, void (T::*memberPtr)(const GattCharacteristicWriteCBParams *context)) {
502+
transport->getGattServer().setOnDataWritten(objPtr, memberPtr);
503+
}
504+
505+
481506
inline void
482507
BLEDevice::onUpdatesEnabled(GattServer::EventCallback_t callback)
483508
{
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
17+
#define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
18+
19+
#include <string.h>
20+
#include "FunctionPointerWithContext.h"
21+
22+
namespace mbed {
23+
24+
/** Group one or more functions in an instance of a CallChainOfFunctionPointersWithContext, then call them in
25+
* sequence using CallChainOfFunctionPointersWithContext::call(). Used mostly by the interrupt chaining code,
26+
* but can be used for other purposes.
27+
*
28+
* Example:
29+
* @code
30+
* #include "mbed.h"
31+
*
32+
* CallChainOfFunctionPointersWithContext<void *> chain;
33+
*
34+
* void first(void *context) {
35+
* printf("'first' function.\n");
36+
* }
37+
*
38+
* void second(void *context) {
39+
* printf("'second' function.\n");
40+
* }
41+
*
42+
* class Test {
43+
* public:
44+
* void f(void *context) {
45+
* printf("A::f (class member).\n");
46+
* }
47+
* };
48+
*
49+
* int main() {
50+
* Test test;
51+
*
52+
* chain.add(second);
53+
* chain.add_front(first);
54+
* chain.add(&test, &Test::f);
55+
* chain.call();
56+
* }
57+
* @endcode
58+
*/
59+
60+
template <typename ContextType>
61+
class CallChainOfFunctionPointersWithContext {
62+
public:
63+
typedef FunctionPointerWithContext<ContextType>* pFunctionPointerWithContext_t;
64+
65+
public:
66+
/** Create an empty chain
67+
*
68+
* @param size (optional) Initial size of the chain
69+
*/
70+
CallChainOfFunctionPointersWithContext() : chainHead(NULL) {
71+
/* empty */
72+
}
73+
74+
virtual ~CallChainOfFunctionPointersWithContext() {
75+
clear();
76+
}
77+
78+
/** Add a function at the front of the chain
79+
*
80+
* @param function A pointer to a void function
81+
*
82+
* @returns
83+
* The function object created for 'function'
84+
*/
85+
pFunctionPointerWithContext_t add(void (*function)(ContextType context)) {
86+
return common_add(new FunctionPointerWithContext<ContextType>(function));
87+
}
88+
89+
/** Add a function at the front of the chain
90+
*
91+
* @param tptr pointer to the object to call the member function on
92+
* @param mptr pointer to the member function to be called
93+
*
94+
* @returns
95+
* The function object created for 'tptr' and 'mptr'
96+
*/
97+
template<typename T>
98+
pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) {
99+
return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
100+
}
101+
102+
/** Clear the call chain (remove all functions in the chain).
103+
*/
104+
void clear(void) {
105+
pFunctionPointerWithContext_t fptr = chainHead;
106+
while (fptr) {
107+
pFunctionPointerWithContext_t deadPtr = fptr;
108+
fptr = deadPtr->getNext();
109+
delete deadPtr;
110+
}
111+
112+
chainHead = NULL;
113+
}
114+
115+
bool hasCallbacksAttached(void) const {
116+
return (chainHead != NULL);
117+
}
118+
119+
/** Call all the functions in the chain in sequence
120+
* @Note: the stack frames of all the callbacks within the chained
121+
* FunctionPointers will stack up. Hopefully there won't be too many
122+
* chained FunctionPointers.
123+
*/
124+
void call(ContextType context) {
125+
if (chainHead)
126+
chainHead->call(context);
127+
}
128+
129+
private:
130+
pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) {
131+
if (chainHead == NULL) {
132+
chainHead = pf;
133+
} else {
134+
pf->chainAsNext(chainHead);
135+
chainHead = pf;
136+
}
137+
138+
return chainHead;
139+
}
140+
141+
private:
142+
pFunctionPointerWithContext_t chainHead;
143+
144+
/* disallow copy constructor and assignment operators */
145+
private:
146+
CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &);
147+
CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &);
148+
};
149+
150+
} // namespace mbed
151+
152+
#endif
153+

public/FunctionPointerWithContext.h

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
18+
#define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
19+
20+
#include <string.h>
21+
22+
namespace mbed {
23+
24+
/** A class for storing and calling a pointer to a static or member void function
25+
* which takes a context.
26+
*/
27+
template <typename ContextType>
28+
class FunctionPointerWithContext {
29+
public:
30+
typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
31+
typedef void (*pvoidfcontext_t)(ContextType context);
32+
33+
/** Create a FunctionPointerWithContext, attaching a static function
34+
*
35+
* @param function The void static function to attach (default is none)
36+
*/
37+
FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
38+
_function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
39+
attach(function);
40+
}
41+
42+
/** Create a FunctionPointerWithContext, attaching a member function
43+
*
44+
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
45+
* @param function The address of the void member function to attach
46+
*/
47+
template<typename T>
48+
FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
49+
_function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
50+
attach(object, member);
51+
}
52+
53+
/** Attach a static function
54+
*
55+
* @param function The void static function to attach (default is none)
56+
*/
57+
void attach(void (*function)(ContextType context) = NULL) {
58+
_function = function;
59+
}
60+
61+
/** Attach a member function
62+
*
63+
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
64+
* @param function The address of the void member function to attach
65+
*/
66+
template<typename T>
67+
void attach(T *object, void (T::*member)(ContextType context)) {
68+
_object = static_cast<void *>(object);
69+
memcpy(_member, (char *)&member, sizeof(member));
70+
_membercaller = &FunctionPointerWithContext::membercaller<T>;
71+
}
72+
73+
/** Call the attached static or member function; and if there are chained
74+
* FunctionPointers their callbacks are invoked as well.
75+
* @Note: all chained callbacks stack up; so hopefully there won't be too
76+
* many FunctionPointers in a chain. */
77+
void call(ContextType context) {
78+
if (_function) {
79+
_function(context);
80+
} else if (_object && _membercaller) {
81+
_membercaller(_object, _member, context);
82+
}
83+
84+
/* Propagate the call to next in the chain. */
85+
if (_next) {
86+
_next->call(context);
87+
}
88+
}
89+
90+
/**
91+
* Setup an external FunctionPointer as a next in the chain of related
92+
* callbacks. Invoking call() on the head FunctionPointer will invoke all
93+
* chained callbacks.
94+
*
95+
* Refer to 'CallChain' as an alternative.
96+
*/
97+
void chainAsNext(pFunctionPointerWithContext_t next) {
98+
_next = next;
99+
}
100+
101+
pFunctionPointerWithContext_t getNext(void) const {
102+
return _next;
103+
}
104+
105+
pvoidfcontext_t get_function() const {
106+
return (pvoidfcontext_t)_function;
107+
}
108+
109+
private:
110+
template<typename T>
111+
static void membercaller(void *object, char *member, ContextType context) {
112+
T *o = static_cast<T *>(object);
113+
void (T::*m)(ContextType);
114+
memcpy((char *)&m, member, sizeof(m));
115+
(o->*m)(context);
116+
}
117+
118+
void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */
119+
void *_object; /**< object this pointer - NULL if none attached */
120+
char _member[16]; /**< raw member function pointer storage - converted back by
121+
* registered _membercaller */
122+
void (*_membercaller)(void *, char *, ContextType); /**< registered membercaller function to convert back and call
123+
* _member on _object passing the context. */
124+
pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this
125+
* allows chaining function pointers without requiring
126+
* external memory to manage the chain. Also refer to
127+
* 'CallChain' as an alternative. */
128+
};
129+
} // namespace mbed
130+
131+
#endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H

public/GattAttribute.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
class GattAttribute
3030
{
3131
public:
32+
typedef uint16_t Handle_t;
3233

34+
public:
3335
/**
3436
* @brief Creates a new GattAttribute using the specified
3537
* UUID, value length, and inital value
@@ -59,21 +61,26 @@ class GattAttribute
5961
}
6062

6163
public:
62-
uint16_t getHandle(void) const {
64+
Handle_t getHandle(void) const {
6365
return _handle;
6466
}
65-
void setHandle(uint16_t id) {
67+
68+
void setHandle(Handle_t id) {
6669
_handle = id;
6770
}
71+
6872
const UUID &getUUID(void) const {
6973
return _uuid;
7074
}
75+
7176
uint16_t getInitialLength(void) const {
7277
return _initialLen;
7378
}
79+
7480
uint16_t getMaxLength(void) const {
7581
return _lenMax;
7682
}
83+
7784
uint8_t *getValuePtr(void) {
7885
return _valuePtr;
7986
}
@@ -83,7 +90,7 @@ class GattAttribute
8390
uint8_t *_valuePtr;
8491
uint16_t _initialLen; /* Initial length of the value */
8592
uint16_t _lenMax; /* Maximum length of the value */
86-
uint16_t _handle;
93+
Handle_t _handle;
8794
};
8895

8996
#endif // ifndef __GATT_ATTRIBUTE_H__

0 commit comments

Comments
 (0)