Merge pull request #89 from lancaster-university/ble-ccccd-persist
Basic Persistent Storage
This commit is contained in:
commit
41447b634d
9 changed files with 375 additions and 32 deletions
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "MicroBitBLEManager.h"
|
||||
#include "MicroBitRadio.h"
|
||||
#include "MicroBitStorage.h"
|
||||
|
||||
// MicroBit::flags values
|
||||
#define MICROBIT_FLAG_SCHEDULER_RUNNING 0x00000001
|
||||
|
|
|
@ -50,7 +50,7 @@ extern const int8_t MICROBIT_BLE_POWER_LEVEL[];
|
|||
*
|
||||
*/
|
||||
class MicroBitBLEManager
|
||||
{
|
||||
{
|
||||
public:
|
||||
|
||||
// The mbed abstraction of the BlueTooth Low Energy (BLE) hardware
|
||||
|
|
|
@ -97,6 +97,16 @@ struct CompassSample
|
|||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
bool operator==(const CompassSample& other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
||||
bool operator!=(const CompassSample& other) const
|
||||
{
|
||||
return !(x == other.x && y == other.y && z == other.z);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
74
inc/MicroBitStorage.h
Normal file
74
inc/MicroBitStorage.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#ifndef MICROBIT_STORAGE_H
|
||||
#define MICROBIT_STORAGE_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitBLEManager.h"
|
||||
#include "MicroBitCompass.h"
|
||||
|
||||
#define MICROBIT_STORAGE_CONFIG_MAGIC 0xCAFECAFE
|
||||
|
||||
struct BLESysAttribute
|
||||
{
|
||||
uint32_t magic;
|
||||
uint8_t sys_attr[8];
|
||||
};
|
||||
|
||||
struct MicroBitConfigurationBlock
|
||||
{
|
||||
uint32_t magic;
|
||||
BLESysAttribute sysAttrs[MICROBIT_BLE_MAXIMUM_BONDS];
|
||||
CompassSample compassCalibrationData;
|
||||
int thermometerCalibration;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class definition for the MicroBitStorage class.
|
||||
* This allows reading and writing of small blocks of data to FLASH memory.
|
||||
*/
|
||||
class MicroBitStorage
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Default constructor.
|
||||
*/
|
||||
MicroBitStorage();
|
||||
|
||||
/*
|
||||
* Writes the given number of bytes to the address specified.
|
||||
* @param buffer the data to write.
|
||||
* @param address the location in memory to write to.
|
||||
* @param length the number of bytes to write.
|
||||
* TODO: Write this one!
|
||||
*/
|
||||
int writeBytes(uint8_t *buffer, uint32_t address, int length);
|
||||
|
||||
/**
|
||||
* Method for erasing a page in flash.
|
||||
* @param page_address Address of the first word in the page to be erased.
|
||||
*/
|
||||
void flashPageErase(uint32_t * page_address);
|
||||
|
||||
/**
|
||||
* Method for writing a word of data in flash with a value.
|
||||
|
||||
* @param address Address of the word to change.
|
||||
* @param value Value to be written to flash.
|
||||
*/
|
||||
void flashWordWrite(uint32_t * address, uint32_t value);
|
||||
|
||||
/*
|
||||
* Reads the micro:bit's configuration data block from FLASH into a RAM buffer.
|
||||
* @return a structure containing the stored data.
|
||||
*/
|
||||
MicroBitConfigurationBlock *getConfigurationBlock();
|
||||
|
||||
/*
|
||||
* Writes the micro:bit's configuration data block from FLASH into a RAM buffer.
|
||||
* @return a structure containing the stored data.
|
||||
*/
|
||||
int setConfigurationBlock(MicroBitConfigurationBlock *block);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -32,6 +32,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"MicroBitLightSensor.cpp"
|
||||
"RefCounted.cpp"
|
||||
"MemberFunctionCallback.cpp"
|
||||
"MicroBitStorage.cpp"
|
||||
"ble-services/MicroBitBLEManager.cpp"
|
||||
"ble-services/MicroBitDFUService.cpp"
|
||||
"ble-services/MicroBitEventService.cpp"
|
||||
|
|
|
@ -488,6 +488,24 @@ void MicroBitCompass::calibrateEnd()
|
|||
*/
|
||||
void MicroBitCompass::setCalibration(CompassSample calibration)
|
||||
{
|
||||
|
||||
MicroBitStorage s = MicroBitStorage();
|
||||
MicroBitConfigurationBlock *b = s.getConfigurationBlock();
|
||||
|
||||
//check we are not storing our restored calibration data.
|
||||
if(b->compassCalibrationData != calibration)
|
||||
{
|
||||
b->magic = MICROBIT_STORAGE_CONFIG_MAGIC;
|
||||
|
||||
b->compassCalibrationData.x = calibration.x;
|
||||
b->compassCalibrationData.y = calibration.y;
|
||||
b->compassCalibrationData.z = calibration.z;
|
||||
|
||||
s.setConfigurationBlock(b);
|
||||
}
|
||||
|
||||
delete b;
|
||||
|
||||
average = calibration;
|
||||
status |= MICROBIT_COMPASS_STATUS_CALIBRATED;
|
||||
}
|
||||
|
|
189
source/MicroBitStorage.cpp
Normal file
189
source/MicroBitStorage.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* Class definition for the MicroBitStorage class.
|
||||
* This allows reading and writing of FLASH memory.
|
||||
*/
|
||||
|
||||
#include "MicroBit.h"
|
||||
|
||||
/*
|
||||
* Default constructor
|
||||
*/
|
||||
MicroBitStorage::MicroBitStorage()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the given number of bytes to the address specified.
|
||||
* TODO: Complete this function to provide an abstraction across SD and no SD builds.
|
||||
*
|
||||
* @param buffer the data to write.
|
||||
* @param address the location in memory to write to.
|
||||
* @param length the number of bytes to write.
|
||||
*/
|
||||
int MicroBitStorage::writeBytes(uint8_t *buffer, uint32_t address, int length)
|
||||
{
|
||||
(void) buffer;
|
||||
(void) address;
|
||||
(void) length;
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for erasing a page in flash.
|
||||
*
|
||||
* @param page_address Address of the first word in the page to be erased.
|
||||
*/
|
||||
void MicroBitStorage::flashPageErase(uint32_t * page_address)
|
||||
{
|
||||
// Turn on flash erase enable and wait until the NVMC is ready:
|
||||
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
|
||||
// Erase page:
|
||||
NRF_NVMC->ERASEPAGE = (uint32_t)page_address;
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
|
||||
// Turn off flash erase enable and wait until the NVMC is ready:
|
||||
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads the micro:bit's configuration data block from FLASH into a RAM buffer.
|
||||
* @return a pointer to the structure containing the stored data.
|
||||
* NOTE: it is the callers responsibility to free the buffer.
|
||||
*/
|
||||
|
||||
MicroBitConfigurationBlock *MicroBitStorage::getConfigurationBlock()
|
||||
{
|
||||
uint32_t pg_size = NRF_FICR->CODEPAGESIZE;
|
||||
uint32_t pg_num = NRF_FICR->CODESIZE - 19; // Use the page just below the BLE Bond Data
|
||||
|
||||
MicroBitConfigurationBlock *block = new MicroBitConfigurationBlock();
|
||||
memcpy(block, (uint32_t *)(pg_size * pg_num), sizeof(MicroBitConfigurationBlock));
|
||||
|
||||
if (block->magic != MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
memclr(block, sizeof(MicroBitConfigurationBlock));
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_DBG)
|
||||
|
||||
uBit.serial.printf("RETREIVE:\r\n");
|
||||
|
||||
if(block->magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
uBit.serial.printf("magic: %.2x\r\n", block->magic);
|
||||
|
||||
for(int attrIterator = 0; attrIterator < MICROBIT_BLE_MAXIMUM_BONDS; attrIterator++)
|
||||
{
|
||||
if(block->sysAttrs[attrIterator].magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
uBit.serial.printf("systemAttrs[%d]: ", attrIterator);
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
uBit.serial.printf("%.2x\r\n", block->sysAttrs[attrIterator].sys_attr[i]);
|
||||
}
|
||||
|
||||
uBit.serial.printf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
uBit.serial.printf("compass x: %d y: %d z: %d\r\n", block->compassCalibrationData.x, block->compassCalibrationData.y, block->compassCalibrationData.z);
|
||||
|
||||
uBit.serial.printf("temperature: %d\r\n", block->thermometerCalibration);
|
||||
}
|
||||
#endif
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for filling a page in flash with a value.
|
||||
*
|
||||
* @param address Address of the first word in the page to be filled.
|
||||
* @param value Value to be written to flash.
|
||||
*/
|
||||
void MicroBitStorage::flashWordWrite(uint32_t * address, uint32_t value)
|
||||
{
|
||||
// Turn on flash write enable and wait until the NVMC is ready:
|
||||
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
|
||||
*address = value;
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
|
||||
// Turn off flash write enable and wait until the NVMC is ready:
|
||||
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
|
||||
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Writes the micro:bit's configuration data block from FLASH into a RAM buffer.
|
||||
* @return a structure containing the stored data.
|
||||
*/
|
||||
int MicroBitStorage::setConfigurationBlock(MicroBitConfigurationBlock *block)
|
||||
{
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_DBG)
|
||||
|
||||
uBit.serial.printf("STORE:\r\n");
|
||||
|
||||
if(block->magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
uBit.serial.printf("magic: %.2x\r\n", block->magic);
|
||||
|
||||
for(int attrIterator = 0; attrIterator < MICROBIT_BLE_MAXIMUM_BONDS; attrIterator++)
|
||||
{
|
||||
if(block->sysAttrs[attrIterator].magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
uBit.serial.printf("systemAttrs[%d]: ", attrIterator);
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
uBit.serial.printf("%.2x\r\n", block->sysAttrs[attrIterator].sys_attr[i]);
|
||||
}
|
||||
|
||||
uBit.serial.printf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
uBit.serial.printf("compass x: %d y: %d z: %d\r\n", block->compassCalibrationData.x, block->compassCalibrationData.y, block->compassCalibrationData.z);
|
||||
|
||||
uBit.serial.printf("temperature: %d\r\n", block->thermometerCalibration);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t * addr;
|
||||
uint32_t pg_size;
|
||||
uint32_t pg_num;
|
||||
int wordsToWrite = sizeof(MicroBitConfigurationBlock) / 4 + 1;
|
||||
|
||||
pg_size = NRF_FICR->CODEPAGESIZE;
|
||||
pg_num = NRF_FICR->CODESIZE - 19; // Use the page just below the BLE Bond Data
|
||||
|
||||
addr = (uint32_t *)(pg_size * pg_num);
|
||||
|
||||
flashPageErase(addr);
|
||||
|
||||
uint32_t *b = (uint32_t *) block;
|
||||
|
||||
for (int i = 0; i < wordsToWrite; i++)
|
||||
{
|
||||
flashWordWrite(addr, *b);
|
||||
addr++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
|
@ -36,6 +36,19 @@ int main()
|
|||
// Provide time for all threaded initialisers to complete.
|
||||
uBit.sleep(100);
|
||||
|
||||
//check our persistent storage for compassCalibrationData
|
||||
MicroBitStorage s = MicroBitStorage();
|
||||
MicroBitConfigurationBlock *b = s.getConfigurationBlock();
|
||||
|
||||
//if we have some calibrated data, calibrate the compass!
|
||||
if(b->magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
if(b->compassCalibrationData != CompassSample(0,0,0))
|
||||
uBit.compass.setCalibration(b->compassCalibrationData);
|
||||
}
|
||||
|
||||
delete b;
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
|
||||
// Test if we need to enter BLE pairing mode...
|
||||
int i=0;
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#endif
|
||||
|
||||
#include "ble.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "device_manager.h"
|
||||
}
|
||||
|
||||
/*
|
||||
* Return to our predefined compiler settings.
|
||||
|
@ -36,6 +40,7 @@ const int8_t MICROBIT_BLE_POWER_LEVEL[] = {-30, -20, -16, -12, -8, -4, 0, 4};
|
|||
* whilst keeping the code modular.
|
||||
*/
|
||||
static MicroBitBLEManager *manager = NULL;
|
||||
static uint8_t deviceID = 255;
|
||||
|
||||
/**
|
||||
* Callback when a BLE GATT disconnect occurs.
|
||||
|
@ -44,12 +49,26 @@ static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *r
|
|||
{
|
||||
(void) reason; /* -Wunused-param */
|
||||
|
||||
// configure the stack to release CPU during critical timing events.
|
||||
// mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures
|
||||
// on secure BLE channels.
|
||||
ble_common_opt_radio_cpu_mutex_t opt;
|
||||
opt.enable = 0;
|
||||
sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);
|
||||
BLESysAttribute attrib;
|
||||
uint16_t len = sizeof(BLESysAttribute);
|
||||
|
||||
sd_ble_gatts_sys_attr_get(reason->handle, attrib.sys_attr, &len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
|
||||
|
||||
if (deviceID < MICROBIT_BLE_MAXIMUM_BONDS)
|
||||
{
|
||||
MicroBitStorage s = MicroBitStorage();
|
||||
MicroBitConfigurationBlock *b = s.getConfigurationBlock();
|
||||
|
||||
if(b->sysAttrs[deviceID].magic != MICROBIT_STORAGE_CONFIG_MAGIC || memcmp(b->sysAttrs[deviceID].sys_attr, attrib.sys_attr, sizeof(BLESysAttribute)) != 0)
|
||||
{
|
||||
b->magic = MICROBIT_STORAGE_CONFIG_MAGIC;
|
||||
b->sysAttrs[deviceID].magic = MICROBIT_STORAGE_CONFIG_MAGIC;
|
||||
memcpy(b->sysAttrs[deviceID].sys_attr, attrib.sys_attr, sizeof(BLESysAttribute));
|
||||
s.setConfigurationBlock(b);
|
||||
}
|
||||
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (manager)
|
||||
manager->advertise();
|
||||
|
@ -60,23 +79,29 @@ static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *r
|
|||
*/
|
||||
static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t *reason)
|
||||
{
|
||||
// configure the stack to hold on to CPU during critical timing events.
|
||||
// mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures
|
||||
// on secure BLE channels.
|
||||
ble_common_opt_radio_cpu_mutex_t opt;
|
||||
opt.enable = 1;
|
||||
sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);
|
||||
deviceID = 255;
|
||||
|
||||
// Ensure that there's no stale, cached information in the client... invalidate all characteristics.
|
||||
uint16_t len = 8;
|
||||
dm_handle_t dm_handle = {0,0,0,0};
|
||||
|
||||
// Configure the ServiceChanged characteristic to receive service changed indications
|
||||
// TODO: This is really a workaround as we can't maintain persistent state on the micro:bit across USB
|
||||
// reprogramming flashes.... yet.
|
||||
uint8_t data[] = {0x0B,0x00,0x02,0x00,0x02,0x00,0xB8,0x46};
|
||||
int ret = dm_handle_get(reason->handle, &dm_handle);
|
||||
|
||||
sd_ble_gatts_sys_attr_set(reason->handle, data, len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
|
||||
sd_ble_gatts_service_changed(reason->handle, 0x000c, 0xffff);
|
||||
if (ret == 0)
|
||||
deviceID = dm_handle.device_id;
|
||||
|
||||
if (deviceID < MICROBIT_BLE_MAXIMUM_BONDS)
|
||||
{
|
||||
// Ensure that there's no stale, cached information in the client... invalidate all characteristics.
|
||||
MicroBitStorage s = MicroBitStorage();
|
||||
MicroBitConfigurationBlock *b = s.getConfigurationBlock();
|
||||
|
||||
if(b->sysAttrs[deviceID].magic == MICROBIT_STORAGE_CONFIG_MAGIC)
|
||||
{
|
||||
sd_ble_gatts_sys_attr_set(reason->handle, b->sysAttrs[deviceID].sys_attr, sizeof(BLESysAttribute), BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
|
||||
sd_ble_gatts_service_changed(reason->handle, 0x000c, 0xffff);
|
||||
}
|
||||
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
|
||||
|
@ -93,6 +118,12 @@ static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager
|
|||
{
|
||||
(void) handle; /* -Wunused-param */
|
||||
|
||||
dm_handle_t dm_handle = {0,0,0,0};
|
||||
int ret = dm_handle_get(handle, &dm_handle);
|
||||
|
||||
if (ret == 0)
|
||||
deviceID = dm_handle.device_id;
|
||||
|
||||
if (manager)
|
||||
manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -144,11 +175,16 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
ble = new BLEDevice();
|
||||
ble->init();
|
||||
|
||||
|
||||
// automatically restart advertising after a device disconnects.
|
||||
ble->onDisconnection(bleDisconnectionCallback);
|
||||
ble->onConnection(bleConnectionCallback);
|
||||
|
||||
// Configure the stack to hold onto the CPU during critical timing events.
|
||||
// mbed-classic performs __disable_irq() calls in its timers that can cause
|
||||
// MIC failures on secure BLE channels...
|
||||
ble_common_opt_radio_cpu_mutex_t opt;
|
||||
opt.enable = 1;
|
||||
sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES)
|
||||
// Configure for private addresses, so kids' behaviour can't be easily tracked.
|
||||
|
@ -160,12 +196,13 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
|
||||
ble->securityManager().init(enableBonding, MICROBIT_BLE_REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY);
|
||||
|
||||
// If we're in pairing mode, review the size of the bond table.
|
||||
if (enableBonding)
|
||||
{
|
||||
// If we're in pairing mode, review the size of the bond table.
|
||||
int bonds = getBondCount();
|
||||
|
||||
// TODO: It would be much better to implement some sort of LRU/NFU policy here,
|
||||
// but this isn't currently supported in mbed, so we'd need to layer break...
|
||||
int bonds = getBondCount();
|
||||
|
||||
// If we're full, empty the bond table.
|
||||
if (bonds >= MICROBIT_BLE_MAXIMUM_BONDS)
|
||||
|
@ -173,7 +210,7 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
}
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
|
||||
// Configure a whitelist to filter all connection requetss from unbonded devices.
|
||||
// Configure a whitelist to filter all connection requetss from unbonded devices.
|
||||
// Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks.
|
||||
BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS];
|
||||
Gap::Whitelist_t whitelist;
|
||||
|
@ -182,13 +219,12 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
|
||||
ble->securityManager().getAddressesFromBondTable(whitelist);
|
||||
ble->gap().setWhitelist(whitelist);
|
||||
|
||||
ble->gap().setScanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST);
|
||||
ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Configure the radio at our default power level
|
||||
setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER);
|
||||
setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER);
|
||||
|
||||
// Bring up any configured auxiliary services.
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
|
||||
|
@ -255,14 +291,14 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
// If whiltelisting is disabled, then we always advertise.
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST)
|
||||
if (whitelist.size > 0)
|
||||
#endif
|
||||
#endif
|
||||
ble->startAdvertising();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the output power level of the transmitter to the given value.
|
||||
*
|
||||
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest.
|
||||
* @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest.
|
||||
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range.
|
||||
*
|
||||
*/
|
||||
|
@ -299,7 +335,7 @@ int MicroBitBLEManager::getBondCount()
|
|||
*/
|
||||
void MicroBitBLEManager::pairingRequested(ManagedString passKey)
|
||||
{
|
||||
// Update our mode to display the passkey.
|
||||
// Update our mode to display the passkey.
|
||||
this->passKey = passKey;
|
||||
this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST;
|
||||
}
|
||||
|
@ -416,7 +452,8 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
|||
{
|
||||
MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n");
|
||||
display.print(tick,0,0,0);
|
||||
uBit.sleep(5000);
|
||||
uBit.sleep(15000);
|
||||
timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30;
|
||||
|
||||
/*
|
||||
* Disabled, as the API to return the number of active bonds is not reliable at present...
|
||||
|
|
Loading…
Reference in a new issue