Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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 <stdio.h>
00018 #include "ble/BLE.h"
00019 #include "ble/BLEInstanceBase.h "
00020 
00021 #if defined(TARGET_OTA_ENABLED)
00022 #include "ble/services/DFUService.h"
00023 #endif
00024 
00025 #ifdef YOTTA_CFG_MBED_OS
00026 #include <minar/minar.h>
00027 #endif
00028 
00029 #if !defined(YOTTA_CFG_MBED_OS)
00030 #include <mbed_error.h>
00031 #include <toolchain.h>
00032 #endif
00033 
00034 static const char* error_strings[] = {
00035     "BLE_ERROR_NONE: No error",
00036     "BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted",
00037     "BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW",
00038     "BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range",
00039     "BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid",
00040     "BLE_STACK_BUSY: The stack is busy",
00041     "BLE_ERROR_INVALID_STATE: Invalid state",
00042     "BLE_ERROR_NO_MEM: Out of Memory",
00043     "BLE_ERROR_OPERATION_NOT_PERMITTED: The operation requested is not permitted",
00044     "BLE_ERROR_INITIALIZATION_INCOMPLETE: The BLE subsystem has not completed its initialisation",
00045     "BLE_ERROR_ALREADY_INITIALIZED: The BLE system has already been initialised",
00046     "BLE_ERROR_UNSPECIFIED: Unknown error",
00047     "BLE_ERROR_INTERNAL_STACK_FAILURE: The platform-specific stack failed"
00048 };
00049 
00050 const char* BLE::errorToString(ble_error_t error)
00051 {
00052     if (error > BLE_ERROR_INTERNAL_STACK_FAILURE) {
00053         return "Illegal error code";
00054     }
00055     return error_strings[error];
00056 }
00057 
00058 ble_error_t
00059 BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
00060 {
00061     ble_error_t err = transport->init(instanceID, callback);
00062     if (err != BLE_ERROR_NONE) {
00063         return err;
00064     }
00065 
00066     /* Platforms enabled for DFU should introduce the DFU Service into
00067      * applications automatically. */
00068 #if defined(TARGET_OTA_ENABLED)
00069     static DFUService dfu(*this); // defined static so that the object remains alive
00070 #endif // TARGET_OTA_ENABLED
00071 
00072     return BLE_ERROR_NONE;
00073 }
00074 
00075 /**
00076  * BLE::Instance() and BLE constructor rely upon a static array of initializers
00077  * to create actual BLE transport instances. A description of these instances
00078  * and initializers is supposed to be put in some .json file contributing to
00079  * yotta's configuration (typically in the target definition described by
00080  * target.json). Here's a sample:
00081  *
00082  *  "config": {
00083  *    ...
00084  *    "ble_instances": {
00085  *      "count": 1,
00086  *      "0" : {
00087  *        "initializer" : "createBLEInstance"
00088  *      }
00089  *    }
00090  *    ...
00091  *  }
00092  *
00093  * The following macros result in translating the above config into a static
00094  * array: instanceConstructors.
00095  */
00096 #ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
00097 #define CONCATENATE(A, B) A ## B
00098 #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). */
00099 
00100 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
00101 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
00102 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
00103 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
00104 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
00105 /* ... add more of the above if ever needed */
00106 
00107 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
00108 #elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
00109 /*
00110  * The following applies when building without yotta. By default BLE_API provides
00111  * a trivial initializer list containing a single constructor: createBLEInstance.
00112  * This may be overridden.
00113  */
00114 #define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance
00115 
00116 // yotta unlike mbed-cli has proper dependency mechanisms
00117 // It is not required to defined a stub for createBLEInstance
00118 #if !defined(YOTTA_CFG_MBED_OS)
00119 
00120 // this stub is required by ARMCC otherwise link will systematically fail
00121 MBED_WEAK BLEInstanceBase* createBLEInstance() {
00122     error("Please provide an implementation for mbed BLE");
00123     return NULL;
00124 }
00125 
00126 #endif
00127 
00128 
00129 #endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */
00130 
00131 typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
00132 static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
00133 #ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
00134     INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
00135 #else
00136     INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
00137 #endif
00138 };
00139 
00140 BLE &
00141 BLE::Instance(InstanceID_t id)
00142 {
00143     static BLE *singletons[NUM_INSTANCES];
00144     if (id < NUM_INSTANCES) {
00145         if (singletons[id] == NULL) {
00146             singletons[id] = new BLE(id); /* This object will never be freed. */
00147         }
00148 
00149         return *singletons[id];
00150     }
00151 
00152     /* we come here only in the case of a bad interfaceID. */
00153     static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
00154     return badSingleton;
00155 }
00156 
00157 #ifdef YOTTA_CFG_MBED_OS
00158 void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
00159     minar::Scheduler::postCallback(&params->ble, &BLE::processEvents);
00160 }
00161 #else
00162 #define defaultSchedulingCallback NULL
00163 #endif
00164 
00165 
00166 BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
00167     whenEventsToProcess(defaultSchedulingCallback),
00168     event_signaled(false)
00169 {
00170     static BLEInstanceBase *transportInstances[NUM_INSTANCES];
00171 
00172     if (instanceID < NUM_INSTANCES) {
00173         if (!transportInstances[instanceID]) {
00174             transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
00175         }
00176         transport = transportInstances[instanceID];
00177     } else {
00178         transport = NULL;
00179     }
00180 }
00181 
00182 bool BLE::hasInitialized(void) const
00183 {
00184     if (!transport) {
00185         error("bad handle to underlying transport");
00186     }
00187 
00188     return transport->hasInitialized();
00189 }
00190 
00191 ble_error_t BLE::shutdown(void)
00192 {
00193     if (!transport) {
00194         error("bad handle to underlying transport");
00195     }
00196 
00197     event_signaled = false;
00198     return transport->shutdown();
00199 }
00200 
00201 const char *BLE::getVersion(void)
00202 {
00203     if (!transport) {
00204         error("bad handle to underlying transport");
00205     }
00206 
00207     return transport->getVersion();
00208 }
00209 
00210 const Gap &BLE::gap() const
00211 {
00212     if (!transport) {
00213         error("bad handle to underlying transport");
00214     }
00215 
00216     return transport->getGap();
00217 }
00218 
00219 Gap &BLE::gap()
00220 {
00221     if (!transport) {
00222         error("bad handle to underlying transport");
00223     }
00224 
00225     return transport->getGap();
00226 }
00227 
00228 const GattServer& BLE::gattServer() const
00229 {
00230     if (!transport) {
00231         error("bad handle to underlying transport");
00232     }
00233 
00234     return transport->getGattServer();
00235 }
00236 
00237 GattServer& BLE::gattServer()
00238 {
00239     if (!transport) {
00240         error("bad handle to underlying transport");
00241     }
00242 
00243     return transport->getGattServer();
00244 }
00245 
00246 const GattClient& BLE::gattClient() const
00247 {
00248     if (!transport) {
00249         error("bad handle to underlying transport");
00250     }
00251 
00252     return transport->getGattClient();
00253 }
00254 
00255 GattClient& BLE::gattClient()
00256 {
00257     if (!transport) {
00258         error("bad handle to underlying transport");
00259     }
00260 
00261     return transport->getGattClient();
00262 }
00263 
00264 const SecurityManager& BLE::securityManager() const
00265 {
00266     if (!transport) {
00267         error("bad handle to underlying transport");
00268     }
00269 
00270     return transport->getSecurityManager();
00271 }
00272 
00273 SecurityManager& BLE::securityManager()
00274 {
00275     if (!transport) {
00276         error("bad handle to underlying transport");
00277     }
00278 
00279     return transport->getSecurityManager();
00280 }
00281 
00282 void BLE::waitForEvent(void)
00283 {
00284     if (!transport) {
00285         error("bad handle to underlying transport");
00286     }
00287 
00288     transport->waitForEvent();
00289 }
00290 
00291 void BLE::processEvents()
00292 {
00293     if (event_signaled == false) {
00294         return;
00295     }
00296 
00297     if (!transport) {
00298         error("bad handle to underlying transport");
00299     }
00300 
00301     event_signaled = false;
00302 
00303     transport->processEvents();
00304 }
00305 
00306 void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t & callback)
00307 {
00308     whenEventsToProcess = callback;
00309 
00310     // If events were previously signaled but the handler was not in place then
00311     // signal immediately events availability
00312     if (event_signaled && whenEventsToProcess) {
00313         OnEventsToProcessCallbackContext params = {
00314             *this
00315         };
00316         whenEventsToProcess(&params);
00317     }
00318 }
00319 
00320 void BLE::signalEventsToProcess()
00321 {
00322     if (event_signaled == true) {
00323         return;
00324     }
00325 
00326     event_signaled = true;
00327 
00328     if (whenEventsToProcess) {
00329         OnEventsToProcessCallbackContext params = {
00330             *this
00331         };
00332         whenEventsToProcess(&params);
00333     }
00334 }