Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Simon Cooksey 0:fb7af294d5d9 1 /* mbed Microcontroller Library
Simon Cooksey 0:fb7af294d5d9 2 * Copyright (c) 2006-2013 ARM Limited
Simon Cooksey 0:fb7af294d5d9 3 *
Simon Cooksey 0:fb7af294d5d9 4 * Licensed under the Apache License, Version 2.0 (the "License");
Simon Cooksey 0:fb7af294d5d9 5 * you may not use this file except in compliance with the License.
Simon Cooksey 0:fb7af294d5d9 6 * You may obtain a copy of the License at
Simon Cooksey 0:fb7af294d5d9 7 *
Simon Cooksey 0:fb7af294d5d9 8 * http://www.apache.org/licenses/LICENSE-2.0
Simon Cooksey 0:fb7af294d5d9 9 *
Simon Cooksey 0:fb7af294d5d9 10 * Unless required by applicable law or agreed to in writing, software
Simon Cooksey 0:fb7af294d5d9 11 * distributed under the License is distributed on an "AS IS" BASIS,
Simon Cooksey 0:fb7af294d5d9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Simon Cooksey 0:fb7af294d5d9 13 * See the License for the specific language governing permissions and
Simon Cooksey 0:fb7af294d5d9 14 * limitations under the License.
Simon Cooksey 0:fb7af294d5d9 15 */
Simon Cooksey 0:fb7af294d5d9 16
Simon Cooksey 0:fb7af294d5d9 17 #include "ble/BLE.h"
Simon Cooksey 0:fb7af294d5d9 18 #include "ble/BLEInstanceBase.h"
Simon Cooksey 0:fb7af294d5d9 19
Simon Cooksey 0:fb7af294d5d9 20 #if defined(TARGET_OTA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 21 #include "ble/services/DFUService.h"
Simon Cooksey 0:fb7af294d5d9 22 #endif
Simon Cooksey 0:fb7af294d5d9 23
Simon Cooksey 0:fb7af294d5d9 24 #ifdef YOTTA_CFG_MBED_OS
Simon Cooksey 0:fb7af294d5d9 25 #include <minar/minar.h>
Simon Cooksey 0:fb7af294d5d9 26 #endif
Simon Cooksey 0:fb7af294d5d9 27
Simon Cooksey 0:fb7af294d5d9 28 #if !defined(YOTTA_CFG_MBED_OS)
Simon Cooksey 0:fb7af294d5d9 29 #include <mbed_error.h>
Simon Cooksey 0:fb7af294d5d9 30 #include <toolchain.h>
Simon Cooksey 0:fb7af294d5d9 31 #endif
Simon Cooksey 0:fb7af294d5d9 32
Simon Cooksey 0:fb7af294d5d9 33 ble_error_t
Simon Cooksey 0:fb7af294d5d9 34 BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
Simon Cooksey 0:fb7af294d5d9 35 {
Simon Cooksey 0:fb7af294d5d9 36 ble_error_t err = transport->init(instanceID, callback);
Simon Cooksey 0:fb7af294d5d9 37 if (err != BLE_ERROR_NONE) {
Simon Cooksey 0:fb7af294d5d9 38 return err;
Simon Cooksey 0:fb7af294d5d9 39 }
Simon Cooksey 0:fb7af294d5d9 40
Simon Cooksey 0:fb7af294d5d9 41 /* Platforms enabled for DFU should introduce the DFU Service into
Simon Cooksey 0:fb7af294d5d9 42 * applications automatically. */
Simon Cooksey 0:fb7af294d5d9 43 #if defined(TARGET_OTA_ENABLED)
Simon Cooksey 0:fb7af294d5d9 44 static DFUService dfu(*this); // defined static so that the object remains alive
Simon Cooksey 0:fb7af294d5d9 45 #endif // TARGET_OTA_ENABLED
Simon Cooksey 0:fb7af294d5d9 46
Simon Cooksey 0:fb7af294d5d9 47 return BLE_ERROR_NONE;
Simon Cooksey 0:fb7af294d5d9 48 }
Simon Cooksey 0:fb7af294d5d9 49
Simon Cooksey 0:fb7af294d5d9 50 /**
Simon Cooksey 0:fb7af294d5d9 51 * BLE::Instance() and BLE constructor rely upon a static array of initializers
Simon Cooksey 0:fb7af294d5d9 52 * to create actual BLE transport instances. A description of these instances
Simon Cooksey 0:fb7af294d5d9 53 * and initializers is supposed to be put in some .json file contributing to
Simon Cooksey 0:fb7af294d5d9 54 * yotta's configuration (typically in the target definition described by
Simon Cooksey 0:fb7af294d5d9 55 * target.json). Here's a sample:
Simon Cooksey 0:fb7af294d5d9 56 *
Simon Cooksey 0:fb7af294d5d9 57 * "config": {
Simon Cooksey 0:fb7af294d5d9 58 * ...
Simon Cooksey 0:fb7af294d5d9 59 * "ble_instances": {
Simon Cooksey 0:fb7af294d5d9 60 * "count": 1,
Simon Cooksey 0:fb7af294d5d9 61 * "0" : {
Simon Cooksey 0:fb7af294d5d9 62 * "initializer" : "createBLEInstance"
Simon Cooksey 0:fb7af294d5d9 63 * }
Simon Cooksey 0:fb7af294d5d9 64 * }
Simon Cooksey 0:fb7af294d5d9 65 * ...
Simon Cooksey 0:fb7af294d5d9 66 * }
Simon Cooksey 0:fb7af294d5d9 67 *
Simon Cooksey 0:fb7af294d5d9 68 * The following macros result in translating the above config into a static
Simon Cooksey 0:fb7af294d5d9 69 * array: instanceConstructors.
Simon Cooksey 0:fb7af294d5d9 70 */
Simon Cooksey 0:fb7af294d5d9 71 #ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
Simon Cooksey 0:fb7af294d5d9 72 #define CONCATENATE(A, B) A ## B
Simon Cooksey 0:fb7af294d5d9 73 #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). */
Simon Cooksey 0:fb7af294d5d9 74
Simon Cooksey 0:fb7af294d5d9 75 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
Simon Cooksey 0:fb7af294d5d9 76 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
Simon Cooksey 0:fb7af294d5d9 77 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
Simon Cooksey 0:fb7af294d5d9 78 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
Simon Cooksey 0:fb7af294d5d9 79 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
Simon Cooksey 0:fb7af294d5d9 80 /* ... add more of the above if ever needed */
Simon Cooksey 0:fb7af294d5d9 81
Simon Cooksey 0:fb7af294d5d9 82 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
Simon Cooksey 0:fb7af294d5d9 83 #elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
Simon Cooksey 0:fb7af294d5d9 84 /*
Simon Cooksey 0:fb7af294d5d9 85 * The following applies when building without yotta. By default BLE_API provides
Simon Cooksey 0:fb7af294d5d9 86 * a trivial initializer list containing a single constructor: createBLEInstance.
Simon Cooksey 0:fb7af294d5d9 87 * This may be overridden.
Simon Cooksey 0:fb7af294d5d9 88 */
Simon Cooksey 0:fb7af294d5d9 89 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance
Simon Cooksey 0:fb7af294d5d9 90
Simon Cooksey 0:fb7af294d5d9 91 // yotta unlike mbed-cli has proper dependency mechanisms
Simon Cooksey 0:fb7af294d5d9 92 // It is not required to defined a stub for createBLEInstance
Simon Cooksey 0:fb7af294d5d9 93 #if !defined(YOTTA_CFG_MBED_OS)
Simon Cooksey 0:fb7af294d5d9 94
Simon Cooksey 0:fb7af294d5d9 95 // this stub is required by ARMCC otherwise link will systematically fail
Simon Cooksey 0:fb7af294d5d9 96 MBED_WEAK BLEInstanceBase* createBLEInstance() {
Simon Cooksey 0:fb7af294d5d9 97 error("Please provide an implementation for mbed BLE");
Simon Cooksey 0:fb7af294d5d9 98 return NULL;
Simon Cooksey 0:fb7af294d5d9 99 }
Simon Cooksey 0:fb7af294d5d9 100
Simon Cooksey 0:fb7af294d5d9 101 #endif
Simon Cooksey 0:fb7af294d5d9 102
Simon Cooksey 0:fb7af294d5d9 103
Simon Cooksey 0:fb7af294d5d9 104 #endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */
Simon Cooksey 0:fb7af294d5d9 105
Simon Cooksey 0:fb7af294d5d9 106 typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
Simon Cooksey 0:fb7af294d5d9 107 static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
Simon Cooksey 0:fb7af294d5d9 108 #ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
Simon Cooksey 0:fb7af294d5d9 109 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
Simon Cooksey 0:fb7af294d5d9 110 #else
Simon Cooksey 0:fb7af294d5d9 111 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
Simon Cooksey 0:fb7af294d5d9 112 #endif
Simon Cooksey 0:fb7af294d5d9 113 };
Simon Cooksey 0:fb7af294d5d9 114
Simon Cooksey 0:fb7af294d5d9 115 BLE &
Simon Cooksey 0:fb7af294d5d9 116 BLE::Instance(InstanceID_t id)
Simon Cooksey 0:fb7af294d5d9 117 {
Simon Cooksey 0:fb7af294d5d9 118 static BLE *singletons[NUM_INSTANCES];
Simon Cooksey 0:fb7af294d5d9 119 if (id < NUM_INSTANCES) {
Simon Cooksey 0:fb7af294d5d9 120 if (singletons[id] == NULL) {
Simon Cooksey 0:fb7af294d5d9 121 singletons[id] = new BLE(id); /* This object will never be freed. */
Simon Cooksey 0:fb7af294d5d9 122 }
Simon Cooksey 0:fb7af294d5d9 123
Simon Cooksey 0:fb7af294d5d9 124 return *singletons[id];
Simon Cooksey 0:fb7af294d5d9 125 }
Simon Cooksey 0:fb7af294d5d9 126
Simon Cooksey 0:fb7af294d5d9 127 /* we come here only in the case of a bad interfaceID. */
Simon Cooksey 0:fb7af294d5d9 128 static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
Simon Cooksey 0:fb7af294d5d9 129 return badSingleton;
Simon Cooksey 0:fb7af294d5d9 130 }
Simon Cooksey 0:fb7af294d5d9 131
Simon Cooksey 0:fb7af294d5d9 132 #ifdef YOTTA_CFG_MBED_OS
Simon Cooksey 0:fb7af294d5d9 133 void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
Simon Cooksey 0:fb7af294d5d9 134 minar::Scheduler::postCallback(&params->ble, &BLE::processEvents);
Simon Cooksey 0:fb7af294d5d9 135 }
Simon Cooksey 0:fb7af294d5d9 136 #else
Simon Cooksey 0:fb7af294d5d9 137 #define defaultSchedulingCallback NULL
Simon Cooksey 0:fb7af294d5d9 138 #endif
Simon Cooksey 0:fb7af294d5d9 139
Simon Cooksey 0:fb7af294d5d9 140
Simon Cooksey 0:fb7af294d5d9 141 BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
Simon Cooksey 0:fb7af294d5d9 142 whenEventsToProcess(defaultSchedulingCallback)
Simon Cooksey 0:fb7af294d5d9 143 {
Simon Cooksey 0:fb7af294d5d9 144 static BLEInstanceBase *transportInstances[NUM_INSTANCES];
Simon Cooksey 0:fb7af294d5d9 145
Simon Cooksey 0:fb7af294d5d9 146 if (instanceID < NUM_INSTANCES) {
Simon Cooksey 0:fb7af294d5d9 147 if (!transportInstances[instanceID]) {
Simon Cooksey 0:fb7af294d5d9 148 transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
Simon Cooksey 0:fb7af294d5d9 149 }
Simon Cooksey 0:fb7af294d5d9 150 transport = transportInstances[instanceID];
Simon Cooksey 0:fb7af294d5d9 151 } else {
Simon Cooksey 0:fb7af294d5d9 152 transport = NULL;
Simon Cooksey 0:fb7af294d5d9 153 }
Simon Cooksey 0:fb7af294d5d9 154 }
Simon Cooksey 0:fb7af294d5d9 155
Simon Cooksey 0:fb7af294d5d9 156 bool BLE::hasInitialized(void) const
Simon Cooksey 0:fb7af294d5d9 157 {
Simon Cooksey 0:fb7af294d5d9 158 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 159 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 160 }
Simon Cooksey 0:fb7af294d5d9 161
Simon Cooksey 0:fb7af294d5d9 162 return transport->hasInitialized();
Simon Cooksey 0:fb7af294d5d9 163 }
Simon Cooksey 0:fb7af294d5d9 164
Simon Cooksey 0:fb7af294d5d9 165 ble_error_t BLE::shutdown(void)
Simon Cooksey 0:fb7af294d5d9 166 {
Simon Cooksey 0:fb7af294d5d9 167 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 168 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 169 }
Simon Cooksey 0:fb7af294d5d9 170
Simon Cooksey 0:fb7af294d5d9 171 return transport->shutdown();
Simon Cooksey 0:fb7af294d5d9 172 }
Simon Cooksey 0:fb7af294d5d9 173
Simon Cooksey 0:fb7af294d5d9 174 const char *BLE::getVersion(void)
Simon Cooksey 0:fb7af294d5d9 175 {
Simon Cooksey 0:fb7af294d5d9 176 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 177 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 178 }
Simon Cooksey 0:fb7af294d5d9 179
Simon Cooksey 0:fb7af294d5d9 180 return transport->getVersion();
Simon Cooksey 0:fb7af294d5d9 181 }
Simon Cooksey 0:fb7af294d5d9 182
Simon Cooksey 0:fb7af294d5d9 183 const Gap &BLE::gap() const
Simon Cooksey 0:fb7af294d5d9 184 {
Simon Cooksey 0:fb7af294d5d9 185 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 186 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 187 }
Simon Cooksey 0:fb7af294d5d9 188
Simon Cooksey 0:fb7af294d5d9 189 return transport->getGap();
Simon Cooksey 0:fb7af294d5d9 190 }
Simon Cooksey 0:fb7af294d5d9 191
Simon Cooksey 0:fb7af294d5d9 192 Gap &BLE::gap()
Simon Cooksey 0:fb7af294d5d9 193 {
Simon Cooksey 0:fb7af294d5d9 194 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 195 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 196 }
Simon Cooksey 0:fb7af294d5d9 197
Simon Cooksey 0:fb7af294d5d9 198 return transport->getGap();
Simon Cooksey 0:fb7af294d5d9 199 }
Simon Cooksey 0:fb7af294d5d9 200
Simon Cooksey 0:fb7af294d5d9 201 const GattServer& BLE::gattServer() const
Simon Cooksey 0:fb7af294d5d9 202 {
Simon Cooksey 0:fb7af294d5d9 203 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 204 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 205 }
Simon Cooksey 0:fb7af294d5d9 206
Simon Cooksey 0:fb7af294d5d9 207 return transport->getGattServer();
Simon Cooksey 0:fb7af294d5d9 208 }
Simon Cooksey 0:fb7af294d5d9 209
Simon Cooksey 0:fb7af294d5d9 210 GattServer& BLE::gattServer()
Simon Cooksey 0:fb7af294d5d9 211 {
Simon Cooksey 0:fb7af294d5d9 212 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 213 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 214 }
Simon Cooksey 0:fb7af294d5d9 215
Simon Cooksey 0:fb7af294d5d9 216 return transport->getGattServer();
Simon Cooksey 0:fb7af294d5d9 217 }
Simon Cooksey 0:fb7af294d5d9 218
Simon Cooksey 0:fb7af294d5d9 219 const GattClient& BLE::gattClient() const
Simon Cooksey 0:fb7af294d5d9 220 {
Simon Cooksey 0:fb7af294d5d9 221 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 222 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 223 }
Simon Cooksey 0:fb7af294d5d9 224
Simon Cooksey 0:fb7af294d5d9 225 return transport->getGattClient();
Simon Cooksey 0:fb7af294d5d9 226 }
Simon Cooksey 0:fb7af294d5d9 227
Simon Cooksey 0:fb7af294d5d9 228 GattClient& BLE::gattClient()
Simon Cooksey 0:fb7af294d5d9 229 {
Simon Cooksey 0:fb7af294d5d9 230 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 231 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 232 }
Simon Cooksey 0:fb7af294d5d9 233
Simon Cooksey 0:fb7af294d5d9 234 return transport->getGattClient();
Simon Cooksey 0:fb7af294d5d9 235 }
Simon Cooksey 0:fb7af294d5d9 236
Simon Cooksey 0:fb7af294d5d9 237 const SecurityManager& BLE::securityManager() const
Simon Cooksey 0:fb7af294d5d9 238 {
Simon Cooksey 0:fb7af294d5d9 239 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 240 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 241 }
Simon Cooksey 0:fb7af294d5d9 242
Simon Cooksey 0:fb7af294d5d9 243 return transport->getSecurityManager();
Simon Cooksey 0:fb7af294d5d9 244 }
Simon Cooksey 0:fb7af294d5d9 245
Simon Cooksey 0:fb7af294d5d9 246 SecurityManager& BLE::securityManager()
Simon Cooksey 0:fb7af294d5d9 247 {
Simon Cooksey 0:fb7af294d5d9 248 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 249 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 250 }
Simon Cooksey 0:fb7af294d5d9 251
Simon Cooksey 0:fb7af294d5d9 252 return transport->getSecurityManager();
Simon Cooksey 0:fb7af294d5d9 253 }
Simon Cooksey 0:fb7af294d5d9 254
Simon Cooksey 0:fb7af294d5d9 255 void BLE::waitForEvent(void)
Simon Cooksey 0:fb7af294d5d9 256 {
Simon Cooksey 0:fb7af294d5d9 257 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 258 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 259 }
Simon Cooksey 0:fb7af294d5d9 260
Simon Cooksey 0:fb7af294d5d9 261 transport->waitForEvent();
Simon Cooksey 0:fb7af294d5d9 262 }
Simon Cooksey 0:fb7af294d5d9 263
Simon Cooksey 0:fb7af294d5d9 264 void BLE::processEvents()
Simon Cooksey 0:fb7af294d5d9 265 {
Simon Cooksey 0:fb7af294d5d9 266 if (!transport) {
Simon Cooksey 0:fb7af294d5d9 267 error("bad handle to underlying transport");
Simon Cooksey 0:fb7af294d5d9 268 }
Simon Cooksey 0:fb7af294d5d9 269
Simon Cooksey 0:fb7af294d5d9 270 transport->processEvents();
Simon Cooksey 0:fb7af294d5d9 271 }
Simon Cooksey 0:fb7af294d5d9 272
Simon Cooksey 0:fb7af294d5d9 273 void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t& callback)
Simon Cooksey 0:fb7af294d5d9 274 {
Simon Cooksey 0:fb7af294d5d9 275 whenEventsToProcess = callback;
Simon Cooksey 0:fb7af294d5d9 276 }
Simon Cooksey 0:fb7af294d5d9 277
Simon Cooksey 0:fb7af294d5d9 278 void BLE::signalEventsToProcess()
Simon Cooksey 0:fb7af294d5d9 279 {
Simon Cooksey 0:fb7af294d5d9 280 if (whenEventsToProcess) {
Simon Cooksey 0:fb7af294d5d9 281 OnEventsToProcessCallbackContext params = {
Simon Cooksey 0:fb7af294d5d9 282 *this
Simon Cooksey 0:fb7af294d5d9 283 };
Simon Cooksey 0:fb7af294d5d9 284 whenEventsToProcess(&params);
Simon Cooksey 0:fb7af294d5d9 285 }
Simon Cooksey 0:fb7af294d5d9 286 }