High level Bluetooth Low Energy API and radio abstraction layer

Fork of BLE_API by Bluetooth Low Energy

Committer:
rgrover1
Date:
Mon Nov 02 09:09:06 2015 +0000
Revision:
854:ad4ae73c2b5a
Parent:
828:d22ab1419e92
Child:
857:7f578be2d01d
Synchronized with git rev 918af4fb
Author: Rohit Grover
Major change:
- There's a new type: BLE::InitializationCompleteCallback_t
- init() now takes a completion callback. This is an optional parameter, if no callback is setup the application can still determine the status of initialization using BLE::hasInitialized() (see below).
- There's a new API: BLEInstanceBase::hasInitialized() which transports need to implement.
- BLEInstanceBase.h is no longer included from BLE.h. We use a forward declaration of BLEInstanceBase instead. This is required us to move implementations of BLE methods out of the header and into BLE.cpp.
- There's a new API: BLE::getInstanceID(), which simply returns the ID of an instance.
- There are new error types around initialization.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 712:b04b5db36865 1 /* mbed Microcontroller Library
rgrover1 712:b04b5db36865 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 712:b04b5db36865 3 *
rgrover1 712:b04b5db36865 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 712:b04b5db36865 5 * you may not use this file except in compliance with the License.
rgrover1 712:b04b5db36865 6 * You may obtain a copy of the License at
rgrover1 712:b04b5db36865 7 *
rgrover1 712:b04b5db36865 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 712:b04b5db36865 9 *
rgrover1 712:b04b5db36865 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 712:b04b5db36865 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 712:b04b5db36865 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 712:b04b5db36865 13 * See the License for the specific language governing permissions and
rgrover1 712:b04b5db36865 14 * limitations under the License.
rgrover1 712:b04b5db36865 15 */
rgrover1 712:b04b5db36865 16
rgrover1 712:b04b5db36865 17 #include "ble/BLE.h"
rgrover1 854:ad4ae73c2b5a 18 #include "ble/BLEInstanceBase.h"
rgrover1 712:b04b5db36865 19
rgrover1 712:b04b5db36865 20 #if defined(TARGET_OTA_ENABLED)
rgrover1 732:916f36dd93f8 21 #include "ble/services/DFUService.h"
rgrover1 712:b04b5db36865 22 #endif
rgrover1 712:b04b5db36865 23
rgrover1 712:b04b5db36865 24 ble_error_t
rgrover1 854:ad4ae73c2b5a 25 BLE::init(BLE::InitializationCompleteCallback_t callback)
rgrover1 712:b04b5db36865 26 {
rgrover1 854:ad4ae73c2b5a 27 ble_error_t err = transport->init(instanceID, callback);
rgrover1 712:b04b5db36865 28 if (err != BLE_ERROR_NONE) {
rgrover1 712:b04b5db36865 29 return err;
rgrover1 712:b04b5db36865 30 }
rgrover1 712:b04b5db36865 31
rgrover1 712:b04b5db36865 32 /* Platforms enabled for DFU should introduce the DFU Service into
rgrover1 712:b04b5db36865 33 * applications automatically. */
rgrover1 712:b04b5db36865 34 #if defined(TARGET_OTA_ENABLED)
rgrover1 712:b04b5db36865 35 static DFUService dfu(*this); // defined static so that the object remains alive
rgrover1 712:b04b5db36865 36 #endif // TARGET_OTA_ENABLED
rgrover1 712:b04b5db36865 37
rgrover1 712:b04b5db36865 38 return BLE_ERROR_NONE;
rgrover1 822:a0f080d1e836 39 }
rgrover1 822:a0f080d1e836 40
rgrover1 822:a0f080d1e836 41 /**
rgrover1 822:a0f080d1e836 42 * BLE::Instance() and BLE constructor rely upon a static array of initializers
rgrover1 822:a0f080d1e836 43 * to create actual BLE transport instances. A description of these instances
rgrover1 822:a0f080d1e836 44 * and initializers is supposed to be put in some .json file contributing to
rgrover1 828:d22ab1419e92 45 * yotta's configuration (typically in the target definition described by
rgrover1 828:d22ab1419e92 46 * target.json). Here's a sample:
rgrover1 822:a0f080d1e836 47 *
rgrover1 822:a0f080d1e836 48 * "config": {
rgrover1 822:a0f080d1e836 49 * ...
rgrover1 822:a0f080d1e836 50 * "ble_instances": {
rgrover1 822:a0f080d1e836 51 * "count": 1,
rgrover1 822:a0f080d1e836 52 * "0" : {
rgrover1 822:a0f080d1e836 53 * "initializer" : "createBLEInstance"
rgrover1 822:a0f080d1e836 54 * }
rgrover1 822:a0f080d1e836 55 * }
rgrover1 828:d22ab1419e92 56 * ...
rgrover1 822:a0f080d1e836 57 * }
rgrover1 822:a0f080d1e836 58 *
rgrover1 822:a0f080d1e836 59 * The following macros result in translating the above config into a static
rgrover1 822:a0f080d1e836 60 * array: instanceConstructors.
rgrover1 822:a0f080d1e836 61 */
rgrover1 822:a0f080d1e836 62 #ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
rgrover1 822:a0f080d1e836 63 #define CONCATENATE(A, B) A ## B
rgrover1 822:a0f080d1e836 64 #define EXPAND(X) X /* this adds a level of indirection needed to allow macro-expansion following a token-paste operation (see use of CONCATENATE() below). */
rgrover1 822:a0f080d1e836 65
rgrover1 822:a0f080d1e836 66 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
rgrover1 822:a0f080d1e836 67 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
rgrover1 822:a0f080d1e836 68 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
rgrover1 822:a0f080d1e836 69 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
rgrover1 822:a0f080d1e836 70 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
rgrover1 822:a0f080d1e836 71 /* ... add more of the above if ever needed */
rgrover1 822:a0f080d1e836 72
rgrover1 822:a0f080d1e836 73 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
rgrover1 827:a63b24d78132 74 #elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
rgrover1 827:a63b24d78132 75 /*
rgrover1 827:a63b24d78132 76 * The following applies when building without yotta. By default BLE_API provides
rgrover1 827:a63b24d78132 77 * a trivial initializer list containing a single constructor: createBLEInstance.
rgrover1 827:a63b24d78132 78 * This may be overridden.
rgrover1 827:a63b24d78132 79 */
rgrover1 827:a63b24d78132 80 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance
rgrover1 822:a0f080d1e836 81 #endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */
rgrover1 822:a0f080d1e836 82
rgrover1 822:a0f080d1e836 83 typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
rgrover1 822:a0f080d1e836 84 static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
rgrover1 822:a0f080d1e836 85 #ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
rgrover1 827:a63b24d78132 86 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
rgrover1 822:a0f080d1e836 87 #else
rgrover1 822:a0f080d1e836 88 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
rgrover1 822:a0f080d1e836 89 #endif
rgrover1 822:a0f080d1e836 90 };
rgrover1 822:a0f080d1e836 91
rgrover1 825:b65c6a222525 92 BLE &
rgrover1 822:a0f080d1e836 93 BLE::Instance(InstanceID_t id)
rgrover1 822:a0f080d1e836 94 {
rgrover1 822:a0f080d1e836 95 static BLE *singletons[NUM_INSTANCES];
rgrover1 822:a0f080d1e836 96 if (id < NUM_INSTANCES) {
rgrover1 822:a0f080d1e836 97 if (singletons[id] == NULL) {
rgrover1 822:a0f080d1e836 98 singletons[id] = new BLE(id); /* This object will never be freed. */
rgrover1 822:a0f080d1e836 99 }
rgrover1 822:a0f080d1e836 100
rgrover1 822:a0f080d1e836 101 return *singletons[id];
rgrover1 822:a0f080d1e836 102 }
rgrover1 822:a0f080d1e836 103
rgrover1 822:a0f080d1e836 104 /* we come here only in the case of a bad interfaceID. */
rgrover1 822:a0f080d1e836 105 static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
rgrover1 822:a0f080d1e836 106 return badSingleton;
rgrover1 822:a0f080d1e836 107 }
rgrover1 822:a0f080d1e836 108
rgrover1 854:ad4ae73c2b5a 109 BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport()
rgrover1 822:a0f080d1e836 110 {
rgrover1 822:a0f080d1e836 111 static BLEInstanceBase *transportInstances[NUM_INSTANCES];
rgrover1 822:a0f080d1e836 112
rgrover1 822:a0f080d1e836 113 if (instanceID < NUM_INSTANCES) {
rgrover1 822:a0f080d1e836 114 if (!transportInstances[instanceID]) {
rgrover1 822:a0f080d1e836 115 transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
rgrover1 822:a0f080d1e836 116 }
rgrover1 822:a0f080d1e836 117 transport = transportInstances[instanceID];
rgrover1 822:a0f080d1e836 118 } else {
rgrover1 822:a0f080d1e836 119 transport = NULL;
rgrover1 822:a0f080d1e836 120 }
rgrover1 854:ad4ae73c2b5a 121 }
rgrover1 854:ad4ae73c2b5a 122
rgrover1 854:ad4ae73c2b5a 123 bool BLE::hasInitialized(void) const
rgrover1 854:ad4ae73c2b5a 124 {
rgrover1 854:ad4ae73c2b5a 125 if (!transport) {
rgrover1 854:ad4ae73c2b5a 126 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 127 }
rgrover1 854:ad4ae73c2b5a 128
rgrover1 854:ad4ae73c2b5a 129 return transport->hasInitialized();
rgrover1 854:ad4ae73c2b5a 130 }
rgrover1 854:ad4ae73c2b5a 131
rgrover1 854:ad4ae73c2b5a 132 ble_error_t BLE::shutdown(void)
rgrover1 854:ad4ae73c2b5a 133 {
rgrover1 854:ad4ae73c2b5a 134 clearAdvertisingPayload();
rgrover1 854:ad4ae73c2b5a 135 if (!transport) {
rgrover1 854:ad4ae73c2b5a 136 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 137 }
rgrover1 854:ad4ae73c2b5a 138
rgrover1 854:ad4ae73c2b5a 139 return transport->shutdown();
rgrover1 854:ad4ae73c2b5a 140 }
rgrover1 854:ad4ae73c2b5a 141
rgrover1 854:ad4ae73c2b5a 142 const char *BLE::getVersion(void)
rgrover1 854:ad4ae73c2b5a 143 {
rgrover1 854:ad4ae73c2b5a 144 if (!transport) {
rgrover1 854:ad4ae73c2b5a 145 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 146 }
rgrover1 854:ad4ae73c2b5a 147
rgrover1 854:ad4ae73c2b5a 148 return transport->getVersion();
rgrover1 854:ad4ae73c2b5a 149 }
rgrover1 854:ad4ae73c2b5a 150
rgrover1 854:ad4ae73c2b5a 151 const Gap &BLE::gap() const
rgrover1 854:ad4ae73c2b5a 152 {
rgrover1 854:ad4ae73c2b5a 153 if (!transport) {
rgrover1 854:ad4ae73c2b5a 154 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 155 }
rgrover1 854:ad4ae73c2b5a 156
rgrover1 854:ad4ae73c2b5a 157 return transport->getGap();
rgrover1 854:ad4ae73c2b5a 158 }
rgrover1 854:ad4ae73c2b5a 159
rgrover1 854:ad4ae73c2b5a 160 Gap &BLE::gap()
rgrover1 854:ad4ae73c2b5a 161 {
rgrover1 854:ad4ae73c2b5a 162 if (!transport) {
rgrover1 854:ad4ae73c2b5a 163 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 164 }
rgrover1 854:ad4ae73c2b5a 165
rgrover1 854:ad4ae73c2b5a 166 return transport->getGap();
rgrover1 854:ad4ae73c2b5a 167 }
rgrover1 854:ad4ae73c2b5a 168
rgrover1 854:ad4ae73c2b5a 169 const GattServer& BLE::gattServer() const
rgrover1 854:ad4ae73c2b5a 170 {
rgrover1 854:ad4ae73c2b5a 171 if (!transport) {
rgrover1 854:ad4ae73c2b5a 172 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 173 }
rgrover1 854:ad4ae73c2b5a 174
rgrover1 854:ad4ae73c2b5a 175 return transport->getGattServer();
rgrover1 854:ad4ae73c2b5a 176 }
rgrover1 854:ad4ae73c2b5a 177
rgrover1 854:ad4ae73c2b5a 178 GattServer& BLE::gattServer()
rgrover1 854:ad4ae73c2b5a 179 {
rgrover1 854:ad4ae73c2b5a 180 if (!transport) {
rgrover1 854:ad4ae73c2b5a 181 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 182 }
rgrover1 854:ad4ae73c2b5a 183
rgrover1 854:ad4ae73c2b5a 184 return transport->getGattServer();
rgrover1 854:ad4ae73c2b5a 185 }
rgrover1 854:ad4ae73c2b5a 186
rgrover1 854:ad4ae73c2b5a 187 const GattClient& BLE::gattClient() const
rgrover1 854:ad4ae73c2b5a 188 {
rgrover1 854:ad4ae73c2b5a 189 if (!transport) {
rgrover1 854:ad4ae73c2b5a 190 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 191 }
rgrover1 854:ad4ae73c2b5a 192
rgrover1 854:ad4ae73c2b5a 193 return transport->getGattClient();
rgrover1 854:ad4ae73c2b5a 194 }
rgrover1 854:ad4ae73c2b5a 195
rgrover1 854:ad4ae73c2b5a 196 GattClient& BLE::gattClient()
rgrover1 854:ad4ae73c2b5a 197 {
rgrover1 854:ad4ae73c2b5a 198 if (!transport) {
rgrover1 854:ad4ae73c2b5a 199 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 200 }
rgrover1 854:ad4ae73c2b5a 201
rgrover1 854:ad4ae73c2b5a 202 return transport->getGattClient();
rgrover1 854:ad4ae73c2b5a 203 }
rgrover1 854:ad4ae73c2b5a 204
rgrover1 854:ad4ae73c2b5a 205 const SecurityManager& BLE::securityManager() const
rgrover1 854:ad4ae73c2b5a 206 {
rgrover1 854:ad4ae73c2b5a 207 if (!transport) {
rgrover1 854:ad4ae73c2b5a 208 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 209 }
rgrover1 854:ad4ae73c2b5a 210
rgrover1 854:ad4ae73c2b5a 211 return transport->getSecurityManager();
rgrover1 854:ad4ae73c2b5a 212 }
rgrover1 854:ad4ae73c2b5a 213
rgrover1 854:ad4ae73c2b5a 214 SecurityManager& BLE::securityManager()
rgrover1 854:ad4ae73c2b5a 215 {
rgrover1 854:ad4ae73c2b5a 216 if (!transport) {
rgrover1 854:ad4ae73c2b5a 217 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 218 }
rgrover1 854:ad4ae73c2b5a 219
rgrover1 854:ad4ae73c2b5a 220 return transport->getSecurityManager();
rgrover1 854:ad4ae73c2b5a 221 }
rgrover1 854:ad4ae73c2b5a 222
rgrover1 854:ad4ae73c2b5a 223 void BLE::waitForEvent(void)
rgrover1 854:ad4ae73c2b5a 224 {
rgrover1 854:ad4ae73c2b5a 225 if (!transport) {
rgrover1 854:ad4ae73c2b5a 226 error("bad handle to underlying transport");
rgrover1 854:ad4ae73c2b5a 227 }
rgrover1 854:ad4ae73c2b5a 228
rgrover1 854:ad4ae73c2b5a 229 transport->waitForEvent();
rgrover1 712:b04b5db36865 230 }