this is using the mbed os version 5-13-1
source/BleManager.cpp
- Committer:
- ocomeni
- Date:
- 2019-05-27
- Branch:
- PassingRegression
- Revision:
- 120:779b74689747
- Parent:
- 119:8d939a902333
- Child:
- 121:ac4f59839e4f
File content as of revision 120:779b74689747:
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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.
*/
#include <events/mbed_events.h>
#include <mbed.h>
#include "debug.h"
#include "common_config.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"
#include "SecurityManager.h"
#include "BleManager.h"
#if MBED_CONF_APP_FILESYSTEM_SUPPORT
#include "LittleFileSystem.h"
#include "HeapBlockDevice.h"
#endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
#define FILE_CODE "btle"
//static const uint8_t DEVICE_NAME[] = "SM_device";
//static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
extern UARTService *uart;
/** This example demonstrates all the basic setup required
* for pairing and setting up link security both as a central and peripheral
*
* The example is implemented as two classes, one for the peripheral and one
* for central inheriting from a common base. They are run in sequence and
* require a peer device to connect to. During the peripheral device demonstration
* a peer device is required to connect. In the central device demonstration
* this peer device will be scanned for and connected to - therefore it should
* be advertising with the same address as when it connected.
*
* During the test output is written on the serial connection to monitor its
* progress.
*/
//static const uint8_t DEVICE_NAME[] = "SM_device";
/* for demonstration purposes we will store the peer device address
* of the device that connects to us in the first demonstration
* so we can use its address to reconnect to it later */
//static BLEProtocol::AddressBytes_t peer_address;
/** Base class for both peripheral and central. The same class that provides
* the logic for the application also implements the SecurityManagerEventHandler
* which is the interface used by the Security Manager to communicate events
* back to the applications. You can provide overrides for a selection of events
* your application is interested in.
*/
SMDevice::SMDevice(BLE &ble, events::EventQueue &event_queue,
BLEProtocol::AddressBytes_t &peer_address,
MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ble_config_t *ble_config) :
_ble(ble),
_event_queue(event_queue),
_peer_address(peer_address),
_aT2BleDatamPool (aT2BleDatamPool),
_aT2BleDataQueue (aT2BleDataQueue),
_ble2ATDatamPool (ble2ATDatamPool),
_ble2ATDataQueue (ble2ATDataQueue),
ble_config(ble_config),
_handle(0),
_is_connecting(false),
_led1(LED1, 0)
{
isConnected = false;
}
SMDevice::~SMDevice()
{
if (_ble.hasInitialized()) {
_ble.shutdown();
}
}
/** Start BLE interface initialisation */
void SMDevice::run()
{
dbg_printf(LOG, "\r\n [BTLE MAN] Thread Id = %X\r\n", (uint32_t)ThisThread::get_id());
ble_error_t error;
/* to show we're running we'll blink every 10secs */
//_event_queue.call_every(10000, this, &SMDevice::blink);
/* to show we're advertising we'll print status every minute */
//_event_queue.call_every(60000, this, &SMDevice::reportGapState);
/* process queues every BLE_PROCESS_QUEUES_INTERVAL_MS */
_event_queue.call_every(BLE_PROCESS_QUEUES_INTERVAL_MS, this, &SMDevice::processQueues);
if (_ble.hasInitialized()) {
dbg_printf(LOG, "Ble instance already initialised.\r\n");
return;
}
/* this will inform us off all events so we can schedule their handling
* using our event queue */
_ble.onEventsToProcess(
makeFunctionPointer(this, &SMDevice::schedule_ble_events)
);
/* handle timeouts, for example when connection attempts fail */
_ble.gap().onTimeout(
makeFunctionPointer(this, &SMDevice::on_timeout)
);
error = _ble.init(this, &SMDevice::on_init_complete);
if (error) {
dbg_printf(LOG, "Error returned by BLE::init.\r\n");
return;
}
/* this will not return until shutdown */
//_event_queue.dispatch_forever();
}
void SMDevice::shutDown()
{
if (_ble.hasInitialized()) {
_ble.shutdown();
dbg_printf(LOG, "Shutting down BLE Instance...\r\n");
_event_queue.break_dispatch();
}
}
/* event handler functions */
/** Respond to a pairing request. This will be called by the stack
* when a pairing request arrives and expects the application to
* call acceptPairingRequest or cancelPairingRequest */
void SMDevice::pairingRequest(
ble::connection_handle_t connectionHandle
) {
dbg_printf(LOG, "Pairing requested - authorising\r\n");
_ble.securityManager().acceptPairingRequest(connectionHandle);
}
/** Inform the application of a successful pairing. Terminate the demonstration. */
void SMDevice::pairingResult(
ble::connection_handle_t connectionHandle,
SecurityManager::SecurityCompletionStatus_t result
) {
if (result == SecurityManager::SEC_STATUS_SUCCESS) {
dbg_printf(LOG, "Pairing successful\r\n");
} else {
dbg_printf(LOG, "Pairing failed\r\n");
}
}
/** Inform the application of change in encryption status. This will be
* communicated through the serial port */
void SMDevice::linkEncryptionResult(
ble::connection_handle_t connectionHandle,
ble::link_encryption_t result
) {
if (result == ble::link_encryption_t::ENCRYPTED) {
dbg_printf(LOG, "Link ENCRYPTED\r\n");
} else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
dbg_printf(LOG, "Link ENCRYPTED_WITH_MITM\r\n");
} else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
dbg_printf(LOG, "Link NOT_ENCRYPTED\r\n");
}
#ifdef DEMO_BLE_SECURITY
/* disconnect in 2 s */
_event_queue.call_in(
2000, &_ble.gap(),
&Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
);
#endif
}
/** Override to start chosen activity when initialisation completes */
//void SMDevice::start() = 0;
/** This is called when BLE interface is initialised and starts the demonstration */
void SMDevice::on_init_complete(BLE::InitializationCompleteCallbackContext *event)
{
ble_error_t error;
if (event->error) {
dbg_printf(LOG, "Error during the initialisation\r\n");
return;
}
/* This path will be used to store bonding information but will fallback
* to storing in memory if file access fails (for example due to lack of a filesystem) */
const char* db_path = "/fs/bt_sec_db";
/* If the security manager is required this needs to be called before any
* calls to the Security manager happen. */
error = _ble.securityManager().init(
true,
false,
SecurityManager::IO_CAPS_DISPLAY_ONLY, // SecurityManager::IO_CAPS_NONE
ble_config->pairingKey,
false,
db_path
);
if (error) {
dbg_printf(LOG, "Error during init %d\r\n", error);
return;
}
error = _ble.securityManager().preserveBondingStateOnReset(true);
if (error) {
dbg_printf(LOG, "Error during preserveBondingStateOnReset %d\r\n", error);
}
#if MBED_CONF_APP_FILESYSTEM_SUPPORT
/* Enable privacy so we can find the keys */
error = _ble.gap().enablePrivacy(true);
if (error) {
dbg_printf(LOG, "Error enabling privacy\r\n");
}
Gap::PeripheralPrivacyConfiguration_t configuration_p = {
/* use_non_resolvable_random_address */ false,
Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
};
_ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
Gap::CentralPrivacyConfiguration_t configuration_c = {
/* use_non_resolvable_random_address */ false,
Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
};
_ble.gap().setCentralPrivacyConfiguration(&configuration_c);
/* this demo switches between being master and slave */
_ble.securityManager().setHintFutureRoleReversal(true);
#endif
/* Tell the security manager to use methods in this class to inform us
* of any events. Class needs to implement SecurityManagerEventHandler. */
_ble.securityManager().setSecurityManagerEventHandler(this);
/* print device address */
Gap::AddressType_t addr_type;
Gap::Address_t addr;
_ble.gap().getAddress(&addr_type, addr);
dbg_printf(LOG, "Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
/* when scanning we want to connect to a peer device so we need to
* attach callbacks that are used by Gap to notify us of events */
_ble.gap().onConnection(this, &SMDevice::on_connect);
_ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
_ble.gattServer().onDataWritten(this, &SMDevice::onDataWrittenCallback);
//_ble.securityManager().onPasskeyDisplay(this, &SMDevice::passkeyDisplayCallback);
//_ble.securityManager().onSecuritySetupCompleted(this, &SMDevice::securitySetupCompletedCallback);
/* start test in 500 ms */
_event_queue.call_in(500, this, &SMDevice::start);
}
/** This is called by Gap to notify the application we connected */
//void SMDevice::on_connect(const Gap::ConnectionCallbackParams_t *connection_event);
/** This is called by Gap to notify the application we disconnected,
* in our case it ends the demonstration. */
void SMDevice::on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
{
dbg_printf(LOG, "Disconnected\r\n");
#ifndef DEMO_BLE_SECURITY
dbg_printf(LOG, "Restarting advertising...\r\n");
_ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
#else
_event_queue.break_dispatch();
#endif
isConnected = false;
}
/** End demonstration unexpectedly. Called if timeout is reached during advertising,
* scanning or connection initiation */
void SMDevice::on_timeout(const Gap::TimeoutSource_t source)
{
dbg_printf(LOG, "Unexpected timeout - aborting\r\n");
_event_queue.break_dispatch();
}
/** Schedule processing of events from the BLE in the event queue. */
void SMDevice::schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
{
_event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
};
/** Echo received data back */
void SMDevice::EchoBleUartReceived()
{
uart->writeString(buffer);
uart->writeString("\n"); //flushes uart output buffer and sends data
}
/** Send data aynchronously using BLE */
void SMDevice::sendBLEUartData(const uint8_t * buf, int len)
{
//gapState.connected
if(isConnected){
uart->write(buf, len);
//uart->writeString("\n"); //flushes uart output buffer and sends data
}
else
{
dbg_printf(LOG, "BLE not connected\r\n");
}
}
/**
* This callback allows the UARTService to receive updates.
*
* @param[in] params
* Information about the characterisitc being updated.
*/
void SMDevice::onDataWrittenCallback(const GattWriteCallbackParams *params) {
if ((uart != NULL) && (params->handle == uart->getTXCharacteristicHandle())) {
uint16_t bytesRead = params->len;
dbg_printf(LOG, "received %u bytes\n\r ", bytesRead);
if(bytesRead >= 255){
dbg_printf(LOG, "Overflow command %u n\r ", bytesRead);
bytesRead = 255;
}
unsigned index = 0;
for (; index < bytesRead; index++) {
buffer[index] = params->data[index];
}
buffer[index++] = 0;
at_data_resp = new ble_at_msg_t;
at_data_resp->dataLen = params->len;
memcpy(at_data_resp->buffer, params->data, params->len);
dbg_printf(LOG, "Data : %s ",buffer);
dbg_printf(LOG, "\r\n");
/* start echo in 50 ms */
_event_queue.call(this, &SMDevice::setNextCommand, BLE_CMD_SEND_RX_DATA_2AT);
_event_queue.call_in(50, this, &SMDevice::EchoBleUartReceived);
//_event_queue.call(EchoBleUartReceived);
}
}
/** Blink LED to show we're running */
void SMDevice::blink(void)
{
_led1 = !_led1;
}
void SMDevice::reportGapState()
{
//Gap::GapState_t gapState = _ble.gap().getState();
char connStr[20] = " Not Connected ";
char advStr[20] = " Not Advertising ";
//char devName[20] = "";
//if(gapState.advertising){
if(_ble.gap().isAdvertisingActive(ble::LEGACY_ADVERTISING_HANDLE)){
strncpy(advStr, " Advertising ", 20);
}
if(isConnected){
strncpy(connStr, " Connected ", 20);
}
dbg_printf(LOG, "\n Advertising Status = %s\n Connection Status = %s\n", advStr, connStr);
}
/** A peripheral device will advertise, accept the connection and request
* a change in link security. */
SMDevicePeripheral::SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address,
MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ble_config_t *ble_config)
: SMDevice(ble, event_queue, peer_address,
aT2BleDatamPool, aT2BleDataQueue,
ble2ATDatamPool, ble2ATDataQueue,
ble_config) { }
void SMDevicePeripheral::start()
{
/* Set up and start advertising */
ble_error_t error;
GapAdvertisingData advertising_data;
/* add advertising flags */
advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
| GapAdvertisingData::BREDR_NOT_SUPPORTED);
/* add device name */
advertising_data.addData(
GapAdvertisingData::COMPLETE_LOCAL_NAME,
(const uint8_t *)ble_config->deviceName,
strlen(ble_config->deviceName)
);
/* Setup primary service */
uart = new UARTService(_ble);
/* add device name */
error = advertising_data.addData(
GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS ,
(const uint8_t *)UARTServiceUUID_reversed,
sizeof(sizeof(UARTServiceUUID_reversed))
);
/* setup advertising */
//error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
//ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
//error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
/* set up the services that can be discovered */
//error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
//error = _ble.gap().setAdvertisingPayload(advertising_data);
if (error) {
dbg_printf(LOG, "Error during Gap::setAdvertisingPayload\r\n");
return;
}
/* advertise to everyone */
_ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
/* how many milliseconds between advertisements, lower interval
* increases the chances of being seen at the cost of more power */
//_ble.gap().setAdvertisingInterval(20);
//_ble.gap().setAdvertisingTimeout(0);
_ble.gap().setAdvertisingInterval(ble_config->advInterval); /* setting in ble_config */
_ble.gap().setAdvertisingTimeout(ble_config->advTimeout); /* setting in ble_config */
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
dbg_printf(LOG, "Error during Gap::startAdvertising.\r\n");
return;
}
dbg_printf(LOG, "Please connect to device\r\n");
/** This tells the stack to generate a pairingRequest event
* which will require this application to respond before pairing
* can proceed. Setting it to false will automatically accept
* pairing. */
_ble.securityManager().setPairingRequestAuthorisation(true);
}
/** This is called by Gap to notify the application we connected,
* in our case it immediately requests a change in link security */
void SMDevicePeripheral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
{
ble_error_t error;
/* remember the device that connects to us now so we can connect to it
* during the next demonstration */
memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
dbg_printf(LOG, "Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
_peer_address[5], _peer_address[4], _peer_address[3],
_peer_address[2], _peer_address[1], _peer_address[0]);
/* store the handle for future Security Manager requests */
_handle = connection_event->handle;
/* Request a change in link security. This will be done
* indirectly by asking the master of the connection to
* change it. Depending on circumstances different actions
* may be taken by the master which will trigger events
* which the applications should deal with. */
error = _ble.securityManager().setLinkSecurity(
_handle,
SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
);
if (error) {
dbg_printf(LOG, "Error during SM::setLinkSecurity %d\r\n", error);
return;
}
dbg_printf(LOG, "SM::setLinkSecurity setup\r\n");
isConnected = true;
_event_queue.call(this, &SMDevicePeripheral::setNextCommand, BLE_CMD_CONNECT);
}
void SMDevicePeripheral::stopAdvertising()
{
if (_ble.hasInitialized()) {
ble_error_t error;
error = _ble.gap().stopAdvertising(ble::LEGACY_ADVERTISING_HANDLE);;
if(error){
dbg_printf(LOG, " Error stopping advertising...\r\n");
return;
}
dbg_printf(LOG, "Stopping advertising...\r\n");
//_event_queue.break_dispatch();
}
}
void SMDevicePeripheral::startAdvertising()
{
if (_ble.hasInitialized()) {
ble_error_t error;
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if(error){
dbg_printf(LOG, " Error Restarting advertising...\r\n");
return;
}
dbg_printf(LOG, "Restarting advertising...\r\n");
//_event_queue.break_dispatch();
}
}
void SMDevicePeripheral::processQueues()
{
dequeueATdataResponse();
switch(bleCmd)
{
case BLE_CMD_NONE:
break;
case BLE_CMD_CONFIG:
_aT2BleDatamPool->free(data_msg);
bleCmd = BLE_CMD_NONE;
break;
case BLE_CMD_CONNECT:
at_data_resp = new ble_at_msg_t;
at_data_resp->dataLen = 10; // 10 bytes total
int idx = 0;
// connect type BLE = 0x01
at_data_resp->buffer[idx++] = 0x01;
// Serial Port Service BLE profile = 0x0E (14)
at_data_resp->buffer[idx++] = 0x0E;
// copy peer device address
memcpy(&at_data_resp->buffer[idx], _peer_address, sizeof(_peer_address));
idx+=sizeof(_peer_address);
// frame size 0x0166
at_data_resp->buffer[idx++] = 0x01;
at_data_resp->buffer[idx++] = 0x66;
bleCmd = BLE_CMD_NONE;
sendATresponseBytes(BLE_CONNECT_EVENT);
break;
case BLE_CMD_DISCONNECT:
sendATresponseBytes(BLE_CONNECT_EVENT);
bleCmd = BLE_CMD_NONE;
break;
case BLE_CMD_SEND_RX_DATA_2AT:
sendATresponseBytes(AT_BLE_RESPONSE);
bleCmd = BLE_CMD_NONE;
break;
case BLE_CMD_SEND_AT_DATA_2BLE:
sendBLEUartData(data_msg->buffer, data_msg->dataLen);
_aT2BleDatamPool->free(data_msg);
bleCmd = BLE_CMD_NONE;
break;
default:
_aT2BleDatamPool->free(data_msg);
bleCmd = BLE_CMD_NONE;
break;
}
}
bool SMDevicePeripheral::queueBleDataResponse(ble_at_msg_t at_resp)
{
ble_at_msg_t *atData = _ble2ATDatamPool->alloc();
if(atData == NULL) return false; // queue full;
atData->at_resp = at_resp.at_resp;
atData->dataLen = at_resp.dataLen;
memcpy(atData->buffer, at_resp.buffer, at_resp.dataLen);
_ble2ATDataQueue->put(atData);
dbg_printf(LOG, "[BLE-MAN] queued data size = %d : at_resp = %d\n", at_resp.dataLen, at_resp.at_resp);
return true;
}
bool SMDevicePeripheral::dequeueATdataResponse(){
if(bleCmd != BLE_CMD_NONE) return false; // busy
osEvent evt = _aT2BleDataQueue->get(0);
if(evt.status == osEventMessage){
data_msg = (at_ble_msg_t*)evt.value.p;
setNextCommand(data_msg->ble_cmd);
//_wiFi2ATDatamPool->free(data_msg);
}
return true;
}
void SMDevicePeripheral::sendATresponseBytes(at_cmd_resp_t at_cmd)
{
//at_data_resp = new ble_at_msg_t;
// package and send on BLE data queue
// set string length
//at_data_resp->dataLen = len;
// copy data
//memcpy(at_data_resp->buffer, buf, len);
// copy response type
at_data_resp->at_resp = at_cmd;
bool queueResult = true;
int wait_count = 0;
queueResult = queueBleDataResponse(*at_data_resp);
delete at_data_resp;
at_data_resp = NULL;
dbg_printf(LOG, "[BLE-MAN] sendATresponseBytes completed successfully\r\n");
}
bool SMDevicePeripheral::setNextCommand(ble_cmd_t cmd)
{
dbg_printf(LOG, "\n [BLE-MAN] About to set next BLE manager command to %d\n", cmd);
if(bleCmd == BLE_CMD_NONE){
bleCmd = cmd;
return true; // success
}
dbg_printf(LOG, "\n [BLE-MAN] Busy : current state = %d \n", bleCmd);
return false; // BleManager busy
}
/** A central device will scan, connect to a peer and request pairing. */
SMDeviceCentral::SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address,
MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool,
Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue,
MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool,
Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue,
ble_config_t *ble_config)
: SMDevice(ble, event_queue, peer_address,
aT2BleDatamPool, aT2BleDataQueue,
ble2ATDatamPool, ble2ATDataQueue,
ble_config) { };
void SMDeviceCentral::start()
{
/* start scanning and attach a callback that will handle advertisements
* and scan requests responses */
ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
dbg_printf(LOG, "Please advertise\r\n");
dbg_printf(LOG, "Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
_peer_address[5], _peer_address[4], _peer_address[3],
_peer_address[2], _peer_address[1], _peer_address[0]);
if (error) {
dbg_printf(LOG, "Error during Gap::startScan %d\r\n", error);
return;
}
}
/** Look at scan payload to find a peer device and connect to it */
void SMDeviceCentral::on_scan(const Gap::AdvertisementCallbackParams_t *params)
{
/* don't bother with analysing scan result if we're already connecting */
if (_is_connecting) {
return;
}
/* connect to the same device that connected to us */
if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
ble_error_t error = _ble.gap().connect(
params->peerAddr, params->peerAddrType,
NULL, NULL
);
if (error) {
dbg_printf(LOG, "Error during Gap::connect %d\r\n", error);
return;
}
dbg_printf(LOG, "Connecting... ");
/* we may have already scan events waiting
* to be processed so we need to remember
* that we are already connecting and ignore them */
_is_connecting = true;
return;
}
}
/** This is called by Gap to notify the application we connected,
* in our case it immediately request pairing */
void SMDeviceCentral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
{
ble_error_t error;
/* store the handle for future Security Manager requests */
_handle = connection_event->handle;
/* in this example the local device is the master so we request pairing */
error = _ble.securityManager().requestPairing(_handle);
dbg_printf(LOG, "Connected\r\n");
if (error) {
dbg_printf(LOG, "Error during SM::requestPairing %d\r\n", error);
return;
}
/* upon pairing success the application will disconnect */
}
#if MBED_CONF_APP_FILESYSTEM_SUPPORT
bool create_filesystem()
{
static LittleFileSystem fs("fs");
/* replace this with any physical block device your board supports (like an SD card) */
static HeapBlockDevice bd(4096, 256);
int err = bd.init();
if (err) {
return false;
}
err = bd.erase(0, bd.size());
if (err) {
return false;
}
err = fs.mount(&bd);
if (err) {
/* Reformat if we can't mount the filesystem */
dbg_printf(LOG, "No filesystem found, formatting...\r\n");
err = fs.reformat(&bd);
if (err) {
return false;
}
}
return true;
}
#endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
#ifdef BLE_SECURITY_MAIN
int main()
{
BLE& ble = BLE::Instance();
events::EventQueue queue;
#if MBED_CONF_APP_FILESYSTEM_SUPPORT
/* if filesystem creation fails or there is no filesystem the security manager
* will fallback to storing the security database in memory */
if (!create_filesystem()) {
dbg_printf(LOG, "Filesystem creation failed, will use memory storage\r\n");
}
#endif
while(1) {
{
dbg_printf(LOG, "\r\n PERIPHERAL \r\n\r\n");
SMDevicePeripheral peripheral(ble, queue, peer_address);
peripheral.run();
}
{
dbg_printf(LOG, "\r\n CENTRAL \r\n\r\n");
SMDeviceCentral central(ble, queue, peer_address);
central.run();
}
}
return 0;
}
#endif