mirror of https://github.com/ARMmbed/mbed-os.git
Squashed 'bluetooth/ble/' content from commit 2f55eed
git-subtree-dir: bluetooth/ble git-subtree-split: 2f55eed1fdde06fdabfb66d41ce6cd14e280978f
commit
fe28524ee8
|
@ -0,0 +1,2 @@
|
|||
# Ignore the generated Doxygen output
|
||||
apidoc/
|
|
@ -0,0 +1,393 @@
|
|||
# Change Log
|
||||
|
||||
## [v2.5.2](https://github.com/ARMmbed/ble/tree/v2.5.2) (2016-03-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.5.1...v2.5.2)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Infinite busy [\#69](https://github.com/ARMmbed/ble/issues/69)
|
||||
|
||||
## [v2.5.1](https://github.com/ARMmbed/ble/tree/v2.5.1) (2016-01-27)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.5.0...v2.5.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Gap state is not updated when the advertising stop after the timeout [\#80](https://github.com/ARMmbed/ble/issues/80)
|
||||
- crash on memory allocation [\#26](https://github.com/ARMmbed/ble/issues/26)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Change onShutdown\(obj, func\) definition [\#174](https://github.com/ARMmbed/ble/pull/174) ([andresag01](https://github.com/andresag01))
|
||||
- Invalid adv payloads are not committed before checking [\#171](https://github.com/ARMmbed/ble/pull/171) ([andresag01](https://github.com/andresag01))
|
||||
- Update Gap state in startAdvertising\(\) [\#170](https://github.com/ARMmbed/ble/pull/170) ([andresag01](https://github.com/andresag01))
|
||||
- Improve doxygen documentation: [\#169](https://github.com/ARMmbed/ble/pull/169) ([pan-](https://github.com/pan-))
|
||||
- Update Gap state after advertising times out [\#168](https://github.com/ARMmbed/ble/pull/168) ([andresag01](https://github.com/andresag01))
|
||||
- merge version 2.5.0 into master [\#163](https://github.com/ARMmbed/ble/pull/163) ([pan-](https://github.com/pan-))
|
||||
- Fix doxygen warnings for BLE API [\#162](https://github.com/ARMmbed/ble/pull/162) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.5.0](https://github.com/ARMmbed/ble/tree/v2.5.0) (2016-01-12)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.4.0...v2.5.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- merge branch develop \(v2.4.0\) [\#161](https://github.com/ARMmbed/ble/pull/161) ([pan-](https://github.com/pan-))
|
||||
- Add API to get addresses of peers in bond table [\#160](https://github.com/ARMmbed/ble/pull/160) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.4.0](https://github.com/ARMmbed/ble/tree/v2.4.0) (2016-01-07)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.3.0...v2.4.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Whitelisting experimental API [\#159](https://github.com/ARMmbed/ble/pull/159) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.3.0](https://github.com/ARMmbed/ble/tree/v2.3.0) (2015-12-23)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.2.3...v2.3.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Characteristic descriptor discovery [\#105](https://github.com/ARMmbed/ble/pull/105) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.2.3](https://github.com/ARMmbed/ble/tree/v2.2.3) (2015-12-23)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.2.2...v2.2.3)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Two different enum list of BLE appearances [\#136](https://github.com/ARMmbed/ble/issues/136)
|
||||
- Gap::updateAdvertisingPayload should work for different length of data [\#84](https://github.com/ARMmbed/ble/issues/84)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Hotfix for backward compatibility [\#158](https://github.com/ARMmbed/ble/pull/158) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
- Clean up code in DiscoveredCharacteristic.cpp [\#154](https://github.com/ARMmbed/ble/pull/154) ([andresag01](https://github.com/andresag01))
|
||||
- Modify functions that manipulate adv payload [\#153](https://github.com/ARMmbed/ble/pull/153) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.2](https://github.com/ARMmbed/ble/tree/v2.2.2) (2015-12-21)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.2.1...v2.2.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add BLE\_ERROR\_INTERNAL\_STACK\_FAILURE error code [\#155](https://github.com/ARMmbed/ble/pull/155) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.1](https://github.com/ARMmbed/ble/tree/v2.2.1) (2015-12-18)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.2.0...v2.2.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Remove deprecated appearance enum from blecommon.h [\#150](https://github.com/ARMmbed/ble/pull/150) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.0](https://github.com/ARMmbed/ble/tree/v2.2.0) (2015-12-17)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.16...v2.2.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add onShutdown to register callbacks [\#146](https://github.com/ARMmbed/ble/pull/146) ([andresag01](https://github.com/andresag01))
|
||||
- transparenly support existing applications which may have used Gap::ADDR\_TYPE\_\* [\#145](https://github.com/ARMmbed/ble/pull/145) ([rgrover](https://github.com/rgrover))
|
||||
|
||||
## [v2.1.16](https://github.com/ARMmbed/ble/tree/v2.1.16) (2015-12-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.15...v2.1.16)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Improve API to facilitate full shutdown procedure [\#141](https://github.com/ARMmbed/ble/pull/141) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.1.15](https://github.com/ARMmbed/ble/tree/v2.1.15) (2015-12-15)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.14...v2.1.15)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Extract Adress related types from Gap.h into BLEProtocol.h [\#142](https://github.com/ARMmbed/ble/pull/142) ([rgrover](https://github.com/rgrover))
|
||||
|
||||
## [v2.1.14](https://github.com/ARMmbed/ble/tree/v2.1.14) (2015-12-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.13...v2.1.14)
|
||||
|
||||
## [v2.1.13](https://github.com/ARMmbed/ble/tree/v2.1.13) (2015-12-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.11...v2.1.13)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Added SecurityManager::setLinkSecurity call for elevating security settings on a particular connection. [\#140](https://github.com/ARMmbed/ble/pull/140) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v2.1.11](https://github.com/ARMmbed/ble/tree/v2.1.11) (2015-12-10)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.10...v2.1.11)
|
||||
|
||||
## [v2.1.10](https://github.com/ARMmbed/ble/tree/v2.1.10) (2015-12-07)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.9...v2.1.10)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- WIP: UUID endian change [\#128](https://github.com/ARMmbed/ble/pull/128) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v2.1.9](https://github.com/ARMmbed/ble/tree/v2.1.9) (2015-12-04)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.8...v2.1.9)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix documentation for advertising interval getters [\#134](https://github.com/ARMmbed/ble/pull/134) ([andresag01](https://github.com/andresag01))
|
||||
- I change the service description [\#132](https://github.com/ARMmbed/ble/pull/132) ([iriark01](https://github.com/iriark01))
|
||||
- Add a doxyfile that warns for undocumented elements [\#131](https://github.com/ARMmbed/ble/pull/131) ([bremoran](https://github.com/bremoran))
|
||||
|
||||
## [v2.1.8](https://github.com/ARMmbed/ble/tree/v2.1.8) (2015-12-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.7...v2.1.8)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Edit [\#130](https://github.com/ARMmbed/ble/pull/130) ([iriark01](https://github.com/iriark01))
|
||||
- Edit [\#129](https://github.com/ARMmbed/ble/pull/129) ([iriark01](https://github.com/iriark01))
|
||||
|
||||
## [v2.1.7](https://github.com/ARMmbed/ble/tree/v2.1.7) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.6...v2.1.7)
|
||||
|
||||
## [v2.1.6](https://github.com/ARMmbed/ble/tree/v2.1.6) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.5...v2.1.6)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Terrible handling of initLen / minLen and variable length characteristics. [\#93](https://github.com/ARMmbed/ble/issues/93)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Allow GattAttributes to have variable length [\#127](https://github.com/ARMmbed/ble/pull/127) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.1.5](https://github.com/ARMmbed/ble/tree/v2.1.5) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.4...v2.1.5)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Edit [\#126](https://github.com/ARMmbed/ble/pull/126) ([iriark01](https://github.com/iriark01))
|
||||
- Edit [\#125](https://github.com/ARMmbed/ble/pull/125) ([iriark01](https://github.com/iriark01))
|
||||
- Edit [\#124](https://github.com/ARMmbed/ble/pull/124) ([iriark01](https://github.com/iriark01))
|
||||
- Edit [\#123](https://github.com/ARMmbed/ble/pull/123) ([iriark01](https://github.com/iriark01))
|
||||
- Separate the concept of minlen and len in GattAttr [\#122](https://github.com/ARMmbed/ble/pull/122) ([andresag01](https://github.com/andresag01))
|
||||
- Doxygen fixes [\#120](https://github.com/ARMmbed/ble/pull/120) ([metc](https://github.com/metc))
|
||||
- Minor edits [\#114](https://github.com/ARMmbed/ble/pull/114) ([iriark01](https://github.com/iriark01))
|
||||
|
||||
## [v2.1.4](https://github.com/ARMmbed/ble/tree/v2.1.4) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.3...v2.1.4)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Guard nordic specific implementation with \#ifdef TARGET\_NRF51822 [\#119](https://github.com/ARMmbed/ble/pull/119) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
|
||||
## [v2.1.3](https://github.com/ARMmbed/ble/tree/v2.1.3) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.2...v2.1.3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Call bootloader\_start implicitly trough a event handler call [\#118](https://github.com/ARMmbed/ble/pull/118) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
|
||||
## [v2.1.2](https://github.com/ARMmbed/ble/tree/v2.1.2) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.1...v2.1.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Reintroduce old Eddystone with deprecated warnings [\#117](https://github.com/ARMmbed/ble/pull/117) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.1.1](https://github.com/ARMmbed/ble/tree/v2.1.1) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.1.0...v2.1.1)
|
||||
|
||||
## [v2.1.0](https://github.com/ARMmbed/ble/tree/v2.1.0) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.5...v2.1.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- All BLE event handling should happen in thread mode [\#89](https://github.com/ARMmbed/ble/issues/89)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- First Doxygen output [\#116](https://github.com/ARMmbed/ble/pull/116) ([metc](https://github.com/metc))
|
||||
- Minor doc changes [\#113](https://github.com/ARMmbed/ble/pull/113) ([metc](https://github.com/metc))
|
||||
- Minor edits [\#112](https://github.com/ARMmbed/ble/pull/112) ([iriark01](https://github.com/iriark01))
|
||||
- Minor edits [\#111](https://github.com/ARMmbed/ble/pull/111) ([iriark01](https://github.com/iriark01))
|
||||
- Minor edits [\#110](https://github.com/ARMmbed/ble/pull/110) ([iriark01](https://github.com/iriark01))
|
||||
- Remove persistant callbacks [\#109](https://github.com/ARMmbed/ble/pull/109) ([pan-](https://github.com/pan-))
|
||||
- Changed GapAdvertisingData.addData to take current fields into account when adding data. [\#108](https://github.com/ARMmbed/ble/pull/108) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Remove Eddystone implementation in ble/services [\#107](https://github.com/ARMmbed/ble/pull/107) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.0.5](https://github.com/ARMmbed/ble/tree/v2.0.5) (2015-11-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.4...v2.0.5)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Edits - with a couple of comments [\#104](https://github.com/ARMmbed/ble/pull/104) ([iriark01](https://github.com/iriark01))
|
||||
|
||||
## [v2.0.4](https://github.com/ARMmbed/ble/tree/v2.0.4) (2015-11-13)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.3...v2.0.4)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Edits [\#102](https://github.com/ARMmbed/ble/pull/102) ([iriark01](https://github.com/iriark01))
|
||||
|
||||
## [v2.0.3](https://github.com/ARMmbed/ble/tree/v2.0.3) (2015-11-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/mbedos-release-15-11...v2.0.3)
|
||||
|
||||
## [mbedos-release-15-11](https://github.com/ARMmbed/ble/tree/mbedos-release-15-11) (2015-11-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.2...mbedos-release-15-11)
|
||||
|
||||
## [v2.0.2](https://github.com/ARMmbed/ble/tree/v2.0.2) (2015-11-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.1...v2.0.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- BLE::init\(\) should also be able to take an \<object, member\> tuple for its callback [\#97](https://github.com/ARMmbed/ble/pull/97) ([rgrover](https://github.com/rgrover))
|
||||
|
||||
## [v2.0.1](https://github.com/ARMmbed/ble/tree/v2.0.1) (2015-11-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v2.0.0...v2.0.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix beaconPeriod and defaults for voltage/temp [\#94](https://github.com/ARMmbed/ble/pull/94) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.0.0](https://github.com/ARMmbed/ble/tree/v2.0.0) (2015-11-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/mbedos-techcon-oob2...v2.0.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- BLE::init\(\) should be non-blocking [\#90](https://github.com/ARMmbed/ble/issues/90)
|
||||
- Wrong include file in HealthTermometerService.h:20:17 [\#86](https://github.com/ARMmbed/ble/issues/86)
|
||||
- Return error on write request when locked [\#19](https://github.com/ARMmbed/ble/issues/19)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Introduced fixes to Eddystone implementation [\#92](https://github.com/ARMmbed/ble/pull/92) ([andresag01](https://github.com/andresag01))
|
||||
- BLE::init\(\) now takes in a callback paramter [\#91](https://github.com/ARMmbed/ble/pull/91) ([rgrover](https://github.com/rgrover))
|
||||
- Fixed include problem in HealthThermometer header [\#87](https://github.com/ARMmbed/ble/pull/87) ([andresag01](https://github.com/andresag01))
|
||||
- use the github url public url in module.json [\#82](https://github.com/ARMmbed/ble/pull/82) ([jrobeson](https://github.com/jrobeson))
|
||||
- Reduce the memory consumed by FunctionPointerWithContext instances [\#81](https://github.com/ARMmbed/ble/pull/81) ([pan-](https://github.com/pan-))
|
||||
- Introduced fix for defect IOTSFW-1058 [\#79](https://github.com/ARMmbed/ble/pull/79) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [mbedos-techcon-oob2](https://github.com/ARMmbed/ble/tree/mbedos-techcon-oob2) (2015-10-19)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v1.0.0...mbedos-techcon-oob2)
|
||||
|
||||
## [v1.0.0](https://github.com/ARMmbed/ble/tree/v1.0.0) (2015-10-19)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.8...v1.0.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- add support for Eddystone [\#57](https://github.com/ARMmbed/ble/issues/57)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add st-ble-shield as a possible target dependency. [\#76](https://github.com/ARMmbed/ble/pull/76) ([pan-](https://github.com/pan-))
|
||||
- Support for Environmental Service \(temperature, pressure and humidity\) [\#75](https://github.com/ARMmbed/ble/pull/75) ([crespum](https://github.com/crespum))
|
||||
|
||||
## [v0.4.8](https://github.com/ARMmbed/ble/tree/v0.4.8) (2015-09-29)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.7...v0.4.8)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- ERROR: undefined reference to `createBLEInstance\(\)' [\#68](https://github.com/ARMmbed/ble/issues/68)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Adding Eddystone Support [\#74](https://github.com/ARMmbed/ble/pull/74) ([BlackstoneEngineering](https://github.com/BlackstoneEngineering))
|
||||
- Changed onConnection and onDisconnection to accept object/methods and… [\#72](https://github.com/ARMmbed/ble/pull/72) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- adding an initial prototype for a yotta-config based initialization f… [\#71](https://github.com/ARMmbed/ble/pull/71) ([rgrover](https://github.com/rgrover))
|
||||
- Gap.h - Added onConnection callback chain simarly to the currently pr… [\#70](https://github.com/ARMmbed/ble/pull/70) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v0.4.7](https://github.com/ARMmbed/ble/tree/v0.4.7) (2015-08-13)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.6...v0.4.7)
|
||||
|
||||
## [v0.4.6](https://github.com/ARMmbed/ble/tree/v0.4.6) (2015-08-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.5...v0.4.6)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Eddystone Service Working [\#66](https://github.com/ARMmbed/ble/pull/66) ([BlackstoneEngineering](https://github.com/BlackstoneEngineering))
|
||||
|
||||
## [v0.4.5](https://github.com/ARMmbed/ble/tree/v0.4.5) (2015-08-10)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.4...v0.4.5)
|
||||
|
||||
## [v0.4.4](https://github.com/ARMmbed/ble/tree/v0.4.4) (2015-08-07)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/v0.4.3...v0.4.4)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- GapAdvertisingData::getPayload\(\) should not return NULL if payloadLen == 0 [\#64](https://github.com/ARMmbed/ble/issues/64)
|
||||
- enableActiveScanning\(\) [\#60](https://github.com/ARMmbed/ble/issues/60)
|
||||
- add central role for s130 [\#58](https://github.com/ARMmbed/ble/issues/58)
|
||||
- Clash With Definition and Enum Naming [\#46](https://github.com/ARMmbed/ble/issues/46)
|
||||
- URIBeacon2Service Needs initial AdvertisedTxPowerLevels [\#17](https://github.com/ARMmbed/ble/issues/17)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Conversion from advertisement duration units to ms moved from Gap to … [\#63](https://github.com/ARMmbed/ble/pull/63) ([jslater8](https://github.com/jslater8))
|
||||
- Add a new function updateAdvertisingPayload\(\) [\#61](https://github.com/ARMmbed/ble/pull/61) ([sunsmilearm](https://github.com/sunsmilearm))
|
||||
- minor corrections to the comments [\#59](https://github.com/ARMmbed/ble/pull/59) ([ddavidebor](https://github.com/ddavidebor))
|
||||
|
||||
## [v0.4.3](https://github.com/ARMmbed/ble/tree/v0.4.3) (2015-07-22)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/0.4.1...v0.4.3)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- add GattClient::onHVX [\#53](https://github.com/ARMmbed/ble/issues/53)
|
||||
- Need some help regarding the development of BLE network simulator [\#52](https://github.com/ARMmbed/ble/issues/52)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- expose descriptors optional arg in derived GattChar. constructors [\#56](https://github.com/ARMmbed/ble/pull/56) ([OJFord](https://github.com/OJFord))
|
||||
- Change DiscoveredCharacteristic API to return long or short UUIDs. [\#55](https://github.com/ARMmbed/ble/pull/55) ([adfernandes](https://github.com/adfernandes))
|
||||
- Refactor using new include paths [\#51](https://github.com/ARMmbed/ble/pull/51) ([rosterloh](https://github.com/rosterloh))
|
||||
- Revert "use mbed-classic as mbed dependency" [\#50](https://github.com/ARMmbed/ble/pull/50) ([rgrover](https://github.com/rgrover))
|
||||
- use mbed-classic as mbed dependency [\#45](https://github.com/ARMmbed/ble/pull/45) ([autopulated](https://github.com/autopulated))
|
||||
|
||||
## [0.4.1](https://github.com/ARMmbed/ble/tree/0.4.1) (2015-07-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble/compare/workingOldBootloader...0.4.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- DiscoveredCharacteristic::setupOnDataRead\(\) should be GattClient::onDataRead\(\) instead [\#49](https://github.com/ARMmbed/ble/issues/49)
|
||||
- CONNECTION\_TIMEOUT should be added to DisconnectionReason\_t [\#43](https://github.com/ARMmbed/ble/issues/43)
|
||||
- Typo in definition of UNIT\_0\_625\_MS in Gap.h [\#40](https://github.com/ARMmbed/ble/issues/40)
|
||||
- Initial value for \_requiredSecurity member of GattCharacteristic class breaks existing code [\#39](https://github.com/ARMmbed/ble/issues/39)
|
||||
- Allow adding a User Description descriptor to a GattCharacteristic. [\#38](https://github.com/ARMmbed/ble/issues/38)
|
||||
- The example code in GattAttribute.h does not refer to GattAttribute [\#37](https://github.com/ARMmbed/ble/issues/37)
|
||||
- BLEDevice::clearAdvertisingPayload doesn't clear the scan response PDU [\#36](https://github.com/ARMmbed/ble/issues/36)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Added get/set methods for advertisement payload and parameters. [\#42](https://github.com/ARMmbed/ble/pull/42) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [workingOldBootloader](https://github.com/ARMmbed/ble/tree/workingOldBootloader) (2015-03-02)
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Which are the allowed values for txPower? \> BLEDevice::setTxPower\(int8\_t txPower\) [\#30](https://github.com/ARMmbed/ble/issues/30)
|
||||
- Modes: UriBeacon and UriBeaconConfig [\#15](https://github.com/ARMmbed/ble/issues/15)
|
||||
- URIBeacon2Service.h should be called UriBeaconConfigService.h [\#11](https://github.com/ARMmbed/ble/issues/11)
|
||||
- Lock and Unlock missing from URIBeacon2Service.h [\#10](https://github.com/ARMmbed/ble/issues/10)
|
||||
- Service Characteristics [\#9](https://github.com/ARMmbed/ble/issues/9)
|
||||
- URIBeacon2Service.h missing TX Power Mode [\#8](https://github.com/ARMmbed/ble/issues/8)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- URIBeacon2Service configure\(\) [\#14](https://github.com/ARMmbed/ble/issues/14)
|
||||
- URIBeacon2Service.h does not reset to defaults [\#7](https://github.com/ARMmbed/ble/issues/7)
|
||||
- Uri Data Length and semantics [\#6](https://github.com/ARMmbed/ble/issues/6)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Inconsistent use of uint\_16\_t and Handle\_t [\#34](https://github.com/ARMmbed/ble/issues/34)
|
||||
- Incorrect documentation on void setAdvertisingType\(\)? [\#29](https://github.com/ARMmbed/ble/issues/29)
|
||||
- URIBeacon2Service setTxPowerLevel should follow specification [\#16](https://github.com/ARMmbed/ble/issues/16)
|
||||
- URIBeacon2Service does not advertise UriBeacon [\#13](https://github.com/ARMmbed/ble/issues/13)
|
||||
- Roadmap [\#3](https://github.com/ARMmbed/ble/issues/3)
|
||||
- nRF51822 advertising interval problem [\#2](https://github.com/ARMmbed/ble/issues/2)
|
||||
- nRF51822 low-power operation [\#1](https://github.com/ARMmbed/ble/issues/1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Added callback on characteristic reads [\#33](https://github.com/ARMmbed/ble/pull/33) ([jeremybrodt](https://github.com/jeremybrodt))
|
||||
- Updated UUID class to get length and pointer. Added UUID comparison. [\#32](https://github.com/ARMmbed/ble/pull/32) ([jeremybrodt](https://github.com/jeremybrodt))
|
||||
- Extended attribute length handling to support dynamic length. [\#31](https://github.com/ARMmbed/ble/pull/31) ([jeremybrodt](https://github.com/jeremybrodt))
|
||||
- added API for creating iBeacons [\#28](https://github.com/ARMmbed/ble/pull/28) ([BlackstoneEngineering](https://github.com/BlackstoneEngineering))
|
||||
- Uribeacon update [\#25](https://github.com/ARMmbed/ble/pull/25) ([schilit](https://github.com/schilit))
|
||||
- Fix README links [\#23](https://github.com/ARMmbed/ble/pull/23) ([shirishb](https://github.com/shirishb))
|
||||
- Added optional data and length fields to the return struct for authorize... [\#22](https://github.com/ARMmbed/ble/pull/22) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Chained callbacks for onDataSent [\#21](https://github.com/ARMmbed/ble/pull/21) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Updated Readme [\#20](https://github.com/ARMmbed/ble/pull/20) ([BlackstoneEngineering](https://github.com/BlackstoneEngineering))
|
||||
- Add getHandle for readability [\#18](https://github.com/ARMmbed/ble/pull/18) ([schilit](https://github.com/schilit))
|
||||
- make the library less dependent on the mbed.h header [\#5](https://github.com/ARMmbed/ble/pull/5) ([xiongyihui](https://github.com/xiongyihui))
|
||||
- adding initial readme with references to developer.mbed.org [\#4](https://github.com/ARMmbed/ble/pull/4) ([BlackstoneEngineering](https://github.com/BlackstoneEngineering))
|
||||
|
||||
|
||||
|
||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
@ -0,0 +1,7 @@
|
|||
# Hello!
|
||||
We are an open source project of [ARM mbed](https://www.mbed.com). Contributions via [pull request](https://github.com/ARMmbed/ble/pulls), and [bug reports](https://github.com/ARMmbed/ble/issues) are welcome!
|
||||
|
||||
Please submit your pull request to the `develop` branch of [this module](https://github.com/ARMmbed/ble/tree/develop). Commits to develop will be merge into the master branch at the time of the next release.
|
||||
|
||||
# Contributor agreement
|
||||
For your pull request to be accepted, we will need you to agree to our [contributor agreement](https://developer.mbed.org/contributor_agreement/) to give us the necessary rights to use and distribute your contributions. (To click through the agreement create an account on mbed.com and log in.)
|
|
@ -0,0 +1,30 @@
|
|||
# BLE API {#mainpage}
|
||||
|
||||
The BLE module within mbed OS offers a high abstraction level for using
|
||||
Bluetooth Low Energy on multiple platforms.
|
||||
|
||||
This documentation describes the internal structure of the mbed
|
||||
[BLE API](https://github.com/armmbed/ble).
|
||||
|
||||
For getting started with BLE on mbed, check our [introduction
|
||||
page](https://docs.mbed.com/docs/ble-intros/en/latest/).
|
||||
|
||||
For mbed OS examples using BLE, check [this
|
||||
repository](https://github.com/armmbed/ble-examples). For mbed-classic
|
||||
examples, please refer to [code under mbed.org](https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/).
|
||||
|
||||
## Supported Services
|
||||
|
||||
Currently supported reference services include:
|
||||
|
||||
* [Battery](@ref BatteryService)
|
||||
* [Device Firmware Update (DFU)](@ref DFUService)
|
||||
* [Device Information](@ref DeviceInformationService)
|
||||
* [Health Thermometer](@ref HealthThermometerService)
|
||||
* [Heart Rate](@ref HeartRateService)
|
||||
* [UART](@ref UARTService)
|
||||
* [UriBeacon](@ref URIBeaconConfigService)
|
||||
* [iBeacon](@ref iBeacon)
|
||||
|
||||
The [documentation](https://docs.mbed.com/docs/ble-intros/en/latest/AdvSamples/Overview/)
|
||||
contains an overview on how to create new, application-specific services.
|
|
@ -0,0 +1,2 @@
|
|||
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
|
|
@ -0,0 +1,28 @@
|
|||
# mbed Bluetooth Low Energy Stack
|
||||
This is the Github repo for the `BLE_API` used by developer.mbed.org. Please see the [mbed BLE Homepage](https://developer.mbed.org/teams/Bluetooth-Low-Energy/) for all documentation, code examples and general help.
|
||||
|
||||
# Supported Services
|
||||
Supported GATT services and constantly being added and can be found in the [ble/services/](https://github.com/ARMmbed/ble/tree/master/ble/services) folder.
|
||||
|
||||
Currently supported services include:
|
||||
* Battery
|
||||
* Device Firmware Update (DFU)
|
||||
* Device Information
|
||||
* Eddystone Configuration Service
|
||||
* Health Thermometer
|
||||
* Heart Rate
|
||||
* Link Loss
|
||||
* UART
|
||||
* UriBeacon
|
||||
* iBeacon
|
||||
|
||||
The [documentation](https://docs.mbed.com/docs/ble-intros/en/latest/AdvSamples/Overview/)
|
||||
contains an overview on how to create new, application-specific services.
|
||||
|
||||
# Getting Started
|
||||
The mbed BLE API is meant to be used in projects on developer.mbed.org. Please see examples and sample project files there.
|
||||
A good starting point are these pages:
|
||||
* [mbed BLE Homepage](https://developer.mbed.org/teams/Bluetooth-Low-Energy/) for all things BLE
|
||||
* [mbed BLE Getting Started Guide](https://developer.mbed.org/forum/team-63-Bluetooth-Low-Energy-community/topic/5262/) a wonderful primer on using BLE with mbed
|
||||
* [mbed BLE doc](https://docs.mbed.com/docs/ble-intros/en/latest/) for an introduction to mbed BLE
|
||||
* [mbed BLE API page](https://docs.mbed.com/docs/ble-api/en/latest/api/index.html) for the Doxygen API documentation
|
|
@ -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.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,176 @@
|
|||
/* 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 __BLE_DEVICE_INSTANCE_BASE__
|
||||
#define __BLE_DEVICE_INSTANCE_BASE__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/* Forward declarations. */
|
||||
class GattServer;
|
||||
class GattClient;
|
||||
|
||||
/**
|
||||
* The interface for the transport object to be created by the target library's
|
||||
* createBLEInstance().
|
||||
*
|
||||
* @note This class is part of the interface of BLE API with the implementation;
|
||||
* therefore, it is meant to be used only by porters rather than normal
|
||||
* BLE API users.
|
||||
*/
|
||||
class BLEInstanceBase
|
||||
{
|
||||
public:
|
||||
BLEInstanceBase() {}
|
||||
|
||||
/**
|
||||
* Virtual destructor of the interface.
|
||||
*/
|
||||
virtual ~BLEInstanceBase();
|
||||
|
||||
/**
|
||||
* Initialize the underlying BLE stack. This should be called before
|
||||
* anything else in the BLE API.
|
||||
*
|
||||
* @param[in] instanceID
|
||||
* The ID of the instance to initialize.
|
||||
* @param[in] initCallback
|
||||
* A callback for when initialization completes for a BLE
|
||||
* instance. This is an optional parameter set to NULL when not
|
||||
* supplied.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the initialization procedure was started
|
||||
* successfully.
|
||||
*/
|
||||
virtual ble_error_t init(BLE::InstanceID_t instanceID,
|
||||
FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> initCallback) = 0;
|
||||
|
||||
/**
|
||||
* Check whether the underlying stack has already been initialized,
|
||||
* possible with a call to init().
|
||||
*
|
||||
* @return true if the initialization has completed for the underlying BLE
|
||||
* stack.
|
||||
*/
|
||||
virtual bool hasInitialized(void) const = 0;
|
||||
|
||||
/**
|
||||
* Shutdown the underlying BLE stack. This includes purging the stack of
|
||||
* GATT and GAP state and clearing all state from other BLE components
|
||||
* such as the SecurityManager. init() must be called afterwards to
|
||||
* re-instantiate services and GAP state.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the underlying stack and all other services of
|
||||
* the BLE API were shutdown correctly.
|
||||
*/
|
||||
virtual ble_error_t shutdown(void) = 0;
|
||||
|
||||
/**
|
||||
* Fetches a string representation of the underlying BLE stack's version.
|
||||
*
|
||||
* @return A pointer to the string representation of the underlying
|
||||
* BLE stack's version.
|
||||
*/
|
||||
virtual const char * getVersion(void) = 0;
|
||||
|
||||
/**
|
||||
* Accessor to Gap. This function is used by BLE::gap().
|
||||
*
|
||||
* @return A reference to a Gap object associated to this BLE instance.
|
||||
*/
|
||||
virtual Gap& getGap() = 0;
|
||||
|
||||
/**
|
||||
* A const alternative to getGap().
|
||||
*
|
||||
* @return A const reference to a Gap object associated to this BLE instance.
|
||||
*/
|
||||
virtual const Gap& getGap() const = 0;
|
||||
|
||||
/**
|
||||
* Accessor to GattServer. This function is used by BLE::gattServer().
|
||||
*
|
||||
* @return A reference to a GattServer object associated to this BLE instance.
|
||||
*/
|
||||
virtual GattServer& getGattServer() = 0;
|
||||
|
||||
/**
|
||||
* A const alternative to getGattServer().
|
||||
*
|
||||
* @return A const reference to a GattServer object associated to this BLE instance.
|
||||
*/
|
||||
virtual const GattServer& getGattServer() const = 0;
|
||||
|
||||
/**
|
||||
* Accessors to GattClient. This function is used by BLE::gattClient().
|
||||
*
|
||||
* @return A reference to a GattClient object associated to this BLE instance.
|
||||
*/
|
||||
virtual GattClient& getGattClient() = 0;
|
||||
|
||||
/**
|
||||
* Accessors to SecurityManager. This function is used by BLE::securityManager().
|
||||
*
|
||||
* @return A reference to a SecurityManager object associated to this BLE instance.
|
||||
*/
|
||||
virtual SecurityManager& getSecurityManager() = 0;
|
||||
|
||||
/**
|
||||
* A const alternative to getSecurityManager().
|
||||
*
|
||||
* @return A const reference to a SecurityManager object associated to this BLE instance.
|
||||
*/
|
||||
virtual const SecurityManager& getSecurityManager() const = 0;
|
||||
|
||||
/**
|
||||
* Yield control to the BLE stack or to other tasks waiting for events.
|
||||
* refer to BLE::waitForEvent().
|
||||
*/
|
||||
virtual void waitForEvent(void) = 0;
|
||||
|
||||
/**
|
||||
* Process ALL pending events living in the BLE stack .
|
||||
* Return once all events have been consumed.
|
||||
*/
|
||||
virtual void processEvents() = 0;
|
||||
|
||||
/**
|
||||
* This function allow the BLE stack to signal that their is work to do and
|
||||
* event processing should be done (BLE::processEvent()).
|
||||
* @param id: The ID of the BLE instance which does have events to process.
|
||||
*/
|
||||
void signalEventsToProcess(BLE::InstanceID_t id);
|
||||
|
||||
private:
|
||||
// this class is not a value type.
|
||||
// prohibit copy construction and copy assignement
|
||||
BLEInstanceBase(const BLEInstanceBase&);
|
||||
BLEInstanceBase& operator=(const BLEInstanceBase&);
|
||||
};
|
||||
|
||||
/**
|
||||
* BLE uses composition to hide an interface object encapsulating the
|
||||
* backend transport.
|
||||
*
|
||||
* The following API is used to create the singleton interface object. An
|
||||
* implementation for this function must be provided by the device-specific
|
||||
* library, otherwise there will be a linker error.
|
||||
*/
|
||||
extern BLEInstanceBase *createBLEInstance(void);
|
||||
|
||||
#endif // ifndef __BLE_DEVICE_INSTANCE_BASE__
|
|
@ -0,0 +1,80 @@
|
|||
/* 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 __BLE_PROTOCOL_H__
|
||||
#define __BLE_PROTOCOL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* A common namespace for types and constants used everywhere in BLE API.
|
||||
*/
|
||||
namespace BLEProtocol {
|
||||
/**<
|
||||
* A simple container for the enumeration of address-types for Protocol addresses.
|
||||
*
|
||||
* Adding a struct to encapsulate the contained enumeration prevents
|
||||
* polluting the BLEProtocol namespace with the enumerated values. It also
|
||||
* allows type-aliases for the enumeration while retaining the enumerated
|
||||
* values. i.e. doing:
|
||||
* typedef AddressType AliasedType;
|
||||
*
|
||||
* would allow the use of AliasedType::PUBLIC in code.
|
||||
*/
|
||||
struct AddressType {
|
||||
/**< Address-types for Protocol addresses. */
|
||||
enum Type {
|
||||
PUBLIC = 0,
|
||||
RANDOM_STATIC,
|
||||
RANDOM_PRIVATE_RESOLVABLE,
|
||||
RANDOM_PRIVATE_NON_RESOLVABLE
|
||||
};
|
||||
};
|
||||
typedef AddressType::Type AddressType_t; /**< Alias for AddressType::Type */
|
||||
|
||||
static const size_t ADDR_LEN = 6; /**< Length (in octets) of the BLE MAC address. */
|
||||
typedef uint8_t AddressBytes_t[ADDR_LEN]; /**< 48-bit address, in LSB format. */
|
||||
|
||||
/**
|
||||
* BLE address. It contains an address-type (AddressType_t) and bytes (AddressBytes_t).
|
||||
*/
|
||||
struct Address_t {
|
||||
AddressType_t type; /**< The type of the BLE address. */
|
||||
AddressBytes_t address; /**< The BLE address. */
|
||||
|
||||
/**
|
||||
* Construct an Address_t object with the supplied type and address.
|
||||
*
|
||||
* @param[in] typeIn
|
||||
* The BLE address type.
|
||||
* @param[in] addressIn
|
||||
* The BLE address.
|
||||
*/
|
||||
Address_t(AddressType_t typeIn, const AddressBytes_t& addressIn) : type(typeIn) {
|
||||
std::copy(addressIn, addressIn + ADDR_LEN, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
*/
|
||||
Address_t() : type(), address() {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* __BLE_PROTOCOL_H__ */
|
|
@ -0,0 +1,271 @@
|
|||
/* 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 MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
|
||||
#define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
|
||||
|
||||
#include <string.h>
|
||||
#include "FunctionPointerWithContext.h"
|
||||
#include "SafeBool.h"
|
||||
|
||||
|
||||
/** Group one or more functions in an instance of a CallChainOfFunctionPointersWithContext, then call them in
|
||||
* sequence using CallChainOfFunctionPointersWithContext::call(). Used mostly by the interrupt chaining code,
|
||||
* but can be used for other purposes.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
*
|
||||
* CallChainOfFunctionPointersWithContext<void *> chain;
|
||||
*
|
||||
* void first(void *context) {
|
||||
* printf("'first' function.\n");
|
||||
* }
|
||||
*
|
||||
* void second(void *context) {
|
||||
* printf("'second' function.\n");
|
||||
* }
|
||||
*
|
||||
* class Test {
|
||||
* public:
|
||||
* void f(void *context) {
|
||||
* printf("A::f (class member).\n");
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* int main() {
|
||||
* Test test;
|
||||
*
|
||||
* chain.add(second);
|
||||
* chain.add_front(first);
|
||||
* chain.add(&test, &Test::f);
|
||||
* chain.call();
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
template <typename ContextType>
|
||||
class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > {
|
||||
public:
|
||||
/**
|
||||
* The type of each callback in the callchain.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create an empty chain.
|
||||
*/
|
||||
CallChainOfFunctionPointersWithContext() : chainHead(NULL) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
virtual ~CallChainOfFunctionPointersWithContext() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a function at the front of the chain.
|
||||
*
|
||||
* @param[in] function
|
||||
* A pointer to a void function.
|
||||
*
|
||||
* @return The function object created for @p function.
|
||||
*/
|
||||
pFunctionPointerWithContext_t add(void (*function)(ContextType context)) {
|
||||
return common_add(new FunctionPointerWithContext<ContextType>(function));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a function at the front of the chain.
|
||||
*
|
||||
* @param[in] tptr
|
||||
* Pointer to the object to call the member function on.
|
||||
* @param[in] mptr
|
||||
* Pointer to the member function to be called.
|
||||
*
|
||||
* @return The function object created for @p tptr and @p mptr.
|
||||
*/
|
||||
template<typename T>
|
||||
pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) {
|
||||
return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a function at the front of the chain.
|
||||
*
|
||||
* @param[in] func
|
||||
* The FunctionPointerWithContext to add.
|
||||
*
|
||||
* @return The function object created for @p func.
|
||||
*/
|
||||
pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) {
|
||||
return common_add(new FunctionPointerWithContext<ContextType>(func));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach a function pointer from a callchain.
|
||||
*
|
||||
* @param[in] toDetach
|
||||
* FunctionPointerWithContext to detach from this callchain.
|
||||
*
|
||||
* @return true if a function pointer has been detached and false otherwise.
|
||||
*
|
||||
* @note It is safe to remove a function pointer while the chain is
|
||||
* traversed by call(ContextType).
|
||||
*/
|
||||
bool detach(const FunctionPointerWithContext<ContextType>& toDetach) {
|
||||
pFunctionPointerWithContext_t current = chainHead;
|
||||
pFunctionPointerWithContext_t previous = NULL;
|
||||
|
||||
while (current) {
|
||||
if(*current == toDetach) {
|
||||
if(previous == NULL) {
|
||||
if(currentCalled == current) {
|
||||
currentCalled = NULL;
|
||||
}
|
||||
chainHead = current->getNext();
|
||||
} else {
|
||||
if(currentCalled == current) {
|
||||
currentCalled = previous;
|
||||
}
|
||||
previous->chainAsNext(current->getNext());
|
||||
}
|
||||
delete current;
|
||||
return true;
|
||||
}
|
||||
|
||||
previous = current;
|
||||
current = current->getNext();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the call chain (remove all functions in the chain).
|
||||
*/
|
||||
void clear(void) {
|
||||
pFunctionPointerWithContext_t fptr = chainHead;
|
||||
while (fptr) {
|
||||
pFunctionPointerWithContext_t deadPtr = fptr;
|
||||
fptr = deadPtr->getNext();
|
||||
delete deadPtr;
|
||||
}
|
||||
|
||||
chainHead = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the callchain contains any callbacks.
|
||||
*
|
||||
* @return true if the callchain is not empty and false otherwise.
|
||||
*/
|
||||
bool hasCallbacksAttached(void) const {
|
||||
return (chainHead != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call all the functions in the chain in sequence.
|
||||
*/
|
||||
void call(ContextType context) {
|
||||
((const CallChainOfFunctionPointersWithContext*) this)->call(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as call() above, but const.
|
||||
*/
|
||||
void call(ContextType context) const {
|
||||
currentCalled = chainHead;
|
||||
|
||||
while(currentCalled) {
|
||||
currentCalled->call(context);
|
||||
// if this was the head and the call removed the head
|
||||
if(currentCalled == NULL) {
|
||||
currentCalled = chainHead;
|
||||
} else {
|
||||
currentCalled = currentCalled->getNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as call(), but with function call operator.
|
||||
* @code
|
||||
*
|
||||
* void first(bool);
|
||||
* void second(bool);
|
||||
*
|
||||
* CallChainOfFunctionPointerWithContext<bool> foo;
|
||||
*
|
||||
* foo.attach(first);
|
||||
* foo.attach(second);
|
||||
*
|
||||
* // call the callchain like a function
|
||||
* foo(true);
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
void operator()(ContextType context) const {
|
||||
call(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bool conversion operation.
|
||||
*
|
||||
* @return true if the callchain is not empty and false otherwise.
|
||||
*/
|
||||
bool toBool() const {
|
||||
return chainHead != NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Add a callback to the head of the callchain.
|
||||
*
|
||||
* @return A pointer to the head of the callchain.
|
||||
*/
|
||||
pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) {
|
||||
if (chainHead == NULL) {
|
||||
chainHead = pf;
|
||||
} else {
|
||||
pf->chainAsNext(chainHead);
|
||||
chainHead = pf;
|
||||
}
|
||||
|
||||
return chainHead;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* A pointer to the first callback in the callchain or NULL if the callchain is empty.
|
||||
*/
|
||||
pFunctionPointerWithContext_t chainHead;
|
||||
|
||||
/**
|
||||
* Iterator during a function call, this has to be mutable because the call function is const.
|
||||
*
|
||||
* @note Mutable is the correct behaviour here, the iterator never leaks outside the object.
|
||||
* so the object can still be seen as logically const even if it is modified.
|
||||
*/
|
||||
mutable pFunctionPointerWithContext_t currentCalled;
|
||||
|
||||
|
||||
/* Disallow copy constructor and assignment operators. */
|
||||
private:
|
||||
CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &);
|
||||
CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
|
||||
#ifndef __CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
||||
#define __CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
||||
|
||||
#include "FunctionPointerWithContext.h"
|
||||
|
||||
class DiscoveredCharacteristic; // forward declaration
|
||||
class DiscoveredCharacteristicDescriptor; // forward declaration
|
||||
|
||||
/**
|
||||
* @brief Contain all definitions of callbacks and callbacks parameters types
|
||||
* related to characteristic descriptor discovery.
|
||||
*
|
||||
* @details This class act like a namespace for characteristic descriptor discovery
|
||||
* types. It act like ServiceDiscovery by providing callbacks and callbacks
|
||||
* parameters types related to the characteristic descriptor discovery process but
|
||||
* contrary to ServiceDiscovery class, it does not force the porter to use a
|
||||
* specific interface for the characteristic descriptor discovery process.
|
||||
*/
|
||||
class CharacteristicDescriptorDiscovery {
|
||||
public:
|
||||
/**
|
||||
* @brief Parameter type of CharacteristicDescriptorDiscovery::DiscoveryCallback_t.
|
||||
* @details Every time a characteristic descriptor has been discovered, the callback
|
||||
* registered for the discovery operation through GattClient::discoverCharacteristicDescriptors
|
||||
* or DiscoveredCharacteristic::discoverDescriptors will be called with this parameter.
|
||||
*
|
||||
*/
|
||||
struct DiscoveryCallbackParams_t {
|
||||
/**
|
||||
* The characteristic owning the DiscoveredCharacteristicDescriptor
|
||||
*/
|
||||
const DiscoveredCharacteristic& characteristic;
|
||||
|
||||
/**
|
||||
* The characteristic descriptor discovered
|
||||
*/
|
||||
const DiscoveredCharacteristicDescriptor& descriptor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter type of CharacteristicDescriptorDiscovery::TerminationCallback_t.
|
||||
* @details Once a characteristic descriptor discovery process terminate, the termination
|
||||
* callback registered for the discovery operation through
|
||||
* GattClient::discoverCharacteristicDescriptors or DiscoveredCharacteristic::discoverDescriptors
|
||||
* will be called with this parameter.
|
||||
*/
|
||||
struct TerminationCallbackParams_t {
|
||||
/**
|
||||
* The characteristic for which the descriptors has been discovered
|
||||
*/
|
||||
const DiscoveredCharacteristic& characteristic;
|
||||
|
||||
/**
|
||||
* status of the discovery operation
|
||||
*/
|
||||
ble_error_t status;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Callback type for when a matching characteristic descriptor is found during
|
||||
* characteristic descriptor discovery.
|
||||
*
|
||||
* @param param A pointer to a DiscoveryCallbackParams_t object which will remain
|
||||
* valid for the lifetime of the callback. Memory for this object is owned by
|
||||
* the BLE_API eventing framework. The application can safely make a persistent
|
||||
* shallow-copy of this object in order to work with the service beyond the
|
||||
* callback.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const DiscoveryCallbackParams_t*> DiscoveryCallback_t;
|
||||
|
||||
/**
|
||||
* @brief Callback type for when characteristic descriptor discovery terminates.
|
||||
*
|
||||
* @param param A pointer to a TerminationCallbackParams_t object which will remain
|
||||
* valid for the lifetime of the callback. Memory for this object is owned by
|
||||
* the BLE_API eventing framework. The application can safely make a persistent
|
||||
* shallow-copy of this object in order to work with the service beyond the
|
||||
* callback.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const TerminationCallbackParams_t*> TerminationCallback_t;
|
||||
};
|
||||
|
||||
#endif // ifndef __CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
|
@ -0,0 +1,433 @@
|
|||
/* 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 __DISCOVERED_CHARACTERISTIC_H__
|
||||
#define __DISCOVERED_CHARACTERISTIC_H__
|
||||
|
||||
#include "UUID.h"
|
||||
#include "Gap.h"
|
||||
#include "GattAttribute.h"
|
||||
#include "GattClient.h"
|
||||
#include "CharacteristicDescriptorDiscovery.h"
|
||||
#include "ble/DiscoveredCharacteristicDescriptor.h"
|
||||
|
||||
/**
|
||||
* @brief Representation of a characteristic discovered during a GattClient
|
||||
* discovery procedure (see GattClient::launchServiceDiscovery ).
|
||||
*
|
||||
* @details Provide detailed informations about a discovered characteristic like:
|
||||
* - Its UUID (see getUUID()).
|
||||
* - The most important handles of the characteristic definition
|
||||
* (see getDeclHandle(), getValueHandle(), getLastHandle())
|
||||
* - Its properties (see getProperties()).
|
||||
* This class also provide functions to operate on the characteristic:
|
||||
* - Read the characteristic value (see read())
|
||||
* - Writing a characteristic value (see write() or writeWoResponse())
|
||||
* - Discover descriptors inside the characteristic definition. These descriptors
|
||||
* extends the characteristic. More information about descriptor usage is
|
||||
* available in DiscoveredCharacteristicDescriptor class.
|
||||
*/
|
||||
class DiscoveredCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Structure that encapsulates the properties of a discovered
|
||||
* characteristic.
|
||||
*/
|
||||
struct Properties_t {
|
||||
uint8_t _broadcast :1; /**< Broadcasting the value permitted. */
|
||||
uint8_t _read :1; /**< Reading the value permitted. */
|
||||
uint8_t _writeWoResp :1; /**< Writing the value with Write Command permitted. */
|
||||
uint8_t _write :1; /**< Writing the value with Write Request permitted. */
|
||||
uint8_t _notify :1; /**< Notifications of the value permitted. */
|
||||
uint8_t _indicate :1; /**< Indications of the value permitted. */
|
||||
uint8_t _authSignedWrite :1; /**< Writing the value with Signed Write Command permitted. */
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Check if broadcasting is permitted.
|
||||
*
|
||||
* @return true if broadcasting the value is permitted, and false
|
||||
* otherwise.
|
||||
*/
|
||||
bool broadcast(void) const {
|
||||
return _broadcast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check reading is permitted.
|
||||
*
|
||||
* @return true if reading the value is permitted, and false
|
||||
* otherwise.
|
||||
*/
|
||||
bool read(void) const {
|
||||
return _read;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if writing with Write Command is permitted.
|
||||
*
|
||||
* @return true if writing the value with Write Command is permitted,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool writeWoResp(void) const {
|
||||
return _writeWoResp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if writing with Write Request is permitted.
|
||||
*
|
||||
* @return true if writing the value with Write Request is permitted,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool write(void) const {
|
||||
return _write;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check notifications are permitted.
|
||||
*
|
||||
* @return true if notifications of the value are permitted, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool notify(void) const {
|
||||
return _notify;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if indications are permitted.
|
||||
*
|
||||
* @return true if indications of the value are permitted, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool indicate(void) const {
|
||||
return _indicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if writing with Signed Write Command is permitted.
|
||||
*
|
||||
* @return true if writing the value with Signed Write Command is
|
||||
* permitted, false otherwise.
|
||||
*/
|
||||
bool authSignedWrite(void) const {
|
||||
return _authSignedWrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Equal to" operator for DiscoveredCharacteristic::Properties_t
|
||||
*
|
||||
* @param[in] lhs The left hand side of the equality expression
|
||||
* @param[in] rhs The right hand side of the equality expression
|
||||
*
|
||||
* @return true if operands are equals, false otherwise.
|
||||
*/
|
||||
friend bool operator==(Properties_t lhs, Properties_t rhs) {
|
||||
return lhs._broadcast == rhs._broadcast &&
|
||||
lhs._read == rhs._read &&
|
||||
lhs._writeWoResp == rhs._writeWoResp &&
|
||||
lhs._write == rhs._write &&
|
||||
lhs._notify == rhs._notify &&
|
||||
lhs._indicate == rhs._indicate &&
|
||||
lhs._authSignedWrite == rhs._authSignedWrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Not equal to" operator for DiscoveredCharacteristic::Properties_t
|
||||
*
|
||||
* @param lhs The right hand side of the expression
|
||||
* @param rhs The left hand side of the expression
|
||||
*
|
||||
* @return true if operands are not equals, false otherwise.
|
||||
*/
|
||||
friend bool operator!=(Properties_t lhs, Properties_t rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
operator uint8_t() const; /* Disallow implicit conversion into an integer. */
|
||||
operator unsigned() const; /* Disallow implicit conversion into an integer. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiate (or continue) a read for the value attribute, optionally at a
|
||||
* given offset. If the characteristic or descriptor to be read is longer
|
||||
* than ATT_MTU - 1, this function must be called multiple times with
|
||||
* appropriate offset to read the complete value.
|
||||
*
|
||||
* @param[in] offset
|
||||
* The position - in the characteristic value bytes stream - where
|
||||
* the read operation begin.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if a read has been initiated, or
|
||||
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
|
||||
* BLE_STACK_BUSY if some client procedure is already in progress, or
|
||||
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
|
||||
*/
|
||||
ble_error_t read(uint16_t offset = 0) const;
|
||||
|
||||
/**
|
||||
* @brief Same as #read(uint16_t) const but allow the user to register a callback
|
||||
* which will be fired once the read is done.
|
||||
*
|
||||
* @param[in] offset
|
||||
* The position - in the characteristic value bytes stream - where
|
||||
* the read operation begin.
|
||||
* @param[in] onRead
|
||||
* Continuation of the read operation
|
||||
*/
|
||||
ble_error_t read(uint16_t offset, const GattClient::ReadCallback_t& onRead) const;
|
||||
|
||||
/**
|
||||
* Perform a write without response procedure.
|
||||
*
|
||||
* @param[in] length
|
||||
* The amount of data being written.
|
||||
* @param[in] value
|
||||
* The bytes being written.
|
||||
*
|
||||
* @note It is important to note that a write without response will generate
|
||||
* an onDataSent() callback when the packet has been transmitted. There
|
||||
* will be a BLE-stack specific limit to the number of pending
|
||||
* writeWoResponse operations; the user may want to use the onDataSent()
|
||||
* callback for flow-control.
|
||||
*
|
||||
* @retval BLE_ERROR_NONE Successfully started the Write procedure, or
|
||||
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
|
||||
* BLE_STACK_BUSY if some client procedure is already in progress, or
|
||||
* BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
|
||||
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
|
||||
*/
|
||||
ble_error_t writeWoResponse(uint16_t length, const uint8_t *value) const;
|
||||
|
||||
/**
|
||||
* Initiate a GATT Characteristic Descriptor Discovery procedure for descriptors within this characteristic.
|
||||
*
|
||||
* @param[in] onDescriptorDiscovered This callback will be called every time a descriptor is discovered
|
||||
* @param[in] onTermination This callback will be called when the discovery process is over.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if descriptor discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
ble_error_t discoverDescriptors(const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& onDescriptorDiscovered,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& onTermination) const;
|
||||
|
||||
/**
|
||||
* Perform a write procedure.
|
||||
*
|
||||
* @param[in] length
|
||||
* The amount of data being written.
|
||||
* @param[in] value
|
||||
* The bytes being written.
|
||||
*
|
||||
* @note It is important to note that a write will generate
|
||||
* an onDataWritten() callback when the peer acknowledges the request.
|
||||
*
|
||||
* @retval BLE_ERROR_NONE Successfully started the Write procedure, or
|
||||
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
|
||||
* BLE_STACK_BUSY if some client procedure is already in progress, or
|
||||
* BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
|
||||
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
|
||||
*/
|
||||
ble_error_t write(uint16_t length, const uint8_t *value) const;
|
||||
|
||||
/**
|
||||
* Same as write(uint16_t, const uint8_t *) const but register a callback
|
||||
* which will be called once the data has been written.
|
||||
*
|
||||
* @param[in] length
|
||||
* The amount of bytes to write.
|
||||
* @param[in] value
|
||||
* The bytes to write.
|
||||
* @param[in] onWrite
|
||||
* Continuation callback for the write operation
|
||||
*
|
||||
* @retval BLE_ERROR_NONE Successfully started the Write procedure, or
|
||||
* BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
|
||||
* BLE_STACK_BUSY if some client procedure is already in progress, or
|
||||
* BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
|
||||
* BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
|
||||
*/
|
||||
ble_error_t write(uint16_t length, const uint8_t *value, const GattClient::WriteCallback_t& onWrite) const;
|
||||
|
||||
void setupLongUUID(UUID::LongUUIDBytes_t longUUID, UUID::ByteOrder_t order = UUID::MSB) {
|
||||
uuid.setupLong(longUUID, order);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the UUID of the discovered characteristic
|
||||
* @return the UUID of this characteristic
|
||||
*/
|
||||
const UUID& getUUID(void) const {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the properties of this characteristic
|
||||
* @return the set of properties of this characteristic
|
||||
*/
|
||||
const Properties_t& getProperties(void) const {
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the declaration handle of this characteristic.
|
||||
* @details The declaration handle is the first handle of a characteristic
|
||||
* definition. The value accessible at this handle contains the following
|
||||
* informations:
|
||||
* - The characteristics properties (see Properties_t). This value can
|
||||
* be accessed by using #getProperties .
|
||||
* - The characteristic value attribute handle. This field can be accessed
|
||||
* by using #getValueHandle .
|
||||
* - The characteristic UUID, this value can be accessed by using the
|
||||
* function #getUUID .
|
||||
* @return the declaration handle of this characteristic.
|
||||
*/
|
||||
GattAttribute::Handle_t getDeclHandle(void) const {
|
||||
return declHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the handle used to access the value of this characteristic.
|
||||
* @details This handle is the one provided in the characteristic declaration
|
||||
* value. Usually, it is equal to #getDeclHandle() + 1. But it is not always
|
||||
* the case. Anyway, users are allowed to use #getDeclHandle() + 1 to access
|
||||
* the value of a characteristic.
|
||||
* @return The handle to access the value of this characteristic.
|
||||
*/
|
||||
GattAttribute::Handle_t getValueHandle(void) const {
|
||||
return valueHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the last handle of the characteristic definition.
|
||||
* @details A Characteristic definition can contain a lot of handles:
|
||||
* - one for the declaration (see #getDeclHandle)
|
||||
* - one for the value (see #getValueHandle)
|
||||
* - zero of more for the characteristic descriptors.
|
||||
* This handle is the last handle of the characteristic definition.
|
||||
* @return The last handle of this characteristic definition.
|
||||
*/
|
||||
GattAttribute::Handle_t getLastHandle(void) const {
|
||||
return lastHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the GattClient which can operate on this characteristic.
|
||||
* @return The GattClient which can operate on this characteristic.
|
||||
*/
|
||||
GattClient* getGattClient() {
|
||||
return gattc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the GattClient which can operate on this characteristic.
|
||||
* @return The GattClient which can operate on this characteristic.
|
||||
*/
|
||||
const GattClient* getGattClient() const {
|
||||
return gattc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the connection handle to the GattServer which contain
|
||||
* this characteristic.
|
||||
* @return the connection handle to the GattServer which contain
|
||||
* this characteristic.
|
||||
*/
|
||||
Gap::Handle_t getConnectionHandle() const {
|
||||
return connHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Equal to" operator for DiscoveredCharacteristic
|
||||
*
|
||||
* @param[in] lhs
|
||||
* The left hand side of the equality expression
|
||||
* @param[in] rhs
|
||||
* The right hand side of the equality expression
|
||||
*
|
||||
* @return true if operands are equals, false otherwise.
|
||||
*/
|
||||
friend bool operator==(const DiscoveredCharacteristic& lhs, const DiscoveredCharacteristic& rhs) {
|
||||
return lhs.gattc == rhs.gattc &&
|
||||
lhs.uuid == rhs.uuid &&
|
||||
lhs.props == rhs.props &&
|
||||
lhs.declHandle == rhs.declHandle &&
|
||||
lhs.valueHandle == rhs.valueHandle &&
|
||||
lhs.lastHandle == rhs.lastHandle &&
|
||||
lhs.connHandle == rhs.connHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Not equal to" operator for DiscoveredCharacteristic
|
||||
*
|
||||
* @param[in] lhs
|
||||
* The right hand side of the expression
|
||||
* @param[in] rhs
|
||||
* The left hand side of the expression
|
||||
*
|
||||
* @return true if operands are not equal, false otherwise.
|
||||
*/
|
||||
friend bool operator !=(const DiscoveredCharacteristic& lhs, const DiscoveredCharacteristic& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
public:
|
||||
DiscoveredCharacteristic() : gattc(NULL),
|
||||
uuid(UUID::ShortUUIDBytes_t(0)),
|
||||
props(),
|
||||
declHandle(GattAttribute::INVALID_HANDLE),
|
||||
valueHandle(GattAttribute::INVALID_HANDLE),
|
||||
lastHandle(GattAttribute::INVALID_HANDLE),
|
||||
connHandle() {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Pointer to the underlying GattClient for this DiscoveredCharacteristic object.
|
||||
*/
|
||||
GattClient *gattc;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Discovered characteristic's UUID.
|
||||
*/
|
||||
UUID uuid;
|
||||
/**
|
||||
* Hold the configured properties of the discovered characteristic.
|
||||
* For more information refer to Properties_t.
|
||||
*/
|
||||
Properties_t props;
|
||||
/**
|
||||
* Value handle of the discovered characteristic's declaration attribute.
|
||||
*/
|
||||
GattAttribute::Handle_t declHandle;
|
||||
/**
|
||||
* Value handle of the discovered characteristic's value attribute.
|
||||
*/
|
||||
GattAttribute::Handle_t valueHandle;
|
||||
/**
|
||||
* Value handle of the discovered characteristic's last attribute.
|
||||
*/
|
||||
GattAttribute::Handle_t lastHandle;
|
||||
|
||||
/**
|
||||
* Handle for the connection where the characteristic was discovered.
|
||||
*/
|
||||
Gap::Handle_t connHandle;
|
||||
};
|
||||
|
||||
#endif /*__DISCOVERED_CHARACTERISTIC_H__*/
|
|
@ -0,0 +1,111 @@
|
|||
/* 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 __DISCOVERED_CHARACTERISTIC_DESCRIPTOR_H__
|
||||
#define __DISCOVERED_CHARACTERISTIC_DESCRIPTOR_H__
|
||||
|
||||
#include "UUID.h"
|
||||
#include "Gap.h"
|
||||
#include "GattAttribute.h"
|
||||
#include "GattClient.h"
|
||||
#include "CharacteristicDescriptorDiscovery.h"
|
||||
|
||||
/**
|
||||
* @brief Representation of a descriptor discovered during a GattClient
|
||||
* discovery procedure (see GattClient::discoverCharacteristicDescriptors or
|
||||
* DiscoveredCharacteristic::discoverDescriptors ).
|
||||
*
|
||||
* @details Provide detailed informations about a discovered characteristic descriptor
|
||||
* like:
|
||||
* - Its UUID (see #getUUID).
|
||||
* - Its handle (see #getAttributeHandle)
|
||||
* Basic read (see GattClient::read) and write (see GattClient::write) procedure from
|
||||
* GattClient can be used access the value of the descriptor.
|
||||
*
|
||||
* @todo read member function
|
||||
* @todo write member function
|
||||
* @todo enumeration of standard descriptors
|
||||
*/
|
||||
class DiscoveredCharacteristicDescriptor {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief construct a new instance of a DiscoveredCharacteristicDescriptor
|
||||
*
|
||||
* @param client The client from where the descriptor has been discovered
|
||||
* @param connectionHandle The connection handle on which the descriptor has
|
||||
* been discovered
|
||||
* @param attributeHandle The handle of the attribute containing this descriptor
|
||||
* @param uuid The UUID of the descriptor
|
||||
*/
|
||||
DiscoveredCharacteristicDescriptor(
|
||||
GattClient* client, Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const UUID& uuid) :
|
||||
_client(client), _connectionHandle(connectionHandle), _uuid(uuid), _gattHandle(attributeHandle) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the GattClient which can operate on this descriptor.
|
||||
* @return The GattClient which can operate on this descriptor.
|
||||
*/
|
||||
GattClient* getGattClient() {
|
||||
return _client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the GattClient which can operate on this descriptor.
|
||||
* @return The GattClient which can operate on this descriptor.
|
||||
*/
|
||||
const GattClient* getGattClient() const {
|
||||
return _client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the connection handle to the GattServer which contain
|
||||
* this descriptor.
|
||||
* @return the connection handle to the GattServer which contain
|
||||
* this descriptor.
|
||||
*/
|
||||
Gap::Handle_t getConnectionHandle() const {
|
||||
return _connectionHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the UUID of this descriptor
|
||||
* @return the UUID of this descriptor
|
||||
*/
|
||||
const UUID& getUUID(void) const {
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the attribute handle to use to access to this descriptor
|
||||
* on the gatt server.
|
||||
* @return The attribute handle of the descriptor
|
||||
*/
|
||||
GattAttribute::Handle_t getAttributeHandle() const {
|
||||
return _gattHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
GattClient *_client;
|
||||
Gap::Handle_t _connectionHandle;
|
||||
UUID _uuid;
|
||||
GattAttribute::Handle_t _gattHandle;
|
||||
};
|
||||
|
||||
#endif /*__DISCOVERED_CHARACTERISTIC_DESCRIPTOR_H__*/
|
|
@ -0,0 +1,119 @@
|
|||
/* 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 __DISCOVERED_SERVICE_H__
|
||||
#define __DISCOVERED_SERVICE_H__
|
||||
|
||||
#include "UUID.h"
|
||||
#include "GattAttribute.h"
|
||||
|
||||
/**@brief Type for holding information about the service and the characteristics found during
|
||||
* the discovery process.
|
||||
*/
|
||||
class DiscoveredService {
|
||||
public:
|
||||
/**
|
||||
* Set information about the discovered service.
|
||||
*
|
||||
* @param[in] uuidIn
|
||||
* The UUID of the discovered service.
|
||||
* @param[in] startHandleIn
|
||||
* The start handle of the discovered service in the peer's
|
||||
* ATT table.
|
||||
* @param[in] endHandleIn
|
||||
* The end handle of the discovered service in the peer's
|
||||
* ATT table.
|
||||
*/
|
||||
void setup(UUID uuidIn, GattAttribute::Handle_t startHandleIn, GattAttribute::Handle_t endHandleIn) {
|
||||
uuid = uuidIn;
|
||||
startHandle = startHandleIn;
|
||||
endHandle = endHandleIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start and end handle of the discovered service.
|
||||
* @param[in] startHandleIn
|
||||
* The start handle of the discovered service in the peer's
|
||||
* ATT table.
|
||||
* @param[in] endHandleIn
|
||||
* The end handle of the discovered service in the peer's
|
||||
* ATT table.
|
||||
*/
|
||||
void setup(GattAttribute::Handle_t startHandleIn, GattAttribute::Handle_t endHandleIn) {
|
||||
startHandle = startHandleIn;
|
||||
endHandle = endHandleIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the long UUID of the discovered service.
|
||||
*
|
||||
* @param[in] longUUID
|
||||
* The long UUID of the discovered service.
|
||||
* @param[in] order
|
||||
* The byte ordering of @p longUUID.
|
||||
*/
|
||||
void setupLongUUID(UUID::LongUUIDBytes_t longUUID, UUID::ByteOrder_t order = UUID::MSB) {
|
||||
uuid.setupLong(longUUID, order);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the UUID of the discovered service.
|
||||
*
|
||||
* @return A reference to the UUID of the discovered service.
|
||||
*/
|
||||
const UUID &getUUID(void) const {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start handle of the discovered service in the peer's ATT table.
|
||||
*
|
||||
* @return A reference to the start handle.
|
||||
*/
|
||||
const GattAttribute::Handle_t& getStartHandle(void) const {
|
||||
return startHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end handle of the discovered service in the peer's ATT table.
|
||||
*
|
||||
* @return A reference to the end handle.
|
||||
*/
|
||||
const GattAttribute::Handle_t& getEndHandle(void) const {
|
||||
return endHandle;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a DiscoveredService instance.
|
||||
*/
|
||||
DiscoveredService() : uuid(UUID::ShortUUIDBytes_t(0)),
|
||||
startHandle(GattAttribute::INVALID_HANDLE),
|
||||
endHandle(GattAttribute::INVALID_HANDLE) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
private:
|
||||
DiscoveredService(const DiscoveredService &);
|
||||
|
||||
private:
|
||||
UUID uuid; /**< UUID of the service. */
|
||||
GattAttribute::Handle_t startHandle; /**< Service Handle Range. */
|
||||
GattAttribute::Handle_t endHandle; /**< Service Handle Range. */
|
||||
};
|
||||
|
||||
#endif /*__DISCOVERED_SERVICE_H__*/
|
|
@ -0,0 +1,212 @@
|
|||
/* 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 MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
|
||||
#define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
|
||||
|
||||
#include <string.h>
|
||||
#include "SafeBool.h"
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function
|
||||
* that takes a context.
|
||||
*/
|
||||
template <typename ContextType>
|
||||
class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<ContextType> > {
|
||||
public:
|
||||
typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
|
||||
typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t;
|
||||
typedef void (*pvoidfcontext_t)(ContextType context);
|
||||
|
||||
/** Create a FunctionPointerWithContext, attaching a static function.
|
||||
*
|
||||
* @param function The void static function to attach (default is none).
|
||||
*/
|
||||
FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
|
||||
_memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointerWithContext, attaching a member function.
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (the "this" pointer).
|
||||
* @param function The address of the void member function to attach.
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
|
||||
_memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
FunctionPointerWithContext(const FunctionPointerWithContext& that) :
|
||||
_memberFunctionAndPointer(that._memberFunctionAndPointer), _caller(that._caller), _next(NULL) {
|
||||
}
|
||||
|
||||
FunctionPointerWithContext& operator=(const FunctionPointerWithContext& that) {
|
||||
_memberFunctionAndPointer = that._memberFunctionAndPointer;
|
||||
_caller = that._caller;
|
||||
_next = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Attach a static function.
|
||||
*
|
||||
* @param function The void static function to attach (default is none).
|
||||
*/
|
||||
void attach(void (*function)(ContextType context) = NULL) {
|
||||
_function = function;
|
||||
_caller = functioncaller;
|
||||
}
|
||||
|
||||
/** Attach a member function.
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (the "this" pointer).
|
||||
* @param function The address of the void member function to attach.
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, void (T::*member)(ContextType context)) {
|
||||
_memberFunctionAndPointer._object = static_cast<void *>(object);
|
||||
memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member));
|
||||
_caller = &FunctionPointerWithContext::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function; if there are chained
|
||||
* FunctionPointers their callbacks are invoked as well.
|
||||
* @Note: All chained callbacks stack up, so hopefully there won't be too
|
||||
* many FunctionPointers in a chain. */
|
||||
void call(ContextType context) const {
|
||||
_caller(this, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Same as above
|
||||
*/
|
||||
void operator()(ContextType context) const {
|
||||
call(context);
|
||||
}
|
||||
|
||||
/** Same as above, workaround for mbed os FunctionPointer implementation. */
|
||||
void call(ContextType context) {
|
||||
((const FunctionPointerWithContext*) this)->call(context);
|
||||
}
|
||||
|
||||
typedef void (FunctionPointerWithContext::*bool_type)() const;
|
||||
|
||||
/**
|
||||
* implementation of safe bool operator
|
||||
*/
|
||||
bool toBool() const {
|
||||
return (_function || _memberFunctionAndPointer._object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up an external FunctionPointer as a next in the chain of related
|
||||
* callbacks. Invoking call() on the head FunctionPointer will invoke all
|
||||
* chained callbacks.
|
||||
*
|
||||
* Refer to 'CallChain' as an alternative.
|
||||
*/
|
||||
void chainAsNext(pFunctionPointerWithContext_t next) {
|
||||
_next = next;
|
||||
}
|
||||
|
||||
pFunctionPointerWithContext_t getNext(void) const {
|
||||
return _next;
|
||||
}
|
||||
|
||||
pvoidfcontext_t get_function() const {
|
||||
return (pvoidfcontext_t)_function;
|
||||
}
|
||||
|
||||
friend bool operator==(const FunctionPointerWithContext& lhs, const FunctionPointerWithContext& rhs) {
|
||||
return rhs._caller == lhs._caller &&
|
||||
memcmp(
|
||||
&rhs._memberFunctionAndPointer,
|
||||
&lhs._memberFunctionAndPointer,
|
||||
sizeof(rhs._memberFunctionAndPointer)
|
||||
) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) {
|
||||
if (self->_memberFunctionAndPointer._object) {
|
||||
T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
|
||||
void (T::*m)(ContextType);
|
||||
memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m));
|
||||
(o->*m)(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) {
|
||||
if (self->_function) {
|
||||
self->_function(context);
|
||||
}
|
||||
}
|
||||
|
||||
struct MemberFunctionAndPtr {
|
||||
/*
|
||||
* Forward declaration of a class and a member function to this class.
|
||||
* Because the compiler doesn't know anything about the forwarded member
|
||||
* function, it will always use the biggest size and the biggest alignment
|
||||
* that a member function can take for objects of type UndefinedMemberFunction.
|
||||
*/
|
||||
class UndefinedClass;
|
||||
typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType);
|
||||
|
||||
void* _object;
|
||||
union {
|
||||
char _memberFunction[sizeof(UndefinedMemberFunction)];
|
||||
UndefinedMemberFunction _alignment;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
pvoidfcontext_t _function; /**< Static function pointer - NULL if none attached */
|
||||
/**
|
||||
* object this pointer and pointer to member -
|
||||
* _memberFunctionAndPointer._object will be NULL if none attached
|
||||
*/
|
||||
mutable MemberFunctionAndPtr _memberFunctionAndPointer;
|
||||
};
|
||||
|
||||
void (*_caller)(const FunctionPointerWithContext*, ContextType);
|
||||
|
||||
pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers. This
|
||||
* allows chaining function pointers without requiring
|
||||
* external memory to manage the chain. Refer to
|
||||
* 'CallChain' as an alternative. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new FunctionPointerWithContext which bind an instance and a
|
||||
* a member function together.
|
||||
* @details This little helper is a just here to eliminate the need to write the
|
||||
* FunctionPointerWithContext type each time you want to create one by kicking
|
||||
* automatic type deduction of function templates. With this function, it is easy
|
||||
* to write only one entry point for functions which expect a FunctionPointer
|
||||
* in parameters.
|
||||
*
|
||||
* @param object to bound with member function
|
||||
* @param member The member function called
|
||||
* @return a new FunctionPointerWithContext
|
||||
*/
|
||||
template<typename T, typename ContextType>
|
||||
FunctionPointerWithContext<ContextType> makeFunctionPointer(T *object, void (T::*member)(ContextType context))
|
||||
{
|
||||
return FunctionPointerWithContext<ContextType>(object, member);
|
||||
}
|
||||
|
||||
#endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
|
|
@ -0,0 +1,567 @@
|
|||
/* 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 __GAP_ADVERTISING_DATA_H__
|
||||
#define __GAP_ADVERTISING_DATA_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blecommon.h"
|
||||
|
||||
#define GAP_ADVERTISING_DATA_MAX_PAYLOAD (31)
|
||||
|
||||
/**
|
||||
* @brief This class provides several helper functions to generate properly
|
||||
* formatted GAP Advertising and Scan Response data payloads.
|
||||
*
|
||||
* @note See Bluetooth Specification 4.0 (Vol. 3), Part C, Sections 11 and 18
|
||||
* for further information on Advertising and Scan Response data.
|
||||
*
|
||||
* @par Advertising and Scan Response Payloads
|
||||
* Advertising data and Scan Response data are organized around a set of
|
||||
* data types called 'AD types' in Bluetooth 4.0 (see the Bluetooth Core
|
||||
* Specification v4.0, Vol. 3, Part C, Sections 11 and 18).
|
||||
*
|
||||
* @par
|
||||
* Each AD type has its own standardized assigned number, as defined
|
||||
* by the Bluetooth SIG:
|
||||
* https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile.
|
||||
*
|
||||
* @par
|
||||
* For convenience, all appropriate AD types are encapsulated
|
||||
* in GapAdvertisingData::DataType.
|
||||
*
|
||||
* @par
|
||||
* Before the AD Types and their payload (if any) can be inserted into
|
||||
* the Advertising or Scan Response frames, they need to be formatted as
|
||||
* follows:
|
||||
*
|
||||
* @li @c Record length (1 byte).
|
||||
* @li @c AD Type (1 byte).
|
||||
* @li @c AD payload (optional; only present if record length > 1).
|
||||
*
|
||||
* @par
|
||||
* This class takes care of properly formatting the payload, performs
|
||||
* some basic checks on the payload length, and tries to avoid common
|
||||
* errors like adding an exclusive AD field twice in the Advertising
|
||||
* or Scan Response payload.
|
||||
*
|
||||
* @par EXAMPLE
|
||||
*
|
||||
* @code
|
||||
*
|
||||
* // ToDo
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
class GapAdvertisingData
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* @brief A list of Advertising Data types commonly used by peripherals.
|
||||
* These AD types are used to describe the capabilities of the
|
||||
* peripheral, and are inserted inside the advertising or scan
|
||||
* response payloads.
|
||||
*
|
||||
* @par Source
|
||||
*
|
||||
* @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18.
|
||||
* @li @c https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile.
|
||||
*/
|
||||
enum DataType_t {
|
||||
FLAGS = 0x01, /**< Flags, refer to GapAdvertisingData::Flags_t. */
|
||||
INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, /**< Incomplete list of 16-bit Service IDs. */
|
||||
COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, /**< Complete list of 16-bit Service IDs. */
|
||||
INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0). */
|
||||
COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0). */
|
||||
INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit Service IDs. */
|
||||
COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, /**< Complete list of 128-bit Service IDs. */
|
||||
SHORTENED_LOCAL_NAME = 0x08, /**< Shortened Local Name. */
|
||||
COMPLETE_LOCAL_NAME = 0x09, /**< Complete Local Name. */
|
||||
TX_POWER_LEVEL = 0x0A, /**< TX Power Level (in dBm). */
|
||||
DEVICE_ID = 0x10, /**< Device ID. */
|
||||
SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave Connection Interval Range. */
|
||||
LIST_128BIT_SOLICITATION_IDS = 0x15, /**< List of 128 bit service UUIDs the device is looking for. */
|
||||
SERVICE_DATA = 0x16, /**< Service Data. */
|
||||
APPEARANCE = 0x19, /**< Appearance, refer to GapAdvertisingData::Appearance_t. */
|
||||
ADVERTISING_INTERVAL = 0x1A, /**< Advertising Interval. */
|
||||
MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer Specific Data. */
|
||||
};
|
||||
/**
|
||||
* Type alias for GapAdvertisingData::DataType_t.
|
||||
*
|
||||
* @deprecated This type alias will be dropped in future releases.
|
||||
*/
|
||||
typedef enum DataType_t DataType;
|
||||
|
||||
/**
|
||||
* @brief A list of values for the FLAGS AD Type.
|
||||
*
|
||||
* @note You can use more than one value in the FLAGS AD Type (ex.
|
||||
* LE_GENERAL_DISCOVERABLE and BREDR_NOT_SUPPORTED).
|
||||
*
|
||||
* @par Source
|
||||
*
|
||||
* @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1.
|
||||
*/
|
||||
enum Flags_t {
|
||||
LE_LIMITED_DISCOVERABLE = 0x01, /**< Peripheral device is discoverable for a limited period of time. */
|
||||
LE_GENERAL_DISCOVERABLE = 0x02, /**< Peripheral device is discoverable at any moment. */
|
||||
BREDR_NOT_SUPPORTED = 0x04, /**< Peripheral device is LE only. */
|
||||
SIMULTANEOUS_LE_BREDR_C = 0x08, /**< Not relevant - central mode only. */
|
||||
SIMULTANEOUS_LE_BREDR_H = 0x10 /**< Not relevant - central mode only. */
|
||||
};
|
||||
/**
|
||||
* Type alias for GapAdvertisingData::Flags_t.
|
||||
*
|
||||
* @deprecated This type alias will be dropped in future releases.
|
||||
*/
|
||||
typedef enum Flags_t Flags;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* A list of values for the APPEARANCE AD Type, which describes the
|
||||
* physical shape or appearance of the device.
|
||||
*
|
||||
* @par Source
|
||||
*
|
||||
* @li @c Bluetooth Core Specification Supplement, Part A, Section 1.12.
|
||||
* @li @c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2.
|
||||
* @li @c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml.
|
||||
*/
|
||||
enum Appearance_t {
|
||||
UNKNOWN = 0, /**< Unknown or unspecified appearance type. */
|
||||
GENERIC_PHONE = 64, /**< Generic Phone. */
|
||||
GENERIC_COMPUTER = 128, /**< Generic Computer. */
|
||||
GENERIC_WATCH = 192, /**< Generic Watch. */
|
||||
WATCH_SPORTS_WATCH = 193, /**< Sports Watch. */
|
||||
GENERIC_CLOCK = 256, /**< Generic Clock. */
|
||||
GENERIC_DISPLAY = 320, /**< Generic Display. */
|
||||
GENERIC_REMOTE_CONTROL = 384, /**< Generic Remote Control. */
|
||||
GENERIC_EYE_GLASSES = 448, /**< Generic Eye Glasses. */
|
||||
GENERIC_TAG = 512, /**< Generic Tag. */
|
||||
GENERIC_KEYRING = 576, /**< Generic Keyring. */
|
||||
GENERIC_MEDIA_PLAYER = 640, /**< Generic Media Player. */
|
||||
GENERIC_BARCODE_SCANNER = 704, /**< Generic Barcode Scanner. */
|
||||
GENERIC_THERMOMETER = 768, /**< Generic Thermometer. */
|
||||
THERMOMETER_EAR = 769, /**< Ear Thermometer. */
|
||||
GENERIC_HEART_RATE_SENSOR = 832, /**< Generic Heart Rate Sensor. */
|
||||
HEART_RATE_SENSOR_HEART_RATE_BELT = 833, /**< Belt Heart Rate Sensor. */
|
||||
GENERIC_BLOOD_PRESSURE = 896, /**< Generic Blood Pressure. */
|
||||
BLOOD_PRESSURE_ARM = 897, /**< Arm Blood Pressure. */
|
||||
BLOOD_PRESSURE_WRIST = 898, /**< Wrist Blood Pressure. */
|
||||
HUMAN_INTERFACE_DEVICE_HID = 960, /**< Human Interface Device (HID). */
|
||||
KEYBOARD = 961, /**< Keyboard. */
|
||||
MOUSE = 962, /**< Mouse. */
|
||||
JOYSTICK = 963, /**< Joystick. */
|
||||
GAMEPAD = 964, /**< Gamepad. */
|
||||
DIGITIZER_TABLET = 965, /**< Digitizer Tablet. */
|
||||
CARD_READER = 966, /**< Card Reader. */
|
||||
DIGITAL_PEN = 967, /**< Digital Pen. */
|
||||
BARCODE_SCANNER = 968, /**< Barcode Scanner. */
|
||||
GENERIC_GLUCOSE_METER = 1024, /**< Generic Glucose Meter. */
|
||||
GENERIC_RUNNING_WALKING_SENSOR = 1088, /**< Generic Running/Walking Sensor. */
|
||||
RUNNING_WALKING_SENSOR_IN_SHOE = 1089, /**< In Shoe Running/Walking Sensor. */
|
||||
RUNNING_WALKING_SENSOR_ON_SHOE = 1090, /**< On Shoe Running/Walking Sensor. */
|
||||
RUNNING_WALKING_SENSOR_ON_HIP = 1091, /**< On Hip Running/Walking Sensor. */
|
||||
GENERIC_CYCLING = 1152, /**< Generic Cycling. */
|
||||
CYCLING_CYCLING_COMPUTER = 1153, /**< Cycling Computer. */
|
||||
CYCLING_SPEED_SENSOR = 1154, /**< Cycling Speed Sensor. */
|
||||
CYCLING_CADENCE_SENSOR = 1155, /**< Cycling Cadence Sensor. */
|
||||
CYCLING_POWER_SENSOR = 1156, /**< Cycling Power Sensor. */
|
||||
CYCLING_SPEED_AND_CADENCE_SENSOR = 1157, /**< Cycling Speed and Cadence Sensor. */
|
||||
PULSE_OXIMETER_GENERIC = 3136, /**< Generic Pulse Oximeter. */
|
||||
PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip Pulse Oximeter. */
|
||||
PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn Pulse Oximeter. */
|
||||
GENERIC_WEIGHT_SCALE = 3200, /**< Generic Weight Scale. */
|
||||
OUTDOOR_GENERIC = 5184, /**< Generic Outdoor. */
|
||||
OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device. */
|
||||
OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device. */
|
||||
OUTDOOR_LOCATION_POD = 5187, /**< Outdoor Location Pod. */
|
||||
OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188 /**< Outdoor Location and Navigation Pod. */
|
||||
};
|
||||
/**
|
||||
* Type alias for GapAdvertisingData::Appearance_t.
|
||||
*
|
||||
* @deprecated This type alias will be dropped in future releases.
|
||||
*/
|
||||
typedef enum Appearance_t Appearance;
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
*/
|
||||
GapAdvertisingData(void) : _payload(), _payloadLen(0), _appearance(GENERIC_TAG) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds advertising data based on the specified AD type (see GapAdvertisingData::DataType_t).
|
||||
* If the supplied AD type is already present in the advertising
|
||||
* payload, then the value is updated.
|
||||
*
|
||||
* @param[in] advDataType The Advertising 'DataType' to add.
|
||||
* @param[in] payload Pointer to the payload contents.
|
||||
* @param[in] len Size of the payload in bytes.
|
||||
*
|
||||
* @return BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
|
||||
* advertising buffer to overflow. BLE_ERROR_NONE is returned
|
||||
* on success.
|
||||
*
|
||||
* @note When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
|
||||
* supplied value is appended to the values previously added to the
|
||||
* payload.
|
||||
*/
|
||||
ble_error_t addData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
/* Find field */
|
||||
uint8_t* field = findField(advDataType);
|
||||
|
||||
if (field) {
|
||||
/* Field type already exist, either add to field or replace */
|
||||
return addField(advDataType, payload, len, field);
|
||||
} else {
|
||||
/* Field doesn't exists, insert new */
|
||||
return appendField(advDataType, payload, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a particular ADV field in the advertising payload (based on
|
||||
* matching type).
|
||||
*
|
||||
* @param[in] advDataType The Advertising 'DataType' to add.
|
||||
* @param[in] payload Pointer to the payload contents.
|
||||
* @param[in] len Size of the payload in bytes.
|
||||
*
|
||||
* @return BLE_ERROR_UNSPECIFIED if the specified field is not found,
|
||||
* BLE_ERROR_BUFFER_OVERFLOW if the new value causes the
|
||||
* advertising buffer to overflow. BLE_ERROR_NONE is returned
|
||||
* on success.
|
||||
*/
|
||||
ble_error_t updateData(DataType_t advDataType, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
/* Find field */
|
||||
uint8_t* field = findField(advDataType);
|
||||
|
||||
if (field) {
|
||||
/* Field type already exist, replace field contents */
|
||||
return updateField(advDataType, payload, len, field);
|
||||
} else {
|
||||
/* field doesn't exists, return an error */
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to add APPEARANCE data to the advertising payload.
|
||||
*
|
||||
* @param appearance
|
||||
* The APPEARANCE value to add.
|
||||
*
|
||||
* @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
|
||||
* advertising buffer to overflow, else BLE_ERROR_NONE.
|
||||
*/
|
||||
ble_error_t addAppearance(Appearance appearance = GENERIC_TAG) {
|
||||
_appearance = appearance;
|
||||
return addData(GapAdvertisingData::APPEARANCE, (uint8_t *)&appearance, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to add FLAGS data to the advertising payload.
|
||||
*
|
||||
* @param[in] flags
|
||||
* LE_LIMITED_DISCOVERABLE
|
||||
* The peripheral is discoverable for a limited period of time.
|
||||
* LE_GENERAL_DISCOVERABLE
|
||||
* The peripheral is permanently discoverable.
|
||||
* BREDR_NOT_SUPPORTED
|
||||
* This peripheral is a Bluetooth Low Energy only device (no EDR support).
|
||||
*
|
||||
* @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
|
||||
* advertising buffer to overflow, else BLE_ERROR_NONE.
|
||||
*/
|
||||
ble_error_t addFlags(uint8_t flags = LE_GENERAL_DISCOVERABLE) {
|
||||
return addData(GapAdvertisingData::FLAGS, &flags, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to add TX_POWER_LEVEL data to the advertising payload.
|
||||
*
|
||||
* @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
|
||||
* advertising buffer to overflow, else BLE_ERROR_NONE.
|
||||
*/
|
||||
ble_error_t addTxPower(int8_t txPower) {
|
||||
/* To Do: Basic error checking to make sure txPower is in range. */
|
||||
return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t *)&txPower, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the payload and resets the payload length counter.
|
||||
*/
|
||||
void clear(void) {
|
||||
memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
|
||||
_payloadLen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the current payload.
|
||||
*
|
||||
* @return A pointer to the current payload.
|
||||
*/
|
||||
const uint8_t *getPayload(void) const {
|
||||
return _payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current payload length.
|
||||
*
|
||||
* @return The current payload length (0..31 bytes).
|
||||
*/
|
||||
uint8_t getPayloadLen(void) const {
|
||||
return _payloadLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current appearance value.
|
||||
*
|
||||
* @return The 16-bit appearance value for this device.
|
||||
*/
|
||||
uint16_t getAppearance(void) const {
|
||||
return (uint16_t)_appearance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search advertisement data for a specific field.
|
||||
*
|
||||
* @param[in] type
|
||||
* The type of the field to find.
|
||||
*
|
||||
* @return A pointer to the first element in the field if found, NULL otherwise.
|
||||
* Where the first element is the length of the field.
|
||||
*/
|
||||
const uint8_t* findField(DataType_t type) const {
|
||||
return findField(type);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Append advertising data based on the specified AD type (see
|
||||
* GapAdvertisingData::DataType_t).
|
||||
*
|
||||
* @param[in] advDataType
|
||||
* The type of the new data.
|
||||
* @param[in] payload
|
||||
* A pointer to the data to be appended to the advertising
|
||||
* payload.
|
||||
* @param[in] len
|
||||
* The length of th data pointed to by @p payload.
|
||||
*
|
||||
* @return BLE_ERROR_BUFFER_OVERFLOW if the specified data would cause the
|
||||
* advertising buffer to overflow, else BLE_ERROR_NONE.
|
||||
*/
|
||||
ble_error_t appendField(DataType advDataType, const uint8_t *payload, uint8_t len)
|
||||
{
|
||||
/* Make sure we don't exceed the 31 byte payload limit */
|
||||
if (_payloadLen + len + 2 > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
return BLE_ERROR_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Field length. */
|
||||
memset(&_payload[_payloadLen], len + 1, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Field ID. */
|
||||
memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
|
||||
_payloadLen++;
|
||||
|
||||
/* Payload. */
|
||||
memcpy(&_payload[_payloadLen], payload, len);
|
||||
_payloadLen += len;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search advertisement data for field.
|
||||
*
|
||||
* @param[in] type
|
||||
* The type of the data to find.
|
||||
*
|
||||
* @return A pointer to the first element in the field if found, NULL
|
||||
* otherwise. Where the first element is the length of the field.
|
||||
*/
|
||||
uint8_t* findField(DataType_t type) {
|
||||
/* Scan through advertisement data */
|
||||
for (uint8_t idx = 0; idx < _payloadLen; ) {
|
||||
uint8_t fieldType = _payload[idx + 1];
|
||||
|
||||
if (fieldType == type) {
|
||||
return &_payload[idx];
|
||||
}
|
||||
|
||||
/* Advance to next field */
|
||||
idx += _payload[idx] + 1;
|
||||
}
|
||||
|
||||
/* Field not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the a pointer to a field in the advertising payload it replaces
|
||||
* the existing data in the field with the supplied data.
|
||||
*
|
||||
* @param[in] advDataType
|
||||
* The type of the new data.
|
||||
* @param[in] payload
|
||||
* A pointer to the data to be added to the advertising
|
||||
* payload.
|
||||
* @param[in] len
|
||||
* The length of th data pointed to by @p payload.
|
||||
* @param[in] field
|
||||
* A pointer to the field of type @p advDataType in the
|
||||
* advertising buffer.
|
||||
*
|
||||
* When the specified AD type is INCOMPLETE_LIST_16BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_16BIT_SERVICE_IDS, INCOMPLETE_LIST_32BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_32BIT_SERVICE_IDS, INCOMPLETE_LIST_128BIT_SERVICE_IDS,
|
||||
* COMPLETE_LIST_128BIT_SERVICE_IDS or LIST_128BIT_SOLICITATION_IDS the
|
||||
* supplied value is appended to the values previously added to the
|
||||
* payload.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t addField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
|
||||
{
|
||||
ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
|
||||
|
||||
switch(advDataType) {
|
||||
/* These fields will have the new data appended if there is sufficient space */
|
||||
case INCOMPLETE_LIST_16BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_16BIT_SERVICE_IDS:
|
||||
case INCOMPLETE_LIST_32BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_32BIT_SERVICE_IDS:
|
||||
case INCOMPLETE_LIST_128BIT_SERVICE_IDS:
|
||||
case COMPLETE_LIST_128BIT_SERVICE_IDS:
|
||||
case LIST_128BIT_SOLICITATION_IDS: {
|
||||
/* Check if data fits */
|
||||
if ((_payloadLen + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
/*
|
||||
* Make room for new field by moving the remainder of the
|
||||
* advertisement payload "to the right" starting after the
|
||||
* TYPE field.
|
||||
*/
|
||||
uint8_t* end = &_payload[_payloadLen];
|
||||
|
||||
while (&field[1] < end) {
|
||||
end[len] = *end;
|
||||
end--;
|
||||
}
|
||||
|
||||
/* Insert new data */
|
||||
for (uint8_t idx = 0; idx < len; idx++) {
|
||||
field[2 + idx] = payload[idx];
|
||||
}
|
||||
|
||||
/* Increment lengths */
|
||||
field[0] += len;
|
||||
_payloadLen += len;
|
||||
|
||||
result = BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
/* These fields will be overwritten with the new value */
|
||||
default: {
|
||||
result = updateField(advDataType, payload, len, field);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the a pointer to a field in the advertising payload it replaces
|
||||
* the existing data in the field with the supplied data.
|
||||
*
|
||||
* @param[in] advDataType
|
||||
* The type of the data to be updated.
|
||||
* @param[in] payload
|
||||
* A pointer to the data to be updated to the advertising
|
||||
* payload.
|
||||
* @param[in] len
|
||||
* The length of th data pointed to by @p payload.
|
||||
* @param[in] field
|
||||
* A pointer to the field of type @p advDataType in the
|
||||
* advertising buffer.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t updateField(DataType_t advDataType, const uint8_t *payload, uint8_t len, uint8_t* field)
|
||||
{
|
||||
ble_error_t result = BLE_ERROR_BUFFER_OVERFLOW;
|
||||
uint8_t dataLength = field[0] - 1;
|
||||
|
||||
/* New data has same length, do in-order replacement */
|
||||
if (len == dataLength) {
|
||||
for (uint8_t idx = 0; idx < dataLength; idx++) {
|
||||
field[2 + idx] = payload[idx];
|
||||
}
|
||||
|
||||
result = BLE_ERROR_NONE;
|
||||
} else {
|
||||
/* Check if data fits */
|
||||
if ((_payloadLen - dataLength + len) <= GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
|
||||
|
||||
/* Remove old field */
|
||||
while ((field + dataLength + 2) < &_payload[_payloadLen]) {
|
||||
*field = field[dataLength + 2];
|
||||
field++;
|
||||
}
|
||||
|
||||
/* Reduce length */
|
||||
_payloadLen -= dataLength + 2;
|
||||
|
||||
/* Add new field */
|
||||
result = appendField(advDataType, payload, len);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The advertising data buffer
|
||||
*/
|
||||
uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
|
||||
/**
|
||||
* The length of the data added to the advertising buffer.
|
||||
*/
|
||||
uint8_t _payloadLen;
|
||||
/**
|
||||
* Appearance value.
|
||||
*/
|
||||
uint16_t _appearance;
|
||||
};
|
||||
|
||||
#endif /* ifndef __GAP_ADVERTISING_DATA_H__ */
|
|
@ -0,0 +1,207 @@
|
|||
/* 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 __GAP_ADVERTISING_PARAMS_H__
|
||||
#define __GAP_ADVERTISING_PARAMS_H__
|
||||
|
||||
/**
|
||||
* This class provides a wrapper for the core advertising parameters,
|
||||
* including the advertising type (Connectable Undirected,
|
||||
* Non Connectable Undirected and so on), as well as the advertising and
|
||||
* timeout intervals.
|
||||
*/
|
||||
class GapAdvertisingParams {
|
||||
public:
|
||||
/**
|
||||
* Minimum Advertising interval for connectable undirected and connectable
|
||||
* directed events in 625us units - 20ms.
|
||||
*/
|
||||
static const unsigned GAP_ADV_PARAMS_INTERVAL_MIN = 0x0020;
|
||||
/**
|
||||
* Minimum Advertising interval for scannable and non-connectable
|
||||
* undirected events in 625us units - 100ms.
|
||||
*/
|
||||
static const unsigned GAP_ADV_PARAMS_INTERVAL_MIN_NONCON = 0x00A0;
|
||||
/**
|
||||
* Maximum Advertising interval in 625us units - 10.24s.
|
||||
*/
|
||||
static const unsigned GAP_ADV_PARAMS_INTERVAL_MAX = 0x4000;
|
||||
/**
|
||||
* Maximum advertising timeout seconds.
|
||||
*/
|
||||
static const unsigned GAP_ADV_PARAMS_TIMEOUT_MAX = 0x3FFF;
|
||||
|
||||
/**
|
||||
* Encapsulates the peripheral advertising modes, which determine how
|
||||
* the device appears to other central devices in hearing range.
|
||||
*/
|
||||
enum AdvertisingType_t {
|
||||
ADV_CONNECTABLE_UNDIRECTED, /**< Vol 3, Part C, Section 9.3.4 and Vol 6, Part B, Section 2.3.1.1. */
|
||||
ADV_CONNECTABLE_DIRECTED, /**< Vol 3, Part C, Section 9.3.3 and Vol 6, Part B, Section 2.3.1.2. */
|
||||
ADV_SCANNABLE_UNDIRECTED, /**< Include support for Scan Response payloads, see Vol 6, Part B, Section 2.3.1.4. */
|
||||
ADV_NON_CONNECTABLE_UNDIRECTED /**< Vol 3, Part C, Section 9.3.2 and Vol 6, Part B, Section 2.3.1.3. */
|
||||
};
|
||||
/**
|
||||
* Type alias for GapAdvertisingParams::AdvertisingType_t.
|
||||
*
|
||||
* @deprecated This type alias will be dropped in future releases.
|
||||
*/
|
||||
typedef enum AdvertisingType_t AdvertisingType;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an instance of GapAdvertisingParams.
|
||||
*
|
||||
* @param[in] advType
|
||||
* Type of advertising. Default is
|
||||
* GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED.
|
||||
* @param[in] interval
|
||||
* Advertising interval in units of 0.625ms. Default is
|
||||
* GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON.
|
||||
* @param[in] timeout
|
||||
* Advertising timeout. Default is 0.
|
||||
*/
|
||||
GapAdvertisingParams(AdvertisingType_t advType = ADV_CONNECTABLE_UNDIRECTED,
|
||||
uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
|
||||
uint16_t timeout = 0) : _advType(advType), _interval(interval), _timeout(timeout) {
|
||||
/* Interval checks. */
|
||||
if (_advType == ADV_CONNECTABLE_DIRECTED) {
|
||||
/* Interval must be 0 in directed connectable mode. */
|
||||
_interval = 0;
|
||||
} else if (_advType == ADV_NON_CONNECTABLE_UNDIRECTED) {
|
||||
/* Min interval is slightly larger than in other modes. */
|
||||
if (_interval < GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) {
|
||||
_interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON;
|
||||
}
|
||||
if (_interval > GAP_ADV_PARAMS_INTERVAL_MAX) {
|
||||
_interval = GAP_ADV_PARAMS_INTERVAL_MAX;
|
||||
}
|
||||
} else {
|
||||
/* Stay within interval limits. */
|
||||
if (_interval < GAP_ADV_PARAMS_INTERVAL_MIN) {
|
||||
_interval = GAP_ADV_PARAMS_INTERVAL_MIN;
|
||||
}
|
||||
if (_interval > GAP_ADV_PARAMS_INTERVAL_MAX) {
|
||||
_interval = GAP_ADV_PARAMS_INTERVAL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Timeout checks. */
|
||||
if (timeout) {
|
||||
/* Stay within timeout limits. */
|
||||
if (_timeout > GAP_ADV_PARAMS_TIMEOUT_MAX) {
|
||||
_timeout = GAP_ADV_PARAMS_TIMEOUT_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const uint16_t UNIT_0_625_MS = 625; /**< Number of microseconds in 0.625 milliseconds. */
|
||||
/**
|
||||
* Convert milliseconds to units of 0.625ms.
|
||||
*
|
||||
* @param[in] durationInMillis
|
||||
* The number of milliseconds to convert.
|
||||
*
|
||||
* @return The value of @p durationInMillis in units of 0.625ms.
|
||||
*/
|
||||
static uint16_t MSEC_TO_ADVERTISEMENT_DURATION_UNITS(uint32_t durationInMillis) {
|
||||
return (durationInMillis * 1000) / UNIT_0_625_MS;
|
||||
}
|
||||
/**
|
||||
* Convert units of 0.625ms to milliseconds.
|
||||
*
|
||||
* @param[in] gapUnits
|
||||
* The number of units of 0.625ms to convert.
|
||||
*
|
||||
* @return The value of @p gapUnits in milliseconds.
|
||||
*/
|
||||
static uint16_t ADVERTISEMENT_DURATION_UNITS_TO_MS(uint16_t gapUnits) {
|
||||
return (gapUnits * UNIT_0_625_MS) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the advertising type.
|
||||
*
|
||||
* @return The advertising type.
|
||||
*/
|
||||
AdvertisingType_t getAdvertisingType(void) const {
|
||||
return _advType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the advertising interval in milliseconds.
|
||||
*
|
||||
* @return The advertisement interval (in milliseconds).
|
||||
*/
|
||||
uint16_t getInterval(void) const {
|
||||
return ADVERTISEMENT_DURATION_UNITS_TO_MS(_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the advertisement interval in units of 0.625ms.
|
||||
*
|
||||
* @return The advertisement interval in advertisement duration units (0.625ms units).
|
||||
*/
|
||||
uint16_t getIntervalInADVUnits(void) const {
|
||||
return _interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The advertising timeout.
|
||||
*
|
||||
* @return The advertising timeout (in seconds).
|
||||
*/
|
||||
uint16_t getTimeout(void) const {
|
||||
return _timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the advertising type.
|
||||
*
|
||||
* @param[in] newAdvType
|
||||
* The new advertising type.
|
||||
*/
|
||||
void setAdvertisingType(AdvertisingType_t newAdvType) {
|
||||
_advType = newAdvType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the advertising interval in milliseconds.
|
||||
*
|
||||
* @param[in] newInterval
|
||||
* The new advertising interval in milliseconds.
|
||||
*/
|
||||
void setInterval(uint16_t newInterval) {
|
||||
_interval = MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the advertising timeout.
|
||||
*
|
||||
* @param[in] newTimeout
|
||||
* The new advertising timeout (in seconds).
|
||||
*/
|
||||
void setTimeout(uint16_t newTimeout) {
|
||||
_timeout = newTimeout;
|
||||
}
|
||||
|
||||
private:
|
||||
AdvertisingType_t _advType; /**< The advertising type. */
|
||||
uint16_t _interval; /**< The advertising interval in ADV duration units (i.e. 0.625ms). */
|
||||
uint16_t _timeout; /**< The advertising timeout in seconds. */
|
||||
};
|
||||
|
||||
#endif /* ifndef __GAP_ADVERTISING_PARAMS_H__ */
|
|
@ -0,0 +1,46 @@
|
|||
/* 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 __GAP_EVENTS_H__
|
||||
#define __GAP_EVENTS_H__
|
||||
|
||||
#include "blecommon.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
The base class used to abstract away the callback events that can be
|
||||
triggered with the GAP.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class GapEvents
|
||||
{
|
||||
public:
|
||||
/******************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Identifies GAP events generated by the radio HW when an event
|
||||
callback occurs.
|
||||
*/
|
||||
/******************************************************************/
|
||||
typedef enum gapEvent_e {
|
||||
GAP_EVENT_TIMEOUT = 1, /**< Advertising timed out before a connection could be established. */
|
||||
GAP_EVENT_CONNECTED = 2, /**< A connection was established with a central device. */
|
||||
GAP_EVENT_DISCONNECTED = 3 /**< A connection was closed or lost with a central device. */
|
||||
} gapEvent_t;
|
||||
};
|
||||
|
||||
#endif // ifndef __GAP_EVENTS_H__
|
|
@ -0,0 +1,152 @@
|
|||
/* 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 __GAP_SCANNING_PARAMS_H__
|
||||
#define __GAP_SCANNING_PARAMS_H__
|
||||
|
||||
class GapScanningParams {
|
||||
public:
|
||||
static const unsigned SCAN_INTERVAL_MIN = 0x0004; /**< Minimum Scan interval in 625us units - 2.5ms. */
|
||||
static const unsigned SCAN_INTERVAL_MAX = 0x4000; /**< Maximum Scan interval in 625us units - 10.24s. */
|
||||
static const unsigned SCAN_WINDOW_MIN = 0x0004; /**< Minimum Scan window in 625us units - 2.5ms. */
|
||||
static const unsigned SCAN_WINDOW_MAX = 0x4000; /**< Maximum Scan window in 625us units - 10.24s. */
|
||||
static const unsigned SCAN_TIMEOUT_MIN = 0x0001; /**< Minimum Scan timeout in seconds. */
|
||||
static const unsigned SCAN_TIMEOUT_MAX = 0xFFFF; /**< Maximum Scan timeout in seconds. */
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an instance of GapScanningParams.
|
||||
*
|
||||
* @param[in] interval
|
||||
* The scan interval in milliseconds. Default is
|
||||
* GapScanningParams::SCAN_INTERVAL_MIN.
|
||||
* @param[in] window
|
||||
* The scan window in milliseconds. Default is
|
||||
* GapScanningParams::SCAN_WINDOW_MAX.
|
||||
* @param[in] timeout
|
||||
* The scan timeout in seconds. Default is 0.
|
||||
* @param[in] activeScanning
|
||||
* Set to True if active-scanning is required. This is used to
|
||||
* fetch the scan response from a peer if possible. Default is
|
||||
* false.
|
||||
*/
|
||||
GapScanningParams(uint16_t interval = SCAN_INTERVAL_MAX,
|
||||
uint16_t window = SCAN_WINDOW_MAX,
|
||||
uint16_t timeout = 0,
|
||||
bool activeScanning = false);
|
||||
|
||||
static const uint16_t UNIT_0_625_MS = 625; /**< Number of microseconds in 0.625 milliseconds. */
|
||||
/**
|
||||
* Convert milliseconds to units of 0.625ms.
|
||||
*
|
||||
* @param[in] durationInMillis
|
||||
* The number of milliseconds to convert.
|
||||
*
|
||||
* @return The value of @p durationInMillis in units of 0.625ms.
|
||||
*/
|
||||
static uint16_t MSEC_TO_SCAN_DURATION_UNITS(uint32_t durationInMillis) {
|
||||
return (durationInMillis * 1000) / UNIT_0_625_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scan interval.
|
||||
*
|
||||
* @param[in] newIntervalInMS
|
||||
* New scan interval in milliseconds.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the new scan interval was set successfully.
|
||||
*/
|
||||
ble_error_t setInterval(uint16_t newIntervalInMS);
|
||||
|
||||
/**
|
||||
* Set the scan window.
|
||||
*
|
||||
* @param[in] newWindowInMS
|
||||
* New scan window in milliseconds.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the new scan window was set successfully.
|
||||
*/
|
||||
ble_error_t setWindow(uint16_t newWindowInMS);
|
||||
|
||||
/**
|
||||
* Set the scan timeout.
|
||||
*
|
||||
* @param[in] newTimeout
|
||||
* New scan timeout in seconds.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the new scan window was set successfully.
|
||||
*/
|
||||
ble_error_t setTimeout(uint16_t newTimeout);
|
||||
|
||||
/**
|
||||
* Set active scanning. This is used to fetch the scan response from a peer
|
||||
* if possible.
|
||||
*
|
||||
* @param[in] activeScanning
|
||||
* The new boolean value of active scanning.
|
||||
*/
|
||||
void setActiveScanning(bool activeScanning);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the scan interval.
|
||||
*
|
||||
* @return the scan interval in units of 0.625ms.
|
||||
*/
|
||||
uint16_t getInterval(void) const {
|
||||
return _interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scan window.
|
||||
*
|
||||
* @return the scan window in units of 0.625ms.
|
||||
*/
|
||||
uint16_t getWindow(void) const {
|
||||
return _window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scan timeout.
|
||||
*
|
||||
* @return The scan timeout in seconds.
|
||||
*/
|
||||
uint16_t getTimeout(void) const {
|
||||
return _timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether active scanning is set.
|
||||
*
|
||||
* @return True if active scanning is set, false otherwise.
|
||||
*/
|
||||
bool getActiveScanning(void) const {
|
||||
return _activeScanning;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t _interval; /**< Scan interval in units of 625us (between 2.5ms and 10.24s). */
|
||||
uint16_t _window; /**< Scan window in units of 625us (between 2.5ms and 10.24s). */
|
||||
uint16_t _timeout; /**< Scan timeout between 0x0001 and 0xFFFF in seconds; 0x0000 disables timeout. */
|
||||
bool _activeScanning; /**< Obtain the peer device's advertising data and (if possible) scanResponse. */
|
||||
|
||||
private:
|
||||
/* Disallow copy constructor. */
|
||||
GapScanningParams(const GapScanningParams &);
|
||||
GapScanningParams& operator =(const GapScanningParams &in);
|
||||
};
|
||||
|
||||
#endif /* ifndef __GAP_SCANNING_PARAMS_H__ */
|
|
@ -0,0 +1,174 @@
|
|||
/* 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 __GATT_ATTRIBUTE_H__
|
||||
#define __GATT_ATTRIBUTE_H__
|
||||
|
||||
#include "UUID.h"
|
||||
|
||||
/**
|
||||
* Instances of this class encapsulate the data that belongs to a Bluetooth Low
|
||||
* Energy attribute.
|
||||
*/
|
||||
class GattAttribute {
|
||||
public:
|
||||
/**
|
||||
* Type for the handle or ID of the attribute in the ATT table. These are
|
||||
* unique and are usually generated by the underlying BLE stack.
|
||||
*/
|
||||
typedef uint16_t Handle_t;
|
||||
/**
|
||||
* Define the value of an invalid attribute handle.
|
||||
*/
|
||||
static const Handle_t INVALID_HANDLE = 0x0000;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new GattAttribute using the specified
|
||||
* UUID, value length, and inital value.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The UUID to use for this attribute.
|
||||
* @param[in] valuePtr
|
||||
* The memory holding the initial value.
|
||||
* @param[in] len
|
||||
* The length in bytes of this attribute's value.
|
||||
* @param[in] maxLen
|
||||
* The max length in bytes of this attribute's value.
|
||||
* @param[in] hasVariableLen
|
||||
* Whether the attribute's value length changes overtime.
|
||||
*
|
||||
* @section EXAMPLE
|
||||
*
|
||||
* @code
|
||||
*
|
||||
* // UUID = 0x2A19, Min length 2, Max len = 2
|
||||
* GattAttribute attr = GattAttribute(0x2A19, &someValue, 2, 2);
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
GattAttribute(const UUID &uuid, uint8_t *valuePtr = NULL, uint16_t len = 0, uint16_t maxLen = 0, bool hasVariableLen = true) :
|
||||
_uuid(uuid), _valuePtr(valuePtr), _lenMax(maxLen), _len(len), _hasVariableLen(hasVariableLen), _handle() {
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the attribute's handle in the ATT table.
|
||||
*
|
||||
* @return The attribute's handle.
|
||||
*/
|
||||
Handle_t getHandle(void) const {
|
||||
return _handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* The UUID of the characteristic that this attribute belongs to.
|
||||
*
|
||||
* @return The characteristic's UUID.
|
||||
*/
|
||||
const UUID &getUUID(void) const {
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current length of the attribute value.
|
||||
*
|
||||
* @return The current length of the attribute value.
|
||||
*/
|
||||
uint16_t getLength(void) const {
|
||||
return _len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum length of the attribute value.
|
||||
*
|
||||
* The maximum length of the attribute value.
|
||||
*/
|
||||
uint16_t getMaxLength(void) const {
|
||||
return _lenMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pointer to the current length of the attribute value.
|
||||
*
|
||||
* @return A pointer to the current length of the attribute value.
|
||||
*/
|
||||
uint16_t *getLengthPtr(void) {
|
||||
return &_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute handle.
|
||||
*
|
||||
* @param[in] id
|
||||
* The new attribute handle.
|
||||
*/
|
||||
void setHandle(Handle_t id) {
|
||||
_handle = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pointer to the attribute value.
|
||||
*
|
||||
* @return A pointer to the attribute value.
|
||||
*/
|
||||
uint8_t *getValuePtr(void) {
|
||||
return _valuePtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the length of the attribute's value can change over time.
|
||||
*
|
||||
* @return true if the attribute has variable length, false otherwise.
|
||||
*/
|
||||
bool hasVariableLength(void) const {
|
||||
return _hasVariableLen;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Characteristic's UUID.
|
||||
*/
|
||||
UUID _uuid;
|
||||
/**
|
||||
* Pointer to the attribute's value.
|
||||
*/
|
||||
uint8_t *_valuePtr;
|
||||
/**
|
||||
* Maximum length of the value pointed to by GattAttribute::_valuePtr.
|
||||
*/
|
||||
uint16_t _lenMax;
|
||||
/**
|
||||
* Current length of the value pointed to by GattAttribute::_valuePtr.
|
||||
*/
|
||||
uint16_t _len;
|
||||
/**
|
||||
* Whether the length of the value can change over time.
|
||||
*/
|
||||
bool _hasVariableLen;
|
||||
/**
|
||||
* The attribute's handle in the ATT table.
|
||||
*/
|
||||
Handle_t _handle;
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
GattAttribute(const GattAttribute &);
|
||||
GattAttribute& operator=(const GattAttribute &);
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_ATTRIBUTE_H__ */
|
|
@ -0,0 +1,115 @@
|
|||
/* 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 __GATT_CALLBACK_PARAM_TYPES_H__
|
||||
#define __GATT_CALLBACK_PARAM_TYPES_H__
|
||||
|
||||
struct GattWriteCallbackParams {
|
||||
/**
|
||||
* Enumeration for write operations.
|
||||
*/
|
||||
enum WriteOp_t {
|
||||
OP_INVALID = 0x00, /**< Invalid operation. */
|
||||
OP_WRITE_REQ = 0x01, /**< Write request. */
|
||||
OP_WRITE_CMD = 0x02, /**< Write command. */
|
||||
OP_SIGN_WRITE_CMD = 0x03, /**< Signed write command. */
|
||||
OP_PREP_WRITE_REQ = 0x04, /**< Prepare write request. */
|
||||
OP_EXEC_WRITE_REQ_CANCEL = 0x05, /**< Execute write request: cancel all prepared writes. */
|
||||
OP_EXEC_WRITE_REQ_NOW = 0x06, /**< Execute write request: immediately execute all prepared writes. */
|
||||
};
|
||||
|
||||
Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event */
|
||||
GattAttribute::Handle_t handle; /**< Attribute Handle to which the write operation applies. */
|
||||
WriteOp_t writeOp; /**< Type of write operation. */
|
||||
uint16_t offset; /**< Offset for the write operation. */
|
||||
uint16_t len; /**< Length (in bytes) of the data to write. */
|
||||
/**
|
||||
* Pointer to the data to write.
|
||||
*
|
||||
* @note Data might not persist beyond the callback; make a local copy if
|
||||
* needed.
|
||||
*/
|
||||
const uint8_t *data;
|
||||
};
|
||||
|
||||
struct GattReadCallbackParams {
|
||||
Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event */
|
||||
GattAttribute::Handle_t handle; /**< Attribute Handle to which the read operation applies. */
|
||||
uint16_t offset; /**< Offset for the read operation. */
|
||||
uint16_t len; /**< Length (in bytes) of the data to read. */
|
||||
/**
|
||||
* Pointer to the data read.
|
||||
*
|
||||
* @note Data might not persist beyond the callback; make a local copy if
|
||||
* needed.
|
||||
*/
|
||||
const uint8_t *data;
|
||||
};
|
||||
|
||||
enum GattAuthCallbackReply_t {
|
||||
AUTH_CALLBACK_REPLY_SUCCESS = 0x00, /**< Success. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INVALID_HANDLE = 0x0101, /**< ATT Error: Invalid attribute handle. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_READ_NOT_PERMITTED = 0x0102, /**< ATT Error: Read not permitted. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED = 0x0103, /**< ATT Error: Write not permitted. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHENTICATION = 0x0105, /**< ATT Error: Authenticated link required. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET = 0x0107, /**< ATT Error: The specified offset was past the end of the attribute. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION = 0x0108, /**< ATT Error: Used in ATT as "insufficient authorization". */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_PREPARE_QUEUE_FULL = 0x0109, /**< ATT Error: Used in ATT as "prepare queue full". */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_ATTRIBUTE_NOT_FOUND = 0x010A, /**< ATT Error: Used in ATT as "attribute not found". */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_ATTRIBUTE_NOT_LONG = 0x010B, /**< ATT Error: Attribute cannot be read or written using read/write blob requests. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH = 0x010D, /**< ATT Error: Invalid value size. */
|
||||
AUTH_CALLBACK_REPLY_ATTERR_INSUF_RESOURCES = 0x0111, /**< ATT Error: Encrypted link required. */
|
||||
};
|
||||
|
||||
struct GattWriteAuthCallbackParams {
|
||||
Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event */
|
||||
GattAttribute::Handle_t handle; /**< Attribute Handle to which the write operation applies. */
|
||||
uint16_t offset; /**< Offset for the write operation. */
|
||||
uint16_t len; /**< Length of the incoming data. */
|
||||
const uint8_t *data; /**< Incoming data, variable length. */
|
||||
/**
|
||||
* This is the out parameter that the callback needs to set to
|
||||
* AUTH_CALLBACK_REPLY_SUCCESS for the request to proceed.
|
||||
*/
|
||||
GattAuthCallbackReply_t authorizationReply;
|
||||
};
|
||||
|
||||
struct GattReadAuthCallbackParams {
|
||||
Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event */
|
||||
GattAttribute::Handle_t handle; /**< Attribute Handle to which the read operation applies. */
|
||||
uint16_t offset; /**< Offset for the read operation. */
|
||||
uint16_t len; /**< Optional: new length of the outgoing data. */
|
||||
uint8_t *data; /**< Optional: new outgoing data. Leave at NULL if data is unchanged. */
|
||||
/**
|
||||
* This is the out parameter that the callback needs to set to
|
||||
* AUTH_CALLBACK_REPLY_SUCCESS for the request to proceed.
|
||||
*/
|
||||
GattAuthCallbackReply_t authorizationReply;
|
||||
};
|
||||
|
||||
/**
|
||||
* For encapsulating handle-value update events (notifications or indications)
|
||||
* generated at the remote server.
|
||||
*/
|
||||
struct GattHVXCallbackParams {
|
||||
Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event */
|
||||
GattAttribute::Handle_t handle; /**< Attribute Handle to which the HVx operation applies. */
|
||||
HVXType_t type; /**< Indication or Notification, see HVXType_t. */
|
||||
uint16_t len; /**< Attribute data length. */
|
||||
const uint8_t *data; /**< Attribute data, variable length. */
|
||||
};
|
||||
|
||||
#endif /*__GATT_CALLBACK_PARAM_TYPES_H__*/
|
|
@ -0,0 +1,855 @@
|
|||
/* 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 __GATT_CHARACTERISTIC_H__
|
||||
#define __GATT_CHARACTERISTIC_H__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "SecurityManager.h"
|
||||
#include "GattAttribute.h"
|
||||
#include "GattCallbackParamTypes.h"
|
||||
#include "FunctionPointerWithContext.h"
|
||||
|
||||
class GattCharacteristic {
|
||||
public:
|
||||
enum {
|
||||
UUID_BATTERY_LEVEL_STATE_CHAR = 0x2A1B,
|
||||
UUID_BATTERY_POWER_STATE_CHAR = 0x2A1A,
|
||||
UUID_REMOVABLE_CHAR = 0x2A3A,
|
||||
UUID_SERVICE_REQUIRED_CHAR = 0x2A3B,
|
||||
UUID_ALERT_CATEGORY_ID_CHAR = 0x2A43,
|
||||
UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR = 0x2A42,
|
||||
UUID_ALERT_LEVEL_CHAR = 0x2A06,
|
||||
UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR = 0x2A44,
|
||||
UUID_ALERT_STATUS_CHAR = 0x2A3F,
|
||||
UUID_BATTERY_LEVEL_CHAR = 0x2A19,
|
||||
UUID_BLOOD_PRESSURE_FEATURE_CHAR = 0x2A49,
|
||||
UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR = 0x2A35,
|
||||
UUID_BODY_SENSOR_LOCATION_CHAR = 0x2A38,
|
||||
UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR = 0x2A22,
|
||||
UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR = 0x2A32,
|
||||
UUID_BOOT_MOUSE_INPUT_REPORT_CHAR = 0x2A33,
|
||||
UUID_CURRENT_TIME_CHAR = 0x2A2B,
|
||||
UUID_DATE_TIME_CHAR = 0x2A08,
|
||||
UUID_DAY_DATE_TIME_CHAR = 0x2A0A,
|
||||
UUID_DAY_OF_WEEK_CHAR = 0x2A09,
|
||||
UUID_DST_OFFSET_CHAR = 0x2A0D,
|
||||
UUID_EXACT_TIME_256_CHAR = 0x2A0C,
|
||||
UUID_FIRMWARE_REVISION_STRING_CHAR = 0x2A26,
|
||||
UUID_GLUCOSE_FEATURE_CHAR = 0x2A51,
|
||||
UUID_GLUCOSE_MEASUREMENT_CHAR = 0x2A18,
|
||||
UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR = 0x2A34,
|
||||
UUID_HARDWARE_REVISION_STRING_CHAR = 0x2A27,
|
||||
UUID_HEART_RATE_CONTROL_POINT_CHAR = 0x2A39,
|
||||
UUID_HEART_RATE_MEASUREMENT_CHAR = 0x2A37,
|
||||
UUID_HID_CONTROL_POINT_CHAR = 0x2A4C,
|
||||
UUID_HID_INFORMATION_CHAR = 0x2A4A,
|
||||
UUID_HUMIDITY_CHAR = 0x2A6F,
|
||||
UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR = 0x2A2A,
|
||||
UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR = 0x2A36,
|
||||
UUID_INTERMEDIATE_TEMPERATURE_CHAR = 0x2A1E,
|
||||
UUID_LOCAL_TIME_INFORMATION_CHAR = 0x2A0F,
|
||||
UUID_MANUFACTURER_NAME_STRING_CHAR = 0x2A29,
|
||||
UUID_MEASUREMENT_INTERVAL_CHAR = 0x2A21,
|
||||
UUID_MODEL_NUMBER_STRING_CHAR = 0x2A24,
|
||||
UUID_UNREAD_ALERT_CHAR = 0x2A45,
|
||||
UUID_NEW_ALERT_CHAR = 0x2A46,
|
||||
UUID_PNP_ID_CHAR = 0x2A50,
|
||||
UUID_PRESSURE_CHAR = 0x2A6D,
|
||||
UUID_PROTOCOL_MODE_CHAR = 0x2A4E,
|
||||
UUID_RECORD_ACCESS_CONTROL_POINT_CHAR = 0x2A52,
|
||||
UUID_REFERENCE_TIME_INFORMATION_CHAR = 0x2A14,
|
||||
UUID_REPORT_CHAR = 0x2A4D,
|
||||
UUID_REPORT_MAP_CHAR = 0x2A4B,
|
||||
UUID_RINGER_CONTROL_POINT_CHAR = 0x2A40,
|
||||
UUID_RINGER_SETTING_CHAR = 0x2A41,
|
||||
UUID_SCAN_INTERVAL_WINDOW_CHAR = 0x2A4F,
|
||||
UUID_SCAN_REFRESH_CHAR = 0x2A31,
|
||||
UUID_SERIAL_NUMBER_STRING_CHAR = 0x2A25,
|
||||
UUID_SOFTWARE_REVISION_STRING_CHAR = 0x2A28,
|
||||
UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR = 0x2A47,
|
||||
UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR = 0x2A48,
|
||||
UUID_SYSTEM_ID_CHAR = 0x2A23,
|
||||
UUID_TEMPERATURE_CHAR = 0x2A6E,
|
||||
UUID_TEMPERATURE_MEASUREMENT_CHAR = 0x2A1C,
|
||||
UUID_TEMPERATURE_TYPE_CHAR = 0x2A1D,
|
||||
UUID_TIME_ACCURACY_CHAR = 0x2A12,
|
||||
UUID_TIME_SOURCE_CHAR = 0x2A13,
|
||||
UUID_TIME_UPDATE_CONTROL_POINT_CHAR = 0x2A16,
|
||||
UUID_TIME_UPDATE_STATE_CHAR = 0x2A17,
|
||||
UUID_TIME_WITH_DST_CHAR = 0x2A11,
|
||||
UUID_TIME_ZONE_CHAR = 0x2A0E,
|
||||
UUID_TX_POWER_LEVEL_CHAR = 0x2A07,
|
||||
UUID_CSC_FEATURE_CHAR = 0x2A5C,
|
||||
UUID_CSC_MEASUREMENT_CHAR = 0x2A5B,
|
||||
UUID_RSC_FEATURE_CHAR = 0x2A54,
|
||||
UUID_RSC_MEASUREMENT_CHAR = 0x2A53
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Standard GATT characteristic presentation format unit types.
|
||||
* These unit types are used to describe what the raw numeric
|
||||
* data in a characteristic actually represents.
|
||||
*
|
||||
* @note See https://developer.bluetooth.org/gatt/units/Pages/default.aspx
|
||||
*/
|
||||
enum {
|
||||
BLE_GATT_UNIT_NONE = 0x2700, /**< No specified unit type. */
|
||||
BLE_GATT_UNIT_LENGTH_METRE = 0x2701, /**< Length, metre. */
|
||||
BLE_GATT_UNIT_MASS_KILOGRAM = 0x2702, /**< Mass, kilogram. */
|
||||
BLE_GATT_UNIT_TIME_SECOND = 0x2703, /**< Time, second. */
|
||||
BLE_GATT_UNIT_ELECTRIC_CURRENT_AMPERE = 0x2704, /**< Electric current, ampere. */
|
||||
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_KELVIN = 0x2705, /**< Thermodynamic temperature, kelvin. */
|
||||
BLE_GATT_UNIT_AMOUNT_OF_SUBSTANCE_MOLE = 0x2706, /**< Amount of substance, mole. */
|
||||
BLE_GATT_UNIT_LUMINOUS_INTENSITY_CANDELA = 0x2707, /**< Luminous intensity, candela. */
|
||||
BLE_GATT_UNIT_AREA_SQUARE_METRES = 0x2710, /**< Area, square metres. */
|
||||
BLE_GATT_UNIT_VOLUME_CUBIC_METRES = 0x2711, /**< Volume, cubic metres. */
|
||||
BLE_GATT_UNIT_VELOCITY_METRES_PER_SECOND = 0x2712, /**< Velocity, metres per second. */
|
||||
BLE_GATT_UNIT_ACCELERATION_METRES_PER_SECOND_SQUARED = 0x2713, /**< Acceleration, metres per second squared. */
|
||||
BLE_GATT_UNIT_WAVENUMBER_RECIPROCAL_METRE = 0x2714, /**< Wave number reciprocal, metre. */
|
||||
BLE_GATT_UNIT_DENSITY_KILOGRAM_PER_CUBIC_METRE = 0x2715, /**< Density, kilogram per cubic metre. */
|
||||
BLE_GATT_UNIT_SURFACE_DENSITY_KILOGRAM_PER_SQUARE_METRE = 0x2716, /**< */
|
||||
BLE_GATT_UNIT_SPECIFIC_VOLUME_CUBIC_METRE_PER_KILOGRAM = 0x2717, /**< */
|
||||
BLE_GATT_UNIT_CURRENT_DENSITY_AMPERE_PER_SQUARE_METRE = 0x2718, /**< */
|
||||
BLE_GATT_UNIT_MAGNETIC_FIELD_STRENGTH_AMPERE_PER_METRE = 0x2719, /**< Magnetic field strength, ampere per metre. */
|
||||
BLE_GATT_UNIT_AMOUNT_CONCENTRATION_MOLE_PER_CUBIC_METRE = 0x271A, /**< */
|
||||
BLE_GATT_UNIT_MASS_CONCENTRATION_KILOGRAM_PER_CUBIC_METRE = 0x271B, /**< */
|
||||
BLE_GATT_UNIT_LUMINANCE_CANDELA_PER_SQUARE_METRE = 0x271C, /**< */
|
||||
BLE_GATT_UNIT_REFRACTIVE_INDEX = 0x271D, /**< */
|
||||
BLE_GATT_UNIT_RELATIVE_PERMEABILITY = 0x271E, /**< */
|
||||
BLE_GATT_UNIT_PLANE_ANGLE_RADIAN = 0x2720, /**< */
|
||||
BLE_GATT_UNIT_SOLID_ANGLE_STERADIAN = 0x2721, /**< */
|
||||
BLE_GATT_UNIT_FREQUENCY_HERTZ = 0x2722, /**< Frequency, hertz. */
|
||||
BLE_GATT_UNIT_FORCE_NEWTON = 0x2723, /**< Force, newton. */
|
||||
BLE_GATT_UNIT_PRESSURE_PASCAL = 0x2724, /**< Pressure, pascal. */
|
||||
BLE_GATT_UNIT_ENERGY_JOULE = 0x2725, /**< Energy, joule. */
|
||||
BLE_GATT_UNIT_POWER_WATT = 0x2726, /**< Power, watt. */
|
||||
BLE_GATT_UNIT_ELECTRIC_CHARGE_COULOMB = 0x2727, /**< Electrical charge, coulomb. */
|
||||
BLE_GATT_UNIT_ELECTRIC_POTENTIAL_DIFFERENCE_VOLT = 0x2728, /**< Electrical potential difference, voltage. */
|
||||
BLE_GATT_UNIT_CAPACITANCE_FARAD = 0x2729, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_RESISTANCE_OHM = 0x272A, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_CONDUCTANCE_SIEMENS = 0x272B, /**< */
|
||||
BLE_GATT_UNIT_MAGNETIC_FLEX_WEBER = 0x272C, /**< */
|
||||
BLE_GATT_UNIT_MAGNETIC_FLEX_DENSITY_TESLA = 0x272D, /**< */
|
||||
BLE_GATT_UNIT_INDUCTANCE_HENRY = 0x272E, /**< */
|
||||
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_CELSIUS = 0x272F, /**< */
|
||||
BLE_GATT_UNIT_LUMINOUS_FLUX_LUMEN = 0x2730, /**< */
|
||||
BLE_GATT_UNIT_ILLUMINANCE_LUX = 0x2731, /**< */
|
||||
BLE_GATT_UNIT_ACTIVITY_REFERRED_TO_A_RADIONUCLIDE_BECQUEREL = 0x2732, /**< */
|
||||
BLE_GATT_UNIT_ABSORBED_DOSE_GRAY = 0x2733, /**< */
|
||||
BLE_GATT_UNIT_DOSE_EQUIVALENT_SIEVERT = 0x2734, /**< */
|
||||
BLE_GATT_UNIT_CATALYTIC_ACTIVITY_KATAL = 0x2735, /**< */
|
||||
BLE_GATT_UNIT_DYNAMIC_VISCOSITY_PASCAL_SECOND = 0x2740, /**< */
|
||||
BLE_GATT_UNIT_MOMENT_OF_FORCE_NEWTON_METRE = 0x2741, /**< */
|
||||
BLE_GATT_UNIT_SURFACE_TENSION_NEWTON_PER_METRE = 0x2742, /**< */
|
||||
BLE_GATT_UNIT_ANGULAR_VELOCITY_RADIAN_PER_SECOND = 0x2743, /**< */
|
||||
BLE_GATT_UNIT_ANGULAR_ACCELERATION_RADIAN_PER_SECOND_SQUARED = 0x2744, /**< */
|
||||
BLE_GATT_UNIT_HEAT_FLUX_DENSITY_WATT_PER_SQUARE_METRE = 0x2745, /**< */
|
||||
BLE_GATT_UNIT_HEAT_CAPACITY_JOULE_PER_KELVIN = 0x2746, /**< */
|
||||
BLE_GATT_UNIT_SPECIFIC_HEAT_CAPACITY_JOULE_PER_KILOGRAM_KELVIN = 0x2747, /**< */
|
||||
BLE_GATT_UNIT_SPECIFIC_ENERGY_JOULE_PER_KILOGRAM = 0x2748, /**< */
|
||||
BLE_GATT_UNIT_THERMAL_CONDUCTIVITY_WATT_PER_METRE_KELVIN = 0x2749, /**< */
|
||||
BLE_GATT_UNIT_ENERGY_DENSITY_JOULE_PER_CUBIC_METRE = 0x274A, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_FIELD_STRENGTH_VOLT_PER_METRE = 0x274B, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_CHARGE_DENSITY_COULOMB_PER_CUBIC_METRE = 0x274C, /**< */
|
||||
BLE_GATT_UNIT_SURFACE_CHARGE_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274D, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_FLUX_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274E, /**< */
|
||||
BLE_GATT_UNIT_PERMITTIVITY_FARAD_PER_METRE = 0x274F, /**< */
|
||||
BLE_GATT_UNIT_PERMEABILITY_HENRY_PER_METRE = 0x2750, /**< */
|
||||
BLE_GATT_UNIT_MOLAR_ENERGY_JOULE_PER_MOLE = 0x2751, /**< */
|
||||
BLE_GATT_UNIT_MOLAR_ENTROPY_JOULE_PER_MOLE_KELVIN = 0x2752, /**< */
|
||||
BLE_GATT_UNIT_EXPOSURE_COULOMB_PER_KILOGRAM = 0x2753, /**< */
|
||||
BLE_GATT_UNIT_ABSORBED_DOSE_RATE_GRAY_PER_SECOND = 0x2754, /**< */
|
||||
BLE_GATT_UNIT_RADIANT_INTENSITY_WATT_PER_STERADIAN = 0x2755, /**< */
|
||||
BLE_GATT_UNIT_RADIANCE_WATT_PER_SQUARE_METRE_STERADIAN = 0x2756, /**< */
|
||||
BLE_GATT_UNIT_CATALYTIC_ACTIVITY_CONCENTRATION_KATAL_PER_CUBIC_METRE = 0x2757, /**< */
|
||||
BLE_GATT_UNIT_TIME_MINUTE = 0x2760, /**< Time, minute. */
|
||||
BLE_GATT_UNIT_TIME_HOUR = 0x2761, /**< Time, hour. */
|
||||
BLE_GATT_UNIT_TIME_DAY = 0x2762, /**< Time, day. */
|
||||
BLE_GATT_UNIT_PLANE_ANGLE_DEGREE = 0x2763, /**< */
|
||||
BLE_GATT_UNIT_PLANE_ANGLE_MINUTE = 0x2764, /**< */
|
||||
BLE_GATT_UNIT_PLANE_ANGLE_SECOND = 0x2765, /**< */
|
||||
BLE_GATT_UNIT_AREA_HECTARE = 0x2766, /**< */
|
||||
BLE_GATT_UNIT_VOLUME_LITRE = 0x2767, /**< */
|
||||
BLE_GATT_UNIT_MASS_TONNE = 0x2768, /**< */
|
||||
BLE_GATT_UNIT_PRESSURE_BAR = 0x2780, /**< Pressure, bar. */
|
||||
BLE_GATT_UNIT_PRESSURE_MILLIMETRE_OF_MERCURY = 0x2781, /**< Pressure, millimetre of mercury. */
|
||||
BLE_GATT_UNIT_LENGTH_ANGSTROM = 0x2782, /**< */
|
||||
BLE_GATT_UNIT_LENGTH_NAUTICAL_MILE = 0x2783, /**< */
|
||||
BLE_GATT_UNIT_AREA_BARN = 0x2784, /**< */
|
||||
BLE_GATT_UNIT_VELOCITY_KNOT = 0x2785, /**< */
|
||||
BLE_GATT_UNIT_LOGARITHMIC_RADIO_QUANTITY_NEPER = 0x2786, /**< */
|
||||
BLE_GATT_UNIT_LOGARITHMIC_RADIO_QUANTITY_BEL = 0x2787, /**< */
|
||||
BLE_GATT_UNIT_LENGTH_YARD = 0x27A0, /**< Length, yard. */
|
||||
BLE_GATT_UNIT_LENGTH_PARSEC = 0x27A1, /**< Length, parsec. */
|
||||
BLE_GATT_UNIT_LENGTH_INCH = 0x27A2, /**< Length, inch. */
|
||||
BLE_GATT_UNIT_LENGTH_FOOT = 0x27A3, /**< Length, foot. */
|
||||
BLE_GATT_UNIT_LENGTH_MILE = 0x27A4, /**< Length, mile. */
|
||||
BLE_GATT_UNIT_PRESSURE_POUND_FORCE_PER_SQUARE_INCH = 0x27A5, /**< */
|
||||
BLE_GATT_UNIT_VELOCITY_KILOMETRE_PER_HOUR = 0x27A6, /**< Velocity, kilometre per hour. */
|
||||
BLE_GATT_UNIT_VELOCITY_MILE_PER_HOUR = 0x27A7, /**< Velocity, mile per hour. */
|
||||
BLE_GATT_UNIT_ANGULAR_VELOCITY_REVOLUTION_PER_MINUTE = 0x27A8, /**< Angular Velocity, revolution per minute. */
|
||||
BLE_GATT_UNIT_ENERGY_GRAM_CALORIE = 0x27A9, /**< Energy, gram calorie. */
|
||||
BLE_GATT_UNIT_ENERGY_KILOGRAM_CALORIE = 0x27AA, /**< Energy, kilogram calorie. */
|
||||
BLE_GATT_UNIT_ENERGY_KILOWATT_HOUR = 0x27AB, /**< Energy, killowatt hour. */
|
||||
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_FAHRENHEIT = 0x27AC, /**< */
|
||||
BLE_GATT_UNIT_PERCENTAGE = 0x27AD, /**< Percentage. */
|
||||
BLE_GATT_UNIT_PER_MILLE = 0x27AE, /**< */
|
||||
BLE_GATT_UNIT_PERIOD_BEATS_PER_MINUTE = 0x27AF, /**< */
|
||||
BLE_GATT_UNIT_ELECTRIC_CHARGE_AMPERE_HOURS = 0x27B0, /**< */
|
||||
BLE_GATT_UNIT_MASS_DENSITY_MILLIGRAM_PER_DECILITRE = 0x27B1, /**< */
|
||||
BLE_GATT_UNIT_MASS_DENSITY_MILLIMOLE_PER_LITRE = 0x27B2, /**< */
|
||||
BLE_GATT_UNIT_TIME_YEAR = 0x27B3, /**< Time, year. */
|
||||
BLE_GATT_UNIT_TIME_MONTH = 0x27B4, /**< Time, month. */
|
||||
BLE_GATT_UNIT_CONCENTRATION_COUNT_PER_CUBIC_METRE = 0x27B5, /**< */
|
||||
BLE_GATT_UNIT_IRRADIANCE_WATT_PER_SQUARE_METRE = 0x27B6 /**< */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Standard GATT number types.
|
||||
*
|
||||
* @note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.3.5.2.
|
||||
*
|
||||
* @note See http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
|
||||
*/
|
||||
enum {
|
||||
BLE_GATT_FORMAT_RFU = 0x00, /**< Reserved for future use. */
|
||||
BLE_GATT_FORMAT_BOOLEAN = 0x01, /**< Boolean. */
|
||||
BLE_GATT_FORMAT_2BIT = 0x02, /**< Unsigned 2-bit integer. */
|
||||
BLE_GATT_FORMAT_NIBBLE = 0x03, /**< Unsigned 4-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT8 = 0x04, /**< Unsigned 8-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT12 = 0x05, /**< Unsigned 12-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT16 = 0x06, /**< Unsigned 16-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT24 = 0x07, /**< Unsigned 24-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT32 = 0x08, /**< Unsigned 32-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT48 = 0x09, /**< Unsigned 48-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT64 = 0x0A, /**< Unsigned 64-bit integer. */
|
||||
BLE_GATT_FORMAT_UINT128 = 0x0B, /**< Unsigned 128-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT8 = 0x0C, /**< Signed 2-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT12 = 0x0D, /**< Signed 12-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT16 = 0x0E, /**< Signed 16-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT24 = 0x0F, /**< Signed 24-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT32 = 0x10, /**< Signed 32-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT48 = 0x11, /**< Signed 48-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT64 = 0x12, /**< Signed 64-bit integer. */
|
||||
BLE_GATT_FORMAT_SINT128 = 0x13, /**< Signed 128-bit integer. */
|
||||
BLE_GATT_FORMAT_FLOAT32 = 0x14, /**< IEEE-754 32-bit floating point. */
|
||||
BLE_GATT_FORMAT_FLOAT64 = 0x15, /**< IEEE-754 64-bit floating point. */
|
||||
BLE_GATT_FORMAT_SFLOAT = 0x16, /**< IEEE-11073 16-bit SFLOAT. */
|
||||
BLE_GATT_FORMAT_FLOAT = 0x17, /**< IEEE-11073 32-bit FLOAT. */
|
||||
BLE_GATT_FORMAT_DUINT16 = 0x18, /**< IEEE-20601 format. */
|
||||
BLE_GATT_FORMAT_UTF8S = 0x19, /**< UTF-8 string. */
|
||||
BLE_GATT_FORMAT_UTF16S = 0x1A, /**< UTF-16 string. */
|
||||
BLE_GATT_FORMAT_STRUCT = 0x1B /**< Opaque Structure. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Standard GATT characteristic properties.
|
||||
*
|
||||
* @note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.1.1
|
||||
* and Section 3.3.3.1 for Extended Properties.
|
||||
*/
|
||||
enum Properties_t {
|
||||
BLE_GATT_CHAR_PROPERTIES_NONE = 0x00,
|
||||
BLE_GATT_CHAR_PROPERTIES_BROADCAST = 0x01, /**< Permits broadcasts of the characteristic value using the Server Characteristic Configuration descriptor. */
|
||||
BLE_GATT_CHAR_PROPERTIES_READ = 0x02, /**< Permits reads of the characteristic value. */
|
||||
BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE = 0x04, /**< Permits writes of the characteristic value without response. */
|
||||
BLE_GATT_CHAR_PROPERTIES_WRITE = 0x08, /**< Permits writes of the characteristic value with response. */
|
||||
BLE_GATT_CHAR_PROPERTIES_NOTIFY = 0x10, /**< Permits notifications of a characteristic value without acknowledgment. */
|
||||
BLE_GATT_CHAR_PROPERTIES_INDICATE = 0x20, /**< Permits indications of a characteristic value with acknowledgment. */
|
||||
BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Permits signed writes to the characteristic value. */
|
||||
BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES = 0x80 /**< Additional characteristic properties are defined in the Characteristic Extended Properties descriptor */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GATT presentation format wrapper.
|
||||
*
|
||||
* @note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.3.5.
|
||||
*
|
||||
* @note See https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
|
||||
*/
|
||||
struct PresentationFormat_t {
|
||||
uint8_t gatt_format; /**< Format of the value. */
|
||||
int8_t exponent; /**< Exponent for integer data types. Example: if Exponent = -3 and the char value is 3892, the actual value is 3.892 */
|
||||
uint16_t gatt_unit; /**< UUID from Bluetooth Assigned Numbers. */
|
||||
uint8_t gatt_namespace; /**< Namespace from Bluetooth Assigned Numbers, normally '1'. */
|
||||
uint16_t gatt_nsdesc; /**< Namespace description from Bluetooth Assigned Numbers, normally '0'. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new GattCharacteristic using the specified 16-bit
|
||||
* UUID, value length, and properties.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The UUID to use for this characteristic.
|
||||
* @param[in] valuePtr
|
||||
* The memory holding the initial value. The value is copied
|
||||
* into the stack when the enclosing service is added, and
|
||||
* is thereafter maintained internally by the stack.
|
||||
* @param[in] len
|
||||
* The length in bytes of this characteristic's value.
|
||||
* @param[in] maxLen
|
||||
* The max length in bytes of this characteristic's value.
|
||||
* @param[in] props
|
||||
* The 8-bit field containing the characteristic's properties.
|
||||
* @param[in] descriptors
|
||||
* A pointer to an array of descriptors to be included within
|
||||
* this characteristic. The memory for the descriptor array is
|
||||
* owned by the caller, and should remain valid at least until
|
||||
* the enclosing service is added to the GATT table.
|
||||
* @param[in] numDescriptors
|
||||
* The number of descriptors in the previous array.
|
||||
* @param[in] hasVariableLen
|
||||
* Whether the attribute's value length changes over time.
|
||||
*
|
||||
* @note The UUID value must be unique in the service and is normally >1.
|
||||
*
|
||||
* @note If valuePtr == NULL, length == 0, and properties == READ
|
||||
* for the value attribute of a characteristic, then that particular
|
||||
* characteristic may be considered optional and dropped while
|
||||
* instantiating the service with the underlying BLE stack.
|
||||
*/
|
||||
GattCharacteristic(const UUID &uuid,
|
||||
uint8_t *valuePtr = NULL,
|
||||
uint16_t len = 0,
|
||||
uint16_t maxLen = 0,
|
||||
uint8_t props = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0,
|
||||
bool hasVariableLen = true) :
|
||||
_valueAttribute(uuid, valuePtr, len, maxLen, hasVariableLen),
|
||||
_properties(props),
|
||||
_requiredSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK),
|
||||
_descriptors(descriptors),
|
||||
_descriptorCount(numDescriptors),
|
||||
enabledReadAuthorization(false),
|
||||
enabledWriteAuthorization(false),
|
||||
readAuthorizationCallback(),
|
||||
writeAuthorizationCallback() {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Set up the minimum security (mode and level) requirements for access to
|
||||
* the characteristic's value attribute.
|
||||
*
|
||||
* @param[in] securityMode
|
||||
* Can be one of encryption or signing, with or without
|
||||
* protection for man in the middle attacks (MITM).
|
||||
*/
|
||||
void requireSecurity(SecurityManager::SecurityMode_t securityMode) {
|
||||
_requiredSecurity = securityMode;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Set up callback that will be triggered before the GATT Client is allowed
|
||||
* to write this characteristic. The handler will determine the
|
||||
* authorization reply for the write.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
void setWriteAuthorizationCallback(void (*callback)(GattWriteAuthCallbackParams *)) {
|
||||
writeAuthorizationCallback.attach(callback);
|
||||
enabledWriteAuthorization = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattCharacrteristic::setWriteAuthorizationCallback(), but allows
|
||||
* the possibility to add an object reference and member function as
|
||||
* handler for connection event callbacks.
|
||||
*
|
||||
* @param[in] object
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p member).
|
||||
* @param[in] member
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void setWriteAuthorizationCallback(T *object, void (T::*member)(GattWriteAuthCallbackParams *)) {
|
||||
writeAuthorizationCallback.attach(object, member);
|
||||
enabledWriteAuthorization = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up callback that will be triggered before the GATT Client is allowed
|
||||
* to read this characteristic. The handler will determine the
|
||||
* authorizaion reply for the read.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
void setReadAuthorizationCallback(void (*callback)(GattReadAuthCallbackParams *)) {
|
||||
readAuthorizationCallback.attach(callback);
|
||||
enabledReadAuthorization = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattCharacrteristic::setReadAuthorizationCallback(), but allows
|
||||
* the possibility to add an object reference and member function as
|
||||
* handler for connection event callbacks.
|
||||
*
|
||||
* @param[in] object
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p member).
|
||||
* @param[in] member
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void setReadAuthorizationCallback(T *object, void (T::*member)(GattReadAuthCallbackParams *)) {
|
||||
readAuthorizationCallback.attach(object, member);
|
||||
enabledReadAuthorization = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that calls the registered handler to determine the authorization
|
||||
* reply for a write request. This function is meant to be called from the
|
||||
* BLE stack specific implementation.
|
||||
*
|
||||
* @param[in] params
|
||||
* To capture the context of the write-auth request. Also
|
||||
* contains an out-parameter for reply.
|
||||
*
|
||||
* @return A GattAuthCallbackReply_t value indicating whether authorization
|
||||
* is granted.
|
||||
*/
|
||||
GattAuthCallbackReply_t authorizeWrite(GattWriteAuthCallbackParams *params) {
|
||||
if (!isWriteAuthorizationEnabled()) {
|
||||
return AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
|
||||
params->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; /* Initialized to no-error by default. */
|
||||
writeAuthorizationCallback.call(params);
|
||||
return params->authorizationReply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that calls the registered handler to determine the authorization
|
||||
* reply for a read request. This function is meant to be called from the
|
||||
* BLE stack specific implementation.
|
||||
*
|
||||
* @param[in] params
|
||||
* To capture the context of the read-auth request.
|
||||
*
|
||||
* @return A GattAuthCallbackReply_t value indicating whether authorization
|
||||
* is granted.
|
||||
*
|
||||
* @note To authorize or deny the read the params->authorizationReply field
|
||||
* should be set to true (authorize) or false (deny).
|
||||
*
|
||||
* @note If the read is approved and params->data is unchanged (NULL),
|
||||
* the current characteristic value will be used.
|
||||
*
|
||||
* @note If the read is approved, a new value can be provided by setting
|
||||
* the params->data pointer and params->len fields.
|
||||
*/
|
||||
GattAuthCallbackReply_t authorizeRead(GattReadAuthCallbackParams *params) {
|
||||
if (!isReadAuthorizationEnabled()) {
|
||||
return AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
|
||||
params->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; /* Initialized to no-error by default. */
|
||||
readAuthorizationCallback.call(params);
|
||||
return params->authorizationReply;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the characteristic's value attribute.
|
||||
*
|
||||
* @return A reference to the characteristic's value attribute.
|
||||
*/
|
||||
GattAttribute& getValueAttribute() {
|
||||
return _valueAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* A const alternative to GattCharacteristic::getValueAttribute().
|
||||
*
|
||||
* @return A const reference to the characteristic's value attribute.
|
||||
*/
|
||||
const GattAttribute& getValueAttribute() const {
|
||||
return _valueAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the characteristic's value attribute handle in the ATT table.
|
||||
*
|
||||
* @return The value attribute handle.
|
||||
*
|
||||
* @note The attribute handle is typically assigned by the underlying BLE
|
||||
* stack.
|
||||
*/
|
||||
GattAttribute::Handle_t getValueHandle(void) const {
|
||||
return getValueAttribute().getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the characteristic's propertied. Refer to
|
||||
* GattCharacteristic::Properties_t.
|
||||
*
|
||||
* @return The characteristic's properties.
|
||||
*/
|
||||
uint8_t getProperties(void) const {
|
||||
return _properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the characteristic's required security.
|
||||
*
|
||||
* @return The characteristic's required security.
|
||||
*/
|
||||
SecurityManager::SecurityMode_t getRequiredSecurity() const {
|
||||
return _requiredSecurity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of descriptors within this characteristic.
|
||||
*
|
||||
* @return The total number of descriptors.
|
||||
*/
|
||||
uint8_t getDescriptorCount(void) const {
|
||||
return _descriptorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether read authorization is enabled i.e. check whether a
|
||||
* read authorization callback was previously registered. Refer to
|
||||
* GattCharacteristic::setReadAuthorizationCallback().
|
||||
*
|
||||
* @return true if read authorization is enabled, false otherwise.
|
||||
*/
|
||||
bool isReadAuthorizationEnabled() const {
|
||||
return enabledReadAuthorization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether write authorization is enabled i.e. check whether a
|
||||
* write authorization callback was previously registered. Refer to
|
||||
* GattCharacteristic::setReadAuthorizationCallback().
|
||||
*
|
||||
* @return true if write authorization is enabled, false otherwise.
|
||||
*/
|
||||
bool isWriteAuthorizationEnabled() const {
|
||||
return enabledWriteAuthorization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this characteristic's descriptor at a specific index.
|
||||
*
|
||||
* @param[in] index
|
||||
* The descriptor's index.
|
||||
*
|
||||
* @return A pointer the requested descriptor if @p index contains a valid
|
||||
* descriptor, or NULL otherwise.
|
||||
*/
|
||||
GattAttribute *getDescriptor(uint8_t index) {
|
||||
if (index >= _descriptorCount) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _descriptors[index];
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Attribute that contains the actual value of this characteristic.
|
||||
*/
|
||||
GattAttribute _valueAttribute;
|
||||
/**
|
||||
* The characteristic's properties. Refer to
|
||||
* GattCharacteristic::Properties_t.
|
||||
*/
|
||||
uint8_t _properties;
|
||||
/**
|
||||
* The characteristic's required security.
|
||||
*/
|
||||
SecurityManager::SecurityMode_t _requiredSecurity;
|
||||
/**
|
||||
* The characteristic's descriptor attributes.
|
||||
*/
|
||||
GattAttribute **_descriptors;
|
||||
/**
|
||||
* The number of descriptors in this characteristic.
|
||||
*/
|
||||
uint8_t _descriptorCount;
|
||||
|
||||
/**
|
||||
* Whether read authorization is enabled i.e. whether there is a registered
|
||||
* callback to determine read authorization reply.
|
||||
*/
|
||||
bool enabledReadAuthorization;
|
||||
/**
|
||||
* Whether write authorization is enabled i.e. whether there is a registered
|
||||
* callback to determine write authorization reply.
|
||||
*/
|
||||
bool enabledWriteAuthorization;
|
||||
/**
|
||||
* The registered callback handler for read authorization reply.
|
||||
*/
|
||||
FunctionPointerWithContext<GattReadAuthCallbackParams *> readAuthorizationCallback;
|
||||
/**
|
||||
* The registered callback handler for write authorization reply.
|
||||
*/
|
||||
FunctionPointerWithContext<GattWriteAuthCallbackParams *> writeAuthorizationCallback;
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
GattCharacteristic(const GattCharacteristic &);
|
||||
GattCharacteristic& operator=(const GattCharacteristic &);
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a read-only GattCharacteristic.
|
||||
*/
|
||||
template <typename T>
|
||||
class ReadOnlyGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a ReadOnlyGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to the characterisitic's initial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_READ.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of ReadOnlyGattCharacteristic have a fixed length
|
||||
* attribute value that equals sizeof(T). For a variable length
|
||||
* alternative use GattCharacteristic directly.
|
||||
*/
|
||||
ReadOnlyGattCharacteristic<T>(const UUID &uuid,
|
||||
T *valuePtr,
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T), sizeof(T),
|
||||
BLE_GATT_CHAR_PROPERTIES_READ | additionalProperties, descriptors, numDescriptors, false) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a write-only GattCharacteristic.
|
||||
*/
|
||||
template <typename T>
|
||||
class WriteOnlyGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a WriteOnlyGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to the characterisitic's initial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of WriteOnlyGattCharacteristic have variable length
|
||||
* attribute value with maximum size equal to sizeof(T). For a fixed length
|
||||
* alternative use GattCharacteristic directly.
|
||||
*/
|
||||
WriteOnlyGattCharacteristic<T>(const UUID &uuid,
|
||||
T *valuePtr,
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T), sizeof(T),
|
||||
BLE_GATT_CHAR_PROPERTIES_WRITE | additionalProperties, descriptors, numDescriptors) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a readable and writable GattCharacteristic.
|
||||
*/
|
||||
template <typename T>
|
||||
class ReadWriteGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a ReadWriteGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to the characterisitic's initial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE |
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_READ.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of ReadWriteGattCharacteristic have variable length
|
||||
* attribute value with maximum size equal to sizeof(T). For a fixed length
|
||||
* alternative use GattCharacteristic directly.
|
||||
*/
|
||||
ReadWriteGattCharacteristic<T>(const UUID &uuid,
|
||||
T *valuePtr,
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T), sizeof(T),
|
||||
BLE_GATT_CHAR_PROPERTIES_READ | BLE_GATT_CHAR_PROPERTIES_WRITE | additionalProperties, descriptors, numDescriptors) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a write-only GattCharacteristic with an array
|
||||
* value.
|
||||
*/
|
||||
template <typename T, unsigned NUM_ELEMENTS>
|
||||
class WriteOnlyArrayGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a WriteOnlyGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to an array of length NUM_ELEMENTS containing the
|
||||
* characteristic's intitial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of WriteOnlyGattCharacteristic have variable length
|
||||
* attribute value with maximum size equal to sizeof(T) * NUM_ELEMENTS.
|
||||
* For a fixed length alternative use GattCharacteristic directly.
|
||||
*/
|
||||
WriteOnlyArrayGattCharacteristic<T, NUM_ELEMENTS>(const UUID &uuid,
|
||||
T valuePtr[NUM_ELEMENTS],
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T) * NUM_ELEMENTS, sizeof(T) * NUM_ELEMENTS,
|
||||
BLE_GATT_CHAR_PROPERTIES_WRITE | additionalProperties, descriptors, numDescriptors) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a read-only GattCharacteristic with an array
|
||||
* value.
|
||||
*/
|
||||
template <typename T, unsigned NUM_ELEMENTS>
|
||||
class ReadOnlyArrayGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a ReadOnlyGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to an array of length NUM_ELEMENTS containing the
|
||||
* characteristic's intitial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_READ.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of ReadOnlyGattCharacteristic have fixed length
|
||||
* attribute value that equals sizeof(T) * NUM_ELEMENTS.
|
||||
* For a variable length alternative use GattCharacteristic directly.
|
||||
*/
|
||||
ReadOnlyArrayGattCharacteristic<T, NUM_ELEMENTS>(const UUID &uuid,
|
||||
T valuePtr[NUM_ELEMENTS],
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T) * NUM_ELEMENTS, sizeof(T) * NUM_ELEMENTS,
|
||||
BLE_GATT_CHAR_PROPERTIES_READ | additionalProperties, descriptors, numDescriptors, false) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a readable and writable GattCharacteristic with an array
|
||||
* value.
|
||||
*/
|
||||
template <typename T, unsigned NUM_ELEMENTS>
|
||||
class ReadWriteArrayGattCharacteristic : public GattCharacteristic {
|
||||
public:
|
||||
/**
|
||||
* Construct a ReadWriteGattCharacteristic.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The characteristic's UUID.
|
||||
* @param[in] valuePtr
|
||||
* Pointer to an array of length NUM_ELEMENTS containing the
|
||||
* characteristic's intitial value.
|
||||
* @param[in] additionalProperties
|
||||
* Additional characterisitic properties. By default, the
|
||||
* properties are set to
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE |
|
||||
* Properties_t::BLE_GATT_CHAR_PROPERTIES_READ.
|
||||
* @param[in] descriptors
|
||||
* An array of pointers to descriptors to be added to the new
|
||||
* characteristic.
|
||||
* @param[in] numDescriptors
|
||||
* The total number of descriptors in @p descriptors.
|
||||
*
|
||||
* @note Instances of ReadWriteGattCharacteristic have variable length
|
||||
* attribute value with maximum size equal to sizeof(T) * NUM_ELEMENTS.
|
||||
* For a fixed length alternative use GattCharacteristic directly.
|
||||
*/
|
||||
ReadWriteArrayGattCharacteristic<T, NUM_ELEMENTS>(const UUID &uuid,
|
||||
T valuePtr[NUM_ELEMENTS],
|
||||
uint8_t additionalProperties = BLE_GATT_CHAR_PROPERTIES_NONE,
|
||||
GattAttribute *descriptors[] = NULL,
|
||||
unsigned numDescriptors = 0) :
|
||||
GattCharacteristic(uuid, reinterpret_cast<uint8_t *>(valuePtr), sizeof(T) * NUM_ELEMENTS, sizeof(T) * NUM_ELEMENTS,
|
||||
BLE_GATT_CHAR_PROPERTIES_READ | BLE_GATT_CHAR_PROPERTIES_WRITE | additionalProperties, descriptors, numDescriptors) {
|
||||
/* empty */
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_CHARACTERISTIC_H__ */
|
|
@ -0,0 +1,626 @@
|
|||
/* 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 __GATT_CLIENT_H__
|
||||
#define __GATT_CLIENT_H__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "GattAttribute.h"
|
||||
#include "ServiceDiscovery.h"
|
||||
#include "CharacteristicDescriptorDiscovery.h"
|
||||
|
||||
#include "GattCallbackParamTypes.h"
|
||||
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
|
||||
class GattClient {
|
||||
public:
|
||||
/**
|
||||
* Type for the registered callbacks added to the data read callchain.
|
||||
* Refer to GattClient::onDataRead().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattReadCallbackParams*> ReadCallback_t;
|
||||
/**
|
||||
* Type for the data read event callchain. Refer to GattClient::onDataRead().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattReadCallbackParams*> ReadCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Enumerator for write operations.
|
||||
*/
|
||||
enum WriteOp_t {
|
||||
GATT_OP_WRITE_REQ = 0x01, /**< Write request. */
|
||||
GATT_OP_WRITE_CMD = 0x02, /**< Write command. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the data write callchain.
|
||||
* Refer to GattClient::onDataWrite().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattWriteCallbackParams*> WriteCallback_t;
|
||||
/**
|
||||
* Type for the data write event callchain. Refer to GattClient::onDataWrite().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattWriteCallbackParams*> WriteCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the update event callchain.
|
||||
* Refer to GattClient::onHVX().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattHVXCallbackParams*> HVXCallback_t;
|
||||
/**
|
||||
* Type for the update event callchain. Refer to GattClient::onHVX().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattHVXCallbackParams*> HVXCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the shutdown callchain.
|
||||
* Refer to GattClient::onShutdown().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattClient *> GattClientShutdownCallback_t;
|
||||
/**
|
||||
* Type for the shutdown event callchain. Refer to GattClient::onShutown().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattClient *> GattClientShutdownCallbackChain_t;
|
||||
|
||||
/*
|
||||
* The following functions are meant to be overridden in the platform-specific sub-class.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Launch service discovery. Once launched, application callbacks will be
|
||||
* invoked for matching services or characteristics. isServiceDiscoveryActive()
|
||||
* can be used to determine status, and a termination callback (if one was set up)
|
||||
* will be invoked at the end. Service discovery can be terminated prematurely,
|
||||
* if needed, using terminateServiceDiscovery().
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param[in] sc
|
||||
* This is the application callback for a matching service. Taken as
|
||||
* NULL by default. Note: service discovery may still be active
|
||||
* when this callback is issued; calling asynchronous BLE-stack
|
||||
* APIs from within this application callback might cause the
|
||||
* stack to abort service discovery. If this becomes an issue, it
|
||||
* may be better to make a local copy of the discoveredService and
|
||||
* wait for service discovery to terminate before operating on the
|
||||
* service.
|
||||
* @param[in] cc
|
||||
* This is the application callback for a matching characteristic.
|
||||
* Taken as NULL by default. Note: service discovery may still be
|
||||
* active when this callback is issued; calling asynchronous
|
||||
* BLE-stack APIs from within this application callback might cause
|
||||
* the stack to abort service discovery. If this becomes an issue,
|
||||
* it may be better to make a local copy of the discoveredCharacteristic
|
||||
* and wait for service discovery to terminate before operating on the
|
||||
* characteristic.
|
||||
* @param[in] matchingServiceUUID
|
||||
* UUID-based filter for specifying a service in which the application is
|
||||
* interested. By default it is set as the wildcard UUID_UNKNOWN,
|
||||
* in which case it matches all services. If characteristic-UUID
|
||||
* filter (below) is set to the wildcard value, then a service
|
||||
* callback will be invoked for the matching service (or for every
|
||||
* service if the service filter is a wildcard).
|
||||
* @param[in] matchingCharacteristicUUIDIn
|
||||
* UUID-based filter for specifying characteristic in which the application
|
||||
* is interested. By default it is set as the wildcard UUID_UKNOWN
|
||||
* to match against any characteristic. If both service-UUID
|
||||
* filter and characteristic-UUID filter are used with non-wildcard
|
||||
* values, then only a single characteristic callback is
|
||||
* invoked for the matching characteristic.
|
||||
*
|
||||
* @note Using wildcard values for both service-UUID and characteristic-
|
||||
* UUID will result in complete service discovery: callbacks being
|
||||
* called for every service and characteristic.
|
||||
*
|
||||
* @note Providing NULL for the characteristic callback will result in
|
||||
* characteristic discovery being skipped for each matching
|
||||
* service. This allows for an inexpensive method to discover only
|
||||
* services.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t sc = NULL,
|
||||
ServiceDiscovery::CharacteristicCallback_t cc = NULL,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
|
||||
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)sc;
|
||||
(void)cc;
|
||||
(void)matchingServiceUUID;
|
||||
(void)matchingCharacteristicUUIDIn;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch service discovery for services. Once launched, service discovery will remain
|
||||
* active with service-callbacks being issued back into the application for matching
|
||||
* services. isServiceDiscoveryActive() can be used to
|
||||
* determine status, and a termination callback (if set up) will be invoked
|
||||
* at the end. Service discovery can be terminated prematurely, if needed,
|
||||
* using terminateServiceDiscovery().
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param[in] callback
|
||||
* This is the application callback for a matching service.
|
||||
* Note: service discovery may still be active
|
||||
* when this callback is issued; calling asynchronous BLE-stack
|
||||
* APIs from within this application callback might cause the
|
||||
* stack to abort service discovery. If this becomes an issue, it
|
||||
* may be better to make a local copy of the discoveredService and
|
||||
* wait for service discovery to terminate before operating on the
|
||||
* service.
|
||||
* @param[in] matchingServiceUUID
|
||||
* UUID-based filter for specifying a service in which the application is
|
||||
* interested. By default it is set as the wildcard UUID_UNKNOWN,
|
||||
* in which case it matches all services.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t discoverServices(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t callback,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) {
|
||||
return launchServiceDiscovery(connectionHandle, callback, NULL, matchingServiceUUID); /* We take advantage of the property
|
||||
* that providing NULL for the characteristic callback will result in
|
||||
* characteristic discovery being skipped for each matching
|
||||
* service. This allows for an inexpensive method to discover only
|
||||
* services. Porters are free to override this. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch service discovery for services. Once launched, service discovery will remain
|
||||
* active with service-callbacks being issued back into the application for matching
|
||||
* services. isServiceDiscoveryActive() can be used to
|
||||
* determine status, and a termination callback (if set up) will be invoked
|
||||
* at the end. Service discovery can be terminated prematurely, if needed,
|
||||
* using terminateServiceDiscovery().
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param[in] callback
|
||||
* This is the application callback for a matching service.
|
||||
* Note: service discovery may still be active
|
||||
* when this callback is issued; calling asynchronous BLE-stack
|
||||
* APIs from within this application callback might cause the
|
||||
* stack to abort service discovery. If this becomes an issue, it
|
||||
* may be better to make a local copy of the discoveredService and
|
||||
* wait for service discovery to terminate before operating on the
|
||||
* service.
|
||||
* @param[in] startHandle, endHandle
|
||||
* Handle range within which to limit the search.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t discoverServices(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t callback,
|
||||
GattAttribute::Handle_t startHandle,
|
||||
GattAttribute::Handle_t endHandle) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)callback;
|
||||
(void)startHandle;
|
||||
(void)endHandle;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if service-discovery is currently active.
|
||||
*
|
||||
* @return true if service-discovery is active, false otherwise.
|
||||
*/
|
||||
virtual bool isServiceDiscoveryActive(void) const {
|
||||
return false; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate an ongoing service discovery. This should result in an
|
||||
* invocation of TerminationCallback if service-discovery is active.
|
||||
*/
|
||||
virtual void terminateServiceDiscovery(void) {
|
||||
/* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a GATT Client read procedure by attribute-handle.
|
||||
*
|
||||
* @param[in] connHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param[in] attributeHandle
|
||||
* Handle of the attribute to read data from.
|
||||
* @param[in] offset
|
||||
* The offset from the start of the attribute value to be read.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if read procedure was successfully started.
|
||||
*/
|
||||
virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connHandle;
|
||||
(void)attributeHandle;
|
||||
(void)offset;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a GATT Client write procedure.
|
||||
*
|
||||
* @param[in] cmd
|
||||
* Command can be either a write-request (which generates a
|
||||
* matching response from the peripheral), or a write-command
|
||||
* (which doesn't require the connected peer to respond).
|
||||
* @param[in] connHandle
|
||||
* Connection handle.
|
||||
* @param[in] attributeHandle
|
||||
* Handle for the target attribtue on the remote GATT server.
|
||||
* @param[in] length
|
||||
* Length of the new value.
|
||||
* @param[in] value
|
||||
* New value being written.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if write procedure was successfully started.
|
||||
*/
|
||||
virtual ble_error_t write(GattClient::WriteOp_t cmd,
|
||||
Gap::Handle_t connHandle,
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
size_t length,
|
||||
const uint8_t *value) const {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)cmd;
|
||||
(void)connHandle;
|
||||
(void)attributeHandle;
|
||||
(void)length;
|
||||
(void)value;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/* Event callback handlers. */
|
||||
public:
|
||||
/**
|
||||
* Set up a callback for read response events.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to chain together multiple onDataRead callbacks
|
||||
* (potentially from different modules of an application).
|
||||
*
|
||||
* @note It is possible to unregister a callback using
|
||||
* onDataRead().detach(callbackToRemove).
|
||||
*/
|
||||
void onDataRead(ReadCallback_t callback) {
|
||||
onDataReadCallbackChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of read event callbacks.
|
||||
*
|
||||
* @return A reference to the read event callback chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onDataRead().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onDataRead().detach(callback).
|
||||
*/
|
||||
ReadCallbackChain_t& onDataRead() {
|
||||
return onDataReadCallbackChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for write response events.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to remove registered callbacks using
|
||||
* onDataWritten().detach(callbackToRemove).
|
||||
*
|
||||
* @note Write commands (issued using writeWoResponse) don't generate a response.
|
||||
*/
|
||||
void onDataWritten(WriteCallback_t callback) {
|
||||
onDataWriteCallbackChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of data written callbacks.
|
||||
*
|
||||
* @return A reference to the data written callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onDataWritten().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onDataWritten().detach(callback).
|
||||
*/
|
||||
WriteCallbackChain_t& onDataWritten() {
|
||||
return onDataWriteCallbackChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for write response events.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note Write commands (issued using writeWoResponse) don't generate a response.
|
||||
*
|
||||
* @deprecated Please use GattServer::onDataWritten() instead.
|
||||
*/
|
||||
void onDataWrite(WriteCallback_t callback) {
|
||||
onDataWritten(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when serviceDiscovery terminates.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
||||
(void)callback; /* Avoid compiler warnings about ununsed variables. */
|
||||
|
||||
/* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Launch discovery of descriptors for a given characteristic.
|
||||
*
|
||||
* @details This function will discover all descriptors available for a
|
||||
* specific characteristic.
|
||||
*
|
||||
* @param[in] characteristic
|
||||
* The characteristic targeted by this discovery procedure.
|
||||
* @param[in] discoveryCallback
|
||||
* User function called each time a descriptor is found during
|
||||
* the procedure.
|
||||
* @param[in] terminationCallback
|
||||
* User provided function which will be called once the
|
||||
* discovery procedure is terminating. This will get called
|
||||
* when all the descriptors have been discovered or if an
|
||||
* error occur during the discovery procedure.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if characteristic descriptor discovery is launched
|
||||
* successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t discoverCharacteristicDescriptors(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback) {
|
||||
(void) characteristic;
|
||||
(void) discoveryCallback;
|
||||
(void) terminationCallback;
|
||||
/* Requesting action from porter(s): override this API if this capability is supported. */
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Indicate if the discovery of characteristic descriptors is active
|
||||
* for a given characteristic or not.
|
||||
*
|
||||
* @param[in] characteristic
|
||||
* The characteristic concerned by the descriptors discovery.
|
||||
*
|
||||
* @return true if a descriptors discovery is active for the characteristic
|
||||
* in input; otherwise false.
|
||||
*/
|
||||
virtual bool isCharacteristicDescriptorDiscoveryActive(const DiscoveredCharacteristic& characteristic) const
|
||||
{
|
||||
(void) characteristic;
|
||||
return false; /* Requesting action from porter(s): override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminate an ongoing characteristic descriptor discovery.
|
||||
*
|
||||
* @details This should result in an invocation of the TerminationCallback if
|
||||
* the characteristic descriptor discovery is active.
|
||||
*
|
||||
* @param[in] characteristic
|
||||
* The characteristic on which the running descriptors
|
||||
* discovery should be stopped.
|
||||
*/
|
||||
virtual void terminateCharacteristicDescriptorDiscovery(const DiscoveredCharacteristic& characteristic) {
|
||||
/* Requesting action from porter(s): override this API if this capability is supported. */
|
||||
(void) characteristic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when the GATT Client receives an update event
|
||||
* corresponding to a change in the value of a characteristic on the remote
|
||||
* GATT Server.
|
||||
*
|
||||
* @note It is possible to unregister callbacks using
|
||||
* onHVX().detach(callbackToRemove).
|
||||
*/
|
||||
void onHVX(HVXCallback_t callback) {
|
||||
onHVXCallbackChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a callback to be invoked to notify the user application that the
|
||||
* GattClient instance is about to shutdown (possibly as a result of a call
|
||||
* to BLE::shutdown()).
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to chain together multiple onShutdown callbacks
|
||||
* (potentially from different modules of an application) to be notified
|
||||
* before the GattClient is shutdown.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*
|
||||
* @note It is possible to unregister a callback using onShutdown().detach(callback).
|
||||
*/
|
||||
void onShutdown(const GattClientShutdownCallback_t& callback) {
|
||||
shutdownCallChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattClient::onShutdown(), but allows the possibility to add an object
|
||||
* reference and member function as handler for shutdown event
|
||||
* callbacks.
|
||||
*
|
||||
* @param[in] objPtr
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p memberPtr).
|
||||
* @param[in] memberPtr
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *)) {
|
||||
shutdownCallChain.add(objPtr, memberPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of shutdown event callbacks.
|
||||
*
|
||||
* @return A reference to the shutdown event callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onShutdown().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onShutdown().detach(callback).
|
||||
*/
|
||||
GattClientShutdownCallbackChain_t& onShutdown() {
|
||||
return shutdownCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief provide access to the callchain of HVX callbacks.
|
||||
*
|
||||
* @return A reference to the HVX callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onHVX().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onHVX().detach(callback).
|
||||
*/
|
||||
HVXCallbackChain_t& onHVX() {
|
||||
return onHVXCallbackChain;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Notify all registered onShutdown callbacks that the GattClient is
|
||||
* about to be shutdown and clear all GattClient state of the
|
||||
* associated object.
|
||||
*
|
||||
* This function is meant to be overridden in the platform-specific
|
||||
* sub-class. Nevertheless, the sub-class is only expected to reset its
|
||||
* state and not the data held in GattClient members. This shall be achieved
|
||||
* by a call to GattClient::reset() from the sub-class' reset()
|
||||
* implementation.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
/* Notify that the instance is about to shutdown */
|
||||
shutdownCallChain.call(this);
|
||||
shutdownCallChain.clear();
|
||||
|
||||
onDataReadCallbackChain.clear();
|
||||
onDataWriteCallbackChain.clear();
|
||||
onHVXCallbackChain.clear();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
protected:
|
||||
GattClient() {
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
/* Entry points for the underlying stack to report events back to the user. */
|
||||
public:
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of a data read event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when a data read event occurs.
|
||||
*
|
||||
* @param[in] params
|
||||
* The data read parameters passed to the registered
|
||||
* handlers.
|
||||
*/
|
||||
void processReadResponse(const GattReadCallbackParams *params) {
|
||||
onDataReadCallbackChain(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of a data written event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when a data written event occurs.
|
||||
*
|
||||
* @param[in] params
|
||||
* The data written parameters passed to the registered
|
||||
* handlers.
|
||||
*/
|
||||
void processWriteResponse(const GattWriteCallbackParams *params) {
|
||||
onDataWriteCallbackChain(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of an update event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when an update event occurs.
|
||||
*
|
||||
* @param[in] params
|
||||
* The update event parameters passed to the registered
|
||||
* handlers.
|
||||
*/
|
||||
void processHVXEvent(const GattHVXCallbackParams *params) {
|
||||
if (onHVXCallbackChain) {
|
||||
onHVXCallbackChain(params);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data read
|
||||
* events.
|
||||
*/
|
||||
ReadCallbackChain_t onDataReadCallbackChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data write
|
||||
* events.
|
||||
*/
|
||||
WriteCallbackChain_t onDataWriteCallbackChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for update
|
||||
* events.
|
||||
*/
|
||||
HVXCallbackChain_t onHVXCallbackChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for shutdown
|
||||
* events.
|
||||
*/
|
||||
GattClientShutdownCallbackChain_t shutdownCallChain;
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
GattClient(const GattClient &);
|
||||
GattClient& operator=(const GattClient &);
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_CLIENT_H__ */
|
|
@ -0,0 +1,689 @@
|
|||
/* 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 __GATT_SERVER_H__
|
||||
#define __GATT_SERVER_H__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "GattService.h"
|
||||
#include "GattAttribute.h"
|
||||
#include "GattServerEvents.h"
|
||||
#include "GattCallbackParamTypes.h"
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
|
||||
class GattServer {
|
||||
public:
|
||||
/**
|
||||
* Type for the registered callbacks added to the data sent callchain.
|
||||
* Refer to GattServer::onDataSent().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<unsigned> DataSentCallback_t;
|
||||
/**
|
||||
* Type for the data sent event callchain. Refer to GattServer::onDataSent().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<unsigned> DataSentCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the data written callchain.
|
||||
* Refer to GattServer::onDataWritten().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattWriteCallbackParams*> DataWrittenCallback_t;
|
||||
/**
|
||||
* Type for the data written event callchain. Refer to GattServer::onDataWritten().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattWriteCallbackParams*> DataWrittenCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the data read callchain.
|
||||
* Refer to GattServer::onDataRead().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattReadCallbackParams*> DataReadCallback_t;
|
||||
/**
|
||||
* Type for the data read event callchain. Refer to GattServer::onDataRead().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattReadCallbackParams *> DataReadCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callbacks added to the shutdown callchain.
|
||||
* Refer to GattServer::onShutdown().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const GattServer *> GattServerShutdownCallback_t;
|
||||
/**
|
||||
* Type for the shutdown event callchain. Refer to GattServer::onShutdown().
|
||||
*/
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattServer *> GattServerShutdownCallbackChain_t;
|
||||
|
||||
/**
|
||||
* Type for the registered callback for various events. Refer to
|
||||
* GattServer::onUpdatesEnabled(), GattServer::onUpdateDisabled() and
|
||||
* GattServer::onConfirmationReceived().
|
||||
*/
|
||||
typedef FunctionPointerWithContext<GattAttribute::Handle_t> EventCallback_t;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Construct a GattServer instance.
|
||||
*/
|
||||
GattServer() :
|
||||
serviceCount(0),
|
||||
characteristicCount(0),
|
||||
dataSentCallChain(),
|
||||
dataWrittenCallChain(),
|
||||
dataReadCallChain(),
|
||||
updatesEnabledCallback(NULL),
|
||||
updatesDisabledCallback(NULL),
|
||||
confirmationReceivedCallback(NULL) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/*
|
||||
* The following functions are meant to be overridden in the platform-specific sub-class.
|
||||
*/
|
||||
public:
|
||||
|
||||
/**
|
||||
* Add a service declaration to the local server ATT table. Also add the
|
||||
* characteristics contained within.
|
||||
*
|
||||
* @param[in] service
|
||||
* The service to be added.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the service was successfully added.
|
||||
*/
|
||||
virtual ble_error_t addService(GattService &service) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)service;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of a characteristic from the local GATT server.
|
||||
*
|
||||
* @param[in] attributeHandle
|
||||
* Attribute handle for the value attribute of the characteristic.
|
||||
* @param[out] buffer
|
||||
* A buffer to hold the value being read.
|
||||
* @param[in,out] lengthP
|
||||
* Length of the buffer being supplied. If the attribute
|
||||
* value is longer than the size of the supplied buffer,
|
||||
* this variable will hold upon return the total attribute value length
|
||||
* (excluding offset). The application may use this
|
||||
* information to allocate a suitable buffer size.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
|
||||
*/
|
||||
virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)attributeHandle;
|
||||
(void)buffer;
|
||||
(void)lengthP;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of a characteristic from the local GATT server.
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Connection handle.
|
||||
* @param[in] attributeHandle
|
||||
* Attribute handle for the value attribute of the characteristic.
|
||||
* @param[out] buffer
|
||||
* A buffer to hold the value being read.
|
||||
* @param[in,out] lengthP
|
||||
* Length of the buffer being supplied. If the attribute
|
||||
* value is longer than the size of the supplied buffer,
|
||||
* this variable will hold upon return the total attribute value length
|
||||
* (excluding offset). The application may use this
|
||||
* information to allocate a suitable buffer size.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if a value was read successfully into the buffer.
|
||||
*
|
||||
* @note This API is a version of the above, with an additional connection handle
|
||||
* parameter to allow fetches for connection-specific multivalued
|
||||
* attributes (such as the CCCDs).
|
||||
*/
|
||||
virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t *buffer, uint16_t *lengthP) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)attributeHandle;
|
||||
(void)buffer;
|
||||
(void)lengthP;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value of a characteristic on the local GATT server.
|
||||
*
|
||||
* @param[in] attributeHandle
|
||||
* Handle for the value attribute of the characteristic.
|
||||
* @param[in] value
|
||||
* A pointer to a buffer holding the new value.
|
||||
* @param[in] size
|
||||
* Size of the new value (in bytes).
|
||||
* @param[in] localOnly
|
||||
* Should this update be kept on the local
|
||||
* GATT server regardless of the state of the
|
||||
* notify/indicate flag in the CCCD for this
|
||||
* Characteristic? If set to true, no notification
|
||||
* or indication is generated.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if we have successfully set the value of the attribute.
|
||||
*/
|
||||
virtual ble_error_t write(GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly = false) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)attributeHandle;
|
||||
(void)value;
|
||||
(void)size;
|
||||
(void)localOnly;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value of a characteristic on the local GATT server. A version
|
||||
* of the same as the above, with a connection handle parameter to allow updates
|
||||
* for connection-specific multivalued attributes (such as the CCCDs).
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Connection handle.
|
||||
* @param[in] attributeHandle
|
||||
* Handle for the value attribute of the characteristic.
|
||||
* @param[in] value
|
||||
* A pointer to a buffer holding the new value.
|
||||
* @param[in] size
|
||||
* Size of the new value (in bytes).
|
||||
* @param[in] localOnly
|
||||
* Should this update be kept on the local
|
||||
* GattServer regardless of the state of the
|
||||
* notify/indicate flag in the CCCD for this
|
||||
* Characteristic? If set to true, no notification
|
||||
* or indication is generated.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if we have successfully set the value of the attribute.
|
||||
*/
|
||||
virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t *value, uint16_t size, bool localOnly = false) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)attributeHandle;
|
||||
(void)value;
|
||||
(void)size;
|
||||
(void)localOnly;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the updates-enabled status (notification or indication) for the current connection from a characteristic's CCCD.
|
||||
*
|
||||
* @param[in] characteristic
|
||||
* The characteristic.
|
||||
* @param[out] enabledP
|
||||
* Upon return, *enabledP is true if updates are enabled, else false.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the connection and handle are found. False otherwise.
|
||||
*/
|
||||
virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)characteristic;
|
||||
(void)enabledP;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the connection-specific updates-enabled status (notification or indication) from a characteristic's CCCD.
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* The connection handle.
|
||||
* @param[in] characteristic
|
||||
* The characteristic.
|
||||
* @param[out] enabledP
|
||||
* Upon return, *enabledP is true if updates are enabled, else false.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the connection and handle are found. False otherwise.
|
||||
*/
|
||||
virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)characteristic;
|
||||
(void)enabledP;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* A virtual function to allow underlying stacks to indicate if they support
|
||||
* onDataRead(). It should be overridden to return true as applicable.
|
||||
*
|
||||
* @return true if onDataRead is supported, false otherwise.
|
||||
*/
|
||||
virtual bool isOnDataReadAvailable() const {
|
||||
return false; /* Requesting action from porters: override this API if this capability is supported. */
|
||||
}
|
||||
|
||||
/*
|
||||
* APIs with non-virtual implementations.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Add a callback for the GATT event DATA_SENT (which is triggered when
|
||||
* updates are sent out by GATT in the form of notifications).
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to chain together multiple onDataSent callbacks
|
||||
* (potentially from different modules of an application) to receive updates
|
||||
* to characteristics.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*/
|
||||
void onDataSent(const DataSentCallback_t& callback) {
|
||||
dataSentCallChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattServer::onDataSent(), but allows the possibility to add an object
|
||||
* reference and member function as handler for DATA_SENT event
|
||||
* callbacks.
|
||||
*
|
||||
* @param[in] objPtr
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p memberPtr).
|
||||
* @param[in] memberPtr
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count)) {
|
||||
dataSentCallChain.add(objPtr, memberPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of DATA_SENT event callbacks.
|
||||
*
|
||||
* @return A reference to the DATA_SENT event callback chain.
|
||||
*/
|
||||
DataSentCallbackChain_t& onDataSent() {
|
||||
return dataSentCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when an attribute has its value updated by or at the
|
||||
* connected peer. For a peripheral, this callback is triggered when the local
|
||||
* GATT server has an attribute updated by a write command from the peer.
|
||||
* For a central, this callback is triggered when a response is received for
|
||||
* a write request.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to chain together multiple onDataWritten callbacks
|
||||
* (potentially from different modules of an application) to receive updates
|
||||
* to characteristics. Many services, such as DFU and UART, add their own
|
||||
* onDataWritten callbacks behind the scenes to trap interesting events.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*
|
||||
* @note It is possible to unregister a callback using onDataWritten().detach(callback)
|
||||
*/
|
||||
void onDataWritten(const DataWrittenCallback_t& callback) {
|
||||
dataWrittenCallChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattServer::onDataWritten(), but allows the possibility to add an object
|
||||
* reference and member function as handler for data written event
|
||||
* callbacks.
|
||||
*
|
||||
* @param[in] objPtr
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p memberPtr).
|
||||
* @param[in] memberPtr
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void onDataWritten(T *objPtr, void (T::*memberPtr)(const GattWriteCallbackParams *context)) {
|
||||
dataWrittenCallChain.add(objPtr, memberPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of data written event callbacks.
|
||||
*
|
||||
* @return A reference to the data written event callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onDataWritten().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onDataWritten().detach(callback).
|
||||
*/
|
||||
DataWrittenCallbackChain_t& onDataWritten() {
|
||||
return dataWrittenCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a callback to be invoked on the peripheral when an attribute is
|
||||
* being read by a remote client.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @return BLE_ERROR_NOT_IMPLEMENTED if this functionality isn't available;
|
||||
* else BLE_ERROR_NONE.
|
||||
*
|
||||
* @note This functionality may not be available on all underlying stacks.
|
||||
* You could use GattCharacteristic::setReadAuthorizationCallback() as an
|
||||
* alternative. Refer to isOnDataReadAvailable().
|
||||
*
|
||||
* @note It is possible to chain together multiple onDataRead callbacks
|
||||
* (potentially from different modules of an application) to receive updates
|
||||
* to characteristics. Services may add their own onDataRead callbacks
|
||||
* behind the scenes to trap interesting events.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*
|
||||
* @note It is possible to unregister a callback using onDataRead().detach(callback).
|
||||
*/
|
||||
ble_error_t onDataRead(const DataReadCallback_t& callback) {
|
||||
if (!isOnDataReadAvailable()) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
dataReadCallChain.add(callback);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattServer::onDataRead(), but allows the possibility to add an object
|
||||
* reference and member function as handler for data read event
|
||||
* callbacks.
|
||||
*
|
||||
* @param[in] objPtr
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p memberPtr).
|
||||
* @param[in] memberPtr
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
ble_error_t onDataRead(T *objPtr, void (T::*memberPtr)(const GattReadCallbackParams *context)) {
|
||||
if (!isOnDataReadAvailable()) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
dataReadCallChain.add(objPtr, memberPtr);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of data read event callbacks.
|
||||
*
|
||||
* @return A reference to the data read event callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onDataRead().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onDataRead().detach(callback).
|
||||
*/
|
||||
DataReadCallbackChain_t& onDataRead() {
|
||||
return dataReadCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a callback to be invoked to notify the user application that the
|
||||
* GattServer instance is about to shutdown (possibly as a result of a call
|
||||
* to BLE::shutdown()).
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*
|
||||
* @note It is possible to chain together multiple onShutdown callbacks
|
||||
* (potentially from different modules of an application) to be notified
|
||||
* before the GattServer is shutdown.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*
|
||||
* @note It is possible to unregister a callback using onShutdown().detach(callback)
|
||||
*/
|
||||
void onShutdown(const GattServerShutdownCallback_t& callback) {
|
||||
shutdownCallChain.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as GattServer::onShutdown(), but allows the possibility to add an object
|
||||
* reference and member function as handler for shutdown event
|
||||
* callbacks.
|
||||
*
|
||||
* @param[in] objPtr
|
||||
* Pointer to the object of a class defining the member callback
|
||||
* function (@p memberPtr).
|
||||
* @param[in] memberPtr
|
||||
* The member callback (within the context of an object) to be
|
||||
* invoked.
|
||||
*/
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattServer *)) {
|
||||
shutdownCallChain.add(objPtr, memberPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide access to the callchain of shutdown event callbacks.
|
||||
*
|
||||
* @return A reference to the shutdown event callbacks chain.
|
||||
*
|
||||
* @note It is possible to register callbacks using onShutdown().add(callback).
|
||||
*
|
||||
* @note It is possible to unregister callbacks using onShutdown().detach(callback).
|
||||
*/
|
||||
GattServerShutdownCallbackChain_t& onShutdown() {
|
||||
return shutdownCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when notifications or indications are enabled for a
|
||||
* characteristic on the local GATT server.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
void onUpdatesEnabled(EventCallback_t callback) {
|
||||
updatesEnabledCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when notifications or indications are disabled for a
|
||||
* characteristic on the local GATT server.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
void onUpdatesDisabled(EventCallback_t callback) {
|
||||
updatesDisabledCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a callback for when the GATT server receives a response for an
|
||||
* indication event sent previously.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Event handler being registered.
|
||||
*/
|
||||
void onConfirmationReceived(EventCallback_t callback) {
|
||||
confirmationReceivedCallback = callback;
|
||||
}
|
||||
|
||||
/* Entry points for the underlying stack to report events back to the user. */
|
||||
protected:
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of a data written event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when a data written event occurs.
|
||||
*
|
||||
* @param[in] params
|
||||
* The data written parameters passed to the registered
|
||||
* handlers.
|
||||
*/
|
||||
void handleDataWrittenEvent(const GattWriteCallbackParams *params) {
|
||||
dataWrittenCallChain.call(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of a data read event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when a data read event occurs.
|
||||
*
|
||||
* @param[in] params
|
||||
* The data read parameters passed to the registered
|
||||
* handlers.
|
||||
*/
|
||||
void handleDataReadEvent(const GattReadCallbackParams *params) {
|
||||
dataReadCallChain.call(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that notifies the registered handler of an occurrence
|
||||
* of updates enabled, updates disabled and confirmation received events.
|
||||
* This function is meant to be called from the BLE stack specific
|
||||
* implementation when any of these events occurs.
|
||||
*
|
||||
* @param[in] type
|
||||
* The type of event that occurred.
|
||||
* @param[in] attributeHandle
|
||||
* The handle of the attribute that was modified.
|
||||
*/
|
||||
void handleEvent(GattServerEvents::gattEvent_e type, GattAttribute::Handle_t attributeHandle) {
|
||||
switch (type) {
|
||||
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
|
||||
if (updatesEnabledCallback) {
|
||||
updatesEnabledCallback(attributeHandle);
|
||||
}
|
||||
break;
|
||||
case GattServerEvents::GATT_EVENT_UPDATES_DISABLED:
|
||||
if (updatesDisabledCallback) {
|
||||
updatesDisabledCallback(attributeHandle);
|
||||
}
|
||||
break;
|
||||
case GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED:
|
||||
if (confirmationReceivedCallback) {
|
||||
confirmationReceivedCallback(attributeHandle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that notifies all registered handlers of an occurrence
|
||||
* of a data sent event. This function is meant to be called from the
|
||||
* BLE stack specific implementation when a data sent event occurs.
|
||||
*
|
||||
* @param[in] count
|
||||
* Number of packets sent.
|
||||
*/
|
||||
void handleDataSentEvent(unsigned count) {
|
||||
dataSentCallChain.call(count);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Notify all registered onShutdown callbacks that the GattServer is
|
||||
* about to be shutdown and clear all GattServer state of the
|
||||
* associated object.
|
||||
*
|
||||
* This function is meant to be overridden in the platform-specific
|
||||
* sub-class. Nevertheless, the sub-class is only expected to reset its
|
||||
* state and not the data held in GattServer members. This shall be achieved
|
||||
* by a call to GattServer::reset() from the sub-class' reset()
|
||||
* implementation.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
/* Notify that the instance is about to shutdown */
|
||||
shutdownCallChain.call(this);
|
||||
shutdownCallChain.clear();
|
||||
|
||||
serviceCount = 0;
|
||||
characteristicCount = 0;
|
||||
|
||||
dataSentCallChain.clear();
|
||||
dataWrittenCallChain.clear();
|
||||
dataReadCallChain.clear();
|
||||
updatesEnabledCallback = NULL;
|
||||
updatesDisabledCallback = NULL;
|
||||
confirmationReceivedCallback = NULL;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The total number of services added to the ATT table.
|
||||
*/
|
||||
uint8_t serviceCount;
|
||||
/**
|
||||
* The total number of characteristics added to the ATT table.
|
||||
*/
|
||||
uint8_t characteristicCount;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data sent
|
||||
* events.
|
||||
*/
|
||||
DataSentCallbackChain_t dataSentCallChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data written
|
||||
* events.
|
||||
*/
|
||||
DataWrittenCallbackChain_t dataWrittenCallChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data read
|
||||
* events.
|
||||
*/
|
||||
DataReadCallbackChain_t dataReadCallChain;
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for shutdown
|
||||
* events.
|
||||
*/
|
||||
GattServerShutdownCallbackChain_t shutdownCallChain;
|
||||
/**
|
||||
* The registered callback handler for updates enabled events.
|
||||
*/
|
||||
EventCallback_t updatesEnabledCallback;
|
||||
/**
|
||||
* The registered callback handler for updates disabled events.
|
||||
*/
|
||||
EventCallback_t updatesDisabledCallback;
|
||||
/**
|
||||
* The registered callback handler for confirmation received events.
|
||||
*/
|
||||
EventCallback_t confirmationReceivedCallback;
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
GattServer(const GattServer &);
|
||||
GattServer& operator=(const GattServer &);
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_SERVER_H__ */
|
|
@ -0,0 +1,41 @@
|
|||
/* 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 __GATT_SERVER_EVENTS_H__
|
||||
#define __GATT_SERVER_EVENTS_H__
|
||||
|
||||
/**
|
||||
* @brief The base class used to abstract away the callback events that can be
|
||||
* triggered with the GATT Server.
|
||||
*/
|
||||
class GattServerEvents
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Enumeration for GattServer events.
|
||||
*/
|
||||
typedef enum gattEvent_e {
|
||||
GATT_EVENT_DATA_SENT = 1, /**< Fired when a message was successfully sent out (notify only?) */
|
||||
GATT_EVENT_DATA_WRITTEN = 2, /**< Client wrote data to the server (separate into char and descriptor writes?) */
|
||||
GATT_EVENT_UPDATES_ENABLED = 3, /**< Notify/Indicate enabled in CCCD. */
|
||||
GATT_EVENT_UPDATES_DISABLED = 4, /**< Notify/Indicate disabled in CCCD. */
|
||||
GATT_EVENT_CONFIRMATION_RECEIVED = 5, /**< Response received from Indicate message. */
|
||||
GATT_EVENT_READ_AUTHORIZATION_REQ = 6, /**< Request application to authorize read. */
|
||||
GATT_EVENT_WRITE_AUTHORIZATION_REQ = 7, /**< Request application to authorize write. */
|
||||
} gattEvent_t;
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_SERVER_EVENTS_H__ */
|
|
@ -0,0 +1,144 @@
|
|||
/* 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 __GATT_SERVICE_H__
|
||||
#define __GATT_SERVICE_H__
|
||||
|
||||
#include "UUID.h"
|
||||
#include "GattCharacteristic.h"
|
||||
|
||||
class GattService {
|
||||
public:
|
||||
enum {
|
||||
UUID_ALERT_NOTIFICATION_SERVICE = 0x1811,
|
||||
UUID_BATTERY_SERVICE = 0x180F,
|
||||
UUID_BLOOD_PRESSURE_SERVICE = 0x1810,
|
||||
UUID_CURRENT_TIME_SERVICE = 0x1805,
|
||||
UUID_CYCLING_SPEED_AND_CADENCE = 0x1816,
|
||||
UUID_DEVICE_INFORMATION_SERVICE = 0x180A,
|
||||
UUID_ENVIRONMENTAL_SERVICE = 0x181A,
|
||||
UUID_GLUCOSE_SERVICE = 0x1808,
|
||||
UUID_HEALTH_THERMOMETER_SERVICE = 0x1809,
|
||||
UUID_HEART_RATE_SERVICE = 0x180D,
|
||||
UUID_HUMAN_INTERFACE_DEVICE_SERVICE = 0x1812,
|
||||
UUID_IMMEDIATE_ALERT_SERVICE = 0x1802,
|
||||
UUID_LINK_LOSS_SERVICE = 0x1803,
|
||||
UUID_NEXT_DST_CHANGE_SERVICE = 0x1807,
|
||||
UUID_PHONE_ALERT_STATUS_SERVICE = 0x180E,
|
||||
UUID_REFERENCE_TIME_UPDATE_SERVICE = 0x1806,
|
||||
UUID_RUNNING_SPEED_AND_CADENCE = 0x1814,
|
||||
UUID_SCAN_PARAMETERS_SERVICE = 0x1813,
|
||||
UUID_TX_POWER_SERVICE = 0x1804
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new GattService using the specified 16-bit
|
||||
* UUID, value length, and properties.
|
||||
*
|
||||
* @note The UUID value must be unique and is normally >1.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* The UUID to use for this service.
|
||||
* @param[in] characteristics
|
||||
* A pointer to an array of characteristics to be included within this service.
|
||||
* @param[in] numCharacteristics
|
||||
* The number of characteristics.
|
||||
*/
|
||||
GattService(const UUID &uuid, GattCharacteristic *characteristics[], unsigned numCharacteristics) :
|
||||
_primaryServiceID(uuid),
|
||||
_characteristicCount(numCharacteristics),
|
||||
_characteristics(characteristics),
|
||||
_handle(0) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this service's UUID.
|
||||
*
|
||||
* @return A reference to the service's UUID.
|
||||
*/
|
||||
const UUID &getUUID(void) const {
|
||||
return _primaryServiceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get handle of the service declaration attribute in the ATT table.
|
||||
*
|
||||
* @return The service's handle.
|
||||
*/
|
||||
uint16_t getHandle(void) const {
|
||||
return _handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of characteristics within this service.
|
||||
*
|
||||
* @return The total number of characteristics within this service.
|
||||
*/
|
||||
uint8_t getCharacteristicCount(void) const {
|
||||
return _characteristicCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the handle of the service declaration attribute in the ATT table.
|
||||
*
|
||||
* @param[in] handle
|
||||
* The service's handle.
|
||||
*/
|
||||
void setHandle(uint16_t handle) {
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this service's characteristic at a specific index.
|
||||
*
|
||||
* @param[in] index
|
||||
* The index of the characteristic.
|
||||
*
|
||||
* @return A pointer to the characterisitic at index @p index.
|
||||
*/
|
||||
GattCharacteristic *getCharacteristic(uint8_t index) {
|
||||
if (index >= _characteristicCount) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _characteristics[index];
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* This service's UUID.
|
||||
*/
|
||||
UUID _primaryServiceID;
|
||||
/**
|
||||
* Total number of characteristics within this service.
|
||||
*/
|
||||
uint8_t _characteristicCount;
|
||||
/**
|
||||
* An array with pointers to the characteristics added to this service.
|
||||
*/
|
||||
GattCharacteristic **_characteristics;
|
||||
/**
|
||||
* Handle of the service declaration attribute in the ATT table.
|
||||
*
|
||||
* @note This handle is generally assigned by the underlying BLE stack when the
|
||||
* service is added to the ATT table.
|
||||
*/
|
||||
uint16_t _handle;
|
||||
};
|
||||
|
||||
#endif /* ifndef __GATT_SERVICE_H__ */
|
|
@ -0,0 +1,124 @@
|
|||
/* 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 BLE_API_SAFE_BOOL_H_
|
||||
#define BLE_API_SAFE_BOOL_H_
|
||||
|
||||
/* Safe bool idiom, see : http://www.artima.com/cppsource/safebool.html */
|
||||
|
||||
namespace SafeBool_ {
|
||||
/**
|
||||
* @brief Base class for all intances of SafeBool.
|
||||
* This base class reduces instantiation of trueTag function.
|
||||
*/
|
||||
class base {
|
||||
template<typename>
|
||||
friend class SafeBool;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The bool type is a pointer to method which can be used in boolean context.
|
||||
*/
|
||||
typedef void (base::*BoolType_t)() const;
|
||||
|
||||
/**
|
||||
* Non implemented call, use to disallow conversion between unrelated types.
|
||||
*/
|
||||
void invalidTag() const;
|
||||
|
||||
/**
|
||||
* Member function which indicate true value.
|
||||
*/
|
||||
void trueTag() const {}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief template class SafeBool use CRTP to made boolean conversion easy and correct.
|
||||
* Derived class should implement the function bool toBool() const to make this work. Inheritance
|
||||
* should be public.
|
||||
*
|
||||
* @tparam T Type of the derived class
|
||||
*
|
||||
* @code
|
||||
*
|
||||
* class A : public SafeBool<A> {
|
||||
* public:
|
||||
*
|
||||
* // boolean conversion
|
||||
* bool toBool() {
|
||||
*
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* class B : public SafeBool<B> {
|
||||
* public:
|
||||
*
|
||||
* // boolean conversion
|
||||
* bool toBool() const {
|
||||
*
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* A a;
|
||||
* B b;
|
||||
*
|
||||
* // will compile
|
||||
* if(a) {
|
||||
*
|
||||
* }
|
||||
*
|
||||
* // compilation error
|
||||
* if(a == b) {
|
||||
*
|
||||
* }
|
||||
*
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
template <typename T>
|
||||
class SafeBool : public SafeBool_::base {
|
||||
public:
|
||||
/**
|
||||
* Bool operator implementation, derived class has to provide bool toBool() const function.
|
||||
*/
|
||||
operator BoolType_t() const {
|
||||
return (static_cast<const T*>(this))->toBool()
|
||||
? &SafeBool<T>::trueTag : 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Avoid conversion to bool between different classes.
|
||||
*/
|
||||
template <typename T, typename U>
|
||||
void operator==(const SafeBool<T>& lhs,const SafeBool<U>& rhs) {
|
||||
lhs.invalidTag();
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid conversion to bool between different classes.
|
||||
*/
|
||||
template <typename T,typename U>
|
||||
void operator!=(const SafeBool<T>& lhs,const SafeBool<U>& rhs) {
|
||||
lhs.invalidTag();
|
||||
// return false;
|
||||
}
|
||||
|
||||
#endif /* BLE_API_SAFE_BOOL_H_ */
|
|
@ -0,0 +1,331 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
|
||||
#ifndef __SECURITY_MANAGER_H__
|
||||
#define __SECURITY_MANAGER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Gap.h"
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
|
||||
class SecurityManager {
|
||||
public:
|
||||
enum SecurityMode_t {
|
||||
SECURITY_MODE_NO_ACCESS,
|
||||
SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< Require no protection, open link. */
|
||||
SECURITY_MODE_ENCRYPTION_NO_MITM, /**< Require encryption, but no MITM protection. */
|
||||
SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< Require encryption and MITM protection. */
|
||||
SECURITY_MODE_SIGNED_NO_MITM, /**< Require signing or encryption, but no MITM protection. */
|
||||
SECURITY_MODE_SIGNED_WITH_MITM, /**< Require signing or encryption, and MITM protection. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Defines possible security status or states.
|
||||
*
|
||||
* @details Defines possible security status or states of a link when requested by getLinkSecurity().
|
||||
*/
|
||||
enum LinkSecurityStatus_t {
|
||||
NOT_ENCRYPTED, /**< The link is not secured. */
|
||||
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
|
||||
ENCRYPTED /**< The link is secure.*/
|
||||
};
|
||||
|
||||
enum SecurityIOCapabilities_t {
|
||||
IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display only. */
|
||||
IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and yes/no entry. */
|
||||
IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard only. */
|
||||
IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */
|
||||
IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and display. */
|
||||
};
|
||||
|
||||
enum SecurityCompletionStatus_t {
|
||||
SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */
|
||||
SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */
|
||||
SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */
|
||||
SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user canceled or other). */
|
||||
SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */
|
||||
SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */
|
||||
SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */
|
||||
SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */
|
||||
SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */
|
||||
SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */
|
||||
SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */
|
||||
SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */
|
||||
SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Declaration of type containing a passkey to be used during pairing. This
|
||||
* is passed into initializeSecurity() to specify a pre-programmed passkey
|
||||
* for authentication instead of generating a random one.
|
||||
*/
|
||||
static const unsigned PASSKEY_LEN = 6;
|
||||
typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
|
||||
|
||||
public:
|
||||
typedef void (*HandleSpecificEvent_t)(Gap::Handle_t handle);
|
||||
typedef void (*SecuritySetupInitiatedCallback_t)(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps);
|
||||
typedef void (*SecuritySetupCompletedCallback_t)(Gap::Handle_t, SecurityCompletionStatus_t status);
|
||||
typedef void (*LinkSecuredCallback_t)(Gap::Handle_t handle, SecurityMode_t securityMode);
|
||||
typedef void (*PasskeyDisplayCallback_t)(Gap::Handle_t handle, const Passkey_t passkey);
|
||||
|
||||
typedef FunctionPointerWithContext<const SecurityManager *> SecurityManagerShutdownCallback_t;
|
||||
typedef CallChainOfFunctionPointersWithContext<const SecurityManager *> SecurityManagerShutdownCallbackChain_t;
|
||||
|
||||
/*
|
||||
* The following functions are meant to be overridden in the platform-specific sub-class.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Enable the BLE 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.
|
||||
* Calling this API is a prerequisite for encryption and pairing (bonding).
|
||||
*
|
||||
* @param[in] enableBonding Allow for bonding.
|
||||
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
|
||||
* @param[in] iocaps To specify the I/O 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.
|
||||
*/
|
||||
virtual ble_error_t init(bool enableBonding = true,
|
||||
bool requireMITM = true,
|
||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||
const Passkey_t passkey = NULL) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)enableBonding;
|
||||
(void)requireMITM;
|
||||
(void)iocaps;
|
||||
(void)passkey;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the security status of a connection.
|
||||
*
|
||||
* @param[in] connectionHandle Handle to identify the connection.
|
||||
* @param[out] securityStatusP Security status.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)securityStatusP;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Requested security mode.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)connectionHandle;
|
||||
(void)securityMode;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all peer device context and all related bonding information from
|
||||
* the database within the security manager.
|
||||
*
|
||||
* @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 or
|
||||
* application registration.
|
||||
*/
|
||||
virtual ble_error_t purgeAllBondingState(void) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of addresses from all peers in the bond table.
|
||||
*
|
||||
* @param[in,out] addresses
|
||||
* (on input) addresses.capacity contains the maximum
|
||||
* number of addresses to be returned.
|
||||
* (on output) The populated table with copies of the
|
||||
* addresses in the implementation's whitelist.
|
||||
*
|
||||
* @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 or
|
||||
* application registration.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const {
|
||||
/* Avoid compiler warnings about unused variables */
|
||||
(void) addresses;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/* Event callback handlers. */
|
||||
public:
|
||||
/**
|
||||
* Setup a callback to be invoked to notify the user application that the
|
||||
* SecurityManager instance is about to shutdown (possibly as a result of a call
|
||||
* to BLE::shutdown()).
|
||||
*
|
||||
* @note It is possible to chain together multiple onShutdown callbacks
|
||||
* (potentially from different modules of an application) to be notified
|
||||
* before the SecurityManager is shutdown.
|
||||
*
|
||||
* @note It is also possible to set up a callback into a member function of
|
||||
* some object.
|
||||
*
|
||||
* @note It is possible to unregister a callback using onShutdown().detach(callback)
|
||||
*/
|
||||
void onShutdown(const SecurityManagerShutdownCallback_t& callback) {
|
||||
shutdownCallChain.add(callback);
|
||||
}
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const SecurityManager *)) {
|
||||
shutdownCallChain.add(objPtr, memberPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief provide access to the callchain of shutdown event callbacks
|
||||
* It is possible to register callbacks using onShutdown().add(callback);
|
||||
* It is possible to unregister callbacks using onShutdown().detach(callback)
|
||||
* @return The shutdown event callbacks chain
|
||||
*/
|
||||
SecurityManagerShutdownCallbackChain_t& onShutdown() {
|
||||
return shutdownCallChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* To indicate that a security procedure for the link has started.
|
||||
*/
|
||||
virtual void onSecuritySetupInitiated(SecuritySetupInitiatedCallback_t callback) {securitySetupInitiatedCallback = callback;}
|
||||
|
||||
/**
|
||||
* To indicate that the security procedure for the link has completed.
|
||||
*/
|
||||
virtual void onSecuritySetupCompleted(SecuritySetupCompletedCallback_t callback) {securitySetupCompletedCallback = callback;}
|
||||
|
||||
/**
|
||||
* To indicate that the link with the peer is secured. For bonded devices,
|
||||
* subsequent reconnections with a bonded peer will result only in this callback
|
||||
* when the link is secured; setup procedures will not occur (unless the
|
||||
* bonding information is either lost or deleted on either or both sides).
|
||||
*/
|
||||
virtual void onLinkSecured(LinkSecuredCallback_t callback) {linkSecuredCallback = callback;}
|
||||
|
||||
/**
|
||||
* To indicate that device context is stored persistently.
|
||||
*/
|
||||
virtual void onSecurityContextStored(HandleSpecificEvent_t callback) {securityContextStoredCallback = callback;}
|
||||
|
||||
/**
|
||||
* To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability.
|
||||
*/
|
||||
virtual void onPasskeyDisplay(PasskeyDisplayCallback_t callback) {passkeyDisplayCallback = callback;}
|
||||
|
||||
/* Entry points for the underlying stack to report events back to the user. */
|
||||
public:
|
||||
void processSecuritySetupInitiatedEvent(Gap::Handle_t handle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) {
|
||||
if (securitySetupInitiatedCallback) {
|
||||
securitySetupInitiatedCallback(handle, allowBonding, requireMITM, iocaps);
|
||||
}
|
||||
}
|
||||
|
||||
void processSecuritySetupCompletedEvent(Gap::Handle_t handle, SecurityCompletionStatus_t status) {
|
||||
if (securitySetupCompletedCallback) {
|
||||
securitySetupCompletedCallback(handle, status);
|
||||
}
|
||||
}
|
||||
|
||||
void processLinkSecuredEvent(Gap::Handle_t handle, SecurityMode_t securityMode) {
|
||||
if (linkSecuredCallback) {
|
||||
linkSecuredCallback(handle, securityMode);
|
||||
}
|
||||
}
|
||||
|
||||
void processSecurityContextStoredEvent(Gap::Handle_t handle) {
|
||||
if (securityContextStoredCallback) {
|
||||
securityContextStoredCallback(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void processPasskeyDisplayEvent(Gap::Handle_t handle, const Passkey_t passkey) {
|
||||
if (passkeyDisplayCallback) {
|
||||
passkeyDisplayCallback(handle, passkey);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SecurityManager() :
|
||||
securitySetupInitiatedCallback(),
|
||||
securitySetupCompletedCallback(),
|
||||
linkSecuredCallback(),
|
||||
securityContextStoredCallback(),
|
||||
passkeyDisplayCallback() {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Notify all registered onShutdown callbacks that the SecurityManager is
|
||||
* about to be shutdown and clear all SecurityManager state of the
|
||||
* associated object.
|
||||
*
|
||||
* This function is meant to be overridden in the platform-specific
|
||||
* sub-class. Nevertheless, the sub-class is only expected to reset its
|
||||
* state and not the data held in SecurityManager members. This shall be
|
||||
* achieved by a call to SecurityManager::reset() from the sub-class'
|
||||
* reset() implementation.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
/* Notify that the instance is about to shutdown */
|
||||
shutdownCallChain.call(this);
|
||||
shutdownCallChain.clear();
|
||||
|
||||
securitySetupInitiatedCallback = NULL;
|
||||
securitySetupCompletedCallback = NULL;
|
||||
linkSecuredCallback = NULL;
|
||||
securityContextStoredCallback = NULL;
|
||||
passkeyDisplayCallback = NULL;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
protected:
|
||||
SecuritySetupInitiatedCallback_t securitySetupInitiatedCallback;
|
||||
SecuritySetupCompletedCallback_t securitySetupCompletedCallback;
|
||||
LinkSecuredCallback_t linkSecuredCallback;
|
||||
HandleSpecificEvent_t securityContextStoredCallback;
|
||||
PasskeyDisplayCallback_t passkeyDisplayCallback;
|
||||
|
||||
private:
|
||||
SecurityManagerShutdownCallbackChain_t shutdownCallChain;
|
||||
};
|
||||
|
||||
#endif /*__SECURITY_MANAGER_H__*/
|
|
@ -0,0 +1,183 @@
|
|||
/* 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 __SERVICE_DISOVERY_H__
|
||||
#define __SERVICE_DISOVERY_H__
|
||||
|
||||
#include "UUID.h"
|
||||
#include "Gap.h"
|
||||
#include "GattAttribute.h"
|
||||
|
||||
class DiscoveredService;
|
||||
class DiscoveredCharacteristic;
|
||||
|
||||
class ServiceDiscovery {
|
||||
public:
|
||||
/*
|
||||
* Exposed application callback types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Callback type for when a matching service is found during service-
|
||||
* discovery. The receiving function is passed in a pointer to a
|
||||
* DiscoveredService object, which will remain valid for the lifetime of the
|
||||
* callback. Memory for this object is owned by the BLE_API eventing
|
||||
* framework. The application can safely make a persistent shallow-copy of
|
||||
* this object to work with the service beyond the callback.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const DiscoveredService *> ServiceCallback_t;
|
||||
|
||||
/**
|
||||
* Callback type for when a matching characteristic is found during service-
|
||||
* discovery. The receiving function is passed in a pointer to a
|
||||
* DiscoveredCharacteristic object, which will remain valid for the lifetime
|
||||
* of the callback. Memory for this object is owned by the BLE_API eventing
|
||||
* framework. The application can safely make a persistent shallow-copy of
|
||||
* this object to work with the characteristic beyond the callback.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<const DiscoveredCharacteristic *> CharacteristicCallback_t;
|
||||
|
||||
/**
|
||||
* Callback type for when serviceDiscovery terminates.
|
||||
*/
|
||||
typedef FunctionPointerWithContext<Gap::Handle_t> TerminationCallback_t;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Launch service discovery. Once launched, service discovery will remain
|
||||
* active with callbacks being issued back into the application for matching
|
||||
* services or characteristics. isActive() can be used to determine status, and
|
||||
* a termination callback (if set up) will be invoked at the end. Service
|
||||
* discovery can be terminated prematurely, if needed, using terminate().
|
||||
*
|
||||
* @param connectionHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param sc
|
||||
* This is the application callback for a matching service. Taken as
|
||||
* NULL by default. Note: service discovery may still be active
|
||||
* when this callback is issued; calling asynchronous BLE-stack
|
||||
* APIs from within this application callback might cause the
|
||||
* stack to abort service discovery. If this becomes an issue, it
|
||||
* may be better to make a local copy of the discoveredService and
|
||||
* wait for service discovery to terminate before operating on the
|
||||
* service.
|
||||
* @param cc
|
||||
* This is the application callback for a matching characteristic.
|
||||
* Taken as NULL by default. Note: service discovery may still be
|
||||
* active when this callback is issued; calling asynchronous
|
||||
* BLE-stack APIs from within this application callback might cause
|
||||
* the stack to abort service discovery. If this becomes an issue,
|
||||
* it may be better to make a local copy of the discoveredCharacteristic
|
||||
* and wait for service discovery to terminate before operating on the
|
||||
* characteristic.
|
||||
* @param matchingServiceUUID
|
||||
* UUID-based filter for specifying a service in which the application is
|
||||
* interested. By default it is set as the wildcard UUID_UNKNOWN,
|
||||
* in which case it matches all services. If characteristic-UUID
|
||||
* filter (below) is set to the wildcard value, then a service
|
||||
* callback will be invoked for the matching service (or for every
|
||||
* service if the service filter is a wildcard).
|
||||
* @param matchingCharacteristicUUIDIn
|
||||
* UUID-based filter for specifying a characteristic in which the application
|
||||
* is interested. By default it is set as the wildcard UUID_UKNOWN
|
||||
* to match against any characteristic. If both service-UUID
|
||||
* filter and characteristic-UUID filter are used with non-wildcard
|
||||
* values, then only a single characteristic callback is
|
||||
* invoked for the matching characteristic.
|
||||
*
|
||||
* @note Using wildcard values for both service-UUID and characteristic-
|
||||
* UUID will result in complete service discovery: callbacks being
|
||||
* called for every service and characteristic.
|
||||
*
|
||||
* @note Providing NULL for the characteristic callback will result in
|
||||
* characteristic discovery being skipped for each matching
|
||||
* service. This allows for an inexpensive method to discover only
|
||||
* services.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t launch(Gap::Handle_t connectionHandle,
|
||||
ServiceCallback_t sc = NULL,
|
||||
CharacteristicCallback_t cc = NULL,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
|
||||
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) = 0;
|
||||
|
||||
/**
|
||||
* Check whether service-discovery is currently active.
|
||||
*/
|
||||
virtual bool isActive(void) const = 0;
|
||||
|
||||
/**
|
||||
* Terminate an ongoing service discovery. This should result in an
|
||||
* invocation of the TerminationCallback if service discovery is active.
|
||||
*/
|
||||
virtual void terminate(void) = 0;
|
||||
|
||||
/**
|
||||
* Set up a callback to be invoked when service discovery is terminated.
|
||||
*/
|
||||
virtual void onTermination(TerminationCallback_t callback) = 0;
|
||||
|
||||
/**
|
||||
* Clear all ServiceDiscovery state of the associated object.
|
||||
*
|
||||
* This function is meant to be overridden in the platform-specific
|
||||
* sub-class. Nevertheless, the sub-class is only expected to reset its
|
||||
* state and not the data held in ServiceDiscovery members. This shall be
|
||||
* achieved by a call to ServiceDiscovery::reset() from the sub-class'
|
||||
* reset() implementation.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
connHandle = 0;
|
||||
matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN);
|
||||
serviceCallback = NULL;
|
||||
matchingCharacteristicUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN);
|
||||
characteristicCallback = NULL;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Connection handle as provided by the SoftDevice.
|
||||
*/
|
||||
Gap::Handle_t connHandle;
|
||||
/**
|
||||
* UUID-based filter that specifies the service that the application is
|
||||
* interested in.
|
||||
*/
|
||||
UUID matchingServiceUUID;
|
||||
/**
|
||||
* The registered callback handle for when a matching service is found
|
||||
* during service-discovery.
|
||||
*/
|
||||
ServiceCallback_t serviceCallback;
|
||||
/**
|
||||
* UUID-based filter that specifies the characteristic that the
|
||||
* application is interested in.
|
||||
*/
|
||||
UUID matchingCharacteristicUUID;
|
||||
/**
|
||||
* The registered callback handler for when a matching characteristic is
|
||||
* found during service-discovery.
|
||||
*/
|
||||
CharacteristicCallback_t characteristicCallback;
|
||||
};
|
||||
|
||||
#endif /* ifndef __SERVICE_DISOVERY_H__ */
|
|
@ -0,0 +1,331 @@
|
|||
/* 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 __UUID_H__
|
||||
#define __UUID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "blecommon.h"
|
||||
|
||||
/**
|
||||
* A trivial converter for single hexadecimal character to an unsigned integer.
|
||||
*
|
||||
* @param c
|
||||
* Hexadecimal character.
|
||||
*
|
||||
* @return The corresponding value as unsigned integer.
|
||||
*/
|
||||
static uint8_t char2int(char c) {
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
return c - '0';
|
||||
} else if ((c >= 'a') && (c <= 'f')) {
|
||||
return c - 'a' + 10;
|
||||
} else if ((c >= 'A') && (c <= 'F')) {
|
||||
return c - 'A' + 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of this class represents a Universally Unique Identifier (UUID)
|
||||
* in the BLE API.
|
||||
*/
|
||||
class UUID {
|
||||
public:
|
||||
/**
|
||||
* Enumeration of the possible types of UUIDs in BLE with regards to length.
|
||||
*/
|
||||
enum UUID_Type_t {
|
||||
UUID_TYPE_SHORT = 0, /**< Short 16-bit UUID. */
|
||||
UUID_TYPE_LONG = 1 /**< Full 128-bit UUID. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumeration to specify byte ordering of the long version of the UUID.
|
||||
*/
|
||||
typedef enum {
|
||||
MSB, /**< Most-significant byte first (at the smallest address) */
|
||||
LSB /**< least-significant byte first (at the smallest address) */
|
||||
} ByteOrder_t;
|
||||
|
||||
/**
|
||||
* Type for a 16-bit UUID.
|
||||
*/
|
||||
typedef uint16_t ShortUUIDBytes_t;
|
||||
|
||||
/**
|
||||
* Length of a long UUID in bytes.
|
||||
*/
|
||||
static const unsigned LENGTH_OF_LONG_UUID = 16;
|
||||
/**
|
||||
* Type for a 128-bit UUID.
|
||||
*/
|
||||
typedef uint8_t LongUUIDBytes_t[LENGTH_OF_LONG_UUID];
|
||||
|
||||
/**
|
||||
* Maximum length of a string representation of a UUID not including the
|
||||
* null termination ('\0'): two characters per
|
||||
* byte plus four '-' characters.
|
||||
*/
|
||||
static const unsigned MAX_UUID_STRING_LENGTH = LENGTH_OF_LONG_UUID * 2 + 4;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a new 128-bit UUID.
|
||||
*
|
||||
* @note The UUID is a unique 128-bit (16 byte) ID used to identify
|
||||
* different service or characteristics on the BLE device.
|
||||
*
|
||||
* @param stringUUID
|
||||
* The 128-bit (16-byte) UUID as a human readable const-string.
|
||||
* Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
* Upper and lower case supported. Hyphens are optional, but only
|
||||
* upto four of them. The UUID is stored internally as a 16 byte
|
||||
* array, LSB (little endian), which is opposite from the string.
|
||||
*/
|
||||
UUID(const char* stringUUID) : type(UUID_TYPE_LONG), baseUUID(), shortUUID(0) {
|
||||
bool nibble = false;
|
||||
uint8_t byte = 0;
|
||||
size_t baseIndex = 0;
|
||||
uint8_t tempUUID[LENGTH_OF_LONG_UUID];
|
||||
|
||||
/*
|
||||
* Iterate through string, abort if NULL is encountered prematurely.
|
||||
* Ignore upto four hyphens.
|
||||
*/
|
||||
for (size_t index = 0; (index < MAX_UUID_STRING_LENGTH) && (baseIndex < LENGTH_OF_LONG_UUID); index++) {
|
||||
if (stringUUID[index] == '\0') {
|
||||
/* Error abort */
|
||||
break;
|
||||
} else if (stringUUID[index] == '-') {
|
||||
/* Ignore hyphen */
|
||||
continue;
|
||||
} else if (nibble) {
|
||||
/* Got second nibble */
|
||||
byte |= char2int(stringUUID[index]);
|
||||
nibble = false;
|
||||
|
||||
/* Store copy */
|
||||
tempUUID[baseIndex++] = byte;
|
||||
} else {
|
||||
/* Got first nibble */
|
||||
byte = char2int(stringUUID[index]) << 4;
|
||||
nibble = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Populate internal variables if string was successfully parsed */
|
||||
if (baseIndex == LENGTH_OF_LONG_UUID) {
|
||||
setupLong(tempUUID, UUID::MSB);
|
||||
} else {
|
||||
const uint8_t sig[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
|
||||
setupLong(sig, UUID::MSB);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new 128-bit UUID.
|
||||
*
|
||||
* @param[in] longUUID
|
||||
* The 128-bit (16-byte) UUID value.
|
||||
* @param[in] order
|
||||
* The bit order of the UUID, MSB by default.
|
||||
*
|
||||
* @note The UUID is a unique 128-bit (16 byte) ID used to identify
|
||||
* different service or characteristics on the BLE device.
|
||||
*/
|
||||
UUID(const LongUUIDBytes_t longUUID, ByteOrder_t order = UUID::MSB) : type(UUID_TYPE_LONG), baseUUID(), shortUUID(0) {
|
||||
setupLong(longUUID, order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new 16-bit UUID.
|
||||
*
|
||||
* For efficiency, and because 16 bytes would take a large chunk of the
|
||||
* 27-byte data payload length of the Link Layer, the BLE specification adds
|
||||
* two additional UUID formats: 16-bit and 32-bit UUIDs. These shortened
|
||||
* formats can be used only with UUIDs that are defined in the Bluetooth
|
||||
* specification (listed by the Bluetooth SIG as standard
|
||||
* Bluetooth UUIDs).
|
||||
*
|
||||
* To reconstruct the full 128-bit UUID from the shortened version, insert
|
||||
* the 16-bit short value (indicated by xxxx, including leading zeros) into
|
||||
* the Bluetooth Base UUID:
|
||||
*
|
||||
* 0000xxxx-0000-1000-8000-00805F9B34FB
|
||||
*
|
||||
* @param[in] _shortUUID
|
||||
* The short UUID value.
|
||||
*
|
||||
* @note Shortening is not available for UUIDs that are not derived from the
|
||||
* Bluetooth Base UUID. Such non-standard UUIDs are commonly called
|
||||
* vendor-specific UUIDs. In these cases, you’ll need to use the full
|
||||
* 128-bit UUID value at all times.
|
||||
*
|
||||
* @note The UUID is a unique 16-bit (2 byte) ID used to identify
|
||||
* different service or characteristics on the BLE device.
|
||||
*
|
||||
* @note We do not yet support 32-bit shortened UUIDs.
|
||||
*/
|
||||
UUID(ShortUUIDBytes_t _shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(_shortUUID) {
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*
|
||||
* @param[in] source
|
||||
* The UUID to copy.
|
||||
*/
|
||||
UUID(const UUID &source) {
|
||||
type = source.type;
|
||||
shortUUID = source.shortUUID;
|
||||
memcpy(baseUUID, source.baseUUID, LENGTH_OF_LONG_UUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The empty constructor.
|
||||
*
|
||||
* @note The type of the resulting UUID instance is UUID_TYPE_SHORT and the
|
||||
* value BLE_UUID_UNKNOWN.
|
||||
*/
|
||||
UUID(void) : type(UUID_TYPE_SHORT), shortUUID(BLE_UUID_UNKNOWN) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in a 128-bit UUID; this is useful when the UUID is not known at the
|
||||
* time of the object construction.
|
||||
*
|
||||
* @param[in] longUUID
|
||||
* The UUID value to copy.
|
||||
* @param[in] order
|
||||
* The byte ordering of the UUID at @p longUUID.
|
||||
*/
|
||||
void setupLong(const LongUUIDBytes_t longUUID, ByteOrder_t order = UUID::MSB) {
|
||||
type = UUID_TYPE_LONG;
|
||||
if (order == UUID::MSB) {
|
||||
/*
|
||||
* Switch endian. Input is big-endian, internal representation
|
||||
* is little endian.
|
||||
*/
|
||||
std::reverse_copy(longUUID, longUUID + LENGTH_OF_LONG_UUID, baseUUID);
|
||||
} else {
|
||||
std::copy(longUUID, longUUID + LENGTH_OF_LONG_UUID, baseUUID);
|
||||
}
|
||||
shortUUID = (uint16_t)((baseUUID[13] << 8) | (baseUUID[12]));
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Check whether this UUID is short or long.
|
||||
*
|
||||
* @return UUID_TYPE_SHORT if the UUID is short, UUID_TYPE_LONG otherwise.
|
||||
*/
|
||||
UUID_Type_t shortOrLong(void) const {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pointer to the UUID value based on the current UUID type.
|
||||
*
|
||||
* @return A pointer to the short UUID if the type is set to
|
||||
* UUID_TYPE_SHORT. Otherwise, a pointer to the long UUID if the
|
||||
* type is set to UUID_TYPE_LONG.
|
||||
*/
|
||||
const uint8_t *getBaseUUID(void) const {
|
||||
if (type == UUID_TYPE_SHORT) {
|
||||
return (const uint8_t*)&shortUUID;
|
||||
} else {
|
||||
return baseUUID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the short UUID.
|
||||
*
|
||||
* @return The short UUID.
|
||||
*/
|
||||
ShortUUIDBytes_t getShortUUID(void) const {
|
||||
return shortUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length (in bytes) of the UUID based on its type.
|
||||
*
|
||||
* @retval sizeof(ShortUUIDBytes_t) if the UUID type is UUID_TYPE_SHORT.
|
||||
* @retval LENGTH_OF_LONG_UUID if the UUID type is UUID_TYPE_LONG.
|
||||
*/
|
||||
uint8_t getLen(void) const {
|
||||
return ((type == UUID_TYPE_SHORT) ? sizeof(ShortUUIDBytes_t) : LENGTH_OF_LONG_UUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload == operator to enable UUID comparisons.
|
||||
*
|
||||
* @param[in] other
|
||||
* The other UUID in the comparison.
|
||||
*
|
||||
* @return true if this == @p other, false otherwise.
|
||||
*/
|
||||
bool operator== (const UUID &other) const {
|
||||
if ((this->type == UUID_TYPE_SHORT) && (other.type == UUID_TYPE_SHORT) &&
|
||||
(this->shortUUID == other.shortUUID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((this->type == UUID_TYPE_LONG) && (other.type == UUID_TYPE_LONG) &&
|
||||
(memcmp(this->baseUUID, other.baseUUID, LENGTH_OF_LONG_UUID) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload != operator to enable UUID comparisons.
|
||||
*
|
||||
* @param[in] other
|
||||
* The other UUID in the comparison.
|
||||
*
|
||||
* @return true if this != @p other, false otherwise.
|
||||
*/
|
||||
bool operator!= (const UUID &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The UUID type. Refer to UUID_Type_t.
|
||||
*/
|
||||
UUID_Type_t type;
|
||||
/**
|
||||
* The long UUID value.
|
||||
*/
|
||||
LongUUIDBytes_t baseUUID;
|
||||
/**
|
||||
* The short UUID value.
|
||||
*/
|
||||
ShortUUIDBytes_t shortUUID;
|
||||
};
|
||||
|
||||
#endif // ifndef __UUID_H__
|
|
@ -0,0 +1,81 @@
|
|||
/* 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 __BLE_COMMON_H__
|
||||
#define __BLE_COMMON_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*! @brief Assigned values for BLE UUIDs. */
|
||||
enum {
|
||||
BLE_UUID_UNKNOWN = 0x0000, /**< Reserved UUID. */
|
||||
BLE_UUID_SERVICE_PRIMARY = 0x2800, /**< Primary Service. */
|
||||
BLE_UUID_SERVICE_SECONDARY = 0x2801, /**< Secondary Service. */
|
||||
BLE_UUID_SERVICE_INCLUDE = 0x2802, /**< Include. */
|
||||
BLE_UUID_CHARACTERISTIC = 0x2803, /**< Characteristic. */
|
||||
BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP = 0x2900, /**< Characteristic Extended Properties Descriptor. */
|
||||
BLE_UUID_DESCRIPTOR_CHAR_USER_DESC = 0x2901, /**< Characteristic User Description Descriptor. */
|
||||
BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG = 0x2902, /**< Client Characteristic Configuration Descriptor. */
|
||||
BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG = 0x2903, /**< Server Characteristic Configuration Descriptor. */
|
||||
BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT = 0x2904, /**< Characteristic Presentation Format Descriptor. */
|
||||
BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT = 0x2905, /**< Characteristic Aggregate Format Descriptor. */
|
||||
|
||||
/* GATT specific UUIDs */
|
||||
BLE_UUID_GATT = 0x1801, /**< Generic Attribute Profile. */
|
||||
BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED = 0x2A05, /**< Service Changed Characteristic. */
|
||||
|
||||
/* GAP specific UUIDs */
|
||||
BLE_UUID_GAP = 0x1800, /**< Generic Access Profile. */
|
||||
BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME = 0x2A00, /**< Device Name Characteristic. */
|
||||
BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE = 0x2A01, /**< Appearance Characteristic. */
|
||||
BLE_UUID_GAP_CHARACTERISTIC_PPF = 0x2A02, /**< Peripheral Privacy Flag Characteristic. */
|
||||
BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR = 0x2A03, /**< Reconnection Address Characteristic. */
|
||||
BLE_UUID_GAP_CHARACTERISTIC_PPCP = 0x2A04, /**< Peripheral Preferred Connection Parameters Characteristic. */
|
||||
};
|
||||
|
||||
/*! @brief Error codes for the BLE API. */
|
||||
enum ble_error_t {
|
||||
BLE_ERROR_NONE = 0, /**< No error. */
|
||||
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted. */
|
||||
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implemented or isn't supported by the target HW. */
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range. */
|
||||
BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid. */
|
||||
BLE_STACK_BUSY = 5, /**< The stack is busy. */
|
||||
BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */
|
||||
BLE_ERROR_NO_MEM = 7, /**< Out of memory */
|
||||
BLE_ERROR_OPERATION_NOT_PERMITTED = 8,
|
||||
BLE_ERROR_INITIALIZATION_INCOMPLETE = 9,
|
||||
BLE_ERROR_ALREADY_INITIALIZED = 10,
|
||||
BLE_ERROR_UNSPECIFIED = 11, /**< Unknown error. */
|
||||
BLE_ERROR_INTERNAL_STACK_FAILURE = 12, /**< The platform-specific stack failed */
|
||||
};
|
||||
|
||||
/** @brief Default MTU size. */
|
||||
static const unsigned BLE_GATT_MTU_SIZE_DEFAULT = 23;
|
||||
|
||||
enum HVXType_t {
|
||||
BLE_HVX_NOTIFICATION = 0x01, /**< Handle Value Notification. */
|
||||
BLE_HVX_INDICATION = 0x02, /**< Handle Value Indication. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifndef __BLE_COMMON_H__
|
|
@ -0,0 +1,26 @@
|
|||
/* 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 __DEPRECATE_H__
|
||||
#define __DEPRECATE_H__
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "compiler-polyfill/attributes.h"
|
||||
#else
|
||||
#define __deprecated_message(msg)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
/* 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 __BLE_BATTERY_SERVICE_H__
|
||||
#define __BLE_BATTERY_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class BatteryService
|
||||
* @brief BLE Battery Service. This service displays the battery level from 0% to 100%, represented as an 8bit number.
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.battery_service.xml
|
||||
* Battery Level Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.battery_level.xml
|
||||
*/
|
||||
class BatteryService {
|
||||
public:
|
||||
/**
|
||||
* @param[in] _ble
|
||||
* BLE object for the underlying controller.
|
||||
* @param[in] level
|
||||
* 8bit batterly level. Usually used to represent percentage of batterly charge remaining.
|
||||
*/
|
||||
BatteryService(BLE &_ble, uint8_t level = 100) :
|
||||
ble(_ble),
|
||||
batteryLevel(level),
|
||||
batteryLevelCharacteristic(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, &batteryLevel, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
|
||||
|
||||
GattCharacteristic *charTable[] = {&batteryLevelCharacteristic};
|
||||
GattService batteryService(GattService::UUID_BATTERY_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(batteryService);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the battery level with a new value. Valid values lie between 0 and 100,
|
||||
* anything outside this range will be ignored.
|
||||
*
|
||||
* @param newLevel
|
||||
* Update to battery level.
|
||||
*/
|
||||
void updateBatteryLevel(uint8_t newLevel) {
|
||||
batteryLevel = newLevel;
|
||||
ble.gattServer().write(batteryLevelCharacteristic.getValueHandle(), &batteryLevel, 1);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A reference to the underlying BLE instance that this object is attached to.
|
||||
* The services and characteristics will be registered in this BLE instance.
|
||||
*/
|
||||
BLE &ble;
|
||||
|
||||
/**
|
||||
* The current battery level represented as an integer from 0% to 100%.
|
||||
*/
|
||||
uint8_t batteryLevel;
|
||||
/**
|
||||
* A ReadOnlyGattCharacteristic that allows access to the peer device to the
|
||||
* batteryLevel value through BLE.
|
||||
*/
|
||||
ReadOnlyGattCharacteristic<uint8_t> batteryLevelCharacteristic;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_BATTERY_SERVICE_H__*/
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#ifdef TARGET_NRF51822 /* DFU only supported on nrf51 platforms */
|
||||
|
||||
#ifndef __BLE_DFU_SERVICE_H__
|
||||
#define __BLE_DFU_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/UUID.h"
|
||||
|
||||
extern "C" {
|
||||
#include "dfu_app_handler.h"
|
||||
}
|
||||
|
||||
extern const uint8_t DFUServiceBaseUUID[];
|
||||
extern const uint16_t DFUServiceShortUUID;
|
||||
extern const uint16_t DFUServiceControlCharacteristicShortUUID;
|
||||
|
||||
extern const uint8_t DFUServiceUUID[];
|
||||
extern const uint8_t DFUServiceControlCharacteristicUUID[];
|
||||
extern const uint8_t DFUServicePacketCharacteristicUUID[];
|
||||
|
||||
/**
|
||||
* @class DFUService
|
||||
* @brief Device Firmware Update Service.
|
||||
*/
|
||||
class DFUService {
|
||||
public:
|
||||
/**
|
||||
* @brief Signature for the handover callback. The application may provide this
|
||||
* callback when setting up the DFU service. The callback is then
|
||||
* invoked before handing control over to the bootloader.
|
||||
*/
|
||||
typedef void (*ResetPrepare_t)(void);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Adds Device Firmware Update Service to an existing BLE object.
|
||||
*
|
||||
* @param[ref] _ble
|
||||
* BLE object for the underlying controller.
|
||||
* @param[in] _handoverCallback
|
||||
* Application-specific handover callback.
|
||||
*/
|
||||
DFUService(BLE &_ble, ResetPrepare_t _handoverCallback = NULL) :
|
||||
ble(_ble),
|
||||
controlPoint(DFUServiceControlCharacteristicUUID, controlBytes, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
|
||||
packet(DFUServicePacketCharacteristicUUID, packetBytes, SIZEOF_PACKET_BYTES, SIZEOF_PACKET_BYTES,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
|
||||
controlBytes(),
|
||||
packetBytes() {
|
||||
static bool serviceAdded = false; /* We only add the DFU service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set an initial value for control bytes, so that the application's DFU service can
|
||||
* be distinguished from the real DFU service provided by the bootloader. */
|
||||
controlBytes[0] = 0xFF;
|
||||
controlBytes[1] = 0xFF;
|
||||
|
||||
GattCharacteristic *dfuChars[] = {&controlPoint, &packet};
|
||||
GattService dfuService(DFUServiceUUID, dfuChars, sizeof(dfuChars) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(dfuService);
|
||||
handoverCallback = _handoverCallback;
|
||||
serviceAdded = true;
|
||||
|
||||
ble.onDataWritten(this, &DFUService::onDataWritten);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the handle for the value attribute of the control characteristic.
|
||||
*/
|
||||
uint16_t getControlHandle(void) const {
|
||||
return controlPoint.getValueHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This callback allows the DFU service to receive the initial trigger to
|
||||
* hand control over to the bootloader. First, the application is given a
|
||||
* chance to clean up.
|
||||
*
|
||||
* @param[in] params
|
||||
* Information about the characterisitc being updated.
|
||||
*/
|
||||
virtual void onDataWritten(const GattWriteCallbackParams *params) {
|
||||
if (params->handle == controlPoint.getValueHandle()) {
|
||||
/* At present, writing anything will do the trick - this needs to be improved. */
|
||||
if (handoverCallback) {
|
||||
handoverCallback();
|
||||
}
|
||||
|
||||
// Call bootloader_start implicitly trough a event handler call
|
||||
// it is a work around for bootloader_start not being public in sdk 8.1
|
||||
ble_dfu_t p_dfu;
|
||||
ble_dfu_evt_t p_evt;
|
||||
|
||||
p_dfu.conn_handle = params->connHandle;
|
||||
p_evt.ble_dfu_evt_type = BLE_DFU_START;
|
||||
|
||||
dfu_app_on_dfu_evt(&p_dfu, &p_evt);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
static const unsigned SIZEOF_CONTROL_BYTES = 2;
|
||||
static const unsigned SIZEOF_PACKET_BYTES = 20;
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
|
||||
/**< Writing to the control characteristic triggers the handover to DFU
|
||||
* bootloader. At present, writing anything will do the trick - this needs
|
||||
* to be improved. */
|
||||
WriteOnlyArrayGattCharacteristic<uint8_t, SIZEOF_CONTROL_BYTES> controlPoint;
|
||||
|
||||
/**< The packet characteristic in this service doesn't do anything meaningful;
|
||||
* it is only a placeholder to mimic the corresponding characteristic in the
|
||||
* actual DFU service implemented by the bootloader. Without this, some
|
||||
* FOTA clients might get confused, because service definitions change after
|
||||
* handing control over to the bootloader. */
|
||||
GattCharacteristic packet;
|
||||
|
||||
uint8_t controlBytes[SIZEOF_CONTROL_BYTES];
|
||||
uint8_t packetBytes[SIZEOF_PACKET_BYTES];
|
||||
|
||||
static ResetPrepare_t handoverCallback; /**< Application-specific handover callback. */
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_DFU_SERVICE_H__*/
|
||||
#endif /* #ifdef TARGET_NRF51822 */
|
|
@ -0,0 +1,138 @@
|
|||
/* 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 __BLE_DEVICE_INFORMATION_SERVICE_H__
|
||||
#define __BLE_DEVICE_INFORMATION_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class DeviceInformationService
|
||||
* @brief BLE Device Information Service
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml
|
||||
* Manufacturer Name String Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.manufacturer_name_string.xml
|
||||
*/
|
||||
class DeviceInformationService {
|
||||
public:
|
||||
/**
|
||||
* @brief Device Information Service Constructor: copies device-specific information
|
||||
* into the BLE stack.
|
||||
*
|
||||
* @param[in] _ble
|
||||
* A reference to a BLE object for the underlying controller.
|
||||
* @param[in] manufacturersName
|
||||
* The name of the manufacturer of the device.
|
||||
* @param[in] modelNumber
|
||||
* The model number that is assigned by the device vendor.
|
||||
* @param[in] serialNumber
|
||||
* The serial number for a particular instance of the device.
|
||||
* @param[in] hardwareRevision
|
||||
* The hardware revision for the hardware within the device.
|
||||
* @param[in] firmwareRevision
|
||||
* The device's firmware version.
|
||||
* @param[in] softwareRevision
|
||||
* The device's software version.
|
||||
*/
|
||||
DeviceInformationService(BLE &_ble,
|
||||
const char *manufacturersName = NULL,
|
||||
const char *modelNumber = NULL,
|
||||
const char *serialNumber = NULL,
|
||||
const char *hardwareRevision = NULL,
|
||||
const char *firmwareRevision = NULL,
|
||||
const char *softwareRevision = NULL) :
|
||||
ble(_ble),
|
||||
manufacturersNameStringCharacteristic(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR,
|
||||
(uint8_t *)manufacturersName,
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* Min length */
|
||||
(manufacturersName != NULL) ? strlen(manufacturersName) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
modelNumberStringCharacteristic(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR,
|
||||
(uint8_t *)modelNumber,
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* Min length */
|
||||
(modelNumber != NULL) ? strlen(modelNumber) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
serialNumberStringCharacteristic(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR,
|
||||
(uint8_t *)serialNumber,
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* Min length */
|
||||
(serialNumber != NULL) ? strlen(serialNumber) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
hardwareRevisionStringCharacteristic(GattCharacteristic::UUID_HARDWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)hardwareRevision,
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* Min length */
|
||||
(hardwareRevision != NULL) ? strlen(hardwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
firmwareRevisionStringCharacteristic(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)firmwareRevision,
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* Min length */
|
||||
(firmwareRevision != NULL) ? strlen(firmwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ),
|
||||
softwareRevisionStringCharacteristic(GattCharacteristic::UUID_SOFTWARE_REVISION_STRING_CHAR,
|
||||
(uint8_t *)softwareRevision,
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* Min length */
|
||||
(softwareRevision != NULL) ? strlen(softwareRevision) : 0, /* Max length */
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)
|
||||
{
|
||||
static bool serviceAdded = false; /* We only add the information service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
GattCharacteristic *charTable[] = {&manufacturersNameStringCharacteristic,
|
||||
&modelNumberStringCharacteristic,
|
||||
&serialNumberStringCharacteristic,
|
||||
&hardwareRevisionStringCharacteristic,
|
||||
&firmwareRevisionStringCharacteristic,
|
||||
&softwareRevisionStringCharacteristic};
|
||||
GattService deviceInformationService(GattService::UUID_DEVICE_INFORMATION_SERVICE, charTable,
|
||||
sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(deviceInformationService);
|
||||
serviceAdded = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A reference to the BLE instance object to which the services and
|
||||
* characteristics will be added.
|
||||
*/
|
||||
BLE &ble;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the manufacturer's name.
|
||||
*/
|
||||
GattCharacteristic manufacturersNameStringCharacteristic;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the model number.
|
||||
*/
|
||||
GattCharacteristic modelNumberStringCharacteristic;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the serial number.
|
||||
*/
|
||||
GattCharacteristic serialNumberStringCharacteristic;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the hardware revision string.
|
||||
*/
|
||||
GattCharacteristic hardwareRevisionStringCharacteristic;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the firmware revision string.
|
||||
*/
|
||||
GattCharacteristic firmwareRevisionStringCharacteristic;
|
||||
/**
|
||||
* BLE characterising to allow BLE peers access to the software revision string.
|
||||
*/
|
||||
GattCharacteristic softwareRevisionStringCharacteristic;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_DEVICE_INFORMATION_SERVICE_H__*/
|
|
@ -0,0 +1,542 @@
|
|||
/* 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 SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
|
||||
#define SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
|
||||
|
||||
#warning ble/services/EddystoneConfigService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.
|
||||
|
||||
#include "mbed.h"
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/services/EddystoneService.h"
|
||||
|
||||
#define UUID_URI_BEACON(FIRST, SECOND) { \
|
||||
0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba, \
|
||||
0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8, \
|
||||
}
|
||||
|
||||
static const uint8_t UUID_URI_BEACON_SERVICE[] = UUID_URI_BEACON(0x20, 0x80);
|
||||
static const uint8_t UUID_LOCK_STATE_CHAR[] = UUID_URI_BEACON(0x20, 0x81);
|
||||
static const uint8_t UUID_LOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x82);
|
||||
static const uint8_t UUID_UNLOCK_CHAR[] = UUID_URI_BEACON(0x20, 0x83);
|
||||
static const uint8_t UUID_URI_DATA_CHAR[] = UUID_URI_BEACON(0x20, 0x84);
|
||||
static const uint8_t UUID_FLAGS_CHAR[] = UUID_URI_BEACON(0x20, 0x85);
|
||||
static const uint8_t UUID_ADV_POWER_LEVELS_CHAR[] = UUID_URI_BEACON(0x20, 0x86);
|
||||
static const uint8_t UUID_TX_POWER_MODE_CHAR[] = UUID_URI_BEACON(0x20, 0x87);
|
||||
static const uint8_t UUID_BEACON_PERIOD_CHAR[] = UUID_URI_BEACON(0x20, 0x88);
|
||||
static const uint8_t UUID_RESET_CHAR[] = UUID_URI_BEACON(0x20, 0x89);
|
||||
extern const uint8_t BEACON_EDDYSTONE[2];
|
||||
|
||||
/**
|
||||
* @class EddystoneConfigService
|
||||
* @brief Eddystone Configuration Service. Used to set URL, adjust power levels, and set flags.
|
||||
* See https://github.com/google/eddystone
|
||||
*
|
||||
*/
|
||||
class EddystoneConfigService
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Transmission Power Modes for UriBeacon
|
||||
*/
|
||||
enum {
|
||||
TX_POWER_MODE_LOWEST,
|
||||
TX_POWER_MODE_LOW,
|
||||
TX_POWER_MODE_MEDIUM,
|
||||
TX_POWER_MODE_HIGH,
|
||||
NUM_POWER_MODES
|
||||
};
|
||||
|
||||
static const unsigned ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service.
|
||||
static const unsigned SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets.
|
||||
|
||||
typedef uint8_t Lock_t[16]; /* 128 bits. */
|
||||
typedef int8_t PowerLevels_t[NUM_POWER_MODES];
|
||||
|
||||
// There are currently three subframes defined: URI, UID, and TLM.
|
||||
#define EDDYSTONE_MAX_FRAMETYPE 3
|
||||
static const unsigned URI_DATA_MAX = 18;
|
||||
typedef uint8_t UriData_t[URI_DATA_MAX];
|
||||
|
||||
// UID Frame Type subfields.
|
||||
static const size_t UID_NAMESPACEID_SIZE = 10;
|
||||
typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
|
||||
static const size_t UID_INSTANCEID_SIZE = 6;
|
||||
typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
|
||||
|
||||
// Eddystone Frame Type ID.
|
||||
static const uint8_t FRAME_TYPE_UID = 0x00;
|
||||
static const uint8_t FRAME_TYPE_URL = 0x10;
|
||||
static const uint8_t FRAME_TYPE_TLM = 0x20;
|
||||
|
||||
static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14B.
|
||||
static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes.
|
||||
|
||||
struct Params_t {
|
||||
// Config Data
|
||||
bool isConfigured; // Flag for configuration being complete:
|
||||
// True = configured, False = not configured. Reset at instantiation, used for external callbacks.
|
||||
uint8_t lockedState;
|
||||
Lock_t lock;
|
||||
uint8_t flags;
|
||||
PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels.
|
||||
uint8_t txPowerMode; // Firmware power levels used with setTxPower().
|
||||
uint16_t beaconPeriod;
|
||||
// TLM Frame Data
|
||||
uint8_t tlmVersion; // Version of TLM packet.
|
||||
bool tlmEnabled;
|
||||
float tlmBeaconPeriod; // How often to broadcat TLM frame, in seconds.
|
||||
// URI Frame Data
|
||||
uint8_t uriDataLength;
|
||||
UriData_t uriData;
|
||||
bool uriEnabled;
|
||||
float uriBeaconPeriod; // How often to broadcast URIFrame, in seconds.
|
||||
// UID Frame Data
|
||||
UIDNamespaceID_t uidNamespaceID; // UUID type, Namespace ID, 10B.
|
||||
UIDInstanceID_t uidInstanceID; // UUID type, Instance ID, 6B.
|
||||
bool uidEnabled;
|
||||
float uidBeaconPeriod; // How often to broadcast UID Frame, in seconds.
|
||||
};
|
||||
|
||||
/**
|
||||
* @param[ref] ble
|
||||
* BLEDevice object for the underlying controller.
|
||||
* @param[in/out] paramsIn
|
||||
* Reference to application-visible beacon state, loaded
|
||||
* from persistent storage at startup.
|
||||
* @param[in] defaultAdvPowerLevelsIn
|
||||
* Default power-levels array; applies only if resetToDefaultsFlag is true.
|
||||
*/
|
||||
EddystoneConfigService(BLEDevice &bleIn,
|
||||
Params_t ¶msIn,
|
||||
PowerLevels_t &defaultAdvPowerLevelsIn,
|
||||
PowerLevels_t &radioPowerLevelsIn) :
|
||||
ble(bleIn),
|
||||
params(paramsIn), // Initialize URL data.
|
||||
defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
|
||||
radioPowerLevels(radioPowerLevelsIn),
|
||||
initSucceeded(false),
|
||||
resetFlag(),
|
||||
defaultUidNamespaceID(), // Initialize UID data.
|
||||
defaultUidInstanceID(),
|
||||
defaultUidPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
|
||||
uidIsSet(false),
|
||||
defaultUriDataLength(),
|
||||
defaultUriData(),
|
||||
defaultUrlPower(defaultAdvPowerLevelsIn[params.txPowerMode]),
|
||||
urlIsSet(false),
|
||||
tlmIsSet(false),
|
||||
lockedStateChar(UUID_LOCK_STATE_CHAR, ¶ms.lockedState),
|
||||
lockChar(UUID_LOCK_CHAR, ¶ms.lock),
|
||||
uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
|
||||
unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock),
|
||||
flagsChar(UUID_FLAGS_CHAR, ¶ms.flags),
|
||||
advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels),
|
||||
txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode),
|
||||
beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod),
|
||||
resetChar(UUID_RESET_CHAR, &resetFlag) {
|
||||
// Set Eddystone as not configured yet. Used to exit config before timeout if GATT services are written to.
|
||||
params.isConfigured = false;
|
||||
|
||||
lockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::lockAuthorizationCallback);
|
||||
unlockChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::unlockAuthorizationCallback);
|
||||
uriDataChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::uriDataWriteAuthorizationCallback);
|
||||
flagsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
|
||||
advPowerLevelsChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<PowerLevels_t>);
|
||||
txPowerModeChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::powerModeAuthorizationCallback);
|
||||
beaconPeriodChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint16_t>);
|
||||
resetChar.setWriteAuthorizationCallback(this, &EddystoneConfigService::basicAuthorizationCallback<uint8_t>);
|
||||
|
||||
static GattCharacteristic *charTable[] = {
|
||||
&lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
|
||||
&flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
|
||||
};
|
||||
|
||||
GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(configService);
|
||||
ble.onDataWritten(this, &EddystoneConfigService::onDataWrittenCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start EddystoneConfig advertising. This function should be called
|
||||
* after the EddystoneConfig constructor and after all the frames have been added.
|
||||
*
|
||||
* @paramsP[in] resetToDefaultsFlag
|
||||
* Applies to the state of the 'paramsIn' parameter.
|
||||
* If true, it indicates that paramsIn is potentially
|
||||
* un-initialized, and default values should be used
|
||||
* instead. Otherwise, paramsIn overrides the defaults.
|
||||
*/
|
||||
void start(bool resetToDefaultsFlag){
|
||||
INFO("reset to defaults flag = %d", resetToDefaultsFlag);
|
||||
if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
|
||||
INFO("Reset to Defaults triggered");
|
||||
resetToDefaultsFlag = true;
|
||||
}
|
||||
|
||||
if (resetToDefaultsFlag) {
|
||||
resetToDefaults();
|
||||
} else {
|
||||
updateCharacteristicValues();
|
||||
}
|
||||
|
||||
setupEddystoneConfigAdvertisements(); /* Set up advertising for the config service. */
|
||||
initSucceeded = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if Eddystone initialized successfully.
|
||||
*/
|
||||
bool initSuccessfully(void) const {
|
||||
return initSucceeded;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Function to update the default values for the TLM frame. Only applied if Reset Defaults is applied.
|
||||
*
|
||||
* @param[in] tlmVersionIn Version of the TLM frame being used.
|
||||
* @param[in] advPeriodInMin How long between TLM frames being advertised, measured in minutes.
|
||||
*
|
||||
*/
|
||||
void setDefaultTLMFrameData(uint8_t tlmVersionIn = 0, float advPeriodInSec = 60){
|
||||
DBG("Setting Default TLM Data, version = %d, advPeriodInMind= %f", tlmVersionIn, advPeriodInSec);
|
||||
defaultTlmVersion = tlmVersionIn;
|
||||
TlmBatteryVoltage = 0;
|
||||
TlmBeaconTemp = 0x8000;
|
||||
TlmPduCount = 0;
|
||||
TlmTimeSinceBoot = 0;
|
||||
defaultTlmAdvPeriod = advPeriodInSec;
|
||||
tlmIsSet = true; // Flag to add this to Eddystone service when config is done.
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Function to update the default values for the URI frame. Only applied if Reset Defaults is applied.
|
||||
*
|
||||
* @param[in] uriIn URL to advertise.
|
||||
* @param[in] advPeriod How long to advertise the URL, measured in number of ADV frames.
|
||||
*
|
||||
*/
|
||||
void setDefaultURIFrameData(const char *uriIn, float advPeriod = 1){
|
||||
DBG("Setting Default URI Data");
|
||||
// Set URL Frame
|
||||
EddystoneService::encodeURL(uriIn, defaultUriData, defaultUriDataLength); // Encode URL to URL Formatting.
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return;
|
||||
}
|
||||
INFO("\t URI input = %s : %d", uriIn, defaultUriDataLength);
|
||||
INFO("\t default URI = %s : %d ", defaultUriData, defaultUriDataLength );
|
||||
defaultUriAdvPeriod = advPeriod;
|
||||
urlIsSet = true; // Flag to add this to Eddystone service when config is done.
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Function to update the default values for the UID frame. Only applied if Reset Defaults is applied.
|
||||
*
|
||||
* @param[in] namespaceID 10Byte Namespace ID.
|
||||
* @param[in] instanceID 6Byte Instance ID.
|
||||
* @param[in] advPeriod How long to advertise the URL, measured in the number of ADV frames.
|
||||
*
|
||||
*/
|
||||
void setDefaultUIDFrameData(UIDNamespaceID_t *namespaceID, UIDInstanceID_t *instanceID, float advPeriod = 10){
|
||||
//Set UID frame
|
||||
DBG("Setting default UID Data");
|
||||
memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
|
||||
memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
|
||||
defaultUidAdvPeriod = advPeriod;
|
||||
uidIsSet = true; // Flag to add this to Eddystone service when config is done.
|
||||
}
|
||||
|
||||
/* Start out by advertising the config service for a limited time after
|
||||
* startup, then switch to the normal non-connectible beacon functionality.
|
||||
*/
|
||||
void setupEddystoneConfigAdvertisements() {
|
||||
const char DEVICE_NAME[] = "eddystone Config";
|
||||
|
||||
ble.clearAdvertisingPayload();
|
||||
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
|
||||
|
||||
// UUID is in a different order in the ADV frame (!)
|
||||
uint8_t reversedServiceUUID[sizeof(UUID_URI_BEACON_SERVICE)];
|
||||
for (unsigned int i = 0; i < sizeof(UUID_URI_BEACON_SERVICE); i++) {
|
||||
reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
|
||||
}
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
|
||||
ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
|
||||
ble.accumulateScanResponse(
|
||||
GapAdvertisingData::TX_POWER_LEVEL,
|
||||
reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[EddystoneConfigService::TX_POWER_MODE_LOW]),
|
||||
sizeof(uint8_t));
|
||||
|
||||
ble.setTxPower(radioPowerLevels[params.txPowerMode]);
|
||||
ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
|
||||
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
|
||||
ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function actually impliments the Eddystone Beacon service. It can be called with the help of the wrapper function
|
||||
* to load saved config params, or it can be called explicitly to reset the Eddystone beacon to hardcoded values on each reset.
|
||||
*
|
||||
*/
|
||||
void setupEddystoneAdvertisements() {
|
||||
DBG("Switching Config -> adv");
|
||||
// Save params to storage.
|
||||
extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* forward declaration; necessary to avoid a circular dependency. */
|
||||
saveURIBeaconConfigParams(¶ms);
|
||||
INFO("Saved Params to Memory.")
|
||||
// Set up Eddystone Service.
|
||||
static EddystoneService eddyServ(ble, params.beaconPeriod, radioPowerLevels[params.txPowerMode]);
|
||||
// Set configured frames (TLM, UID, URI and so on).
|
||||
if (params.tlmEnabled) {
|
||||
eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
|
||||
}
|
||||
if (params.uriEnabled) {
|
||||
eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
|
||||
}
|
||||
if (params.uidEnabled) {
|
||||
eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode],
|
||||
(uint8_t *)params.uidNamespaceID,
|
||||
(uint8_t *)params.uidInstanceID,
|
||||
params.uidBeaconPeriod);
|
||||
}
|
||||
// Start advertising the Eddystone service.
|
||||
eddyServ.start();
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* This callback is invoked when a GATT client attempts to modify any of the
|
||||
* characteristics of this service. Attempts to do so are also applied to
|
||||
* the internal state of this service object.
|
||||
*/
|
||||
void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
|
||||
uint16_t handle = writeParams->handle;
|
||||
|
||||
if (handle == lockChar.getValueHandle()) {
|
||||
// Validated earlier.
|
||||
memcpy(params.lock, writeParams->data, sizeof(Lock_t));
|
||||
// Set the state to be locked by the lock code (note: zeros are a valid lock).
|
||||
params.lockedState = true;
|
||||
INFO("Device Locked");
|
||||
} else if (handle == unlockChar.getValueHandle()) {
|
||||
// Validated earlier.
|
||||
params.lockedState = false;
|
||||
INFO("Device Unlocked");
|
||||
} else if (handle == uriDataChar.getValueHandle()) {
|
||||
params.uriDataLength = writeParams->len;
|
||||
memset(params.uriData, 0x00, URI_DATA_MAX); // Clear URI string.
|
||||
memcpy(params.uriData, writeParams->data, writeParams->len); // Set URI string.
|
||||
params.uriEnabled = true;
|
||||
INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
|
||||
} else if (handle == flagsChar.getValueHandle()) {
|
||||
params.flags = *(writeParams->data);
|
||||
INFO("flagsChar = 0x%x", params.flags);
|
||||
} else if (handle == advPowerLevelsChar.getValueHandle()) {
|
||||
memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
|
||||
INFO("PowerLevelsChar = %4x", params.advPowerLevels);
|
||||
} else if (handle == txPowerModeChar.getValueHandle()) {
|
||||
params.txPowerMode = *(writeParams->data);
|
||||
INFO("TxPowerModeChar = %d", params.txPowerMode);
|
||||
} else if (handle == beaconPeriodChar.getValueHandle()) {
|
||||
params.beaconPeriod = *((uint16_t *)(writeParams->data));
|
||||
INFO("BeaconPeriod = %d", params.beaconPeriod);
|
||||
|
||||
/* Re-map beaconPeriod to within permissible bounds if necessary. */
|
||||
if (params.beaconPeriod != 0) {
|
||||
bool paramsUpdated = false;
|
||||
if (params.beaconPeriod < ble.getMinAdvertisingInterval()) {
|
||||
params.beaconPeriod = ble.getMinAdvertisingInterval();
|
||||
paramsUpdated = true;
|
||||
} else if (params.beaconPeriod > ble.getMaxAdvertisingInterval()) {
|
||||
params.beaconPeriod = ble.getMaxAdvertisingInterval();
|
||||
paramsUpdated = true;
|
||||
}
|
||||
if (paramsUpdated) {
|
||||
ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
} else if (handle == resetChar.getValueHandle()) {
|
||||
INFO("Reset triggered from Config Service, resetting to defaults");
|
||||
resetToDefaults();
|
||||
}
|
||||
updateCharacteristicValues();
|
||||
params.isConfigured = true; // Some configuration data has been passed; on disconnect switch to advertising mode.
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the default values.
|
||||
*/
|
||||
void resetToDefaults(void) {
|
||||
INFO("Resetting to defaults");
|
||||
// General.
|
||||
params.lockedState = false;
|
||||
memset(params.lock, 0, sizeof(Lock_t));
|
||||
params.flags = 0x10;
|
||||
memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
|
||||
params.txPowerMode = TX_POWER_MODE_LOW;
|
||||
params.beaconPeriod = (uint16_t) defaultUriAdvPeriod * 1000;
|
||||
|
||||
// TLM Frame.
|
||||
params.tlmVersion = defaultTlmVersion;
|
||||
params.tlmBeaconPeriod = defaultTlmAdvPeriod;
|
||||
params.tlmEnabled = tlmIsSet;
|
||||
|
||||
// URL Frame.
|
||||
memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
|
||||
params.uriDataLength = defaultUriDataLength;
|
||||
params.uriBeaconPeriod = defaultUriAdvPeriod;
|
||||
params.uriEnabled = urlIsSet;
|
||||
|
||||
// UID Frame.
|
||||
memcpy(params.uidNamespaceID, defaultUidNamespaceID, UID_NAMESPACEID_SIZE);
|
||||
memcpy(params.uidInstanceID, defaultUidInstanceID, UID_INSTANCEID_SIZE);
|
||||
params.uidBeaconPeriod = defaultUidAdvPeriod;
|
||||
params.uidEnabled = uidIsSet;
|
||||
|
||||
updateCharacteristicValues();
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal helper function used to update the GATT database following any
|
||||
* change to the internal state of the service object.
|
||||
*/
|
||||
void updateCharacteristicValues(void) {
|
||||
ble.updateCharacteristicValue(lockedStateChar.getValueHandle(), ¶ms.lockedState, 1);
|
||||
ble.updateCharacteristicValue(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
|
||||
ble.updateCharacteristicValue(flagsChar.getValueHandle(), ¶ms.flags, 1);
|
||||
ble.updateCharacteristicValue(beaconPeriodChar.getValueHandle(),
|
||||
reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t));
|
||||
ble.updateCharacteristicValue(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1);
|
||||
ble.updateCharacteristicValue(advPowerLevelsChar.getValueHandle(),
|
||||
reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
|
||||
}
|
||||
|
||||
private:
|
||||
void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (params.lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(Lock_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if ((!params.lockedState) && (authParams->len == sizeof(Lock_t))) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
} else if (authParams->len != sizeof(Lock_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (params.lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (params.lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(uint8_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (params.lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(T)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
BLEDevice &ble;
|
||||
Params_t ¶ms;
|
||||
Ticker timeSinceBootTick;
|
||||
Timeout switchFrame;
|
||||
// Default value that is restored on reset.
|
||||
PowerLevels_t &defaultAdvPowerLevels; // This goes into the advertising frames (radio power measured at 1m from device).
|
||||
PowerLevels_t &radioPowerLevels; // This configures the power levels of the radio.
|
||||
uint8_t lockedState;
|
||||
bool initSucceeded;
|
||||
uint8_t resetFlag;
|
||||
bool switchFlag;
|
||||
|
||||
//UID default value that is restored on reset.
|
||||
UIDNamespaceID_t defaultUidNamespaceID;
|
||||
UIDInstanceID_t defaultUidInstanceID;
|
||||
float defaultUidAdvPeriod;
|
||||
int8_t defaultUidPower;
|
||||
uint16_t uidRFU;
|
||||
bool uidIsSet;
|
||||
|
||||
//URI default value that is restored on reset.
|
||||
uint8_t defaultUriDataLength;
|
||||
UriData_t defaultUriData;
|
||||
int8_t defaultUrlPower;
|
||||
float defaultUriAdvPeriod;
|
||||
bool urlIsSet;
|
||||
|
||||
//TLM default value that is restored on reset.
|
||||
uint8_t defaultTlmVersion;
|
||||
float defaultTlmAdvPeriod;
|
||||
volatile uint16_t TlmBatteryVoltage;
|
||||
volatile uint16_t TlmBeaconTemp;
|
||||
volatile uint32_t TlmPduCount;
|
||||
volatile uint32_t TlmTimeSinceBoot;
|
||||
bool tlmIsSet;
|
||||
|
||||
ReadOnlyGattCharacteristic<uint8_t> lockedStateChar;
|
||||
WriteOnlyGattCharacteristic<Lock_t> lockChar;
|
||||
GattCharacteristic uriDataChar;
|
||||
WriteOnlyGattCharacteristic<Lock_t> unlockChar;
|
||||
ReadWriteGattCharacteristic<uint8_t> flagsChar;
|
||||
ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
|
||||
ReadWriteGattCharacteristic<uint8_t> txPowerModeChar;
|
||||
ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
|
||||
WriteOnlyGattCharacteristic<uint8_t> resetChar;
|
||||
};
|
||||
|
||||
#endif // SERVICES_EDDYSTONE_BEACON_CONFIG_SERVICE_H_
|
|
@ -0,0 +1,653 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_EDDYSTONEBEACON_H_
|
||||
#define SERVICES_EDDYSTONEBEACON_H_
|
||||
|
||||
#warning ble/services/EddystoneService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "mbed.h"
|
||||
#include "CircularBuffer.h"
|
||||
static const uint8_t BEACON_EDDYSTONE[] = {0xAA, 0xFE};
|
||||
|
||||
//Debug is disabled by default
|
||||
#if 0
|
||||
#define DBG(MSG, ...) printf("[EddyStone: DBG]" MSG " \t[%s,%d]\r\n", \
|
||||
## __VA_ARGS__, \
|
||||
__FILE__, \
|
||||
__LINE__);
|
||||
#define WARN(MSG, ...) printf("[EddyStone: WARN]" MSG " \t[%s,%d]\r\n", \
|
||||
## __VA_ARGS__, \
|
||||
__FILE__, \
|
||||
__LINE__);
|
||||
#define ERR(MSG, ...) printf("[EddyStone: ERR]" MSG " \t[%s,%d]\r\n", \
|
||||
## __VA_ARGS__, \
|
||||
__FILE__, \
|
||||
__LINE__);
|
||||
#else // if 0
|
||||
#define DBG(x, ...) //wait_us(10);
|
||||
#define WARN(x, ...) //wait_us(10);
|
||||
#define ERR(x, ...)
|
||||
#endif // if 0
|
||||
|
||||
#if 0
|
||||
#define INFO(x, ...) printf("[EddyStone: INFO]"x " \t[%s,%d]\r\n", \
|
||||
## __VA_ARGS__, \
|
||||
__FILE__, \
|
||||
__LINE__);
|
||||
#else // if 0
|
||||
#define INFO(x, ...)
|
||||
#endif // if 0
|
||||
|
||||
/**
|
||||
* @class Eddystone
|
||||
* @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags.
|
||||
* See https://github.com/google/eddystone
|
||||
*
|
||||
*/
|
||||
class EddystoneService
|
||||
{
|
||||
public:
|
||||
enum FrameTypes {
|
||||
NONE,
|
||||
url,
|
||||
uid,
|
||||
tlm
|
||||
};
|
||||
|
||||
static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets
|
||||
|
||||
// There are currently 3 subframes defined, URI, UID, and TLM
|
||||
#define EDDYSTONE_MAX_FRAMETYPE 3
|
||||
void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
|
||||
static const int URI_DATA_MAX = 18;
|
||||
typedef uint8_t UriData_t[URI_DATA_MAX];
|
||||
CircularBuffer<FrameTypes, EDDYSTONE_MAX_FRAMETYPE> overflow;
|
||||
|
||||
// UID Frame Type subfields
|
||||
static const int UID_NAMESPACEID_SIZE = 10;
|
||||
typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
|
||||
static const int UID_INSTANCEID_SIZE = 6;
|
||||
typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
|
||||
|
||||
// Eddystone Frame Type ID
|
||||
static const uint8_t FRAME_TYPE_UID = 0x00;
|
||||
static const uint8_t FRAME_TYPE_URL = 0x10;
|
||||
static const uint8_t FRAME_TYPE_TLM = 0x20;
|
||||
|
||||
static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
|
||||
static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
|
||||
|
||||
/**
|
||||
* Set Eddystone UID Frame information.
|
||||
*
|
||||
* @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB.
|
||||
* @param[in] namespaceID 10B namespace ID
|
||||
* @param[in] instanceID 6B instance ID
|
||||
* @param[in] RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
|
||||
*/
|
||||
void setUIDFrameData(int8_t power,
|
||||
UIDNamespaceID_t namespaceID,
|
||||
UIDInstanceID_t instanceID,
|
||||
float uidAdvPeriodIn,
|
||||
uint16_t RFU = 0x0000) {
|
||||
if (0.0f == uidAdvPeriodIn) {
|
||||
uidIsSet = false;
|
||||
return;
|
||||
}
|
||||
if (power > 20) {
|
||||
power = 20;
|
||||
}
|
||||
if (power < -100) {
|
||||
power = -100;
|
||||
}
|
||||
|
||||
defaultUidPower = power;
|
||||
memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
|
||||
memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
|
||||
uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesn't really matter yet.
|
||||
uidAdvPeriod = uidAdvPeriodIn;
|
||||
uidIsSet = true; // set toggle to advertise UID frames
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct UID frame from private variables
|
||||
* @param[in/out] Data pointer to array to store constructed frame in
|
||||
* @param[in] maxSize number of bytes left in array, effectively how much empty space is available to write to
|
||||
* @return number of bytes used. negative number indicates error message.
|
||||
*/
|
||||
unsigned constructUIDFrame(uint8_t *Data, uint8_t maxSize) {
|
||||
unsigned index = 0;
|
||||
|
||||
Data[index++] = FRAME_TYPE_UID; // 1B Type
|
||||
|
||||
if (defaultUidPower > 20) {
|
||||
defaultUidPower = 20; // enforce range of vaild values.
|
||||
}
|
||||
if (defaultUidPower < -100) {
|
||||
defaultUidPower = -100;
|
||||
}
|
||||
Data[index++] = defaultUidPower; // 1B Power @ 0meter
|
||||
|
||||
DBG("UID NamespaceID = '0x");
|
||||
for (size_t x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespace ID
|
||||
Data[index++] = defaultUidNamespaceID[x];
|
||||
DBG("%x,", defaultUidNamespaceID[x]);
|
||||
}
|
||||
DBG("'\r\n");
|
||||
|
||||
DBG("UID InstanceID = '0x");
|
||||
for (size_t x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID
|
||||
Data[index++] = defaultUidInstanceID[x];
|
||||
DBG("%x,", defaultUidInstanceID[x]);
|
||||
}
|
||||
DBG("'\r\n");
|
||||
|
||||
if (0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore
|
||||
Data[index++] = (uint8_t)(uidRFU >> 0);
|
||||
Data[index++] = (uint8_t)(uidRFU >> 8);
|
||||
}
|
||||
DBG("construcUIDFrame %d, %d", maxSize, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Eddystone URL Frame information.
|
||||
* @param[in] power TX Power in dB measured at 0 meters from the device.
|
||||
* @param[in] url URL to encode
|
||||
* @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods)
|
||||
* @return false on success, true on failure.
|
||||
*/
|
||||
bool setURLFrameData(int8_t power, const char *urlIn, float urlAdvPeriodIn) {
|
||||
if (0.0f == urlAdvPeriodIn) {
|
||||
urlIsSet = false;
|
||||
return false;
|
||||
}
|
||||
encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return true; // error, URL is too big
|
||||
}
|
||||
defaultUrlPower = power;
|
||||
urlAdvPeriod = urlAdvPeriodIn;
|
||||
urlIsSet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Eddystone URL Frame information.
|
||||
* @param[in] power TX Power in dB measured at 0 meters from the device.
|
||||
* @param[in] encodedUrlIn Encoded URL
|
||||
* @param[in] encodedUrlInLength Length of the encoded URL
|
||||
* @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods)
|
||||
* @return false on success, true on failure.
|
||||
*/
|
||||
bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, float urlAdvPeriodIn) {
|
||||
if (0.0f == urlAdvPeriodIn) {
|
||||
urlIsSet = false;
|
||||
return false;
|
||||
}
|
||||
memcpy(defaultUriData, encodedUrlIn, encodedUrlInLength);
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return true; // error, URL is too big
|
||||
}
|
||||
defaultUrlPower = power;
|
||||
defaultUriDataLength = encodedUrlInLength;
|
||||
urlAdvPeriod = urlAdvPeriodIn;
|
||||
urlIsSet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct URL frame from private variables
|
||||
* @param[in/out] Data pointer to array to store constructed frame in
|
||||
* @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
|
||||
* @return number of bytes used. negative number indicates error message.
|
||||
*/
|
||||
int constructURLFrame(uint8_t *Data, uint8_t maxSize) {
|
||||
int index = 0;
|
||||
Data[index++] = FRAME_TYPE_URL; // 1B Type
|
||||
Data[index++] = defaultUrlPower; // 1B TX Power
|
||||
for (int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL
|
||||
Data[index++] = defaultUriData[x];
|
||||
}
|
||||
DBG("constructURLFrame: %d, %d", maxSize, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set Eddystone TLM Frame information.
|
||||
* @param[in] Version of the TLM beacon data format
|
||||
* @param[in] advPeriod how often to advertise the TLM frame for (in minutes)
|
||||
* @param batteryVoltage in milivolts
|
||||
* @param beaconTemp in 8.8 floating point notation
|
||||
*
|
||||
*/
|
||||
void setTLMFrameData(uint8_t version = 0,
|
||||
float advPeriod = 60.0f,
|
||||
uint16_t batteryVoltage = 0,
|
||||
uint16_t beaconTemp = 0x8000,
|
||||
uint32_t pduCount = 0,
|
||||
uint32_t timeSinceBoot = 0) {
|
||||
if (0.0f == advPeriod) {
|
||||
tlmIsSet = false;
|
||||
return;
|
||||
}
|
||||
TlmVersion = version;
|
||||
TlmBatteryVoltage = batteryVoltage;
|
||||
TlmBeaconTemp = beaconTemp;
|
||||
TlmPduCount = pduCount; // reset
|
||||
TlmTimeSinceBoot = timeSinceBoot; // reset
|
||||
TlmAdvPeriod = advPeriod;
|
||||
tlmIsSet = true; // TLM Data has been enabled
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct TLM frame from private variables
|
||||
* @param[in/out] Data pointer to array to store constructed frame in
|
||||
* @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
|
||||
* @return number of bytes used. negative number indicates error message.
|
||||
*/
|
||||
int constructTLMFrame(uint8_t *Data, uint8_t maxSize) {
|
||||
uint32_t now = timeSinceBootTimer.read_ms();
|
||||
TlmTimeSinceBoot += (now - lastBootTimerRead) / 100;
|
||||
lastBootTimerRead = now;
|
||||
|
||||
int index = 0;
|
||||
Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry
|
||||
Data[index++] = TlmVersion; // TLM Version Number
|
||||
Data[index++] = (uint8_t)(TlmBatteryVoltage >> 8); // Battery Voltage[0]
|
||||
Data[index++] = (uint8_t)(TlmBatteryVoltage >> 0); // Battery Voltage[1]
|
||||
Data[index++] = (uint8_t)(TlmBeaconTemp >> 8); // Beacon Temp[0]
|
||||
Data[index++] = (uint8_t)(TlmBeaconTemp >> 0); // Beacon Temp[1]
|
||||
Data[index++] = (uint8_t)(TlmPduCount >> 24); // PDU Count [0]
|
||||
Data[index++] = (uint8_t)(TlmPduCount >> 16); // PDU Count [1]
|
||||
Data[index++] = (uint8_t)(TlmPduCount >> 8); // PDU Count [2]
|
||||
Data[index++] = (uint8_t)(TlmPduCount >> 0); // PDU Count [3]
|
||||
Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 24); // Time Since Boot [0]
|
||||
Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 16); // Time Since Boot [1]
|
||||
Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 8); // Time Since Boot [2]
|
||||
Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 0); // Time Since Boot [3]
|
||||
DBG("constructURLFrame: %d, %d", maxSize, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the TLM frame battery voltage value
|
||||
* @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV)
|
||||
* @return nothing
|
||||
*/
|
||||
void updateTlmBatteryVoltage(uint16_t voltagemv) {
|
||||
TlmBatteryVoltage = voltagemv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the TLM frame beacon temperature
|
||||
* @param[in] temp Temperature of beacon (in 8.8fpn)
|
||||
* @return nothing
|
||||
*/
|
||||
void updateTlmBeaconTemp(uint16_t temp) {
|
||||
TlmBeaconTemp = temp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the TLM frame PDU Count field
|
||||
* @param[in] pduCount Number of Advertisiting frames sent since powerup
|
||||
* @return nothing
|
||||
*/
|
||||
void updateTlmPduCount(uint32_t pduCount) {
|
||||
TlmPduCount = pduCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the TLM frame Time since boot in 0.1s incriments
|
||||
* @param[in] timeSinceBoot Time since boot in 0.1s incriments
|
||||
* @return nothing
|
||||
*/
|
||||
void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) {
|
||||
TlmTimeSinceBoot = timeSinceBoot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update advertising data
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) {
|
||||
// Fields from the Service
|
||||
DBG("Updating AdvFrame: %d", serviceDataLen);
|
||||
|
||||
ble.clearAdvertisingPayload();
|
||||
ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
|
||||
ble.setAdvertisingInterval(100);
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE));
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* State machine for switching out frames.
|
||||
* This function is called by the radioNotificationCallback when a frame needs to get swapped out.
|
||||
* This function exists because of time constraints in the radioNotificationCallback, so it is effectively
|
||||
* broken up into two functions.
|
||||
*/
|
||||
void swapOutFrames(FrameTypes frameType) {
|
||||
uint8_t serviceData[SERVICE_DATA_MAX];
|
||||
unsigned serviceDataLen = 0;
|
||||
//hard code in the eddystone UUID
|
||||
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
|
||||
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
|
||||
|
||||
// if certain frames are not enabled, then skip them. Worst case TLM is always enabled
|
||||
switch (frameType) {
|
||||
case tlm:
|
||||
// TLM frame
|
||||
if (tlmIsSet) {
|
||||
DBG("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d",
|
||||
TlmVersion,
|
||||
TlmBatteryVoltage,
|
||||
TlmBeaconTemp,
|
||||
TlmPduCount,
|
||||
TlmTimeSinceBoot);
|
||||
serviceDataLen += constructTLMFrame(serviceData + serviceDataLen, 20);
|
||||
DBG("\t Swapping in TLM Frame: len=%d", serviceDataLen);
|
||||
updateAdvPacket(serviceData, serviceDataLen);
|
||||
}
|
||||
break;
|
||||
case url:
|
||||
// URL Frame
|
||||
if (urlIsSet) {
|
||||
DBG("Swapping in URL Frame: Power: %d", defaultUrlPower);
|
||||
serviceDataLen += constructURLFrame(serviceData + serviceDataLen, 20);
|
||||
DBG("\t Swapping in URL Frame: len=%d ", serviceDataLen);
|
||||
updateAdvPacket(serviceData, serviceDataLen);
|
||||
//switchFlag = false;
|
||||
}
|
||||
break;
|
||||
case uid:
|
||||
// UID Frame
|
||||
if (uidIsSet) {
|
||||
DBG("Swapping in UID Frame: Power: %d", defaultUidPower);
|
||||
serviceDataLen += constructUIDFrame(serviceData + serviceDataLen, 20);
|
||||
DBG("\t Swapping in UID Frame: len=%d", serviceDataLen);
|
||||
updateAdvPacket(serviceData, serviceDataLen);
|
||||
//switchFlag = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR("You have not initialized a Frame yet, please initialize one before starting a beacon");
|
||||
ERR("uidIsSet = %d, urlIsSet = %d, tlmIsSet = %d", uidIsSet, urlIsSet, tlmIsSet);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to swap in URL frame
|
||||
*/
|
||||
void urlCallback(void) {
|
||||
DBG("urlCallback");
|
||||
if (false == advLock) {
|
||||
advLock = true;
|
||||
DBG("advLock = url")
|
||||
frameIndex = url;
|
||||
swapOutFrames(frameIndex);
|
||||
ble.startAdvertising();
|
||||
} else {
|
||||
// Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
|
||||
INFO("URI(%d) cannot complete, %d is currently broadcasting", url, frameIndex);
|
||||
FrameTypes x = url;
|
||||
overflow.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to swap in UID frame
|
||||
*/
|
||||
void uidCallback(void) {
|
||||
DBG("uidCallback");
|
||||
if (false == advLock) {
|
||||
advLock = true;
|
||||
DBG("advLock = uid")
|
||||
frameIndex = uid;
|
||||
swapOutFrames(frameIndex);
|
||||
ble.startAdvertising();
|
||||
} else {
|
||||
// Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
|
||||
INFO("UID(%d) cannot complete, %d is currently broadcasting", uid, frameIndex);
|
||||
FrameTypes x = uid; // have to do this to satisfy cont vs volatile keywords... sigh...
|
||||
overflow.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to swap in TLM frame
|
||||
*/
|
||||
void tlmCallback(void) {
|
||||
DBG("tlmCallback");
|
||||
if (false == advLock) {
|
||||
// OK to broadcast
|
||||
advLock = true;
|
||||
DBG("advLock = tlm")
|
||||
frameIndex = tlm;
|
||||
swapOutFrames(frameIndex);
|
||||
ble.startAdvertising();
|
||||
} else {
|
||||
// Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
|
||||
INFO("TLM(%d) cannot complete, %d is currently broadcasting", tlm, frameIndex);
|
||||
FrameTypes x = tlm;
|
||||
overflow.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
void stopAdvCallback(void) {
|
||||
if (overflow.empty()) {
|
||||
// if nothing left to transmit, stop
|
||||
ble.stopAdvertising();
|
||||
advLock = false; // unlock lock
|
||||
} else {
|
||||
// transmit other packets at current time index
|
||||
FrameTypes x = NONE;
|
||||
overflow.pop(x);
|
||||
INFO("Re-Transmitting %d", x);
|
||||
swapOutFrames(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback from onRadioNotification(), used to update the PDUCounter and process next state.
|
||||
*/
|
||||
#define EDDYSTONE_SWAPFRAME_DELAYMS 1
|
||||
void radioNotificationCallback(bool radioActive) {
|
||||
// Update PDUCount
|
||||
TlmPduCount++;
|
||||
// True just before an frame is sent, false just after a frame is sent
|
||||
if (radioActive) {
|
||||
// Do Nothing
|
||||
} else {
|
||||
// Packet has been sent, disable advertising
|
||||
stopAdv.attach_us(this, &EddystoneService::stopAdvCallback, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function explicityly sets the parameters used by the Eddystone beacon.
|
||||
* this function should be used in leu of the config service.
|
||||
*
|
||||
* @param bleIn ble object used to broadcast eddystone information
|
||||
* @param beaconPeriodus is how often ble broadcasts are mde, in mili seconds
|
||||
* @param txPowerLevel sets the broadcasting power level.
|
||||
*
|
||||
*/
|
||||
EddystoneService(BLEDevice &bleIn,
|
||||
uint16_t beaconPeriodus = 100,
|
||||
uint8_t txPowerIn = 0) :
|
||||
ble(bleIn),
|
||||
advPeriodus(beaconPeriodus),
|
||||
txPower(txPowerIn),
|
||||
advLock(false),
|
||||
frameIndex(NONE) {
|
||||
}
|
||||
|
||||
/*
|
||||
* @breif this function starts eddystone advertising based on configured frames.
|
||||
*/
|
||||
void start(void) {
|
||||
// Initialize Frame transition, start with URL to pass eddystone validator app on first try
|
||||
if (urlIsSet) {
|
||||
frameIndex = url;
|
||||
urlTicker.attach(this, &EddystoneService::urlCallback, (float) advPeriodus / 1000.0f);
|
||||
DBG("attached urlCallback every %d seconds", urlAdvPeriod);
|
||||
}
|
||||
if (uidIsSet) {
|
||||
frameIndex = uid;
|
||||
uidTicker.attach(this, &EddystoneService::uidCallback, uidAdvPeriod);
|
||||
DBG("attached uidCallback every %d seconds", uidAdvPeriod);
|
||||
}
|
||||
if (tlmIsSet) {
|
||||
frameIndex = tlm;
|
||||
// Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset
|
||||
updateTlmPduCount(0);
|
||||
updateTlmTimeSinceBoot(0);
|
||||
lastBootTimerRead = 0;
|
||||
timeSinceBootTimer.start();
|
||||
tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod);
|
||||
DBG("attached tlmCallback every %d seconds", TlmAdvPeriod);
|
||||
}
|
||||
if (NONE == frameIndex) {
|
||||
error("No Frames were Initialized! Please initialize a frame before starting an eddystone beacon.");
|
||||
}
|
||||
//uidRFU = 0;
|
||||
|
||||
ble.setTxPower(txPower);
|
||||
ble.gap().onRadioNotification(this, &EddystoneService::radioNotificationCallback);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Eddystone Variables
|
||||
BLEDevice &ble;
|
||||
uint16_t advPeriodus;
|
||||
uint8_t txPower;
|
||||
Timer timeSinceBootTimer;
|
||||
volatile uint32_t lastBootTimerRead;
|
||||
volatile bool advLock;
|
||||
volatile FrameTypes frameIndex;
|
||||
Timeout stopAdv;
|
||||
|
||||
|
||||
// URI Frame Variables
|
||||
uint8_t defaultUriDataLength;
|
||||
UriData_t defaultUriData;
|
||||
int8_t defaultUrlPower;
|
||||
bool urlIsSet; // flag that enables / disable URI Frames
|
||||
float urlAdvPeriod; // how long the url frame will be advertised for
|
||||
Ticker urlTicker;
|
||||
|
||||
// UID Frame Variables
|
||||
UIDNamespaceID_t defaultUidNamespaceID;
|
||||
UIDInstanceID_t defaultUidInstanceID;
|
||||
int8_t defaultUidPower;
|
||||
uint16_t uidRFU;
|
||||
bool uidIsSet; // flag that enables / disable UID Frames
|
||||
float uidAdvPeriod; // how long the uid frame will be advertised for
|
||||
Ticker uidTicker;
|
||||
|
||||
// TLM Frame Variables
|
||||
uint8_t TlmVersion;
|
||||
volatile uint16_t TlmBatteryVoltage;
|
||||
volatile uint16_t TlmBeaconTemp;
|
||||
volatile uint32_t TlmPduCount;
|
||||
volatile uint32_t TlmTimeSinceBoot;
|
||||
bool tlmIsSet; // flag that enables / disables TLM frames
|
||||
float TlmAdvPeriod; // number of minutes between adv frames
|
||||
Ticker tlmTicker;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
|
||||
*/
|
||||
static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, uint8_t &sizeofURIDataOut) {
|
||||
DBG("Encode URL = %s", uriDataIn);
|
||||
const char *prefixes[] = {
|
||||
"http://www.",
|
||||
"https://www.",
|
||||
"http://",
|
||||
"https://",
|
||||
};
|
||||
const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
|
||||
const char *suffixes[] = {
|
||||
".com/",
|
||||
".org/",
|
||||
".edu/",
|
||||
".net/",
|
||||
".info/",
|
||||
".biz/",
|
||||
".gov/",
|
||||
".com",
|
||||
".org",
|
||||
".edu",
|
||||
".net",
|
||||
".info",
|
||||
".biz",
|
||||
".gov"
|
||||
};
|
||||
const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
|
||||
|
||||
sizeofURIDataOut = 0;
|
||||
memset(uriDataOut, 0, sizeof(UriData_t));
|
||||
|
||||
if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle prefix
|
||||
*/
|
||||
for (unsigned i = 0; i < NUM_PREFIXES; i++) {
|
||||
size_t prefixLen = strlen(prefixes[i]);
|
||||
if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
|
||||
uriDataOut[sizeofURIDataOut++] = i;
|
||||
uriDataIn += prefixLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handle suffixes
|
||||
*/
|
||||
while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
|
||||
/* check for suffix match */
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_SUFFIXES; i++) {
|
||||
size_t suffixLen = strlen(suffixes[i]);
|
||||
if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
|
||||
uriDataOut[sizeofURIDataOut++] = i;
|
||||
uriDataIn += suffixLen;
|
||||
break; /* from the for loop for checking against suffixes */
|
||||
}
|
||||
}
|
||||
/* This is the default case where we've got an ordinary character which doesn't match a suffix. */
|
||||
INFO("Encoding URI: No Suffix Found");
|
||||
if (i == NUM_SUFFIXES) {
|
||||
uriDataOut[sizeofURIDataOut++] = *uriDataIn;
|
||||
++uriDataIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SERVICES_EDDYSTONEBEACON_H_
|
|
@ -0,0 +1,106 @@
|
|||
/* 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 __BLE_ENVIRONMENTAL_SERVICE_H__
|
||||
#define __BLE_ENVIRONMENTAL_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class EnvironmentalService
|
||||
* @brief BLE Environmental Service. This service provides temperature, humidity and pressure measurement.
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.environmental_sensing.xml
|
||||
* Temperature: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature.xml
|
||||
* Humidity: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.humidity.xml
|
||||
* Pressure: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.pressure.xml
|
||||
*/
|
||||
class EnvironmentalService {
|
||||
public:
|
||||
typedef int16_t TemperatureType_t;
|
||||
typedef uint16_t HumidityType_t;
|
||||
typedef uint32_t PressureType_t;
|
||||
|
||||
/**
|
||||
* @brief EnvironmentalService constructor.
|
||||
* @param ble Reference to BLE device.
|
||||
* @param temperature_en Enable this characteristic.
|
||||
* @param humidity_en Enable this characteristic.
|
||||
* @param pressure_en Enable this characteristic.
|
||||
*/
|
||||
EnvironmentalService(BLE& _ble) :
|
||||
ble(_ble),
|
||||
temperatureCharacteristic(GattCharacteristic::UUID_TEMPERATURE_CHAR, &temperature),
|
||||
humidityCharacteristic(GattCharacteristic::UUID_HUMIDITY_CHAR, &humidity),
|
||||
pressureCharacteristic(GattCharacteristic::UUID_PRESSURE_CHAR, &pressure)
|
||||
{
|
||||
static bool serviceAdded = false; /* We should only ever need to add the information service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
GattCharacteristic *charTable[] = { &humidityCharacteristic,
|
||||
&pressureCharacteristic,
|
||||
&temperatureCharacteristic };
|
||||
|
||||
GattService environmentalService(GattService::UUID_ENVIRONMENTAL_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.gattServer().addService(environmentalService);
|
||||
serviceAdded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update humidity characteristic.
|
||||
* @param newHumidityVal New humidity measurement.
|
||||
*/
|
||||
void updateHumidity(HumidityType_t newHumidityVal)
|
||||
{
|
||||
humidity = (HumidityType_t) (newHumidityVal * 100);
|
||||
ble.gattServer().write(humidityCharacteristic.getValueHandle(), (uint8_t *) &humidity, sizeof(HumidityType_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update pressure characteristic.
|
||||
* @param newPressureVal New pressure measurement.
|
||||
*/
|
||||
void updatePressure(PressureType_t newPressureVal)
|
||||
{
|
||||
pressure = (PressureType_t) (newPressureVal * 10);
|
||||
ble.gattServer().write(pressureCharacteristic.getValueHandle(), (uint8_t *) &pressure, sizeof(PressureType_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update temperature characteristic.
|
||||
* @param newTemperatureVal New temperature measurement.
|
||||
*/
|
||||
void updateTemperature(float newTemperatureVal)
|
||||
{
|
||||
temperature = (TemperatureType_t) (newTemperatureVal * 100);
|
||||
ble.gattServer().write(temperatureCharacteristic.getValueHandle(), (uint8_t *) &temperature, sizeof(TemperatureType_t));
|
||||
}
|
||||
|
||||
private:
|
||||
BLE& ble;
|
||||
|
||||
TemperatureType_t temperature;
|
||||
HumidityType_t humidity;
|
||||
PressureType_t pressure;
|
||||
|
||||
ReadOnlyGattCharacteristic<TemperatureType_t> temperatureCharacteristic;
|
||||
ReadOnlyGattCharacteristic<HumidityType_t> humidityCharacteristic;
|
||||
ReadOnlyGattCharacteristic<PressureType_t> pressureCharacteristic;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_ENVIRONMENTAL_SERVICE_H__*/
|
|
@ -0,0 +1,150 @@
|
|||
/* 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 __BLE_HEALTH_THERMOMETER_SERVICE_H__
|
||||
#define __BLE_HEALTH_THERMOMETER_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class HealthThermometerService
|
||||
* @brief BLE Health Thermometer Service. This service provides the location of the thermometer and the temperature.
|
||||
* Service: https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.health_thermometer.xml
|
||||
* Temperature Measurement: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml
|
||||
* Temperature Type: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_type.xml
|
||||
*/
|
||||
class HealthThermometerService {
|
||||
public:
|
||||
/**
|
||||
* @enum Sensor Location.
|
||||
* @brief Location of sensor on the body.
|
||||
*/
|
||||
enum SensorLocation_t {
|
||||
LOCATION_ARMPIT = 1, /*!< Armpit. */
|
||||
LOCATION_BODY, /*!< Body. */
|
||||
LOCATION_EAR, /*!< Ear. */
|
||||
LOCATION_FINGER, /*!< Finger. */
|
||||
LOCATION_GI_TRACT, /*!< GI tract */
|
||||
LOCATION_MOUTH, /*!< Mouth. */
|
||||
LOCATION_RECTUM, /*!< Rectum. */
|
||||
LOCATION_TOE, /*!< Toe. */
|
||||
LOCATION_EAR_DRUM, /*!< Eardrum. */
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Add the Health Thermometer Service to an existing BLE object, initialize with temperature and location.
|
||||
* @param[ref] _ble Reference to the BLE device.
|
||||
* @param[in] initialTemp Initial value in celsius.
|
||||
* @param[in] _location
|
||||
*/
|
||||
HealthThermometerService(BLE &_ble, float initialTemp, uint8_t _location) :
|
||||
ble(_ble),
|
||||
valueBytes(initialTemp),
|
||||
tempMeasurement(GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, (TemperatureValueBytes *)valueBytes.getPointer(), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
|
||||
tempLocation(GattCharacteristic::UUID_TEMPERATURE_TYPE_CHAR, &_location) {
|
||||
|
||||
GattCharacteristic *hrmChars[] = {&tempMeasurement, &tempLocation, };
|
||||
GattService hrmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, hrmChars, sizeof(hrmChars) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(hrmService);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the temperature being broadcast.
|
||||
*
|
||||
* @param[in] temperature
|
||||
* Floating point value of the temperature.
|
||||
*
|
||||
*/
|
||||
void updateTemperature(float temperature) {
|
||||
if (ble.getGapState().connected) {
|
||||
valueBytes.updateTemperature(temperature);
|
||||
ble.gattServer().write(tempMeasurement.getValueHandle(), valueBytes.getPointer(), sizeof(TemperatureValueBytes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the location.
|
||||
* @param loc
|
||||
* New location value.
|
||||
*/
|
||||
void updateLocation(SensorLocation_t loc) {
|
||||
ble.gattServer().write(tempLocation.getValueHandle(), reinterpret_cast<uint8_t *>(&loc), sizeof(uint8_t));
|
||||
}
|
||||
|
||||
private:
|
||||
/* Private internal representation for the bytes used to work with the vaulue of the temperature characteristic. */
|
||||
struct TemperatureValueBytes {
|
||||
static const unsigned OFFSET_OF_FLAGS = 0;
|
||||
static const unsigned OFFSET_OF_VALUE = OFFSET_OF_FLAGS + sizeof(uint8_t);
|
||||
static const unsigned SIZEOF_VALUE_BYTES = sizeof(uint8_t) + sizeof(float);
|
||||
|
||||
static const unsigned TEMPERATURE_UNITS_FLAG_POS = 0;
|
||||
static const unsigned TIMESTAMP_FLAG_POS = 1;
|
||||
static const unsigned TEMPERATURE_TYPE_FLAG_POS = 2;
|
||||
|
||||
static const uint8_t TEMPERATURE_UNITS_CELSIUS = 0;
|
||||
static const uint8_t TEMPERATURE_UNITS_FAHRENHEIT = 1;
|
||||
|
||||
TemperatureValueBytes(float initialTemperature) : bytes() {
|
||||
/* Assumption: temperature values are expressed in celsius */
|
||||
bytes[OFFSET_OF_FLAGS] = (TEMPERATURE_UNITS_CELSIUS << TEMPERATURE_UNITS_FLAG_POS) |
|
||||
(false << TIMESTAMP_FLAG_POS) |
|
||||
(false << TEMPERATURE_TYPE_FLAG_POS);
|
||||
updateTemperature(initialTemperature);
|
||||
}
|
||||
|
||||
void updateTemperature(float temp) {
|
||||
uint32_t temp_ieee11073 = quick_ieee11073_from_float(temp);
|
||||
memcpy(&bytes[OFFSET_OF_VALUE], &temp_ieee11073, sizeof(float));
|
||||
}
|
||||
|
||||
uint8_t *getPointer(void) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
const uint8_t *getPointer(void) const {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
|
||||
* @param temperature The temperature as a float.
|
||||
* @return The temperature in 11073-20601 FLOAT-Type format.
|
||||
*/
|
||||
uint32_t quick_ieee11073_from_float(float temperature) {
|
||||
uint8_t exponent = 0xFE; //Exponent is -2
|
||||
uint32_t mantissa = (uint32_t)(temperature * 100);
|
||||
|
||||
return (((uint32_t)exponent) << 24) | mantissa;
|
||||
}
|
||||
|
||||
private:
|
||||
/* First byte: 8-bit flags. Second field is a float holding the temperature value. */
|
||||
/* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
|
||||
uint8_t bytes[SIZEOF_VALUE_BYTES];
|
||||
};
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
TemperatureValueBytes valueBytes;
|
||||
ReadOnlyGattCharacteristic<TemperatureValueBytes> tempMeasurement;
|
||||
ReadOnlyGattCharacteristic<uint8_t> tempLocation;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__*/
|
|
@ -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 __BLE_HEART_RATE_SERVICE_H__
|
||||
#define __BLE_HEART_RATE_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class HeartRateService
|
||||
* @brief BLE Service for HeartRate. This BLE Service contains the location of the sensor and the heart rate in beats per minute.
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml
|
||||
* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
|
||||
* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml
|
||||
*/
|
||||
class HeartRateService {
|
||||
public:
|
||||
/**
|
||||
* @enum SensorLocation
|
||||
* @brief Location of the heart rate sensor on body.
|
||||
*/
|
||||
enum {
|
||||
LOCATION_OTHER = 0, /*!< Other location. */
|
||||
LOCATION_CHEST, /*!< Chest. */
|
||||
LOCATION_WRIST, /*!< Wrist. */
|
||||
LOCATION_FINGER, /*!< Finger. */
|
||||
LOCATION_HAND, /*!< Hand. */
|
||||
LOCATION_EAR_LOBE, /*!< Earlobe. */
|
||||
LOCATION_FOOT, /*!< Foot. */
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor with 8-bit HRM Counter value.
|
||||
*
|
||||
* @param[ref] _ble
|
||||
* Reference to the underlying BLE.
|
||||
* @param[in] hrmCounter (8-bit)
|
||||
* Initial value for the HRM counter.
|
||||
* @param[in] location
|
||||
* Sensor's location.
|
||||
*/
|
||||
HeartRateService(BLE &_ble, uint8_t hrmCounter, uint8_t location) :
|
||||
ble(_ble),
|
||||
valueBytes(hrmCounter),
|
||||
hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
|
||||
valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
|
||||
hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location),
|
||||
controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
|
||||
setupService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor with a 16-bit HRM Counter value.
|
||||
*
|
||||
* @param[in] _ble
|
||||
* Reference to the underlying BLE.
|
||||
* @param[in] hrmCounter (8-bit)
|
||||
* Initial value for the HRM counter.
|
||||
* @param[in] location
|
||||
* Sensor's location.
|
||||
*/
|
||||
HeartRateService(BLE &_ble, uint16_t hrmCounter, uint8_t location) :
|
||||
ble(_ble),
|
||||
valueBytes(hrmCounter),
|
||||
hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
|
||||
valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
|
||||
hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location),
|
||||
controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
|
||||
setupService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a new 8-bit value for the heart rate.
|
||||
*
|
||||
* @param[in] hrmCounter
|
||||
* Heart rate in BPM.
|
||||
*/
|
||||
void updateHeartRate(uint8_t hrmCounter) {
|
||||
valueBytes.updateHeartRate(hrmCounter);
|
||||
ble.gattServer().write(hrmRate.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new 16-bit value for the heart rate.
|
||||
*
|
||||
* @param[in] hrmCounter
|
||||
* Heart rate in BPM.
|
||||
*/
|
||||
void updateHeartRate(uint16_t hrmCounter) {
|
||||
valueBytes.updateHeartRate(hrmCounter);
|
||||
ble.gattServer().write(hrmRate.getValueHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback allows the heart rate service to receive updates to the
|
||||
* controlPoint characteristic.
|
||||
*
|
||||
* @param[in] params
|
||||
* Information about the characterisitc being updated.
|
||||
*/
|
||||
virtual void onDataWritten(const GattWriteCallbackParams *params) {
|
||||
if (params->handle == controlPoint.getValueAttribute().getHandle()) {
|
||||
/* Do something here if the new value is 1; else you can override this method by
|
||||
* extending this class.
|
||||
* @NOTE: If you are extending this class, be sure to also call
|
||||
* ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
|
||||
* your constructor.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void setupService(void) {
|
||||
GattCharacteristic *charTable[] = {&hrmRate, &hrmLocation, &controlPoint};
|
||||
GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(hrmService);
|
||||
ble.onDataWritten(this, &HeartRateService::onDataWritten);
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Private internal representation for the bytes used to work with the value of the heart rate characteristic. */
|
||||
struct HeartRateValueBytes {
|
||||
static const unsigned MAX_VALUE_BYTES = 3; /* Flags, and up to two bytes for heart rate. */
|
||||
static const unsigned FLAGS_BYTE_INDEX = 0;
|
||||
|
||||
static const unsigned VALUE_FORMAT_BITNUM = 0;
|
||||
static const uint8_t VALUE_FORMAT_FLAG = (1 << VALUE_FORMAT_BITNUM);
|
||||
|
||||
HeartRateValueBytes(uint8_t hrmCounter) : valueBytes() {
|
||||
updateHeartRate(hrmCounter);
|
||||
}
|
||||
|
||||
HeartRateValueBytes(uint16_t hrmCounter) : valueBytes() {
|
||||
updateHeartRate(hrmCounter);
|
||||
}
|
||||
|
||||
void updateHeartRate(uint8_t hrmCounter) {
|
||||
valueBytes[FLAGS_BYTE_INDEX] &= ~VALUE_FORMAT_FLAG;
|
||||
valueBytes[FLAGS_BYTE_INDEX + 1] = hrmCounter;
|
||||
}
|
||||
|
||||
void updateHeartRate(uint16_t hrmCounter) {
|
||||
valueBytes[FLAGS_BYTE_INDEX] |= VALUE_FORMAT_FLAG;
|
||||
valueBytes[FLAGS_BYTE_INDEX + 1] = (uint8_t)(hrmCounter & 0xFF);
|
||||
valueBytes[FLAGS_BYTE_INDEX + 2] = (uint8_t)(hrmCounter >> 8);
|
||||
}
|
||||
|
||||
uint8_t *getPointer(void) {
|
||||
return valueBytes;
|
||||
}
|
||||
|
||||
const uint8_t *getPointer(void) const {
|
||||
return valueBytes;
|
||||
}
|
||||
|
||||
unsigned getNumValueBytes(void) const {
|
||||
return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & VALUE_FORMAT_FLAG) ? sizeof(uint16_t) : sizeof(uint8_t));
|
||||
}
|
||||
|
||||
private:
|
||||
/* First byte: 8-bit values, no extra info. Second byte: uint8_t HRM value */
|
||||
/* See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
|
||||
uint8_t valueBytes[MAX_VALUE_BYTES];
|
||||
};
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
|
||||
HeartRateValueBytes valueBytes;
|
||||
uint8_t controlPointValue;
|
||||
|
||||
GattCharacteristic hrmRate;
|
||||
ReadOnlyGattCharacteristic<uint8_t> hrmLocation;
|
||||
WriteOnlyGattCharacteristic<uint8_t> controlPoint;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_HEART_RATE_SERVICE_H__*/
|
|
@ -0,0 +1,103 @@
|
|||
/* 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 __BLE_LINK_LOSS_SERVICE_H__
|
||||
#define __BLE_LINK_LOSS_SERVICE_H__
|
||||
|
||||
#include "ble/Gap.h"
|
||||
|
||||
/**
|
||||
* @class LinkLossService
|
||||
* @brief This service defines behavior when a link is lost between two devices.
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.link_loss.xml
|
||||
* Alertness Level Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.alert_level.xml
|
||||
*/
|
||||
class LinkLossService {
|
||||
public:
|
||||
enum AlertLevel_t {
|
||||
NO_ALERT = 0,
|
||||
MILD_ALERT = 1,
|
||||
HIGH_ALERT = 2
|
||||
};
|
||||
|
||||
typedef void (* callback_t)(AlertLevel_t level);
|
||||
|
||||
/**
|
||||
* @param[ref] ble
|
||||
* BLE object for the underlying controller.
|
||||
*/
|
||||
LinkLossService(BLE &bleIn, callback_t callbackIn, AlertLevel_t levelIn = NO_ALERT) :
|
||||
ble(bleIn),
|
||||
alertLevel(levelIn),
|
||||
callback(callbackIn),
|
||||
alertLevelChar(GattCharacteristic::UUID_ALERT_LEVEL_CHAR, reinterpret_cast<uint8_t *>(&alertLevel)) {
|
||||
static bool serviceAdded = false; /* We should only ever add one LinkLoss service. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
GattCharacteristic *charTable[] = {&alertLevelChar};
|
||||
GattService linkLossService(GattService::UUID_LINK_LOSS_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.gattServer().addService(linkLossService);
|
||||
serviceAdded = true;
|
||||
|
||||
ble.gap().onDisconnection(this, &LinkLossService::onDisconnectionFilter);
|
||||
ble.gattServer().onDataWritten(this, &LinkLossService::onDataWritten);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the callback.
|
||||
*/
|
||||
void setCallback(callback_t newCallback) {
|
||||
callback = newCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update alertness level.
|
||||
*/
|
||||
void setAlertLevel(AlertLevel_t newLevel) {
|
||||
alertLevel = newLevel;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This callback allows receiving updates to the AlertLevel characteristic.
|
||||
*
|
||||
* @param[in] params
|
||||
* Information about the characterisitc being updated.
|
||||
*/
|
||||
virtual void onDataWritten(const GattWriteCallbackParams *params) {
|
||||
if (params->handle == alertLevelChar.getValueHandle()) {
|
||||
alertLevel = *reinterpret_cast<const AlertLevel_t *>(params->data);
|
||||
}
|
||||
}
|
||||
|
||||
void onDisconnectionFilter(const Gap::DisconnectionCallbackParams_t *params) {
|
||||
if (alertLevel != NO_ALERT) {
|
||||
callback(alertLevel);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
AlertLevel_t alertLevel;
|
||||
callback_t callback;
|
||||
|
||||
ReadWriteGattCharacteristic<uint8_t> alertLevelChar;
|
||||
};
|
||||
|
||||
#endif /* __BLE_LINK_LOSS_SERVICE_H__ */
|
|
@ -0,0 +1,206 @@
|
|||
/* 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 __BLE_UART_SERVICE_H__
|
||||
#define __BLE_UART_SERVICE_H__
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#include "mbed-drivers/Stream.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#include "Stream.h"
|
||||
#endif
|
||||
|
||||
#include "ble/UUID.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
extern const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint16_t UARTServiceShortUUID;
|
||||
extern const uint16_t UARTServiceTXCharacteristicShortUUID;
|
||||
extern const uint16_t UARTServiceRXCharacteristicShortUUID;
|
||||
|
||||
extern const uint8_t UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID];
|
||||
|
||||
extern const uint8_t UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID];
|
||||
|
||||
/**
|
||||
* @class UARTService.
|
||||
* @brief BLE Service to enable UART over BLE.
|
||||
*/
|
||||
class UARTService {
|
||||
public:
|
||||
/**< Maximum length of data (in bytes) that the UART service module can transmit to the peer. */
|
||||
static const unsigned BLE_UART_SERVICE_MAX_DATA_LEN = (BLE_GATT_MTU_SIZE_DEFAULT - 3);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @param[ref] ble
|
||||
* BLE object for the underlying controller.
|
||||
*/
|
||||
UARTService(BLE &_ble) :
|
||||
ble(_ble),
|
||||
receiveBuffer(),
|
||||
sendBuffer(),
|
||||
sendBufferIndex(0),
|
||||
numBytesReceived(0),
|
||||
receiveBufferIndex(0),
|
||||
txCharacteristic(UARTServiceTXCharacteristicUUID, receiveBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
|
||||
rxCharacteristic(UARTServiceRXCharacteristicUUID, sendBuffer, 1, BLE_UART_SERVICE_MAX_DATA_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
|
||||
GattCharacteristic *charTable[] = {&txCharacteristic, &rxCharacteristic};
|
||||
GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(uartService);
|
||||
ble.onDataWritten(this, &UARTService::onDataWritten);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
|
||||
*/
|
||||
uint16_t getTXCharacteristicHandle() {
|
||||
return txCharacteristic.getValueAttribute().getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: TX and RX characteristics are to be interpreted from the viewpoint of the GATT client using this service.
|
||||
*/
|
||||
uint16_t getRXCharacteristicHandle() {
|
||||
return rxCharacteristic.getValueAttribute().getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* We attempt to collect bytes before pushing them to the UART RX
|
||||
* characteristic; writing to the RX characteristic then generates
|
||||
* notifications for the client. Updates made in quick succession to a
|
||||
* notification-generating characteristic result in data being buffered
|
||||
* in the Bluetooth stack as notifications are sent out. The stack has
|
||||
* its limits for this buffering - typically a small number under 10.
|
||||
* Collecting data into the sendBuffer buffer helps mitigate the rate of
|
||||
* updates. But we shouldn't buffer a large amount of data before updating
|
||||
* the characteristic, otherwise the client needs to turn around and make
|
||||
* a long read request; this is because notifications include only the first
|
||||
* 20 bytes of the updated data.
|
||||
*
|
||||
* @param buffer The received update.
|
||||
* @param length Number of characters to be appended.
|
||||
* @return Number of characters appended to the rxCharacteristic.
|
||||
*/
|
||||
size_t write(const void *_buffer, size_t length) {
|
||||
size_t origLength = length;
|
||||
const uint8_t *buffer = static_cast<const uint8_t *>(_buffer);
|
||||
|
||||
if (ble.getGapState().connected) {
|
||||
unsigned bufferIndex = 0;
|
||||
while (length) {
|
||||
unsigned bytesRemainingInSendBuffer = BLE_UART_SERVICE_MAX_DATA_LEN - sendBufferIndex;
|
||||
unsigned bytesToCopy = (length < bytesRemainingInSendBuffer) ? length : bytesRemainingInSendBuffer;
|
||||
|
||||
/* Copy bytes into sendBuffer. */
|
||||
memcpy(&sendBuffer[sendBufferIndex], &buffer[bufferIndex], bytesToCopy);
|
||||
length -= bytesToCopy;
|
||||
sendBufferIndex += bytesToCopy;
|
||||
bufferIndex += bytesToCopy;
|
||||
|
||||
/* Have we collected enough? */
|
||||
if ((sendBufferIndex == BLE_UART_SERVICE_MAX_DATA_LEN) ||
|
||||
// (sendBuffer[sendBufferIndex - 1] == '\r') ||
|
||||
(sendBuffer[sendBufferIndex - 1] == '\n')) {
|
||||
ble.gattServer().write(getRXCharacteristicHandle(), static_cast<const uint8_t *>(sendBuffer), sendBufferIndex);
|
||||
sendBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return origLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to write out strings.
|
||||
* @param str The received string.
|
||||
* @return Number of characters appended to the rxCharacteristic.
|
||||
*/
|
||||
size_t writeString(const char *str) {
|
||||
return write(str, strlen(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for Stream::_putc().
|
||||
* @param c
|
||||
* This function writes the character c, cast to an unsigned char, to stream.
|
||||
* @return
|
||||
* The character written as an unsigned char cast to an int or EOF on error.
|
||||
*/
|
||||
int _putc(int c) {
|
||||
return (write(&c, 1) == 1) ? 1 : EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for Stream::_getc().
|
||||
* @return
|
||||
* The character read.
|
||||
*/
|
||||
int _getc() {
|
||||
if (receiveBufferIndex == numBytesReceived) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return receiveBuffer[receiveBufferIndex++];
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This callback allows the UART service to receive updates to the
|
||||
* txCharacteristic. The application should forward the call to this
|
||||
* function from the global onDataWritten() callback handler; if that's
|
||||
* not used, this method can be used as a callback directly.
|
||||
*/
|
||||
void onDataWritten(const GattWriteCallbackParams *params) {
|
||||
if (params->handle == getTXCharacteristicHandle()) {
|
||||
uint16_t bytesRead = params->len;
|
||||
if (bytesRead <= BLE_UART_SERVICE_MAX_DATA_LEN) {
|
||||
numBytesReceived = bytesRead;
|
||||
receiveBufferIndex = 0;
|
||||
memcpy(receiveBuffer, params->data, numBytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
|
||||
uint8_t receiveBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which we receive
|
||||
* inbound data before forwarding it to the
|
||||
* application. */
|
||||
|
||||
uint8_t sendBuffer[BLE_UART_SERVICE_MAX_DATA_LEN]; /**< The local buffer into which outbound data is
|
||||
* accumulated before being pushed to the
|
||||
* rxCharacteristic. */
|
||||
uint8_t sendBufferIndex;
|
||||
uint8_t numBytesReceived;
|
||||
uint8_t receiveBufferIndex;
|
||||
|
||||
GattCharacteristic txCharacteristic; /**< From the point of view of the external client, this is the characteristic
|
||||
* they'd write into in order to communicate with this application. */
|
||||
GattCharacteristic rxCharacteristic; /**< From the point of view of the external client, this is the characteristic
|
||||
* they'd read from in order to receive the bytes transmitted by this
|
||||
* application. */
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_UART_SERVICE_H__*/
|
|
@ -0,0 +1,472 @@
|
|||
/* 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 SERVICES_URIBEACONCONFIGSERVICE_H_
|
||||
#define SERVICES_URIBEACONCONFIGSERVICE_H_
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
|
||||
extern const uint8_t UUID_URI_BEACON_SERVICE[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_LOCK_STATE_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_LOCK_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_UNLOCK_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_URI_DATA_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_FLAGS_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_ADV_POWER_LEVELS_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_TX_POWER_MODE_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_BEACON_PERIOD_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_RESET_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
|
||||
extern const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)];
|
||||
|
||||
/**
|
||||
* @class URIBeaconConfigService
|
||||
* @brief UriBeacon Configuration Service. Can be used to set URL, adjust power levels, and set flags.
|
||||
* See http://uribeacon.org
|
||||
*
|
||||
*/
|
||||
class URIBeaconConfigService {
|
||||
public:
|
||||
/**
|
||||
* @brief Transmission power modes for UriBeacon.
|
||||
*/
|
||||
static const uint8_t TX_POWER_MODE_LOWEST = 0; /*!< Lowest TX power mode. */
|
||||
static const uint8_t TX_POWER_MODE_LOW = 1; /*!< Low TX power mode. */
|
||||
static const uint8_t TX_POWER_MODE_MEDIUM = 2; /*!< Medium TX power mode. */
|
||||
static const uint8_t TX_POWER_MODE_HIGH = 3; /*!< High TX power mode. */
|
||||
static const unsigned NUM_POWER_MODES = 4; /*!< Number of power modes defined. */
|
||||
|
||||
static const int ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service.
|
||||
static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets.
|
||||
|
||||
typedef uint8_t Lock_t[16]; /* 128 bits. */
|
||||
typedef int8_t PowerLevels_t[NUM_POWER_MODES];
|
||||
|
||||
static const int URI_DATA_MAX = 18;
|
||||
typedef uint8_t UriData_t[URI_DATA_MAX];
|
||||
|
||||
struct Params_t {
|
||||
Lock_t lock;
|
||||
uint8_t uriDataLength;
|
||||
UriData_t uriData;
|
||||
uint8_t flags;
|
||||
PowerLevels_t advPowerLevels; // Current value of AdvertisedPowerLevels.
|
||||
uint8_t txPowerMode; // Firmware power levels used with setTxPower().
|
||||
uint16_t beaconPeriod;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param[ref] ble
|
||||
* BLE object for the underlying controller.
|
||||
* @param[in/out] paramsIn
|
||||
* Reference to application-visible beacon state, loaded
|
||||
* from persistent storage at startup.
|
||||
* @paramsP[in] resetToDefaultsFlag
|
||||
* Applies to the state of the 'paramsIn' parameter.
|
||||
* If true, it indicates that paramsIn is potentially
|
||||
* un-initialized, and default values should be used
|
||||
* instead. Otherwise, paramsIn overrides the defaults.
|
||||
* @param[in] defaultUriDataIn
|
||||
* Default un-encoded URI. Applies only if the resetToDefaultsFlag is true.
|
||||
* @param[in] defaultAdvPowerLevelsIn
|
||||
* Default power-levels array. Applies only if the resetToDefaultsFlag is true.
|
||||
*/
|
||||
URIBeaconConfigService(BLE &bleIn,
|
||||
Params_t ¶msIn,
|
||||
bool resetToDefaultsFlag,
|
||||
const char *defaultURIDataIn,
|
||||
PowerLevels_t &defaultAdvPowerLevelsIn) :
|
||||
ble(bleIn),
|
||||
params(paramsIn),
|
||||
defaultUriDataLength(),
|
||||
defaultUriData(),
|
||||
defaultAdvPowerLevels(defaultAdvPowerLevelsIn),
|
||||
initSucceeded(false),
|
||||
resetFlag(),
|
||||
lockedStateChar(UUID_LOCK_STATE_CHAR, &lockedState),
|
||||
lockChar(UUID_LOCK_CHAR, ¶ms.lock),
|
||||
uriDataChar(UUID_URI_DATA_CHAR, params.uriData, 0, URI_DATA_MAX,
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE),
|
||||
unlockChar(UUID_UNLOCK_CHAR, ¶ms.lock),
|
||||
flagsChar(UUID_FLAGS_CHAR, ¶ms.flags),
|
||||
advPowerLevelsChar(UUID_ADV_POWER_LEVELS_CHAR, ¶ms.advPowerLevels),
|
||||
txPowerModeChar(UUID_TX_POWER_MODE_CHAR, ¶ms.txPowerMode),
|
||||
beaconPeriodChar(UUID_BEACON_PERIOD_CHAR, ¶ms.beaconPeriod),
|
||||
resetChar(UUID_RESET_CHAR, &resetFlag) {
|
||||
|
||||
encodeURI(defaultURIDataIn, defaultUriData, defaultUriDataLength);
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!resetToDefaultsFlag && (params.uriDataLength > URI_DATA_MAX)) {
|
||||
resetToDefaultsFlag = true;
|
||||
}
|
||||
if (resetToDefaultsFlag) {
|
||||
resetToDefaults();
|
||||
} else {
|
||||
updateCharacteristicValues();
|
||||
}
|
||||
|
||||
lockedState = isLocked();
|
||||
|
||||
lockChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::lockAuthorizationCallback);
|
||||
unlockChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::unlockAuthorizationCallback);
|
||||
uriDataChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::uriDataWriteAuthorizationCallback);
|
||||
flagsChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::basicAuthorizationCallback<uint8_t>);
|
||||
advPowerLevelsChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::basicAuthorizationCallback<PowerLevels_t>);
|
||||
txPowerModeChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::powerModeAuthorizationCallback);
|
||||
beaconPeriodChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::basicAuthorizationCallback<uint16_t>);
|
||||
resetChar.setWriteAuthorizationCallback(this, &URIBeaconConfigService::basicAuthorizationCallback<uint8_t>);
|
||||
|
||||
static GattCharacteristic *charTable[] = {
|
||||
&lockedStateChar, &lockChar, &unlockChar, &uriDataChar,
|
||||
&flagsChar, &advPowerLevelsChar, &txPowerModeChar, &beaconPeriodChar, &resetChar
|
||||
};
|
||||
|
||||
GattService configService(UUID_URI_BEACON_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(configService);
|
||||
ble.onDataWritten(this, &URIBeaconConfigService::onDataWrittenCallback);
|
||||
|
||||
setupURIBeaconConfigAdvertisements(); /* Set up advertising for the config service. */
|
||||
|
||||
initSucceeded = true;
|
||||
}
|
||||
|
||||
bool configuredSuccessfully(void) const {
|
||||
return initSucceeded;
|
||||
}
|
||||
|
||||
/* Start out by advertising the config service for a limited time after
|
||||
* startup. Then switch to the normal non-connectible beacon functionality.
|
||||
*/
|
||||
void setupURIBeaconConfigAdvertisements()
|
||||
{
|
||||
const char DEVICE_NAME[] = "mUriBeacon Config";
|
||||
|
||||
ble.gap().clearAdvertisingPayload();
|
||||
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
|
||||
|
||||
// UUID is in different order in the ADV frame (!)
|
||||
uint8_t reversedServiceUUID[sizeof(UUID_URI_BEACON_SERVICE)];
|
||||
for (unsigned int i = 0; i < sizeof(UUID_URI_BEACON_SERVICE); i++) {
|
||||
reversedServiceUUID[i] = UUID_URI_BEACON_SERVICE[sizeof(UUID_URI_BEACON_SERVICE) - i - 1];
|
||||
}
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, reversedServiceUUID, sizeof(reversedServiceUUID));
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
|
||||
ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, reinterpret_cast<const uint8_t *>(&DEVICE_NAME), sizeof(DEVICE_NAME));
|
||||
ble.gap().accumulateScanResponse(GapAdvertisingData::TX_POWER_LEVEL,
|
||||
reinterpret_cast<uint8_t *>(&defaultAdvPowerLevels[URIBeaconConfigService::TX_POWER_MODE_LOW]),
|
||||
sizeof(uint8_t));
|
||||
|
||||
ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
|
||||
ble.gap().setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
|
||||
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
|
||||
ble.gap().setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC));
|
||||
}
|
||||
|
||||
/* Helper function to switch to the non-connectible normal mode for UriBeacon. This gets called after a timeout. */
|
||||
void setupURIBeaconAdvertisements()
|
||||
{
|
||||
/* Reinitialize the BLE stack. This will clear away the existing services and advertising state. */
|
||||
ble.shutdown();
|
||||
ble.init();
|
||||
|
||||
// Fields from the service.
|
||||
unsigned beaconPeriod = params.beaconPeriod;
|
||||
unsigned txPowerMode = params.txPowerMode;
|
||||
unsigned uriDataLength = params.uriDataLength;
|
||||
URIBeaconConfigService::UriData_t &uriData = params.uriData;
|
||||
URIBeaconConfigService::PowerLevels_t &advPowerLevels = params.advPowerLevels;
|
||||
uint8_t flags = params.flags;
|
||||
|
||||
extern void saveURIBeaconConfigParams(const Params_t *paramsP); /* Forward declaration; necessary to avoid a circular dependency. */
|
||||
saveURIBeaconConfigParams(¶ms);
|
||||
|
||||
ble.gap().clearAdvertisingPayload();
|
||||
ble.gap().setTxPower(params.advPowerLevels[params.txPowerMode]);
|
||||
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
|
||||
ble.gap().setAdvertisingInterval(beaconPeriod);
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_UUID, sizeof(BEACON_UUID));
|
||||
|
||||
uint8_t serviceData[SERVICE_DATA_MAX];
|
||||
unsigned serviceDataLen = 0;
|
||||
serviceData[serviceDataLen++] = BEACON_UUID[0];
|
||||
serviceData[serviceDataLen++] = BEACON_UUID[1];
|
||||
serviceData[serviceDataLen++] = flags;
|
||||
serviceData[serviceDataLen++] = advPowerLevels[txPowerMode];
|
||||
for (unsigned j = 0; j < uriDataLength; j++) {
|
||||
serviceData[serviceDataLen++] = uriData[j];
|
||||
}
|
||||
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
|
||||
}
|
||||
|
||||
private:
|
||||
// True if the lock bits are non-zero.
|
||||
bool isLocked() {
|
||||
Lock_t testLock;
|
||||
memset(testLock, 0, sizeof(Lock_t));
|
||||
return memcmp(params.lock, testLock, sizeof(Lock_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* This callback is invoked when a GATT client attempts to modify any of the
|
||||
* characteristics of this service. These attempts are also applied to
|
||||
* the internal state of this service object.
|
||||
*/
|
||||
void onDataWrittenCallback(const GattWriteCallbackParams *writeParams) {
|
||||
uint16_t handle = writeParams->handle;
|
||||
|
||||
if (handle == lockChar.getValueHandle()) {
|
||||
// Validated earlier,
|
||||
memcpy(params.lock, writeParams->data, sizeof(Lock_t));
|
||||
// Use isLocked() in case bits are being set to all zeros.
|
||||
lockedState = isLocked();
|
||||
} else if (handle == unlockChar.getValueHandle()) {
|
||||
// Validated earlier.
|
||||
memset(params.lock, 0, sizeof(Lock_t));
|
||||
lockedState = false;
|
||||
} else if (handle == uriDataChar.getValueHandle()) {
|
||||
params.uriDataLength = writeParams->len;
|
||||
memcpy(params.uriData, writeParams->data, params.uriDataLength);
|
||||
} else if (handle == flagsChar.getValueHandle()) {
|
||||
params.flags = *(writeParams->data);
|
||||
} else if (handle == advPowerLevelsChar.getValueHandle()) {
|
||||
memcpy(params.advPowerLevels, writeParams->data, sizeof(PowerLevels_t));
|
||||
} else if (handle == txPowerModeChar.getValueHandle()) {
|
||||
params.txPowerMode = *(writeParams->data);
|
||||
} else if (handle == beaconPeriodChar.getValueHandle()) {
|
||||
params.beaconPeriod = *((uint16_t *)(writeParams->data));
|
||||
|
||||
/* Remap beaconPeriod to within permissible bounds if necessary. */
|
||||
if (params.beaconPeriod != 0) {
|
||||
bool paramsUpdated = false;
|
||||
if (params.beaconPeriod < ble.gap().getMinAdvertisingInterval()) {
|
||||
params.beaconPeriod = ble.gap().getMinAdvertisingInterval();
|
||||
paramsUpdated = true;
|
||||
} else if (params.beaconPeriod > ble.gap().getMaxAdvertisingInterval()) {
|
||||
params.beaconPeriod = ble.gap().getMaxAdvertisingInterval();
|
||||
paramsUpdated = true;
|
||||
}
|
||||
if (paramsUpdated) {
|
||||
ble.gattServer().write(beaconPeriodChar.getValueHandle(), reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
} else if (handle == resetChar.getValueHandle()) {
|
||||
resetToDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the default values.
|
||||
*/
|
||||
void resetToDefaults(void) {
|
||||
lockedState = false;
|
||||
memset(params.lock, 0, sizeof(Lock_t));
|
||||
memcpy(params.uriData, defaultUriData, URI_DATA_MAX);
|
||||
params.uriDataLength = defaultUriDataLength;
|
||||
params.flags = 0;
|
||||
memcpy(params.advPowerLevels, defaultAdvPowerLevels, sizeof(PowerLevels_t));
|
||||
params.txPowerMode = TX_POWER_MODE_LOW;
|
||||
params.beaconPeriod = 1000;
|
||||
updateCharacteristicValues();
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal helper function used to update the GATT database following any
|
||||
* change to the internal state of the service object.
|
||||
*/
|
||||
void updateCharacteristicValues(void) {
|
||||
ble.gattServer().write(lockedStateChar.getValueHandle(), &lockedState, 1);
|
||||
ble.gattServer().write(uriDataChar.getValueHandle(), params.uriData, params.uriDataLength);
|
||||
ble.gattServer().write(flagsChar.getValueHandle(), ¶ms.flags, 1);
|
||||
ble.gattServer().write(beaconPeriodChar.getValueHandle(),
|
||||
reinterpret_cast<uint8_t *>(¶ms.beaconPeriod), sizeof(uint16_t));
|
||||
ble.gattServer().write(txPowerModeChar.getValueHandle(), ¶ms.txPowerMode, 1);
|
||||
ble.gattServer().write(advPowerLevelsChar.getValueHandle(),
|
||||
reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
|
||||
}
|
||||
|
||||
protected:
|
||||
void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(Lock_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void unlockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (!lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
} else if (authParams->len != sizeof(Lock_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else if (memcmp(authParams->data, params.lock, sizeof(Lock_t)) != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void uriDataWriteAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void powerModeAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(uint8_t)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else if (*((uint8_t *)authParams->data) >= NUM_POWER_MODES) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_WRITE_NOT_PERMITTED;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void basicAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
|
||||
if (lockedState) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
|
||||
} else if (authParams->len != sizeof(T)) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH;
|
||||
} else if (authParams->offset != 0) {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET;
|
||||
} else {
|
||||
authParams->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
Params_t ¶ms;
|
||||
|
||||
size_t defaultUriDataLength; // Default value that is restored on reset.
|
||||
UriData_t defaultUriData; // Default value that is restored on reset.
|
||||
PowerLevels_t &defaultAdvPowerLevels; // Default value that is restored on reset.
|
||||
|
||||
uint8_t lockedState;
|
||||
bool initSucceeded;
|
||||
uint8_t resetFlag;
|
||||
|
||||
ReadOnlyGattCharacteristic<uint8_t> lockedStateChar;
|
||||
WriteOnlyGattCharacteristic<Lock_t> lockChar;
|
||||
GattCharacteristic uriDataChar;
|
||||
WriteOnlyGattCharacteristic<Lock_t> unlockChar;
|
||||
ReadWriteGattCharacteristic<uint8_t> flagsChar;
|
||||
ReadWriteGattCharacteristic<PowerLevels_t> advPowerLevelsChar;
|
||||
ReadWriteGattCharacteristic<uint8_t> txPowerModeChar;
|
||||
ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
|
||||
WriteOnlyGattCharacteristic<uint8_t> resetChar;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Encode a human-readable URI into the binary format defined by the UriBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
|
||||
*/
|
||||
static void encodeURI(const char *uriDataIn, UriData_t uriDataOut, size_t &sizeofURIDataOut) {
|
||||
const char *prefixes[] = {
|
||||
"http://www.",
|
||||
"https://www.",
|
||||
"http://",
|
||||
"https://",
|
||||
"urn:uuid:"
|
||||
};
|
||||
const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
|
||||
const char *suffixes[] = {
|
||||
".com/",
|
||||
".org/",
|
||||
".edu/",
|
||||
".net/",
|
||||
".info/",
|
||||
".biz/",
|
||||
".gov/",
|
||||
".com",
|
||||
".org",
|
||||
".edu",
|
||||
".net",
|
||||
".info",
|
||||
".biz",
|
||||
".gov"
|
||||
};
|
||||
const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
|
||||
|
||||
sizeofURIDataOut = 0;
|
||||
memset(uriDataOut, 0, sizeof(UriData_t));
|
||||
|
||||
if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle prefix
|
||||
*/
|
||||
for (unsigned i = 0; i < NUM_PREFIXES; i++) {
|
||||
size_t prefixLen = strlen(prefixes[i]);
|
||||
if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
|
||||
uriDataOut[sizeofURIDataOut++] = i;
|
||||
uriDataIn += prefixLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle suffixes.
|
||||
*/
|
||||
while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
|
||||
/* check for suffix match */
|
||||
unsigned i;
|
||||
for (i = 0; i < NUM_SUFFIXES; i++) {
|
||||
size_t suffixLen = strlen(suffixes[i]);
|
||||
if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
|
||||
uriDataOut[sizeofURIDataOut++] = i;
|
||||
uriDataIn += suffixLen;
|
||||
break; /* From the for loop for checking against suffixes. */
|
||||
}
|
||||
}
|
||||
/* This is the default case where we've got an ordinary character that doesn't match a suffix. */
|
||||
if (i == NUM_SUFFIXES) {
|
||||
uriDataOut[sizeofURIDataOut++] = *uriDataIn;
|
||||
++uriDataIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SERVICES_URIBEACONCONFIGSERVICE_H_
|
|
@ -0,0 +1,75 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
#ifndef __BLE_IBEACON_H__
|
||||
#define __BLE_IBEACON_H__
|
||||
|
||||
#include "core_cmInstr.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class iBeacon
|
||||
* @brief iBeacon Service. This sets up a device to broadcast advertising packets to mimic an iBeacon.
|
||||
*/
|
||||
class iBeacon
|
||||
{
|
||||
public:
|
||||
typedef const uint8_t LocationUUID_t[16];
|
||||
|
||||
union Payload {
|
||||
uint8_t raw[25];
|
||||
struct {
|
||||
uint16_t companyID;
|
||||
uint8_t ID;
|
||||
uint8_t len;
|
||||
uint8_t proximityUUID[16];
|
||||
uint16_t majorNumber;
|
||||
uint16_t minorNumber;
|
||||
uint8_t txPower;
|
||||
};
|
||||
|
||||
Payload(LocationUUID_t uuid, uint16_t majNum, uint16_t minNum, uint8_t transmitPower, uint16_t companyIDIn) :
|
||||
companyID(companyIDIn), ID(0x02), len(0x15), majorNumber(__REV16(majNum)), minorNumber(__REV16(minNum)), txPower(transmitPower)
|
||||
{
|
||||
memcpy(proximityUUID, uuid, sizeof(LocationUUID_t));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
iBeacon(BLE &_ble,
|
||||
LocationUUID_t uuid,
|
||||
uint16_t majNum,
|
||||
uint16_t minNum,
|
||||
uint8_t txP = 0xC8,
|
||||
uint16_t compID = 0x004C) :
|
||||
ble(_ble), data(uuid, majNum, minNum, txP, compID)
|
||||
{
|
||||
// Generate the 0x020106 part of the iBeacon Prefix.
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE );
|
||||
// Generate the 0x1AFF part of the iBeacon Prefix.
|
||||
ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data.raw, sizeof(data.raw));
|
||||
|
||||
// Set advertising type.
|
||||
ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
|
||||
}
|
||||
|
||||
protected:
|
||||
BLE &ble;
|
||||
Payload data;
|
||||
};
|
||||
|
||||
typedef iBeacon iBeaconService; /* This type-alias is deprecated. Please use iBeacon directly. This alias may be dropped from a future release. */
|
||||
|
||||
#endif //__BLE_IBEACON_H__
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"name": "ble",
|
||||
"version": "2.6.0",
|
||||
"description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.",
|
||||
"keywords": [
|
||||
"Bluetooth",
|
||||
"BLE",
|
||||
"mbed",
|
||||
"mbed-official"
|
||||
],
|
||||
"author": "Rohit Grover",
|
||||
"repository": {
|
||||
"url": "https://github.com/ARMmbed/ble.git",
|
||||
"type": "git"
|
||||
},
|
||||
"homepage": "https://developer.mbed.org/teams/Bluetooth-Low-Energy/",
|
||||
"licenses": [
|
||||
{
|
||||
"url": "https://spdx.org/licenses/Apache-2.0",
|
||||
"type": "Apache-2.0"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"targetDependencies": {
|
||||
"st-ble-shield": {
|
||||
"x-nucleo-idb0xa1": "^2.0.0"
|
||||
},
|
||||
"nrf51822": {
|
||||
"ble-nrf51822": "^2.2.8"
|
||||
},
|
||||
"nrf52832": {
|
||||
"ble-nrf52832": "ARMmbed/ble-nrf52832"
|
||||
},
|
||||
"cordio": {
|
||||
"ble-wicentric": "~0.0.4"
|
||||
},
|
||||
"mbed-classic": {
|
||||
"mbed-classic": "~0.0.1"
|
||||
},
|
||||
"mbed-os": {
|
||||
"mbed-drivers": "*",
|
||||
"compiler-polyfill": "^1.2.1"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/* 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 "ble/BLE.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
|
||||
#if defined(TARGET_OTA_ENABLED)
|
||||
#include "ble/services/DFUService.h"
|
||||
#endif
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include <minar/minar.h>
|
||||
#endif
|
||||
|
||||
ble_error_t
|
||||
BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
|
||||
{
|
||||
ble_error_t err = transport->init(instanceID, callback);
|
||||
if (err != BLE_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Platforms enabled for DFU should introduce the DFU Service into
|
||||
* applications automatically. */
|
||||
#if defined(TARGET_OTA_ENABLED)
|
||||
static DFUService dfu(*this); // defined static so that the object remains alive
|
||||
#endif // TARGET_OTA_ENABLED
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* BLE::Instance() and BLE constructor rely upon a static array of initializers
|
||||
* to create actual BLE transport instances. A description of these instances
|
||||
* and initializers is supposed to be put in some .json file contributing to
|
||||
* yotta's configuration (typically in the target definition described by
|
||||
* target.json). Here's a sample:
|
||||
*
|
||||
* "config": {
|
||||
* ...
|
||||
* "ble_instances": {
|
||||
* "count": 1,
|
||||
* "0" : {
|
||||
* "initializer" : "createBLEInstance"
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* The following macros result in translating the above config into a static
|
||||
* array: instanceConstructors.
|
||||
*/
|
||||
#ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
|
||||
#define CONCATENATE(A, B) A ## B
|
||||
#define EXPAND(X) X /* this adds a level of indirection needed to allow macro-expansion following a token-paste operation (see use of CONCATENATE() below). */
|
||||
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
|
||||
/* ... add more of the above if ever needed */
|
||||
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
|
||||
#elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
|
||||
/*
|
||||
* The following applies when building without yotta. By default BLE_API provides
|
||||
* a trivial initializer list containing a single constructor: createBLEInstance.
|
||||
* This may be overridden.
|
||||
*/
|
||||
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance
|
||||
#endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */
|
||||
|
||||
typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
|
||||
static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
|
||||
#ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
|
||||
INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
|
||||
#else
|
||||
INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
|
||||
#endif
|
||||
};
|
||||
|
||||
BLE &
|
||||
BLE::Instance(InstanceID_t id)
|
||||
{
|
||||
static BLE *singletons[NUM_INSTANCES];
|
||||
if (id < NUM_INSTANCES) {
|
||||
if (singletons[id] == NULL) {
|
||||
singletons[id] = new BLE(id); /* This object will never be freed. */
|
||||
}
|
||||
|
||||
return *singletons[id];
|
||||
}
|
||||
|
||||
/* we come here only in the case of a bad interfaceID. */
|
||||
static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
|
||||
return badSingleton;
|
||||
}
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
|
||||
minar::Scheduler::postCallback(¶ms->ble, &BLE::processEvents);
|
||||
}
|
||||
#else
|
||||
#define defaultSchedulingCallback NULL
|
||||
#endif
|
||||
|
||||
|
||||
BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
|
||||
whenEventsToProcess(defaultSchedulingCallback)
|
||||
{
|
||||
static BLEInstanceBase *transportInstances[NUM_INSTANCES];
|
||||
|
||||
if (instanceID < NUM_INSTANCES) {
|
||||
if (!transportInstances[instanceID]) {
|
||||
transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
|
||||
}
|
||||
transport = transportInstances[instanceID];
|
||||
} else {
|
||||
transport = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool BLE::hasInitialized(void) const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->hasInitialized();
|
||||
}
|
||||
|
||||
ble_error_t BLE::shutdown(void)
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->shutdown();
|
||||
}
|
||||
|
||||
const char *BLE::getVersion(void)
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getVersion();
|
||||
}
|
||||
|
||||
const Gap &BLE::gap() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGap();
|
||||
}
|
||||
|
||||
Gap &BLE::gap()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGap();
|
||||
}
|
||||
|
||||
const GattServer& BLE::gattServer() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattServer();
|
||||
}
|
||||
|
||||
GattServer& BLE::gattServer()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattServer();
|
||||
}
|
||||
|
||||
const GattClient& BLE::gattClient() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattClient();
|
||||
}
|
||||
|
||||
GattClient& BLE::gattClient()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattClient();
|
||||
}
|
||||
|
||||
const SecurityManager& BLE::securityManager() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
|
||||
SecurityManager& BLE::securityManager()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
|
||||
void BLE::waitForEvent(void)
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
transport->waitForEvent();
|
||||
}
|
||||
|
||||
void BLE::processEvents()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
transport->processEvents();
|
||||
}
|
||||
|
||||
void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t& callback)
|
||||
{
|
||||
whenEventsToProcess = callback;
|
||||
}
|
||||
|
||||
void BLE::signalEventsToProcess()
|
||||
{
|
||||
if (whenEventsToProcess) {
|
||||
OnEventsToProcessCallbackContext params = {
|
||||
*this
|
||||
};
|
||||
whenEventsToProcess(¶ms);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* 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 "ble/BLE.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
|
||||
BLEInstanceBase::~BLEInstanceBase()
|
||||
{
|
||||
// empty destructor
|
||||
}
|
||||
|
||||
void BLEInstanceBase::signalEventsToProcess(BLE::InstanceID_t id)
|
||||
{
|
||||
BLE::Instance(id).signalEventsToProcess();
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#include "ble/DiscoveredCharacteristic.h"
|
||||
#include "ble/GattClient.h"
|
||||
|
||||
ble_error_t
|
||||
DiscoveredCharacteristic::read(uint16_t offset) const
|
||||
{
|
||||
if (!props.read()) {
|
||||
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||
}
|
||||
|
||||
if (!gattc) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return gattc->read(connHandle, valueHandle, offset);
|
||||
}
|
||||
|
||||
struct OneShotReadCallback {
|
||||
static void launch(GattClient* client, Gap::Handle_t connHandle,
|
||||
GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) {
|
||||
OneShotReadCallback* oneShot = new OneShotReadCallback(client, connHandle, handle, cb);
|
||||
oneShot->attach();
|
||||
// delete will be made when this callback is called
|
||||
}
|
||||
|
||||
private:
|
||||
OneShotReadCallback(GattClient* client, Gap::Handle_t connHandle,
|
||||
GattAttribute::Handle_t handle, const GattClient::ReadCallback_t& cb) :
|
||||
_client(client),
|
||||
_connHandle(connHandle),
|
||||
_handle(handle),
|
||||
_callback(cb) { }
|
||||
|
||||
void attach() {
|
||||
_client->onDataRead(makeFunctionPointer(this, &OneShotReadCallback::call));
|
||||
}
|
||||
|
||||
void call(const GattReadCallbackParams* params) {
|
||||
// verifiy that it is the right characteristic on the right connection
|
||||
if (params->connHandle == _connHandle && params->handle == _handle) {
|
||||
_callback(params);
|
||||
_client->onDataRead().detach(makeFunctionPointer(this, &OneShotReadCallback::call));
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
GattClient* _client;
|
||||
Gap::Handle_t _connHandle;
|
||||
GattAttribute::Handle_t _handle;
|
||||
GattClient::ReadCallback_t _callback;
|
||||
};
|
||||
|
||||
ble_error_t DiscoveredCharacteristic::read(uint16_t offset, const GattClient::ReadCallback_t& onRead) const {
|
||||
ble_error_t error = read(offset);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
OneShotReadCallback::launch(gattc, connHandle, valueHandle, onRead);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
DiscoveredCharacteristic::write(uint16_t length, const uint8_t *value) const
|
||||
{
|
||||
if (!props.write()) {
|
||||
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||
}
|
||||
|
||||
if (!gattc) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return gattc->write(GattClient::GATT_OP_WRITE_REQ, connHandle, valueHandle, length, value);
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
DiscoveredCharacteristic::writeWoResponse(uint16_t length, const uint8_t *value) const
|
||||
{
|
||||
if (!props.writeWoResp()) {
|
||||
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||
}
|
||||
|
||||
if (!gattc) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return gattc->write(GattClient::GATT_OP_WRITE_CMD, connHandle, valueHandle, length, value);
|
||||
}
|
||||
|
||||
struct OneShotWriteCallback {
|
||||
static void launch(GattClient* client, Gap::Handle_t connHandle,
|
||||
GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) {
|
||||
OneShotWriteCallback* oneShot = new OneShotWriteCallback(client, connHandle, handle, cb);
|
||||
oneShot->attach();
|
||||
// delete will be made when this callback is called
|
||||
}
|
||||
|
||||
private:
|
||||
OneShotWriteCallback(GattClient* client, Gap::Handle_t connHandle,
|
||||
GattAttribute::Handle_t handle, const GattClient::WriteCallback_t& cb) :
|
||||
_client(client),
|
||||
_connHandle(connHandle),
|
||||
_handle(handle),
|
||||
_callback(cb) { }
|
||||
|
||||
void attach() {
|
||||
_client->onDataWritten(makeFunctionPointer(this, &OneShotWriteCallback::call));
|
||||
}
|
||||
|
||||
void call(const GattWriteCallbackParams* params) {
|
||||
// verifiy that it is the right characteristic on the right connection
|
||||
if (params->connHandle == _connHandle && params->handle == _handle) {
|
||||
_callback(params);
|
||||
_client->onDataWritten().detach(makeFunctionPointer(this, &OneShotWriteCallback::call));
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
GattClient* _client;
|
||||
Gap::Handle_t _connHandle;
|
||||
GattAttribute::Handle_t _handle;
|
||||
GattClient::WriteCallback_t _callback;
|
||||
};
|
||||
|
||||
ble_error_t DiscoveredCharacteristic::write(uint16_t length, const uint8_t *value, const GattClient::WriteCallback_t& onRead) const {
|
||||
ble_error_t error = write(length, value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
OneShotWriteCallback::launch(gattc, connHandle, valueHandle, onRead);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ble_error_t DiscoveredCharacteristic::discoverDescriptors(
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& onCharacteristicDiscovered,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& onTermination) const {
|
||||
|
||||
if(!gattc) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ble_error_t err = gattc->discoverCharacteristicDescriptors(
|
||||
*this, onCharacteristicDiscovered, onTermination
|
||||
);
|
||||
|
||||
return err;
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#include "ble/Gap.h"
|
||||
#include "ble/GapScanningParams.h"
|
||||
|
||||
GapScanningParams::GapScanningParams(uint16_t interval, uint16_t window, uint16_t timeout, bool activeScanning) :
|
||||
_interval(MSEC_TO_SCAN_DURATION_UNITS(interval)),
|
||||
_window(MSEC_TO_SCAN_DURATION_UNITS(window)),
|
||||
_timeout(timeout),
|
||||
_activeScanning(activeScanning) {
|
||||
/* stay within limits */
|
||||
if (_interval < SCAN_INTERVAL_MIN) {
|
||||
_interval = SCAN_INTERVAL_MIN;
|
||||
}
|
||||
if (_interval > SCAN_INTERVAL_MAX) {
|
||||
_interval = SCAN_INTERVAL_MAX;
|
||||
}
|
||||
if (_window < SCAN_WINDOW_MIN) {
|
||||
_window = SCAN_WINDOW_MIN;
|
||||
}
|
||||
if (_window > SCAN_WINDOW_MAX) {
|
||||
_window = SCAN_WINDOW_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
GapScanningParams::setInterval(uint16_t newIntervalInMS)
|
||||
{
|
||||
uint16_t newInterval = MSEC_TO_SCAN_DURATION_UNITS(newIntervalInMS);
|
||||
if ((newInterval >= SCAN_INTERVAL_MIN) && (newInterval < SCAN_INTERVAL_MAX)) {
|
||||
_interval = newInterval;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
GapScanningParams::setWindow(uint16_t newWindowInMS)
|
||||
{
|
||||
uint16_t newWindow = MSEC_TO_SCAN_DURATION_UNITS(newWindowInMS);
|
||||
if ((newWindow >= SCAN_WINDOW_MIN) && (newWindow < SCAN_WINDOW_MAX)) {
|
||||
_window = newWindow;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
GapScanningParams::setTimeout(uint16_t newTimeout)
|
||||
{
|
||||
_timeout = newTimeout;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
GapScanningParams::setActiveScanning(bool activeScanning)
|
||||
{
|
||||
_activeScanning = activeScanning;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* 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 TARGET_NRF51822 /* DFU only supported on nrf51 platforms */
|
||||
|
||||
#include "ble/services/DFUService.h"
|
||||
|
||||
const uint8_t DFUServiceBaseUUID[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0xEF, 0xDE,
|
||||
0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23,
|
||||
};
|
||||
const uint16_t DFUServiceShortUUID = 0x1530;
|
||||
const uint16_t DFUServiceControlCharacteristicShortUUID = 0x1531;
|
||||
const uint16_t DFUServicePacketCharacteristicShortUUID = 0x1532;
|
||||
|
||||
const uint8_t DFUServiceUUID[] = {
|
||||
0x00, 0x00, (uint8_t)(DFUServiceShortUUID >> 8), (uint8_t)(DFUServiceShortUUID & 0xFF), 0x12, 0x12, 0xEF, 0xDE,
|
||||
0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23,
|
||||
};
|
||||
const uint8_t DFUServiceControlCharacteristicUUID[] = {
|
||||
0x00, 0x00, (uint8_t)(DFUServiceControlCharacteristicShortUUID >> 8), (uint8_t)(DFUServiceControlCharacteristicShortUUID & 0xFF), 0x12, 0x12, 0xEF, 0xDE,
|
||||
0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23,
|
||||
};
|
||||
const uint8_t DFUServicePacketCharacteristicUUID[] = {
|
||||
0x00, 0x00, (uint8_t)(DFUServicePacketCharacteristicShortUUID >> 8), (uint8_t)(DFUServicePacketCharacteristicShortUUID & 0xFF), 0x12, 0x12, 0xEF, 0xDE,
|
||||
0x15, 0x23, 0x78, 0x5F, 0xEA, 0xBC, 0xD1, 0x23,
|
||||
};
|
||||
|
||||
DFUService::ResetPrepare_t DFUService::handoverCallback = NULL;
|
||||
|
||||
#endif /* #ifdef TARGET_NRF51822 */
|
|
@ -0,0 +1,41 @@
|
|||
/* 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 "ble/services/UARTService.h"
|
||||
|
||||
const uint8_t UARTServiceBaseUUID[UUID::LENGTH_OF_LONG_UUID] = {
|
||||
0x6E, 0x40, 0x00, 0x00, 0xB5, 0xA3, 0xF3, 0x93,
|
||||
0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E,
|
||||
};
|
||||
const uint16_t UARTServiceShortUUID = 0x0001;
|
||||
const uint16_t UARTServiceTXCharacteristicShortUUID = 0x0002;
|
||||
const uint16_t UARTServiceRXCharacteristicShortUUID = 0x0003;
|
||||
const uint8_t UARTServiceUUID[UUID::LENGTH_OF_LONG_UUID] = {
|
||||
0x6E, 0x40, (uint8_t)(UARTServiceShortUUID >> 8), (uint8_t)(UARTServiceShortUUID & 0xFF), 0xB5, 0xA3, 0xF3, 0x93,
|
||||
0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E,
|
||||
};
|
||||
const uint8_t UARTServiceUUID_reversed[UUID::LENGTH_OF_LONG_UUID] = {
|
||||
0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
|
||||
0x93, 0xF3, 0xA3, 0xB5, (uint8_t)(UARTServiceShortUUID & 0xFF), (uint8_t)(UARTServiceShortUUID >> 8), 0x40, 0x6E
|
||||
};
|
||||
const uint8_t UARTServiceTXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID] = {
|
||||
0x6E, 0x40, (uint8_t)(UARTServiceTXCharacteristicShortUUID >> 8), (uint8_t)(UARTServiceTXCharacteristicShortUUID & 0xFF), 0xB5, 0xA3, 0xF3, 0x93,
|
||||
0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E,
|
||||
};
|
||||
const uint8_t UARTServiceRXCharacteristicUUID[UUID::LENGTH_OF_LONG_UUID] = {
|
||||
0x6E, 0x40, (uint8_t)(UARTServiceRXCharacteristicShortUUID >> 8), (uint8_t)(UARTServiceRXCharacteristicShortUUID & 0xFF), 0xB5, 0xA3, 0xF3, 0x93,
|
||||
0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E,
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
/* 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 "ble/services/URIBeaconConfigService.h"
|
||||
|
||||
#define UUID_URI_BEACON(FIRST, SECOND) { \
|
||||
0xee, 0x0c, FIRST, SECOND, 0x87, 0x86, 0x40, 0xba, \
|
||||
0xab, 0x96, 0x99, 0xb9, 0x1a, 0xc9, 0x81, 0xd8, \
|
||||
}
|
||||
|
||||
const uint8_t UUID_URI_BEACON_SERVICE[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x80);
|
||||
const uint8_t UUID_LOCK_STATE_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x81);
|
||||
const uint8_t UUID_LOCK_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x82);
|
||||
const uint8_t UUID_UNLOCK_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x83);
|
||||
const uint8_t UUID_URI_DATA_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x84);
|
||||
const uint8_t UUID_FLAGS_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x85);
|
||||
const uint8_t UUID_ADV_POWER_LEVELS_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x86);
|
||||
const uint8_t UUID_TX_POWER_MODE_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x87);
|
||||
const uint8_t UUID_BEACON_PERIOD_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x88);
|
||||
const uint8_t UUID_RESET_CHAR[UUID::LENGTH_OF_LONG_UUID] = UUID_URI_BEACON(0x20, 0x89);
|
||||
|
||||
const uint8_t BEACON_UUID[sizeof(UUID::ShortUUIDBytes_t)] = {0xD8, 0xFE};
|
Loading…
Reference in New Issue