High level Bluetooth Low Energy API and radio abstraction layer

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate BLE_ANCS_SDAPI_IRC ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BLE.cpp Source File

BLE.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "ble/BLE.h"
00018 #include "ble/BLEInstanceBase.h"
00019 
00020 #if defined(TARGET_OTA_ENABLED)
00021 #include "ble/services/DFUService.h"
00022 #endif
00023 
00024 #ifdef YOTTA_CFG_MBED_OS
00025 #include <minar/minar.h>
00026 #endif
00027 
00028 #if !defined(YOTTA_CFG_MBED_OS)
00029 #include <mbed_error.h>
00030 #include <toolchain.h>
00031 #endif
00032 
00033 ble_error_t
00034 BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
00035 {
00036     ble_error_t err = transport->init(instanceID, callback);
00037     if (err != BLE_ERROR_NONE) {
00038         return err;
00039     }
00040 
00041     /* Platforms enabled for DFU should introduce the DFU Service into
00042      * applications automatically. */
00043 #if defined(TARGET_OTA_ENABLED)
00044     static DFUService dfu(*this); // defined static so that the object remains alive
00045 #endif // TARGET_OTA_ENABLED
00046 
00047     return BLE_ERROR_NONE;
00048 }
00049 
00050 /**
00051  * BLE::Instance() and BLE constructor rely upon a static array of initializers
00052  * to create actual BLE transport instances. A description of these instances
00053  * and initializers is supposed to be put in some .json file contributing to
00054  * yotta's configuration (typically in the target definition described by
00055  * target.json). Here's a sample:
00056  *
00057  *  "config": {
00058  *    ...
00059  *    "ble_instances": {
00060  *      "count": 1,
00061  *      "0" : {
00062  *        "initializer" : "createBLEInstance"
00063  *      }
00064  *    }
00065  *    ...
00066  *  }
00067  *
00068  * The following macros result in translating the above config into a static
00069  * array: instanceConstructors.
00070  */
00071 #ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
00072 #define CONCATENATE(A, B) A ## B
00073 #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). */
00074 
00075 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
00076 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
00077 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
00078 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
00079 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
00080 /* ... add more of the above if ever needed */
00081 
00082 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
00083 #elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
00084 /*
00085  * The following applies when building without yotta. By default BLE_API provides
00086  * a trivial initializer list containing a single constructor: createBLEInstance.
00087  * This may be overridden.
00088  */
00089 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance
00090 
00091 // yotta unlike mbed-cli has proper dependency mechanisms
00092 // It is not required to defined a stub for createBLEInstance
00093 #if !defined(YOTTA_CFG_MBED_OS)
00094 
00095 // this stub is required by ARMCC otherwise link will systematically fail
00096 MBED_WEAK BLEInstanceBase* createBLEInstance() {
00097     error("Please provide an implementation for mbed BLE");
00098     return NULL;
00099 }
00100 
00101 #endif
00102 
00103 
00104 #endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */
00105 
00106 typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
00107 static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
00108 #ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
00109     INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
00110 #else
00111     INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
00112 #endif
00113 };
00114 
00115 BLE &
00116 BLE::Instance(InstanceID_t id)
00117 {
00118     static BLE *singletons[NUM_INSTANCES];
00119     if (id < NUM_INSTANCES) {
00120         if (singletons[id] == NULL) {
00121             singletons[id] = new BLE(id); /* This object will never be freed. */
00122         }
00123 
00124         return *singletons[id];
00125     }
00126 
00127     /* we come here only in the case of a bad interfaceID. */
00128     static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
00129     return badSingleton;
00130 }
00131 
00132 #ifdef YOTTA_CFG_MBED_OS
00133 void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
00134     minar::Scheduler::postCallback(&params->ble, &BLE::processEvents);
00135 }
00136 #else
00137 #define defaultSchedulingCallback NULL
00138 #endif
00139 
00140 
00141 BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
00142     whenEventsToProcess(defaultSchedulingCallback)
00143 {
00144     static BLEInstanceBase *transportInstances[NUM_INSTANCES];
00145 
00146     if (instanceID < NUM_INSTANCES) {
00147         if (!transportInstances[instanceID]) {
00148             transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
00149         }
00150         transport = transportInstances[instanceID];
00151     } else {
00152         transport = NULL;
00153     }
00154 }
00155 
00156 bool BLE::hasInitialized (void) const
00157 {
00158     if (!transport) {
00159         error("bad handle to underlying transport");
00160     }
00161 
00162     return transport->hasInitialized();
00163 }
00164 
00165 ble_error_t BLE::shutdown(void)
00166 {
00167     if (!transport) {
00168         error("bad handle to underlying transport");
00169     }
00170 
00171     return transport->shutdown();
00172 }
00173 
00174 const char *BLE::getVersion(void)
00175 {
00176     if (!transport) {
00177         error("bad handle to underlying transport");
00178     }
00179 
00180     return transport->getVersion();
00181 }
00182 
00183 const Gap &BLE::gap() const
00184 {
00185     if (!transport) {
00186         error("bad handle to underlying transport");
00187     }
00188 
00189     return transport->getGap();
00190 }
00191 
00192 Gap &BLE::gap()
00193 {
00194     if (!transport) {
00195         error("bad handle to underlying transport");
00196     }
00197 
00198     return transport->getGap();
00199 }
00200 
00201 const GattServer& BLE::gattServer() const
00202 {
00203     if (!transport) {
00204         error("bad handle to underlying transport");
00205     }
00206 
00207     return transport->getGattServer();
00208 }
00209 
00210 GattServer& BLE::gattServer()
00211 {
00212     if (!transport) {
00213         error("bad handle to underlying transport");
00214     }
00215 
00216     return transport->getGattServer();
00217 }
00218 
00219 const GattClient& BLE::gattClient() const
00220 {
00221     if (!transport) {
00222         error("bad handle to underlying transport");
00223     }
00224 
00225     return transport->getGattClient();
00226 }
00227 
00228 GattClient& BLE::gattClient()
00229 {
00230     if (!transport) {
00231         error("bad handle to underlying transport");
00232     }
00233 
00234     return transport->getGattClient();
00235 }
00236 
00237 const SecurityManager& BLE::securityManager() const
00238 {
00239     if (!transport) {
00240         error("bad handle to underlying transport");
00241     }
00242 
00243     return transport->getSecurityManager();
00244 }
00245 
00246 SecurityManager& BLE::securityManager()
00247 {
00248     if (!transport) {
00249         error("bad handle to underlying transport");
00250     }
00251 
00252     return transport->getSecurityManager();
00253 }
00254 
00255 void BLE::waitForEvent(void)
00256 {
00257     if (!transport) {
00258         error("bad handle to underlying transport");
00259     }
00260 
00261     transport->waitForEvent();
00262 }
00263 
00264 void BLE::processEvents()
00265 {
00266     if (!transport) {
00267         error("bad handle to underlying transport");
00268     }
00269 
00270     transport->processEvents();
00271 }
00272 
00273 void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t & callback)
00274 {
00275     whenEventsToProcess = callback;
00276 }
00277 
00278 void BLE::signalEventsToProcess()
00279 {
00280     if (whenEventsToProcess) {
00281         OnEventsToProcessCallbackContext params = {
00282             *this
00283         };
00284         whenEventsToProcess(&params);
00285     }
00286 }