mirror of https://github.com/ARMmbed/mbed-os.git
490 lines
16 KiB
C++
490 lines
16 KiB
C++
/* mbed Microcontroller Library
|
|
* Copyright (c) 2006-2020 ARM Limited
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef MBED_BLE_H__
|
|
#define MBED_BLE_H__
|
|
|
|
#include "platform/mbed_error.h"
|
|
#include "platform/mbed_assert.h"
|
|
#include "platform/mbed_toolchain.h"
|
|
|
|
#include "ble/Gap.h"
|
|
#include "ble/GattClient.h"
|
|
#include "ble/GattServer.h"
|
|
#include "ble/SecurityManager.h"
|
|
|
|
#include "ble/common/BLERoles.h"
|
|
#include "ble/common/BLETypes.h"
|
|
#include "ble/common/blecommon.h"
|
|
#include "ble/common/FunctionPointerWithContext.h"
|
|
|
|
/* Forward declaration for the implementation class */
|
|
|
|
namespace ble {
|
|
class BLEInstanceBase;
|
|
|
|
/**
|
|
* @addtogroup ble
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Abstract away BLE-capable radio transceivers or SOCs.
|
|
*
|
|
* Instances of this class have three responsibilities:
|
|
* - Initialize the inner BLE subsystem.
|
|
* - Signal user code that BLE events are available and an API to process them.
|
|
* - Manage access to the instances abstracting each BLE layer:
|
|
* + GAP: Handle advertising and scan, as well as connection and
|
|
* disconnection.
|
|
* + GATTServer: API to construct and manage a GATT server, which connected peers can
|
|
* access.
|
|
* + GATTClient: API to interact with a peer GATT server.
|
|
* + SecurityManager: API to manage security.
|
|
*
|
|
* The user should not create BLE instances directly but rather access to the
|
|
* singleton(s) holding the BLE interfaces present in the system by using the
|
|
* static function Instance().
|
|
*
|
|
* @code
|
|
* #include "ble/BLE.h"
|
|
*
|
|
* BLE& ble_interface = BLE::Instance();
|
|
* @endcode
|
|
*
|
|
* Next, the signal handling/process mechanism should be set up. By design,
|
|
* Mbed BLE does not impose to the user an event handling/processing mechanism;
|
|
* however, it exposes APIs, which allows an application to compose its own:
|
|
* - onEventsToProcess(), which registers a callback that
|
|
* the BLE subsystem will call when there is an event ready to be processed.
|
|
* - processEvents(), which processes all the events present in the BLE subsystem.
|
|
*
|
|
* It is common to bind BLE event mechanism with Mbed EventQueue:
|
|
*
|
|
* @code
|
|
* #include <events/mbed_events.h>
|
|
* #include "ble/BLE.h"
|
|
*
|
|
* // declare the event queue, which the whole application will share.
|
|
* static EventQueue event_queue(4 * EVENTS_EVENT_SIZE);
|
|
*
|
|
* // Function invoked when there is a BLE event available.
|
|
* // Event processing is put into the event queue.
|
|
* void schedule_ble_processing(BLE::OnEventsToProcessCallbackContext* context) {
|
|
* event_queue.call(callback(&(context->ble), &BLE::processEvents));
|
|
* }
|
|
*
|
|
* int main()
|
|
* {
|
|
* BLE &ble_interface = BLE::Instance();
|
|
*
|
|
* // Bind event signaling to schedule_ble_processing
|
|
* ble_interface.onEventsToProcess(schedule_ble_processing);
|
|
*
|
|
* // Launch BLE initialisation
|
|
*
|
|
* // Dispatch events in the event queue
|
|
* event_queue.dispatch_forever();
|
|
* return 0;
|
|
* }
|
|
* @endcode
|
|
*
|
|
* Once the event processing mechanism is in place, the Bluetooth subsystem can
|
|
* be initialized with the init() function. That function accepts in input a
|
|
* callback, which will be invoked once the initialization process has finished.
|
|
*
|
|
* @code
|
|
* void on_ble_init_complete(BLE::InitializationCompleteCallbackContext *context)
|
|
* {
|
|
* BLE& ble_interface = context->ble;
|
|
* ble_error_t initialization_error = context->error;
|
|
*
|
|
* if (initialization_error) {
|
|
* // handle error
|
|
* return;
|
|
* }
|
|
*
|
|
* // The BLE interface can be accessed now.
|
|
* }
|
|
*
|
|
* int main() {
|
|
* BLE &ble_interface = BLE::Instance();
|
|
* ble_interface.onEventsToProcess(schedule_ble_processing);
|
|
*
|
|
* // Initialize the BLE interface
|
|
* ble_interface.init(on_ble_init_complete);
|
|
*
|
|
* event_queue.dispatch_forever();
|
|
* return 0;
|
|
* }
|
|
* @endcode
|
|
*/
|
|
class BLE {
|
|
public:
|
|
/**
|
|
* Opaque type used to store the ID of a BLE instance.
|
|
* @deprecated BLE singleton supports one instance. You may create multiple instances by using the constructor.
|
|
*/
|
|
typedef unsigned InstanceID_t;
|
|
|
|
/**
|
|
* The value of the BLE::InstanceID_t for the default BLE instance.
|
|
* @deprecated BLE singleton supports one instance. You may create multiple instances by using the constructor.
|
|
*/
|
|
static const InstanceID_t DEFAULT_INSTANCE = 0;
|
|
|
|
/**
|
|
* The number of permitted BLE instances for the application.
|
|
* @deprecated BLE singleton supports one instance. You may create multiple instances by using the constructor.
|
|
*/
|
|
static const InstanceID_t NUM_INSTANCES = 1;
|
|
|
|
// Prevent copy construction and copy assignment of BLE.
|
|
BLE(const BLE &) = delete;
|
|
BLE &operator=(const BLE &) = delete;
|
|
|
|
/**
|
|
* Get a reference to the BLE singleton.
|
|
*
|
|
* @note Calling Instance() is preferred over constructing a BLE object
|
|
* directly because it returns a reference to singleton.
|
|
*
|
|
* @return A reference to a single object.
|
|
*/
|
|
static BLE &Instance();
|
|
|
|
/**
|
|
* Get a reference to the BLE singleton corresponding to a given interface.
|
|
*
|
|
* There is a static array of BLE singletons.
|
|
*
|
|
* @note Calling Instance() is preferred over constructing a BLE object
|
|
* directly because it returns references to singletons.
|
|
*
|
|
* @param[in] id BLE Instance ID to get.
|
|
*
|
|
* @return A reference to a single object.
|
|
*
|
|
* @pre id shall be less than NUM_INSTANCES.
|
|
*
|
|
*/
|
|
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "BLE singleton supports one instance. You may create multiple"
|
|
"instances by using the constructor. Please use BLE::Instance().")
|
|
static BLE &Instance(InstanceID_t id)
|
|
{
|
|
return Instance();
|
|
}
|
|
|
|
/**
|
|
* Fetch the ID of a BLE instance.
|
|
*
|
|
* @return Instance id of this BLE instance.
|
|
*/
|
|
MBED_DEPRECATED_SINCE("mbed-os-6.3.0", "BLE singleton supports one instance. You may create multiple"
|
|
"instances by using the constructor.")
|
|
InstanceID_t getInstanceID() const
|
|
{
|
|
return DEFAULT_INSTANCE;
|
|
}
|
|
|
|
/**
|
|
* Events to process event.
|
|
*
|
|
* Instances of OnEventsToProcessCallbackContext are passed to the event
|
|
* handler registered with onEventsToProcess().
|
|
*/
|
|
struct OnEventsToProcessCallbackContext {
|
|
/**
|
|
* The ble instance which have events to process.
|
|
*/
|
|
BLE &ble;
|
|
};
|
|
|
|
/**
|
|
* Events to process event handler
|
|
*/
|
|
typedef FunctionPointerWithContext<OnEventsToProcessCallbackContext *>
|
|
OnEventsToProcessCallback_t;
|
|
|
|
/**
|
|
* Register a callback called when the BLE stack has pending work.
|
|
*
|
|
* By registering a callback, application code can know when event processing
|
|
* has to be scheduled.
|
|
*
|
|
* @param on_event_cb Callback invoked when there are new events to process.
|
|
*/
|
|
void onEventsToProcess(const OnEventsToProcessCallback_t &on_event_cb);
|
|
|
|
/**
|
|
* Process ALL pending events living in the BLE stack and return once all
|
|
* events have been consumed.
|
|
*
|
|
* @see onEventsToProcess()
|
|
*/
|
|
void processEvents();
|
|
|
|
/**
|
|
* Initialization complete event.
|
|
*
|
|
* This event is generated at the end of the init() procedure and is passed
|
|
* to the completion callback passed to init().
|
|
*/
|
|
struct InitializationCompleteCallbackContext {
|
|
/**
|
|
* Reference to the BLE object that has been initialized
|
|
*/
|
|
BLE &ble;
|
|
|
|
/**
|
|
* Error status of the initialization.
|
|
*
|
|
* That value is set to BLE_ERROR_NONE if initialization completed
|
|
* successfully or the appropriate error code otherwise.
|
|
* */
|
|
ble_error_t error;
|
|
};
|
|
|
|
/**
|
|
* Initialization complete event handler.
|
|
*
|
|
* @note There are two versions of init(). In addition to the
|
|
* function-pointer, init() can also take an <Object, member> tuple as its
|
|
* callback target. In case of the latter, the following declaration doesn't
|
|
* apply.
|
|
*/
|
|
typedef void (*InitializationCompleteCallback_t)(
|
|
InitializationCompleteCallbackContext *context
|
|
);
|
|
|
|
/**
|
|
* Initialize the BLE controller/stack.
|
|
*
|
|
* init() hands control to the underlying BLE module to accomplish
|
|
* initialization. This initialization may tacitly depend on other hardware
|
|
* setup (such as clocks or power-modes) that happens early on during system
|
|
* startup. It may not be safe to call init() from a global static context
|
|
* where ordering is compiler-specific and can't be guaranteed - it is safe
|
|
* to call BLE::init() from within main().
|
|
*
|
|
* @param[in] completion_cb A callback for when initialization completes for
|
|
* a BLE instance. This is an optional parameter; if no callback is set up,
|
|
* the application can still determine the status of initialization using
|
|
* BLE::hasInitialized() (see below).
|
|
*
|
|
* @return BLE_ERROR_NONE if the initialization procedure started
|
|
* successfully.
|
|
*
|
|
* @note If init() returns BLE_ERROR_NONE, the underlying stack must invoke
|
|
* the initialization completion callback at some point.
|
|
*
|
|
* @note Nearly all BLE APIs would return BLE_ERROR_INITIALIZATION_INCOMPLETE
|
|
* if used on an instance before the corresponding transport is initialized.
|
|
*
|
|
* @note There are two versions of init(). In addition to the
|
|
* function-pointer, init() can also take an <Object, member> pair as its
|
|
* callback target.
|
|
*
|
|
* @attention This should be called before using anything else in the BLE
|
|
* API.
|
|
*/
|
|
ble_error_t init(InitializationCompleteCallback_t completion_cb = nullptr)
|
|
{
|
|
FunctionPointerWithContext<InitializationCompleteCallbackContext *> callback(completion_cb);
|
|
return initImplementation(callback);
|
|
}
|
|
|
|
/**
|
|
* Initialize the BLE controller/stack.
|
|
*
|
|
* This is an alternate declaration for init(). This one takes an
|
|
* <Object, member> pair as its callback target.
|
|
*
|
|
* @param[in] object Object, which will be used to invoke the completion callback.
|
|
* @param[in] completion_cb Member function pointer, which will be invoked when
|
|
* initialization is complete.
|
|
*/
|
|
template<typename T>
|
|
ble_error_t init(T *object, void (T::*completion_cb)(InitializationCompleteCallbackContext *context))
|
|
{
|
|
FunctionPointerWithContext<InitializationCompleteCallbackContext *> callback(object, completion_cb);
|
|
return initImplementation(callback);
|
|
}
|
|
|
|
/**
|
|
* Indicate if the BLE instance has been initialized.
|
|
*
|
|
* @return true if initialization has completed for the underlying BLE
|
|
* transport.
|
|
*
|
|
* @note The application should set up a callback to signal completion of
|
|
* initialization when using init().
|
|
*/
|
|
bool hasInitialized() const;
|
|
|
|
/**
|
|
* Shut down the underlying stack, and reset state of this BLE instance.
|
|
*
|
|
* @return BLE_ERROR_NONE if the instance was shut down without error or the
|
|
* appropriate error code.
|
|
*
|
|
* @attention init() must be called afterward to reinstate services and
|
|
* GAP state. This API offers a way to repopulate the GATT database with new
|
|
* services and characteristics.
|
|
*/
|
|
ble_error_t shutdown();
|
|
|
|
/**
|
|
* This call allows the application to get the BLE stack version information.
|
|
*
|
|
* @return A pointer to a const string representing the version.
|
|
*
|
|
* @note The BLE API owns the string returned.
|
|
*/
|
|
const char *getVersion();
|
|
|
|
/**
|
|
* Accessor to Gap. All Gap-related functionality requires going through
|
|
* this accessor.
|
|
*
|
|
* @return A reference to a Gap object associated to this BLE instance.
|
|
*/
|
|
ble::Gap &gap();
|
|
|
|
/**
|
|
* A const alternative to gap().
|
|
*
|
|
* @return A const reference to a Gap object associated to this BLE instance.
|
|
*/
|
|
const ble::Gap &gap() const;
|
|
|
|
#if BLE_FEATURE_GATT_SERVER
|
|
/**
|
|
* Accessor to GattServer. All GattServer related functionality requires
|
|
* going through this accessor.
|
|
*
|
|
* @return A reference to a GattServer object associated to this BLE instance.
|
|
*/
|
|
ble::GattServer &gattServer();
|
|
|
|
/**
|
|
* A const alternative to gattServer().
|
|
*
|
|
* @return A const reference to a GattServer object associated to this BLE
|
|
* instance.
|
|
*/
|
|
const ble::GattServer &gattServer() const;
|
|
#endif // BLE_FEATURE_GATT_SERVER
|
|
|
|
#if BLE_FEATURE_GATT_CLIENT
|
|
/**
|
|
* Accessors to GattClient. All GattClient related functionality requires
|
|
* going through this accessor.
|
|
*
|
|
* @return A reference to a GattClient object associated to this BLE instance.
|
|
*/
|
|
ble::GattClient &gattClient();
|
|
|
|
/**
|
|
* A const alternative to gattClient().
|
|
*
|
|
* @return A const reference to a GattClient object associated to this BLE
|
|
* instance.
|
|
*/
|
|
const ble::GattClient &gattClient() const;
|
|
#endif // BLE_FEATURE_GATT_CLIENT
|
|
|
|
#if BLE_FEATURE_SECURITY
|
|
/**
|
|
* Accessors to SecurityManager. All SecurityManager-related functionality
|
|
* requires going through this accessor.
|
|
*
|
|
* @return A reference to a SecurityManager object associated to this BLE
|
|
* instance.
|
|
*/
|
|
ble::SecurityManager &securityManager();
|
|
|
|
/**
|
|
* A const alternative to securityManager().
|
|
*
|
|
* @return A const reference to a SecurityManager object associated to this
|
|
* BLE instance.
|
|
*/
|
|
const ble::SecurityManager &securityManager() const;
|
|
#endif // BLE_FEATURE_SECURITY
|
|
|
|
/**
|
|
* Translate error code into a printable string.
|
|
*
|
|
* @param[in] error Error code returned by BLE functions.
|
|
*
|
|
* @return A pointer to a const string describing the error.
|
|
*/
|
|
static const char *errorToString(ble_error_t error);
|
|
|
|
/**
|
|
* This function allows the BLE stack to signal that there is work to do and
|
|
* event processing should be done (BLE::processEvent()).
|
|
*
|
|
* @note This function should be called by the port of BLE_API. It is not
|
|
* meant to be used by end users.
|
|
*/
|
|
void signalEventsToProcess();
|
|
|
|
private:
|
|
friend class ble::BLEInstanceBase;
|
|
|
|
/**
|
|
* Constructor for a handle to a BLE instance (the BLE stack). BLE handles
|
|
* are thin wrappers around a transport object (that is, ptr. to
|
|
* ble::BLEInstanceBase).
|
|
*
|
|
* @param[in] transport Ble transport used for the BLE instance.
|
|
* @note Cordio supports only one instance.
|
|
*/
|
|
BLE(ble::BLEInstanceBase &transport);
|
|
|
|
/**
|
|
* Implementation of init() [internal to BLE_API].
|
|
*
|
|
* The implementation is separated into a private method because it isn't
|
|
* suitable to be included in the header.
|
|
*/
|
|
ble_error_t initImplementation(
|
|
FunctionPointerWithContext<InitializationCompleteCallbackContext *> callback
|
|
);
|
|
|
|
private:
|
|
ble::BLEInstanceBase &transport; /* The device-specific backend */
|
|
OnEventsToProcessCallback_t whenEventsToProcess;
|
|
bool event_signaled;
|
|
};
|
|
|
|
}
|
|
|
|
using ble::BLE;
|
|
/**
|
|
* @namespace ble Entry namespace for all BLE API definitions.
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif /* ifndef MBED_BLE_H__ */
|