Upgrade NRF52 BLE API to version 5

* Add NRF_SD_BLE_API_VERSION=5 macro to MCU_NRF52832 target
* Added initial Softdevice v5 API support for nRF5XPalGattClient.cpp
* Added initial Softdevice v5 API support for nRF5xGap.h
* Added initial Softdevice v5 API support for nRF5xGattServer.cpp
* Make sure the ah() hash function used by the security manager is declared with C linkage
* Removed 'ARM porting pending' checks in Nordic SDK
* Added BLE configuration to mbed_lib.json for NRF52x targets
* Migrated APIs and events model for Nordic SDK14.2 & SD API v5 in btle.cpp; adopted polling dispatch model
* Migrated APIs and events model for Nordic SDK14.2 & SD API v5 in nRF5xn.cpp
* Migrated APIs and events model for Nordic SDK14.2 & SD API v5 in nRF5xGap.cpp
* Added const qualifier to hwCallbacks's p_ble_evt parameter in nRF5xGattServer
* Add workaround to enable Radio Notification module from Nordic SDK
  * Disabled SWI1 interrupt manually from SWI driver module
    * Added missing include directive for "nrf_nvic.h" in ble_radio_notification.c
* Set correct number of custom UUIDs
* Adjust Softdevice RAM requirements for NRF52832/S132
  * RAM settings for the application were adjusted as follow:
    * Start: 0x20003800
    * Size: 0xC800
* Adjust Softdevice RAM requirements for NRF52840/S140
  * RAM settings for the application were adjusted as follow:
    * Start: 0x20003700 (was 0x20003000)
    * Size: 0xC900
* Added 3dBm as a permitted TX Power value for NRF52832
* Fix address type recovery in GAP
* Return min non-connectable adv interval compatible with infrastrcture's expectations
* Moved BLE driver from TARGET_SDK_14_2/FEATURE_BLE to TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble
pull/6547/head
Donatien Garnier 2018-02-22 12:38:36 -08:00 committed by Marcus Chang
parent fa79e685fc
commit 64baf717e8
93 changed files with 8869 additions and 29 deletions

View File

@ -0,0 +1,344 @@
# Change Log
## [v2.5.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.3) (2016-02-16)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.2...v2.5.3)
**Merged pull requests:**
- Fix for compilation errors with S110 softdevice in btle.cpp [\#109](https://github.com/ARMmbed/ble-nrf51822/pull/109) ([ddavidebor](https://github.com/ddavidebor))
## [v2.5.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.2) (2016-02-16)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.1...v2.5.2)
**Merged pull requests:**
- Sync develop against master [\#113](https://github.com/ARMmbed/ble-nrf51822/pull/113) ([pan-](https://github.com/pan-))
- Fix incorrect handles of characteristics descriptors. [\#112](https://github.com/ARMmbed/ble-nrf51822/pull/112) ([pan-](https://github.com/pan-))
## [v2.5.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.1) (2016-01-27)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.0...v2.5.1)
**Merged pull requests:**
- Remove Gap::state updates from this module [\#108](https://github.com/ARMmbed/ble-nrf51822/pull/108) ([andresag01](https://github.com/andresag01))
- merge version [\#106](https://github.com/ARMmbed/ble-nrf51822/pull/106) ([pan-](https://github.com/pan-))
## [v2.5.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.0) (2016-01-12)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.4.1...v2.5.0)
**Merged pull requests:**
- Fix access to enum member [\#105](https://github.com/ARMmbed/ble-nrf51822/pull/105) ([pan-](https://github.com/pan-))
- Hotfix dependency [\#104](https://github.com/ARMmbed/ble-nrf51822/pull/104) ([pan-](https://github.com/pan-))
- Finish implementation of getAddressesFromBondTable [\#103](https://github.com/ARMmbed/ble-nrf51822/pull/103) ([andresag01](https://github.com/andresag01))
## [v2.4.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.4.1) (2016-01-11)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.4.0...v2.4.1)
**Merged pull requests:**
- merge branch develop \(v2.4.0\) [\#100](https://github.com/ARMmbed/ble-nrf51822/pull/100) ([pan-](https://github.com/pan-))
## [v2.4.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.4.0) (2016-01-10)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.3.1...v2.4.0)
**Merged pull requests:**
- Add implementation of experimental whitelisting API [\#99](https://github.com/ARMmbed/ble-nrf51822/pull/99) ([andresag01](https://github.com/andresag01))
## [v2.3.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.3.1) (2016-01-07)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.3.0...v2.3.1)
**Merged pull requests:**
- Update yotta module dependencies [\#98](https://github.com/ARMmbed/ble-nrf51822/pull/98) ([pan-](https://github.com/pan-))
## [v2.3.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.3.0) (2015-12-23)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.10...v2.3.0)
**Merged pull requests:**
- Implementation of Characteristic descriptor discovery [\#74](https://github.com/ARMmbed/ble-nrf51822/pull/74) ([pan-](https://github.com/pan-))
## [v2.2.10](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.10) (2015-12-23)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.9...v2.2.10)
**Fixed bugs:**
- nRF5xn::init don't verify if errors have occurred during btle\_init [\#59](https://github.com/ARMmbed/ble-nrf51822/issues/59)
**Closed issues:**
- A call to shutdown does not clear the state of some components of BLE API [\#85](https://github.com/ARMmbed/ble-nrf51822/issues/85)
- Memory allocation issue on the NRF51DK board. [\#76](https://github.com/ARMmbed/ble-nrf51822/issues/76)
- Terrible handling of initLen / minLen and variable length characteristics. [\#56](https://github.com/ARMmbed/ble-nrf51822/issues/56)
**Merged pull requests:**
- Fix shutdown of Gap instance to avoid NULL refs [\#96](https://github.com/ARMmbed/ble-nrf51822/pull/96) ([andresag01](https://github.com/andresag01))
- Add check for return code of ble\_init [\#95](https://github.com/ARMmbed/ble-nrf51822/pull/95) ([andresag01](https://github.com/andresag01))
## [v2.2.9](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.9) (2015-12-18)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.8...v2.2.9)
**Closed issues:**
- Cannot open source input file "system\_nrf51.h" [\#52](https://github.com/ARMmbed/ble-nrf51822/issues/52)
**Merged pull requests:**
- Remove occurrence of deprecated appearance enum [\#92](https://github.com/ARMmbed/ble-nrf51822/pull/92) ([andresag01](https://github.com/andresag01))
## [v2.2.8](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.8) (2015-12-16)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.7...v2.2.8)
## [v2.2.7](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.7) (2015-12-15)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.6...v2.2.7)
**Merged pull requests:**
- Replace deprecated inclusions of mbed.h [\#89](https://github.com/ARMmbed/ble-nrf51822/pull/89) ([andresag01](https://github.com/andresag01))
- Improve shutdown to clear BLE API and not just SD [\#87](https://github.com/ARMmbed/ble-nrf51822/pull/87) ([andresag01](https://github.com/andresag01))
## [v2.2.6](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.6) (2015-12-15)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.5...v2.2.6)
**Merged pull requests:**
- follow the extraction of address related types from Gap.h into BLEProtocol.h [\#88](https://github.com/ARMmbed/ble-nrf51822/pull/88) ([rgrover](https://github.com/rgrover))
## [v2.2.5](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.5) (2015-12-11)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.3...v2.2.5)
**Merged pull requests:**
- Added SecurityManager::setLinkSecurity call for elevating security settings on a particular connection. [\#86](https://github.com/ARMmbed/ble-nrf51822/pull/86) ([marcuschangarm](https://github.com/marcuschangarm))
## [v2.2.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.3) (2015-12-10)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.2...v2.2.3)
## [v2.2.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.2) (2015-12-08)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.1...v2.2.2)
**Merged pull requests:**
- Add -Wno-unused-function to supress-warnings.cmake [\#83](https://github.com/ARMmbed/ble-nrf51822/pull/83) ([andresag01](https://github.com/andresag01))
## [v2.2.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.1) (2015-12-08)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.0...v2.2.1)
**Merged pull requests:**
- WIP: UUID endian change [\#82](https://github.com/ARMmbed/ble-nrf51822/pull/82) ([marcuschangarm](https://github.com/marcuschangarm))
## [v2.2.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.0) (2015-12-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.4...v2.2.0)
## [v2.1.4](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.4) (2015-12-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.3...v2.1.4)
## [v2.1.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.3) (2015-12-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.2...v2.1.3)
## [v2.1.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.2) (2015-12-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.1...v2.1.2)
**Merged pull requests:**
- Allow GattAttributes to have variable length [\#81](https://github.com/ARMmbed/ble-nrf51822/pull/81) ([andresag01](https://github.com/andresag01))
## [v2.1.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.1) (2015-12-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.0...v2.1.1)
**Merged pull requests:**
- Fixed endianness bug in nRF5xServiceDiscovery::processDiscoverUUIDResponse so it is consistent with BLE API. [\#80](https://github.com/ARMmbed/ble-nrf51822/pull/80) ([marcuschangarm](https://github.com/marcuschangarm))
- Fixed bug in nRF5xGap.setAddress where random adresses where not set properly. [\#79](https://github.com/ARMmbed/ble-nrf51822/pull/79) ([marcuschangarm](https://github.com/marcuschangarm))
- Separate concept of minlen and len for BLE chars [\#78](https://github.com/ARMmbed/ble-nrf51822/pull/78) ([andresag01](https://github.com/andresag01))
- Split nordic sdk into its own module [\#75](https://github.com/ARMmbed/ble-nrf51822/pull/75) ([LiyouZhou](https://github.com/LiyouZhou))
## [v2.1.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.0) (2015-11-27)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.8...v2.1.0)
**Merged pull requests:**
- Update to sdk 8.1 [\#77](https://github.com/ARMmbed/ble-nrf51822/pull/77) ([LiyouZhou](https://github.com/LiyouZhou))
## [v2.0.8](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.8) (2015-11-26)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.7...v2.0.8)
## [v2.0.7](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.7) (2015-11-26)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.6...v2.0.7)
**Closed issues:**
- test2000 [\#72](https://github.com/ARMmbed/ble-nrf51822/issues/72)
- test1000000 [\#71](https://github.com/ARMmbed/ble-nrf51822/issues/71)
- test4 [\#70](https://github.com/ARMmbed/ble-nrf51822/issues/70)
- test3 [\#69](https://github.com/ARMmbed/ble-nrf51822/issues/69)
- test2 [\#68](https://github.com/ARMmbed/ble-nrf51822/issues/68)
**Merged pull requests:**
- use Extern c around \#include to use nordic sdk headers implemented in C [\#73](https://github.com/ARMmbed/ble-nrf51822/pull/73) ([LiyouZhou](https://github.com/LiyouZhou))
## [v2.0.6](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.6) (2015-11-17)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.5...v2.0.6)
**Closed issues:**
- test [\#66](https://github.com/ARMmbed/ble-nrf51822/issues/66)
**Merged pull requests:**
- add Nordic's license agreement. [\#67](https://github.com/ARMmbed/ble-nrf51822/pull/67) ([rgrover](https://github.com/rgrover))
## [v2.0.5](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.5) (2015-11-16)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.4...v2.0.5)
**Merged pull requests:**
- Post radio notification callback through minar [\#65](https://github.com/ARMmbed/ble-nrf51822/pull/65) ([andresag01](https://github.com/andresag01))
## [v2.0.4](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.4) (2015-11-13)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.3...v2.0.4)
**Merged pull requests:**
- Fix assembly sequence to start bootloader in GCC [\#64](https://github.com/ARMmbed/ble-nrf51822/pull/64) ([andresag01](https://github.com/andresag01))
## [v2.0.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.3) (2015-11-09)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.2...v2.0.3)
**Merged pull requests:**
- Added watchdog header file from Nordic SDK 8.1 [\#62](https://github.com/ARMmbed/ble-nrf51822/pull/62) ([marcuschangarm](https://github.com/marcuschangarm))
## [v2.0.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.2) (2015-11-03)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/mbedos-release-15-11...v2.0.2)
## [mbedos-release-15-11](https://github.com/ARMmbed/ble-nrf51822/tree/mbedos-release-15-11) (2015-11-03)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.1...mbedos-release-15-11)
## [v2.0.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.1) (2015-11-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.0...v2.0.1)
**Merged pull requests:**
- Ensure that the initialization flags is set to false if the BLE stack is shutdown properly. [\#58](https://github.com/ARMmbed/ble-nrf51822/pull/58) ([pan-](https://github.com/pan-))
## [v2.0.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.0) (2015-11-02)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v1.1.0...v2.0.0)
**Closed issues:**
- Nordic SDK and SoftDevice [\#57](https://github.com/ARMmbed/ble-nrf51822/issues/57)
- shouldn't eab6631cb be merged into master? [\#54](https://github.com/ARMmbed/ble-nrf51822/issues/54)
**Merged pull requests:**
- Introduced changes for memory savings [\#55](https://github.com/ARMmbed/ble-nrf51822/pull/55) ([andresag01](https://github.com/andresag01))
## [v1.1.0](https://github.com/ARMmbed/ble-nrf51822/tree/v1.1.0) (2015-10-28)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v1.0.0...v1.1.0)
**Closed issues:**
- target dependencies in module.json [\#50](https://github.com/ARMmbed/ble-nrf51822/issues/50)
**Merged pull requests:**
- When connecting, if no scanning parameters are passed, use values from Gap parent. [\#53](https://github.com/ARMmbed/ble-nrf51822/pull/53) ([marcuschangarm](https://github.com/marcuschangarm))
## [v1.0.0](https://github.com/ARMmbed/ble-nrf51822/tree/v1.0.0) (2015-10-19)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/mbedos-techcon-oob2...v1.0.0)
## [mbedos-techcon-oob2](https://github.com/ARMmbed/ble-nrf51822/tree/mbedos-techcon-oob2) (2015-10-19)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.8...mbedos-techcon-oob2)
**Closed issues:**
- rename the bootloader files with \_fota in the name? [\#51](https://github.com/ARMmbed/ble-nrf51822/issues/51)
**Merged pull requests:**
- Update S110 detection macros, again [\#49](https://github.com/ARMmbed/ble-nrf51822/pull/49) ([jpbrucker](https://github.com/jpbrucker))
- Error check number of characteristics [\#48](https://github.com/ARMmbed/ble-nrf51822/pull/48) ([Timmmm](https://github.com/Timmmm))
## [v0.4.8](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.8) (2015-09-25)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.7...v0.4.8)
**Closed issues:**
- Error real cause loss in nRF5xGattServer.cpp [\#44](https://github.com/ARMmbed/ble-nrf51822/issues/44)
**Merged pull requests:**
- rgrover patch fixed [\#47](https://github.com/ARMmbed/ble-nrf51822/pull/47) ([fabiencomte](https://github.com/fabiencomte))
- Update S110 detection macros [\#43](https://github.com/ARMmbed/ble-nrf51822/pull/43) ([jpbrucker](https://github.com/jpbrucker))
- remove some unnecessary include paths [\#42](https://github.com/ARMmbed/ble-nrf51822/pull/42) ([autopulated](https://github.com/autopulated))
- Add FOTA bootloader image [\#41](https://github.com/ARMmbed/ble-nrf51822/pull/41) ([jpbrucker](https://github.com/jpbrucker))
## [v0.4.7](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.7) (2015-08-13)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.6...v0.4.7)
## [v0.4.6](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.6) (2015-08-11)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.5...v0.4.6)
**Closed issues:**
- remove duplication of global static variable BLE\_EVT\_BUFFER [\#39](https://github.com/ARMmbed/ble-nrf51822/issues/39)
- clearScanResponse\(\) [\#30](https://github.com/ARMmbed/ble-nrf51822/issues/30)
- Debug builds fail due to missing bsp.h [\#11](https://github.com/ARMmbed/ble-nrf51822/issues/11)
**Merged pull requests:**
- Disable GattClient features when using S110 SoftDevice [\#38](https://github.com/ARMmbed/ble-nrf51822/pull/38) ([jpbrucker](https://github.com/jpbrucker))
## [v0.4.5](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.5) (2015-08-10)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.4...v0.4.5)
## [v0.4.4](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.4) (2015-08-07)
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.3...v0.4.4)
**Closed issues:**
- nrf51822 hangs after calling sd\_flash\_page\_erase\(\) [\#35](https://github.com/ARMmbed/ble-nrf51822/issues/35)
- nRF5xn::getVersion return \(Unknown\) with version 8 soft device [\#29](https://github.com/ARMmbed/ble-nrf51822/issues/29)
**Merged pull requests:**
- Changed Gap:: to GapAdvertisingParams:: because of change in BLE [\#34](https://github.com/ARMmbed/ble-nrf51822/pull/34) ([jslater8](https://github.com/jslater8))
- Select the clock source dynamically on SoftDevice initialisation [\#32](https://github.com/ARMmbed/ble-nrf51822/pull/32) ([jpbrucker](https://github.com/jpbrucker))
- Add S110 SoftDevice compatibility [\#28](https://github.com/ARMmbed/ble-nrf51822/pull/28) ([jpbrucker](https://github.com/jpbrucker))
## [v0.4.3](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.3) (2015-07-22)
**Closed issues:**
- Target polling failed [\#24](https://github.com/ARMmbed/ble-nrf51822/issues/24)
- support handling of HVX Events \(notifications and indications\). [\#22](https://github.com/ARMmbed/ble-nrf51822/issues/22)
- provide an implementation for GattServer::areUpdatesEnabled\(\) [\#21](https://github.com/ARMmbed/ble-nrf51822/issues/21)
- getValueHandle\(\) returns characteristicIndex instead of attribute-handle [\#20](https://github.com/ARMmbed/ble-nrf51822/issues/20)
- Clash With Definition And Enum Naming [\#16](https://github.com/ARMmbed/ble-nrf51822/issues/16)
- Errors in GCC build [\#14](https://github.com/ARMmbed/ble-nrf51822/issues/14)
- bring s110 support back [\#10](https://github.com/ARMmbed/ble-nrf51822/issues/10)
- Allow adding a User Description descriptor to a GattCharacteristic. [\#9](https://github.com/ARMmbed/ble-nrf51822/issues/9)
- device\_manager\_peripheral.c includes app\_trace.h [\#7](https://github.com/ARMmbed/ble-nrf51822/issues/7)
- linking esb\_gcc.a \(nrf51822 enhanced shock burst\) with mbed [\#5](https://github.com/ARMmbed/ble-nrf51822/issues/5)
- The app\_timer usage may conflict [\#2](https://github.com/ARMmbed/ble-nrf51822/issues/2)
- Nordic License [\#1](https://github.com/ARMmbed/ble-nrf51822/issues/1)
**Merged pull requests:**
- Develop [\#25](https://github.com/ARMmbed/ble-nrf51822/pull/25) ([zoujixing](https://github.com/zoujixing))
- Remove unnecessary 'compiler\_abstraction.h' to get rid of duplicate '… [\#23](https://github.com/ARMmbed/ble-nrf51822/pull/23) ([adfernandes](https://github.com/adfernandes))
- restructure for minimal yotta compatibility [\#15](https://github.com/ARMmbed/ble-nrf51822/pull/15) ([autopulated](https://github.com/autopulated))
- Fix various GCC compilation issues. [\#12](https://github.com/ARMmbed/ble-nrf51822/pull/12) ([adfernandes](https://github.com/adfernandes))
- Fix for GCC lost in SDK v8.0 update [\#8](https://github.com/ARMmbed/ble-nrf51822/pull/8) ([rosterloh](https://github.com/rosterloh))
- new target DELTA\_DFCM\_NNN40 with nrf51822 chip, config internal RC crystal. [\#6](https://github.com/ARMmbed/ble-nrf51822/pull/6) ([Marcomissyou](https://github.com/Marcomissyou))
- Updated return value for nRF51GattServer::updateValue. Will now report w... [\#4](https://github.com/ARMmbed/ble-nrf51822/pull/4) ([marcuschangarm](https://github.com/marcuschangarm))
- Added optional data and length fields to the return struct for authorize... [\#3](https://github.com/ARMmbed/ble-nrf51822/pull/3) ([marcuschangarm](https://github.com/marcuschangarm))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

View File

@ -0,0 +1,6 @@
This module contains softdevice which comes with The Nordic Softdevice License Agreement,
a BSD-like licence for binary distributions, offered by Nordic for use in mbed. Some
other files come from the mbed SDK, and are licensed under Apache-2.0. Unless
specifically indicated otherwise in a file, files are licensed under the
Apache 2.0 license, as can be found in: apache-2.0.txt. The Nordic Semiconductor Softdevice
License Agreement can be found in softdevice_nrf51822_licence_agreement.txt.

View File

@ -0,0 +1,13 @@
Copyright (c) 2015 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.

View File

@ -0,0 +1,36 @@
{
"name": "ble-nrf51822",
"version": "2.7.1",
"description": "Nordic stack and drivers for the mbed BLE API.",
"keywords": [
"Bluetooth",
"BLE",
"mbed",
"mbed-official"
],
"author": "Rohit Grover",
"repository": {
"url": "git@github.com:ARMmbed/ble-nRF51822.git",
"type": "git"
},
"homepage": "https://developer.mbed.org/teams/Nordic-Semiconductor/",
"licenses": [
{
"url": "https://spdx.org/licenses/Apache-2.0",
"type": "Apache-2.0"
},
{
"type": "LicenseRef-softdevice_nrf51822_licence_agreement.txt"
}
],
"dependencies": {
"ble": "^2.6.0",
"nrf51-sdk": "^2.4.0"
},
"extraIncludes": [
"source/btle",
"source/btle/custom",
"source/common"
],
"targetDependencies": {}
}

View File

@ -0,0 +1,30 @@
/*
* S110/S120/S130 License Agreement
*
* Copyright (c) 2015, Nordic Semiconductor ASA, All rights reserved.
*
* Redistribution. Redistribution and use in binary form, without modification,
* are permitted provided that the following conditions are met:
*
* • Redistributions must reproduce the above copyright notice and the following
* disclaimer in the documentation and/or other materials provided with the
* distribution.
* • Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* • No reverse engineering, decompilation, or disassembly of this software is
* permitted.
*
* DISCLAIMER.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* /

View File

@ -0,0 +1,443 @@
/* 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 "common/common.h"
#include "nordic_common.h"
#include "btle.h"
#include "btle_clock.h"
#include "ble_flash.h"
#include "ble_conn_params.h"
#include "btle_gap.h"
#include "custom/custom_helper.h"
#include "ble/GapEvents.h"
#include "nRF5xn.h"
// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work
#undef STATIC_ASSERT_SIMPLE
#undef STATIC_ASSERT_MSG
// FIXME : We can't use mbed_assert.h because we're using these macros within functions
#define STATIC_ASSERT_MSG(EXPR, MSG)
#define STATIC_ASSERT_SIMPLE(EXPR)
#warning FIXME : We can't use mbed_assert.h because we're using these within functions
#ifdef S110
#define IS_LEGACY_DEVICE_MANAGER_ENABLED 1
#elif defined(S130) || defined(S132)
#define IS_LEGACY_DEVICE_MANAGER_ENABLED 0
#endif
extern "C" {
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
#include "pstorage.h"
#include "device_manager.h"
#else
#include "nrf_fstorage.h"
#include "fds.h"
#include "peer_manager.h"
#include "ble_conn_state.h"
#endif
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
}
#include "headers/ble_hci.h"
#include "nRF5XPalGattClient.h"
// Make this volatile at it will be set in interrupt context
volatile bool isEventsSignaled = false;
extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
// Before SDK 14, the softdevice handler is implemented within the SDK
// In SDK 14+, we have to implement it as we're using the "polling" mode for the SD
extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector.
#if NRF_SDK14PLUS_EVENT_HANDLERS
static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context);
#else
static void btle_handler(ble_evt_t *p_ble_evt);
#endif
#if !NRF_SDK14PLUS_EVENT_HANDLERS
static void sys_evt_dispatch(uint32_t sys_evt)
{
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
pstorage_sys_event_handler(sys_evt);
#else
// Forward Softdevice events to the fstorage module
fs_sys_event_handler(sys_evt);
#endif
}
#endif
/**
* This function is called in interrupt context to handle BLE events; i.e. pull
* system and user events out of the pending events-queue of the BLE stack. The
* BLE stack signals the availability of events by the triggering the SWI2
* interrupt, which forwards the handling to this function.
*
* The event processing loop is implemented in intern_softdevice_events_execute().
*
* This function will signal to the user code by calling signalEventsToProcess
* that their is events to process and BLE::processEvents should be called.
*/
static uint32_t signalEvent()
{
if(isEventsSignaled == false) {
isEventsSignaled = true;
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).signalEventsToProcess(BLE::DEFAULT_INSTANCE);
}
return NRF_SUCCESS;
}
error_t btle_init(void)
{
nrf_clock_lf_cfg_t clockConfiguration;
ret_code_t err_code;
// register softdevice handler vector
NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);
#if (NRF_SD_BLE_API_VERSION >= 5)
err_code = nrf_sdh_enable_request();
ASSERT_STATUS(err_code);
#else
// Configure the LF clock according to values provided by btle_clock.h.
// It is input from the chain of the yotta configuration system.
clockConfiguration.source = LFCLK_CONF_SOURCE;
clockConfiguration.xtal_accuracy = LFCLK_CONF_ACCURACY;
clockConfiguration.rc_ctiv = LFCLK_CONF_RC_CTIV;
clockConfiguration.rc_temp_ctiv = LFCLK_CONF_RC_TEMP_CTIV;
SOFTDEVICE_HANDLER_INIT(&clockConfiguration, signalEvent);
#endif
// Enable BLE stack
#if (NRF_SD_BLE_API_VERSION >= 5)
// Configure softdevice manually
// We could have used nrf_sdh_ble_default_cfg_set() but it's tightly coupled with the macros defined in sdk_config.h
ble_cfg_t ble_cfg;
uint32_t ram_start = 0;
// Recover start address of application's RAM
err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
ASSERT_STATUS(err_code);
// First configure GAP parameters, including the maximum number of connections
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG;
ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = TOTAL_LINK_COUNT;
ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = NRF_SDH_BLE_GAP_EVENT_LENGTH; // FIXME?
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// GAP - Configure the number of peripheral and central links
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG;
ble_cfg.gap_cfg.role_count_cfg.periph_role_count = PERIPHERAL_LINK_COUNT;
ble_cfg.gap_cfg.role_count_cfg.central_role_count = CENTRAL_LINK_COUNT;
ble_cfg.gap_cfg.role_count_cfg.central_sec_count = CENTRAL_LINK_COUNT ?
BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT : 0;
err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// Configure GATT
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG;
ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATT, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// Number of custom UUIDs
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = UUID_TABLE_MAX_ENTRIES;
err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// GATT Server attribute table size
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = GATTS_ATTR_TAB_SIZE;
err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// GATT Server, Service Changed characteristic
memset(&ble_cfg, 0, sizeof(ble_cfg_t));
ble_cfg.gatts_cfg.service_changed.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
err_code = sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &ble_cfg, ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
// Enable BLE stack in softdevice
err_code = nrf_sdh_ble_enable(&ram_start);
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
#else
ble_enable_params_t ble_enable_params;
err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
PERIPHERAL_LINK_COUNT,
&ble_enable_params);
ble_enable_params.gatts_enable_params.attr_tab_size = GATTS_ATTR_TAB_SIZE;
ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
ble_enable_params.common_enable_params.vs_uuid_count = UUID_TABLE_MAX_ENTRIES;
if(err_code != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
if (softdevice_enable(&ble_enable_params) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
#endif
// Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp)
pm_init();
#if (NRF_SD_BLE_API_VERSION <= 2)
ble_gap_addr_t addr;
if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
#else
ble_gap_privacy_params_t privacy_params = {0};
privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF;
pm_privacy_set(&privacy_params);
#endif
// From SDK 14 onwards event handlers are registered differently
// http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fmigration.html
#if NRF_SDK14PLUS_EVENT_HANDLERS
// Register a handler for our BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, 3 /* default priority for user events */, btle_handler, NULL);
#else
ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));
#endif
return btle_gap_init();
}
#if NRF_SDK14PLUS_EVENT_HANDLERS
static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context)
#else
static void btle_handler(ble_evt_t *p_ble_evt)
#endif
{
#if NRF_SDK14PLUS_EVENT_HANDLERS
(void)p_context; // Keep compiler happy
#endif
using ble::pal::vendor::nordic::nRF5XGattClient;
// In SDK14+, all other modules from the SDK will be registered independently as softdevice events observers
#if !NRF_SDK14PLUS_EVENT_HANDLERS
/* Library service handlers */
#if SDK_CONN_PARAMS_MODULE_ENABLE
ble_conn_params_on_ble_evt(p_ble_evt);
#endif
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
dm_ble_evt_handler(p_ble_evt);
#else
// Forward BLE events to the Connection State module.
// This must be called before any event handler that uses this module.
ble_conn_state_on_ble_evt(p_ble_evt);
// Forward BLE events to the Peer Manager
pm_on_ble_evt(p_ble_evt);
#endif
#endif
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
nRF5XGattClient::handle_events(p_ble_evt);
#endif
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
nRF5xGap &gap = (nRF5xGap &) ble.getGap();
nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer();
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
/* Custom event handler */
switch (p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED: {
Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110)
/* Only peripheral role is supported by S110 */
Gap::Role_t role = Gap::PERIPHERAL;
#else
Gap::Role_t role = static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role);
#endif
gap.setConnectionHandle(handle);
const Gap::ConnectionParams_t *params = reinterpret_cast<const Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
#if (NRF_SD_BLE_API_VERSION <= 2)
const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr;
gap.processConnectionEvent(handle,
role,
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
static_cast<BLEProtocol::AddressType_t>(own->addr_type), own->addr,
params);
#else
Gap::AddressType_t addr_type;
Gap::Address_t own_address;
gap.getAddress(&addr_type, own_address);
gap.processConnectionEvent(handle,
role,
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
addr_type, own_address,
params);
#endif
break;
}
case BLE_GAP_EVT_DISCONNECTED: {
Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
// Since we are not in a connection and have not started advertising,
// store bonds
gap.setConnectionHandle (BLE_CONN_HANDLE_INVALID);
Gap::DisconnectionReason_t reason;
switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) {
case BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION:
reason = Gap::LOCAL_HOST_TERMINATED_CONNECTION;
break;
case BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION:
reason = Gap::REMOTE_USER_TERMINATED_CONNECTION;
break;
case BLE_HCI_CONN_INTERVAL_UNACCEPTABLE:
reason = Gap::CONN_INTERVAL_UNACCEPTABLE;
break;
default:
/* Please refer to the underlying transport library for an
* interpretion of this reason's value. */
reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
break;
}
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
// Close all pending discoveries for this connection
nRF5XGattClient::handle_connection_termination(handle);
#endif
gap.processDisconnectionEvent(handle, reason);
break;
}
case BLE_GAP_EVT_PASSKEY_DISPLAY:
securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey);
break;
case BLE_GAP_EVT_TIMEOUT:
gap.processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
break;
case BLE_GATTC_EVT_TIMEOUT:
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server and Client timeout events.
// ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle,
// BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
break;
case BLE_GAP_EVT_ADV_REPORT: {
const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report;
gap.processAdvertisementReport(advReport->peer_addr.addr,
advReport->rssi,
advReport->scan_rsp,
static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
advReport->dlen,
advReport->data);
break;
}
default:
break;
}
gattServer.hwCallback(p_ble_evt);
}
/*! @brief Callback when an error occurs inside the SoftDevice */
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
{
ASSERT_TRUE(false, (void) 0);
}
#if NRF_SD_BLE_API_VERSION >= 5
/*!
@brief Handler for general errors above the SoftDevice layer.
Typically we can' recover from this so we do a reset.
This implementation will override the default weak symbol generated by the Nordic SDK
*/
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
ASSERT_STATUS_RET_VOID( id );
NVIC_SystemReset();
}
#else
/*!
@brief Handler for general errors above the SoftDevice layer.
Typically we can' recover from this so we do a reset.
*/
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
{
ASSERT_STATUS_RET_VOID( error_code );
NVIC_SystemReset();
}
#endif
#if NRF_SDK14PLUS_EVENT_HANDLERS
/*!
@brief Handler of Softdevice events.
This signals that the softdevie has events that need to be processed.
*/
extern "C" void SD_EVT_IRQHandler(void)
{
ASSERT_STATUS_RET_VOID(signalEvent());
}
#endif

View File

@ -0,0 +1,75 @@
/* 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.
*/
#ifndef _BTLE_H_
#define _BTLE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
#include "ble_srv_common.h"
#include "headers/nrf_ble.h"
#if NRF_SD_BLE_API_VERSION >= 5
#include "sdk_config.h"
#endif
#define NRF_CONNECTION_TAG 1 /**<Connection tag to use with softdevice */
#define CENTRAL_LINK_COUNT NRF_SDH_BLE_CENTRAL_LINK_COUNT /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
#define PERIPHERAL_LINK_COUNT NRF_SDH_BLE_PERIPHERAL_LINK_COUNT /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
#define TOTAL_LINK_COUNT NRF_SDH_BLE_TOTAL_LINK_COUNT /**<number of total links used by the application. When changing this number remember to adjust the RAM settings */
#define GATTS_ATTR_TAB_SIZE NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE /**< GATTS attribite table size. */
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
/**
* Using this call, the application can select whether to include the
* Service Changed characteristic in the GATT Server. The default in all
* previous releases has been to include the Service Changed characteristic,
* but this affects how GATT clients behave. Specifically, it requires
* clients to subscribe to this attribute and not to cache attribute handles
* between connections unless the devices are bonded. If the application
* does not need to change the structure of the GATT server attributes at
* runtime this adds unnecessary complexity to the interaction with peer
* clients. If the SoftDevice is enabled with the Service Changed
* Characteristics turned off, then clients are allowed to cache attribute
* handles making applications simpler on both sides.
*/
#define IS_SRVC_CHANGED_CHARACT_PRESENT NRF_SDH_BLE_SERVICE_CHANGED
#define UUID_TABLE_MAX_ENTRIES NRF_SDH_BLE_VS_UUID_COUNT /* This is the maximum number of 128-bit UUIDs with distinct bases that
* we expect to be in use; increase this limit if needed. */
#define NRF_SDK14PLUS_EVENT_HANDLERS (NRF_SD_BLE_API_VERSION >= 5) // Softdevice event dispatching has changed in SDK14
error_t btle_init(void);
// flag indicating if events have been signaled or not
// It is used by processEvents and signalEventsToProcess
// signalEventsToProcess raise the flag and processEvents
// clears it.
extern volatile bool isEventsSignaled;
#ifdef __cplusplus
}
#endif
#endif // ifndef _BTLE_H_

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2016 Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
* integrated circuit in a product or a software update for such product, must reproduce
* the above copyright notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior
* written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _BTLE_CLOCK_H_
#define _BTLE_CLOCK_H_
#include "nrf5x_lf_clk_helper.h"
/**
* @brief Module that generates settings for the low-frequency (LF) clock configuration.
*
* This module provides macros that are generated from the mbed config system macros.
*
*
*
* As a result, this module provides the following: @n
* - literal value LFCLK_CONF_SOURCE @n
* - literal value LFCLK_CONF_ACCURACY @n
* - literal value LFCLK_CONF_RC_CTIV @n
* - literal value LFCLK_CONF_RC_TEMP_CTIV
*/
#include "nrf_sdm.h"
#define DEFAULT_LFCLK_CONF_ACCURACY NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM
#ifdef NRF52
#define MAX_LFCLK_CONF_RC_CTIV 32
#else
#define MAX_LFCLK_CONF_RC_CTIV 64
#endif
#define MAX_LFCLK_CONF_RC_TEMP_CTIV 33
#define DEFAULT_LFCLK_CONF_RC_CTIV 16 // Check temperature every 16 * 250ms.
#define DEFAULT_LFCLK_CONF_RC_TEMP_CTIV 1 // Only calibrate if temperature has changed.
#define NRF_LF_SRC_XTAL 2
#define NRF_LF_SRC_SYNTH 3
#define NRF_LF_SRC_RC 4
#if MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_RC
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_RC
#ifdef MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL
#define LFCLK_CONF_RC_CTIV MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL
#else
#define LFCLK_CONF_RC_CTIV DEFAULT_LFCLK_CONF_RC_CTIV
#endif
#ifdef MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG
#define LFCLK_CONF_RC_TEMP_CTIV MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG
#else
#define LFCLK_CONF_RC_TEMP_CTIV DEFAULT_LFCLK_CONF_RC_TEMP_CTIV
#endif
#if (LFCLK_CONF_RC_CTIV < 1) || (LFCLK_CONF_RC_CTIV > MAX_LFCLK_CONF_RC_CTIV)
#error Calibration timer interval out of range!
#endif
#if (LFCLK_CONF_RC_TEMP_CTIV < 0 ) || (LFCLK_CONF_RC_TEMP_CTIV > 33)
#error Number/mode of LF RC calibration intervals out of range!
#endif
#elif MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_SYNTH
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_SYNTH
#define LFCLK_CONF_RC_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
#define LFCLK_CONF_RC_TEMP_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
#ifdef MBED_CONF_NORDIC_LF_CLOCK_HF_SYNTH_ACCURACY
#define LFCLK_CONF_ACCURACY MBED_CONF_NORDIC_LF_CLOCK_HF_SYNTH_ACCURACY
#endif
#else // default is NRF_LF_SRC_SYNTH
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_XTAL
#define LFCLK_CONF_RC_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
#define LFCLK_CONF_RC_TEMP_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
#ifdef MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY
#define LFCLK_CONF_ACCURACY MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY
#endif
#endif
#ifndef LFCLK_CONF_ACCURACY
#define LFCLK_CONF_ACCURACY DEFAULT_LFCLK_CONF_ACCURACY
#endif
#if (LFCLK_CONF_ACCURACY > NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM) || (LFCLK_CONF_ACCURACY < NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM)
#error Low frequency clock accuracy out of range!
#endif
#endif //_BTLE_CLOCK_H_

View File

@ -0,0 +1,99 @@
/* 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 "common/common.h"
#include "headers/ble_gap.h"
#include "ble_conn_params.h"
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST;
#if SDK_CONN_PARAMS_MODULE_ENABLE
static void error_callback(uint32_t nrf_error);
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
/**************************************************************************/
/*!
@brief Initialise GAP in the underlying SoftDevice
@returns
*/
/**************************************************************************/
error_t btle_gap_init(void)
{
ble_gap_conn_params_t gap_conn_params = {0};
gap_conn_params.min_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MIN_INTERVAL_MS); // in 1.25ms units
gap_conn_params.max_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MAX_INTERVAL_MS); // in 1.25ms unit
gap_conn_params.slave_latency = CFG_GAP_CONNECTION_SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS / 10; // in 10ms unit
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
ASSERT_STATUS( sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) CFG_GAP_LOCAL_NAME, strlen(CFG_GAP_LOCAL_NAME)));
ASSERT_STATUS( sd_ble_gap_appearance_set(CFG_GAP_APPEARANCE));
ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params));
ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL));
/**
* Call to conn_params_init() is not necessary; and so is disabled by default.
* This API should be exposed to the user to be invoked when necessary.
*/
#if SDK_CONN_PARAMS_MODULE_ENABLE
/* Connection Parameters */
enum {
FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
NEXT_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
MAX_UPDATE_COUNT = 3
};
ble_conn_params_init_t cp_init = {0};
cp_init.p_conn_params = NULL;
cp_init.first_conn_params_update_delay = FIRST_UPDATE_DELAY;
cp_init.next_conn_params_update_delay = NEXT_UPDATE_DELAY;
cp_init.max_conn_params_update_count = MAX_UPDATE_COUNT;
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
cp_init.disconnect_on_fail = true;
cp_init.evt_handler = NULL;
cp_init.error_handler = error_callback;
ASSERT_STATUS ( ble_conn_params_init(&cp_init));
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Converts msecs to an integer representing 1.25ms units
@param[in] ms
The number of milliseconds to conver to 1.25ms units
@returns The number of 1.25ms units in the supplied number of ms
*/
/**************************************************************************/
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms)
{
return (interval_ms * 4) / 5;
}
#if SDK_CONN_PARAMS_MODULE_ENABLE
static void error_callback(uint32_t nrf_error)
{
ASSERT_STATUS_RET_VOID( nrf_error );
}
#endif // SDK_CONN_PARAMS_MODULE_ENABLE

View File

@ -0,0 +1,24 @@
/* 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.
*/
#ifndef _BTLE_GAP_H_
#define _BTLE_GAP_H_
#include "common/common.h"
error_t btle_gap_init(void);
#endif // ifndef _BTLE_GAP_H_

View File

@ -0,0 +1,326 @@
/* 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.
*/
#if defined(S110)
#include "btle.h"
#include "nRF5xn.h"
extern "C" {
#include "pstorage.h"
#include "device_manager.h"
#include "id_manager.h"
}
#include "btle_security.h"
static dm_application_instance_t applicationInstance;
static bool initialized = false;
static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11.
static ble_gap_sec_params_t securityParameters = {
.bond = true, /**< Perform bonding. */
.mitm = true, /**< Man In The Middle protection required. */
.lesc = false, /**< Enable LE Secure Connection pairing. */
.keypress = false, /**< Enable generation of keypress notifications. */
.io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
.oob = 0, /**< Out Of Band data available. */
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
.kdist_own = {
.enc = 0, /**< Long Term Key and Master Identification. */
.id = 0, /**< Identity Resolving Key and Identity Address Information. */
.sign = 0, /**< Connection Signature Resolving Key. */
.link = 0 /**< Derive the Link Key from the LTK. */
}, /**< Key distribution bitmap: keys that the local device will distribute. */
.kdist_peer = {
.enc = 1, /**< Long Term Key and Master Identification. */
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
.sign = 1, /**< Connection Signature Resolving Key. */
.link = 0 /**< Derive the Link Key from the LTK. */
} /**< Key distribution bitmap: keys that the peripheral device will distribute. */
};
bool
btle_hasInitializedSecurity(void)
{
return initialized;
}
ble_error_t
btle_initializeSecurity(bool enableBonding,
bool requireMITM,
SecurityManager::SecurityIOCapabilities_t iocaps,
const SecurityManager::Passkey_t passkey)
{
/* guard against multiple initializations */
if (initialized) {
return BLE_ERROR_NONE;
}
if (pstorage_init() != NRF_SUCCESS) {
return BLE_ERROR_UNSPECIFIED;
}
ret_code_t rc;
if (passkey) {
ble_opt_t opts;
opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
switch (rc) {
case BLE_ERROR_INVALID_CONN_HANDLE:
case NRF_ERROR_INVALID_ADDR:
case NRF_ERROR_INVALID_PARAM:
default:
return BLE_ERROR_INVALID_PARAM;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_BUSY:
return BLE_STACK_BUSY;
}
}
}
dm_init_param_t dm_init_param = {
.clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */
};
if (dm_init(&dm_init_param) != NRF_SUCCESS) {
return BLE_ERROR_UNSPECIFIED;
}
// update default security parameters with function call parameters
securityParameters.bond = enableBonding;
securityParameters.mitm = requireMITM;
securityParameters.io_caps = iocaps;
const dm_application_param_t dm_param = {
.evt_handler = dm_handler,
.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
.sec_param = securityParameters
};
if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
switch (rc) {
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_NO_MEM:
return BLE_ERROR_NO_MEM;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
initialized = true;
return BLE_ERROR_NONE;
}
ble_error_t
btle_purgeAllBondingState(void)
{
ret_code_t rc;
if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
}
switch (rc) {
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_NO_MEM:
return BLE_ERROR_NO_MEM;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
ble_error_t
btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
{
ret_code_t rc;
dm_handle_t dmHandle = {
.appl_id = applicationInstance,
};
if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) {
if (rc == NRF_ERROR_NOT_FOUND) {
return BLE_ERROR_INVALID_PARAM;
} else {
return BLE_ERROR_UNSPECIFIED;
}
}
if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast<dm_security_status_t *>(securityStatusP))) != NRF_SUCCESS) {
switch (rc) {
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_NO_MEM:
return BLE_ERROR_NO_MEM;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
return BLE_ERROR_NONE;
}
ble_error_t
btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
{
// use default and updated parameters as starting point
// and modify structure based on security mode.
ble_gap_sec_params_t params = securityParameters;
switch (securityMode) {
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
/**< Require no protection, open link. */
securityParameters.bond = false;
securityParameters.mitm = false;
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
/**< Require encryption, but no MITM protection. */
securityParameters.bond = true;
securityParameters.mitm = false;
break;
// not yet implemented security modes
case SecurityManager::SECURITY_MODE_NO_ACCESS:
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
/**< Require encryption and MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
/**< Require signing or encryption, but no MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
/**< Require signing or encryption, and MITM protection. */
default:
return BLE_ERROR_NOT_IMPLEMENTED;
}
// update security settings for given connection
uint32_t result = sd_ble_gap_authenticate(connectionHandle, &params);
if (result == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_UNSPECIFIED;
}
}
ret_code_t
dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
{
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
switch (p_event->event_id) {
case DM_EVT_SECURITY_SETUP: /* started */ {
const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params;
securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle,
peerParams->bond,
peerParams->mitm,
(SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
break;
}
case DM_EVT_SECURITY_SETUP_COMPLETE:
securityManager.
processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle,
(SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status));
break;
case DM_EVT_LINK_SECURED: {
unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm;
unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv;
SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
switch (securityMode) {
case 1:
switch (level) {
case 1:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
break;
case 2:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
break;
case 3:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
break;
}
break;
case 2:
switch (level) {
case 1:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
break;
case 2:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
break;
}
break;
}
securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode);
break;
}
case DM_EVT_DEVICE_CONTEXT_STORED:
securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle);
break;
default:
break;
}
return NRF_SUCCESS;
}
ble_error_t
btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist)
{
if (!btle_hasInitializedSecurity()) {
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
}
ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist);
if (err == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else if (err == NRF_ERROR_NULL) {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
} else {
return BLE_ERROR_INVALID_STATE;
}
}
bool
btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
{
/*
* Use a helper function from the Nordic SDK to test whether the BLE
* address can be generated using the IRK.
*/
return im_address_resolve(p_addr, p_irk);
}
void
btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address)
{
/* Set type to resolvable */
address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
/*
* Assign a random number to the most significant 3 bytes
* of the address.
*/
address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E;
address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F;
address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C;
/* Calculate the hash and store it in the top half of the address */
ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr);
}
#endif

View File

@ -0,0 +1,146 @@
/* 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.
*/
#ifndef _BTLE_SECURITY_H_
#define _BTLE_SECURITY_H_
#include "ble/Gap.h"
#include "ble/SecurityManager.h"
/**
* Function to test whether the SecurityManager has been initialized.
* Possible by a call to @ref btle_initializeSecurity().
*
* @return True if the SecurityManager was previously initialized, false
* otherwise.
*/
bool btle_hasInitializedSecurity(void);
/**
* Enable Nordic's Device Manager, which brings in functionality from the
* stack's Security Manager. The Security Manager implements the actual
* cryptographic algorithms and protocol exchanges that allow two devices to
* securely exchange data and privately detect each other.
*
* @param[in] enableBonding Allow for bonding.
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
* @param[in] iocaps To specify IO capabilities of this peripheral,
* such as availability of a display or keyboard to
* support out-of-band exchanges of security data.
* @param[in] passkey To specify a static passkey.
*
* @return BLE_ERROR_NONE on success.
*/
ble_error_t btle_initializeSecurity(bool enableBonding = true,
bool requireMITM = true,
SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE,
const SecurityManager::Passkey_t passkey = NULL);
/**
* Get the security status of a link.
*
* @param[in] connectionHandle
* Handle to identify the connection.
* @param[out] securityStatusP
* security status.
*
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
*/
ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP);
/**
* Set the security mode on a connection. Useful for elevating the security mode
* once certain conditions are met, e.g., a particular service is found.
*
* @param[in] connectionHandle
* Handle to identify the connection.
* @param[in] securityMode
* security mode.
*
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
*/
ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode);
/**
* Function for deleting all peer device context and all related bonding
* information from the database.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
*/
ble_error_t btle_purgeAllBondingState(void);
#if (NRF_SD_BLE_API_VERSION <= 2)
/**
* Query the SoftDevice bond table to extract a whitelist containing the BLE
* addresses and IRKs of bonded devices.
*
* @param[in/out] p_whitelist
* (on input) p_whitelist->addr_count and
* p_whitelist->irk_count specify the maximum number of
* addresses and IRKs added to the whitelist structure.
* (on output) *p_whitelist is a whitelist containing the
* addresses and IRKs of the bonded devices.
*
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
*/
ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist);
#endif
/**
* Function to test whether a BLE address is generated using an IRK.
*
* @param[in] p_addr
* Pointer to a BLE address.
* @param[in] p_irk
* Pointer to an IRK.
*
* @return True if p_addr can be generated using p_irk, false otherwise.
*/
bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk);
/**
* Function to generate a private resolvable BLE address.
*
* @param[out] p_addr
* The output address.
* @param[in] p_irk
* A reference to a IRK.
*
* @note This function does not generate a secure address since the prand number in the
* resolvable address is not truly random. Therefore, the output of this function
* is only meant to be used by the application internally but never exported.
*/
void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address);
#if (NRF_SD_BLE_API_VERSION >= 3)
/**
* @brief Returns a list of addresses from peers in the stacks bond table.
*
* @param[in/out] addresses
* (on input) @ref Gap::Whitelist_t structure where at
* most addresses.capacity addresses from bonded peers will
* be stored.
* (on output) A copy of the addresses from bonded peers.
*
* @retval BLE_ERROR_NONE if successful.
* @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent.
*/
ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList);
#endif
#endif /* _BTLE_SECURITY_H_ */

View File

@ -0,0 +1,488 @@
/* 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.
*/
#if defined(S130) || defined(S132) || defined(S140)
#include "btle.h"
#include "nRF5xn.h"
extern "C" {
#include "peer_manager.h"
#include "id_manager.h"
#include "fds.h"
}
#include "btle_security.h"
extern "C" void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash);
static bool initialized = false;
static void pm_handler(pm_evt_t const *p_event);
static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing.
volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API.
// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11.
static ble_gap_sec_params_t securityParameters = {
.bond = true, /**< Perform bonding. */
.mitm = true, /**< Man In The Middle protection required. */
.lesc = false, /**< Enable LE Secure Connection pairing. */
.keypress = false, /**< Enable generation of keypress notifications. */
.io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
.oob = 0, /**< Out Of Band data available. */
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
.kdist_own = {
.enc = 0, /**< Long Term Key and Master Identification. */
.id = 0, /**< Identity Resolving Key and Identity Address Information. */
.sign = 0, /**< Connection Signature Resolving Key. */
.link = 0 /**< Derive the Link Key from the LTK. */
}, /**< Key distribution bitmap: keys that the local device will distribute. */
.kdist_peer = {
.enc = 1, /**< Long Term Key and Master Identification. */
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
.sign = 0, /**< Connection Signature Resolving Key. */
.link = 0 /**< Derive the Link Key from the LTK. */
} /**< Key distribution bitmap: keys that the peripheral device will distribute. */
};
bool
btle_hasInitializedSecurity(void)
{
return initialized;
}
ble_error_t
btle_initializeSecurity(bool enableBonding,
bool requireMITM,
SecurityManager::SecurityIOCapabilities_t iocaps,
const SecurityManager::Passkey_t passkey)
{
/* guard against multiple initializations */
if (initialized) {
return BLE_ERROR_NONE;
}
ret_code_t rc;
if (passkey) {
ble_opt_t opts;
opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
switch (rc) {
case BLE_ERROR_INVALID_CONN_HANDLE:
case NRF_ERROR_INVALID_ADDR:
case NRF_ERROR_INVALID_PARAM:
default:
return BLE_ERROR_INVALID_PARAM;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_BUSY:
return BLE_STACK_BUSY;
}
}
}
// update default security parameters with function call parameters
securityParameters.bond = enableBonding;
securityParameters.mitm = requireMITM;
securityParameters.io_caps = iocaps;
if (enableBonding) {
securityParameters.kdist_own.enc = 1;
securityParameters.kdist_own.id = 1;
} else {
securityParameters.kdist_own.enc = 0;
securityParameters.kdist_own.id = 0;
}
rc = pm_sec_params_set(&securityParameters);
if (rc == NRF_SUCCESS) {
rc = pm_register(pm_handler);
}
switch (rc) {
case NRF_SUCCESS:
initialized = true;
return BLE_ERROR_NONE;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_INVALID_PARAM:
return BLE_ERROR_INVALID_PARAM;
default:
return BLE_ERROR_UNSPECIFIED;
}
initialized = true;
return BLE_ERROR_NONE;
}
ble_error_t
btle_purgeAllBondingState(void)
{
ret_code_t rc;
async_ret_code = NRF_ERROR_BUSY;
rc = pm_peers_delete(); // it is asynhronous API
if (rc == NRF_SUCCESS)
{
// waiting for respond from pm_handler
while (async_ret_code == NRF_ERROR_BUSY) {
// busy-loop
}
rc = async_ret_code;
}
switch (rc) {
case NRF_SUCCESS:
return BLE_ERROR_NONE;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
ble_error_t
btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
{
ret_code_t rc;
pm_conn_sec_status_t conn_sec_status;
rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status);
if (rc == NRF_SUCCESS)
{
if (conn_sec_status.encrypted) {
*securityStatusP = SecurityManager::ENCRYPTED;
}
else if (conn_sec_status.connected) {
if (_enc_in_progress) {
*securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS;
}
else {
*securityStatusP = SecurityManager::NOT_ENCRYPTED;
}
}
return BLE_ERROR_NONE;
}
switch (rc) {
case BLE_ERROR_INVALID_CONN_HANDLE:
return BLE_ERROR_INVALID_PARAM;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
ble_error_t
btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
{
// use default and updated parameters as starting point
// and modify structure based on security mode.
ret_code_t rc;
switch (securityMode) {
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
/**< Require no protection, open link. */
securityParameters.bond = false;
securityParameters.mitm = false;
securityParameters.kdist_own.enc = 0;
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
/**< Require encryption, but no MITM protection. */
securityParameters.bond = true;
securityParameters.mitm = false;
securityParameters.kdist_own.enc = 1;
break;
// not yet implemented security modes
case SecurityManager::SECURITY_MODE_NO_ACCESS:
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
/**< Require encryption and MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
/**< Require signing or encryption, but no MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
/**< Require signing or encryption, and MITM protection. */
default:
return BLE_ERROR_NOT_IMPLEMENTED;
}
// update security settings for given connection
rc = pm_sec_params_set(&securityParameters);
if (rc == NRF_SUCCESS) {
rc = pm_conn_secure(connectionHandle, false);
}
switch (rc) {
case NRF_SUCCESS:
initialized = true;
return BLE_ERROR_NONE;
case NRF_ERROR_INVALID_STATE:
return BLE_ERROR_INVALID_STATE;
case NRF_ERROR_INVALID_PARAM:
return BLE_ERROR_INVALID_PARAM;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
void pm_handler(pm_evt_t const *p_event)
{
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
ret_code_t err_code;
SecurityManager::SecurityMode_t resolvedSecurityMode;
switch (p_event->evt_id) {
case PM_EVT_CONN_SEC_START: /* started */ {
const ble_gap_sec_params_t *peerParams = &securityParameters;
securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle,
peerParams->bond,
peerParams->mitm,
(SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
_enc_in_progress = true;
break;
}
case PM_EVT_CONN_SEC_SUCCEEDED:
// Update the rank of the peer.
if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING)
{
err_code = pm_peer_rank_highest(p_event->peer_id);
}
securityManager.
processSecuritySetupCompletedEvent(p_event->conn_handle,
SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t
ble_gap_conn_sec_t conn_sec;
sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec);
resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
switch (conn_sec.sec_mode.sm) {
case 1:
switch (conn_sec.sec_mode.lv) {
case 1:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
break;
case 2:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
break;
case 3:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
break;
}
break;
case 2:
switch (conn_sec.sec_mode.lv) {
case 1:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
break;
case 2:
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
break;
}
break;
}
securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode);
_enc_in_progress = false;
break;
case PM_EVT_CONN_SEC_FAILED:
SecurityManager::SecurityCompletionStatus_t securityCompletionStatus;
if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) {
securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED;
} else {
securityCompletionStatus =
(SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error;
}
securityManager.
processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus);
_enc_in_progress = false;
break;
case PM_EVT_BONDED_PEER_CONNECTED:
pm_peer_rank_highest(p_event->peer_id);
break;
case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE)
{
securityManager.processSecurityContextStoredEvent(p_event->conn_handle);
}
break;
case PM_EVT_PEER_DATA_UPDATE_FAILED:
break;
case PM_EVT_PEERS_DELETE_SUCCEEDED:
async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState
break;
case PM_EVT_PEERS_DELETE_FAILED:
async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState
break;
case PM_EVT_STORAGE_FULL:
// Run garbage collection on the flash.
err_code = fds_gc();
if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
{
// Retry.
}
else
{
APP_ERROR_CHECK(err_code);
}
break;//PM_EVT_STORAGE_FULL
case PM_EVT_CONN_SEC_CONFIG_REQ:{
// A connected peer (central) is trying to pair, but the Peer Manager already has a bond
// for that peer. Setting allow_repairing to false rejects the pairing request.
// If this event is ignored (pm_conn_sec_config_reply is not called in the event
// handler), the Peer Manager assumes allow_repairing to be false.
pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config);
}
break;//PM_EVT_CONN_SEC_CONFIG_REQ
default:
break;
}
}
#if (NRF_SD_BLE_API_VERSION <= 2)
ble_error_t
btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist)
{
if (!btle_hasInitializedSecurity()) {
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
}
ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist);
if (err == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else if (err == NRF_ERROR_NULL) {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
} else {
return BLE_ERROR_INVALID_STATE;
}
}
#endif
bool
btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
{
/*
* Use a helper function from the Nordic SDK to test whether the BLE
* address can be generated using the IRK.
*/
return im_address_resolve(p_addr, p_irk);
}
void
btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address)
{
/* Set type to resolvable */
address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
/*
* Assign a random number to the most significant 3 bytes
* of the address.
*/
address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E;
address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F;
address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C;
/* Calculate the hash and store it in the top half of the address */
ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr);
}
#if (NRF_SD_BLE_API_VERSION >= 3)
ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList)
{
pm_peer_id_t peer_id;
ret_code_t ret;
pm_peer_data_bonding_t bond_data;
addrList.size = 0;
peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
/**
* Fill addresses list:
* Copy addresses from bond table, or
* for every private resolvable address in the bond table generate the resolvable address.
*/
while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) {
memset(&bond_data, 0x00, sizeof(bond_data));
// Read peer data from flash.
ret = pm_peer_data_bonding_load(peer_id, &bond_data);
if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) {
// Peer data could not be found in flash or peer ID is not valid.
return BLE_ERROR_UNSPECIFIED;
}
if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) {
btle_generateResolvableAddress(bond_data.peer_ble_id.id_info,
(ble_gap_addr_t &) addrList.addresses[addrList.size].address);
} else {
memcpy(&addrList.addresses[addrList.size].address,
&bond_data.peer_ble_id.id_addr_info.addr,
sizeof(addrList.addresses[0].address));
}
addrList.addresses[addrList.size].type = static_cast<BLEProtocol::AddressType_t> (bond_data.peer_ble_id.id_addr_info.addr_type);
addrList.size++;
// get next peer id
peer_id = pm_next_peer_id_get(peer_id);
}
return BLE_ERROR_NONE;
}
#endif
#endif // defined(S130) || defined(S132) || defined(S140)

View File

@ -0,0 +1,372 @@
/* 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 "custom_helper.h"
#include "../btle.h"
/*
* The current version of the soft-device doesn't handle duplicate 128-bit UUIDs
* very well. It is therefore necessary to filter away duplicates before
* passing long UUIDs to sd_ble_uuid_vs_add(). The following types and data
* structures involved in maintaining a local cache of 128-bit UUIDs.
*/
typedef struct {
UUID::LongUUIDBytes_t uuid;
uint8_t type;
} converted_uuid_table_entry_t;
static unsigned uuidTableEntries = 0; /* current usage of the table */
converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
void custom_reset_128bits_uuid_table() {
uuidTableEntries = 0;
}
/**
* lookup the cache of previously converted 128-bit UUIDs to find a type value.
* @param uuid base 128-bit UUID
* @param recoveredType the type field of the 3-byte nRF's uuid.
* @return true if a match is found.
*/
static bool
lookupConvertedUUIDTable(const UUID::LongUUIDBytes_t uuid, uint8_t *recoveredType)
{
unsigned i;
for (i = 0; i < uuidTableEntries; i++) {
unsigned byteIndex;
for (byteIndex = 0; byteIndex < UUID::LENGTH_OF_LONG_UUID; byteIndex++) {
/* Skip bytes 2 and 3, because they contain the shortUUID (16-bit) version of the
* long UUID; and we're comparing against the remainder. */
if ((byteIndex == 2) || (byteIndex == 3)) {
continue;
}
if (convertedUUIDTable[i].uuid[byteIndex] != uuid[byteIndex]) {
break;
}
}
if (byteIndex == UUID::LENGTH_OF_LONG_UUID) {
*recoveredType = convertedUUIDTable[i].type;
return true;
}
}
return false;
}
static void
addToConvertedUUIDTable(const UUID::LongUUIDBytes_t uuid, uint8_t type)
{
if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) {
return; /* recovery needed; or at least the user should be warned about this fact.*/
}
memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid, UUID::LENGTH_OF_LONG_UUID);
convertedUUIDTable[uuidTableEntries].uuid[2] = 0;
convertedUUIDTable[uuidTableEntries].uuid[3] = 0;
convertedUUIDTable[uuidTableEntries].type = type;
uuidTableEntries++;
}
/**
* The nRF transport has its own 3-byte representation of a UUID. If the user-
* specified UUID is 128-bits wide, then the UUID base needs to be added to the
* soft-device and converted to a 3-byte handle before being used further. This
* function is responsible for this translation of user-specified UUIDs into
* nRF's representation.
*
* @param[in] uuid
* user-specified UUID
* @return nRF
* 3-byte UUID (containing a type and 16-bit UUID) representation
* to be used with SVC calls.
*/
ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid)
{
ble_uuid_t nordicUUID;
nordicUUID.uuid = uuid.getShortUUID();
nordicUUID.type = BLE_UUID_TYPE_UNKNOWN; /* to be set below */
if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) {
nordicUUID.type = BLE_UUID_TYPE_BLE;
} else {
if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) {
nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID());
addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type);
}
}
return nordicUUID;
}
/**************************************************************************/
/*!
@brief Adds the base UUID to the custom service. All UUIDs used
by this service are based on this 128-bit UUID.
@note This UUID needs to be added to the SoftDevice stack before
adding the service's primary service via
'sd_ble_gatts_service_add'
@param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16)
@returns The UUID type.
A return value of 0 should be considered an error.
@retval 0x00 BLE_UUID_TYPE_UNKNOWN
@retval 0x01 BLE_UUID_TYPE_BLE
@retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN
@section EXAMPLE
@code
// Take note that bytes 2/3 are blank since these are used to identify
// the primary service and individual characteristics
#define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E"
uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE);
ASSERT(uuid_type > 0, ERROR_NOT_FOUND);
// We can now safely add the primary service and any characteristics
// for our custom service ...
@endcode
*/
/**************************************************************************/
uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
{
ble_uuid128_t base_uuid;
uint8_t uuid_type = 0;
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
base_uuid.uuid128[i] = p_uuid_base[i];
}
ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
return uuid_type;
}
/**************************************************************************/
/*!
*/
/**************************************************************************/
error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
ble_uuid_t *p_uuid)
{
UUID::LongUUIDBytes_t uuid_base_le;
for (uint8_t i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
uuid_base_le[i] = p_uuid_base[i];
}
ASSERT_STATUS( sd_ble_uuid_decode(UUID::LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Adds a new characteristic to the custom service, assigning
properties, a UUID add-on value, etc.
@param[in] service_handle
@param[in] p_uuid The 16-bit value to add to the base UUID
for this characteristic (normally >1
since 1 is typically used by the primary
service).
@param[in] char_props The characteristic properties, as
defined by ble_gatt_char_props_t
@param[in] max_length The maximum length of this characeristic
@param[in] has_variable_len Whether the characteristic data has
variable length.
@param[out] p_char_handle
@returns
@retval ERROR_NONE Everything executed normally
*/
/**************************************************************************/
error_t custom_add_in_characteristic(uint16_t service_handle,
ble_uuid_t *p_uuid,
uint8_t properties,
SecurityManager::SecurityMode_t requiredSecurity,
uint8_t *p_data,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen,
const uint8_t *presentationFormatDescriptorValuePtr,
uint16_t presentationFormatDescriptorValueLen,
bool readAuthorization,
bool writeAuthorization,
ble_gatts_char_handles_t *p_char_handle)
{
/* Characteristic metadata */
ble_gatts_attr_md_t cccd_md;
ble_gatt_char_props_t char_props;
memcpy(&char_props, &properties, 1);
if (char_props.notify || char_props.indicate) {
/* Notification requires cccd */
memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t));
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
}
ble_gatts_char_md_t char_md = {0};
char_md.char_props = char_props;
char_md.p_cccd_md =
(char_props.notify || char_props.indicate) ? &cccd_md : NULL;
if ((userDescriptionDescriptorValueLen > 0) && (userDescriptionDescriptorValuePtr != NULL)) {
char_md.p_char_user_desc = const_cast<uint8_t *>(userDescriptionDescriptorValuePtr);
char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen;
char_md.char_user_desc_size = userDescriptionDescriptorValueLen;
}
if ((presentationFormatDescriptorValueLen > 0) && (presentationFormatDescriptorValuePtr != NULL)) {
ASSERT_TRUE( sizeof(ble_gatts_char_pf_t) == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
ASSERT_TRUE( presentationFormatDescriptorValueLen == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
char_md.p_char_pf = const_cast<ble_gatts_char_pf_t *>(reinterpret_cast<const ble_gatts_char_pf_t *>(presentationFormatDescriptorValuePtr));
}
/* Attribute declaration */
ble_gatts_attr_md_t attr_md = {0};
attr_md.rd_auth = readAuthorization;
attr_md.wr_auth = writeAuthorization;
attr_md.vloc = BLE_GATTS_VLOC_STACK;
/* Always set variable size */
attr_md.vlen = has_variable_len;
if (char_props.read || char_props.notify || char_props.indicate) {
switch (requiredSecurity) {
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm);
break;
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm);
break;
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm);
break;
default:
break;
};
}
if (char_props.write || char_props.write_wo_resp) {
switch (requiredSecurity) {
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm);
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm);
break;
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm);
break;
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm);
break;
default:
break;
};
}
ble_gatts_attr_t attr_char_value = {0};
attr_char_value.p_uuid = p_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = length;
attr_char_value.max_len = max_length;
attr_char_value.p_value = p_data;
ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle,
&char_md,
&attr_char_value,
p_char_handle));
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Adds a new descriptor to the custom service, assigning
value, a UUID add-on value, etc.
@param[in] char_handle
@param[in] p_uuid The 16-bit value to add to the base UUID
for this descriptor (normally >1
since 1 is typically used by the primary
service).
@param[in] max_length The maximum length of this descriptor
@param[in] has_variable_len Whether the characteristic data has
variable length.
@returns
@retval ERROR_NONE Everything executed normally
*/
/**************************************************************************/
error_t custom_add_in_descriptor(uint16_t char_handle,
ble_uuid_t *p_uuid,
uint8_t *p_data,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
uint16_t *p_desc_handle)
{
/* Descriptor metadata */
ble_gatts_attr_md_t desc_md = {0};
desc_md.vloc = BLE_GATTS_VLOC_STACK;
/* Always set variable size */
desc_md.vlen = has_variable_len;
/* Make it readable and writable */
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm);
ble_gatts_attr_t attr_desc = {0};
attr_desc.p_uuid = p_uuid;
attr_desc.p_attr_md = &desc_md;
attr_desc.init_len = length;
attr_desc.max_len = max_length;
attr_desc.p_value = p_data;
ASSERT_STATUS ( sd_ble_gatts_descriptor_add(char_handle,
&attr_desc,
p_desc_handle));
return ERROR_NONE;
}

View File

@ -0,0 +1,70 @@
/* 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.
*/
#ifndef _CUSTOM_HELPER_H_
#define _CUSTOM_HELPER_H_
#include "common/common.h"
#include "headers/nrf_ble.h"
#include "ble/UUID.h"
#include "ble/GattCharacteristic.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Reset the table of 128bits uuids.
* This table is used to keep track of vendors uuids added to the softdevice.
* It is important to reset it before disabling the softdevice otherwise the
* next time the softdevice will be enabled, this table will not be synchronmized
* with the softdevice table.
*/
void custom_reset_128bits_uuid_table();
uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base);
error_t custom_decode_uuid(uint8_t const *const p_uuid_base,
ble_uuid_t *p_uuid);
ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid);
error_t custom_add_in_characteristic(uint16_t service_handle,
ble_uuid_t *p_uuid,
uint8_t properties,
SecurityManager::SecurityMode_t requiredSecurity,
uint8_t *p_data,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen,
const uint8_t *presentationFormatDescriptorValuePtr,
uint16_t presentationFormatDescriptorValueLen,
bool readAuthorization,
bool writeAuthorization,
ble_gatts_char_handles_t *p_char_handle);
error_t custom_add_in_descriptor(uint16_t char_handle,
ble_uuid_t *p_uuid,
uint8_t *p_data,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
uint16_t *p_desc_handle);
#ifdef __cplusplus
}
#endif
#endif // ifndef _CUSTOM_HELPER_H_

View File

@ -0,0 +1,103 @@
/**************************************************************************/
/*!
@file ansi_esc_code.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _ANSI_ESC_CODE_H_
#define _ANSI_ESC_CODE_H_
#ifdef __cplusplus
extern "C" {
#endif
#define CSI_CODE(seq) "\33[" seq
#define CSI_SGR(x) CSI_CODE(#x) "m"
//------------- Cursor movement -------------//
#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A")
#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B")
#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C")
#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D")
#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E")
#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F")
#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H")
#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J")
#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K")
/** text color */
#define ANSI_TEXT_BLACK CSI_SGR(30)
#define ANSI_TEXT_RED CSI_SGR(31)
#define ANSI_TEXT_GREEN CSI_SGR(32)
#define ANSI_TEXT_YELLOW CSI_SGR(33)
#define ANSI_TEXT_BLUE CSI_SGR(34)
#define ANSI_TEXT_MAGENTA CSI_SGR(35)
#define ANSI_TEXT_CYAN CSI_SGR(36)
#define ANSI_TEXT_WHITE CSI_SGR(37)
#define ANSI_TEXT_DEFAULT CSI_SGR(39)
/** background color */
#define ANSI_BG_BLACK CSI_SGR(40)
#define ANSI_BG_RED CSI_SGR(41)
#define ANSI_BG_GREEN CSI_SGR(42)
#define ANSI_BG_YELLOW CSI_SGR(43)
#define ANSI_BG_BLUE CSI_SGR(44)
#define ANSI_BG_MAGENTA CSI_SGR(45)
#define ANSI_BG_CYAN CSI_SGR(46)
#define ANSI_BG_WHITE CSI_SGR(47)
#define ANSI_BG_DEFAULT CSI_SGR(49)
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_ANSI_ESC_CODE_H_ */
/** @} */

View File

@ -0,0 +1,197 @@
/**************************************************************************/
/*!
@file assertion.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _ASSERTION_H_
#define _ASSERTION_H_
#include "projectconfig.h"
#ifdef __cplusplus
extern "C"
{
#endif
static inline void debugger_breakpoint(void) ATTR_ALWAYS_INLINE;
static inline void debugger_breakpoint(void)
{
#ifndef _TEST_
__asm("BKPT #0\n");
#endif
}
//--------------------------------------------------------------------+
// Compile-time Assert
//--------------------------------------------------------------------+
#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
#define _ASSERT_COUNTER __COUNTER__
#else
#define _ASSERT_COUNTER __LINE__
#endif
#define ASSERT_STATIC(const_expr, message) enum { XSTRING_CONCAT_(static_assert_, _ASSERT_COUNTER) = 1/(!!(const_expr)) }
//--------------------------------------------------------------------+
// Assert Helper
//--------------------------------------------------------------------+
//#ifndef _TEST_
// #define ASSERT_MESSAGE(format, ...) _PRINTF("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
//#else
// #define ASSERT_MESSAGE(format, ...) _PRINTF("%d:note: Assert " format "\n", __LINE__, __VA_ARGS__)
//#endif
#if CFG_DEBUG == 3
#define ASSERT_MESSAGE(format, ...) debugger_breakpoint()
#elif CFG_DEBUG == 2
#define ASSERT_MESSAGE(format, ...) printf("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define ASSERT_MESSAGE(format, ...)
#endif
#define ASSERT_ERROR_HANDLER(x, para) \
return (x)
#define ASSERT_DEFINE_WITH_HANDLER(error_handler, handler_para, setup_statement, condition, error, format, ...) \
do{\
setup_statement;\
if (!(condition)) {\
ASSERT_MESSAGE(format, __VA_ARGS__);\
error_handler(error, handler_para);\
}\
}while(0)
#define ASSERT_DEFINE(...) ASSERT_DEFINE_WITH_HANDLER(ASSERT_ERROR_HANDLER, NULL, __VA_ARGS__)
//--------------------------------------------------------------------+
// error_t Status Assert TODO use ASSERT_DEFINE
//--------------------------------------------------------------------+
#define ASSERT_STATUS_MESSAGE(sts, message) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, status, "%s: %s", ErrorStr[status], message)
#define ASSERT_STATUS(sts) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, status, "error = %d", status)
#define ASSERT_STATUS_RET_VOID(sts) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, (void) 0, "error = %d", status)
//--------------------------------------------------------------------+
// Logical Assert
//--------------------------------------------------------------------+
#define ASSERT_TRUE(condition , error) ASSERT_DEFINE( , (condition), error, "%s", "evaluated to false")
#define ASSERT_FALSE(condition , error) ASSERT_DEFINE( ,!(condition), error, "%s", "evaluated to true")
//--------------------------------------------------------------------+
// Pointer Assert
//--------------------------------------------------------------------+
#define ASSERT_PTR(...) ASSERT_PTR_NOT_NULL(__VA_ARGS__)
#define ASSERT_PTR_NOT_NULL(pointer, error) ASSERT_DEFINE( , NULL != (pointer), error, "%s", "pointer is NULL")
#define ASSERT_PTR_NULL(pointer, error) ASSERT_DEFINE( , NULL == (pointer), error, "%s", "pointer is not NULL")
//--------------------------------------------------------------------+
// Integral Assert
//--------------------------------------------------------------------+
#define ASSERT_XXX_EQUAL(type_format, expected, actual, error) \
ASSERT_DEFINE(\
uint32_t exp = (expected); uint32_t act = (actual),\
exp==act,\
error,\
"expected " type_format ", actual " type_format, exp, act)
#define ASSERT_XXX_WITHIN(type_format, lower, upper, actual, error) \
ASSERT_DEFINE(\
uint32_t low = (lower); uint32_t up = (upper); uint32_t act = (actual),\
(low <= act) && (act <= up),\
error,\
"expected within " type_format " - " type_format ", actual " type_format, low, up, act)
//--------------------------------------------------------------------+
// Integer Assert
//--------------------------------------------------------------------+
#define ASSERT_INT(...) ASSERT_INT_EQUAL(__VA_ARGS__)
#define ASSERT_INT_EQUAL(...) ASSERT_XXX_EQUAL("%d", __VA_ARGS__)
#define ASSERT_INT_WITHIN(...) ASSERT_XXX_WITHIN("%d", __VA_ARGS__)
//--------------------------------------------------------------------+
// Hex Assert
//--------------------------------------------------------------------+
#define ASSERT_HEX(...) ASSERT_HEX_EQUAL(__VA_ARGS__)
#define ASSERT_HEX_EQUAL(...) ASSERT_XXX_EQUAL("0x%x", __VA_ARGS__)
#define ASSERT_HEX_WITHIN(...) ASSERT_XXX_WITHIN("0x%x", __VA_ARGS__)
//--------------------------------------------------------------------+
// Bin Assert
//--------------------------------------------------------------------+
#define BIN8_PRINTF_PATTERN "%d%d%d%d%d%d%d%d"
#define BIN8_PRINTF_CONVERT(byte) \
((byte) & 0x80 ? 1 : 0), \
((byte) & 0x40 ? 1 : 0), \
((byte) & 0x20 ? 1 : 0), \
((byte) & 0x10 ? 1 : 0), \
((byte) & 0x08 ? 1 : 0), \
((byte) & 0x04 ? 1 : 0), \
((byte) & 0x02 ? 1 : 0), \
((byte) & 0x01 ? 1 : 0)
#define ASSERT_BIN8(...) ASSERT_BIN8_EQUAL(__VA_ARGS__)
#define ASSERT_BIN8_EQUAL(expected, actual, error)\
ASSERT_DEFINE(\
uint8_t exp = (expected); uint8_t act = (actual),\
exp==act,\
error,\
"expected " BIN8_PRINTF_PATTERN ", actual " BIN8_PRINTF_PATTERN, BIN8_PRINTF_CONVERT(exp), BIN8_PRINTF_CONVERT(act) )
#ifdef __cplusplus
}
#endif
#endif /* _ASSERTION_H_ */
/** @} */

View File

@ -0,0 +1,96 @@
/**************************************************************************/
/*!
@file binary.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _BINARY_H_
#define _BINARY_H_
#ifdef __cplusplus
extern "C" {
#endif
/// n-th Bit
#define BIT(n) (1 << (n))
/// set n-th bit of x to 1
#define BIT_SET(x, n) ( (x) | BIT(n) )
/// clear n-th bit of x
#define BIT_CLR(x, n) ( (x) & (~BIT(n)) )
/// test n-th bit of x
#define BIT_TEST(x, n) ( (x) & BIT(n) )
#if defined(__GNUC__) && !defined(__CC_ARM) // keil does not support binary format
#define BIN8(x) ((uint8_t) (0b##x))
#define BIN16(b1, b2) ((uint16_t) (0b##b1##b2))
#define BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4))
#else
// internal macro of B8, B16, B32
#define _B8__(x) (((x&0x0000000FUL)?1:0) \
+((x&0x000000F0UL)?2:0) \
+((x&0x00000F00UL)?4:0) \
+((x&0x0000F000UL)?8:0) \
+((x&0x000F0000UL)?16:0) \
+((x&0x00F00000UL)?32:0) \
+((x&0x0F000000UL)?64:0) \
+((x&0xF0000000UL)?128:0))
#define BIN8(d) ((uint8_t) _B8__(0x##d##UL))
#define BIN16(dmsb,dlsb) (((uint16_t)BIN8(dmsb)<<8) + BIN8(dlsb))
#define BIN32(dmsb,db2,db3,dlsb) \
(((uint32_t)BIN8(dmsb)<<24) \
+ ((uint32_t)BIN8(db2)<<16) \
+ ((uint32_t)BIN8(db3)<<8) \
+ BIN8(dlsb))
#endif
#ifdef __cplusplus
}
#endif
#endif /* _BINARY_H_ */
/** @} */

View File

@ -0,0 +1,151 @@
/**************************************************************************/
/*!
@file ble_error.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief Error Header
*
* \note TBD
*/
/** \ingroup Group_Common
* \defgroup Group_Error Error Codes
* @{
*/
#ifndef _BLE_ERROR_H_
#define _BLE_ERROR_H_
#include "projectconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
/*=======================================================================
NORDIC GLOBAL ERRORS 0x0000 .. 0x00FF
-----------------------------------------------------------------------
Errors mapped from nrf_error.h
-----------------------------------------------------------------------*/
ERROR_NONE = 0x0000 , ///< Successful command
ERROR_SVC_HANDLER_MISSING = 0x0001 , ///< SVC handler is missing
ERROR_SOFTDEVICE_NOT_ENABLED = 0x0002 , ///< SoftDevice has not been enabled
ERROR_INTERNAL = 0x0003 , ///< Internal Error
ERROR_NO_MEM = 0x0004 , ///< No Memory for operation
ERROR_NOT_FOUND = 0x0005 , ///< Not found
ERROR_NOT_SUPPORTED = 0x0006 , ///< Not supported
ERROR_INVALID_PARAM = 0x0007 , ///< Invalid Parameter
ERROR_INVALID_STATE = 0x0008 , ///< Invalid state, operation disallowed in this state
ERROR_INVALID_LENGTH = 0x0009 , ///< Invalid Length
ERROR_INVALID_FLAGS = 0x000A , ///< Invalid Flags
ERROR_INVALID_DATA = 0x000B , ///< Invalid Data
ERROR_DATA_SIZE = 0x000C , ///< Data size exceeds limit
ERROR_TIMEOUT = 0x000D , ///< Operation timed out
ERROR_NULL = 0x000E , ///< Null Pointer
ERROR_FORBIDDEN = 0x000F , ///< Forbidden Operation
ERROR_INVALID_ADDR = 0x0010 , ///< Bad Memory Address
ERROR_BUSY = 0x0011 , ///< Busy
/*=======================================================================*/
ERROR_INVALIDPARAMETER = 0x0100 , /**< An invalid parameter value was provided */
ERROR_I2C_XFER_FAILED = 0x0101 , /**< an failed attempt to make I2C transfer */
/*=======================================================================
SIMPLE BINARY PROTOCOL ERRORS 0x0120 .. 0x013F
-----------------------------------------------------------------------
Errors relating to the simple binary protocol (/src//protocol)
-----------------------------------------------------------------------*/
ERROR_PROT_INVALIDMSGTYPE = 0x121, /**< Unexpected msg type encountered */
ERROR_PROT_INVALIDCOMMANDID = 0x122, /**< Unknown or out of range command ID */
ERROR_PROT_INVALIDPAYLOAD = 0x123, /**< Message payload has a problem (invalid len, etc.) */
/*=======================================================================*/
//------------- based on Nordic SDM nrf_error_sdm.h -------------//
ERROR_SDM_LFCLK_SOURCE_UNKNOWN = 0x1000 , ///< Unknown lfclk source
ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION = 0x1001 , ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts)
ERROR_SDM_INCORRECT_CLENR0 = 0x1002 , ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing)
//------------- based on Nordic SOC nrf_error_soc.h -------------//
/* Mutex Errors */
ERROR_SOC_MUTEX_ALREADY_TAKEN = 0x2000 , ///< Mutex already taken
/* NVIC errors */
ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE = 0x2001 , ///< NVIC interrupt not available
ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED = 0x2002 , ///< NVIC interrupt priority not allowed
ERROR_SOC_NVIC_SHOULD_NOT_RETURN = 0x2003 , ///< NVIC should not return
/* Power errors */
ERROR_SOC_POWER_MODE_UNKNOWN = 0x2004 , ///< Power mode unknown
ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN = 0x2005 , ///< Power POF threshold unknown
ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN = 0x2006 , ///< Power off should not return
/* Rand errors */
ERROR_SOC_RAND_NOT_ENOUGH_VALUES = 0x2007 , ///< RAND not enough values
/* PPI errors */
ERROR_SOC_PPI_INVALID_CHANNEL = 0x2008 , ///< Invalid PPI Channel
ERROR_SOC_PPI_INVALID_GROUP = 0x2009 , ///< Invalid PPI Group
//------------- based on Nordic STK (ble) ble_err.h -------------//
ERROR_BLE_INVALID_CONN_HANDLE = 0x3001 , /**< Invalid connection handle. */
ERROR_BLE_INVALID_ATTR_HANDLE = 0x3002 , /**< Invalid attribute handle. */
ERROR_BLE_NO_TX_BUFFERS = 0x3003 , /**< Buffer capacity exceeded. */
// L2CAP
ERROR_BLE_L2CAP_CID_IN_USE = 0x3100 , /**< CID already in use. */
// GAP
ERROR_BLE_GAP_UUID_LIST_MISMATCH = 0x3200 , /**< UUID list does not contain an integral number of UUIDs. */
ERROR_BLE_GAP_DISCOVERABLE_WITH_WHITELIST = 0x3201 , /**< Use of Whitelist not permitted with discoverable advertising. */
ERROR_BLE_GAP_INVALID_BLE_ADDR = 0x3202 , /**< The upper two bits of the address do not correspond to the specified address type. */
// GATTC
ERROR_BLE_GATTC_PROC_NOT_PERMITTED = 0x3300 ,
// GATTS
ERROR_BLEGATTS_INVALID_ATTR_TYPE = 0x3400 , /**< Invalid attribute type. */
ERROR_BLEGATTS_SYS_ATTR_MISSING = 0x3401 , /**< System Attributes missing. */
}error_t;
#ifdef __cplusplus
}
#endif
#endif /* _BLE_ERROR_H_ */
/** @} */

View File

@ -0,0 +1,236 @@
/**************************************************************************/
/*!
@file common.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \defgroup Group_Common Common Files
* @{
*
* \defgroup Group_CommonH common.h
*
* @{
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// INCLUDES
//--------------------------------------------------------------------+
//------------- Standard Header -------------//
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
//------------- General Header -------------//
#include "projectconfig.h"
#include "compiler.h"
#include "assertion.h"
#include "binary.h"
#include "ble_error.h"
//------------- MCU header -------------//
//#include "nrf.h"
//--------------------------------------------------------------------+
// TYPEDEFS
//--------------------------------------------------------------------+
typedef unsigned char byte_t;
typedef float float32_t;
typedef double float64_t;
//--------------------------------------------------------------------+
// MACROS
//--------------------------------------------------------------------+
#define STRING_(x) #x // stringify without expand
#define XSTRING_(x) STRING_(x) // expand then stringify
#define STRING_CONCAT_(a, b) a##b // concat without expand
#define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat
#define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff))
#define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff))
#define U16_TO_U8S_BE(u16) U16_HIGH_U8(u16), U16_LOW_U8(u16)
#define U16_TO_U8S_LE(u16) U16_LOW_U8(u16), U16_HIGH_U8(u16)
#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB
#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff))
#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff))
#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB
#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32)
#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32)
//--------------------------------------------------------------------+
// INLINE FUNCTION
//--------------------------------------------------------------------+
#define memclr_(buffer, size) memset(buffer, 0, size)
//------------- Conversion -------------//
/// form an uint32_t from 4 x uint8_t
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4)
{
return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
}
static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint8_t u16_high_u8(uint16_t u16)
{
return (uint8_t) ((u16 >> 8) & 0x00ff);
}
static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint8_t u16_low_u8(uint16_t u16)
{
return (uint8_t) (u16 & 0x00ff);
}
//------------- Min -------------//
static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t min8_of(uint8_t x, uint8_t y)
{
return (x < y) ? x : y;
}
static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint16_t min16_of(uint16_t x, uint16_t y)
{
return (x < y) ? x : y;
}
static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t min32_of(uint32_t x, uint32_t y)
{
return (x < y) ? x : y;
}
//------------- Max -------------//
static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t max32_of(uint32_t x, uint32_t y)
{
return (x > y) ? x : y;
}
//------------- Align -------------//
static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align32 (uint32_t value)
{
return (value & 0xFFFFFFE0UL);
}
static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align16 (uint32_t value)
{
return (value & 0xFFFFFFF0UL);
}
static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align_n (uint32_t alignment, uint32_t value)
{
return value & (~(alignment-1));
}
static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align4k (uint32_t value)
{
return (value & 0xFFFFF000UL);
}
static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t offset4k(uint32_t value)
{
return (value & 0xFFFUL);
}
//------------- Mathematics -------------//
/// inclusive range checking
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper)
{
return (lower <= value) && (value <= upper);
}
/// exclusive range checking
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper)
{
return (lower < value) && (value < upper);
}
static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t log2_of(uint32_t value)
{
uint8_t result = 0; // log2 of a value is its MSB's position
while (value >>= 1)
{
result++;
}
return result;
}
// return the number of set bits in value
static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t cardinality_of(uint32_t value)
{
// Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only
// the high bit set, then it will only go once through the loop
// Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie)
// mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method
// "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and
// published in 1964 in a book edited by Beckenbach.)"
uint8_t count;
for (count = 0; value; count++)
{
value &= value - 1; // clear the least significant bit set
}
return count;
}
#ifdef __cplusplus
}
#endif
#endif /* _COMMON_H_ */
/** @} */
/** @} */

View File

@ -0,0 +1,160 @@
/**************************************************************************/
/*!
@file compiler.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief GCC Header
*/
/** \ingroup Group_Compiler
* \defgroup Group_GCC GNU GCC
* @{
*/
#ifndef _COMPILER_GCC_H_
#define _COMPILER_GCC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "projectconfig.h"
//#ifndef __GNUC__
// #define ATTR_ALWAYS_INLINE
// #define ATTR_CONST
//#else
#ifdef _TEST_
#define ATTR_ALWAYS_INLINE
#define STATIC_
#define INLINE_
#else
#define STATIC_ static
#define INLINE_ inline
#if CFG_DEBUG == 3
#define ATTR_ALWAYS_INLINE // no inline for debug = 3
#endif
#endif
#ifdef __GNUC__
#define ALIGN_OF(x) __alignof__(x)
/// Normally, the compiler places the objects it generates in sections like data or bss & function in text. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a particular section
#define ATTR_SECTION(section) __attribute__ ((#section))
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error that includes message is diagnosed. This is useful for compile-time checking
#define ATTR_ERROR(Message) __attribute__ ((error(Message)))
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning that includes message is diagnosed. This is useful for compile-time checking
#define ATTR_WARNING(Message) __attribute__ ((warning(Message)))
/**
* \defgroup Group_VariableAttr Variable Attributes
* @{
*/
/// This attribute specifies a minimum alignment for the variable or structure field, measured in bytes
#define ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
/// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute
#define ATTR_PACKED __attribute__ ((packed))
#define ATTR_PREPACKED
#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed))
/** @} */
/**
* \defgroup Group_FuncAttr Function Attributes
* @{
*/
#ifndef ATTR_ALWAYS_INLINE
/// Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level is specified
#define ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#endif
/// The nonnull attribute specifies that some function parameters should be non-null pointers. f the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. All pointer arguments are marked as non-null
#define ATTR_NON_NULL __attribute__ ((nonull))
/// Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure
#define ATTR_PURE __attribute__ ((pure))
/// Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory.
/// Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void
#define ATTR_CONST __attribute__ ((const))
/// The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses
#define ATTR_DEPRECATED __attribute__ ((deprecated))
/// Same as the deprecated attribute with optional message in the warning
#define ATTR_DEPRECATED_MESS(mess) __attribute__ ((deprecated(mess)))
/// The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions that can be overridden in user code
#define ATTR_WEAK __attribute__ ((weak))
/// The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified
#define ATTR_ALIAS(func) __attribute__ ((alias(#func)))
/// The weakref attribute marks a declaration as a weak reference. It is equivalent with weak + alias attribute, but require function is static
#define ATTR_WEAKREF(func) __attribute__ ((weakref(#func)))
/// The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. This is useful for functions where not checking the result is either a security problem or always a bug
#define ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
/// This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.
#define ATTR_USED __attribute__ ((used))
/// This attribute, attached to a function, means that the function is meant to be possibly unused. GCC does not produce a warning for this function.
#define ATTR_UNUSED __attribute__ ((unused))
#elif defined (__ICCARM__) //IAR
#define ATTR_ALWAYS_INLINE // IAR dosn't provide such a syntax extension in function's prototypes.
#define ATTR_CONST // IAR dosn't provide such a syntax extension in function's prototypes.
#endif
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _COMPILER_GCC_H_ */
/// @}

View File

@ -0,0 +1,257 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-2017 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.
*/
#ifndef BLE_NORDIC_PAL_GATT_CLIENT_H_
#define BLE_NORDIC_PAL_GATT_CLIENT_H_
#include "ble/pal/PalGattClient.h"
#include "ble/blecommon.h"
#include "ble/UUID.h"
#include "headers/nrf_ble.h"
#include "headers/ble_gatt.h"
#include "headers/ble_types.h"
#include "btle.h"
namespace ble {
namespace pal {
namespace vendor {
namespace nordic {
/**
* Implementation of pal::GattClient for the Nordic stack.
*/
class nRF5XGattClient : public ble::pal::GattClient {
public:
nRF5XGattClient();
virtual ~nRF5XGattClient();
/**
* see pal::GattClient::initialize .
*/
virtual ble_error_t initialize();
/**
* see pal::GattClient::terminate .
*/
virtual ble_error_t terminate();
/**
* see pal::GattClient::exchange_mtu .
*/
virtual ble_error_t exchange_mtu(connection_handle_t connection);
/**
* see pal::GattClient::get_mtu_size .
*/
virtual ble_error_t get_mtu_size(
connection_handle_t connection_handle, uint16_t& mtu_size
);
/**
* see pal::GattClient::discover_primary_service .
*/
virtual ble_error_t discover_primary_service(
connection_handle_t connection,
attribute_handle_t discovery_range_begining
);
/**
* see pal::GattClient::discover_primary_service_by_service_uuid .
*/
virtual ble_error_t discover_primary_service_by_service_uuid(
connection_handle_t connection_handle,
attribute_handle_t discovery_range_beginning,
const UUID& uuid
);
/**
* see pal::GattClient::find_included_service .
*/
virtual ble_error_t find_included_service(
connection_handle_t connection_handle,
attribute_handle_range_t service_range
);
/**
* see pal::GattClient::discover_characteristics_of_a_service .
*/
virtual ble_error_t discover_characteristics_of_a_service(
connection_handle_t connection_handle,
attribute_handle_range_t discovery_range
);
/**
* see pal::GattClient::discover_characteristics_descriptors .
*/
virtual ble_error_t discover_characteristics_descriptors(
connection_handle_t connection_handle,
attribute_handle_range_t descriptors_discovery_range
);
/**
* see pal::GattClient::read_attribute_value .
*/
virtual ble_error_t read_attribute_value(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle
);
/**
* see pal::GattClient::read_using_characteristic_uuid .
*/
virtual ble_error_t read_using_characteristic_uuid(
connection_handle_t connection_handle,
attribute_handle_range_t read_range,
const UUID& uuid
);
/**
* see pal::GattClient::read_attribute_blob .
*/
virtual ble_error_t read_attribute_blob(
connection_handle_t connection,
attribute_handle_t attribute_handle,
uint16_t offset
);
/**
* see pal::GattClient::read_multiple_characteristic_values .
*/
virtual ble_error_t read_multiple_characteristic_values(
connection_handle_t connection,
const ArrayView<const attribute_handle_t>& characteristic_handles
);
/**
* see pal::GattClient::write_without_response .
*/
virtual ble_error_t write_without_response(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const ArrayView<const uint8_t>& value
);
/**
* see pal::GattClient::signed_write_without_response .
*/
virtual ble_error_t signed_write_without_response(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const ArrayView<const uint8_t>& value
);
/**
* see pal::GattClient::write_attribute .
*/
virtual ble_error_t write_attribute(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
const ArrayView<const uint8_t>& value
);
/**
* see pal::GattClient::queue_prepare_write .
*/
virtual ble_error_t queue_prepare_write(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const ArrayView<const uint8_t>& value,
uint16_t offset
);
/**
* see pal::GattClient::execute_write_queue .
*/
virtual ble_error_t execute_write_queue(
connection_handle_t connection_handle,
bool execute
);
// singleton of the ARM Cordio client
static nRF5XGattClient& get_client();
/**
* Function call from btle.cpp
*
* Do not call directly.
*/
static void handle_events(const ble_evt_t *p_ble_evt);
/**
* Called by btle.cpp when a disconnection happens.
*/
static void handle_connection_termination(connection_handle_t connection);
private:
struct GattProcedure;
struct RegularGattProcedure;
struct DiscoverPrimaryServiceProcedure;
struct DiscoverPrimaryServiceByUUIDProcedure;
struct FindIncludedServicesProcedure;
struct DiscoverCharacteristicsProcedure;
struct DiscoverDescriptorsProcedure;
struct ReadAttributeProcedure;
struct ReadUsingCharacteristicUUIDProcedure;
struct ReadAttributeBlobProcedure;
struct ReadMultipleCharacteristicsProcedure;
struct WriteAttributeProcedure;
struct QueuePrepareWriteProcedure;
struct ExecuteWriteQueueProcedure;
template<typename ProcType, typename A0>
ble_error_t launch_procedure(connection_handle_t connection, const A0& a0);
template<typename ProcType, typename A0, typename A1>
ble_error_t launch_procedure(
connection_handle_t connection, const A0& a0, const A1& a1
);
template<typename ProcType, typename A0, typename A1, typename A2>
ble_error_t launch_procedure(
connection_handle_t connection,
const A0& a0, const A1& a1, const A2& a2
);
template<typename ProcType, typename A0, typename A1, typename A2, typename A3>
ble_error_t launch_procedure(
connection_handle_t connection,
const A0& a0, const A1& a1, const A2& a2, const A3& a3
);
GattProcedure* get_procedure(connection_handle_t) const;
bool register_procedure(GattProcedure*);
bool remove_procedure(GattProcedure*);
void handle_procedure_event(const ble_evt_t &evt);
void handle_hvx_event(const ble_evt_t &evt);
void handle_timeout_event(const ble_evt_t &evt);
static const size_t max_procedures_count =
CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT;
// Note: Ideally we would have used an array of variant here
GattProcedure* _procedures[max_procedures_count];
};
} // nordic
} // vendor
} // pal
} // ble
#endif /* BLE_NORDIC_PAL_GATT_CLIENT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,285 @@
/* 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.
*/
#ifndef __NRF5x_GAP_H__
#define __NRF5x_GAP_H__
#ifdef YOTTA_CFG_MBED_OS
#include "mbed-drivers/mbed.h"
#else
#include "mbed.h"
#endif
#ifndef YOTTA_CFG_WHITELIST_MAX_SIZE
#define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT
#elif YOTTA_CFG_WHITELIST_MAX_SIZE > BLE_GAP_WHITELIST_ADDR_MAX_COUNT
#undef YOTTA_CFG_WHITELIST_MAX_SIZE
#define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT
#endif
#ifndef YOTTA_CFG_IRK_TABLE_MAX_SIZE
#if (NRF_SD_BLE_API_VERSION >= 3)
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT
#else
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT
#endif
#elif YOTTA_CFG_IRK_TABLE_MAX_SIZE > BLE_GAP_WHITELIST_IRK_MAX_COUNT
#undef YOTTA_CFG_IRK_TABLE_MAX_SIZE
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT
#endif
#include "ble/blecommon.h"
#include "headers/nrf_ble.h"
#include "ble/GapAdvertisingParams.h"
#include "ble/GapAdvertisingData.h"
#include "ble/Gap.h"
#include "ble/GapScanningParams.h"
#include "nrf_soc.h"
extern "C" {
#include "ble_radio_notification.h"
#include "app_util_platform.h"
}
#include "btle_security.h"
void radioNotificationStaticCallback(bool param);
/**************************************************************************/
/*!
\brief
*/
/**************************************************************************/
class nRF5xGap : public Gap
{
public:
/* Functions that must be implemented from Gap */
virtual ble_error_t setAddress(AddressType_t type, const Address_t address);
virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address);
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &);
virtual uint16_t getMinAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);}
virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {
#if (NRF_SD_BLE_API_VERSION >= 5) // In SD v5+, non connectable advertising interval is the same as connectable advertising interval
// The Mbed infrastructure expects 100ms+ - so for now return that
// return getMinAdvertisingInterval();
// FIXME infrastructure
return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON;
#else
return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);
#endif
}
virtual uint16_t getMaxAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);}
virtual ble_error_t startAdvertising(const GapAdvertisingParams &);
virtual ble_error_t stopAdvertising(void);
virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams);
virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason);
virtual ble_error_t disconnect(DisconnectionReason_t reason);
virtual ble_error_t setDeviceName(const uint8_t *deviceName);
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance);
virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP);
virtual ble_error_t setTxPower(int8_t txPower);
virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP);
void setConnectionHandle(uint16_t con_handle);
uint16_t getConnectionHandle(void);
virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params);
virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params);
virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params);
virtual ble_error_t reset(void);
/*
* The following functions are part of the whitelisting experimental API.
* Therefore, this functionality can change in the near future.
*/
virtual uint8_t getMaxWhitelistSize(void) const;
virtual ble_error_t getWhitelist(Gap::Whitelist_t &whitelistOut) const;
virtual ble_error_t setWhitelist(const Gap::Whitelist_t &whitelistIn);
virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode);
virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode);
virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode);
virtual Gap::AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const;
virtual Gap::ScanningPolicyMode_t getScanningPolicyMode(void) const;
virtual Gap::InitiatorPolicyMode_t getInitiatorPolicyMode(void) const;
virtual ble_error_t initRadioNotification(void) {
if (ble_radio_notification_init(APP_IRQ_PRIORITY_HIGH /*MID*/, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationStaticCallback) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
}
return BLE_ERROR_UNSPECIFIED;
}
/* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams);
virtual ble_error_t stopScan(void);
#endif
private:
/*
* Whitelisting API related structures and helper functions.
*/
/* Policy modes set by the user. By default these are set to ignore the whitelist */
Gap::AdvertisingPolicyMode_t advertisingPolicyMode;
Gap::ScanningPolicyMode_t scanningPolicyMode;
/* Internal representation of a whitelist */
uint8_t whitelistAddressesSize;
ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE];
#if (NRF_SD_BLE_API_VERSION <= 2)
/*
* An internal function used to populate the ble_gap_whitelist_t that will be used by
* the SoftDevice for filtering requests. This function is needed because for the BLE
* API the whitelist is just a collection of keys, but for the stack it also includes
* the IRK table.
*/
ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist);
#endif
#if (NRF_SD_BLE_API_VERSION >= 3)
/* internal type for passing a whitelist and a identities list. */
typedef struct
{
ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
uint32_t addrs_cnt;
ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
uint32_t identities_cnt;
} GapWhiteAndIdentityList_t;
/* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/
ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
/* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/
ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
/* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice.
*
* This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */
ble_error_t updateWhiteAndIdentityListInStack(void);
#endif
private:
bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */
Timeout radioNotificationTimeout;
/*
* A helper function to post radio notification callbacks with low interrupt priority.
*/
void postRadioNotificationCallback(void) {
#ifdef YOTTA_CFG_MBED_OS
/*
* In mbed OS, all user-facing BLE events (interrupts) are posted to the
* MINAR scheduler to be executed as callbacks in thread mode. MINAR guards
* its critical sections from interrupts by acquiring CriticalSectionLock,
* which results in a call to sd_nvic_critical_region_enter(). Thus, it is
* safe to invoke MINAR APIs from interrupt context as long as those
* interrupts are blocked by sd_nvic_critical_region_enter().
*
* Radio notifications are a special case for the above. The Radio
* Notification IRQ is handled at a very high priority--higher than the
* level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification
* events can preempt MINAR's critical sections. Using MINAR APIs (such as
* posting an event) directly in processRadioNotification() may result in a
* race condition ending in a hard-fault.
*
* The solution is to *not* call MINAR APIs directly from the Radio
* Notification handling; i.e. to do the bulk of RadioNotification
* processing at a reduced priority which respects MINAR's critical
* sections. Unfortunately, on a cortex-M0, there is no clean way to demote
* priority for the currently executing interrupt--we wouldn't want to
* demote the radio notification handling anyway because it is sensitive to
* timing, and the system expects to finish this handling very quickly. The
* workaround is to employ a Timeout to trigger
* postRadioNotificationCallback() after a very short delay (~0 us) and post
* the MINAR callback that context.
*
* !!!WARNING!!! Radio notifications are very time critical events. The
* current solution is expected to work under the assumption that
* postRadioNotificationCalback() will be executed BEFORE the next radio
* notification event is generated.
*/
minar::Scheduler::postCallback(
mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam)
);
#else
/*
* In mbed classic, all user-facing BLE events execute callbacks in interrupt
* mode. Radio Notifications are a special case because its IRQ is handled at
* a very high priority. Thus Radio Notification events can preempt other
* operations that require interaction with the SoftDevice such as advertising
* payload updates and changing the Gap state. Therefore, executing a Radio
* Notification callback directly from processRadioNotification() may result
* in a race condition ending in a hard-fault.
*
* The solution is to *not* execute the Radio Notification callback directly
* from the Radio Notification handling; i.e. to do the bulk of the
* Radio Notification processing at a reduced priority. Unfortunately, on a
* cortex-M0, there is no clean way to demote priority for the currently
* executing interrupt--we wouldn't want to demote the radio notification
* handling anyway because it is sensitive to timing, and the system expects
* to finish this handling very quickly. The workaround is to employ a Timeout
* to trigger postRadioNotificationCallback() after a very short delay (~0 us)
* and execute the callback in that context.
*
* !!!WARNING!!! Radio notifications are very time critical events. The
* current solution is expected to work under the assumption that
* postRadioNotificationCalback() will be executed BEFORE the next radio
* notification event is generated.
*/
radioNotificationCallback.call(radioNotificationCallbackParam);
#endif /* #ifdef YOTTA_CFG_MBED_OS */
}
/**
* A helper function to process radio-notification events; to be called internally.
* @param param [description]
*/
void processRadioNotificationEvent(bool param) {
radioNotificationCallbackParam = param;
radioNotificationTimeout.attach_us(mbed::callback(this, &nRF5xGap::postRadioNotificationCallback), 0);
}
friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */
private:
uint16_t m_connectionHandle;
/*
* Allow instantiation from nRF5xn when required.
*/
friend class nRF5xn;
nRF5xGap() :
advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST),
scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST),
whitelistAddressesSize(0) {
m_connectionHandle = BLE_CONN_HANDLE_INVALID;
}
nRF5xGap(nRF5xGap const &);
void operator=(nRF5xGap const &);
};
#endif // ifndef __NRF5x_GAP_H__

View File

@ -0,0 +1,847 @@
/* 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 "nRF5xGattServer.h"
#ifdef YOTTA_CFG_MBED_OS
#include "mbed-drivers/mbed.h"
#else
#include "mbed.h"
#endif
#include "common/common.h"
#include "btle/custom/custom_helper.h"
#include "nRF5xn.h"
namespace {
static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL
}
}
};
static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET
}
}
};
static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = BLE_GATT_STATUS_SUCCESS,
.update = 0
}
}
};
static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID
}
}
};
static ble_error_t set_attribute_value(
Gap::Handle_t connectionHandle,
GattAttribute::Handle_t attributeHandle,
ble_gatts_value_t *value
) {
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, value);
switch(err) {
case NRF_SUCCESS:
return BLE_ERROR_NONE;
case NRF_ERROR_INVALID_ADDR:
case NRF_ERROR_INVALID_PARAM:
return BLE_ERROR_INVALID_PARAM;
case NRF_ERROR_NOT_FOUND:
case NRF_ERROR_DATA_SIZE:
case BLE_ERROR_INVALID_CONN_HANDLE:
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
return BLE_ERROR_PARAM_OUT_OF_RANGE;
case NRF_ERROR_FORBIDDEN:
return BLE_ERROR_OPERATION_NOT_PERMITTED;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
} // end of anonymous namespace
/**************************************************************************/
/*!
@brief Adds a new service to the GATT table on the peripheral
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF5xGattServer::addService(GattService &service)
{
/* ToDo: Make sure this service UUID doesn't already exist (?) */
/* ToDo: Basic validation */
/* Add the service to the nRF51 */
ble_uuid_t nordicUUID;
nordicUUID = custom_convert_to_nordic_uuid(service.getUUID());
uint16_t serviceHandle;
ASSERT_TRUE( ERROR_NONE ==
sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&nordicUUID,
&serviceHandle),
BLE_ERROR_PARAM_OUT_OF_RANGE );
service.setHandle(serviceHandle);
/* Add characteristics to the service */
for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) {
if (characteristicCount >= BLE_TOTAL_CHARACTERISTICS) {
return BLE_ERROR_NO_MEM;
}
GattCharacteristic *p_char = service.getCharacteristic(i);
GattAttribute *p_description_descriptor = NULL;
GattAttribute *p_presentation_format_descriptor = NULL;
/* Skip any incompletely defined, read-only characteristics. */
if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
(p_char->getValueAttribute().getLength() == 0) &&
(p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) {
continue;
}
nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID());
/* The user-description and presentation-format descriptors are special cases
* that need to be handled at the time of adding each characteristic. The
* following block is meant to discover their presence. */
const uint8_t *userDescriptionDescriptorValuePtr = NULL;
uint16_t userDescriptionDescriptorValueLen = 0;
const uint8_t *presentationFormatDescriptorValuePtr = NULL;
uint16_t presentationFormatDescriptorValueLen = 0;
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
GattAttribute *p_desc = p_char->getDescriptor(j);
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
p_description_descriptor = p_desc;
userDescriptionDescriptorValuePtr = p_desc->getValuePtr();
userDescriptionDescriptorValueLen = p_desc->getLength();
}
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) {
p_presentation_format_descriptor = p_desc;
presentationFormatDescriptorValuePtr = p_desc->getValuePtr();
presentationFormatDescriptorValueLen = p_desc->getLength();
}
}
ASSERT_TRUE ( ERROR_NONE ==
custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID,
&nordicUUID,
p_char->getProperties(),
p_char->getRequiredSecurity(),
p_char->getValueAttribute().getValuePtr(),
p_char->getValueAttribute().getLength(),
p_char->getValueAttribute().getMaxLength(),
p_char->getValueAttribute().hasVariableLength(),
userDescriptionDescriptorValuePtr,
userDescriptionDescriptorValueLen,
presentationFormatDescriptorValuePtr,
presentationFormatDescriptorValueLen,
p_char->isReadAuthorizationEnabled(),
p_char->isWriteAuthorizationEnabled(),
&nrfCharacteristicHandles[characteristicCount]),
BLE_ERROR_PARAM_OUT_OF_RANGE );
/* Update the characteristic handle */
p_characteristics[characteristicCount] = p_char;
p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle);
if (p_description_descriptor) {
p_description_descriptor->setHandle(
nrfCharacteristicHandles[characteristicCount].user_desc_handle
);
}
if (p_presentation_format_descriptor) {
// The handle is not available from the SoftDevice
p_presentation_format_descriptor->setHandle(GattAttribute::INVALID_HANDLE);
}
characteristicCount++;
/* Add optional descriptors if any */
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
if (descriptorCount >= BLE_TOTAL_DESCRIPTORS) {
return BLE_ERROR_NO_MEM;
}
GattAttribute *p_desc = p_char->getDescriptor(j);
/* skip the user-description or presentation-format descriptor here;
* they have already been handled when adding the characteristic (above). */
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC
|| p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) {
continue;
}
nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID());
ASSERT_TRUE(ERROR_NONE ==
custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID,
&nordicUUID,
p_desc->getValuePtr(),
p_desc->getLength(),
p_desc->getMaxLength(),
p_desc->hasVariableLength(),
&nrfDescriptorHandles[descriptorCount]),
BLE_ERROR_PARAM_OUT_OF_RANGE);
p_descriptors[descriptorCount] = p_desc;
p_desc->setHandle(nrfDescriptorHandles[descriptorCount]);
descriptorCount++;
}
}
serviceCount++;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Reads the value of a characteristic, based on the service
and characteristic index fields
@param[in] attributeHandle
The handle of the GattCharacteristic to read from
@param[in] buffer
Buffer to hold the the characteristic's value
(raw byte array in LSB format)
@param[in/out] len
input: Length in bytes to be read.
output: Total length of attribute value upon successful return.
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
*/
/**************************************************************************/
ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP);
}
ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
ble_gatts_value_t value = {
.len = *lengthP,
.offset = 0,
.p_value = buffer,
};
ASSERT_TRUE( ERROR_NONE ==
sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value),
BLE_ERROR_PARAM_OUT_OF_RANGE);
*lengthP = value.len;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Updates the value of a characteristic, based on the service
and characteristic index fields
@param[in] charHandle
The handle of the GattCharacteristic to write to
@param[in] buffer
Data to use when updating the characteristic's value
(raw byte array in LSB format)
@param[in] len
The number of bytes in buffer
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
*/
/**************************************************************************/
ble_error_t nRF5xGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
{
return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly);
}
ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
{
ble_error_t returnValue = BLE_ERROR_NONE;
ble_gatts_value_t value = {
.len = len,
.offset = 0,
.p_value = const_cast<uint8_t *>(buffer),
};
if (localOnly) {
/* Only update locally regardless of notify/indicate */
ASSERT_INT( ERROR_NONE,
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
BLE_ERROR_PARAM_OUT_OF_RANGE );
return BLE_ERROR_NONE;
}
int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
if ((characteristicIndex != -1) &&
(p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
/* HVX update for the characteristic value */
ble_gatts_hvx_params_t hvx_params;
hvx_params.handle = attributeHandle;
hvx_params.type =
(p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
hvx_params.offset = 0;
hvx_params.p_data = const_cast<uint8_t *>(buffer);
hvx_params.p_len = &len;
if (connectionHandle == BLE_CONN_HANDLE_INVALID) { /* use the default connection handle if the caller hasn't specified a valid connectionHandle. */
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
connectionHandle = gap.getConnectionHandle();
}
bool updatesEnabled = false;
if (connectionHandle != BLE_CONN_HANDLE_INVALID) {
ble_error_t err = areUpdatesEnabled(connectionHandle, attributeHandle, &updatesEnabled);
// FIXME: The softdevice allocates and populates CCCD when the client
// interract with them. Checking for updates may return an out of
// range error in such case.
if(err && err != BLE_ERROR_PARAM_OUT_OF_RANGE) {
return err;
}
}
if (updatesEnabled) {
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
if (error != ERROR_NONE) {
switch (error) {
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
case ERROR_BUSY:
returnValue = BLE_STACK_BUSY;
break;
case ERROR_INVALID_STATE:
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
returnValue = BLE_ERROR_INVALID_STATE;
break;
default :
ASSERT_INT( ERROR_NONE,
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
BLE_ERROR_PARAM_OUT_OF_RANGE );
/* Notifications consume application buffers. The return value can
* be used for resending notifications. */
returnValue = BLE_STACK_BUSY;
break;
}
}
} else {
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
}
} else {
returnValue = set_attribute_value(connectionHandle, attributeHandle, &value);
}
return returnValue;
}
ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP)
{
/* Forward the call with the default connection handle. */
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
return areUpdatesEnabled(gap.getConnectionHandle(), characteristic, enabledP);
}
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
{
return areUpdatesEnabled(connectionHandle, characteristic.getValueHandle(), enabledP);
}
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, bool *enabledP)
{
int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
if (characteristicIndex == -1) {
return BLE_ERROR_INVALID_PARAM;
}
/* Read the cccd value from the GATT server. */
GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle;
uint16_t cccdValue;
uint16_t length = sizeof(cccdValue);
ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length);
if (rc != BLE_ERROR_NONE) {
return rc;
}
if (length != sizeof(cccdValue)) {
return BLE_ERROR_INVALID_STATE;
}
/* Check for NOTFICATION or INDICATION in CCCD. */
if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) {
*enabledP = true;
}
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Clear nRF5xGattServer's state.
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
*/
/**************************************************************************/
ble_error_t nRF5xGattServer::reset(void)
{
/* Clear all state that is from the parent, including private members */
if (GattServer::reset() != BLE_ERROR_NONE) {
return BLE_ERROR_INVALID_STATE;
}
/* Clear derived class members */
memset(p_characteristics, 0, sizeof(p_characteristics));
memset(p_descriptors, 0, sizeof(p_descriptors));
memset(nrfCharacteristicHandles, 0, sizeof(ble_gatts_char_handles_t));
memset(nrfDescriptorHandles, 0, sizeof(nrfDescriptorHandles));
descriptorCount = 0;
releaseAllWriteRequests();
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Callback handler for events getting pushed up from the SD
*/
/**************************************************************************/
void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt)
{
GattAttribute::Handle_t handle_value;
GattServerEvents::gattEvent_t eventType;
const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt;
switch (p_ble_evt->header.evt_id) {
case BLE_GATTS_EVT_WRITE: {
/* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
/* 1.) Handle CCCD changes */
handle_value = gattsEventP->params.write.handle;
int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value);
if ((characteristicIndex != -1) &&
(p_characteristics[characteristicIndex]->getProperties() &
(GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) ||
((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
} else {
eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
}
handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle());
return;
}
/* 2.) Changes to the characteristic value will be handled with other events below */
eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
}
break;
case BLE_GATTS_EVT_HVC:
/* Indication confirmation received */
eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
handle_value = gattsEventP->params.hvc.handle;
break;
#if NRF_SD_BLE_API_VERSION >= 4 // This event has been renamed in API V4+
case BLE_GATTS_EVT_HVN_TX_COMPLETE: {
handleDataSentEvent(p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count);
return;
}
#else
case BLE_EVT_TX_COMPLETE: {
handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count);
return;
}
#endif
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0);
return;
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
switch (gattsEventP->params.authorize_request.type) {
case BLE_GATTS_AUTHORIZE_TYPE_READ:
eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ;
handle_value = gattsEventP->params.authorize_request.request.read.handle;
break;
case BLE_GATTS_AUTHORIZE_TYPE_WRITE:
eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ;
handle_value = gattsEventP->params.authorize_request.request.write.handle;
break;
default:
return;
}
break;
case BLE_EVT_USER_MEM_REQUEST: {
uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle;
// allocate a new long request for this connection
// NOTE: we don't care about the result at this stage,
// it is not possible to cancel the operation anyway.
// If the request was not allocated then it will gracefully failled
// at subsequent stages.
allocateLongWriteRequest(conn_handle);
sd_ble_user_mem_reply(conn_handle, NULL);
return;
}
default:
return;
}
int characteristicIndex = resolveValueHandleToCharIndex(handle_value);
if (characteristicIndex == -1) {
// filter out the case were the request is a long one,
// and there is no attribute handle provided
uint8_t write_op = gattsEventP->params.authorize_request.request.write.op;
if (eventType != GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ ||
(write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW &&
write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) {
return;
}
}
/* Find index (charHandle) in the pool */
switch (eventType) {
case GattServerEvents::GATT_EVENT_DATA_WRITTEN: {
GattWriteCallbackParams cbParams = {
/* .connHandle = */ gattsEventP->conn_handle,
/* .handle = */ handle_value,
/* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op),
/* .offset = */ gattsEventP->params.write.offset,
/* .len = */ gattsEventP->params.write.len,
/* .data = */ gattsEventP->params.write.data
};
handleDataWrittenEvent(&cbParams);
break;
}
case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: {
uint16_t conn_handle = gattsEventP->conn_handle;
const ble_gatts_evt_write_t& input_req = gattsEventP->params.authorize_request.request.write;
const uint16_t max_size = getBiggestCharacteristicSize();
// this is a long write request, handle it here.
switch (input_req.op) {
case BLE_GATTS_OP_PREP_WRITE_REQ: {
// verify that the request is not outside of the possible range
if ((input_req.offset + input_req.len) > max_size) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply);
releaseLongWriteRequest(conn_handle);
return;
}
// find the write request
long_write_request_t* req = findLongWriteRequest(conn_handle);
if (!req) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
return;
}
// initialize the first request by setting the offset
if (req->length == 0) {
req->attr_handle = input_req.handle;
req->offset = input_req.offset;
} else {
// it should be the subsequent write
if ((req->offset + req->length) != input_req.offset) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply);
releaseLongWriteRequest(conn_handle);
return;
}
// it is not allowed to write multiple characteristic with the same request
if (input_req.handle != req->attr_handle) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
releaseLongWriteRequest(conn_handle);
return;
}
}
// start the copy of what is in input
memcpy(req->data + req->length, input_req.data, input_req.len);
// update the lenght of the data written
req->length = req->length + input_req.len;
// success, signal it to the softdevice
ble_gatts_rw_authorize_reply_params_t reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = BLE_GATT_STATUS_SUCCESS,
.update = 1,
.offset = input_req.offset,
.len = input_req.len,
.p_data = input_req.data
}
}
};
sd_ble_gatts_rw_authorize_reply(conn_handle, &reply);
} return;
case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: {
releaseLongWriteRequest(conn_handle);
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply);
} return;
case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: {
long_write_request_t* req = findLongWriteRequest(conn_handle);
if (!req) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
return;
}
GattWriteAuthCallbackParams cbParams = {
.connHandle = conn_handle,
.handle = req->attr_handle,
.offset = req->offset,
.len = req->length,
.data = req->data,
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
* request is to proceed. */
};
uint16_t write_authorization = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams);
// the user code didn't provide the write authorization,
// just leave here.
if (write_authorization != AUTH_CALLBACK_REPLY_SUCCESS) {
// report the status of the operation in any cases
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
releaseLongWriteRequest(conn_handle);
return;
}
// FIXME can't use ::write here, this function doesn't take the offset into account ...
ble_gatts_value_t value = {
.len = req->length,
.offset = req->offset,
.p_value = req->data
};
uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value);
if (update_err) {
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
releaseLongWriteRequest(conn_handle);
return;
}
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply);
GattWriteCallbackParams writeParams = {
/* .connHandle = */ conn_handle,
/* .handle = */ req->attr_handle,
/* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(input_req.op),
/* .offset = */ req->offset,
/* .len = */ req->length,
/* .data = */ req->data,
};
handleDataWrittenEvent(&writeParams);
releaseLongWriteRequest(conn_handle);
} return;
}
GattWriteAuthCallbackParams cbParams = {
.connHandle = gattsEventP->conn_handle,
.handle = handle_value,
.offset = gattsEventP->params.authorize_request.request.write.offset,
.len = gattsEventP->params.authorize_request.request.write.len,
.data = gattsEventP->params.authorize_request.request.write.data,
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
* request is to proceed. */
};
ble_gatts_rw_authorize_reply_params_t reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
.params = {
.write = {
.gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams),
.update = 1,
.offset = cbParams.offset,
.len = cbParams.len,
.p_data = cbParams.data
}
}
};
if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
{
reply.params.write.update = 0;
}
sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
/*
* If write-authorization is enabled for a characteristic,
* AUTHORIZATION_REQ event (if replied with true) is *not*
* followed by another DATA_WRITTEN event; so we still need
* to invoke handleDataWritten(), much the same as we would
* have done if write-authorization had not been enabled.
*/
if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) {
GattWriteCallbackParams cbParams = {
/* .connHandle = */ gattsEventP->conn_handle,
/* .handle = */ handle_value,
/* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op),
/* .offset = */ gattsEventP->params.authorize_request.request.write.offset,
/* .len = */ gattsEventP->params.authorize_request.request.write.len,
/* .data = */ gattsEventP->params.authorize_request.request.write.data,
};
handleDataWrittenEvent(&cbParams);
}
break;
}
case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: {
GattReadAuthCallbackParams cbParams = {
.connHandle = gattsEventP->conn_handle,
.handle = handle_value,
.offset = gattsEventP->params.authorize_request.request.read.offset,
.len = 0,
.data = NULL,
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
* request is to proceed. */
};
ble_gatts_rw_authorize_reply_params_t reply = {
.type = BLE_GATTS_AUTHORIZE_TYPE_READ,
.params = {
.read = {
.gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams)
}
}
};
if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) {
if (cbParams.data != NULL) {
reply.params.read.update = 1;
reply.params.read.offset = cbParams.offset;
reply.params.read.len = cbParams.len;
reply.params.read.p_data = cbParams.data;
}
}
sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
break;
}
default:
handleEvent(eventType, handle_value);
break;
}
}
uint16_t nRF5xGattServer::getBiggestCharacteristicSize() const {
uint16_t result = 0;
for (size_t i = 0; i < characteristicCount; ++i) {
uint16_t current_size = p_characteristics[i]->getValueAttribute().getMaxLength();
if (current_size > result) {
result = current_size;
}
}
return result;
}
nRF5xGattServer::long_write_request_t* nRF5xGattServer::allocateLongWriteRequest(uint16_t connection_handle) {
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
long_write_request_t& req = long_write_requests[i];
if (req.data == NULL) {
uint16_t block_size = getBiggestCharacteristicSize();
req.data = static_cast<uint8_t*>(malloc(block_size));
req.offset = 0;
req.length = 0;
req.conn_handle = connection_handle;
return &req;
}
}
// if nothing has been found then return null
return NULL;
}
bool nRF5xGattServer::releaseLongWriteRequest(uint16_t connection_handle) {
long_write_request_t* req = findLongWriteRequest(connection_handle);
if (!req) {
return false;
}
free(req->data);
req->data = NULL;
// the other fields are not relevant, return now
return true;
}
nRF5xGattServer::long_write_request_t* nRF5xGattServer::findLongWriteRequest(uint16_t connection_handle) {
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
long_write_request_t& req = long_write_requests[i];
if (req.data != NULL && req.conn_handle == connection_handle) {
return &req;
}
}
// if nothing has been found then return null
return NULL;
}
void nRF5xGattServer::releaseAllWriteRequests() {
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
long_write_request_t& req = long_write_requests[i];
if (req.data != NULL) {
free(req.data);
req.data = NULL;
}
}
}

View File

@ -0,0 +1,167 @@
/* 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.
*/
#ifndef __NRF51822_GATT_SERVER_H__
#define __NRF51822_GATT_SERVER_H__
#include <stddef.h>
#include "ble/blecommon.h"
#include "headers/nrf_ble.h" /* nordic ble */
#include "ble/Gap.h"
#include "ble/GattServer.h"
class nRF5xGattServer : public GattServer
{
public:
/* Functions that must be implemented from GattServer */
virtual ble_error_t addService(GattService &);
virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP);
virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP);
virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP);
virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP);
virtual ble_error_t reset(void);
/* nRF51 Functions */
void eventCallback(void);
void hwCallback(const ble_evt_t *p_ble_evt);
private:
const static unsigned BLE_TOTAL_CHARACTERISTICS = 20;
const static unsigned BLE_TOTAL_DESCRIPTORS = 8;
const static unsigned TOTAL_CONCURRENT_LONG_WRITE_REQUESTS = 3;
private:
struct long_write_request_t {
// the connection handle for a long write request
uint16_t conn_handle;
// the attribute handle for the long write request
// This implementation folow the bluetooth route
// where a write request target a single characteristic
// (see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] - 4.9.4)
uint16_t attr_handle;
// offset of the transaction
uint16_t offset;
// length of the data
uint16_t length;
// current data
uint8_t* data;
};
private:
/**
* resolve a value attribute to its owning characteristic.
* @param valueHandle the value handle to be resolved.
* @return characteristic index if a resolution is found, else -1.
*/
int resolveValueHandleToCharIndex(GattAttribute::Handle_t valueHandle) const {
unsigned charIndex;
for (charIndex = 0; charIndex < characteristicCount; charIndex++) {
if (nrfCharacteristicHandles[charIndex].value_handle == valueHandle) {
return charIndex;
}
}
return -1;
}
/**
* resolve a CCCD attribute handle to its owning characteristic.
* @param cccdHandle the CCCD handle to be resolved.
* @return characteristic index if a resolution is found, else -1.
*/
int resolveCCCDHandleToCharIndex(GattAttribute::Handle_t cccdHandle) const {
unsigned charIndex;
for (charIndex = 0; charIndex < characteristicCount; charIndex++) {
if (nrfCharacteristicHandles[charIndex].cccd_handle == cccdHandle) {
return charIndex;
}
}
return -1;
}
/**
* Return the biggest size used by a characteristic in the server
*/
uint16_t getBiggestCharacteristicSize() const;
/**
* Allocate a new write long request. return null if no requests are available.
* @param connection_handle The connection handle to be associated with the request.
* @return the allocated request or NULL if no requests are available.
*/
long_write_request_t* allocateLongWriteRequest(uint16_t connection_handle);
/**
* Release a long write request and free a slot for subsequent write long requests.
* @param connection_handle The connection handle associated with the request
* @return true if the request where allocated and was release, false otherwise.
*/
bool releaseLongWriteRequest(uint16_t connection_handle);
/**
* Find a long write request from a characteristic handle
* @param connection_handle The connection handle associated with the request.
* @return a pointer to the request if found otherwise NULL.
*/
long_write_request_t* findLongWriteRequest(uint16_t connection_handle);
/**
* Release all pending write requests.
*/
void releaseAllWriteRequests();
/**
* Query if updates of a characteristics are enabled for a given connection.
*/
ble_error_t areUpdatesEnabled(
Gap::Handle_t connectionHandle,
GattAttribute::Handle_t valueHandle,
bool *enabledP
);
private:
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
GattAttribute *p_descriptors[BLE_TOTAL_DESCRIPTORS];
uint8_t descriptorCount;
uint16_t nrfDescriptorHandles[BLE_TOTAL_DESCRIPTORS];
long_write_request_t long_write_requests[TOTAL_CONCURRENT_LONG_WRITE_REQUESTS];
/*
* Allow instantiation from nRF5xn when required.
*/
friend class nRF5xn;
nRF5xGattServer() : GattServer(), p_characteristics(), nrfCharacteristicHandles(), p_descriptors(), descriptorCount(0), nrfDescriptorHandles(), long_write_requests() {
/* empty */
}
private:
nRF5xGattServer(const nRF5xGattServer &);
const nRF5xGattServer& operator=(const nRF5xGattServer &);
};
#endif // ifndef __NRF51822_GATT_SERVER_H__

View File

@ -0,0 +1,194 @@
/* 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.
*/
#ifndef __NRF51822_SECURITY_MANAGER_H__
#define __NRF51822_SECURITY_MANAGER_H__
#include <stddef.h>
#include "nRF5xGap.h"
#include "ble/SecurityManager.h"
#include "btle_security.h"
class nRF5xSecurityManager : public SecurityManager
{
public:
/* Functions that must be implemented from SecurityManager */
virtual ble_error_t init(bool enableBonding,
bool requireMITM,
SecurityIOCapabilities_t iocaps,
const Passkey_t passkey) {
return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey);
}
virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) {
return btle_getLinkSecurity(connectionHandle, securityStatusP);
}
virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) {
return btle_setLinkSecurity(connectionHandle, securityMode);
}
virtual ble_error_t purgeAllBondingState(void) {
return btle_purgeAllBondingState();
}
#if (NRF_SD_BLE_API_VERSION <= 2)
/**
* @brief Returns a list of addresses from peers in the stacks bond table.
*
* @param[in/out] addresses
* (on input) @ref Gap::Whitelist_t structure where at
* most addresses.capacity addresses from bonded peers will
* be stored.
* (on output) A copy of the addresses from bonded peers.
*
* @return
* BLE_ERROR_NONE if successful.
*/
virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const {
uint8_t i;
ble_gap_whitelist_t whitelistFromBondTable;
ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE];
ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
/* Initialize the structure so that we get as many addreses as the whitelist can hold */
whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
whitelistFromBondTable.pp_addrs = addressPtr;
whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
whitelistFromBondTable.pp_irks = irkPtr;
ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable);
if (error != BLE_ERROR_NONE) {
addresses.size = 0;
return error;
}
/* Put all the addresses in the structure */
for (i = 0; i < whitelistFromBondTable.addr_count; ++i) {
if (i >= addresses.capacity) {
/* Ran out of space in the output Gap::Whitelist_t */
addresses.size = i;
return BLE_ERROR_NONE;
}
memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t));
}
/* Update the current address count */
addresses.size = i;
/* The assumption here is that the underlying implementation of
* createWhitelistFromBondTable() will not return the private resolvable
* addresses (which is the case in the SoftDevice). Rather it returns the
* IRKs, so we need to generate the private resolvable address by ourselves.
*/
for (i = 0; i < whitelistFromBondTable.irk_count; ++i) {
if (i + addresses.size >= addresses.capacity) {
/* Ran out of space in the output Gap::Whitelist_t */
addresses.size += i;
return BLE_ERROR_NONE;
}
btle_generateResolvableAddress(
*whitelistFromBondTable.pp_irks[i],
(ble_gap_addr_t &) addresses.addresses[i + addresses.size]
);
}
/* Update the current address count */
addresses.size += i;
return BLE_ERROR_NONE;
}
#else // -> NRF_SD_BLE_API_VERSION >= 3
/**
* @brief Returns a list of addresses from peers in the stacks bond table.
*
* @param[in/out] addresses
* (on input) @ref Gap::Whitelist_t structure where at
* most addresses.capacity addresses from bonded peers will
* be stored.
* (on output) A copy of the addresses from bonded peers.
*
* @retval BLE_ERROR_NONE if successful.
* @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent.
*/
virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const {
return btle_getAddressesFromBondTable(addresses);
}
#endif // #if (NRF_SD_BLE_API_VERSION <= 2)
/**
* @brief Clear nRF5xSecurityManager's state.
*
* @return
* BLE_ERROR_NONE if successful.
*/
virtual ble_error_t reset(void)
{
if (SecurityManager::reset() != BLE_ERROR_NONE) {
return BLE_ERROR_INVALID_STATE;
}
return BLE_ERROR_NONE;
}
bool hasInitialized(void) const {
return btle_hasInitializedSecurity();
}
public:
/*
* Allow instantiation from nRF5xn when required.
*/
friend class nRF5xn;
nRF5xSecurityManager() {
/* empty */
}
private:
nRF5xSecurityManager(const nRF5xSecurityManager &);
const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &);
#if (NRF_SD_BLE_API_VERSION <= 2)
/*
* Expose an interface that allows us to query the SoftDevice bond table
* and extract a whitelist.
*/
ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const {
return btle_createWhitelistFromBondTable(&whitelistFromBondTable);
}
#endif
/*
* Given a BLE address and a IRK this function check whether the address
* can be generated from the IRK. To do so, this function uses the hash
* function and algorithm described in the Bluetooth low Energy
* Specification. Internally, Nordic SDK functions are used.
*/
bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const {
return btle_matchAddressAndIrk(address, irk);
}
/*
* Give nRF5xGap access to createWhitelistFromBondTable() and
* matchAddressAndIrk()
*/
friend class nRF5xGap;
};
#endif // ifndef __NRF51822_SECURITY_MANAGER_H__

View File

@ -0,0 +1,236 @@
/* 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.
*/
#ifdef YOTTA_CFG_MBED_OS
#include "mbed-drivers/mbed.h"
#else
#include "mbed.h"
#endif
#include "nRF5xn.h"
#include "ble/blecommon.h"
#include "nrf_soc.h"
#include "btle/btle.h"
#include "btle/custom/custom_helper.h"
#include "nrf_delay.h"
extern "C" {
#include "nrf_sdh.h"
}
#include "nRF5XPalGattClient.h"
/**
* The singleton which represents the nRF51822 transport for the BLE.
*/
static nRF5xn& getDeviceInstance() {
static nRF5xn deviceInstance;
return deviceInstance;
}
/**
* BLE-API requires an implementation of the following function in order to
* obtain its transport handle.
*/
BLEInstanceBase *
createBLEInstance(void)
{
return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
}
nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId)
{
return getDeviceInstance();
}
nRF5xn::nRF5xn(void) :
initialized(false),
instanceID(BLE::DEFAULT_INSTANCE),
gapInstance(),
gattServerInstance(NULL),
gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())),
securityManagerInstance(NULL)
{
}
nRF5xn::~nRF5xn(void)
{
}
const char *nRF5xn::getVersion(void)
{
if (!initialized) {
return "INITIALIZATION_INCOMPLETE";
}
static char versionString[32];
static bool versionFetched = false;
if (!versionFetched) {
ble_version_t version;
if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) {
switch (version.version_number) {
case 0x07:
case 0x08:
snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 ver:%u fw:%04x", version.version_number, version.subversion_number);
break;
default:
snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) ver:%u fw:%04x", version.version_number, version.subversion_number);
break;
}
versionFetched = true;
} else {
strncpy(versionString, "unknown", sizeof(versionString));
}
}
return versionString;
}
/**************************************************************************/
/*!
@brief Initialize the BLE stack.
@returns ble_error_t
@retval BLE_ERROR_NONE if everything executed properly and
BLE_ERROR_ALREADY_INITIALIZED if the stack has already
been initialized (possibly through a call to nRF5xn::init()).
BLE_ERROR_INTERNAL_STACK_FAILURE is returned if initialization
of the internal stack (SoftDevice) failed.
*/
/**************************************************************************/
ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
{
if (initialized) {
BLE::InitializationCompleteCallbackContext context = {
BLE::Instance(instanceID),
BLE_ERROR_ALREADY_INITIALIZED
};
callback.call(&context);
return BLE_ERROR_ALREADY_INITIALIZED;
}
instanceID = instanceID;
/* ToDo: Clear memory contents, reset the SD, etc. */
if (btle_init() != ERROR_NONE) {
return BLE_ERROR_INTERNAL_STACK_FAILURE;
}
initialized = true;
BLE::InitializationCompleteCallbackContext context = {
BLE::Instance(instanceID),
BLE_ERROR_NONE
};
callback.call(&context);
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Purge the BLE stack of GATT and GAP state.
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@note When using S110, GattClient::shutdown() will not be called
since Gatt client features are not supported.
*/
/**************************************************************************/
ble_error_t nRF5xn::shutdown(void)
{
if (!initialized) {
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
}
/*
* Shutdown the SoftDevice first. This is because we need to disable all
* interrupts. Otherwise if we clear the BLE API and glue code first there
* will be many NULL references and no config information which could lead
* to errors if the shutdown process is interrupted.
*/
#if NRF_SD_BLE_API_VERSION >= 5
if (nrf_sdh_disable_request() != NRF_SUCCESS) {
return BLE_STACK_BUSY;
}
#else
if (softdevice_handler_sd_disable() != NRF_SUCCESS) {
return BLE_STACK_BUSY;
}
#endif
/* Shutdown the BLE API and nRF51 glue code */
ble_error_t error;
if (gattServerInstance != NULL) {
error = gattServerInstance->reset();
if (error != BLE_ERROR_NONE) {
return error;
}
}
if (securityManagerInstance != NULL) {
error = securityManagerInstance->reset();
if (error != BLE_ERROR_NONE) {
return error;
}
}
/* S110 does not support BLE client features, nothing to reset. */
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
error = getGattClient().reset();
if (error != BLE_ERROR_NONE) {
return error;
}
#endif
/* Gap instance is always present */
error = gapInstance.reset();
if (error != BLE_ERROR_NONE) {
return error;
}
custom_reset_128bits_uuid_table();
initialized = false;
return BLE_ERROR_NONE;
}
void
nRF5xn::waitForEvent(void)
{
processEvents();
sd_app_evt_wait();
}
void nRF5xn::processEvents() {
if (isEventsSignaled) {
isEventsSignaled = false;
#if NRF_SD_BLE_API_VERSION >= 5
// We use the "polling" dispatch model
// http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v14.2.0/group__nrf__sdh.html?cp=4_0_0_6_11_60_20#gab4d7be69304d4f5feefd1d440cc3e6c7
// This will process any pending events from the Softdevice
nrf_sdh_evts_poll();
#else
intern_softdevice_events_execute();
#endif
}
}

View File

@ -0,0 +1,179 @@
/* 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.
*/
#ifndef __NRF51822_H__
#define __NRF51822_H__
#include "ble/BLE.h"
#include "ble/blecommon.h"
#include "ble/BLEInstanceBase.h"
#include "ble/generic/GenericGattClient.h"
#include "nRF5xGap.h"
#include "nRF5xGattServer.h"
#include "nRF5xSecurityManager.h"
#include "btle.h"
class nRF5xn : public BLEInstanceBase
{
public:
nRF5xn(void);
virtual ~nRF5xn(void);
virtual ble_error_t init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback);
virtual bool hasInitialized(void) const {
return initialized;
}
virtual ble_error_t shutdown(void);
virtual const char *getVersion(void);
/**
* Accessors to GAP. This function checks whether gapInstance points to an
* object. If if does not, then the gapInstance is updated to
* &_getInstance before returning.
*
* @return A reference to GattServer.
*
* @note Unlike the GattClient, GattServer and SecurityManager, Gap is
* always needed in a BLE application. Therefore it is allocated
* statically.
*/
virtual Gap &getGap() {
return gapInstance;
};
/**
* Accessors to GATT Server. This function checks whether a GattServer
* object was previously instantiated. If such object does not exist, then
* it is created before returning.
*
* @return A reference to GattServer.
*/
virtual GattServer &getGattServer() {
if (gattServerInstance == NULL) {
gattServerInstance = new nRF5xGattServer();
}
return *gattServerInstance;
};
/**
* Accessors to GATT Client. This function checks whether a GattClient
* object was previously instantiated. If such object does not exist, then
* it is created before returning.
*
* @return A reference to GattClient.
*/
virtual GattClient &getGattClient() {
return gattClient;
}
/**
* Accessors to Security Manager. This function checks whether a SecurityManager
* object was previously instantiated. If such object does not exist, then
* it is created before returning.
*
* @return A reference to GattServer.
*/
virtual nRF5xSecurityManager &getSecurityManager() {
if (securityManagerInstance == NULL) {
securityManagerInstance = new nRF5xSecurityManager();
}
return *securityManagerInstance;
}
/**
* Accessors to GAP. This function checks whether gapInstance points to an
* object. If if does not, then the gapInstance is updated to
* &_getInstance before returning.
*
* @return A const reference to GattServer.
*
* @note Unlike the GattClient, GattServer and SecurityManager, Gap is
* always needed in a BLE application. Therefore it is allocated
* statically.
*
* @note The accessor is able to modify the object's state because the
* internal pointer has been declared mutable.
*/
virtual const nRF5xGap &getGap() const {
return gapInstance;
};
/**
* Accessors to GATT Server. This function checks whether a GattServer
* object was previously instantiated. If such object does not exist, then
* it is created before returning.
*
* @return A const reference to GattServer.
*
* @note The accessor is able to modify the object's state because the
* internal pointer has been declared mutable.
*/
virtual const nRF5xGattServer &getGattServer() const {
if (gattServerInstance == NULL) {
gattServerInstance = new nRF5xGattServer();
}
return *gattServerInstance;
};
/**
* Accessors to Security Manager. This function checks whether a SecurityManager
* object was previously instantiated. If such object does not exist, then
* it is created before returning.
*
* @return A const reference to GattServer.
*
* @note The accessor is able to modify the object's state because the
* internal pointer has been declared mutable.
*/
virtual const nRF5xSecurityManager &getSecurityManager() const {
if (securityManagerInstance == NULL) {
securityManagerInstance = new nRF5xSecurityManager();
}
return *securityManagerInstance;
}
virtual void waitForEvent(void);
virtual void processEvents();
public:
static nRF5xn& Instance(BLE::InstanceID_t instanceId);
private:
bool initialized;
BLE::InstanceID_t instanceID;
private:
mutable nRF5xGap gapInstance; /**< Gap instance whose reference is returned from a call to
* getGap(). Unlike the GattClient, GattServer and
* SecurityManager, Gap is always needed in a BLE application. */
private:
mutable nRF5xGattServer *gattServerInstance; /**< Pointer to the GattServer object instance.
* If NULL, then GattServer has not been initialized.
* The pointer has been declared as 'mutable' so that
* it can be assigned inside a 'const' function. */
ble::generic::GenericGattClient gattClient;
mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance.
* If NULL, then SecurityManager has not been initialized.
* The pointer has been declared as 'mutable' so that
* it can be assigned inside a 'const' function. */
};
#endif

View File

@ -0,0 +1,136 @@
/* 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.
*/
#ifndef _PROJECTCONFIG_H_
#define _PROJECTCONFIG_H_
#include "ble/GapAdvertisingData.h"
/*=========================================================================
MCU & BOARD SELCTION
CFG_BOARD is one of the value defined in board.h
-----------------------------------------------------------------------*/
#define CFG_BOARD BOARD_PCA10001
#define CFG_MCU_STRING "nRF51822"
/*=========================================================================*/
/*=========================================================================
CODE BASE VERSION SETTINGS
Please do not modify this version number. To set a version number
for your project or firmware, change the values in your 'boards/'
config file.
-----------------------------------------------------------------------*/
#define CFG_CODEBASE_VERSION_MAJOR 0
#define CFG_CODEBASE_VERSION_MINOR 1
#define CFG_CODEBASE_VERSION_REVISION 0
/*=========================================================================*/
/*=========================================================================
FIRMWARE VERSION SETTINGS
-----------------------------------------------------------------------*/
#define CFG_FIRMWARE_VERSION_MAJOR 0
#define CFG_FIRMWARE_VERSION_MINOR 0
#define CFG_FIRMWARE_VERSION_REVISION 0
/*=========================================================================*/
/*=========================================================================
DEBUG LEVEL
-----------------------------------------------------------------------
CFG_DEBUG Level 3: Full debug output, any failed assert
will produce a breakpoint for the
debugger
Level 2: ATTR_ALWAYS_INLINE is null, ASSERT
has text
Level 1: ATTR_ALWAYS_INLINE is an attribute,
ASSERT has no text
Level 0: No debug information generated
-----------------------------------------------------------------------*/
#define CFG_DEBUG (1)
#if (CFG_DEBUG > 3) || (CFG_DEBUG < 0)
#error "CFG_DEBUG must be a value between 0 (no debug) and 3"
#endif
/*=========================================================================*/
/*=========================================================================
GENERAL NRF51 PERIPHERAL SETTINGS
-----------------------------------------------------------------------
CFG_SCHEDULER_ENABLE Set this to 'true' or 'false' depending on
if you use the event scheduler or not
-----------------------------------------------------------------------*/
#define CFG_SCHEDULER_ENABLE false
/*------------------------------- GPIOTE ------------------------------*/
#define CFG_GPIOTE_MAX_USERS 1 /**< Maximum number of users of the GPIOTE handler. */
/*-------------------------------- TIMER ------------------------------*/
#define CFG_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. freq = (32768/(PRESCALER+1)) */
#define CFG_TIMER_MAX_INSTANCE 1 /**< Maximum number of simultaneously created timers. */
#define CFG_TIMER_OPERATION_QUEUE_SIZE 2 /**< Size of timer operation queues. */
/*=========================================================================*/
/*=========================================================================
BTLE SETTINGS
-----------------------------------------------------------------------*/
#define CFG_BLE_TX_POWER_LEVEL 0 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
/*---------------------------- BOND MANAGER ---------------------------*/
#define CFG_BLE_BOND_FLASH_PAGE_BOND (BLE_FLASH_PAGE_END-1) /**< Flash page used for bond manager bonding information.*/
#define CFG_BLE_BOND_FLASH_PAGE_SYS_ATTR (BLE_FLASH_PAGE_END-3) /**< Flash page used for bond manager system attribute information. TODO check if we can use BLE_FLASH_PAGE_END-2*/
#define CFG_BLE_BOND_DELETE_BUTTON_NUM 0 /**< Button to press to delete bond details during init */
/*------------------------------ SECURITY -----------------------------*/
#define CFG_BLE_SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */
#define CFG_BLE_SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
#define CFG_BLE_SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
#define CFG_BLE_SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
#define CFG_BLE_SEC_PARAM_MAX_KEY_SIZE 16
/*--------------------------------- GAP -------------------------------*/
#define CFG_GAP_APPEARANCE GapAdvertisingData::GENERIC_TAG
#define CFG_GAP_LOCAL_NAME "nRF5x"
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 50 /**< Minimum acceptable connection interval */
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 500 /**< Maximum acceptable connection interval */
#define CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS 4000 /**< Connection supervisory timeout */
#define CFG_GAP_CONNECTION_SLAVE_LATENCY 0 /**< Slave Latency in number of connection events. */
#define CFG_GAP_ADV_INTERVAL_MS 25 /**< The advertising interval in miliseconds, should be multiply of 0.625 */
#define CFG_GAP_ADV_TIMEOUT_S 180 /**< The advertising timeout in units of seconds. */
/*=========================================================================*/
/*=========================================================================
VALIDATION
-----------------------------------------------------------------------*/
#if CFG_BLE_TX_POWER_LEVEL != -40 && CFG_BLE_TX_POWER_LEVEL != -20 && CFG_BLE_TX_POWER_LEVEL != -16 && CFG_BLE_TX_POWER_LEVEL != -12 && CFG_BLE_TX_POWER_LEVEL != -8 && CFG_BLE_TX_POWER_LEVEL != -4 && CFG_BLE_TX_POWER_LEVEL != 0 && CFG_BLE_TX_POWER_LEVEL != 4
#error "CFG_BLE_TX_POWER_LEVEL must be -40, -20, -16, -12, -8, -4, 0 or 4"
#endif
/*=========================================================================*/
#endif /* _PROJECTCONFIG_H_ */

View File

@ -0,0 +1,21 @@
# Copyright 2015 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.
message("suppressing warnings from ble-nrf51822")
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set_target_properties(ble-nrf51822
PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function -Wno-missing-field-initializers"
)
endif()

View File

@ -14,8 +14,8 @@
#define MBED_RAM_START 0x20000000
#define MBED_RAM_SIZE 0x10000
#else
#define MBED_RAM_START 0x20003000
#define MBED_RAM_SIZE 0xD000
#define MBED_RAM_START 0x20003800
#define MBED_RAM_SIZE 0xC800
#endif
#define MBED_RAM0_START MBED_RAM_START

View File

@ -30,8 +30,8 @@
#define MBED_RAM_START 0x20000000
#define MBED_RAM_SIZE 0x10000
#else
#define MBED_RAM_START 0x20003000
#define MBED_RAM_SIZE 0xD000
#define MBED_RAM_START 0x20003800
#define MBED_RAM_SIZE 0xC800
#endif
#define MBED_RAM0_START MBED_RAM_START

View File

@ -16,8 +16,8 @@ if (MBED_APP_START == 0) {
define symbol MBED_RAM_START = 0x20000000;
define symbol MBED_RAM_SIZE = 0x10000;
} else {
define symbol MBED_RAM_START = 0x20003000;
define symbol MBED_RAM_SIZE = 0xD000;
define symbol MBED_RAM_START = 0x20003800;
define symbol MBED_RAM_SIZE = 0xC800;
}
define symbol MBED_RAM0_START = MBED_RAM_START;

View File

@ -14,8 +14,8 @@
#define MBED_RAM_START 0x20000000
#define MBED_RAM_SIZE 0x40000
#else
#define MBED_RAM_START 0x20004000
#define MBED_RAM_SIZE 0x3C000
#define MBED_RAM_START 0x20003700
#define MBED_RAM_SIZE 0x3C900
#endif
#define MBED_RAM0_START MBED_RAM_START

View File

@ -30,8 +30,8 @@
#define MBED_RAM_START 0x20000000
#define MBED_RAM_SIZE 0x40000
#else
#define MBED_RAM_START 0x20004000
#define MBED_RAM_SIZE 0x3C000
#define MBED_RAM_START 0x20003700
#define MBED_RAM_SIZE 0x3C900
#endif
#define MBED_RAM0_START MBED_RAM_START

View File

@ -16,8 +16,8 @@ if (MBED_APP_START == 0) {
define symbol MBED_RAM_START = 0x20000000;
define symbol MBED_RAM_SIZE = 0x40000;
} else {
define symbol MBED_RAM_START = 0x20004000;
define symbol MBED_RAM_SIZE = 0x3C000;
define symbol MBED_RAM_START = 0x20003700;
define symbol MBED_RAM_SIZE = 0x3C900;
}
define symbol MBED_RAM0_START = MBED_RAM_START;

View File

@ -1,5 +1,6 @@
# Folder origin
components/ble
components/softdevice
components/libraries/fstorage/nrf_fstorage_sd.*

View File

@ -38,12 +38,10 @@
*
*/
#warning arm porting pending
#if ARM_PORTING_PENDING
#include "ble_radio_notification.h"
#include <stdlib.h>
#include "nrf_nvic.h"
static bool m_radio_active = false; /**< Current radio state. */
static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */
@ -89,5 +87,3 @@ uint32_t ble_radio_notification_init(uint32_t irq_pr
// Configure the event
return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance);
}
#endif

View File

@ -38,9 +38,6 @@
*
*/
#warning arm porting pending
#if ARM_PORTING_PENDING
#include "ble_advdata.h"
#include "ble_gap.h"
#include "ble_srv_common.h"
@ -707,5 +704,3 @@ uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t *
// Pass encoded advertising data and/or scan response data to the stack.
return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
}
#endif

View File

@ -1,13 +1,45 @@
{
"name": "softdevice",
"config": {
"comment": {
"help": "S132, BLE_STACK_SUPPORT_REQD: These macros are currently defined in target.json but should be moved here.",
"value": null
}
},
"macros": [
"SOFTDEVICE_PRESENT=1",
"BLE_STACK_SUPPORT_REQD=1",
"NRF_SDH_CLOCK_LF_SRC=1",
"NRF_SDH_CLOCK_LF_RC_CTIV=0",
"NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0",
"NRF_SDH_CLOCK_LF_XTAL_ACCURACY=7",
"NRF_SD_BLE_API_VERSION=5",
"NRF_SDH_ENABLED=1",
"NRF_SDH_SOC_ENABLED=1",
"NRF_SDH_BLE_ENABLED=1",
"PEER_MANAGER_ENABLED=1",
"NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3",
"NRF_SDH_BLE_CENTRAL_LINK_COUNT=1",
"NRF_SDH_BLE_TOTAL_LINK_COUNT=4",
"NRF_SDH_BLE_SERVICE_CHANGED=1",
"NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23",
"NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE=0x600",
"NRF_SDH_BLE_VS_UUID_COUNT=4",
"NRF_SDH_BLE_OBSERVER_PRIO_LEVELS=4",
"NRF_SDH_BLE_GAP_EVENT_LENGTH=3",
"BLE_ADV_BLE_OBSERVER_PRIO=1",
"BLE_CONN_STATE_BLE_OBSERVER_PRIO=0",
"BLE_CONN_PARAMS_BLE_OBSERVER_PRIO=1",
"NRF_BLE_GATT_BLE_OBSERVER_PRIO=1",
"NRF_SDH_DISPATCH_MODEL=2",
"NRF_SDH_SOC_ENABLED=1",
"NRF_SDH_STACK_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_STATE_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_SOC_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_REQ_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_BLE_STACK_OBSERVER_PRIO=0",
"NRF_SDH_SOC_STACK_OBSERVER_PRIO=0",
"FDS_BACKEND=2",
"S132=1"
"SWI_DISABLE1=1",
"NRF_LOG_ENABLED=0"
],
"target_overrides": {
"*": {

View File

@ -2,14 +2,40 @@
"name": "softdevice",
"macros": [
"SOFTDEVICE_PRESENT=1",
"BLE_STACK_SUPPORT_REQD=1",
"NRF_DFU_SETTINGS_VERSION=1",
"NRF_SDH_CLOCK_LF_SRC=1",
"NRF_SDH_CLOCK_LF_RC_CTIV=0",
"NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0",
"NRF_SDH_CLOCK_LF_XTAL_ACCURACY=7",
"BLE_STACK_SUPPORT_REQD",
"NRF_SD_BLE_API_VERSION=5",
"S140",
"NRF_SDH_ENABLED=1",
"NRF_SDH_SOC_ENABLED=1",
"NRF_SDH_BLE_ENABLED=1",
"PEER_MANAGER_ENABLED=1",
"NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3",
"NRF_SDH_BLE_CENTRAL_LINK_COUNT=1",
"NRF_SDH_BLE_TOTAL_LINK_COUNT=4",
"NRF_SDH_BLE_SERVICE_CHANGED=1",
"NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23",
"NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE=0x600",
"NRF_SDH_BLE_VS_UUID_COUNT=4",
"NRF_SDH_BLE_OBSERVER_PRIO_LEVELS=4",
"NRF_SDH_BLE_GAP_EVENT_LENGTH=3",
"BLE_ADV_BLE_OBSERVER_PRIO=1",
"BLE_CONN_STATE_BLE_OBSERVER_PRIO=0",
"BLE_CONN_PARAMS_BLE_OBSERVER_PRIO=1",
"NRF_BLE_GATT_BLE_OBSERVER_PRIO=1",
"NRF_SDH_DISPATCH_MODEL=2",
"NRF_SDH_SOC_ENABLED=1",
"NRF_SDH_STACK_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_STATE_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_SOC_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_REQ_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_BLE_STACK_OBSERVER_PRIO=0",
"NRF_SDH_SOC_STACK_OBSERVER_PRIO=0",
"FDS_BACKEND=2",
"S140=1"
"SWI_DISABLE1=1",
"S140"
],
"target_overrides": {
"*": {