mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-24 23:07:17 +00:00
commit
99d40825f9
1
lib/libesp32_div/NimBLE-Arduino/.gitignore
vendored
Normal file
1
lib/libesp32_div/NimBLE-Arduino/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
docs/doxydocs
|
@ -2,6 +2,41 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.4.0] - 2022-07-10
|
||||
|
||||
### Fixed
|
||||
- Fixed missing data from long notification values.
|
||||
- Fixed NimbleCharacteristicCallbacks::onRead not being called when a non-long read command is received.
|
||||
|
||||
### Changed
|
||||
- Updated NimBLE core to use the v1.4.0 branch of esp-nimble.
|
||||
- AD flags are no longer set in the advertisements of non-connectable beacons, freeing up 3 bytes of advertisement room.
|
||||
|
||||
### Added
|
||||
- Preliminary support for non-esp devices, NRF51 and NRF52 devices supported with [n-able arduino core](https://github.com/h2zero/n-able-Arduino)
|
||||
- Alias added for `NimBLEServerCallbacks::onMTUChange` to `onMtuChanged` in order to support porting code from original library.
|
||||
- `NimBLEAttValue` Class added to reduce and control RAM footprint of characteristic/descriptor values and support conversions from Arduino Strings and many other data types.
|
||||
- Bluetooth 5 extended advertising support for capable devices. CODED Phy, 2M Phy, extended advertising data, and multi-advertising are supported, periodic advertising will be implemented in the future.
|
||||
|
||||
## [1.3.8] - 2022-04-27
|
||||
|
||||
### Fixed
|
||||
- Fix compile error with ESP32S3.
|
||||
- Prevent a potential crash when retrieving characteristics from a service if the result was successful but no characteristics found.
|
||||
|
||||
### Changed
|
||||
- Save resources when retrieving descriptors if the characteristic handle is the same as the end handle (no descriptors).
|
||||
- Subscribing to characteristic notifications/indications will now always use write with response, as per BLE specifications.
|
||||
- `NimBLEClient::discoverAttributes` now returns a bool value to indicate success/failure
|
||||
|
||||
## [1.3.7] - 2022-02-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- Crash when retrieving an attribute that does not exist on the peer.
|
||||
- Memory leak when deleting client instances.
|
||||
- Compilation errors for esp32s3
|
||||
|
||||
## [1.3.6] - 2022-01-18
|
||||
|
||||
### Changed
|
||||
@ -11,7 +46,7 @@ All notable changes to this project will be documented in this file.
|
||||
- Memory leak when services are changed on server devices.
|
||||
- Rare crashing that occurs when BLE commands are sent from ISR context using IPC.
|
||||
- Crashing caused by uninitialized disconnect timer in client.
|
||||
- Potential crash due to unintialized advertising callback pointer.
|
||||
- Potential crash due to uninitialized advertising callback pointer.
|
||||
|
||||
## [1.3.5] - 2022-01-14
|
||||
|
||||
@ -48,7 +83,7 @@ All notable changes to this project will be documented in this file.
|
||||
## [1.3.0] - 2021-08-02
|
||||
|
||||
### Added
|
||||
- `NimBLECharacteristic::removeDescriptor`: Dynamically remove a descriptor from a characterisic. Takes effect after all connections are closed and sends a service changed indication.
|
||||
- `NimBLECharacteristic::removeDescriptor`: Dynamically remove a descriptor from a characteristic. Takes effect after all connections are closed and sends a service changed indication.
|
||||
- `NimBLEService::removeCharacteristic`: Dynamically remove a characteristic from a service. Takes effect after all connections are closed and sends a service changed indication
|
||||
- `NimBLEServerCallbacks::onMTUChange`: This is callback is called when the MTU is updated after connection with a client.
|
||||
- ESP32C3 support
|
||||
@ -79,12 +114,12 @@ All notable changes to this project will be documented in this file.
|
||||
### Fixed
|
||||
- `NimBLECharacteristicCallbacks::onSubscribe` Is now called after the connection is added to the vector.
|
||||
- Corrected bonding failure when reinitializing the BLE stack.
|
||||
- Writing to a characterisic with a std::string value now correctly writes values with null characters.
|
||||
- Retrieving remote descriptors now uses the characterisic end handle correctly.
|
||||
- Writing to a characteristic with a std::string value now correctly writes values with null characters.
|
||||
- Retrieving remote descriptors now uses the characteristic end handle correctly.
|
||||
- Missing data in long writes to remote descriptors.
|
||||
- Hanging on task notification when sending an indication from the characteristic callback.
|
||||
- BLE controller memory could be released when using Arduino as a component.
|
||||
- Complile errors with NimBLE release 1.3.0.
|
||||
- Compile errors with NimBLE release 1.3.0.
|
||||
|
||||
## [1.2.0] - 2021-02-08
|
||||
|
||||
@ -97,7 +132,7 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
- `NimBLEService::getCharacteristicByHandle`: Get a pointer to the characteristic object with the specified handle.
|
||||
|
||||
- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
|
||||
- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
|
||||
Overloads to get a vector containing pointers to all the characteristics in a service with the UUID. (supports multiple same UUID's in a service)
|
||||
- `NimBLEService::getCharacteristics(const char *uuid)`
|
||||
- `NimBLEService::getCharacteristics(const NimBLEUUID &uuid)`
|
||||
@ -139,12 +174,12 @@ Overloads to get a vector containing pointers to all the characteristics in a se
|
||||
|
||||
- `NimBLEAdvertising` Transmission power is no longer advertised by default and can be added to the advertisement by calling `NimBLEAdvertising::addTxPower`
|
||||
|
||||
- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisment.
|
||||
- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisement.
|
||||
|
||||
- `NimBLEScan` Now uses the controller duplicate filter.
|
||||
- `NimBLEScan` Now uses the controller duplicate filter.
|
||||
|
||||
- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
|
||||
Instead the data will be parsed on-demand when the user application asks for specific data.
|
||||
- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
|
||||
Instead the data will be parsed on-demand when the user application asks for specific data.
|
||||
|
||||
### Fixed
|
||||
- `NimBLEHIDDevice` Characteristics now use encryption, this resolves an issue with communicating with devices requiring encryption for HID devices.
|
||||
@ -153,84 +188,84 @@ Instead the data will be parsed on-demand when the user application asks for spe
|
||||
## [1.1.0] - 2021-01-20
|
||||
|
||||
### Added
|
||||
- `NimBLEDevice::setOwnAddrType` added to enable the use of random and random-resolvable addresses, by asukiaaa
|
||||
- `NimBLEDevice::setOwnAddrType` added to enable the use of random and random-resolvable addresses, by asukiaaa
|
||||
|
||||
- New examples for securing and authenticating client/server connections, by mblasee.
|
||||
- New examples for securing and authenticating client/server connections, by mblasee.
|
||||
|
||||
- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
|
||||
- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
|
||||
|
||||
- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
|
||||
- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
|
||||
|
||||
- `NimBLEClient::setValue` Now takes an extra bool parameter `response` to enable the use of write with response (default = false).
|
||||
- `NimBLEClient::setValue` Now takes an extra bool parameter `response` to enable the use of write with response (default = false).
|
||||
|
||||
- `NimBLEClient::getCharacteristic(uint16_t handle)` Enabling the use of the characteristic handle to be used to find
|
||||
the NimBLERemoteCharacteristic object.
|
||||
- `NimBLEClient::getCharacteristic(uint16_t handle)` Enabling the use of the characteristic handle to be used to find
|
||||
the NimBLERemoteCharacteristic object.
|
||||
|
||||
- `NimBLEHIDDevice` class added by wakwak-koba.
|
||||
- `NimBLEHIDDevice` class added by wakwak-koba.
|
||||
|
||||
- `NimBLEServerCallbacks::onDisconnect` overloaded callback added to provide a ble_gap_conn_desc parameter for the application
|
||||
to obtain information about the disconnected client.
|
||||
- `NimBLEServerCallbacks::onDisconnect` overloaded callback added to provide a ble_gap_conn_desc parameter for the application
|
||||
to obtain information about the disconnected client.
|
||||
|
||||
- Conditional checks in `nimconfig.h` for command line defined macros to support platformio config settings.
|
||||
- Conditional checks in `nimconfig.h` for command line defined macros to support platformio config settings.
|
||||
|
||||
### Changed
|
||||
- `NimBLEAdvertising::start` now returns a bool value to indicate success/failure.
|
||||
- `NimBLEAdvertising::start` now returns a bool value to indicate success/failure.
|
||||
|
||||
- Some asserts were removed in `NimBLEAdvertising::start` and replaced with better return code handling and logging.
|
||||
- Some asserts were removed in `NimBLEAdvertising::start` and replaced with better return code handling and logging.
|
||||
|
||||
- If a host reset event occurs, scanning and advertising will now only be restarted if their previous duration was indefinite.
|
||||
- If a host reset event occurs, scanning and advertising will now only be restarted if their previous duration was indefinite.
|
||||
|
||||
- `NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::registerForNotify` will now set the callback
|
||||
regardless of the existance of the CCCD and return true unless the descriptor write operation failed.
|
||||
regardless of the existence of the CCCD and return true unless the descriptor write operation failed.
|
||||
|
||||
- Advertising tx power level is now sent in the advertisement packet instead of scan response.
|
||||
- Advertising tx power level is now sent in the advertisement packet instead of scan response.
|
||||
|
||||
- `NimBLEScan` When the scan ends the scan stopped flag is now set before calling the scan complete callback (if used)
|
||||
this allows the starting of a new scan from the callback function.
|
||||
- `NimBLEScan` When the scan ends the scan stopped flag is now set before calling the scan complete callback (if used)
|
||||
this allows the starting of a new scan from the callback function.
|
||||
|
||||
### Fixed
|
||||
- Sometimes `NimBLEClient::connect` would hang on the task block if no event arrived to unblock.
|
||||
A time limit has been added to timeout appropriately.
|
||||
- Sometimes `NimBLEClient::connect` would hang on the task block if no event arrived to unblock.
|
||||
A time limit has been added to timeout appropriately.
|
||||
|
||||
- When getting descriptors for a characterisic the end handle of the service was used as a proxy for the characteristic end
|
||||
handle. This would be rejected by some devices and has been changed to use the next characteristic handle as the end when possible.
|
||||
- When getting descriptors for a characteristic the end handle of the service was used as a proxy for the characteristic end
|
||||
handle. This would be rejected by some devices and has been changed to use the next characteristic handle as the end when possible.
|
||||
|
||||
- An exception could occur when deleting a client instance if a notification arrived while the attribute vectors were being
|
||||
deleted. A flag has been added to prevent this.
|
||||
|
||||
- An exception could occur after a host reset event when the host re-synced if the tasks that were stopped during the event did
|
||||
not finish processing. A yield has been added after re-syncing to allow tasks to finish before proceeding.
|
||||
|
||||
- Occasionally the controller would fail to send a disconnected event causing the client to indicate it is connected
|
||||
and would be unable to reconnect. A timer has been added to reset the host/controller if it expires.
|
||||
|
||||
- Occasionally the call to start scanning would get stuck in a loop on BLE_HS_EBUSY, this loop has been removed.
|
||||
- An exception could occur when deleting a client instance if a notification arrived while the attribute vectors were being
|
||||
deleted. A flag has been added to prevent this.
|
||||
|
||||
- 16bit and 32bit UUID's in some cases were not discovered or compared correctly if the device
|
||||
advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
|
||||
|
||||
- `FreeRTOS` compile errors resolved in latest Ardruino core and IDF v3.3.
|
||||
- An exception could occur after a host reset event when the host re-synced if the tasks that were stopped during the event did
|
||||
not finish processing. A yield has been added after re-syncing to allow tasks to finish before proceeding.
|
||||
|
||||
- Multiple instances of `time()` called inside critical sections caused sporadic crashes, these have been moved out of critical regions.
|
||||
- Occasionally the controller would fail to send a disconnected event causing the client to indicate it is connected
|
||||
and would be unable to reconnect. A timer has been added to reset the host/controller if it expires.
|
||||
|
||||
- Advertisement type now correctly set when using non-connectable (advertiser only) mode.
|
||||
- Occasionally the call to start scanning would get stuck in a loop on BLE_HS_EBUSY, this loop has been removed.
|
||||
|
||||
- Advertising payload length correction, now accounts for appearance.
|
||||
- 16bit and 32bit UUID's in some cases were not discovered or compared correctly if the device
|
||||
advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
|
||||
|
||||
- (Arduino) Ensure controller mode is set to BLE Only.
|
||||
- `FreeRTOS` compile errors resolved in latest Arduino core and IDF v3.3.
|
||||
|
||||
- Multiple instances of `time()` called inside critical sections caused sporadic crashes, these have been moved out of critical regions.
|
||||
|
||||
- Advertisement type now correctly set when using non-connectable (advertiser only) mode.
|
||||
|
||||
- Advertising payload length correction, now accounts for appearance.
|
||||
|
||||
- (Arduino) Ensure controller mode is set to BLE Only.
|
||||
|
||||
|
||||
## [1.0.2] - 2020-09-13
|
||||
|
||||
### Changed
|
||||
|
||||
- `NimBLEAdvertising::start` Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a
|
||||
callback that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
- `NimBLEAdvertising::start` Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a
|
||||
callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
- (Arduino) Maximum BLE connections can now be altered by only changing the value of `CONFIG_BT_NIMBLE_MAX_CONNECTIONS` in `nimconfig.h`.
|
||||
Any changes to the controller max connection settings in `sdkconfig.h` will now have no effect when using this library.
|
||||
|
||||
- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
|
||||
- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
|
||||
a task running on core 0 (same as the controller) has been implemented. This improves response times and reliability for all BLE functions.
|
||||
|
||||
|
||||
|
@ -1,63 +1,50 @@
|
||||
[Latest release 
|
||||
](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
|
||||
](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
|
||||
|
||||
Need help? Have questions or suggestions? Join the [](https://gitter.im/NimBLE-Arduino/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
Need help? Have questions or suggestions? Join the [](https://gitter.im/NimBLE-Arduino/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
<br/>
|
||||
|
||||
# NimBLE-Arduino
|
||||
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
||||
A fork of the NimBLE stack refactored for compilation in the Ardruino IDE.
|
||||
|
||||
**Note for IDF users: This repo will not compile correctly in ESP-IDF. An ESP-IDF component version of this library can be [found here.](https://github.com/h2zero/esp-nimble-cpp)**
|
||||
**As of release 1.4.0 Nordic Semiconductor nRF51 and nRF52 series devices are now supported**
|
||||
|
||||
This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared
|
||||
with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original
|
||||
library but refactored to use the NimBLE stack. In addition, this library will be more actively developed and maintained
|
||||
to provide improved capabilites and stability over the original.
|
||||
## Supported MCU's
|
||||
- Espressif: ESP32, ESP32C3, ESP32S3
|
||||
- Nordic: nRF51, nRF52 series (**Requires** using [n-able arduino core](https://github.com/h2zero/n-able-Arduino))
|
||||
|
||||
**Note for ESP-IDF users: This repo will not compile correctly in ESP-IDF. An ESP-IDF component version of this library can be [found here.](https://github.com/h2zero/esp-nimble-cpp)**
|
||||
|
||||
This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original library but refactored to use the NimBLE stack. In addition, this library will be more actively developed and maintained to provide improved capabilities and stability over the original.
|
||||
<br/>
|
||||
|
||||
## Resource use improvement
|
||||
For Nordic devices, this library provides access to a completely open source and configurable BLE stack. No softdevice to work around, allowing for full debugging and resource management, continuous updates, with a cross platform API.
|
||||
|
||||
### (Original) BLE_client example comparison (Debug):
|
||||
#### Arduino BLE Library
|
||||
Sketch uses **1216377** bytes (58%) of program storage space.
|
||||
Memory after connection: Free Heap: **171548**
|
||||
|
||||
#### NimBLE-Arduino library
|
||||
Sketch uses **617256** bytes (29%) of program storage space.
|
||||
Memory after connection: Free Heap: **270336**
|
||||
***
|
||||
### (Original) BLE_notify example comparison (Debug):
|
||||
#### Arduino BLE Library
|
||||
Sketch uses **1208409** bytes (57%) of program storage space.
|
||||
Memory after connection: Free Heap: **173300**
|
||||
|
||||
#### NimBLE-Arduino library
|
||||
Sketch uses **603432** bytes (28%) of program storage space.
|
||||
Memory after connection: Free Heap: **269792**
|
||||
|
||||
**As shown: there is nearly a 50% reduction in flash use and approx. 100kB less ram consumed!**
|
||||
<br/>
|
||||
|
||||
# Installation
|
||||
**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
|
||||
# Arduino installation
|
||||
**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries`, search for NimBLE and install.
|
||||
|
||||
**Alternatively:** Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
|
||||
|
||||
`#include "NimBLEDevice.h"` at the beginning of your sketch.
|
||||
|
||||
Tested and working with esp32-arduino in Arduino IDE and platform IO.
|
||||
<br/>
|
||||
# Platformio installation
|
||||
* Open platformio.ini, a project configuration file located in the root of PlatformIO project.
|
||||
* Add the following line to the lib_deps option of [env:] section:
|
||||
```
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
```
|
||||
* Build a project, PlatformIO will automatically install dependencies.
|
||||
|
||||
# Using
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
|
||||
If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
|
||||
If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
|
||||
|
||||
If you are familiar with the original library, see: [The migration guide](docs/Migration_guide.md) for details about breaking changes and migration.
|
||||
If you are familiar with the original library, see: [The migration guide](docs/Migration_guide.md) for details about breaking changes and migration.
|
||||
|
||||
Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes.
|
||||
|
||||
[Full API documentation and class list can be found here.](https://h2zero.github.io/esp-nimble-cpp/)
|
||||
[Full API documentation and class list can be found here.](https://h2zero.github.io/NimBLE-Arduino/)
|
||||
|
||||
For added performance and optimizations see [Usage tips](docs/Usage_tips.md).
|
||||
|
||||
@ -65,21 +52,21 @@ Check the Refactored_original_examples in the examples folder for highlights of
|
||||
|
||||
More advanced examples highlighting many available features are in examples/ NimBLE_Server, NimBLE_Client.
|
||||
|
||||
Beacon examples provided by @beegee-tokyo are in examples/ BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
|
||||
Beacon examples provided by @beegee-tokyo are in examples/ BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
|
||||
|
||||
Change the settings in the `src/nimconfig.h` file to customize NimBLE to your project,
|
||||
such as increasing max connections, default is 3, absolute maximum connections is 9.
|
||||
Change the settings in the `src/nimconfig.h` file to customize NimBLE to your project,
|
||||
such as increasing max connections, default is 3, absolute maximum connections is 9.
|
||||
<br/>
|
||||
|
||||
# Development Status
|
||||
This Library is tracking the esp-nimble repo, nimble-1.3.0-idf master branch, currently [@5bb7b40.](https://github.com/espressif/esp-nimble)
|
||||
This Library is tracking the esp-nimble repo, nimble-1.4.0-idf branch, currently [@3df0d20.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@639e7ad.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@95db4bb.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
<br/>
|
||||
|
||||
# Acknowledgments
|
||||
* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from.
|
||||
* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples.
|
||||
* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
|
||||
<br/>
|
||||
|
||||
* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
|
||||
<br/>
|
||||
|
||||
|
28
lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md
Normal file
28
lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Bluetooth 5.x features
|
||||
|
||||
## About extended advertising
|
||||
Extended advertising allows for much more capability and flexibility.
|
||||
|
||||
* Allows for 251 bytes of advertisement data and up to 1650 bytes when chained (configuration dependant) vs 31.
|
||||
|
||||
* New PHY's (physical layers) that allow for faster data rate (2M PHY) or long range/slower data rates (CODED PHY) as well as the original 1M PHY.
|
||||
|
||||
* New periodic advertising, allowing the scanning device to sync with the advertisements of a beacon. This allows for the scanning device to sleep or perform other tasks before the next expected advertisement is sent, preserving cpu cycles and power (To be implemented).
|
||||
<br/>
|
||||
|
||||
## Enabling extended advertising
|
||||
Extended advertising is supported when enabled with the config option `CONFIG_BT_NIMBLE_EXT_ADV` set to a value of 1. This is done in menuconfig under `Component config > Bluetooth > NimBLE options > Enable extended advertising`, or set in `nimconfig.h` for Arduino, or in `build_flags` in PlatformIO.
|
||||
|
||||
When enabled the following will occur:
|
||||
* `NimBLEScan::start` method will scan on both the 1M PHY and the coded PHY standards automatically.
|
||||
|
||||
* `NimBLEClient::connect` will use the primary PHY the device is listening on, unless specified (see below).
|
||||
|
||||
* `NimBLEClient::setConnectPhy` becomes available to specify the PHY's to connect with (default is all).
|
||||
|
||||
* `NimBLEAdvertising` is no longer available for use and is replaced by `NimBLEExtAdvertising`. `NimBLEDevice::getAdvertising` will now return an instance of `NimBLEExtAdvertising`.
|
||||
|
||||
* `NimBLEAdvertisementData` is no longer available for use and is replaced by `NimBLEExtAdvertisement`. This new class is where everything about the advertisement is configured, including the advertisement intervals and advertisement ended callback.
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ characteristic or descriptor is constructed before a value is read/notifed.
|
||||
Increasing this will reduce reallocations but increase memory footprint.
|
||||
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
|
||||
<br/>
|
||||
|
||||
|
||||
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||
|
||||
Sets the default MTU size.
|
||||
@ -140,3 +140,41 @@ Set the task stack size for the NimBLE core.
|
||||
- Default is 4096
|
||||
<br/>
|
||||
|
||||
`CONFIG_NIMBLE_STACK_USE_MEM_POOLS`
|
||||
|
||||
Enable the use of memory pools for stack operations. This will use slightly more RAM but may provide more stability.
|
||||
|
||||
- Options: 0 or 1, default is disabled (0)
|
||||
<br/>
|
||||
|
||||
### Extended advertising settings, For use with ESP32C3, ESP32S3, ESP32H2 ONLY!
|
||||
|
||||
`CONFIG_BT_NIMBLE_EXT_ADV`
|
||||
|
||||
Set to 1 to enable extended advertising features.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES`
|
||||
|
||||
Sets the max number of extended advertising instances
|
||||
- Range: 0 - 4
|
||||
- Default is 1
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN`
|
||||
|
||||
Set the max extended advertising data size,
|
||||
- Range: 31 - 1650
|
||||
- Default is 255
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV`
|
||||
|
||||
Set to 1 to enable periodic advertising.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS`
|
||||
|
||||
Set the maximum number of periodically synced devices.
|
||||
- Range: 1 - 8
|
||||
- Default is 1
|
||||
|
2673
lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile
Normal file
2673
lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
# Improvements and updates
|
||||
|
||||
Many improvements have been made to this library vs the original, this is a brief overview of the most significant changes.
|
||||
Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) for futher information on class specifics.
|
||||
Many improvements have been made to this library vs the original, this is a brief overview of the most significant changes. Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) for further information on class specifics.
|
||||
|
||||
* [Server](#server)
|
||||
* [Advertising](#advertising)
|
||||
@ -10,23 +9,26 @@ Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annot
|
||||
<br/>
|
||||
|
||||
<a name="server"></a>
|
||||
# Server
|
||||
# Server
|
||||
|
||||
`NimBLECharacteristic::setValue(const T &s)`
|
||||
`NimBLEDescriptor::setValue(const T &s)`
|
||||
`NimBLEService::NimBLEService::createCharacteristic` takes a 3rd parameter to specify the maximum data size that can be stored by the characteristic. This allows for limiting the RAM use of the characteristic in cases where small amounts of data are expected.
|
||||
<br/>
|
||||
|
||||
Now use a template to accomodate standard and custom types/values.
|
||||
`NimBLECharacteristic::setValue(const T &s)`
|
||||
`NimBLEDescriptor::setValue(const T &s)`
|
||||
|
||||
Now use the `NimbleAttValue` class and templates to accommodate standard and custom types/values.
|
||||
|
||||
**Example**
|
||||
```
|
||||
struct my_struct{
|
||||
struct my_struct {
|
||||
uint8_t one;
|
||||
uint16_t two;
|
||||
uint32_t four;
|
||||
uint64_t eight;
|
||||
float flt;
|
||||
}myStruct;
|
||||
|
||||
} myStruct;
|
||||
|
||||
myStruct.one = 1;
|
||||
myStruct.two = 2;
|
||||
myStruct.four = 4;
|
||||
@ -34,12 +36,14 @@ struct my_struct{
|
||||
myStruct.flt = 1234.56;
|
||||
|
||||
pCharacteristic->setValue(myStruct);
|
||||
```
|
||||
This will send the struct to the recieving client when read or a notification sent.
|
||||
|
||||
`NimBLECharacteristic::getValue` now takes an optional timestamp parameter which will update it's value with
|
||||
the time the last value was recieved. In addition an overloaded template has been added to retrieve the value
|
||||
as a type specified by the user.
|
||||
// Arduino String support
|
||||
String myString = "Hello";
|
||||
pCharacteristic->setValue(myString);
|
||||
```
|
||||
This will send the struct to the receiving client when read or a notification sent.
|
||||
|
||||
`NimBLECharacteristic::getValue` now takes an optional timestamp parameter which will update it's value with the time the last value was received. In addition an overloaded template has been added to retrieve the value as a type specified by the user.
|
||||
|
||||
**Example**
|
||||
```
|
||||
@ -48,38 +52,34 @@ as a type specified by the user.
|
||||
```
|
||||
<br/>
|
||||
|
||||
**Advertising will automatically start when a client disconnects.**
|
||||
**Advertising will automatically start when a client disconnects.**
|
||||
|
||||
A new method `NimBLEServer::advertiseOnDisconnect(bool)` has been implemented to control this, true(default) = enabled.
|
||||
<br/>
|
||||
|
||||
`NimBLEServer::removeService` takes an additional parameter `bool deleteSvc` that if true will delete the service
|
||||
and all characteristics / descriptors belonging to it and invalidating any pointers to them.
|
||||
`NimBLEServer::removeService` takes an additional parameter `bool deleteSvc` that if true will delete the service and all characteristics / descriptors belonging to it and invalidating any pointers to them.
|
||||
|
||||
If false the service is only removed from visibility by clients. The pointers to the service and
|
||||
it's characteristics / descriptors will remain valid and the service can be re-added in the future
|
||||
using `NimBLEServer::addService`.
|
||||
If false the service is only removed from visibility by clients. The pointers to the service and it's characteristics / descriptors will remain valid and the service can be re-added in the future using `NimBLEServer::addService`.
|
||||
<br/>
|
||||
|
||||
<a name="advertising"></a>
|
||||
# Advertising
|
||||
`NimBLEAdvertising::start`
|
||||
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
|
||||
that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
This provides an opportunity to update the advertisment data if desired.
|
||||
This provides an opportunity to update the advertisement data if desired.
|
||||
|
||||
Also now returns a bool value to indicate if advertising successfully started or not.
|
||||
<br/>
|
||||
Also now returns a bool value to indicate if advertising successfully started or not.
|
||||
<br/>
|
||||
|
||||
<a name="client"></a>
|
||||
# Client
|
||||
# Client
|
||||
|
||||
`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
|
||||
`NimBLERemoteDescriptor::readValue(bool)`
|
||||
`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
|
||||
`NimBLERemoteDescriptor::readValue(bool)`
|
||||
|
||||
Have been added as templates to allow reading the values as any specified type.
|
||||
Have been added as templates to allow reading the values as any specified type.
|
||||
|
||||
**Example**
|
||||
```
|
||||
@ -93,56 +93,56 @@ struct my_struct{
|
||||
|
||||
time_t timestamp;
|
||||
myStruct = pRemoteCharacteristic->readValue<myStruct>(×tamp); // timestamp optional
|
||||
```
|
||||
```
|
||||
<br/>
|
||||
|
||||
`NimBLERemoteCharacteristic::registerForNotify`
|
||||
Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is recieved.
|
||||
`NimBLERemoteCharacteristic::registerForNotify`
|
||||
Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is received.
|
||||
|
||||
`NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it.
|
||||
A callback is no longer requred to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to
|
||||
get the last updated value any time.
|
||||
<br/>
|
||||
`NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it.
|
||||
A callback is no longer required to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to get the last updated value any time.
|
||||
<br/>
|
||||
|
||||
The `notifiy_callback` function is now defined as a `std::function` to take advantage of using `std::bind` to specifiy a class member function for the callback.
|
||||
The `notify_callback` function is now defined as a `std::function` to take advantage of using `std::bind` to specify a class member function for the callback.
|
||||
|
||||
Example:
|
||||
Example:
|
||||
```
|
||||
using namespace std::placeholders;
|
||||
notify_callback callback = std::bind(&<ClassName>::<memberFunctionCallbackName>, this, _1, _2, _3, _4);
|
||||
|
||||
<remoteCharacteristicInstance>->subscribe(true, callback);
|
||||
```
|
||||
|
||||
`NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with
|
||||
the time the last value was recieved.
|
||||
`NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with
|
||||
the time the last value was received.
|
||||
|
||||
> NimBLEClient::getService
|
||||
> NimBLERemoteService::getCharacteristic
|
||||
> NimBLERemoteCharacteristic::getDescriptor
|
||||
> NimBLERemoteCharacteristic::getDescriptor
|
||||
|
||||
These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
|
||||
the specified attribute from the peripheral.
|
||||
These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
|
||||
the specified attribute from the peripheral.
|
||||
|
||||
These changes allow more control for the user to manage the resources used for the attributes.
|
||||
These changes allow more control for the user to manage the resources used for the attributes.
|
||||
<br/>
|
||||
|
||||
`NimBLEClient::connect()` can now be called without an address or advertised device parameter. This will connect to the
|
||||
device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
|
||||
`NimBLEClient::connect()` can now be called without an address or advertised device parameter. This will connect to the device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
|
||||
|
||||
<a name="general"></a>
|
||||
# General
|
||||
To reduce resource use all instances of `std::map` have been replaced with `std::vector`.
|
||||
# General
|
||||
To reduce resource use all instances of `std::map` have been replaced with `std::vector`.
|
||||
|
||||
Use of `FreeRTOS::Semaphore` has been removed as it was consuming too much ram, the related files have been left in place to accomodate application use.
|
||||
Use of `FreeRTOS::Semaphore` has been removed as it was consuming too much ram, the related files have been left in place to accomodate application use.
|
||||
|
||||
Operators `==`, `!=` and `std::string` have been added to `NimBLEAddress` and `NimBLEUUID` for easier comparison and logging.
|
||||
Operators `==`, `!=` and `std::string` have been added to `NimBLEAddress` and `NimBLEUUID` for easier comparison and logging.
|
||||
|
||||
New constructor for `NimBLEUUID(uint32_t, uint16_t, uint16_t, uint64_t)` added to lower memory use vs string construction. See: [#21](https://github.com/h2zero/NimBLE-Arduino/pull/21).
|
||||
New constructor for `NimBLEUUID(uint32_t, uint16_t, uint16_t, uint64_t)` added to lower memory use vs string construction. See: [#21](https://github.com/h2zero/NimBLE-Arduino/pull/21).
|
||||
|
||||
Security/pairing operations are now handled in the respective `NimBLEClientCallbacks` and `NimBLEServerCallbacks` classes, `NimBLESecurity`(deprecated) remains for backward compatibility.
|
||||
Security/pairing operations are now handled in the respective `NimBLEClientCallbacks` and `NimBLEServerCallbacks` classes, `NimBLESecurity`(deprecated) remains for backward compatibility.
|
||||
|
||||
Configuration options have been added to add or remove debugging information, when disabled (default) significatly reduces binary size.
|
||||
Configuration options have been added to add or remove debugging information, when disabled (default) significantly reduces binary size.
|
||||
In ESP-IDF the options are in menuconfig: `Main menu -> ESP-NimBLE-cpp configuration`.
|
||||
For Arduino the options must be commented / uncommented in nimconfig.h.
|
||||
<br/>
|
||||
For Arduino the options must be commented / uncommented in nimconfig.h.
|
||||
|
||||
Characteristics and descriptors now use the `NimBLEAttValue` class to store their data. This is a polymorphic container class capable of converting to/from many different types efficiently. See: [#286](https://github.com/h2zero/NimBLE-Arduino/pull/286)
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Migrating from Bluedroid to NimBLE
|
||||
|
||||
This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
|
||||
This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
|
||||
|
||||
**The changes listed here are only the required changes that must be made**, and a short overview of options for migrating existing applications.
|
||||
**The changes listed here are only the required changes that must be made**, and a short overview of options for migrating existing applications.
|
||||
|
||||
For more information on the improvements and additions please refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) and [Improvements and updates](Improvements_and_updates.md)
|
||||
For more information on the improvements and additions please refer to the [class documentation](https://h2zero.github.io/NimBLE-Arduino/annotated.html) and [Improvements and updates](Improvements_and_updates.md)
|
||||
|
||||
* [General Changes](#general-information)
|
||||
* [Server](#server-api)
|
||||
@ -19,82 +19,78 @@ For more information on the improvements and additions please refer to the [clas
|
||||
* [Security](#client-security)
|
||||
* [General Security](#security-api)
|
||||
* [Configuration](#arduino-configuration)
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<a name="general-information"></a>
|
||||
## General Information
|
||||
|
||||
### Header Files
|
||||
All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
|
||||
All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
|
||||
|
||||
(Mainly for Arduino) You may choose to include `NimBLELog.h` in your appplication if you want to use the `NIMBLE_LOGx` macros for debugging.
|
||||
These macros are used the same way as the `ESP_LOGx` macros.
|
||||
(Mainly for Arduino) You may choose to include `NimBLELog.h` in your application if you want to use the `NIMBLE_LOGx` macros for debugging. These macros are used the same way as the `ESP_LOGx` macros.
|
||||
<br/>
|
||||
|
||||
### Class Names
|
||||
Class names remain the same as the original with the addition of a "Nim" prefix.
|
||||
For example `BLEDevice` is now `NimBLEDevice` and `BLEServer` is now `NimBLEServer` etc.
|
||||
Class names remain the same as the original with the addition of a "Nim" prefix.
|
||||
For example `BLEDevice` is now `NimBLEDevice` and `BLEServer` is now `NimBLEServer` etc.
|
||||
|
||||
For convienience definitions have been added to allow applications to use either name for all classes
|
||||
this means **no class names need to be changed in existing code** and makes migrating easier.
|
||||
For convenience definitions have been added to allow applications to use either name for all classes this means **no class names need to be changed in existing code** and makes migrating easier.
|
||||
<br/>
|
||||
|
||||
### BLE Addresses
|
||||
`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *(optional)* `uint8_t type` paramameter
|
||||
to specify the address type. Default is (0) Public static address.
|
||||
`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *(optional)* `uint8_t type` parameter to specify the address type. Default is (0) Public static address.
|
||||
|
||||
For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address object with an address type of: 1 (Random).
|
||||
For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address object with an address type of: 1 (Random).
|
||||
|
||||
As this paramameter is optional no changes to existing code are needed, it is mentioned here for information.
|
||||
<br/>
|
||||
`BLEAddress::getNative` (`NimBLEAddress::getNative`) returns a uint8_t pointer to the native address byte array.
|
||||
In this library the address bytes are stored in reverse order from the original library. This is due to the way
|
||||
the NimBLE stack expects addresses to be presented to it. All other functions such as `toString` are
|
||||
not affected as the endian change is made within them.
|
||||
As this parameter is optional no changes to existing code are needed, it is mentioned here for information.
|
||||
|
||||
`BLEAddress::getNative` (`NimBLEAddress::getNative`) returns a uint8_t pointer to the native address byte array. In this library the address bytes are stored in reverse order from the original library. This is due to the way the NimBLE stack expects addresses to be presented to it. All other functions such as `toString` are
|
||||
not affected as the endian change is made within them.
|
||||
<br/>
|
||||
|
||||
<a name="server-api"></a>
|
||||
## Server API
|
||||
Creating a `BLEServer` instance is the same as original, no changes required.
|
||||
For example `BLEDevice::createServer()` will work just as it did before.
|
||||
For example `BLEDevice::createServer()` will work just as it did before.
|
||||
|
||||
`BLEServerCallbacks` (`NimBLEServerCallbacks`) has new methods for handling security operations.
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
`BLEServerCallbacks` (`NimBLEServerCallbacks`) has new methods for handling security operations.
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
<a name="services"></a>
|
||||
### Services
|
||||
Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
|
||||
For example `BLEServer::createService(SERVICE_UUID)` will work just as it did before.
|
||||
Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
|
||||
For example `BLEServer::createService(SERVICE_UUID)` will work just as it did before.
|
||||
|
||||
<a name="characteristics"></a>
|
||||
### Characteristics
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
|
||||
#### Originally
|
||||
> BLECharacteristic::PROPERTY_READ |
|
||||
> BLECharacteristic::PROPERTY_WRITE
|
||||
> BLECharacteristic::PROPERTY_READ |
|
||||
> BLECharacteristic::PROPERTY_WRITE
|
||||
|
||||
#### Is Now
|
||||
> NIMBLE_PROPERTY::READ |
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
> NIMBLE_PROPERTY::READ |
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
<br/>
|
||||
|
||||
#### The full list of properties
|
||||
> NIMBLE_PROPERTY::READ
|
||||
> NIMBLE_PROPERTY::READ_ENC
|
||||
> NIMBLE_PROPERTY::READ_AUTHEN
|
||||
> NIMBLE_PROPERTY::READ_AUTHOR
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
> NIMBLE_PROPERTY::WRITE_NR
|
||||
> NIMBLE_PROPERTY::WRITE_ENC
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHEN
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHOR
|
||||
> NIMBLE_PROPERTY::BROADCAST
|
||||
> NIMBLE_PROPERTY::NOTIFY
|
||||
> NIMBLE_PROPERTY::INDICATE
|
||||
> NIMBLE_PROPERTY::READ
|
||||
> NIMBLE_PROPERTY::READ_ENC
|
||||
> NIMBLE_PROPERTY::READ_AUTHEN
|
||||
> NIMBLE_PROPERTY::READ_AUTHOR
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
> NIMBLE_PROPERTY::WRITE_NR
|
||||
> NIMBLE_PROPERTY::WRITE_ENC
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHEN
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHOR
|
||||
> NIMBLE_PROPERTY::BROADCAST
|
||||
> NIMBLE_PROPERTY::NOTIFY
|
||||
> NIMBLE_PROPERTY::INDICATE
|
||||
|
||||
<br/>
|
||||
|
||||
**Example:**
|
||||
@ -102,7 +98,7 @@ When creating a characteristic the properties are now set with `NIMBLE_PROPERTY:
|
||||
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID,
|
||||
BLECharacteristic::PROPERTY_READ |
|
||||
BLECharacteristic::PROPERTY_WRITE
|
||||
BLECharacteristic::PROPERTY_WRITE
|
||||
);
|
||||
|
||||
```
|
||||
@ -111,23 +107,22 @@ Needs to be changed to:
|
||||
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE
|
||||
NIMBLE_PROPERTY::WRITE
|
||||
);
|
||||
```
|
||||
<br/>
|
||||
|
||||
`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe`
|
||||
which is called when a client subscribes to notifications/indications.
|
||||
`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe` which is called when a client subscribes to notifications/indications.
|
||||
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
> BLECharacteristic::getData
|
||||
> BLECharacteristic::getData
|
||||
|
||||
**Has been removed from the API.**
|
||||
Originally this returned a `uint8_t*` to the internal data, which is volatile.
|
||||
To prevent possibly throwing exceptions this has been removed and `NimBLECharacteristic::getValue` should be used
|
||||
to get a copy of the data first which can then safely be accessed via pointer.
|
||||
**Has been removed from the API.**
|
||||
Originally this returned a `uint8_t*` to the internal data, which is volatile.
|
||||
To prevent possibly throwing exceptions this has been removed and `NimBLECharacteristic::getValue` should be used
|
||||
to get a copy of the data first which can then safely be accessed via pointer.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
@ -142,48 +137,47 @@ my_struct_t myStruct = pChr->getValue<my_struct_t>();
|
||||
|
||||
<a name="descriptors"></a>
|
||||
### Descriptors
|
||||
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||
|
||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor` method.
|
||||
|
||||
BLE2902 or NimBLE2902 class has been removed.
|
||||
NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
|
||||
|
||||
It was no longer useful to have a class for the 0x2902 descriptor as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
|
||||
to handle callback functionality and the client subscription status is handled internally.
|
||||
BLE2902 or NimBLE2902 class has been removed.
|
||||
NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
|
||||
|
||||
**Note:** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
|
||||
It was no longer useful to have a class for the 0x2902 descriptor as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
|
||||
to handle callback functionality and the client subscription status is handled internally.
|
||||
|
||||
**Note:** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
|
||||
allowing the creation of it would cause a fault in the NimBLE stack.
|
||||
|
||||
All other descriptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` method (except 0x2904, see below).
|
||||
All other descriptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` method (except 0x2904, see below).
|
||||
Which are defined as:
|
||||
```
|
||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||
uint32_t properties =
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
|
||||
|
||||
NimBLEDescriptor* createDescriptor(NimBLEUUID uuid,
|
||||
uint32_t properties =
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
```
|
||||
##### Example
|
||||
```
|
||||
pDescriptor = pCharacteristic->createDescriptor("ABCD",
|
||||
NIMBLE_PROPERTY::READ |
|
||||
pDescriptor = pCharacteristic->createDescriptor("ABCD",
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE |
|
||||
NIMBLE_PROPERTY::WRITE_ENC,
|
||||
25);
|
||||
```
|
||||
Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
|
||||
Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
|
||||
<br/>
|
||||
|
||||
For the 0x2904, there is a special class that is created when you call `createDescriptor("2904").
|
||||
|
||||
The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to
|
||||
The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to
|
||||
`NimBLE2904` to access the specific class methods.
|
||||
|
||||
##### Example
|
||||
@ -195,127 +189,115 @@ p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904");
|
||||
<a name="server-security"></a>
|
||||
### Server Security
|
||||
Security is set on the characteristic or descriptor properties by applying one of the following:
|
||||
> NIMBLE_PROPERTY::READ_ENC
|
||||
> NIMBLE_PROPERTY::READ_AUTHEN
|
||||
> NIMBLE_PROPERTY::READ_AUTHOR
|
||||
> NIMBLE_PROPERTY::WRITE_ENC
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHEN
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHOR
|
||||
> NIMBLE_PROPERTY::READ_ENC
|
||||
> NIMBLE_PROPERTY::READ_AUTHEN
|
||||
> NIMBLE_PROPERTY::READ_AUTHOR
|
||||
> NIMBLE_PROPERTY::WRITE_ENC
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHEN
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHOR
|
||||
|
||||
When a peer wants to read or write a characteristic or descriptor with any of these properties applied
|
||||
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
||||
This can be changed to use passkey authentication or numeric comparison. See [Security API](#security-api) for details.
|
||||
<br/>
|
||||
|
||||
When a peer wants to read or write a characteristic or descriptor with any of these properties applied it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
||||
|
||||
This can be changed to use passkey authentication or numeric comparison. See [Security API](#security-api) for details.
|
||||
<br/>
|
||||
|
||||
<a name="advertising-api"></a>
|
||||
## Advertising API
|
||||
Advertising works the same as the original API except:
|
||||
> BLEAdvertising::setMinPreferred
|
||||
> BLEAdvertising::setMaxPreferred
|
||||
Advertising works the same as the original API except:
|
||||
|
||||
These methods were found to not provide useful functionality and consumed valuable advertising space (6 bytes of 31) if used unknowingly.
|
||||
If you wish to advertise these parameters you can still do so manually via `BLEAdvertisementData::addData` (`NimBLEAdvertisementData::addData`).
|
||||
<br/>
|
||||
|
||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
||||
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
|
||||
~~Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.~~
|
||||
No longer true as of release 1.2.0 and above, custom scan response is now supported without custom advertisement data.
|
||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
||||
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
<br/>
|
||||
|
||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
||||
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
|
||||
that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
This provides an opportunity to update the advertisment data if desired.
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
This provides an opportunity to update the advertisement data if desired.
|
||||
<br/>
|
||||
|
||||
<a name="client-api"></a>
|
||||
## Client API
|
||||
|
||||
Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
|
||||
Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
|
||||
|
||||
Multiple client instances can be created, up to the maximum number of connections set in the config file (default: 3).
|
||||
To delete a client instance you must use `NimBLEDevice::deleteClient`.
|
||||
Multiple client instances can be created, up to the maximum number of connections set in the config file (default: 3). To delete a client instance you must use `NimBLEDevice::deleteClient`.
|
||||
|
||||
`BLEClient::connect`(`NimBLEClient::connect`) Has had it's parameters altered.
|
||||
`BLEClient::connect`(`NimBLEClient::connect`) Has had it's parameters altered.
|
||||
Defined as:
|
||||
> NimBLEClient::connect(bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAddress address, bool deleteServices = true);
|
||||
> NimBLEClient::connect(bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAddress address, bool deleteServices = true);
|
||||
|
||||
The type parameter has been removed and a new bool parameter has been added to indicate if the client should
|
||||
delete the attribute database previously retrieved (if applicable) for the peripheral, default value is true.
|
||||
If set to false the client will use the attribute database it retrieved from the peripheral when previously connected.
|
||||
This allows for faster connections and power saving if the devices dropped connection and are reconnecting.
|
||||
The type parameter has been removed and a new bool parameter has been added to indicate if the client should delete the attribute database previously retrieved (if applicable) for the peripheral, default value is true.
|
||||
|
||||
If set to false the client will use the attribute database it retrieved from the peripheral when previously connected.
|
||||
|
||||
This allows for faster connections and power saving if the devices dropped connection and are reconnecting.
|
||||
<br/>
|
||||
|
||||
> `BLEClient::getServices` (`NimBLEClient::getServices`)
|
||||
> `BLEClient::getServices` (`NimBLEClient::getServices`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the services should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
This method now takes an optional (bool) parameter to indicate if the services should be retrieved from the server (true) or the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data
|
||||
the user may not be interested in.
|
||||
|
||||
**Added:** `NimBLEClient::discoverAttributes` for the user to discover all the peripheral attributes
|
||||
to replace the the removed automatic functionality.
|
||||
**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data the user may not be interested in.
|
||||
|
||||
**Added:** `NimBLEClient::discoverAttributes` for the user to discover all the peripheral attributes to replace the the removed automatic functionality.
|
||||
<br/>
|
||||
|
||||
<a name="remote-services"></a>
|
||||
### Remote Services
|
||||
`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
|
||||
`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
|
||||
|
||||
> BLERemoteService::getCharacteristicsByHandle
|
||||
|
||||
This method has been removed.
|
||||
This method has been removed.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
|
||||
> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the characteristics should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
This method now takes an optional (bool) parameter to indicate if the characteristics should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
<a name="remote-characteristics"></a>
|
||||
### Remote Characteristics
|
||||
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
|
||||
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`)
|
||||
There have been a few changes to the methods in this class:
|
||||
|
||||
> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
|
||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
|
||||
Is now **deprecated**.
|
||||
> `NimBLERemoteCharacteristic::subscribe`
|
||||
> `NimBLERemoteCharacteristic::unsubscribe`
|
||||
Is now **deprecated**.
|
||||
> `NimBLERemoteCharacteristic::subscribe`
|
||||
> `NimBLERemoteCharacteristic::unsubscribe`
|
||||
|
||||
Are the new methods added to replace it.
|
||||
Are the new methods added to replace it.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`)
|
||||
> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`)
|
||||
> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`)
|
||||
> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`)
|
||||
> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`)
|
||||
> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`)
|
||||
> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`)
|
||||
> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`)
|
||||
|
||||
Are **deprecated** a template: NimBLERemoteCharacteristic::readValue<type\>(time_t\*, bool) has been added to replace them.
|
||||
Are **deprecated** a template: `NimBLERemoteCharacteristic::readValue<type\>(time_t\*, bool)` has been added to replace them.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::readRawData`
|
||||
> `BLERemoteCharacteristic::readRawData`
|
||||
|
||||
**Has been removed from the API**
|
||||
Originally it stored an unnecessary copy of the data and was returning a `uint8_t` pointer to volatile internal data.
|
||||
The user application should use `NimBLERemoteCharacteristic::readValue` or `NimBLERemoteCharacteristic::getValue`.
|
||||
To obatain a copy of the data, then cast the returned std::string to the type required such as:
|
||||
**Has been removed from the API**
|
||||
Originally it stored an unnecessary copy of the data and was returning a `uint8_t` pointer to volatile internal data.
|
||||
The user application should use `NimBLERemoteCharacteristic::readValue` or `NimBLERemoteCharacteristic::getValue`.
|
||||
To obtain a copy of the data, then cast the returned std::string to the type required such as:
|
||||
```
|
||||
std::string value = pChr->readValue();
|
||||
uint8_t *data = (uint8_t*)value.data();
|
||||
@ -325,75 +307,73 @@ Alternatively use the `readValue` template:
|
||||
my_struct_t myStruct = pChr->readValue<my_struct_t>();
|
||||
```
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the descriptors should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the descriptors should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
<a name="client-security"></a>
|
||||
### Client Security
|
||||
The client will automatically initiate security when the peripheral responds that it's required.
|
||||
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||
The client will automatically initiate security when the peripheral responds that it's required.
|
||||
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||
<br/>
|
||||
|
||||
<a name="security-api"></a>
|
||||
## Security API
|
||||
Security operations have been moved to `BLEDevice` (`NimBLEDevice`).
|
||||
|
||||
Also security callback methods are now incorporated in the `NimBLEServerCallbacks` / `NimBLEClientCallbacks` classes.
|
||||
However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
|
||||
Also security callback methods are now incorporated in the `NimBLEServerCallbacks` / `NimBLEClientCallbacks` classes.
|
||||
However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
|
||||
|
||||
The callback methods are:
|
||||
|
||||
> `bool onConfirmPIN(uint32_t pin)`
|
||||
> `bool onConfirmPIN(uint32_t pin)`
|
||||
|
||||
Receives the pin when using numeric comparison authentication, `return true;` to accept.
|
||||
Receives the pin when using numeric comparison authentication, `return true;` to accept.
|
||||
<br/>
|
||||
|
||||
> `uint32_t onPassKeyRequest()`
|
||||
> `uint32_t onPassKeyRequest()`
|
||||
|
||||
For server callback; return the passkey expected from the client.
|
||||
For client callback; return the passkey to send to the server.
|
||||
For server callback; return the passkey expected from the client.
|
||||
For client callback; return the passkey to send to the server.
|
||||
<br/>
|
||||
|
||||
> `void onAuthenticationComplete(ble_gap_conn_desc\* desc)`
|
||||
> `void onAuthenticationComplete(ble_gap_conn_desc\* desc)`
|
||||
|
||||
Authentication complete, success or failed information is in `desc`.
|
||||
Authentication complete, success or failed information is in `desc`.
|
||||
<br/>
|
||||
|
||||
Security settings and IO capabilities are now set by the following methods of NimBLEDevice.
|
||||
> `NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc)`
|
||||
> `NimBLEDevice::setSecurityAuth(uint8_t auth_req)`
|
||||
> `NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc)`
|
||||
> `NimBLEDevice::setSecurityAuth(uint8_t auth_req)`
|
||||
|
||||
Sets the authorization mode for this device.
|
||||
Sets the authorization mode for this device.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityIOCap(uint8_t iocap)`
|
||||
> `NimBLEDevice::setSecurityIOCap(uint8_t iocap)`
|
||||
|
||||
Sets the Input/Output capabilities of this device.
|
||||
Sets the Input/Output capabilities of this device.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityInitKey(uint8_t init_key)`
|
||||
> `NimBLEDevice::setSecurityInitKey(uint8_t init_key)`
|
||||
|
||||
If we are the initiator of the security procedure this sets the keys we will distribute.
|
||||
If we are the initiator of the security procedure this sets the keys we will distribute.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityRespKey(uint8_t resp_key)`
|
||||
> `NimBLEDevice::setSecurityRespKey(uint8_t resp_key)`
|
||||
|
||||
Sets the keys we are willing to accept from the peer during pairing.
|
||||
Sets the keys we are willing to accept from the peer during pairing.
|
||||
<br/>
|
||||
|
||||
<a name="arduino-configuration"></a>
|
||||
## Arduino Configuration
|
||||
|
||||
Unlike the original library pre-packaged in the esp32-arduino, this library has all the configuration
|
||||
options that are normally set in menuconfig available in the *src/nimconfig.h* file.
|
||||
Unlike the original library pre-packaged in the esp32-arduino, this library has all the configuration options that are normally set in menuconfig available in the *src/nimconfig.h* file.
|
||||
|
||||
This allows Arduino users to fully customize the build, such as increasing max connections
|
||||
or loading the BLE stack into external PSRAM.
|
||||
This allows Arduino users to fully customize the build, such as increasing max connections or loading the BLE stack into external PSRAM.
|
||||
|
||||
For details on the options, they are fully commented in *nimconfig.h*
|
||||
For details on the options, they are fully commented in *nimconfig.h*
|
||||
<br/>
|
||||
|
@ -23,7 +23,7 @@ This can be called any time you wish to use BLE functions and does not need to b
|
||||
|
||||
<a name="creating-a-server"></a>
|
||||
## Creating a Server
|
||||
BLE servers perform 2 tasks, they advertise their existance for clients to find them and they provide services which contain information for the connecting client.
|
||||
BLE servers perform 2 tasks, they advertise their existence for clients to find them and they provide services which contain information for the connecting client.
|
||||
|
||||
After initializing the NimBLE stack we create a server by calling `NimBLEDevice::createServer()`, this will create a server instance and return a pointer to it.
|
||||
|
||||
@ -91,7 +91,7 @@ void app_main(void)
|
||||
}
|
||||
```
|
||||
|
||||
All that's left to do now is start the sevice, give the characteristic a value and start advertising for clients.
|
||||
All that's left to do now is start the service, give the characteristic a value and start advertising for clients.
|
||||
|
||||
Fist we start the service by calling `NimBLEService::start()`.
|
||||
|
||||
@ -214,7 +214,7 @@ for(int i = 0; i < results.getCount(); i++) {
|
||||
}
|
||||
}
|
||||
```
|
||||
As shown, the call to `NimBLEClient::connect` should have it's eturn value tested to make sure it succeeded before proceeding to get data.
|
||||
As shown, the call to `NimBLEClient::connect` should have it's return value tested to make sure it succeeded before proceeding to get data.
|
||||
<br/>
|
||||
|
||||
Next we need to access the servers data by asking it for the service and the characteristic we are interested in, then read the characteristic value.
|
||||
@ -222,7 +222,7 @@ Next we need to access the servers data by asking it for the service and the cha
|
||||
To do this we call `NimBLEClient::getService`, which takes as a parameter the UUID of the service and returns
|
||||
a pointer an instance to `NimBLERemoteService` or `nullptr` if the service was not found.
|
||||
|
||||
Next we will call `NimBLERemoteService::getCharateristic` which takes as a parameter the UUID of the service and returns
|
||||
Next we will call `NimBLERemoteService::getCharacteristic` which takes as a parameter the UUID of the service and returns
|
||||
a pointer to an instance of `NimBLERemoteCharacteristic` or `nullptr` if not found.
|
||||
|
||||
Finally we will read the characteristic value with `NimBLERemoteCharacteristic::readValue()`.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Put BLE functions in a task running on the NimBLE stack core
|
||||
|
||||
When commands are sent to the stack from a differnt core they can experience delays in execution.
|
||||
When commands are sent to the stack from a different core they can experience delays in execution.
|
||||
This library detects this and invokes the esp32 IPC to reroute these commands through the correct core but this also increases overhead.
|
||||
Therefore it is highly recommended to create tasks for BLE to run on the same core, the macro `CONFIG_BT_NIMBLE_PINNED_TO_CORE` can be used to set the core.
|
||||
<br/>
|
||||
@ -13,12 +13,12 @@ When a client instance has been created and has connected to a peer device and i
|
||||
If you are periodically connecting to the same devices and you have deleted the client instance or the services when connecting again it will cause a retrieval of that information from the peer again.
|
||||
This results in significant energy drain on the battery of the devices, fragments heap, and reduces connection performance.
|
||||
|
||||
Client instances in this library use approximately 20% of the original bluedroid library, deleteing them will provide much less gain than it did before.
|
||||
Client instances in this library use approximately 20% of the original bluedroid library, deleting them will provide much less gain than it did before.
|
||||
|
||||
It is recommended to retain the client instance in cases where the time between connecting to the same device is less than 5 minutes.
|
||||
<br/>
|
||||
|
||||
## Only retrieve the services and characteriscs needed
|
||||
## Only retrieve the services and characteristics needed
|
||||
|
||||
As a client the use of `NimBLEClient::getServices` or `NimBLERemoteService::getCharacteristics` and using `true` for the parameter should be limited to devices that are not known.
|
||||
Instead `NimBLEClient::getService(NimBLEUUID)` or `NimBLERemoteService::getCharacteristic(NimBLEUUID)` should be used to access certain attributes that are useful to the application.
|
||||
|
70
lib/libesp32_div/NimBLE-Arduino/docs/index.md
Normal file
70
lib/libesp32_div/NimBLE-Arduino/docs/index.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Overview
|
||||
|
||||
This is a C++ BLE library for Espressif ESP32 and Nordic nRF51/nRF52 devices that uses the NimBLE BLE stack.
|
||||
The aim is to maintain, as much as reasonable, the original ESP32 Arduino BLE API by while adding new features and making improvements in performance, resource use, and stability.
|
||||
<br/>
|
||||
|
||||
# What is NimBLE?
|
||||
NimBLE is a completely open source Bluetooth Low Energy stack produced by [Apache](https://github.com/apache/mynewt-nimble).
|
||||
<br/>
|
||||
|
||||
# Arduino installation
|
||||
**NOTE:** Nordic devices require using [n-able arduino core](https://github.com/h2zero/n-able-Arduino)
|
||||
|
||||
**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
|
||||
|
||||
**Alternatively:** Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
|
||||
|
||||
`#include "NimBLEDevice.h"` at the beginning of your sketch.
|
||||
|
||||
Call `NimBLEDevice::init` in `setup`.
|
||||
<br/>
|
||||
|
||||
# Platformio installation
|
||||
* Open platformio.ini, a project configuration file located in the root of PlatformIO project.
|
||||
* Add the following line to the lib_deps option of [env:] section:
|
||||
```
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
```
|
||||
* Build a project, PlatformIO will automatically install dependencies.
|
||||
<br/>
|
||||
|
||||
# Using
|
||||
This library is intended to be compatible with the original ESP32 BLE library functions and types with minor changes.
|
||||
|
||||
If you have not used the original BLE library please refer to the [New user guide](New_user_guide.md).
|
||||
|
||||
If you are familiar with the original library, see: [The migration guide](Migration_guide.md) for details.
|
||||
|
||||
Also see [Improvements and updates](Improvements_and_updates.md) for information about non-breaking changes.
|
||||
|
||||
For more advanced usage see [Usage tips](Usage_tips.md) for more performance and optimization.
|
||||
<br/>
|
||||
|
||||
## Examples
|
||||
See the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
||||
|
||||
More advanced examples highlighting many available features are in examples/NimBLE_Server, NimBLE_Client.
|
||||
|
||||
Beacon examples provided by [beegee-tokyo](https://github.com/beegee-tokyo) are in examples/BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
|
||||
|
||||
Change the settings in the nimconfig.h file to customize NimBLE to your project, such as increasing max connections (default is 3).
|
||||
<br/>
|
||||
|
||||
## Arduino command line and platformio
|
||||
As an alternative to changing the configuration in nimconfig.h, Arduino command line and platformio.ini options are available.
|
||||
|
||||
See the command line configuration options available in [Command line config](Command_line_config.md).
|
||||
<br/>
|
||||
|
||||
# Need help? Have a question or suggestion?
|
||||
Come chat on [gitter](https://gitter.im/NimBLE-Arduino/community?utm_source=share-link&utm_medium=link&utm_campaign=share-link) or open an issue at [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino/issues) or [esp-nimble-cpp](https://github.com/h2zero/esp-nimble-cpp/issues)
|
||||
<br/>
|
||||
|
||||
# Acknowledgments
|
||||
|
||||
* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from.
|
||||
* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples.
|
||||
* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
|
||||
<br/>
|
||||
|
@ -0,0 +1,171 @@
|
||||
|
||||
/** NimBLE Extended Client Demo:
|
||||
*
|
||||
* Demonstrates the Bluetooth 5.x client capabilities.
|
||||
*
|
||||
* Created: on April 2 2022
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************************************
|
||||
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||
/**************************************************/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# error Must enable extended advertising, see nimconfig.h file.
|
||||
#endif
|
||||
|
||||
void scanEndedCB(NimBLEScanResults results);
|
||||
|
||||
#define SERVICE_UUID "ABCD"
|
||||
#define CHARACTERISTIC_UUID "1234"
|
||||
|
||||
static NimBLEAdvertisedDevice* advDevice;
|
||||
static bool doConnect = false;
|
||||
static uint32_t scanTime = 10; /* 0 = scan forever */
|
||||
|
||||
/* Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default).*/
|
||||
static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /*| BLE_GAP_LE_PHY_2M_MASK */ ;
|
||||
|
||||
/* Define a class to handle the callbacks for client connection events */
|
||||
class ClientCallbacks : public NimBLEClientCallbacks {
|
||||
void onConnect(NimBLEClient* pClient) {
|
||||
Serial.printf("Connected\n");
|
||||
};
|
||||
|
||||
void onDisconnect(NimBLEClient* pClient) {
|
||||
Serial.printf("%s Disconnected - Starting scan\n", pClient->getPeerAddress().toString().c_str());
|
||||
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* Define a class to handle the callbacks when advertisements are received */
|
||||
class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
||||
|
||||
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
||||
Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||
if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
|
||||
{
|
||||
Serial.printf("Found Our Service\n");
|
||||
/* Ready to connect now */
|
||||
doConnect = true;
|
||||
/* Save the device reference in a global for the client to use*/
|
||||
advDevice = advertisedDevice;
|
||||
/* stop scan before connecting */
|
||||
NimBLEDevice::getScan()->stop();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* Callback to process the results of the last scan or restart it */
|
||||
void scanEndedCB(NimBLEScanResults results){
|
||||
Serial.printf("Scan Ended\n");
|
||||
if (!doConnect) { /* Don't start the scan while connecting */
|
||||
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handles the provisioning of clients and connects / interfaces with the server */
|
||||
bool connectToServer() {
|
||||
NimBLEClient* pClient = nullptr;
|
||||
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setClientCallbacks(new ClientCallbacks, false);
|
||||
|
||||
/* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
|
||||
* * 0x01 BLE_GAP_LE_PHY_1M_MASK
|
||||
* * 0x02 BLE_GAP_LE_PHY_2M_MASK
|
||||
* * 0x04 BLE_GAP_LE_PHY_CODED_MASK
|
||||
* Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
|
||||
*/
|
||||
pClient->setConnectPhy(connectPhys);
|
||||
|
||||
/** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
|
||||
pClient->setConnectTimeout(10);
|
||||
|
||||
if (!pClient->connect(advDevice)) {
|
||||
/* Created a client but failed to connect, don't need to keep it as it has no data */
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
Serial.printf("Failed to connect, deleted client\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Serial.printf("Connected to: %s RSSI: %d\n",
|
||||
pClient->getPeerAddress().toString().c_str(),
|
||||
pClient->getRssi());
|
||||
|
||||
/* Now we can read/write/subscribe the charateristics of the services we are interested in */
|
||||
NimBLERemoteService* pSvc = nullptr;
|
||||
NimBLERemoteCharacteristic* pChr = nullptr;
|
||||
|
||||
pSvc = pClient->getService(SERVICE_UUID);
|
||||
|
||||
if (pSvc) {
|
||||
pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
|
||||
|
||||
if (pChr) {
|
||||
// Read the value of the characteristic.
|
||||
if (pChr->canRead()) {
|
||||
std::string value = pChr->readValue();
|
||||
Serial.printf("Characteristic value: %s\n", value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Serial.printf("ABCD service not found.\n");
|
||||
}
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
Serial.printf("Done with this device!\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("Starting NimBLE Client\n");
|
||||
|
||||
/* Initialize NimBLE, no device name specified as we are not advertising */
|
||||
NimBLEDevice::init("");
|
||||
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||
|
||||
/* create a callback that gets called when advertisers are found */
|
||||
pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
|
||||
|
||||
/* Set scan interval (how often) and window (how long) in milliseconds */
|
||||
pScan->setInterval(97);
|
||||
pScan->setWindow(67);
|
||||
|
||||
/* Active scan will gather scan response data from advertisers
|
||||
* but will use more energy from both devices
|
||||
*/
|
||||
pScan->setActiveScan(true);
|
||||
|
||||
/* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
|
||||
* Optional callback for when scanning stops.
|
||||
*/
|
||||
pScan->start(scanTime, scanEndedCB);
|
||||
|
||||
Serial.printf("Scanning for peripherals\n");
|
||||
}
|
||||
|
||||
void loop () {
|
||||
/* Loop here until we find a device we want to connect to */
|
||||
if (doConnect) {
|
||||
/* Found a device we want to connect to, do it now */
|
||||
if (connectToServer()) {
|
||||
Serial.printf("Success!, scanning for more!\n");
|
||||
} else {
|
||||
Serial.printf("Failed to connect, starting scan\n");
|
||||
}
|
||||
|
||||
doConnect = false;
|
||||
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||
}
|
||||
|
||||
delay(10);
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/** NimBLE Extended Advertiser Demo:
|
||||
*
|
||||
* Demonstrates the Bluetooth 5.x extended advertising capabilities.
|
||||
*
|
||||
* This demo will advertise a long data string on the CODED and 1M Phy's and
|
||||
* starts a server allowing connection over either PHY's. It will advertise for
|
||||
* 5 seconds then sleep for 20 seconds, if a client connects it will sleep once
|
||||
* it has disconnected then repeats.
|
||||
*
|
||||
* Created: on April 2 2022
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************************************
|
||||
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||
/**************************************************/
|
||||
|
||||
#include "NimBLEDevice.h"
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# error Must enable extended advertising, see nimconfig.h file.
|
||||
#endif
|
||||
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#define SERVICE_UUID "ABCD"
|
||||
#define CHARACTERISTIC_UUID "1234"
|
||||
|
||||
/* Time in milliseconds to advertise */
|
||||
static uint32_t advTime = 5000;
|
||||
|
||||
/* Time to sleep between advertisements */
|
||||
static uint32_t sleepSeconds = 20;
|
||||
|
||||
/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
|
||||
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
|
||||
|
||||
/* Secondary PHY used for advertising and connecting,
|
||||
* can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
|
||||
|
||||
|
||||
/* Handler class for server events */
|
||||
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||
Serial.printf("Client connected:: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||
};
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer) {
|
||||
Serial.printf("Client disconnected - sleeping for %u seconds\n", sleepSeconds);
|
||||
esp_deep_sleep_start();
|
||||
};
|
||||
};
|
||||
|
||||
/* Callback class to handle advertising events */
|
||||
class advertisingCallbacks: public NimBLEExtAdvertisingCallbacks {
|
||||
void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
|
||||
/* Check the reason advertising stopped, don't sleep if client is connecting */
|
||||
printf("Advertising instance %u stopped\n", inst_id);
|
||||
switch (reason) {
|
||||
case 0:
|
||||
printf("Client connecting\n");
|
||||
return;
|
||||
case BLE_HS_ETIMEOUT:
|
||||
printf("Time expired - sleeping for %u seconds\n", sleepSeconds);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
};
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
|
||||
NimBLEDevice::init("Extended advertiser");
|
||||
|
||||
/* Create the server and add the services/characteristics/descriptors */
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new ServerCallbacks);
|
||||
|
||||
NimBLEService *pService = pServer->createService(SERVICE_UUID);
|
||||
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE |
|
||||
NIMBLE_PROPERTY::NOTIFY);
|
||||
|
||||
pCharacteristic->setValue("Hello World");
|
||||
|
||||
/* Start the services */
|
||||
pService->start();
|
||||
|
||||
/*
|
||||
* Create an extended advertisement with the instance ID 0 and set the PHY's.
|
||||
* Multiple instances can be added as long as the instance ID is incremented.
|
||||
*/
|
||||
NimBLEExtAdvertisement extAdv(primaryPhy, secondaryPhy);
|
||||
|
||||
/* Set the advertisement as connectable */
|
||||
extAdv.setConnectable(true);
|
||||
|
||||
/* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
|
||||
extAdv.setScannable(false); // The default is false, set here for demonstration.
|
||||
|
||||
/* Extended advertising allows for 251 bytes (minus header bytes ~20) in a single advertisement or up to 1650 if chained */
|
||||
extAdv.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Extended Advertising Demo.\r\n"
|
||||
"Extended advertising allows for "
|
||||
"251 bytes of data in a single advertisement,\r\n"
|
||||
"or up to 1650 bytes with chaining.\r\n"
|
||||
"This example message is 226 bytes long "
|
||||
"and is using CODED_PHY for long range."));
|
||||
|
||||
extAdv.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
|
||||
|
||||
/* When extended advertising is enabled `NimBLEDevice::getAdvertising` returns a pointer to `NimBLEExtAdvertising */
|
||||
NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||
|
||||
/* Set the callbacks for advertising events */
|
||||
pAdvertising->setCallbacks(new advertisingCallbacks);
|
||||
|
||||
/*
|
||||
* NimBLEExtAdvertising::setInstanceData takes the instance ID and
|
||||
* a reference to a `NimBLEExtAdvertisement` object. This sets the data
|
||||
* that will be advertised for this instance ID, returns true if successful.
|
||||
*
|
||||
* Note: It is safe to create the advertisement as a local variable if setInstanceData
|
||||
* is called before exiting the code block as the data will be copied.
|
||||
*/
|
||||
if (pAdvertising->setInstanceData(0, extAdv)) {
|
||||
/*
|
||||
* `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
|
||||
* and a duration in milliseconds or a max number of advertisements to send (or both).
|
||||
*/
|
||||
if (pAdvertising->start(0, advTime)) {
|
||||
Serial.printf("Started advertising\n");
|
||||
} else {
|
||||
Serial.printf("Failed to start advertising\n");
|
||||
}
|
||||
} else {
|
||||
Serial.printf("Failed to register advertisment data\n");
|
||||
}
|
||||
|
||||
esp_sleep_enable_timer_wakeup(sleepSeconds * 1000000);
|
||||
}
|
||||
|
||||
void loop () {
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
/** NimBLE Multi Advertiser Demo:
|
||||
*
|
||||
* Demonstrates the Bluetooth 5.x extended advertising capabilities.
|
||||
*
|
||||
* This demo will advertise 2 advertisements, and extended scannable instance
|
||||
* and a connectable legacy instance. They will advertise for 5 seconds then
|
||||
* sleep for 20 seconds. The extended scannable instance will use the scan
|
||||
* request callback to update it's data when a scan response is requested.
|
||||
*
|
||||
* Created: on April 9 2022
|
||||
* Author: H2zero
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************************************
|
||||
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||
/**************************************************/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# error Must enable extended advertising, see nimconfig.h file.
|
||||
#endif
|
||||
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#define SERVICE_UUID "ABCD"
|
||||
#define CHARACTERISTIC_UUID "1234"
|
||||
|
||||
/* Time in milliseconds to advertise */
|
||||
static uint32_t advTime = 5000;
|
||||
|
||||
/* Time to sleep between advertisements */
|
||||
static uint32_t sleepTime = 20;
|
||||
|
||||
/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
|
||||
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
|
||||
|
||||
/* Secondary PHY used for advertising and connecting,
|
||||
* can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
|
||||
|
||||
|
||||
/* Handler class for server events */
|
||||
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||
Serial.printf("Client connected: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||
};
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer) {
|
||||
Serial.printf("Client disconnected\n");
|
||||
// if still advertising we won't sleep yet.
|
||||
if (!pServer->getAdvertising()->isAdvertising()) {
|
||||
Serial.printf("Sleeping for %u seconds\n", sleepTime);
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/* Callback class to handle advertising events */
|
||||
class advCallbacks: public NimBLEExtAdvertisingCallbacks {
|
||||
void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
|
||||
/* Check the reason advertising stopped, don't sleep if client is connecting */
|
||||
Serial.printf("Advertising instance %u stopped\n", inst_id);
|
||||
switch (reason) {
|
||||
case 0:
|
||||
Serial.printf(" client connecting\n");
|
||||
return;
|
||||
case BLE_HS_ETIMEOUT:
|
||||
Serial.printf("Time expired - sleeping for %u seconds\n", sleepTime);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
bool m_updatedSR = false;
|
||||
|
||||
void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t inst_id, NimBLEAddress addr) {
|
||||
Serial.printf("Scan request for instance %u\n", inst_id);
|
||||
// if the data has already been updated we don't need to change it again.
|
||||
if (!m_updatedSR) {
|
||||
Serial.printf("Updating scan data\n");
|
||||
NimBLEExtAdvertisement sr;
|
||||
sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
|
||||
pAdv->setScanResponseData(inst_id, sr);
|
||||
m_updatedSR = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
|
||||
NimBLEDevice::init("Multi advertiser");
|
||||
|
||||
/* Create a server for our legacy advertiser */
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new ServerCallbacks);
|
||||
|
||||
NimBLEService *pService = pServer->createService(SERVICE_UUID);
|
||||
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE |
|
||||
NIMBLE_PROPERTY::NOTIFY);
|
||||
|
||||
pCharacteristic->setValue("Hello World");
|
||||
|
||||
/* Start the service */
|
||||
pService->start();
|
||||
|
||||
/* Create our multi advertising instances */
|
||||
|
||||
// extended scannable instance advertising on coded and 1m PHY's.
|
||||
NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
|
||||
|
||||
// Legacy advertising as a connectable device.
|
||||
NimBLEExtAdvertisement legacyConnectable;
|
||||
|
||||
// Optional scan response data.
|
||||
NimBLEExtAdvertisement legacyScanResponse;
|
||||
|
||||
/* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
|
||||
extScannable.setScannable(true);
|
||||
extScannable.setConnectable(false);
|
||||
|
||||
/* Set the initial data */
|
||||
extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
|
||||
|
||||
/* enable the scan response callback, we will use this to update the data. */
|
||||
extScannable.enableScanRequestCallback(true);
|
||||
|
||||
/* Optional custom address for this advertisment. */
|
||||
legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD"));
|
||||
|
||||
/* Set the advertising data. */
|
||||
legacyConnectable.setName("Legacy");
|
||||
legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
|
||||
|
||||
/* Set the legacy and connectable flags. */
|
||||
legacyConnectable.setLegacyAdvertising(true);
|
||||
legacyConnectable.setConnectable(true);
|
||||
|
||||
/* Put some data in the scan response if desired. */
|
||||
legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
|
||||
|
||||
/* Get the advertising ready */
|
||||
NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||
|
||||
/* Set the callbacks to handle advertising events */
|
||||
pAdvertising->setCallbacks(new advCallbacks);
|
||||
|
||||
/* Set instance data.
|
||||
* Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
|
||||
*
|
||||
* We will set the extended scannable data on instance 0 and the legacy data on instance 1.
|
||||
* Note that the legacy scan response data needs to be set to the same instance (1).
|
||||
*/
|
||||
if (pAdvertising->setInstanceData( 0, extScannable ) &&
|
||||
pAdvertising->setInstanceData( 1, legacyConnectable ) &&
|
||||
pAdvertising->setScanResponseData( 1, legacyScanResponse )) {
|
||||
/*
|
||||
* `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
|
||||
* and a duration in milliseconds or a max number of advertisements to send (or both).
|
||||
*/
|
||||
if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
|
||||
Serial.printf("Started advertising\n");
|
||||
} else {
|
||||
Serial.printf("Failed to start advertising\n");
|
||||
}
|
||||
} else {
|
||||
Serial.printf("Failed to register advertisment data\n");
|
||||
}
|
||||
|
||||
esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
}
|
@ -347,7 +347,11 @@ void setup (){
|
||||
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
|
||||
|
||||
/** Optional: set the transmit power, default is 3db */
|
||||
#ifdef ESP_PLATFORM
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
|
||||
#else
|
||||
NimBLEDevice::setPower(9); /** +9db */
|
||||
#endif
|
||||
|
||||
/** Optional: set any devices you don't want to get advertisments from */
|
||||
// NimBLEDevice::addIgnored(NimBLEAddress ("aa:bb:cc:dd:ee:ff"));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** NimBLE_Secure_Client Demo:
|
||||
*
|
||||
*
|
||||
* This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client.
|
||||
* Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective.
|
||||
* To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash.
|
||||
@ -7,7 +7,7 @@
|
||||
* Created: on Jan 08 2021
|
||||
* Author: mblasee
|
||||
*/
|
||||
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
class ClientCallbacks : public NimBLEClientCallbacks
|
||||
@ -28,7 +28,11 @@ void setup()
|
||||
Serial.println("Starting NimBLE Client");
|
||||
|
||||
NimBLEDevice::init("");
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
#ifdef ESP_PLATFORM
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
|
||||
#else
|
||||
NimBLEDevice::setPower(9); /** +9db */
|
||||
#endif
|
||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY);
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
@ -53,7 +57,7 @@ void setup()
|
||||
if (pService != nullptr)
|
||||
{
|
||||
NimBLERemoteCharacteristic *pNonSecureCharacteristic = pService->getCharacteristic("1234");
|
||||
|
||||
|
||||
if (pNonSecureCharacteristic != nullptr)
|
||||
{
|
||||
// Testing to read a non secured characteristic, you should be able to read this even if you have mismatching passkeys.
|
||||
@ -68,11 +72,11 @@ void setup()
|
||||
{
|
||||
// Testing to read a secured characteristic, you should be able to read this only if you have matching passkeys, otherwise you should
|
||||
// get an error like this. E NimBLERemoteCharacteristic: "<< readValue rc=261"
|
||||
// This means you are trying to do something without the proper permissions.
|
||||
// This means you are trying to do something without the proper permissions.
|
||||
std::string value = pSecureCharacteristic->readValue();
|
||||
// print or do whatever you need with the value
|
||||
Serial.println(value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1,5 +1,5 @@
|
||||
/** NimBLE_Secure_Server Demo:
|
||||
*
|
||||
*
|
||||
* This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client.
|
||||
* Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective.
|
||||
* To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash.
|
||||
@ -14,7 +14,11 @@ void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting NimBLE Server");
|
||||
NimBLEDevice::init("NimBLE");
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
#ifdef ESP_PLATFORM
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
|
||||
#else
|
||||
NimBLEDevice::setPower(9); /** +9db */
|
||||
#endif
|
||||
|
||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
||||
NimBLEDevice::setSecurityPasskey(123456);
|
||||
|
@ -2,10 +2,10 @@
|
||||
/** NimBLE_Server Demo:
|
||||
*
|
||||
* Demonstrates many of the available features of the NimBLE server library.
|
||||
*
|
||||
*
|
||||
* Created: on March 22 2020
|
||||
* Author: H2zero
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
@ -13,16 +13,16 @@
|
||||
static NimBLEServer* pServer;
|
||||
|
||||
/** None of these are required as they will be handled by the library with defaults. **
|
||||
** Remove as you see fit for your needs */
|
||||
** Remove as you see fit for your needs */
|
||||
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer) {
|
||||
Serial.println("Client connected");
|
||||
Serial.println("Multi-connect support: start advertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
};
|
||||
/** Alternative onConnect() method to extract details of the connection.
|
||||
/** Alternative onConnect() method to extract details of the connection.
|
||||
* See: src/ble_gap.h for the details of the ble_gap_conn_desc struct.
|
||||
*/
|
||||
*/
|
||||
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||
Serial.print("Client address: ");
|
||||
Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||
@ -31,7 +31,7 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
* latency, supervision timeout.
|
||||
* Units; Min/Max Intervals: 1.25 millisecond increments.
|
||||
* Latency: number of intervals allowed to skip.
|
||||
* Timeout: 10 millisecond increments, try for 5x interval time for best results.
|
||||
* Timeout: 10 millisecond increments, try for 5x interval time for best results.
|
||||
*/
|
||||
pServer->updateConnParams(desc->conn_handle, 24, 48, 0, 60);
|
||||
};
|
||||
@ -42,25 +42,25 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc) {
|
||||
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
|
||||
};
|
||||
|
||||
|
||||
/********************* Security handled here **********************
|
||||
****** Note: these are the same return values as defaults ********/
|
||||
uint32_t onPassKeyRequest(){
|
||||
Serial.println("Server Passkey Request");
|
||||
/** This should return a random 6 digit number for security
|
||||
/** This should return a random 6 digit number for security
|
||||
* or make your own static passkey as done here.
|
||||
*/
|
||||
return 123456;
|
||||
return 123456;
|
||||
};
|
||||
|
||||
bool onConfirmPIN(uint32_t pass_key){
|
||||
Serial.print("The passkey YES/NO number: ");Serial.println(pass_key);
|
||||
/** Return false if passkeys don't match. */
|
||||
return true;
|
||||
return true;
|
||||
};
|
||||
|
||||
void onAuthenticationComplete(ble_gap_conn_desc* desc){
|
||||
/** Check that encryption was successful, if not we disconnect the client */
|
||||
/** Check that encryption was successful, if not we disconnect the client */
|
||||
if(!desc->sec_state.encrypted) {
|
||||
NimBLEDevice::getServer()->disconnect(desc->conn_handle);
|
||||
Serial.println("Encrypt connection failed - disconnecting client");
|
||||
@ -83,7 +83,7 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
Serial.print(": onWrite(), value: ");
|
||||
Serial.println(pCharacteristic->getValue().c_str());
|
||||
};
|
||||
/** Called before notification or indication is sent,
|
||||
/** Called before notification or indication is sent,
|
||||
* the value can be changed here before sending if desired.
|
||||
*/
|
||||
void onNotify(NimBLECharacteristic* pCharacteristic) {
|
||||
@ -99,7 +99,7 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
str += status;
|
||||
str += ", return code: ";
|
||||
str += code;
|
||||
str += ", ";
|
||||
str += ", ";
|
||||
str += NimBLEUtils::returnCodeToString(code);
|
||||
Serial.println(str);
|
||||
};
|
||||
@ -123,8 +123,8 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
||||
Serial.println(str);
|
||||
};
|
||||
};
|
||||
|
||||
/** Handler class for descriptor actions */
|
||||
|
||||
/** Handler class for descriptor actions */
|
||||
class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
|
||||
void onWrite(NimBLEDescriptor* pDescriptor) {
|
||||
std::string dscVal = pDescriptor->getValue();
|
||||
@ -139,7 +139,7 @@ class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
|
||||
};
|
||||
|
||||
|
||||
/** Define callback instances globally to use for multiple Charateristics \ Descriptors */
|
||||
/** Define callback instances globally to use for multiple Charateristics \ Descriptors */
|
||||
static DescriptorCallbacks dscCallbacks;
|
||||
static CharacteristicCallbacks chrCallbacks;
|
||||
|
||||
@ -152,8 +152,12 @@ void setup() {
|
||||
NimBLEDevice::init("NimBLE-Arduino");
|
||||
|
||||
/** Optional: set the transmit power, default is 3db */
|
||||
#ifdef ESP_PLATFORM
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
|
||||
|
||||
#else
|
||||
NimBLEDevice::setPower(9); /** +9db */
|
||||
#endif
|
||||
|
||||
/** Set the IO capabilities of the device, each option will trigger a different pairing method.
|
||||
* BLE_HS_IO_DISPLAY_ONLY - Passkey pairing
|
||||
* BLE_HS_IO_DISPLAY_YESNO - Numeric comparison pairing
|
||||
@ -164,10 +168,10 @@ void setup() {
|
||||
|
||||
/** 2 different ways to set security - both calls achieve the same result.
|
||||
* no bonding, no man in the middle protection, secure connections.
|
||||
*
|
||||
* These are the default values, only shown here for demonstration.
|
||||
*/
|
||||
//NimBLEDevice::setSecurityAuth(false, false, true);
|
||||
*
|
||||
* These are the default values, only shown here for demonstration.
|
||||
*/
|
||||
//NimBLEDevice::setSecurityAuth(false, false, true);
|
||||
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
|
||||
|
||||
pServer = NimBLEDevice::createServer();
|
||||
@ -182,7 +186,7 @@ void setup() {
|
||||
NIMBLE_PROPERTY::READ_ENC | // only allow reading if paired / encrypted
|
||||
NIMBLE_PROPERTY::WRITE_ENC // only allow writing if paired / encrypted
|
||||
);
|
||||
|
||||
|
||||
pBeefCharacteristic->setValue("Burger");
|
||||
pBeefCharacteristic->setCallbacks(&chrCallbacks);
|
||||
|
||||
@ -191,10 +195,10 @@ void setup() {
|
||||
* However we must cast the returned reference to the correct type as the method
|
||||
* only returns a pointer to the base NimBLEDescriptor class.
|
||||
*/
|
||||
NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904");
|
||||
NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904");
|
||||
pBeef2904->setFormat(NimBLE2904::FORMAT_UTF8);
|
||||
pBeef2904->setCallbacks(&dscCallbacks);
|
||||
|
||||
|
||||
|
||||
NimBLEService* pBaadService = pServer->createService("BAAD");
|
||||
NimBLECharacteristic* pFoodCharacteristic = pBaadService->createCharacteristic(
|
||||
@ -214,7 +218,7 @@ void setup() {
|
||||
/** Custom descriptor: Arguments are UUID, Properties, max length in bytes of the value */
|
||||
NimBLEDescriptor* pC01Ddsc = pFoodCharacteristic->createDescriptor(
|
||||
"C01D",
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE|
|
||||
NIMBLE_PROPERTY::WRITE_ENC, // only allow writing if paired / encrypted
|
||||
20
|
||||
@ -222,7 +226,7 @@ void setup() {
|
||||
pC01Ddsc->setValue("Send it back!");
|
||||
pC01Ddsc->setCallbacks(&dscCallbacks);
|
||||
|
||||
/** Start the services when finished creating all Characteristics and Descriptors */
|
||||
/** Start the services when finished creating all Characteristics and Descriptors */
|
||||
pDeadService->start();
|
||||
pBaadService->start();
|
||||
|
||||
@ -251,6 +255,6 @@ void loop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delay(2000);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
"name": "NimBLE-Arduino",
|
||||
"keywords": "esp32, bluetooth",
|
||||
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
|
||||
"version": "1.3.6",
|
||||
"version": "1.4.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32"
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
name=NimBLE-Arduino
|
||||
version=1.3.6
|
||||
version=1.4.0
|
||||
author=h2zero
|
||||
maintainer=h2zero <powellperalta@gmail.com>
|
||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||
paragraph=This is a more updated and lower resource alternative to the original bluedroid BLE library for esp32. Uses 50% less flash space and approximately 100KB less ram with the same functionality. Nearly 100% compatible with existing application code, migration guide included.
|
||||
url=https://github.com/h2zero/NimBLE-Arduino
|
||||
category=Communication
|
||||
architectures=esp32
|
||||
architectures=esp32,arm-ble
|
||||
includes=NimBLEDevice.h
|
@ -22,11 +22,11 @@
|
||||
#include "NimBLE2904.h"
|
||||
|
||||
|
||||
NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
|
||||
NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacteristic)
|
||||
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904),
|
||||
BLE_GATT_CHR_F_READ,
|
||||
sizeof(BLE2904_Data),
|
||||
pCharacterisitic)
|
||||
pCharacteristic)
|
||||
{
|
||||
m_data.m_format = 0;
|
||||
m_data.m_exponent = 0;
|
||||
|
@ -156,7 +156,7 @@ std::string NimBLEAddress::toString() const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this address is equal to another.
|
||||
* @brief Convenience operator to check if this address is equal to another.
|
||||
*/
|
||||
bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
|
||||
return memcmp(rhs.m_address, m_address, sizeof m_address) == 0;
|
||||
@ -164,7 +164,7 @@ bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this address is not equal to another.
|
||||
* @brief Convenience operator to check if this address is not equal to another.
|
||||
*/
|
||||
bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
@ -186,7 +186,7 @@ NimBLEAddress::operator std::string() const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to convert the native address representation to uint_64.
|
||||
* @brief Convenience operator to convert the native address representation to uint_64.
|
||||
*/
|
||||
NimBLEAddress::operator uint64_t() const {
|
||||
uint64_t address = 0;
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||
|
||||
|
||||
@ -50,9 +52,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getAddress() {
|
||||
* @brief Get the advertisement type.
|
||||
* @return The advertising type the device is reporting:
|
||||
* * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising
|
||||
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertisng - high duty cycle
|
||||
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertising - high duty cycle
|
||||
* * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response
|
||||
* * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertisng - not connectable
|
||||
* * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertising - not connectable
|
||||
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||
@ -64,12 +66,12 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||
* @brief Get the appearance.
|
||||
*
|
||||
* A %BLE device can declare its own appearance. The appearance is how it would like to be shown to an end user
|
||||
* typcially in the form of an icon.
|
||||
* typically in the form of an icon.
|
||||
*
|
||||
* @return The appearance of the advertised device.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -87,7 +89,7 @@ uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||
* @return The advertisement interval in 0.625ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -105,7 +107,7 @@ uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||
* @return The preferred min connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -123,7 +125,7 @@ uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||
* @return The preferred max connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -141,7 +143,7 @@ uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||
* @return The manufacturer data of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -159,7 +161,7 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||
* @return The URI data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getURI() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -177,7 +179,7 @@ std::string NimBLEAdvertisedDevice::getURI() {
|
||||
* @return The name of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getName() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
||||
@ -214,7 +216,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
||||
* @brief Get the number of target addresses.
|
||||
* @return The number of addresses.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||
@ -232,7 +234,7 @@ size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0xFF;
|
||||
size_t data_loc = ULONG_MAX;
|
||||
|
||||
index++;
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||
@ -242,7 +244,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
||||
}
|
||||
|
||||
if(count > 0 && data_loc != 0xFF) {
|
||||
if(count > 0 && data_loc != ULONG_MAX) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
@ -264,9 +266,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
size_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
if(data_loc != ULONG_MAX) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > bytes) {
|
||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||
@ -286,9 +288,9 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t index = 0;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
size_t data_loc = findServiceData(index, &bytes);
|
||||
size_t plSize = m_payload.size() - 2;
|
||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||
uint8_t plSize = m_payload.size() - 2;
|
||||
|
||||
while(data_loc < plSize) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -306,16 +308,16 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of the serice data at the index.
|
||||
* @brief Get the UUID of the service data at the index.
|
||||
* @param [in] index The index of the service data UUID requested.
|
||||
* @return The advertised service data UUID or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
size_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
if(data_loc != ULONG_MAX) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length >= bytes) {
|
||||
return NimBLEUUID(field->value, bytes, false);
|
||||
@ -330,10 +332,10 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
* @brief Find the service data at the index.
|
||||
* @param [in] index The index of the service data to find.
|
||||
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
||||
* @return The index in the vector where the data is located, 0xFF if not found.
|
||||
* @return The index in the vector where the data is located, ULONG_MAX if not found.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
uint8_t data_loc = 0;
|
||||
size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
size_t data_loc = 0;
|
||||
uint8_t found = 0;
|
||||
|
||||
*bytes = 0;
|
||||
@ -358,7 +360,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
return ULONG_MAX;
|
||||
}
|
||||
|
||||
|
||||
@ -366,7 +368,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
* @brief Get the count of advertised service data UUIDS
|
||||
* @return The number of service data UUIDS in the vector.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||
@ -384,7 +386,7 @@ size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
uint8_t uuidBytes = 0;
|
||||
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
@ -431,7 +433,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
* @brief Get the number of services advertised
|
||||
* @return The count of services in the advertising packet.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
||||
@ -446,7 +448,7 @@ size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check advertised services for existance of the required UUID
|
||||
* @brief Check advertised services for existence of the required UUID
|
||||
* @param [in] uuid The service uuid to look for in the advertisement.
|
||||
* @return Return true if service is advertised
|
||||
*/
|
||||
@ -467,7 +469,7 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
||||
* @return The TX Power of the advertised device.
|
||||
*/
|
||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@ -581,17 +583,60 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||
} // haveTXPower
|
||||
|
||||
|
||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t data = 0;
|
||||
uint8_t length = m_payload.size();
|
||||
uint8_t count = 0;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Get the set ID of the extended advertisement.
|
||||
* @return The set ID.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getSetId() {
|
||||
return m_sid;
|
||||
} // getSetId
|
||||
|
||||
if(length < 2) {
|
||||
|
||||
/**
|
||||
* @brief Get the primary PHY used by this advertisement.
|
||||
* @return The PHY type, one of:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getPrimaryPhy() {
|
||||
return m_primPhy;
|
||||
} // getPrimaryPhy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the primary PHY used by this advertisement.
|
||||
* @return The PHY type, one of:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_2M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() {
|
||||
return m_secPhy;
|
||||
} // getSecondaryPhy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the periodic interval of the advertisement.
|
||||
* @return The periodic advertising interval, 0 if not periodic advertising.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() {
|
||||
return m_periodicItvl;
|
||||
} // getPeriodicInterval
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t * data_loc) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
size_t length = m_payload.size();
|
||||
size_t data = 0;
|
||||
uint8_t count = 0;
|
||||
|
||||
if (length < 3) {
|
||||
return count;
|
||||
}
|
||||
|
||||
while (length > 1) {
|
||||
while (length > 2) {
|
||||
field = (ble_hs_adv_field*)&m_payload[data];
|
||||
|
||||
if (field->length >= length) {
|
||||
@ -599,7 +644,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
}
|
||||
|
||||
if (field->type == type) {
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||
count += field->length / 2;
|
||||
@ -625,8 +670,8 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
break;
|
||||
}
|
||||
|
||||
if(data_loc != nullptr) {
|
||||
if(index == 0 || count >= index) {
|
||||
if (data_loc != nullptr) {
|
||||
if (index == 0 || count >= index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -636,7 +681,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
if(data_loc != nullptr && field != nullptr) {
|
||||
if (data_loc != nullptr && field != nullptr) {
|
||||
*data_loc = data;
|
||||
}
|
||||
|
||||
@ -657,8 +702,13 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
||||
* @brief Set the adFlag for this device.
|
||||
* @param [in] advType The advertisement flag data from the advertisement.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType, bool isLegacyAdv) {
|
||||
m_advType = advType;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_isLegacyAdv = isLegacyAdv;
|
||||
#else
|
||||
(void)isLegacyAdv;
|
||||
#endif
|
||||
} // setAdvType
|
||||
|
||||
|
||||
@ -703,10 +753,10 @@ std::string NimBLEAdvertisedDevice::toString() {
|
||||
res += val;
|
||||
}
|
||||
|
||||
if(haveServiceData()) {
|
||||
size_t count = getServiceDataCount();
|
||||
if (haveServiceData()) {
|
||||
uint8_t count = getServiceDataCount();
|
||||
res += "\nService Data:";
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
||||
res += ", Data: " + getServiceData(i);
|
||||
}
|
||||
@ -744,7 +794,7 @@ void NimBLEAdvertisedDevice::setPayload(const uint8_t *payload, uint8_t length,
|
||||
|
||||
/**
|
||||
* @brief Get the length of the advertisement data in the payload.
|
||||
* @return The number of bytes in the payload that is from the advertisment.
|
||||
* @return The number of bytes in the payload that is from the advertisement.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getAdvLength() {
|
||||
return m_advLength;
|
||||
@ -781,5 +831,34 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||
return m_payload.size();
|
||||
} // getPayloadLength
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if this device is advertising as connectable.
|
||||
* @return True if the device is connectable.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isConnectable() {
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
if (m_isLegacyAdv) {
|
||||
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND ||
|
||||
m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
||||
}
|
||||
#endif
|
||||
return (m_advType & BLE_HCI_ADV_CONN_MASK) ||
|
||||
(m_advType & BLE_HCI_ADV_DIRECT_MASK);
|
||||
} // isConnectable
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if this advertisement is a legacy or extended type
|
||||
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isLegacyAdvertisement() {
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
return m_isLegacyAdv;
|
||||
# else
|
||||
return true;
|
||||
#endif
|
||||
} // isLegacyAdvertisement
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
||||
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
std::string getName();
|
||||
int getRSSI();
|
||||
NimBLEScan* getScan();
|
||||
size_t getServiceDataCount();
|
||||
uint8_t getServiceDataCount();
|
||||
std::string getServiceData(uint8_t index = 0);
|
||||
std::string getServiceData(const NimBLEUUID &uuid);
|
||||
|
||||
@ -111,9 +111,9 @@ public:
|
||||
|
||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||
size_t getServiceUUIDCount();
|
||||
uint8_t getServiceUUIDCount();
|
||||
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||
size_t getTargetAddressCount();
|
||||
uint8_t getTargetAddressCount();
|
||||
int8_t getTXPower();
|
||||
uint8_t* getPayload();
|
||||
uint8_t getAdvLength();
|
||||
@ -133,16 +133,30 @@ public:
|
||||
bool haveTargetAddress();
|
||||
bool haveURI();
|
||||
std::string toString();
|
||||
bool isConnectable();
|
||||
bool isLegacyAdvertisement();
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
uint8_t getSetId();
|
||||
uint8_t getPrimaryPhy();
|
||||
uint8_t getSecondaryPhy();
|
||||
uint16_t getPeriodicInterval();
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class NimBLEScan;
|
||||
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setAdvType(uint8_t advType, bool isLegacyAdv);
|
||||
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
||||
void setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
void setSetId(uint8_t sid) { m_sid = sid; }
|
||||
void setPrimaryPhy(uint8_t phy) { m_primPhy = phy; }
|
||||
void setSecondaryPhy(uint8_t phy) { m_secPhy = phy; }
|
||||
void setPeriodicInterval(uint16_t itvl) { m_periodicItvl = itvl; }
|
||||
#endif
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t * data_loc = nullptr);
|
||||
size_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
|
||||
NimBLEAddress m_address = NimBLEAddress("");
|
||||
uint8_t m_advType;
|
||||
@ -150,6 +164,13 @@ private:
|
||||
time_t m_timestamp;
|
||||
bool m_callbackSent;
|
||||
uint8_t m_advLength;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
bool m_isLegacyAdv;
|
||||
uint8_t m_sid;
|
||||
uint8_t m_primPhy;
|
||||
uint8_t m_secPhy;
|
||||
uint16_t m_periodicItvl;
|
||||
#endif
|
||||
|
||||
std::vector<uint8_t> m_payload;
|
||||
};
|
||||
|
@ -14,7 +14,9 @@
|
||||
*
|
||||
*/
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#if (defined(CONFIG_BT_ENABLED) && \
|
||||
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||
!CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
|
||||
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
@ -412,7 +414,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
// If already advertising just return
|
||||
if(ble_gap_adv_active()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Advertising already active");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Save the duration incase of host reset so we can restart with the same params
|
||||
@ -432,15 +434,16 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
if(m_advParams.conn_mode == BLE_GAP_CONN_MODE_NON) {
|
||||
if(!m_scanResp) {
|
||||
m_advParams.disc_mode = BLE_GAP_DISC_MODE_NON;
|
||||
m_advData.flags = BLE_HS_ADV_F_BREDR_UNSUP;
|
||||
// non-connectable advertising does not require AD flags.
|
||||
m_advData.flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
|
||||
if (!m_customAdvData && !m_advDataSet) {
|
||||
//start with 3 bytes for the flags data
|
||||
uint8_t payloadLen = (2 + 1);
|
||||
//start with 3 bytes for the flags data if required
|
||||
uint8_t payloadLen = (m_advData.flags > 0) ? (2 + 1) : 0;
|
||||
if(m_advData.mfg_data_len > 0)
|
||||
payloadLen += (2 + m_advData.mfg_data_len);
|
||||
|
||||
@ -625,7 +628,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
&m_advParams,
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
||||
NimBLEAdvertising::handleGapEvent,
|
||||
(pServer != nullptr) ? (void*)pServer : (void*)this);
|
||||
(void*)this);
|
||||
#else
|
||||
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
|
||||
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
|
||||
@ -634,6 +637,10 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
|
||||
break;
|
||||
|
||||
case BLE_HS_EINVAL:
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Duration too long");
|
||||
break;
|
||||
@ -656,24 +663,26 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
||||
return (rc == 0);
|
||||
return (rc == 0 || rc == BLE_HS_EALREADY);
|
||||
} // start
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
void NimBLEAdvertising::stop() {
|
||||
bool NimBLEAdvertising::stop() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||
|
||||
int rc = ble_gap_adv_stop();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
||||
return true;
|
||||
} // stop
|
||||
|
||||
|
||||
@ -749,7 +758,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceded");
|
||||
NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceeded");
|
||||
return;
|
||||
}
|
||||
m_payload.append(data);
|
||||
@ -1026,4 +1035,4 @@ std::string NimBLEAdvertisementData::getPayload() {
|
||||
return m_payload;
|
||||
} // getPayload
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
||||
|
@ -15,7 +15,9 @@
|
||||
#ifndef MAIN_BLEADVERTISING_H_
|
||||
#define MAIN_BLEADVERTISING_H_
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#if (defined(CONFIG_BT_ENABLED) && \
|
||||
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||
!CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
|
||||
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
#include "host/ble_gap.h"
|
||||
@ -89,7 +91,7 @@ public:
|
||||
void addServiceUUID(const char* serviceUUID);
|
||||
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||
void stop();
|
||||
bool stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setName(const std::string &name);
|
||||
void setManufacturerData(const std::string &data);
|
||||
@ -111,6 +113,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEServer;
|
||||
|
||||
void onHostSync();
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
@ -134,5 +137,5 @@ private:
|
||||
std::vector<uint8_t> m_uri;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
||||
#endif /* MAIN_BLEADVERTISING_H_ */
|
||||
|
@ -54,7 +54,7 @@ struct Has_c_str_len<T, decltype(void(std::declval<T &>().c_str())),
|
||||
/**
|
||||
* @brief A specialized container class to hold BLE attribute values.
|
||||
* @details This class is designed to be more memory efficient than using\n
|
||||
* standard container types for value storage, while being convertable to\n
|
||||
* standard container types for value storage, while being convertible to\n
|
||||
* many different container classes.
|
||||
*/
|
||||
class NimBLEAttValue
|
||||
|
@ -130,7 +130,7 @@ void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) {
|
||||
*/
|
||||
void NimBLEBeacon::setMinor(uint16_t minor) {
|
||||
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
||||
} // setMinior
|
||||
} // setMinor
|
||||
|
||||
|
||||
/**
|
||||
|
@ -126,8 +126,8 @@ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a descriptor from the characterisitc.
|
||||
* @param[in] pDescriptor A pointer to the descriptor instance to remove from the characterisitc.
|
||||
* @brief Remove a descriptor from the characteristic.
|
||||
* @param[in] pDescriptor A pointer to the descriptor instance to remove from the characteristic.
|
||||
* @param[in] deleteDsc If true it will delete the descriptor instance and free it's resources.
|
||||
*/
|
||||
void NimBLECharacteristic::removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc) {
|
||||
@ -273,11 +273,13 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
||||
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
|
||||
switch(ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8) {
|
||||
rc = ble_gap_conn_find(conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
rc = ble_gap_conn_find(conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||
pCharacteristic->m_value.size() <= (ble_att_mtu(desc.conn_handle) - 3)) {
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc);
|
||||
}
|
||||
@ -440,7 +442,7 @@ void NimBLECharacteristic::notify(const uint8_t* value, size_t length, bool is_n
|
||||
!(m_properties & NIMBLE_PROPERTY::INDICATE))
|
||||
{
|
||||
NIMBLE_LOGE(LOG_TAG,
|
||||
"<< notify-Error; Notify/indicate not enabled for characterisitc: %s",
|
||||
"<< notify-Error; Notify/indicate not enabled for characteristic: %s",
|
||||
std::string(getUUID()).c_str());
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,11 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee
|
||||
m_pTaskData = nullptr;
|
||||
m_connEstablished = false;
|
||||
m_lastErr = 0;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_phyMask = BLE_GAP_LE_PHY_1M_MASK |
|
||||
BLE_GAP_LE_PHY_2M_MASK |
|
||||
BLE_GAP_LE_PHY_CODED_MASK;
|
||||
#endif
|
||||
|
||||
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
||||
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
||||
@ -94,6 +99,8 @@ NimBLEClient::~NimBLEClient() {
|
||||
delete m_pClientCallbacks;
|
||||
}
|
||||
|
||||
ble_npl_callout_deinit(&m_dcTimer);
|
||||
|
||||
} // ~NimBLEClient
|
||||
|
||||
|
||||
@ -150,35 +157,35 @@ size_t NimBLEClient::deleteService(const NimBLEUUID &uuid) {
|
||||
|
||||
/**
|
||||
* @brief Connect to the BLE Server.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(bool deleteAttibutes) {
|
||||
return connect(m_peerAddress, deleteAttibutes);
|
||||
bool NimBLEClient::connect(bool deleteAttributes) {
|
||||
return connect(m_peerAddress, deleteAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect to an advertising device.
|
||||
* @param [in] device The device to connect to.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes) {
|
||||
bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool deleteAttributes) {
|
||||
NimBLEAddress address(device->getAddress());
|
||||
return connect(address, deleteAttibutes);
|
||||
return connect(address, deleteAttributes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect to the BLE Server.
|
||||
* @param [in] address The address of the server.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
||||
bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
||||
|
||||
if(!NimBLEDevice::m_synced) {
|
||||
@ -218,9 +225,22 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
||||
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
|
||||
*/
|
||||
do {
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
rc = ble_gap_ext_connect(NimBLEDevice::m_own_addr_type,
|
||||
&peerAddr_t,
|
||||
m_connectTimeout,
|
||||
m_phyMask,
|
||||
&m_pConnParams,
|
||||
&m_pConnParams,
|
||||
&m_pConnParams,
|
||||
NimBLEClient::handleGapEvent,
|
||||
this);
|
||||
|
||||
#else
|
||||
rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, &peerAddr_t,
|
||||
m_connectTimeout, &m_pConnParams,
|
||||
NimBLEClient::handleGapEvent, this);
|
||||
#endif
|
||||
switch (rc) {
|
||||
case 0:
|
||||
break;
|
||||
@ -239,7 +259,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
// Already attemting to connect to this device, cancel the previous
|
||||
// Already attempting to connect to this device, cancel the previous
|
||||
// attempt and report failure here so we don't get 2 connections.
|
||||
NIMBLE_LOGE(LOG_TAG, "Already attempting to connect to %s - cancelling",
|
||||
std::string(m_peerAddress).c_str());
|
||||
@ -297,7 +317,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Connection established");
|
||||
}
|
||||
|
||||
if(deleteAttibutes) {
|
||||
if(deleteAttributes) {
|
||||
deleteServices();
|
||||
}
|
||||
|
||||
@ -370,8 +390,8 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
||||
// We use a timer to detect a controller error in the event that it does
|
||||
// not inform the stack when disconnection is complete.
|
||||
// This is a common error in certain esp-idf versions.
|
||||
// The disconnect timeout time is the supervison timeout time + 1 second.
|
||||
// In the case that the event happenss shortly after the supervision timeout
|
||||
// The disconnect timeout time is the supervision timeout time + 1 second.
|
||||
// In the case that the event happens shortly after the supervision timeout
|
||||
// we don't want to prematurely reset the host.
|
||||
ble_npl_time_t ticks;
|
||||
ble_npl_time_ms_to_ticks((desc.supervision_timeout + 100) * 10, &ticks);
|
||||
@ -395,8 +415,23 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
||||
} // disconnect
|
||||
|
||||
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Set the connection paramaters to use when connecting to a server.
|
||||
* @brief Set the PHY types to use when connecting to a server.
|
||||
* @param [in] mask A bitmask indicating what PHYS to connect with.\n
|
||||
* The available bits are:
|
||||
* * 0x01 BLE_GAP_LE_PHY_1M_MASK
|
||||
* * 0x02 BLE_GAP_LE_PHY_2M_MASK
|
||||
* * 0x04 BLE_GAP_LE_PHY_CODED_MASK
|
||||
*/
|
||||
void NimBLEClient::setConnectPhy(uint8_t mask) {
|
||||
m_phyMask = mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the connection parameters to use when connecting to a server.
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
|
||||
* @param [in] latency The number of packets allowed to skip (extends max interval).
|
||||
@ -464,8 +499,8 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
*/
|
||||
void NimBLEClient::setDataLen(uint16_t tx_octets) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
|
||||
ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
|
||||
(ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
|
||||
return;
|
||||
#else
|
||||
uint16_t tx_time = (tx_octets + 14) * 8;
|
||||
@ -618,7 +653,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||
{
|
||||
NimBLEUUID uuid128(uuid);
|
||||
uuid128.to128();
|
||||
return getService(uuid128);
|
||||
if(retrieveServices(&uuid128)) {
|
||||
if(m_servicesVector.size() > prev_size) {
|
||||
return m_servicesVector.back();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the request was successful but the 128 bit uuid not found
|
||||
// try again with the 16 bit uuid.
|
||||
@ -626,7 +665,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||
uuid16.to16();
|
||||
// if the uuid was 128 bit but not of the BLE base type this check will fail
|
||||
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
|
||||
return getService(uuid16);
|
||||
if(retrieveServices(&uuid16)) {
|
||||
if(m_servicesVector.size() > prev_size) {
|
||||
return m_servicesVector.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -660,13 +703,29 @@ std::vector<NimBLERemoteService*>* NimBLEClient::getServices(bool refresh) {
|
||||
|
||||
/**
|
||||
* @brief Retrieves the full database of attributes that the peripheral has available.
|
||||
* @return True if successful.
|
||||
*/
|
||||
void NimBLEClient::discoverAttributes() {
|
||||
for(auto svc: *getServices(true)) {
|
||||
for(auto chr: *svc->getCharacteristics(true)) {
|
||||
chr->getDescriptors(true);
|
||||
bool NimBLEClient::discoverAttributes() {
|
||||
deleteServices();
|
||||
|
||||
if (!retrieveServices()){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for(auto svc: m_servicesVector) {
|
||||
if (!svc->retrieveCharacteristics()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto chr: svc->m_characteristicVector) {
|
||||
if (!chr->retrieveDescriptors()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // discoverAttributes
|
||||
|
||||
|
||||
@ -758,7 +817,7 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||
if(error->status == BLE_HS_EDONE) {
|
||||
pTaskData->rc = 0;
|
||||
} else {
|
||||
NIMBLE_LOGE(LOG_TAG, "characteristicDiscCB() rc=%d %s",
|
||||
NIMBLE_LOGE(LOG_TAG, "serviceDiscoveredCB() rc=%d %s",
|
||||
error->status,
|
||||
NimBLEUtils::returnCodeToString(error->status));
|
||||
pTaskData->rc = error->status;
|
||||
@ -766,7 +825,7 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||
|
||||
xTaskNotifyGive(pTaskData->task);
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG,"<< << Service Discovered");
|
||||
NIMBLE_LOGD(LOG_TAG,"<< Service Discovered");
|
||||
return error->status;
|
||||
}
|
||||
|
||||
@ -791,7 +850,7 @@ NimBLEAttValue NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBL
|
||||
}
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<<getValue");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getValue");
|
||||
return ret;
|
||||
} // getValue
|
||||
|
||||
|
@ -38,9 +38,9 @@ class NimBLEAdvertisedDevice;
|
||||
*/
|
||||
class NimBLEClient {
|
||||
public:
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes = true);
|
||||
bool connect(const NimBLEAddress &address, bool deleteAttibutes = true);
|
||||
bool connect(bool deleteAttibutes = true);
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool deleteAttributes = true);
|
||||
bool connect(const NimBLEAddress &address, bool deleteAttributes = true);
|
||||
bool connect(bool deleteAttributes = true);
|
||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
NimBLEAddress getPeerAddress();
|
||||
void setPeerAddress(const NimBLEAddress &address);
|
||||
@ -70,9 +70,12 @@ public:
|
||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void setDataLen(uint16_t tx_octets);
|
||||
void discoverAttributes();
|
||||
bool discoverAttributes();
|
||||
NimBLEConnInfo getConnInfo();
|
||||
int getLastError();
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
void setConnectPhy(uint8_t mask);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
@ -98,6 +101,9 @@ private:
|
||||
NimBLEClientCallbacks* m_pClientCallbacks;
|
||||
ble_task_data_t* m_pTaskData;
|
||||
ble_npl_callout m_dcTimer;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
uint8_t m_phyMask;
|
||||
#endif
|
||||
|
||||
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||
|
||||
@ -131,7 +137,7 @@ public:
|
||||
* @brief Called when server requests to update the connection parameters.
|
||||
* @param [in] pClient A pointer to the calling client object.
|
||||
* @param [in] params A pointer to the struct containing the connection parameters requested.
|
||||
* @return True to accept the parmeters.
|
||||
* @return True to accept the parameters.
|
||||
*/
|
||||
virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params);
|
||||
|
||||
|
@ -155,6 +155,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
struct ble_gap_conn_desc desc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
||||
@ -164,9 +165,13 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
|
||||
switch(ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC: {
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8) {
|
||||
rc = ble_gap_conn_find(conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||
pDescriptor->m_value.size() <= (ble_att_mtu(desc.conn_handle) - 3)) {
|
||||
pDescriptor->m_pCallbacks->onRead(pDescriptor);
|
||||
}
|
||||
|
||||
@ -256,7 +261,7 @@ void NimBLEDescriptor::setValue(const std::vector<uint8_t>& vec) {
|
||||
|
||||
/**
|
||||
* @brief Set the characteristic this descriptor belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptior belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptor belongs to.
|
||||
*/
|
||||
void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
|
||||
m_pCharacteristic = pChar;
|
||||
|
@ -69,7 +69,11 @@ NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
||||
uint32_t NimBLEDevice::m_passkey = 123456;
|
||||
bool NimBLEDevice::m_synced = false;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
# else
|
||||
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
||||
@ -114,6 +118,45 @@ uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DU
|
||||
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Get the instance of the advertising object.
|
||||
* @return A pointer to the advertising object.
|
||||
*/
|
||||
NimBLEExtAdvertising* NimBLEDevice::getAdvertising() {
|
||||
if(m_bleAdvertising == nullptr) {
|
||||
m_bleAdvertising = new NimBLEExtAdvertising();
|
||||
}
|
||||
return m_bleAdvertising;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convenience function to begin advertising.
|
||||
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
bool NimBLEDevice::startAdvertising(uint8_t inst_id,
|
||||
int duration,
|
||||
int max_events) {
|
||||
return getAdvertising()->start(inst_id, duration, max_events);
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convenience function to stop advertising a data set.
|
||||
* @param [in] inst_id The extended advertisement instance ID to stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
bool NimBLEDevice::stopAdvertising(uint8_t inst_id) {
|
||||
return getAdvertising()->stop(inst_id);
|
||||
} // stopAdvertising
|
||||
|
||||
# endif
|
||||
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Get the instance of the advertising object.
|
||||
* @return A pointer to the advertising object.
|
||||
@ -128,17 +171,19 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
||||
|
||||
/**
|
||||
* @brief Convenience function to begin advertising.
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
void NimBLEDevice::startAdvertising() {
|
||||
getAdvertising()->start();
|
||||
bool NimBLEDevice::startAdvertising() {
|
||||
return getAdvertising()->start();
|
||||
} // startAdvertising
|
||||
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Convenience function to stop advertising.
|
||||
* @brief Convenience function to stop all advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
void NimBLEDevice::stopAdvertising() {
|
||||
getAdvertising()->stop();
|
||||
bool NimBLEDevice::stopAdvertising() {
|
||||
return getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
|
||||
@ -757,7 +802,7 @@ void NimBLEDevice::onSync(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Yield for houskeeping before returning to operations.
|
||||
// Yield for housekeeping before returning to operations.
|
||||
// Occasionally triggers exception without.
|
||||
taskYIELD();
|
||||
|
||||
@ -806,7 +851,7 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
||||
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
|
||||
// make sure the linker includes esp32-hal-bt.c so Arduino init doesn't release BLE memory.
|
||||
btStarted();
|
||||
#endif
|
||||
|
||||
|
@ -23,7 +23,11 @@
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#include "NimBLEAdvertising.h"
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# include "NimBLEExtAdvertising.h"
|
||||
# else
|
||||
# include "NimBLEAdvertising.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
@ -139,9 +143,18 @@ public:
|
||||
static void removeIgnored(const NimBLEAddress &address);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
static void startAdvertising();
|
||||
static void stopAdvertising();
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
static NimBLEExtAdvertising* getAdvertising();
|
||||
static bool startAdvertising(uint8_t inst_id,
|
||||
int duration = 0,
|
||||
int max_events = 0);
|
||||
static bool stopAdvertising(uint8_t inst_id);
|
||||
static bool stopAdvertising();
|
||||
# else
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
static bool startAdvertising();
|
||||
static bool stopAdvertising();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
@ -178,6 +191,10 @@ private:
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
friend class NimBLEAdvertising;
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
friend class NimBLEExtAdvertising;
|
||||
friend class NimBLEExtAdvertisement;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void onReset(int reason);
|
||||
@ -194,7 +211,11 @@ private:
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
static NimBLEExtAdvertising* m_bleAdvertising;
|
||||
# else
|
||||
static NimBLEAdvertising* m_bleAdvertising;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
@ -85,8 +85,8 @@ float NimBLEEddystoneTLM::getTemp() {
|
||||
} // getTemp
|
||||
|
||||
/**
|
||||
* @brief Get the count of advertisments sent.
|
||||
* @return The number of advertisments.
|
||||
* @brief Get the count of advertisements sent.
|
||||
* @return The number of advertisements.
|
||||
*/
|
||||
uint32_t NimBLEEddystoneTLM::getCount() {
|
||||
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
|
||||
@ -94,8 +94,8 @@ uint32_t NimBLEEddystoneTLM::getCount() {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertisment time.
|
||||
* @return The advertisment time.
|
||||
* @brief Get the advertisement time.
|
||||
* @return The advertisement time.
|
||||
*/
|
||||
uint32_t NimBLEEddystoneTLM::getTime() {
|
||||
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
|
||||
@ -158,7 +158,7 @@ std::string NimBLEEddystoneTLM::toString() {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the raw data for the beacon advertisment.
|
||||
* @brief Set the raw data for the beacon advertisement.
|
||||
* @param [in] data The raw data to advertise.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setData(const std::string &data) {
|
||||
@ -208,8 +208,8 @@ void NimBLEEddystoneTLM::setTemp(float temp) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisment count.
|
||||
* @param [in] advCount The advertisment number.
|
||||
* @brief Set the advertisement count.
|
||||
* @param [in] advCount The advertisement number.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
|
||||
m_eddystoneData.advCount = advCount;
|
||||
@ -217,8 +217,8 @@ void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisment time.
|
||||
* @param [in] tmil The advertisment time in milliseconds.
|
||||
* @brief Set the advertisement time.
|
||||
* @param [in] tmil The advertisement time in milliseconds.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
|
||||
m_eddystoneData.tmil = tmil;
|
||||
|
@ -152,7 +152,7 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the raw data for the beacon advertisment.
|
||||
* @brief Set the raw data for the beacon advertisement.
|
||||
* @param [in] data The raw data to advertise.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setData(const std::string &data) {
|
||||
|
870
lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
Normal file
870
lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
Normal file
@ -0,0 +1,870 @@
|
||||
/*
|
||||
* NimBLEExtAdvertising.cpp
|
||||
*
|
||||
* Created: on February 6, 2022
|
||||
* Author H2zero
|
||||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && \
|
||||
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||
CONFIG_BT_NIMBLE_EXT_ADV
|
||||
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#else
|
||||
#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||
#endif
|
||||
#include "NimBLEExtAdvertising.h"
|
||||
#include "NimBLEDevice.h"
|
||||
#include "NimBLEServer.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
static NimBLEExtAdvertisingCallbacks defaultCallbacks;
|
||||
static const char* LOG_TAG = "NimBLEExtAdvertising";
|
||||
|
||||
|
||||
/**
|
||||
* @brief Destructor: deletes callback instances if requested.
|
||||
*/
|
||||
NimBLEExtAdvertising::~NimBLEExtAdvertising() {
|
||||
if(m_deleteCallbacks && m_pCallbacks != &defaultCallbacks) {
|
||||
delete m_pCallbacks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Register the extended advertisement data.
|
||||
* @param [in] inst_id The extended advertisement instance ID to assign to this data.
|
||||
* @param [in] adv The extended advertisement instance with the data to set.
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv) {
|
||||
adv.m_params.sid = inst_id;
|
||||
|
||||
// Legacy advertising as connectable requires the scannable flag also.
|
||||
if (adv.m_params.legacy_pdu && adv.m_params.connectable) {
|
||||
adv.m_params.scannable = true;
|
||||
}
|
||||
|
||||
// If connectable or not scannable disable the callback for scan response requests
|
||||
if (adv.m_params.connectable || !adv.m_params.scannable) {
|
||||
adv.m_params.scan_req_notif = false;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||
if (pServer != nullptr) {
|
||||
if (!pServer->m_gattsStarted) {
|
||||
pServer->start();
|
||||
}
|
||||
}
|
||||
|
||||
int rc = ble_gap_ext_adv_configure(inst_id,
|
||||
&adv.m_params,
|
||||
NULL,
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
||||
NimBLEExtAdvertising::handleGapEvent,
|
||||
NULL);
|
||||
#else
|
||||
int rc = ble_gap_ext_adv_configure(inst_id,
|
||||
&data.m_params,
|
||||
NULL,
|
||||
NimBLEExtAdvertising::handleGapEvent,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Advertising config error: rc = %d", rc);
|
||||
} else {
|
||||
os_mbuf *buf;
|
||||
buf = os_msys_get_pkthdr(adv.m_payload.size(), 0);
|
||||
if (!buf) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = os_mbuf_append(buf, &adv.m_payload[0], adv.m_payload.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to copy data: rc = %d", rc);
|
||||
return false;
|
||||
} else {
|
||||
if (adv.m_params.scannable && !adv.m_params.legacy_pdu) {
|
||||
rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
|
||||
} else {
|
||||
rc = ble_gap_ext_adv_set_data(inst_id, buf);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid advertisement data: rc = %d", rc);
|
||||
} else {
|
||||
if (adv.m_advAddress != NimBLEAddress("")) {
|
||||
ble_addr_t addr;
|
||||
memcpy(&addr.val, adv.m_advAddress.getNative(), 6);
|
||||
// Custom advertising address must be random.
|
||||
addr.type = BLE_OWN_ADDR_RANDOM;
|
||||
rc = ble_gap_ext_adv_set_addr(inst_id, &addr);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error setting advertisement address: rc = %d", rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (rc == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the scan response data for a legacy advertisement.
|
||||
* @param [in] inst_id The extended advertisement instance ID to assign to this data.
|
||||
* @param [in] lsr A reference to a NimBLEExtAdvertisement that contains the data.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & lsr) {
|
||||
os_mbuf *buf = os_msys_get_pkthdr(lsr.m_payload.size(), 0);
|
||||
if (!buf) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int rc = os_mbuf_append(buf, &lsr.m_payload[0], lsr.m_payload.size());
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to copy scan data: rc = %d", rc);
|
||||
return false;
|
||||
} else {
|
||||
rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
|
||||
}
|
||||
return (rc == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start extended advertising.
|
||||
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::start(uint8_t inst_id, int duration, int max_events) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Extended Advertising start");
|
||||
|
||||
// If Host is not synced we cannot start advertising.
|
||||
if(!NimBLEDevice::m_synced) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int rc = ble_gap_ext_adv_start(inst_id, duration / 10, max_events);
|
||||
|
||||
switch (rc) {
|
||||
case 0:
|
||||
m_advStatus[inst_id] = true;
|
||||
break;
|
||||
|
||||
case BLE_HS_EINVAL:
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Value Error");
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
|
||||
break;
|
||||
|
||||
case BLE_HS_ETIMEOUT_HCI:
|
||||
case BLE_HS_EOS:
|
||||
case BLE_HS_ECONTROLLER:
|
||||
case BLE_HS_ENOTSYNCED:
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Host Reset");
|
||||
break;
|
||||
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Error enabling advertising; rc=%d, %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
break;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Extended Advertising start");
|
||||
return (rc == 0 || rc == BLE_HS_EALREADY);
|
||||
} // start
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop and remove this instance data from the advertisement set.
|
||||
* @param [in] inst_id The extended advertisement instance to stop advertising.
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::removeInstance(uint8_t inst_id) {
|
||||
if (stop(inst_id)) {
|
||||
int rc = ble_gap_ext_adv_remove(inst_id);
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_remove rc = %d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} // removeInstance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop and remove all advertising instance data.
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::removeAll() {
|
||||
if (stop()) {
|
||||
int rc = ble_gap_ext_adv_clear();
|
||||
if (rc == 0 || rc == BLE_HS_EALREADY) {
|
||||
return true;
|
||||
} else {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_clear rc = %d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} // removeAll
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising this instance data.
|
||||
* @param [in] inst_id The extended advertisement instance to stop advertising.
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::stop(uint8_t inst_id) {
|
||||
int rc = ble_gap_ext_adv_stop(inst_id);
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_advStatus[inst_id] = false;
|
||||
return true;
|
||||
} // stop
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop all advertisements.
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::stop() {
|
||||
int rc = ble_gap_ext_adv_clear();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto it : m_advStatus) {
|
||||
it = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} // stop
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set a callback to call when the advertisement stops.
|
||||
* @param [in] pCallbacks A pointer to a callback to be invoked when an advertisement stops.
|
||||
* @param [in] deleteCallbacks if true callback class will be deleted when advertising is destructed.
|
||||
*/
|
||||
void NimBLEExtAdvertising::setCallbacks(NimBLEExtAdvertisingCallbacks* pCallbacks,
|
||||
bool deleteCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
m_pCallbacks = pCallbacks;
|
||||
m_deleteCallbacks = deleteCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallbacks;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if currently advertising.
|
||||
* @param [in] inst_id The instance ID of the advertised data to get the status of.
|
||||
* @return True if advertising is active.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::isActive(uint8_t inst_id) {
|
||||
return m_advStatus[inst_id];
|
||||
} // isAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if any instances are currently advertising.
|
||||
* @return True if any instance is active.
|
||||
*/
|
||||
bool NimBLEExtAdvertising::isAdvertising() {
|
||||
for (auto it : m_advStatus) {
|
||||
if (it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // isAdvertising
|
||||
|
||||
|
||||
/*
|
||||
* Host reset seems to clear advertising data,
|
||||
* we need clear the flag so it reloads it.
|
||||
*/
|
||||
void NimBLEExtAdvertising::onHostSync() {
|
||||
NIMBLE_LOGD(LOG_TAG, "Host re-synced");
|
||||
for(auto it : m_advStatus) {
|
||||
it = false;
|
||||
}
|
||||
} // onHostSync
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handler for gap events when not using peripheral role.
|
||||
* @param [in] event the event data.
|
||||
* @param [in] arg pointer to the advertising instance.
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEExtAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
(void)arg;
|
||||
NimBLEExtAdvertising* pAdv = NimBLEDevice::getAdvertising();
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
switch (event->adv_complete.reason) {
|
||||
// Don't call the callback if host reset, we want to
|
||||
// preserve the active flag until re-sync to restart advertising.
|
||||
case BLE_HS_ETIMEOUT_HCI:
|
||||
case BLE_HS_EOS:
|
||||
case BLE_HS_ECONTROLLER:
|
||||
case BLE_HS_ENOTSYNCED:
|
||||
NIMBLE_LOGC(LOG_TAG, "host reset, rc = %d", event->adv_complete.reason);
|
||||
NimBLEDevice::onReset(event->adv_complete.reason);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pAdv->m_advStatus[event->adv_complete.instance] = false;
|
||||
pAdv->m_pCallbacks->onStopped(pAdv, event->adv_complete.reason,
|
||||
event->adv_complete.instance);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_SCAN_REQ_RCVD: {
|
||||
pAdv->m_pCallbacks->onScanRequest(pAdv, event->scan_req_rcvd.instance,
|
||||
NimBLEAddress(event->scan_req_rcvd.scan_addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // handleGapEvent
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
void NimBLEExtAdvertisingCallbacks::onStopped(NimBLEExtAdvertising *pAdv,
|
||||
int reason, uint8_t inst_id) {
|
||||
NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onStopped: Default");
|
||||
} // onStopped
|
||||
|
||||
|
||||
void NimBLEExtAdvertisingCallbacks::onScanRequest(NimBLEExtAdvertising *pAdv,
|
||||
uint8_t inst_id, NimBLEAddress addr) {
|
||||
NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onScanRequest: Default");
|
||||
} // onScanRequest
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a BLE extended advertisement.
|
||||
* @param [in] priPhy The primary Phy to advertise on, can be one of:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
* @param [in] secPhy The secondary Phy to advertise on, can be one of:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_2M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
NimBLEExtAdvertisement::NimBLEExtAdvertisement(uint8_t priPhy, uint8_t secPhy)
|
||||
: m_advAddress("")
|
||||
{
|
||||
memset (&m_params, 0, sizeof(m_params));
|
||||
m_params.own_addr_type = NimBLEDevice::m_own_addr_type;
|
||||
m_params.primary_phy = priPhy;
|
||||
m_params.secondary_phy = secPhy;
|
||||
m_params.tx_power = 127;
|
||||
} // NimBLEExtAdvertisement
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets wether the advertisement should use legacy (BLE 4.0, 31 bytes max) advertising.
|
||||
* @param [in] val true = using legacy advertising.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setLegacyAdvertising(bool val) {
|
||||
m_params.legacy_pdu = val;
|
||||
} // setLegacyAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets wether the advertisement has scan response data available.
|
||||
* @param [in] val true = scan response is available.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setScannable(bool val) {
|
||||
m_params.scannable = val;
|
||||
} // setScannable
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the transmission power level for this advertisement.
|
||||
* @param [in] dbm the transmission power to use in dbm.
|
||||
* @details The allowable value range depends on device hardware. \n
|
||||
* The ESP32C3 and ESP32S3 have a range of -27 to +18.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setTxPower(int8_t dbm) {
|
||||
m_params.tx_power = dbm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets wether this advertisement should advertise as a connectable device.
|
||||
* @param [in] val True = connectable.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setConnectable(bool val) {
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
m_params.connectable = val;
|
||||
#endif
|
||||
} // setConnectable
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the address to use for this advertisement.
|
||||
* @param [in] addr The address to use.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setAddress(const NimBLEAddress & addr) {
|
||||
m_advAddress = addr;
|
||||
// Must use random address type.
|
||||
m_params.own_addr_type = BLE_OWN_ADDR_RANDOM;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets The primary channels to advertise on.
|
||||
* @param [in] ch37 Advertise on channel 37.
|
||||
* @param [in] ch38 Advertise on channel 38.
|
||||
* @param [in] ch39 Advertise on channel 39.
|
||||
* @details This will set a bitmask using the input parameters to allow different \n
|
||||
* combinations. If all inputs are false then all 3 channels will be used.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPrimaryChannels(bool ch37, bool ch38, bool ch39) {
|
||||
m_params.channel_map = (ch37 | (ch38 << 1) | (ch39 << 2));
|
||||
} // setPrimaryChannels
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the filtering for the scan filter.
|
||||
* @param [in] scanRequestWhitelistOnly If true, only allow scan requests from those on the white list.
|
||||
* @param [in] connectWhitelistOnly If true, only allow connections from those on the white list.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) {
|
||||
if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_params.filter_policy = BLE_HCI_ADV_FILT_NONE;
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_params.filter_policy = BLE_HCI_ADV_FILT_SCAN;
|
||||
return;
|
||||
}
|
||||
if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_params.filter_policy = BLE_HCI_ADV_FILT_CONN;
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_params.filter_policy = BLE_HCI_ADV_FILT_BOTH;
|
||||
return;
|
||||
}
|
||||
} // setScanFilter
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the peer to directly advertise to.
|
||||
* @param [in] addr The address of the peer to direct the advertisements.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setDirectedPeer(const NimBLEAddress & addr) {
|
||||
ble_addr_t peerAddr;
|
||||
memcpy(&peerAddr.val, addr.getNative(), 6);
|
||||
peerAddr.type = addr.getType();
|
||||
m_params.peer = peerAddr;
|
||||
} // setDirectedPeer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable or disable direct advertisements to the peer set with `NimBLEExtAdvertisement::setDirectedPeer`
|
||||
* @param [in] val true = send directed advertisements to peer.
|
||||
* @param [in] high_duty true = use fast advertising rate, default - true.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setDirected(bool val, bool high_duty) {
|
||||
m_params.directed = val;
|
||||
m_params.high_duty_directed = high_duty;
|
||||
} // setDirected
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the minimum advertising interval.
|
||||
* @param [in] mininterval Minimum value for advertising interval in 0.625ms units, 0 = use default.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setMinInterval(uint32_t mininterval) {
|
||||
m_params.itvl_min = mininterval;
|
||||
} // setMinInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the maximum advertising interval.
|
||||
* @param [in] maxinterval Maximum value for advertising interval in 0.625ms units, 0 = use default.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setMaxInterval(uint32_t maxinterval) {
|
||||
m_params.itvl_max = maxinterval;
|
||||
} // setMaxInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the primary advertising PHY to use
|
||||
* @param [in] phy Can be one of following constants:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPrimaryPhy(uint8_t phy) {
|
||||
m_params.primary_phy = phy;
|
||||
} // setPrimaryPhy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the secondary advertising PHY to use
|
||||
* @param [in] phy Can be one of following constants:
|
||||
* * BLE_HCI_LE_PHY_1M
|
||||
* * BLE_HCI_LE_PHY_2M
|
||||
* * BLE_HCI_LE_PHY_CODED
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setSecondaryPhy(uint8_t phy) {
|
||||
m_params.secondary_phy = phy;
|
||||
} // setSecondaryPhy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets whether the advertisement should be anonymous.
|
||||
* @param [in] val Set to true to enable anonymous advertising.
|
||||
*
|
||||
* @details Anonymous advertising omits the device's address from the advertisement.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setAnonymous(bool val) {
|
||||
m_params.anonymous = val;
|
||||
} // setAnonymous
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets whether the scan response request callback should be called.
|
||||
* @param [in] enable If true the scan response request callback will be called for this advertisement.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::enableScanRequestCallback(bool enable) {
|
||||
m_params.scan_req_notif = enable;
|
||||
} // enableScanRequestCallback
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clears the data stored in this instance, does not change settings.
|
||||
* @details This will clear all data but preserves advertising parameter settings.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::clearData() {
|
||||
std::vector<uint8_t> swap;
|
||||
std::swap(m_payload, swap);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the size of the current data.
|
||||
*/
|
||||
size_t NimBLEExtAdvertisement::getDataSize() {
|
||||
return m_payload.size();
|
||||
} // getDataSize
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisement data.
|
||||
* @param [in] data The data to be set as the payload.
|
||||
* @param [in] length The size of data.
|
||||
* @details This will completely replace any data that was previously set.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setData(const uint8_t * data, size_t length) {
|
||||
m_payload.assign(data, data + length);
|
||||
} // setData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add data to the payload to be advertised.
|
||||
* @param [in] data The data to be added to the payload.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::addData(const std::string &data) {
|
||||
addData((uint8_t*)data.data(), data.length());
|
||||
} // addData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add data to the payload to be advertised.
|
||||
* @param [in] data The data to be added to the payload.
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::addData(const uint8_t * data, size_t length) {
|
||||
m_payload.insert(m_payload.end(), data, data + length);
|
||||
} // addData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the appearance.
|
||||
* @param [in] appearance The appearance code value.
|
||||
*
|
||||
* See also:
|
||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setAppearance(uint16_t appearance) {
|
||||
char cdata[2];
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
|
||||
addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisement flags.
|
||||
* @param [in] flag The flags to be set in the advertisement.
|
||||
* * BLE_HS_ADV_F_DISC_LTD
|
||||
* * BLE_HS_ADV_F_DISC_GEN
|
||||
* * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setFlags(uint8_t flag) {
|
||||
char cdata[3];
|
||||
cdata[0] = 2;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
|
||||
cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||
addData(std::string(cdata, 3));
|
||||
} // setFlags
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set manufacturer specific data.
|
||||
* @param [in] data The manufacturer data to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setManufacturerData(const std::string &data) {
|
||||
char cdata[2];
|
||||
cdata[0] = data.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||
addData(std::string(cdata, 2) + data);
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the URI to advertise.
|
||||
* @param [in] uri The uri to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setURI(const std::string &uri) {
|
||||
char cdata[2];
|
||||
cdata[0] = uri.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_URI;
|
||||
addData(std::string(cdata, 2) + uri);
|
||||
} // setURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete name of this device.
|
||||
* @param [in] name The name to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setName(const std::string &name) {
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||
addData(std::string(cdata, 2) + name);
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set a single service to advertise as a complete list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
setServices(true, uuid.bitSize(), {uuid});
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 16 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 16, v_uuid);
|
||||
} // setCompleteServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 32 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 32, v_uuid);
|
||||
} // setCompleteServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set a single service to advertise as a partial list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPartialServices(const NimBLEUUID &uuid) {
|
||||
setServices(false, uuid.bitSize(), {uuid});
|
||||
} // setPartialServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 16, v_uuid);
|
||||
} // setPartialServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 32, v_uuid);
|
||||
} // setPartialServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Utility function to create the list of service UUID's from a vector.
|
||||
* @param [in] complete If true the vector is the complete set of services.
|
||||
* @param [in] size The bit size of the UUID's in the vector. (16, 32, or 128).
|
||||
* @param [in] v_uuid The vector of service UUID's to advertise.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid)
|
||||
{
|
||||
char cdata[2];
|
||||
cdata[0] = (size / 8) * v_uuid.size() + 1;
|
||||
switch(size) {
|
||||
case 16:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
break;
|
||||
case 32:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
|
||||
break;
|
||||
case 128:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
std::string uuids;
|
||||
|
||||
for(auto &it : v_uuid){
|
||||
if(it.bitSize() != size) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||
return;
|
||||
} else {
|
||||
switch(size) {
|
||||
case 16:
|
||||
uuids += std::string((char*)&it.getNative()->u16.value, 2);
|
||||
break;
|
||||
case 32:
|
||||
uuids += std::string((char*)&it.getNative()->u32.value, 4);
|
||||
break;
|
||||
case 128:
|
||||
uuids += std::string((char*)&it.getNative()->u128.value, 16);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addData(std::string(cdata, 2) + uuids);
|
||||
} // setServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the service data (UUID + data)
|
||||
* @param [in] uuid The UUID to set with the service data.
|
||||
* @param [in] data The data to be associated with the service data advertised.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x16] [UUID16] data
|
||||
cdata[0] = data.length() + 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x20] [UUID32] data
|
||||
cdata[0] = data.length() + 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x21] [UUID128] data
|
||||
cdata[0] = data.length() + 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the short name.
|
||||
* @param [in] name The short name of the device.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setShortName(const std::string &name) {
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||
addData(std::string(cdata, 2) + name);
|
||||
} // setShortName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds Tx power level to the advertisement data.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::addTxPower() {
|
||||
m_params.include_tx_power = 1;
|
||||
} // addTxPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the preferred connection interval parameters.
|
||||
* @param [in] min The minimum interval desired.
|
||||
* @param [in] max The maximum interval desired.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::setPreferredParams(uint16_t min, uint16_t max) {
|
||||
uint8_t data[6];
|
||||
data[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
|
||||
data[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
|
||||
data[2] = min;
|
||||
data[3] = min >> 8;
|
||||
data[4] = max;
|
||||
data[5] = max >> 8;
|
||||
addData(data, 6);
|
||||
} // setPreferredParams
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
|
152
lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h
Normal file
152
lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* NimBLEExtAdvertising.h
|
||||
*
|
||||
* Created: on February 6, 2022
|
||||
* Author H2zero
|
||||
*/
|
||||
|
||||
#ifndef MAIN_BLEEXTADVERTISING_H_
|
||||
#define MAIN_BLEEXTADVERTISING_H_
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && \
|
||||
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||
CONFIG_BT_NIMBLE_EXT_ADV
|
||||
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
#undef min
|
||||
#undef max
|
||||
/**************************/
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUUID.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class NimBLEExtAdvertisingCallbacks;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Extended advertisement data
|
||||
*/
|
||||
class NimBLEExtAdvertisement {
|
||||
public:
|
||||
NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M,
|
||||
uint8_t secPhy = BLE_HCI_LE_PHY_1M);
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setCompleteServices(const NimBLEUUID &uuid);
|
||||
void setCompleteServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setFlags(uint8_t flag);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setURI(const std::string &uri);
|
||||
void setName(const std::string &name);
|
||||
void setPartialServices(const NimBLEUUID &uuid);
|
||||
void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setPartialServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setShortName(const std::string &name);
|
||||
void setData(const uint8_t * data, size_t length);
|
||||
void addData(const std::string &data);
|
||||
void addData(const uint8_t * data, size_t length);
|
||||
void addTxPower();
|
||||
void setPreferredParams(uint16_t min, uint16_t max);
|
||||
void setLegacyAdvertising(bool val);
|
||||
void setConnectable(bool val);
|
||||
void setScannable(bool val);
|
||||
void setMinInterval(uint32_t mininterval);
|
||||
void setMaxInterval(uint32_t maxinterval);
|
||||
void setPrimaryPhy(uint8_t phy);
|
||||
void setSecondaryPhy(uint8_t phy);
|
||||
void setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly);
|
||||
void setDirectedPeer(const NimBLEAddress & addr);
|
||||
void setDirected(bool val, bool high_duty = true);
|
||||
void setAnonymous(bool val);
|
||||
void setPrimaryChannels(bool ch37, bool ch38, bool ch39);
|
||||
void setTxPower(int8_t dbm);
|
||||
void setAddress(const NimBLEAddress & addr);
|
||||
void enableScanRequestCallback(bool enable);
|
||||
void clearData();
|
||||
size_t getDataSize();
|
||||
|
||||
private:
|
||||
friend class NimBLEExtAdvertising;
|
||||
|
||||
void setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid);
|
||||
|
||||
std::vector<uint8_t> m_payload;
|
||||
ble_gap_ext_adv_params m_params;
|
||||
NimBLEAddress m_advAddress;
|
||||
}; // NimBLEExtAdvertisement
|
||||
|
||||
|
||||
/**
|
||||
* @brief Extended advertising class.
|
||||
*/
|
||||
class NimBLEExtAdvertising {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct an extended advertising object.
|
||||
*/
|
||||
NimBLEExtAdvertising() :m_advStatus(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES + 1, false) {}
|
||||
~NimBLEExtAdvertising();
|
||||
bool start(uint8_t inst_id, int duration = 0, int max_events = 0);
|
||||
bool setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv);
|
||||
bool setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & data);
|
||||
bool removeInstance(uint8_t inst_id);
|
||||
bool removeAll();
|
||||
bool stop(uint8_t inst_id);
|
||||
bool stop();
|
||||
bool isActive(uint8_t inst_id);
|
||||
bool isAdvertising();
|
||||
void setCallbacks(NimBLEExtAdvertisingCallbacks* callbacks,
|
||||
bool deleteCallbacks = true);
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEServer;
|
||||
|
||||
void onHostSync();
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
|
||||
bool m_scanResp;
|
||||
bool m_deleteCallbacks;
|
||||
NimBLEExtAdvertisingCallbacks* m_pCallbacks;
|
||||
ble_gap_ext_adv_params m_advParams;
|
||||
std::vector<bool> m_advStatus;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callbacks associated with NimBLEExtAdvertising class.
|
||||
*/
|
||||
class NimBLEExtAdvertisingCallbacks {
|
||||
public:
|
||||
virtual ~NimBLEExtAdvertisingCallbacks() {};
|
||||
|
||||
/**
|
||||
* @brief Handle an advertising stop event.
|
||||
* @param [in] pAdv A convenience pointer to the extended advertising interface.
|
||||
* @param [in] reason The reason code for stopping the advertising.
|
||||
* @param [in] inst_id The instance ID of the advertisement that was stopped.
|
||||
*/
|
||||
virtual void onStopped(NimBLEExtAdvertising *pAdv, int reason, uint8_t inst_id);
|
||||
|
||||
/**
|
||||
* @brief Handle a scan response request.
|
||||
* This is called when a scanning device requests a scan response.
|
||||
* @param [in] pAdv A convenience pointer to the extended advertising interface.
|
||||
* @param [in] inst_id The instance ID of the advertisement that the scan response request was made.
|
||||
* @param [in] addr The address of the device making the request.
|
||||
*/
|
||||
virtual void onScanRequest(NimBLEExtAdvertising *pAdv, uint8_t inst_id, NimBLEAddress addr);
|
||||
}; // NimBLEExtAdvertisingCallbacks
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
|
||||
#endif /* MAIN_BLEADVERTISING_H_ */
|
@ -99,7 +99,7 @@ void NimBLEHIDDevice::manufacturer(std::string name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the Plug n Play characterisc value.
|
||||
* @brief Sets the Plug n Play characteristic value.
|
||||
* @param [in] sig The vendor ID source number.
|
||||
* @param [in] vid The vendor ID number.
|
||||
* @param [in] pid The product ID number.
|
||||
|
@ -266,6 +266,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
|
||||
}
|
||||
}
|
||||
|
||||
if (m_handle == m_endHandle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
desc_filter_t filter = {uuid_filter, &taskData};
|
||||
|
||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||
@ -323,7 +327,11 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
|
||||
{
|
||||
NimBLEUUID uuid128(uuid);
|
||||
uuid128.to128();
|
||||
return getDescriptor(uuid128);
|
||||
if(retrieveDescriptors(&uuid128)) {
|
||||
if(m_descriptorVector.size() > prev_size) {
|
||||
return m_descriptorVector.back();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the request was successful but the 128 bit uuid not found
|
||||
// try again with the 16 bit uuid.
|
||||
@ -331,7 +339,11 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
|
||||
uuid16.to16();
|
||||
// if the uuid was 128 bit but not of the BLE base type this check will fail
|
||||
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
|
||||
return getDescriptor(uuid16);
|
||||
if(retrieveDescriptors(&uuid16)) {
|
||||
if(m_descriptorVector.size() > prev_size) {
|
||||
return m_descriptorVector.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -604,6 +616,7 @@ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, notify_callback notifyC
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setNotify()");
|
||||
|
||||
response = true; // Always write with response as per Bluetooth core specification.
|
||||
return desc->writeValue((uint8_t *)&val, 2, response);
|
||||
} // setNotify
|
||||
|
||||
|
@ -73,8 +73,8 @@ public:
|
||||
|
||||
bool subscribe(bool notifications = true,
|
||||
notify_callback notifyCallback = nullptr,
|
||||
bool response = false);
|
||||
bool unsubscribe(bool response = false);
|
||||
bool response = true);
|
||||
bool unsubscribe(bool response = true);
|
||||
bool registerForNotify(notify_callback notifyCallback,
|
||||
bool notifications = true,
|
||||
bool response = true)
|
||||
|
@ -116,7 +116,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
|
||||
{
|
||||
NimBLEUUID uuid128(uuid);
|
||||
uuid128.to128();
|
||||
return getCharacteristic(uuid128);
|
||||
if (retrieveCharacteristics(&uuid128)) {
|
||||
if(m_characteristicVector.size() > prev_size) {
|
||||
return m_characteristicVector.back();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the request was successful but the 128 bit uuid not found
|
||||
// try again with the 16 bit uuid.
|
||||
@ -124,7 +128,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
|
||||
uuid16.to16();
|
||||
// if the uuid was 128 bit but not of the BLE base type this check will fail
|
||||
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
|
||||
return getCharacteristic(uuid16);
|
||||
if(retrieveCharacteristics(&uuid16)) {
|
||||
if(m_characteristicVector.size() > prev_size) {
|
||||
return m_characteristicVector.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,7 +165,7 @@ std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback for Characterisic discovery.
|
||||
* @brief Callback for Characteristic discovery.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||
@ -248,7 +256,9 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
||||
}
|
||||
}
|
||||
|
||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||
if (m_characteristicVector.size() > 0) {
|
||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||
}
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||
|
@ -34,7 +34,7 @@ NimBLEScan::NimBLEScan() {
|
||||
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
|
||||
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
|
||||
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
|
||||
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||
m_ignoreResults = false;
|
||||
m_pTaskData = nullptr;
|
||||
@ -56,18 +56,27 @@ NimBLEScan::~NimBLEScan() {
|
||||
* @param [in] param Parameter data for this event.
|
||||
*/
|
||||
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
|
||||
NimBLEScan* pScan = (NimBLEScan*)arg;
|
||||
(void)arg;
|
||||
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||
|
||||
switch(event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_EXT_DISC:
|
||||
case BLE_GAP_EVENT_DISC: {
|
||||
if(pScan->m_ignoreResults) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLEAddress advertisedAddress(event->disc.addr);
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
const auto& disc = event->ext_disc;
|
||||
const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
|
||||
const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
|
||||
#else
|
||||
const auto& disc = event->disc;
|
||||
const bool isLegacyAdv = true;
|
||||
const auto event_type = disc.event_type;
|
||||
#endif
|
||||
NimBLEAddress advertisedAddress(disc.addr);
|
||||
|
||||
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
||||
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
||||
@ -79,7 +88,12 @@ NimBLEScan::~NimBLEScan() {
|
||||
|
||||
// If we've seen this device before get a pointer to it from the vector
|
||||
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||
if(it->getAddress() == advertisedAddress) {
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
// Same address but different set ID should create a new advertised device.
|
||||
if (it->getAddress() == advertisedAddress && it->getSetId() == disc.sid) {
|
||||
#else
|
||||
if (it->getAddress() == advertisedAddress) {
|
||||
#endif
|
||||
advertisedDevice = it;
|
||||
break;
|
||||
}
|
||||
@ -87,20 +101,27 @@ NimBLEScan::~NimBLEScan() {
|
||||
|
||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||
// Otherwise just update the relevant parameters of the already known device.
|
||||
if(advertisedDevice == nullptr && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
|
||||
if (advertisedDevice == nullptr &&
|
||||
(!isLegacyAdv || event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
|
||||
// Check if we have reach the scan results limit, ignore this one if so.
|
||||
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
||||
if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
|
||||
{
|
||||
if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
advertisedDevice->setAddress(advertisedAddress);
|
||||
advertisedDevice->setAdvType(event->disc.event_type);
|
||||
advertisedDevice->setAdvType(event_type, isLegacyAdv);
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
advertisedDevice->setSetId(disc.sid);
|
||||
advertisedDevice->setPrimaryPhy(disc.prim_phy);
|
||||
advertisedDevice->setSecondaryPhy(disc.sec_phy);
|
||||
advertisedDevice->setPeriodicInterval(disc.periodic_adv_itvl);
|
||||
#endif
|
||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else if(advertisedDevice != nullptr) {
|
||||
} else if (advertisedDevice != nullptr) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else {
|
||||
// Scan response from unknown device
|
||||
@ -108,14 +129,18 @@ NimBLEScan::~NimBLEScan() {
|
||||
}
|
||||
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
||||
advertisedDevice->setRSSI(disc.rssi);
|
||||
advertisedDevice->setPayload(disc.data, disc.length_data, (isLegacyAdv &&
|
||||
event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP));
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
if (pScan->m_scan_params.filter_duplicates && advertisedDevice->m_callbackSent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If not active scanning or scan response is not available
|
||||
// report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive ||
|
||||
// or extended advertisement scanning, report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive || !isLegacyAdv ||
|
||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||
{
|
||||
@ -123,7 +148,7 @@ NimBLEScan::~NimBLEScan() {
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
|
||||
// Otherwise, wait for the scan response so we can report the complete data.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
@ -139,7 +164,7 @@ NimBLEScan::~NimBLEScan() {
|
||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
||||
event->disc_complete.reason);
|
||||
|
||||
// If a device advertised with scan reponse available and it was not received
|
||||
// If a device advertised with scan response available and it was not received
|
||||
// the callback would not have been invoked, so do it here.
|
||||
if(pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||
@ -186,7 +211,7 @@ void NimBLEScan::setActiveScan(bool active) {
|
||||
* from devices it has not already seen.
|
||||
* @param [in] enabled If true, scanned devices will only be reported once.
|
||||
* @details The controller has a limited buffer and will start reporting
|
||||
* dupicate devices once the limit is reached.
|
||||
* duplicate devices once the limit is reached.
|
||||
*/
|
||||
void NimBLEScan::setDuplicateFilter(bool enabled) {
|
||||
m_scan_params.filter_duplicates = enabled;
|
||||
@ -211,7 +236,7 @@ void NimBLEScan::setLimitedOnly(bool enabled) {
|
||||
* directed, connectable advertising packets not sent to the scanner.
|
||||
* * BLE_HCI_SCAN_FILT_USE_WL (1)
|
||||
* Scanner processes advertisements from white list only. A connectable,\n
|
||||
* directed advertisment is ignored unless it contains scanners address.
|
||||
* directed advertisement is ignored unless it contains scanners address.
|
||||
* * BLE_HCI_SCAN_FILT_NO_WL_INITA (2)
|
||||
* Scanner process all advertising packets (white list not used). A\n
|
||||
* connectable, directed advertisement shall not be ignored if the InitA
|
||||
@ -304,9 +329,28 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||
m_ignoreResults = true;
|
||||
}
|
||||
|
||||
int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type, duration, &m_scan_params,
|
||||
NimBLEScan::handleGapEvent, this);
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
ble_gap_ext_disc_params scan_params;
|
||||
scan_params.passive = m_scan_params.passive;
|
||||
scan_params.itvl = m_scan_params.itvl;
|
||||
scan_params.window = m_scan_params.window;
|
||||
int rc = ble_gap_ext_disc(NimBLEDevice::m_own_addr_type,
|
||||
duration/10,
|
||||
0,
|
||||
m_scan_params.filter_duplicates,
|
||||
m_scan_params.filter_policy,
|
||||
m_scan_params.limited,
|
||||
&scan_params,
|
||||
&scan_params,
|
||||
NimBLEScan::handleGapEvent,
|
||||
NULL);
|
||||
#else
|
||||
int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type,
|
||||
duration,
|
||||
&m_scan_params,
|
||||
NimBLEScan::handleGapEvent,
|
||||
NULL);
|
||||
#endif
|
||||
switch(rc) {
|
||||
case 0:
|
||||
if(!is_continue) {
|
||||
|
@ -61,8 +61,8 @@ void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the keys we will distibute during encryption.
|
||||
* @param [in] init_key A bitmask of the keys we will distibute.\n
|
||||
* @brief Sets the keys we will distribute during encryption.
|
||||
* @param [in] init_key A bitmask of the keys we will distribute.\n
|
||||
* Can be one or more of:
|
||||
* * ESP_BLE_ENC_KEY_MASK (1 << 0)
|
||||
* * ESP_BLE_ID_KEY_MASK (1 << 1)
|
||||
|
@ -42,7 +42,9 @@ NimBLEServer::NimBLEServer() {
|
||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_advertiseOnDisconnect = true;
|
||||
#endif
|
||||
m_svcChanged = false;
|
||||
m_deleteCallbacks = true;
|
||||
} // NimBLEServer
|
||||
@ -139,15 +141,26 @@ NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
* @return An advertising object.
|
||||
*/
|
||||
NimBLEExtAdvertising* NimBLEServer::getAdvertising() {
|
||||
return NimBLEDevice::getAdvertising();
|
||||
} // getAdvertising
|
||||
#endif
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
*
|
||||
* @return An advertising object.
|
||||
*/
|
||||
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
||||
return NimBLEDevice::getAdvertising();
|
||||
} // getAdvertising
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sends a service changed notification and resets the GATT server.
|
||||
@ -240,6 +253,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
||||
} // disconnect
|
||||
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Set the server to automatically start advertising when a client disconnects.
|
||||
* @param [in] aod true == advertise, false == don't advertise.
|
||||
@ -247,7 +261,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
||||
void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
||||
m_advertiseOnDisconnect = aod;
|
||||
} // advertiseOnDisconnect
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return the number of connected clients.
|
||||
@ -323,8 +337,9 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
* @param [in] param
|
||||
*
|
||||
*/
|
||||
/*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEServer* server = (NimBLEServer*)arg;
|
||||
/*STATIC*/
|
||||
int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEServer* server = NimBLEDevice::getServer();
|
||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
||||
NimBLEUtils::gapEventToString(event->type));
|
||||
int rc = 0;
|
||||
@ -336,7 +351,9 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising */
|
||||
NIMBLE_LOGE(LOG_TAG, "Connection failed");
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::startAdvertising();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||
@ -356,7 +373,7 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT: {
|
||||
// If Host reset tell the device now before returning to prevent
|
||||
// any errors caused by calling host functions before resyncing.
|
||||
// any errors caused by calling host functions before resync.
|
||||
switch(event->disconnect.reason) {
|
||||
case BLE_HS_ETIMEOUT_HCI:
|
||||
case BLE_HS_EOS:
|
||||
@ -381,9 +398,11 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
server->m_pServerCallbacks->onDisconnect(server);
|
||||
server->m_pServerCallbacks->onDisconnect(server, &event->disconnect.conn);
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
if(server->m_advertiseOnDisconnect) {
|
||||
server->startAdvertising();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_DISCONNECT
|
||||
|
||||
@ -471,11 +490,15 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "Advertising Complete");
|
||||
NimBLEDevice::getAdvertising()->advCompleteCB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
|
||||
return NimBLEExtAdvertising::handleGapEvent(event, arg);
|
||||
#else
|
||||
return NimBLEAdvertising::handleGapEvent(event, arg);
|
||||
#endif
|
||||
// BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
|
||||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
|
||||
@ -613,7 +636,7 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCa
|
||||
* @brief Remove a service from the server.
|
||||
*
|
||||
* @details Immediately removes access to the service by clients, sends a service changed indication,
|
||||
* and removes the service (if applicable) from the advertisments.
|
||||
* and removes the service (if applicable) from the advertisements.
|
||||
* The service is not deleted unless the deleteSvc parameter is true, otherwise the service remains
|
||||
* available and can be re-added in the future. If desired a removed but not deleted service can
|
||||
* be deleted later by calling this method with deleteSvc set to true.
|
||||
@ -652,7 +675,9 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
||||
|
||||
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
||||
serviceChanged();
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -715,22 +740,52 @@ void NimBLEServer::resetGATT() {
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
*
|
||||
* Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||
* @return True if advertising started successfully.
|
||||
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* retrieving the advertising object and invoking start upon it.
|
||||
*/
|
||||
void NimBLEServer::startAdvertising() {
|
||||
NimBLEDevice::startAdvertising();
|
||||
bool NimBLEServer::startAdvertising(uint8_t inst_id,
|
||||
int duration,
|
||||
int max_events) {
|
||||
return getAdvertising()->start(inst_id, duration, max_events);
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* @brief Convenience function to stop advertising a data set.
|
||||
* @param [in] inst_id The extended advertisement instance ID to stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
void NimBLEServer::stopAdvertising() {
|
||||
NimBLEDevice::stopAdvertising();
|
||||
bool NimBLEServer::stopAdvertising(uint8_t inst_id) {
|
||||
return getAdvertising()->stop(inst_id);
|
||||
} // stopAdvertising
|
||||
#endif
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV|| defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
* @return True if advertising started successfully.
|
||||
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* retrieving the advertising object and invoking start upon it.
|
||||
*/
|
||||
bool NimBLEServer::startAdvertising() {
|
||||
return getAdvertising()->start();
|
||||
} // startAdvertising
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
bool NimBLEServer::stopAdvertising() {
|
||||
return getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
|
||||
|
||||
@ -782,8 +837,8 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
*/
|
||||
void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
|
||||
ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
|
||||
(ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
|
||||
return;
|
||||
#else
|
||||
uint16_t tx_time = (tx_octets + 14) * 8;
|
||||
|
@ -25,7 +25,11 @@
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEAddress.h"
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#include "NimBLEExtAdvertising.h"
|
||||
#else
|
||||
#include "NimBLEAdvertising.h"
|
||||
#endif
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
@ -46,11 +50,19 @@ public:
|
||||
NimBLEService* createService(const NimBLEUUID &uuid);
|
||||
void removeService(NimBLEService* service, bool deleteSvc = false);
|
||||
void addService(NimBLEService* service);
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
||||
bool deleteCallbacks = true);
|
||||
void startAdvertising();
|
||||
void stopAdvertising();
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEExtAdvertising* getAdvertising();
|
||||
bool startAdvertising(uint8_t inst_id,
|
||||
int duration = 0,
|
||||
int max_events = 0);
|
||||
bool stopAdvertising(uint8_t inst_id);
|
||||
#else
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
bool startAdvertising();
|
||||
#endif
|
||||
bool stopAdvertising();
|
||||
void start();
|
||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
@ -66,7 +78,9 @@ public:
|
||||
NimBLEConnInfo getPeerInfo(size_t index);
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
void advertiseOnDisconnect(bool);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NimBLEServer();
|
||||
@ -75,9 +89,15 @@ private:
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEAdvertising;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
friend class NimBLEExtAdvertising;
|
||||
friend class NimBLEExtAdvertisementData;
|
||||
#endif
|
||||
|
||||
bool m_gattsStarted;
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
bool m_advertiseOnDisconnect;
|
||||
#endif
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
@ -131,7 +151,7 @@ public:
|
||||
* @brief Handle a client disconnection.
|
||||
* This is called when a client discconnects.
|
||||
* @param [in] pServer A pointer to the %BLE server that received the client disconnection.
|
||||
* @param [in] desc A pointer to the connection description structure containig information
|
||||
* @param [in] desc A pointer to the connection description structure containing information
|
||||
* about the connection.
|
||||
*/
|
||||
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc* desc);
|
||||
@ -139,7 +159,7 @@ public:
|
||||
/**
|
||||
* @brief Called when the connection MTU changes.
|
||||
* @param [in] MTU The new MTU value.
|
||||
* @param [in] desc A pointer to the connection description structure containig information
|
||||
* @param [in] desc A pointer to the connection description structure containing information
|
||||
* about the connection.
|
||||
*/
|
||||
virtual void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc);
|
||||
|
@ -297,7 +297,7 @@ std::string NimBLEUUID::toString() const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this UUID is equal to another.
|
||||
* @brief Convenience operator to check if this UUID is equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
@ -336,7 +336,7 @@ bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this UUID is not equal to another.
|
||||
* @brief Convenience operator to check if this UUID is not equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
@ -344,7 +344,7 @@ bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to convert this UUID to string representation.
|
||||
* @brief Convenience operator to convert this UUID to string representation.
|
||||
* @details This allows passing NimBLEUUID to functions
|
||||
* that accept std::string and/or or it's methods as a parameter.
|
||||
*/
|
||||
|
@ -355,7 +355,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||
* @return A string representation of the advertising flags.
|
||||
*/
|
||||
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||
switch(advType) {
|
||||
case BLE_HCI_ADV_TYPE_ADV_IND : //0
|
||||
return "Undirected - Connectable / Scannable";
|
||||
@ -370,10 +370,10 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||
default:
|
||||
return "Unknown flag";
|
||||
}
|
||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||
(void)advType;
|
||||
return "";
|
||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
|
||||
} // adFlagsToString
|
||||
|
||||
|
||||
|
@ -33,6 +33,7 @@ Features highlight:
|
||||
- Support for up to 32 simultaneous connections.
|
||||
- Legacy and SC (secure connections) SMP support (pairing and bonding).
|
||||
- Advertising Extensions.
|
||||
- Periodic Advertising.
|
||||
- Coded (aka Long Range) and 2M PHYs.
|
||||
- Bluetooth Mesh.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# RELEASE NOTES
|
||||
|
||||
18 March 2020 - Apache NimBLE v1.3.0
|
||||
24 March 2021 - Apache NimBLE v1.4.0
|
||||
|
||||
For full release notes, please visit the
|
||||
[Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes).
|
||||
@ -10,23 +10,12 @@ replaces the proprietary SoftDevice on Nordic chipsets.
|
||||
|
||||
New features in this version of NimBLE include:
|
||||
|
||||
* Support for Bluetooth Core Specification 5.1
|
||||
* New blestress test application
|
||||
* Dialog DA1469x CMAC driver
|
||||
* Support for LE Secure Connections out-of-band (OOB) association model
|
||||
* Support for automated generation of syscfg for ports
|
||||
* Qualification related bugfixes
|
||||
* BLE Mesh improvements - fixes and resync with latest Zephyr code
|
||||
* RIOT OS port fixes and improvements
|
||||
* btshell sample application improvements
|
||||
* improvements for bttester application
|
||||
* Controller duplicates filtering improvements
|
||||
* Multi PHY support improvements
|
||||
* Memory and CPU usage optimizations
|
||||
* Use of packed structs for HCI (code size reduction)
|
||||
* Linux sample improvements
|
||||
* PTS test instructions updates
|
||||
* Clock managements improvements in controller
|
||||
* Support for PHY on Dialog Configurable MAC (CMAC)
|
||||
* Support for PHY on Nordic nRF5340
|
||||
* Support for Apache NuttX port of NimBLE
|
||||
* Controller-to-host flow control support
|
||||
* Support for USB transport
|
||||
* Various bugfixes
|
||||
|
||||
If working on next-generation RTOS and Bluetooth protocol stack
|
||||
sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt
|
||||
|
@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define console_printf printf
|
||||
#define console_printf(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -922,6 +922,10 @@
|
||||
#define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (10)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR
|
||||
#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT (MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT)
|
||||
#endif
|
||||
@ -1043,6 +1047,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_CDB
|
||||
#define MYNEWT_VAL_BLE_MESH_CDB (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL
|
||||
#define MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL (1)
|
||||
#endif
|
||||
@ -1088,6 +1096,14 @@
|
||||
#define MYNEWT_VAL_BLE_MESH_RX_SDU_MAX (72)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS
|
||||
#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (72)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX
|
||||
#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2)
|
||||
#endif
|
||||
@ -1100,6 +1116,63 @@
|
||||
#define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST
|
||||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP
|
||||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (50)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS
|
||||
#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL
|
||||
#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL
|
||||
#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT
|
||||
#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED
|
||||
#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED
|
||||
#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED
|
||||
#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED
|
||||
#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL
|
||||
#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20)
|
||||
#endif
|
||||
|
||||
/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_SETTINGS
|
||||
#define MYNEWT_VAL_BLE_MESH_SETTINGS (0)
|
||||
@ -1158,6 +1231,10 @@
|
||||
#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT
|
||||
#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5)
|
||||
#endif
|
||||
|
||||
/*** @apache-mynewt-nimble/nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
@ -1370,6 +1447,18 @@
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BLE_TX_CCA_ENABLED
|
||||
#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (0)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (CONFIG_BLE_TX_CCA_ENABLED)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BLE_CCA_RSSI_THRESH
|
||||
#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (50)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (CONFIG_BLE_CCA_RSSI_THRESH)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
|
||||
#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
|
||||
#endif
|
||||
|
@ -69,6 +69,29 @@ extern "C" {
|
||||
/* Timing jitter as per spec is +/16 usecs */
|
||||
#define BLE_LL_JITTER_USECS (16)
|
||||
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_SCA) < 0
|
||||
#error Invalid SCA value
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 20
|
||||
#define BLE_LL_SCA_ENUM 7
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 30
|
||||
#define BLE_LL_SCA_ENUM 6
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 50
|
||||
#define BLE_LL_SCA_ENUM 5
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 75
|
||||
#define BLE_LL_SCA_ENUM 4
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 100
|
||||
#define BLE_LL_SCA_ENUM 3
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 150
|
||||
#define BLE_LL_SCA_ENUM 2
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 250
|
||||
#define BLE_LL_SCA_ENUM 1
|
||||
#elif MYNEWT_VAL(BLE_LL_SCA) <= 500
|
||||
#define BLE_LL_SCA_ENUM 0
|
||||
#else
|
||||
#error Invalid SCA value
|
||||
#endif
|
||||
|
||||
/* Packet queue header definition */
|
||||
STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
|
||||
|
||||
@ -373,6 +396,12 @@ struct ble_dev_addr
|
||||
#define BLE_LL_LLID_DATA_START (2)
|
||||
#define BLE_LL_LLID_CTRL (3)
|
||||
|
||||
#define BLE_LL_LLID_IS_CTRL(hdr) \
|
||||
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL)
|
||||
#define BLE_LL_LLID_IS_DATA(hdr) \
|
||||
((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
|
||||
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
|
||||
|
||||
/*
|
||||
* CONNECT_REQ
|
||||
* -> InitA (6 bytes)
|
||||
@ -415,6 +444,14 @@ struct ble_dev_addr
|
||||
#define BLE_LL_ADDR_SUBTYPE_RPA (1)
|
||||
#define BLE_LL_ADDR_SUBTYPE_NRPA (2)
|
||||
|
||||
/* ACAD data types */
|
||||
#define BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND 0x28
|
||||
|
||||
struct ble_ll_acad_channel_map_update_ind {
|
||||
uint8_t map[5];
|
||||
uint16_t instant;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*--- External API ---*/
|
||||
/* Initialize the Link Layer */
|
||||
void ble_ll_init(void);
|
||||
@ -545,6 +582,7 @@ void ble_ll_rand_sample(uint8_t rnum);
|
||||
int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
|
||||
void ble_ll_rand_prand_get(uint8_t *prand);
|
||||
int ble_ll_rand_start(void);
|
||||
uint32_t ble_ll_rand(void);
|
||||
|
||||
static inline int
|
||||
ble_ll_get_addr_type(uint8_t txrxflag)
|
||||
|
@ -58,6 +58,8 @@ extern "C" {
|
||||
/* Definition for RSSI when the RSSI is unknown */
|
||||
#define BLE_LL_CONN_UNKNOWN_RSSI (127)
|
||||
|
||||
#define BLE_LL_CONN_HANDLE_ISO_OFFSET (0x0100)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* Encryption states for a connection
|
||||
@ -69,6 +71,7 @@ extern "C" {
|
||||
enum conn_enc_state {
|
||||
CONN_ENC_S_UNENCRYPTED = 1,
|
||||
CONN_ENC_S_ENCRYPTED,
|
||||
CONN_ENC_S_ENC_RSP_TO_BE_SENT,
|
||||
CONN_ENC_S_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSE_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSED,
|
||||
@ -270,6 +273,10 @@ struct ble_ll_conn_sm
|
||||
uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we
|
||||
only use the MD bit now */
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
uint16_t cth_flow_pending;
|
||||
#endif
|
||||
|
||||
/* connection event mgmt */
|
||||
uint8_t reject_reason;
|
||||
uint8_t host_reply_opcode;
|
||||
|
@ -39,7 +39,9 @@ extern "C" {
|
||||
#define BLE_LL_CTRL_PROC_LE_PING (7)
|
||||
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
|
||||
#define BLE_LL_CTRL_PROC_PHY_UPDATE (9)
|
||||
#define BLE_LL_CTRL_PROC_NUM (10)
|
||||
#define BLE_LL_CTRL_PROC_SCA_UPDATE (10)
|
||||
#define BLE_LL_CTRL_PROC_CIS_CREATE (11)
|
||||
#define BLE_LL_CTRL_PROC_NUM (12)
|
||||
#define BLE_LL_CTRL_PROC_IDLE (255)
|
||||
|
||||
/* Checks if a particular control procedure is running */
|
||||
@ -54,45 +56,51 @@ extern "C" {
|
||||
* -> Opcode (1 byte)
|
||||
* -> Data (0 - 26 bytes)
|
||||
*/
|
||||
#define BLE_LL_CTRL_CONN_UPDATE_IND (0)
|
||||
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1)
|
||||
#define BLE_LL_CTRL_TERMINATE_IND (2)
|
||||
#define BLE_LL_CTRL_ENC_REQ (3)
|
||||
#define BLE_LL_CTRL_ENC_RSP (4)
|
||||
#define BLE_LL_CTRL_START_ENC_REQ (5)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP (6)
|
||||
#define BLE_LL_CTRL_UNKNOWN_RSP (7)
|
||||
#define BLE_LL_CTRL_FEATURE_REQ (8)
|
||||
#define BLE_LL_CTRL_FEATURE_RSP (9)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ (10)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP (11)
|
||||
#define BLE_LL_CTRL_VERSION_IND (12)
|
||||
#define BLE_LL_CTRL_REJECT_IND (13)
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14)
|
||||
#define BLE_LL_CTRL_CONN_PARM_REQ (15)
|
||||
#define BLE_LL_CTRL_CONN_PARM_RSP (16)
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT (17)
|
||||
#define BLE_LL_CTRL_PING_REQ (18)
|
||||
#define BLE_LL_CTRL_PING_RSP (19)
|
||||
#define BLE_LL_CTRL_LENGTH_REQ (20)
|
||||
#define BLE_LL_CTRL_LENGTH_RSP (21)
|
||||
#define BLE_LL_CTRL_PHY_REQ (22)
|
||||
#define BLE_LL_CTRL_PHY_RSP (23)
|
||||
#define BLE_LL_CTRL_PHY_UPDATE_IND (24)
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25)
|
||||
#define BLE_LL_CTRL_CTE_REQ (26)
|
||||
#define BLE_LL_CTRL_CTE_RSP (27)
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30)
|
||||
#define BLE_LL_CTRL_CONN_UPDATE_IND (0x00)
|
||||
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (0x01)
|
||||
#define BLE_LL_CTRL_TERMINATE_IND (0x02)
|
||||
#define BLE_LL_CTRL_ENC_REQ (0x03)
|
||||
#define BLE_LL_CTRL_ENC_RSP (0x04)
|
||||
#define BLE_LL_CTRL_START_ENC_REQ (0x05)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP (0x06)
|
||||
#define BLE_LL_CTRL_UNKNOWN_RSP (0x07)
|
||||
#define BLE_LL_CTRL_FEATURE_REQ (0x08)
|
||||
#define BLE_LL_CTRL_FEATURE_RSP (0x09)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ (0x0A)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP (0x0B)
|
||||
#define BLE_LL_CTRL_VERSION_IND (0x0C)
|
||||
#define BLE_LL_CTRL_REJECT_IND (0x0D)
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (0x0E)
|
||||
#define BLE_LL_CTRL_CONN_PARM_REQ (0x0F)
|
||||
#define BLE_LL_CTRL_CONN_PARM_RSP (0x10)
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT (0x11)
|
||||
#define BLE_LL_CTRL_PING_REQ (0x12)
|
||||
#define BLE_LL_CTRL_PING_RSP (0x13)
|
||||
#define BLE_LL_CTRL_LENGTH_REQ (0x14)
|
||||
#define BLE_LL_CTRL_LENGTH_RSP (0x15)
|
||||
#define BLE_LL_CTRL_PHY_REQ (0x16)
|
||||
#define BLE_LL_CTRL_PHY_RSP (0x17)
|
||||
#define BLE_LL_CTRL_PHY_UPDATE_IND (0x18)
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (0x19)
|
||||
#define BLE_LL_CTRL_CTE_REQ (0x1A)
|
||||
#define BLE_LL_CTRL_CTE_RSP (0x1B)
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (0x1C)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (0x1D)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (0x1E)
|
||||
#define BLE_LL_CTRL_CIS_REQ (0x1F)
|
||||
#define BLE_LL_CTRL_CIS_RSP (0x20)
|
||||
#define BLE_LL_CTRL_CIS_IND (0x21)
|
||||
#define BLE_LL_CTRL_CIS_TERMINATE_IND (0x22)
|
||||
|
||||
/* Maximum opcode value */
|
||||
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1)
|
||||
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CIS_TERMINATE_IND + 1)
|
||||
|
||||
extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
|
||||
|
||||
/* Maximum LL control PDU size */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#if MYNEWT_VAL(BLE_ISO)
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (42)
|
||||
#elif MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (35)
|
||||
#else
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (27)
|
||||
@ -261,6 +269,12 @@ struct ble_ll_len_req
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1)
|
||||
|
||||
/* BLE ISO */
|
||||
#define BLE_LL_CTRL_CIS_REQ_LEN (42)
|
||||
#define BLE_LL_CTRL_CIS_RSP_LEN (8)
|
||||
#define BLE_LL_CTRL_CIS_IND_LEN (15)
|
||||
#define BLE_LL_CTRL_CIS_TERMINATE_LEN (3)
|
||||
|
||||
/* API */
|
||||
struct ble_ll_conn_sm;
|
||||
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
|
||||
@ -306,6 +320,11 @@ void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
|
||||
uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask);
|
||||
uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t status, uint8_t peer_sca);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -27,7 +27,7 @@ extern "C" {
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
|
||||
/* For supported commands */
|
||||
#define BLE_LL_SUPP_CMD_LEN (42)
|
||||
#define BLE_LL_SUPP_CMD_LEN (45)
|
||||
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
|
||||
|
||||
/* The largest event the controller will send. */
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 H_BLE_LL_ISO
|
||||
#define H_BLE_LL_ISO
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
|
||||
int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -225,6 +225,8 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
|
||||
if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) {
|
||||
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
|
||||
}
|
||||
#else
|
||||
(void)phy_options;
|
||||
#endif
|
||||
|
||||
return phy_mode;
|
||||
|
@ -248,9 +248,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
|
||||
/** Our random address */
|
||||
uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
|
||||
|
||||
/** Our supported features which can be controller by the host */
|
||||
uint64_t g_ble_ll_supported_host_features = 0;
|
||||
|
||||
static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] =
|
||||
{
|
||||
[BLE_PHY_MODE_1M] =
|
||||
@ -715,6 +712,7 @@ ble_ll_tx_pkt_in(void)
|
||||
uint16_t pb;
|
||||
struct os_mbuf_pkthdr *pkthdr;
|
||||
struct os_mbuf *om;
|
||||
os_sr_t sr;
|
||||
|
||||
/* Drain all packets off the queue */
|
||||
while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) {
|
||||
@ -723,7 +721,9 @@ ble_ll_tx_pkt_in(void)
|
||||
om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
|
||||
|
||||
/* Remove from queue */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
/* Strip HCI ACL header to get handle and length */
|
||||
handle = get_le16(om->om_data);
|
||||
@ -1210,8 +1210,6 @@ ble_ll_task(void *arg)
|
||||
/* Tell the host that we are ready to receive packets */
|
||||
ble_ll_hci_send_noop();
|
||||
|
||||
ble_ll_rand_start();
|
||||
|
||||
while (1) {
|
||||
ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER);
|
||||
assert(ev);
|
||||
@ -1309,10 +1307,6 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len)
|
||||
|
||||
mask = (uint64_t)1 << (cmd->bit_num);
|
||||
if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!(mask & g_ble_ll_supported_host_features)) {
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1376,6 +1370,20 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
|
||||
ble_hdr->txinfo.hdr_byte = hdr;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_validate_task(void)
|
||||
{
|
||||
#ifdef MYNEWT
|
||||
#ifndef NDEBUG
|
||||
struct os_task_info oti;
|
||||
|
||||
os_task_info_get(&g_ble_ll_task, &oti);
|
||||
|
||||
BLE_LL_ASSERT(oti.oti_stkusage < oti.oti_stksize);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to reset the controller. This performs a "software reset" of the link
|
||||
* layer; it does not perform a HW reset of the controller nor does it reset
|
||||
@ -1392,6 +1400,9 @@ ble_ll_reset(void)
|
||||
int rc;
|
||||
os_sr_t sr;
|
||||
|
||||
/* do sanity check on LL task stack */
|
||||
ble_ll_validate_task();
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_phy_disable();
|
||||
ble_ll_sched_stop();
|
||||
@ -1451,23 +1462,6 @@ ble_ll_reset(void)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_seed_prng(void)
|
||||
{
|
||||
uint32_t seed;
|
||||
int i;
|
||||
|
||||
/* Seed random number generator with least significant bytes of device
|
||||
* address.
|
||||
*/
|
||||
seed = 0;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
seed |= g_dev_addr[i];
|
||||
seed <<= 8;
|
||||
}
|
||||
srand(seed);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode)
|
||||
{
|
||||
@ -1685,16 +1679,24 @@ ble_ll_init(void)
|
||||
features |= BLE_LL_FEAT_SYNC_TRANS_SEND;
|
||||
#endif
|
||||
|
||||
/* Initialize random number generation */
|
||||
ble_ll_rand_init();
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
features |= BLE_LL_FEAT_SCA_UPDATE;
|
||||
#endif
|
||||
|
||||
/* XXX: This really doesn't belong here, as the address probably has not
|
||||
* been set yet.
|
||||
*/
|
||||
ble_ll_seed_prng();
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
features |= BLE_LL_FEAT_CIS_MASTER;
|
||||
features |= BLE_LL_FEAT_CIS_SLAVE;
|
||||
features |= BLE_LL_FEAT_ISO_BROADCASTER;
|
||||
features |= BLE_LL_FEAT_ISO_HOST_SUPPORT;
|
||||
#endif
|
||||
|
||||
lldata->ll_supp_features = features;
|
||||
|
||||
/* Initialize random number generation */
|
||||
ble_ll_rand_init();
|
||||
/* Start the random number generator */
|
||||
ble_ll_rand_start();
|
||||
|
||||
rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
|
||||
STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
|
||||
STATS_NAME_INIT_PARMS(ble_ll_stats),
|
||||
|
@ -144,6 +144,7 @@ struct ble_ll_adv_sm
|
||||
uint8_t aux_index : 1;
|
||||
uint8_t aux_first_pdu : 1;
|
||||
uint8_t aux_not_scanned : 1;
|
||||
uint8_t aux_dropped : 1;
|
||||
struct ble_mbuf_hdr *rx_ble_hdr;
|
||||
struct os_mbuf **aux_data;
|
||||
struct ble_ll_adv_aux aux[2];
|
||||
@ -698,7 +699,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
|
||||
dptr[8] = advsm->periodic_chanmap[4] & 0x1f;
|
||||
|
||||
/* SCA (3 bits) */
|
||||
dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
dptr[8] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* AA (4 bytes) */
|
||||
put_le32(&dptr[9], advsm->periodic_access_addr);
|
||||
@ -1282,7 +1283,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
|
||||
if (rc) {
|
||||
STATS_INC(ble_ll_stats, adv_late_starts);
|
||||
goto adv_tx_done;
|
||||
goto adv_aux_dropped;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
@ -1317,7 +1318,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
/* Transmit advertisement */
|
||||
rc = ble_phy_tx(pducb, advsm, end_trans);
|
||||
if (rc) {
|
||||
goto adv_tx_done;
|
||||
goto adv_aux_dropped;
|
||||
}
|
||||
|
||||
/* Enable/disable whitelisting based on filter policy */
|
||||
@ -1335,7 +1336,8 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
|
||||
|
||||
return BLE_LL_SCHED_STATE_RUNNING;
|
||||
|
||||
adv_tx_done:
|
||||
adv_aux_dropped:
|
||||
advsm->aux_dropped = 1;
|
||||
ble_ll_adv_tx_done(advsm);
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
@ -1390,7 +1392,7 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
|
||||
g_ble_ll_conn_params.num_used_chans,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#else
|
||||
aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS,
|
||||
aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS,
|
||||
g_ble_ll_conn_params.master_chan_map);
|
||||
#endif
|
||||
|
||||
@ -1567,6 +1569,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
|
||||
advsm->aux_index = 0;
|
||||
advsm->aux_first_pdu = 1;
|
||||
advsm->aux_not_scanned = 0;
|
||||
advsm->aux_dropped = 0;
|
||||
|
||||
aux = AUX_CURRENT(advsm);
|
||||
ble_ll_adv_aux_calculate(advsm, aux, 0);
|
||||
@ -1866,7 +1869,7 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm)
|
||||
* the previously used value.
|
||||
*/
|
||||
do {
|
||||
advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
|
||||
advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff);
|
||||
} while (old_adi == advsm->adi);
|
||||
}
|
||||
#endif
|
||||
@ -2557,11 +2560,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
|
||||
advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans;
|
||||
advsm->periodic_event_cntr = 0;
|
||||
/* for chaining we start with random counter as we share access addr */
|
||||
advsm->periodic_chain_event_cntr = rand();
|
||||
advsm->periodic_chain_event_cntr = ble_ll_rand();
|
||||
advsm->periodic_access_addr = ble_ll_utils_calc_access_addr();
|
||||
advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^
|
||||
(advsm->periodic_access_addr & 0x0000ffff);
|
||||
advsm->periodic_crcinit = rand() & 0xffffff;
|
||||
advsm->periodic_crcinit = ble_ll_rand() & 0xffffff;
|
||||
|
||||
usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL;
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
@ -2750,7 +2753,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
|
||||
*/
|
||||
earliest_start_time = ble_ll_rfmgmt_enable_now();
|
||||
|
||||
start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
|
||||
start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
|
||||
advsm->adv_pdu_start_time = os_cputime_get32() +
|
||||
os_cputime_usecs_to_ticks(start_delay_us);
|
||||
|
||||
@ -4032,8 +4035,8 @@ ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm,
|
||||
|
||||
/* SID, AType, SCA */
|
||||
sync_ind[24] = (advsm->adi >> 12);
|
||||
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ;
|
||||
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4;
|
||||
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* PHY */
|
||||
sync_ind[25] = (0x01 << (advsm->sec_phy - 1));
|
||||
@ -4849,6 +4852,11 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
|
||||
/* We don't need RF anymore */
|
||||
ble_ll_rfmgmt_release();
|
||||
|
||||
if (advsm->aux_dropped) {
|
||||
ble_ll_adv_drop_event(advsm);
|
||||
return;
|
||||
}
|
||||
|
||||
if (advsm->aux_not_scanned) {
|
||||
ble_ll_sched_rmv_elem(&aux_next->sch);
|
||||
}
|
||||
|
@ -232,6 +232,166 @@ STATS_NAME_END(ble_ll_conn_stats)
|
||||
|
||||
static void ble_ll_conn_event_end(struct ble_npl_event *ev);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
struct ble_ll_conn_cth_flow {
|
||||
bool enabled;
|
||||
uint16_t max_buffers;
|
||||
uint16_t num_buffers;
|
||||
};
|
||||
|
||||
static struct ble_ll_conn_cth_flow g_ble_ll_conn_cth_flow;
|
||||
|
||||
static struct ble_npl_event g_ble_ll_conn_cth_flow_error_ev;
|
||||
|
||||
static bool
|
||||
ble_ll_conn_cth_flow_is_enabled(void)
|
||||
{
|
||||
return g_ble_ll_conn_cth_flow.enabled;
|
||||
}
|
||||
|
||||
static bool
|
||||
ble_ll_conn_cth_flow_alloc_credit(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
if (!cth->num_buffers) {
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
return false;
|
||||
}
|
||||
|
||||
connsm->cth_flow_pending++;
|
||||
cth->num_buffers--;
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_conn_cth_flow_free_credit(struct ble_ll_conn_sm *connsm, uint16_t credits)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
/*
|
||||
* It's not quite clear what we should do if host gives back more credits
|
||||
* that we have allocated. For now let's just set invalid values back to
|
||||
* sane values and continue.
|
||||
*/
|
||||
|
||||
cth->num_buffers += credits;
|
||||
if (cth->num_buffers > cth->max_buffers) {
|
||||
cth->num_buffers = cth->max_buffers;
|
||||
}
|
||||
|
||||
if (connsm->cth_flow_pending < credits) {
|
||||
connsm->cth_flow_pending = 0;
|
||||
} else {
|
||||
connsm->cth_flow_pending -= credits;
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_conn_cth_flow_error_fn(struct ble_npl_event *ev)
|
||||
{
|
||||
struct ble_hci_ev *hci_ev;
|
||||
struct ble_hci_ev_command_complete *hci_ev_cp;
|
||||
uint16_t opcode;
|
||||
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (!hci_ev) {
|
||||
/* Not much we can do anyway... */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are here in case length of HCI_Host_Number_Of_Completed_Packets was
|
||||
* invalid. We will send an error back to host and we can only hope host is
|
||||
* reasonable and will do some actions to recover, e.g. it should disconnect
|
||||
* all connections to guarantee that all credits are back in pool and we're
|
||||
* back in sync (although spec does not really say what should happen).
|
||||
*/
|
||||
|
||||
opcode = BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
|
||||
BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS);
|
||||
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE;
|
||||
hci_ev->length = sizeof(*hci_ev_cp);
|
||||
|
||||
hci_ev_cp = (void *)hci_ev->data;
|
||||
hci_ev_cp->num_packets = BLE_LL_CFG_NUM_HCI_CMD_PKTS;
|
||||
hci_ev_cp->opcode = htole16(opcode);
|
||||
hci_ev_cp->status = BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers)
|
||||
{
|
||||
BLE_LL_ASSERT(num_buffers);
|
||||
|
||||
g_ble_ll_conn_cth_flow.max_buffers = num_buffers;
|
||||
g_ble_ll_conn_cth_flow.num_buffers = num_buffers;
|
||||
}
|
||||
|
||||
bool
|
||||
ble_ll_conn_cth_flow_enable(bool enabled)
|
||||
{
|
||||
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
|
||||
|
||||
if (cth->enabled == enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cth->enabled = enabled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf)
|
||||
{
|
||||
const struct ble_hci_cmd *cmd;
|
||||
const struct ble_hci_cb_host_num_comp_pkts_cp *cp;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
int i;
|
||||
|
||||
cmd = (const void *)cmdbuf;
|
||||
cp = (const void *)cmd->data;
|
||||
|
||||
if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < cp->handles; i++) {
|
||||
/*
|
||||
* It's probably ok that we do not have active connection with given
|
||||
* handle - this can happen if disconnection already happened in LL but
|
||||
* host sent credits back before processing disconnection event. In such
|
||||
* case we can simply ignore command for that connection since credits
|
||||
* are returned by LL already.
|
||||
*/
|
||||
connsm = ble_ll_conn_find_active_conn(cp->h[i].handle);
|
||||
if (connsm) {
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, cp->h[i].count);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
/**
|
||||
* Checks to see if we should start a PHY update procedure
|
||||
@ -339,7 +499,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
|
||||
int rc;
|
||||
|
||||
/* Set time that we last serviced the schedule */
|
||||
if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) {
|
||||
if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) {
|
||||
rc = 1;
|
||||
} else {
|
||||
rc = 0;
|
||||
@ -862,8 +1022,14 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
|
||||
/*
|
||||
* If we are encrypting, we are only allowed to send certain
|
||||
* kinds of LL control PDU's. If none is enqueued, send empty pdu!
|
||||
*
|
||||
* In Slave role, we are allowed to send unencrypted packets until
|
||||
* LL_ENC_RSP is sent.
|
||||
*/
|
||||
if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) {
|
||||
if (((connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_IS_MASTER(connsm)) ||
|
||||
((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) &&
|
||||
CONN_IS_SLAVE(connsm))) {
|
||||
if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) {
|
||||
CONN_F_EMPTY_PDU_TXD(connsm) = 1;
|
||||
goto conn_tx_pdu;
|
||||
@ -998,10 +1164,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
|
||||
}
|
||||
|
||||
ticks = os_cputime_usecs_to_ticks(ticks);
|
||||
if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) {
|
||||
if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) {
|
||||
md = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we send an empty PDU we need to initialize the header */
|
||||
conn_tx_pdu:
|
||||
@ -1457,10 +1623,10 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
*/
|
||||
connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1;
|
||||
connsm->tx_win_off = 0;
|
||||
connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA);
|
||||
connsm->master_sca = BLE_LL_SCA_ENUM;
|
||||
|
||||
/* Hop increment is a random value between 5 and 16. */
|
||||
connsm->hop_inc = (rand() % 12) + 5;
|
||||
connsm->hop_inc = (ble_ll_rand() % 12) + 5;
|
||||
|
||||
/* Set channel map to map requested by host */
|
||||
connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans;
|
||||
@ -1469,7 +1635,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
|
||||
|
||||
/* Calculate random access address and crc initialization value */
|
||||
connsm->access_addr = ble_ll_utils_calc_access_addr();
|
||||
connsm->crcinit = rand() & 0xffffff;
|
||||
connsm->crcinit = ble_ll_rand() & 0xffffff;
|
||||
|
||||
/* Set initial schedule callback */
|
||||
connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
|
||||
@ -1868,6 +2034,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
/* Remove from the active connection list */
|
||||
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending);
|
||||
#endif
|
||||
|
||||
/* Free the current transmit pdu if there is one. */
|
||||
if (connsm->cur_tx_pdu) {
|
||||
os_mbuf_free_chain(connsm->cur_tx_pdu);
|
||||
@ -3246,6 +3416,13 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
|
||||
*/
|
||||
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
} else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) {
|
||||
/* undirected with ID address, assure privacy if on RL */
|
||||
rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
|
||||
if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
|
||||
rl->rl_has_peer) {
|
||||
goto init_rx_isr_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3459,129 +3636,142 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
uint16_t acl_hdr;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
if (BLE_MBUF_HDR_CRC_OK(hdr)) {
|
||||
/* XXX: there is a chance that the connection was thrown away and
|
||||
re-used before processing packets here. Fix this. */
|
||||
/* We better have a connection state machine */
|
||||
connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
|
||||
if (connsm) {
|
||||
/* Check state machine */
|
||||
ble_ll_conn_chk_csm_flags(connsm);
|
||||
/* Packets with invalid CRC are not sent to LL */
|
||||
BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr));
|
||||
|
||||
/* Validate rx data pdu */
|
||||
rxbuf = rxpdu->om_data;
|
||||
hdr_byte = rxbuf[0];
|
||||
acl_len = rxbuf[1];
|
||||
llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
|
||||
/* XXX: there is a chance that the connection was thrown away and
|
||||
re-used before processing packets here. Fix this. */
|
||||
/* We better have a connection state machine */
|
||||
connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
|
||||
if (!connsm) {
|
||||
STATS_INC(ble_ll_conn_stats, no_conn_sm);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the LLID and payload length are reasonable.
|
||||
* Empty payload is only allowed for LLID == 01b.
|
||||
* */
|
||||
if ((llid == 0) ||
|
||||
((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_bad_llid);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
/* Check state machine */
|
||||
ble_ll_conn_chk_csm_flags(connsm);
|
||||
|
||||
/* Validate rx data pdu */
|
||||
rxbuf = rxpdu->om_data;
|
||||
hdr_byte = rxbuf[0];
|
||||
acl_len = rxbuf[1];
|
||||
llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
|
||||
|
||||
/*
|
||||
* Check that the LLID and payload length are reasonable.
|
||||
* Empty payload is only allowed for LLID == 01b.
|
||||
* */
|
||||
if ((llid == 0) || ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_bad_llid);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/* Check if PDU is allowed when encryption is started. If not,
|
||||
* terminate connection.
|
||||
*
|
||||
* Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) &&
|
||||
!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
/* Check if PDU is allowed when encryption is started. If not,
|
||||
* terminate connection.
|
||||
*
|
||||
* Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT &&
|
||||
CONN_IS_MASTER(connsm)) ||
|
||||
(connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT &&
|
||||
CONN_IS_SLAVE(connsm))) {
|
||||
if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
/*
|
||||
* Reset authenticated payload timeout if valid MIC. NOTE: we dont
|
||||
* check the MIC failure bit as that would have terminated the
|
||||
* connection
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
/*
|
||||
* Reset authenticated payload timeout if valid MIC. NOTE: we dont
|
||||
* check the MIC failure bit as that would have terminated the
|
||||
* connection
|
||||
*/
|
||||
if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
|
||||
CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update RSSI */
|
||||
connsm->conn_rssi = hdr->rxinfo.rssi;
|
||||
/* Update RSSI */
|
||||
connsm->conn_rssi = hdr->rxinfo.rssi;
|
||||
|
||||
/*
|
||||
* If we are a slave, we can only start to use slave latency
|
||||
* once we have received a NESN of 1 from the master
|
||||
*/
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
|
||||
connsm->csmflags.cfbit.allow_slave_latency = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard the received PDU if the sequence number is the same
|
||||
* as the last received sequence number
|
||||
*/
|
||||
rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
|
||||
if (rxd_sn != connsm->last_rxd_sn) {
|
||||
/* Update last rxd sn */
|
||||
connsm->last_rxd_sn = rxd_sn;
|
||||
|
||||
/* No need to do anything if empty pdu */
|
||||
if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* XXX: should we check to see if we are in a state where we
|
||||
* might expect to get an encrypted PDU?
|
||||
*/
|
||||
if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
|
||||
STATS_INC(ble_ll_conn_stats, mic_failures);
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (llid == BLE_LL_LLID_CTRL) {
|
||||
/* Process control frame */
|
||||
STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
|
||||
if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
|
||||
}
|
||||
} else {
|
||||
/* Count # of received l2cap frames and byes */
|
||||
STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
|
||||
|
||||
/* NOTE: there should be at least two bytes available */
|
||||
BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
|
||||
os_mbuf_prepend(rxpdu, 2);
|
||||
rxbuf = rxpdu->om_data;
|
||||
|
||||
acl_hdr = (llid << 12) | connsm->conn_handle;
|
||||
put_le16(rxbuf, acl_hdr);
|
||||
put_le16(rxbuf + 2, acl_len);
|
||||
ble_hci_trans_ll_acl_tx(rxpdu);
|
||||
}
|
||||
|
||||
/* NOTE: we dont free the mbuf since we handed it off! */
|
||||
return;
|
||||
} else {
|
||||
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
|
||||
}
|
||||
} else {
|
||||
STATS_INC(ble_ll_conn_stats, no_conn_sm);
|
||||
/*
|
||||
* If we are a slave, we can only start to use slave latency
|
||||
* once we have received a NESN of 1 from the master
|
||||
*/
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
|
||||
if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
|
||||
connsm->csmflags.cfbit.allow_slave_latency = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard the received PDU if the sequence number is the same
|
||||
* as the last received sequence number
|
||||
*/
|
||||
rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
|
||||
if (rxd_sn == connsm->last_rxd_sn) {
|
||||
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
/* Update last rxd sn */
|
||||
connsm->last_rxd_sn = rxd_sn;
|
||||
|
||||
/* No need to do anything if empty pdu */
|
||||
if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* XXX: should we check to see if we are in a state where we
|
||||
* might expect to get an encrypted PDU?
|
||||
*/
|
||||
if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
|
||||
STATS_INC(ble_ll_conn_stats, mic_failures);
|
||||
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (llid == BLE_LL_LLID_CTRL) {
|
||||
/* Process control frame */
|
||||
STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
|
||||
if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
|
||||
}
|
||||
} else {
|
||||
/* Count # of received l2cap frames and byes */
|
||||
STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
|
||||
|
||||
/* NOTE: there should be at least two bytes available */
|
||||
BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
|
||||
os_mbuf_prepend(rxpdu, 2);
|
||||
rxbuf = rxpdu->om_data;
|
||||
|
||||
acl_hdr = (llid << 12) | connsm->conn_handle;
|
||||
put_le16(rxbuf, acl_hdr);
|
||||
put_le16(rxbuf + 2, acl_len);
|
||||
ble_hci_trans_ll_acl_tx(rxpdu);
|
||||
}
|
||||
|
||||
/* NOTE: we dont free the mbuf since we handed it off! */
|
||||
return;
|
||||
|
||||
/* Free buffer */
|
||||
conn_rx_data_pdu_end:
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
/* Need to give credit back if we allocated one for this PDU */
|
||||
if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT) {
|
||||
ble_ll_conn_cth_flow_free_credit(connsm, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
os_mbuf_free_chain(rxpdu);
|
||||
}
|
||||
|
||||
@ -3602,7 +3792,6 @@ int
|
||||
ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
{
|
||||
int rc;
|
||||
int is_ctrl;
|
||||
uint8_t hdr_byte;
|
||||
uint8_t hdr_sn;
|
||||
uint8_t hdr_nesn;
|
||||
@ -3616,14 +3805,43 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
uint32_t add_usecs;
|
||||
struct os_mbuf *txpdu;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
struct os_mbuf *rxpdu;
|
||||
struct os_mbuf *rxpdu = NULL;
|
||||
struct ble_mbuf_hdr *txhdr;
|
||||
int rx_phy_mode;
|
||||
bool alloc_rxpdu = true;
|
||||
|
||||
rc = -1;
|
||||
connsm = g_ble_ll_conn_cur_sm;
|
||||
|
||||
/* Retrieve the header and payload length */
|
||||
hdr_byte = rxbuf[0];
|
||||
rx_pyld_len = rxbuf[1];
|
||||
|
||||
/*
|
||||
* No need to alloc rxpdu for packets with invalid CRC, we would throw them
|
||||
* away instantly from LL anyway.
|
||||
*/
|
||||
if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) {
|
||||
alloc_rxpdu = false;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
/*
|
||||
* If flow control is enabled, we need to have credit available for each
|
||||
* non-empty data packet that LL may send to host. If there are no credits
|
||||
* available, we don't need to allocate buffer for this packet so LL will
|
||||
* nak it.
|
||||
*/
|
||||
if (alloc_rxpdu && ble_ll_conn_cth_flow_is_enabled() &&
|
||||
BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) {
|
||||
if (ble_ll_conn_cth_flow_alloc_credit(connsm)) {
|
||||
rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT;
|
||||
} else {
|
||||
alloc_rxpdu = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to attempt to allocate a buffer here. The reason we do this
|
||||
* now is that we should not ack the packet if we have no receive
|
||||
@ -3631,14 +3849,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
* acked, but we should not ack the received frame if we cant hand it up.
|
||||
* NOTE: we hand up empty pdu's to the LL task!
|
||||
*/
|
||||
rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
|
||||
if (alloc_rxpdu) {
|
||||
rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* We should have a current connection state machine. If we dont, we just
|
||||
* hand the packet to the higher layer to count it.
|
||||
*/
|
||||
rc = -1;
|
||||
connsm = g_ble_ll_conn_cur_sm;
|
||||
if (!connsm) {
|
||||
STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn);
|
||||
goto conn_exit;
|
||||
@ -3700,9 +3918,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* Set last received header byte */
|
||||
connsm->last_rxd_hdr_byte = hdr_byte;
|
||||
|
||||
is_ctrl = 0;
|
||||
if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
|
||||
is_ctrl = 1;
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte)) {
|
||||
opcode = rxbuf[2];
|
||||
}
|
||||
|
||||
@ -3791,7 +4007,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* Adjust payload for max TX time and octets */
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
if (is_ctrl &&
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
|
||||
(connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
|
||||
(opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) {
|
||||
connsm->phy_tx_transition =
|
||||
@ -3810,8 +4026,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
/* If this is a TERMINATE_IND, we have to reply */
|
||||
chk_rx_terminate_ind:
|
||||
/* If we received a terminate IND, we must set some flags */
|
||||
if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND)
|
||||
&& (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
|
||||
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
|
||||
(opcode == BLE_LL_CTRL_TERMINATE_IND) &&
|
||||
(rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
|
||||
connsm->csmflags.cfbit.terminate_ind_rxd = 1;
|
||||
connsm->rxd_disconnect_reason = rxbuf[3];
|
||||
}
|
||||
@ -4233,6 +4450,12 @@ ble_ll_conn_module_reset(void)
|
||||
g_ble_ll_conn_sync_transfer_params.mode = 0;
|
||||
g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
g_ble_ll_conn_cth_flow.enabled = false;
|
||||
g_ble_ll_conn_cth_flow.max_buffers = 1;
|
||||
g_ble_ll_conn_cth_flow.num_buffers = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialize the connection module */
|
||||
@ -4272,6 +4495,11 @@ ble_ll_conn_module_init(void)
|
||||
"ble_ll_conn");
|
||||
BLE_LL_ASSERT(rc == 0);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
ble_npl_event_init(&g_ble_ll_conn_cth_flow_error_ev,
|
||||
ble_ll_conn_cth_flow_error_fn, NULL);
|
||||
#endif
|
||||
|
||||
/* Call reset to finish reset of initialization */
|
||||
ble_ll_conn_module_reset();
|
||||
}
|
||||
|
@ -1129,16 +1129,11 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len)
|
||||
ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
|
||||
{
|
||||
int rc;
|
||||
uint16_t handle;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Check for valid parameters */
|
||||
handle = le16toh(cmd->conn_handle);
|
||||
@ -1566,6 +1561,34 @@ ltk_key_cmd_complete:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
int
|
||||
ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
const struct ble_hci_le_request_peer_sca_cp *params = (const void *)cmdbuf;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = ble_ll_conn_find_active_conn(params->conn_handle);
|
||||
if (!connsm) {
|
||||
return BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SCA_UPDATE >> 24))) {
|
||||
return BLE_ERR_UNSUPP_REM_FEATURE;
|
||||
}
|
||||
|
||||
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE)) {
|
||||
/* Not really specified what we should return */
|
||||
return BLE_ERR_CTLR_BUSY;
|
||||
}
|
||||
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
/**
|
||||
* Read authenticated payload timeout (OGF=3, OCF==0x007B)
|
||||
|
@ -164,7 +164,7 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void);
|
||||
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t reason);
|
||||
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
|
||||
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
|
||||
@ -196,12 +196,23 @@ int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
int ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
|
||||
#else
|
||||
#define ble_ll_conn_auth_pyld_timer_start(x)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
void ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers);
|
||||
bool ble_ll_conn_cth_flow_enable(bool enabled);
|
||||
void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
|
||||
#endif
|
||||
|
||||
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
|
||||
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
|
||||
|
||||
|
@ -114,6 +114,10 @@ const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
|
||||
BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN,
|
||||
BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN,
|
||||
BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN,
|
||||
BLE_LL_CTRL_CIS_REQ_LEN,
|
||||
BLE_LL_CTRL_CIS_RSP_LEN,
|
||||
BLE_LL_CTRL_CIS_IND_LEN,
|
||||
BLE_LL_CTRL_CIS_TERMINATE_LEN
|
||||
};
|
||||
|
||||
/**
|
||||
@ -508,6 +512,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *
|
||||
ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
|
||||
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_UNSUPPORTED, 0);
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_SCA_UPDATE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ctrl_proc = BLE_LL_CTRL_PROC_NUM;
|
||||
@ -839,6 +849,20 @@ ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
|
||||
}
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
/**
|
||||
* Create a LL_CLOCK_ACCURACY_REQ or LL_CLOCK_ACCURACY_RSP pdu
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
* @param ctrdata: Pointer to where CtrData starts in pdu
|
||||
*/
|
||||
static void
|
||||
ble_ll_ctrl_sca_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
|
||||
{
|
||||
ctrdata[0] = BLE_LL_SCA_ENUM;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
|
||||
uint8_t *rsp)
|
||||
@ -1043,11 +1067,70 @@ ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
connsm->sync_transfer_skip,
|
||||
connsm->sync_transfer_sync_timeout);
|
||||
}
|
||||
|
||||
return BLE_ERR_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
/**
|
||||
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_REQ PDU is received
|
||||
*
|
||||
* @param connsm
|
||||
* @param dptr
|
||||
* @param rsp Pointer to CtrData of BLE_LL_CTRL_CLOCK_ACCURACY_RSP.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_sca_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rsp)
|
||||
{
|
||||
ble_ll_ctrl_sca_req_rsp_make(connsm, rsp);
|
||||
return BLE_LL_CTRL_CLOCK_ACCURACY_RSP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_RSP PDU is received
|
||||
*
|
||||
* @param connsm
|
||||
* @param dptr
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_sca_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_SCA_UPDATE) {
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_SUCCESS, dptr[0]);
|
||||
return BLE_ERR_MAX;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rspdata)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
uint8_t *rspdata)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_ll_ctrl_rx_cis_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Create a link layer length request or length response PDU.
|
||||
*
|
||||
@ -1253,6 +1336,15 @@ ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
static void
|
||||
ble_ll_ctrl_cis_create(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
{
|
||||
/* TODO Implement */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a link layer control "encrypt request" PDU.
|
||||
*
|
||||
@ -1354,7 +1446,7 @@ ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
return BLE_LL_CTRL_UNKNOWN_RSP;
|
||||
}
|
||||
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT;
|
||||
|
||||
/* In case we were already encrypted we need to reset packet counters */
|
||||
connsm->enc_data.rx_pkt_cntr = 0;
|
||||
@ -1679,6 +1771,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
*/
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_PROC_SCA_UPDATE:
|
||||
ble_ll_hci_ev_sca_update(connsm, ble_error, 0);
|
||||
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2141,6 +2239,18 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
|
||||
opcode = BLE_LL_CTRL_PHY_REQ;
|
||||
ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_PROC_SCA_UPDATE:
|
||||
opcode = BLE_LL_CTRL_CLOCK_ACCURACY_REQ;
|
||||
ble_ll_ctrl_sca_req_rsp_make(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_LL_CTRL_PROC_CIS_CREATE:
|
||||
opcode = BLE_LL_CTRL_CIS_REQ;
|
||||
ble_ll_ctrl_cis_create(connsm, ctrdata);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BLE_LL_ASSERT(0);
|
||||
@ -2571,6 +2681,26 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
|
||||
rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
|
||||
rsp_opcode = ble_ll_ctrl_rx_sca_req(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CLOCK_ACCURACY_RSP:
|
||||
rsp_opcode = ble_ll_ctrl_rx_sca_rsp(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_LL_CTRL_CIS_REQ:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_req(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CIS_RSP:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_rsp(connsm, dptr, rspdata);
|
||||
break;
|
||||
case BLE_LL_CTRL_CIS_IND:
|
||||
rsp_opcode = ble_ll_ctrl_rx_cis_ind(connsm, dptr);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
case BLE_LL_CTRL_PERIODIC_SYNC_IND:
|
||||
rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr);
|
||||
@ -2712,6 +2842,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT;
|
||||
break;
|
||||
case BLE_LL_CTRL_ENC_RSP:
|
||||
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
|
||||
connsm->csmflags.cfbit.send_ltk_req = 1;
|
||||
break;
|
||||
case BLE_LL_CTRL_START_ENC_RSP:
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "../include/controller/ble_ll_whitelist.h"
|
||||
#include "../include/controller/ble_ll_resolv.h"
|
||||
#include "../include/controller/ble_ll_sync.h"
|
||||
#include "../include/controller/ble_ll_iso.h"
|
||||
#include "ble_ll_priv.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
@ -329,6 +330,31 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
/**
|
||||
* HCI read buffer size v2 command. Returns the ACL and ISO data packet length and
|
||||
* num data packets.
|
||||
*
|
||||
* @param rspbuf Pointer to response buffer
|
||||
* @param rsplen Length of response buffer
|
||||
*
|
||||
* @return int BLE error code
|
||||
*/
|
||||
static int
|
||||
ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
struct ble_hci_le_rd_buf_size_v2_rp *rp = (void *) rspbuf;
|
||||
|
||||
rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size);
|
||||
rp->data_packets = g_ble_ll_data.ll_num_acl_pkts;
|
||||
rp->iso_data_len = 0;
|
||||
rp->iso_data_packets = 0;
|
||||
|
||||
*rsplen = sizeof(*rp);
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
/**
|
||||
* Checks the preferred phy masks for validity and places the preferred masks
|
||||
@ -620,6 +646,9 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
|
||||
case BLE_HCI_OCF_LE_GEN_DHKEY:
|
||||
case BLE_HCI_OCF_LE_SET_PHY:
|
||||
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC:
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
|
||||
#endif
|
||||
rc = 1;
|
||||
break;
|
||||
default:
|
||||
@ -1151,10 +1180,77 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC:
|
||||
rc = ble_ll_iso_read_tx_sync(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_SET_CIG_PARAM:
|
||||
rc = ble_ll_iso_set_cig_param(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_CIS:
|
||||
rc = ble_ll_iso_create_cis(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REMOVE_CIG:
|
||||
rc = ble_ll_iso_remove_cig(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ACCEPT_CIS_REQ:
|
||||
rc = ble_ll_iso_accept_cis_req(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REJECT_CIS_REQ:
|
||||
rc = ble_ll_iso_reject_cis_req(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_BIG:
|
||||
rc = ble_ll_iso_create_big(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_TERMINATE_BIG:
|
||||
rc = ble_ll_iso_terminate_big(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_BIG_CREATE_SYNC:
|
||||
rc = ble_ll_iso_big_create_sync(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC:
|
||||
rc = ble_ll_iso_big_terminate_sync(cmdbuf,len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH:
|
||||
rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH:
|
||||
rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2:
|
||||
rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
|
||||
case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST:
|
||||
rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_CREATE_BIG_TEST:
|
||||
rc = ble_ll_iso_create_big_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST:
|
||||
rc = ble_ll_iso_transmit_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_RECEIVE_TEST:
|
||||
rc = ble_ll_iso_receive_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS:
|
||||
rc = ble_ll_iso_read_counters_test(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_ISO_TEST_END:
|
||||
rc = ble_ll_iso_end_test(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_VERSION) >= 52
|
||||
case BLE_HCI_OCF_LE_SET_HOST_FEAT:
|
||||
rc = ble_ll_set_host_feat(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
|
||||
rc = ble_ll_conn_req_peer_sca(cmdbuf, len,
|
||||
rspbuf, rsplen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
@ -1176,6 +1272,26 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_lc_disconnect_cp *cmd;
|
||||
|
||||
cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
if (le16toh(cmd->conn_handle) >= BLE_LL_CONN_HANDLE_ISO_OFFSET) {
|
||||
return ble_ll_iso_disconnect_cmd(cmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ble_ll_conn_hci_disconnect_cmd(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a link control command sent from the host to the controller. The HCI
|
||||
* command has a 3 byte command header followed by data. The header is:
|
||||
@ -1196,7 +1312,7 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf)
|
||||
|
||||
switch (ocf) {
|
||||
case BLE_HCI_OCF_DISCONNECT_CMD:
|
||||
rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len);
|
||||
rc = ble_ll_hci_disconnect(cmdbuf, len);
|
||||
/* Send command status instead of command complete */
|
||||
rc += (BLE_ERR_MAX + 1);
|
||||
break;
|
||||
@ -1229,6 +1345,64 @@ ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
static int
|
||||
ble_ll_hci_cb_set_ctrlr_to_host_fc(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_cb_ctlr_to_host_fc_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* We only allow to either disable flow control or enable for ACL only */
|
||||
if (cmd->enable > 1) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (!ble_ll_conn_cth_flow_enable(cmd->enable)) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_cb_host_buf_size_cp *cmd = (const void *) cmdbuf;
|
||||
uint16_t acl_num;
|
||||
uint16_t acl_data_len;
|
||||
|
||||
if (len != sizeof (*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* We do not support SCO so those parameters should be set to 0 */
|
||||
if (cmd->sco_num || cmd->sco_data_len) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the
|
||||
* Controller shall support command and event packets, where the data portion
|
||||
* (excluding header) contained in the packets is 255 octets in size.".
|
||||
* This means we can basically accept any allowed value since LL does not
|
||||
* reassemble incoming data thus will not send more than 255 octets in single
|
||||
* data packet.
|
||||
*/
|
||||
acl_num = le16toh(cmd->acl_num);
|
||||
acl_data_len = le16toh(cmd->acl_data_len);
|
||||
if (acl_data_len < 255) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
ble_ll_conn_cth_flow_set_buffers(acl_num);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
@ -1261,6 +1435,22 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
rc = ble_ll_reset();
|
||||
}
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
case BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC:
|
||||
rc = ble_ll_hci_cb_set_ctrlr_to_host_fc(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_CB_HOST_BUF_SIZE:
|
||||
rc = ble_ll_hci_cb_host_buf_size(cmdbuf, len);
|
||||
break;
|
||||
case BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS:
|
||||
/*
|
||||
* HCI_Host_Number_Of_Completed_Packets is handled immediately when
|
||||
* received from transport so we should never receive it here.
|
||||
*/
|
||||
BLE_LL_ASSERT(0);
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
break;
|
||||
#endif
|
||||
case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
|
||||
rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len);
|
||||
break;
|
||||
@ -1337,6 +1527,47 @@ ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len,
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_HCI_VS)
|
||||
static int
|
||||
ble_ll_hci_vs_rd_static_addr(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
struct ble_hci_vs_rd_static_addr_rp *rsp = (void *) rspbuf;
|
||||
ble_addr_t addr;
|
||||
|
||||
if (ble_hw_get_static_addr(&addr) < 0) {
|
||||
return BLE_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
memcpy(rsp->addr, addr.val, sizeof(rsp->addr));
|
||||
|
||||
*rsplen = sizeof(*rsp);
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_vs_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Assume error; if all pass rc gets set to 0 */
|
||||
rc = BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
|
||||
switch (ocf) {
|
||||
case BLE_HCI_OCF_VS_RD_STATIC_ADDR:
|
||||
if (len == 0) {
|
||||
rc = ble_ll_hci_vs_rd_static_addr(rspbuf, rsplen);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called to process an HCI command from the host.
|
||||
*
|
||||
@ -1396,6 +1627,11 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
|
||||
case BLE_HCI_OGF_LE:
|
||||
rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb);
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_HCI_VS)
|
||||
case BLE_HCI_OGF_VENDOR:
|
||||
rc = ble_ll_hci_vs_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* XXX: Need to support other OGF. For now, return unsupported */
|
||||
rc = BLE_ERR_UNKNOWN_HCI_CMD;
|
||||
@ -1456,9 +1692,33 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
|
||||
* BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion.
|
||||
*/
|
||||
int
|
||||
ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
|
||||
ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg)
|
||||
{
|
||||
struct ble_npl_event *ev;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
const struct ble_hci_cmd *cmd;
|
||||
uint16_t opcode;
|
||||
uint16_t ocf;
|
||||
uint16_t ogf;
|
||||
|
||||
cmd = (const void *)cmdbuf;
|
||||
opcode = le16toh(cmd->opcode);
|
||||
ogf = BLE_HCI_OGF(opcode);
|
||||
ocf = BLE_HCI_OCF(opcode);
|
||||
|
||||
/*
|
||||
* HCI_Host_Number_Of_Completed_Packets is processed outside standard flow
|
||||
* thus it can be sent at any time, even if another command is already
|
||||
* pending. This means we should better process it here and send an event to
|
||||
* LL in case of error.
|
||||
*/
|
||||
if ((ogf == BLE_HCI_OGF_CTLR_BASEBAND) &&
|
||||
(ocf == BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS)) {
|
||||
ble_ll_conn_cth_flow_process_cmd(cmdbuf);
|
||||
ble_hci_trans_buf_free(cmdbuf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get an event structure off the queue */
|
||||
ev = &g_ble_ll_hci_cmd_ev;
|
||||
@ -1467,7 +1727,7 @@ ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
|
||||
}
|
||||
|
||||
/* Fill out the event and post to Link Layer */
|
||||
ble_npl_event_set_arg(ev, cmd);
|
||||
ble_npl_event_set_arg(ev, cmdbuf);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
|
||||
return 0;
|
||||
|
@ -463,6 +463,37 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
void
|
||||
ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status,
|
||||
uint8_t peer_sca)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_peer_sca_complete *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (!hci_ev) {
|
||||
return;
|
||||
}
|
||||
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP;
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->sca = peer_sca;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
|
||||
{
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 ESP_PLATFORM
|
||||
#include <stdint.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "../include/controller/ble_ll_iso.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
|
||||
int
|
||||
ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
/* Nothing to do here for now when HCI is supported */
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
|
||||
int
|
||||
ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
return BLE_ERR_UNSUPPORTED;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -18,6 +18,9 @@
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
/* for jrand48 */
|
||||
#define _XOPEN_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -121,6 +124,21 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Simple wrapper to allow easy replacement of rand() */
|
||||
uint32_t
|
||||
ble_ll_rand(void)
|
||||
{
|
||||
static unsigned short xsubi[3];
|
||||
static bool init = true;
|
||||
|
||||
if (init) {
|
||||
init = false;
|
||||
ble_ll_rand_data_get((uint8_t *)xsubi, sizeof(xsubi));
|
||||
}
|
||||
|
||||
return (uint32_t) jrand48(xsubi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
|
||||
*
|
||||
|
@ -295,7 +295,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
|
||||
STATS_INC(ble_ll_stats, scan_req_txf);
|
||||
}
|
||||
|
||||
scansm->backoff_count = rand() & (scansm->upper_limit - 1);
|
||||
scansm->backoff_count = ble_ll_rand() & (scansm->upper_limit - 1);
|
||||
++scansm->backoff_count;
|
||||
BLE_LL_ASSERT(scansm->backoff_count <= 256);
|
||||
}
|
||||
@ -307,7 +307,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
|
||||
ble_npl_time_t now;
|
||||
|
||||
now = ble_npl_time_get();
|
||||
if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
|
||||
if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) {
|
||||
/* Generate new NRPA */
|
||||
ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
|
||||
scansm->scan_nrpa[5] &= ~0xc0;
|
||||
@ -619,7 +619,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd,
|
||||
static int
|
||||
ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
|
||||
const uint8_t *addr, uint8_t addr_type,
|
||||
uint8_t rssi,
|
||||
int8_t rssi,
|
||||
uint8_t adv_data_len,
|
||||
struct os_mbuf *adv_data,
|
||||
const uint8_t *inita, uint8_t inita_type)
|
||||
@ -1127,6 +1127,22 @@ ble_ll_scan_sm_stop(int chk_disable)
|
||||
scansm = &g_ble_ll_scan_sm;
|
||||
os_cputime_timer_stop(&scansm->scan_timer);
|
||||
|
||||
/* Only set state if we are currently in a scan window */
|
||||
if (chk_disable) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
lls = ble_ll_state_get();
|
||||
|
||||
if ((lls == BLE_LL_STATE_SCANNING) ||
|
||||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
|
||||
/* Disable phy */
|
||||
ble_phy_disable();
|
||||
|
||||
/* Set LL state to standby */
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
/* Disable scanning state machine */
|
||||
@ -1151,22 +1167,6 @@ ble_ll_scan_sm_stop(int chk_disable)
|
||||
/* Count # of times stopped */
|
||||
STATS_INC(ble_ll_stats, scan_stops);
|
||||
|
||||
/* Only set state if we are currently in a scan window */
|
||||
if (chk_disable) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
lls = ble_ll_state_get();
|
||||
|
||||
if ((lls == BLE_LL_STATE_SCANNING) ||
|
||||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
|
||||
/* Disable phy */
|
||||
ble_phy_disable();
|
||||
|
||||
/* Set LL state to standby */
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
/* No need for RF anymore */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_ll_rfmgmt_scan_changed(false, 0);
|
||||
@ -1993,10 +1993,10 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad
|
||||
{
|
||||
struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
|
||||
struct ble_ll_scan_params *scanp = scansm->scanp;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo;
|
||||
struct ble_ll_resolv_entry *rl = NULL;
|
||||
#endif
|
||||
@ -2229,6 +2229,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
*/
|
||||
if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
rxinfo->rpa_index = aux_data->rpa_index;
|
||||
if (rxinfo->rpa_index >= 0) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED;
|
||||
@ -2236,6 +2237,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) {
|
||||
rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED;
|
||||
}
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -2687,10 +2689,16 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
|
||||
|
||||
/*
|
||||
* We need another event if either there are still some data left to
|
||||
* send in current PDU or scan is not completed. The only exception is
|
||||
* when this is a scannable event which is not a scan response.
|
||||
* send in current PDU or scan is not completed. There are two exceptions
|
||||
* though:
|
||||
* - we sent all data from this PDU and there is scan error set already;
|
||||
* it may be set before entering current function due to failed aux
|
||||
* scan scheduling
|
||||
* - this is a scannable event which is not a scan response
|
||||
*/
|
||||
need_event = ((offset < datalen) || (aux_data && !(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_COMPLETE))) && !is_scannable_aux;
|
||||
need_event = ((offset < datalen) || (aux_data && !(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_COMPLETE))) &&
|
||||
!((offset == datalen) && (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR)) &&
|
||||
!is_scannable_aux;
|
||||
|
||||
if (need_event) {
|
||||
/*
|
||||
@ -3021,7 +3029,8 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om,
|
||||
|
||||
if (!BLE_MBUF_HDR_DEVMATCH(hdr) ||
|
||||
!BLE_MBUF_HDR_CRC_OK(hdr) ||
|
||||
BLE_MBUF_HDR_IGNORED(hdr)) {
|
||||
BLE_MBUF_HDR_IGNORED(hdr) ||
|
||||
!scansm->scan_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3060,10 +3069,6 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
|
||||
bool send_hci_report;
|
||||
int rc;
|
||||
|
||||
if (!scansm->ext_scanning) {
|
||||
goto scan_continue;
|
||||
}
|
||||
|
||||
if (aux_data) {
|
||||
aux_data->flags_ll |= aux_data->flags_isr;
|
||||
}
|
||||
@ -3079,7 +3084,8 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
|
||||
BLE_MBUF_HDR_IGNORED(hdr) ||
|
||||
BLE_MBUF_HDR_AUX_INVALID(hdr) ||
|
||||
(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) ||
|
||||
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) {
|
||||
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) ||
|
||||
!scansm->scan_enabled) {
|
||||
if (aux_data) {
|
||||
ble_ll_scan_end_adv_evt(aux_data);
|
||||
ble_ll_scan_aux_data_unref(aux_data);
|
||||
|
@ -91,14 +91,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
|
||||
int rc;
|
||||
|
||||
rc = 1;
|
||||
if ((int32_t)(s1->start_time - s2->start_time) < 0) {
|
||||
if (CPUTIME_LT(s1->start_time, s2->start_time)) {
|
||||
/* Make sure this event does not overlap current event */
|
||||
if ((int32_t)(s1->end_time - s2->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(s1->end_time, s2->start_time)) {
|
||||
rc = 0;
|
||||
}
|
||||
} else {
|
||||
/* Check for overlap */
|
||||
if ((int32_t)(s1->start_time - s2->end_time) >= 0) {
|
||||
if (CPUTIME_GEQ(s1->start_time, s2->end_time)) {
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
|
||||
rc = 0;
|
||||
if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
|
||||
ce_end_time = ble_ll_conn_get_ce_end_time();
|
||||
if ((int32_t)(ce_end_time - sch->start_time) > 0) {
|
||||
if (CPUTIME_GT(ce_end_time, sch->start_time)) {
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
@ -186,7 +186,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
|
||||
sch->end_time = connsm->ce_end_time;
|
||||
|
||||
/* Better be past current time or we just leave */
|
||||
if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) {
|
||||
if (CPUTIME_LT(sch->start_time, os_cputime_get32())) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
|
||||
end_overlap = entry;
|
||||
}
|
||||
} else {
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
@ -476,7 +476,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
|
||||
sch->end_time = earliest_end;
|
||||
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
if ((earliest_start - initial_start) <= itvl_t) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
@ -663,7 +663,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
|
||||
sch->end_time = earliest_end;
|
||||
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
if ((earliest_start - initial_start) <= itvl_t) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
@ -778,7 +778,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
|
||||
while (1) {
|
||||
next_sch = entry->link.tqe_next;
|
||||
/* Insert if event ends before next starts */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
@ -1055,7 +1055,7 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
}
|
||||
@ -1119,7 +1119,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
break;
|
||||
}
|
||||
@ -1208,7 +1208,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
end_overlap = entry;
|
||||
}
|
||||
} else {
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
before = entry;
|
||||
break;
|
||||
}
|
||||
@ -1241,7 +1241,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
sch->end_time = sch->start_time + duration;
|
||||
while (1) {
|
||||
next_sch = entry->link.tqe_next;
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rand_ticks = entry->start_time - sch->end_time;
|
||||
before = entry;
|
||||
TAILQ_INSERT_BEFORE(before, sch, link);
|
||||
@ -1274,7 +1274,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
if (!rc) {
|
||||
sch->enqueued = 1;
|
||||
if (rand_ticks) {
|
||||
sch->start_time += rand() % rand_ticks;
|
||||
sch->start_time += ble_ll_rand() % rand_ticks;
|
||||
}
|
||||
sch->end_time = sch->start_time + duration;
|
||||
*start = sch->start_time;
|
||||
@ -1588,7 +1588,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
|
||||
while (sch) {
|
||||
/* Let's check if there is no scheduled item which want to start within
|
||||
* given usecs.*/
|
||||
if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) {
|
||||
if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) {
|
||||
/* We are fine. Have time for scan req */
|
||||
return 0;
|
||||
}
|
||||
@ -1678,7 +1678,7 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
|
||||
os_cputime_timer_stop(&g_ble_ll_sched_timer);
|
||||
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
|
||||
/* We can insert if before entry in list */
|
||||
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
|
||||
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
|
||||
rc = 0;
|
||||
TAILQ_INSERT_BEFORE(entry, sch, link);
|
||||
sch->enqueued = 1;
|
||||
|
@ -37,7 +37,22 @@
|
||||
|
||||
/* Octet 10 */
|
||||
#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
|
||||
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5)
|
||||
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6)
|
||||
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5)
|
||||
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_10 \
|
||||
( \
|
||||
BLE_SUPP_CMD_RD_TX_PWR | \
|
||||
BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \
|
||||
BLE_SUPP_CMD_HOST_BUFFER_SIZE | \
|
||||
BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \
|
||||
)
|
||||
|
||||
/* Octet 14 */
|
||||
#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3)
|
||||
@ -405,10 +420,77 @@
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1)
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_41 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \
|
||||
BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \
|
||||
BLE_SUPP_CMD_LE_SET_CIG_PARAM \
|
||||
)
|
||||
|
||||
/* Octet 42 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_42 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \
|
||||
BLE_SUPP_CMD_LE_CREATE_CIS | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_CIG | \
|
||||
BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \
|
||||
BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \
|
||||
BLE_SUPP_CMD_LE_CREATE_BIG | \
|
||||
BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \
|
||||
BLE_SUPP_CMD_LE_TERMINATE_BIG \
|
||||
)
|
||||
|
||||
/* Octet 43 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
|
||||
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_43 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \
|
||||
)
|
||||
|
||||
/* Octet 44 */
|
||||
#if MYNEWT_VAL(BLE_VERSION) >= 52
|
||||
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_44 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_HOST_FEATURE \
|
||||
)
|
||||
|
||||
/* Defines the array of supported commands */
|
||||
@ -456,6 +538,9 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
|
||||
BLE_LL_SUPP_CMD_OCTET_39,
|
||||
BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */
|
||||
BLE_LL_SUPP_CMD_OCTET_41,
|
||||
BLE_LL_SUPP_CMD_OCTET_42,
|
||||
BLE_LL_SUPP_CMD_OCTET_43,
|
||||
BLE_LL_SUPP_CMD_OCTET_44,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -61,6 +61,7 @@
|
||||
#define BLE_LL_SYNC_SM_FLAG_DISABLED 0x0040
|
||||
#define BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED 0x0080
|
||||
#define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100
|
||||
#define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200
|
||||
|
||||
#define BLE_LL_SYNC_CHMAP_LEN 5
|
||||
#define BLE_LL_SYNC_ITVL_USECS 1250
|
||||
@ -76,6 +77,9 @@ struct ble_ll_sync_sm {
|
||||
uint8_t chanmap[BLE_LL_SYNC_CHMAP_LEN];
|
||||
uint8_t num_used_chans;
|
||||
|
||||
uint8_t chanmap_new[BLE_LL_SYNC_CHMAP_LEN];
|
||||
uint16_t chanmap_new_instant;
|
||||
|
||||
uint8_t chan_index;
|
||||
uint8_t chan_chain;
|
||||
|
||||
@ -526,7 +530,8 @@ ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr)
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
|
||||
ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power,
|
||||
uint8_t **acad, uint8_t *acad_len)
|
||||
{
|
||||
uint8_t *rxbuf = om->om_data;
|
||||
uint8_t ext_hdr_flags;
|
||||
@ -586,12 +591,17 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
|
||||
i += BLE_LL_EXT_ADV_TX_POWER_SIZE;
|
||||
}
|
||||
|
||||
/* TODO Handle ACAD if needed */
|
||||
|
||||
/* sanity check */
|
||||
if (i > ext_hdr_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ACAD */
|
||||
if (ext_hdr_len > (i + 1)) {
|
||||
*acad = ext_hdr + i;
|
||||
*acad_len = ext_hdr_len - i - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pdu_len - ext_hdr_len - 1;
|
||||
@ -997,6 +1007,70 @@ ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm)
|
||||
ble_ll_sync_est_event_failed(BLE_ERR_CONN_ESTABLISHMENT);
|
||||
}
|
||||
|
||||
static bool
|
||||
ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm,
|
||||
const uint8_t *acad, uint8_t acad_len)
|
||||
{
|
||||
const struct ble_ll_acad_channel_map_update_ind *chmu;
|
||||
unsigned int ad_len;
|
||||
uint8_t ad_type;
|
||||
|
||||
/* assume no empty fields */
|
||||
while (acad_len > 2) {
|
||||
ad_len = acad[0];
|
||||
ad_type = acad[1];
|
||||
|
||||
/* early termination should not happen in ACAD */
|
||||
if (ad_len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check if not passing pass acad data */
|
||||
if (ad_len + 1 > acad_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ad_type) {
|
||||
case BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND:
|
||||
chmu = (const void *)&acad[2];
|
||||
|
||||
if (ad_len - 1 != sizeof(*chmu)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Channels Mask (37 bits)
|
||||
* TODO should we check this?
|
||||
*/
|
||||
sm->chanmap_new[0] = chmu->map[0];
|
||||
sm->chanmap_new[1] = chmu->map[1];
|
||||
sm->chanmap_new[2] = chmu->map[2];
|
||||
sm->chanmap_new[3] = chmu->map[3];
|
||||
sm->chanmap_new[4] = chmu->map[4] & 0x1f;
|
||||
|
||||
/* drop if channel map is invalid */
|
||||
if (ble_ll_utils_calc_num_used_chans(sm->chanmap_new) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sm->chanmap_new_instant = le16toh(chmu->instant);
|
||||
sm->flags |= BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
acad += ad_len + 1;
|
||||
acad_len -= ad_len + 1;
|
||||
}
|
||||
|
||||
/* should have no trailing zeros */
|
||||
if (acad_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
{
|
||||
@ -1004,7 +1078,10 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
bool aux_scheduled = false;
|
||||
int8_t tx_power = 127; /* defaults to not available */
|
||||
uint8_t *aux = NULL;
|
||||
uint8_t *acad = NULL;
|
||||
uint8_t acad_len;
|
||||
int datalen;
|
||||
bool reports_enabled;
|
||||
|
||||
BLE_LL_ASSERT(sm);
|
||||
|
||||
@ -1049,36 +1126,43 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
goto end_event;
|
||||
}
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) &&
|
||||
!(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) {
|
||||
/* get ext header data */
|
||||
datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power);
|
||||
if (datalen < 0) {
|
||||
/* we got bad packet, end event */
|
||||
goto end_event;
|
||||
}
|
||||
/* get ext header data */
|
||||
datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len);
|
||||
if (datalen < 0) {
|
||||
/* we got bad packet, end event */
|
||||
goto end_event;
|
||||
}
|
||||
|
||||
reports_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) &&
|
||||
!(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED);
|
||||
|
||||
/* no need to schedule for chain if reporting is disabled */
|
||||
if (reports_enabled) {
|
||||
/* if aux is present, we need to schedule ASAP */
|
||||
if (aux && (ble_ll_sync_schedule_chain(sm, hdr, aux) == 0)) {
|
||||
aux_scheduled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* in case data reporting is enabled we need to send sync established here */
|
||||
if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
|
||||
ble_ll_sync_established(sm);
|
||||
}
|
||||
/* check ACAD, needs to be done before rxpdu is adjusted for ADV data */
|
||||
if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len)) {
|
||||
/* we got bad packet (bad ACAD data), end event */
|
||||
goto end_event;
|
||||
}
|
||||
|
||||
/* we need to establish link even if reporting was disabled */
|
||||
if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
|
||||
ble_ll_sync_established(sm);
|
||||
}
|
||||
|
||||
/* only if reporting is enabled */
|
||||
if (reports_enabled) {
|
||||
/* Adjust rxpdu to contain advertising data only */
|
||||
ble_ll_sync_adjust_ext_hdr(rxpdu);
|
||||
|
||||
/* send reports from this PDU */
|
||||
ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power,
|
||||
datalen, aux, aux_scheduled);
|
||||
} else {
|
||||
/* we need to establish link even if reporting was disabled */
|
||||
if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
|
||||
ble_ll_sync_established(sm);
|
||||
}
|
||||
}
|
||||
|
||||
/* if chain was scheduled we don't end event yet */
|
||||
@ -1132,6 +1216,20 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
|
||||
/* Set event counter to the next event */
|
||||
sm->event_cntr += 1 + skip;
|
||||
|
||||
/* update channel map if needed */
|
||||
if (sm->flags & BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP) {
|
||||
if (((int16_t)(sm->event_cntr - sm->chanmap_new_instant)) >= 0) {
|
||||
/* map was verified on reception */
|
||||
sm->chanmap[0] = sm->chanmap_new[0];
|
||||
sm->chanmap[1] = sm->chanmap_new[1];
|
||||
sm->chanmap[2] = sm->chanmap_new[2];
|
||||
sm->chanmap[3] = sm->chanmap_new[3];
|
||||
sm->chanmap[4] = sm->chanmap_new[4];
|
||||
sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap);
|
||||
sm->flags &= ~BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate channel index of next event */
|
||||
sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id,
|
||||
sm->num_used_chans, sm->chanmap);
|
||||
@ -2092,10 +2190,10 @@ ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm,
|
||||
if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) {
|
||||
sync_ind[24] |= 1 << 4;
|
||||
} else {
|
||||
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ;
|
||||
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4;
|
||||
}
|
||||
|
||||
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
|
||||
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
|
||||
|
||||
/* PHY */
|
||||
sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1));
|
||||
|
@ -51,8 +51,8 @@ ble_ll_utils_calc_access_addr(void)
|
||||
aa = 0;
|
||||
while (1) {
|
||||
/* Get two, 16-bit random numbers */
|
||||
aa_low = rand() & 0xFFFF;
|
||||
aa_high = rand() & 0xFFFF;
|
||||
aa_low = ble_ll_rand() & 0xFFFF;
|
||||
aa_high = ble_ll_rand() & 0xFFFF;
|
||||
|
||||
/* All four bytes cannot be equal */
|
||||
if (aa_low == aa_high) {
|
||||
@ -293,8 +293,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point,
|
||||
time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
|
||||
if (time_since_last_anchor > 0) {
|
||||
delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
|
||||
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] +
|
||||
MYNEWT_VAL(BLE_LL_OUR_SCA);
|
||||
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA);
|
||||
window_widening = (total_sca_ppm * delta_msec) / 1000;
|
||||
}
|
||||
|
||||
|
@ -1508,7 +1508,7 @@ ble_phy_resolv_list_disable(void)
|
||||
void
|
||||
ble_phy_rfclk_enable(void)
|
||||
{
|
||||
#if MYNEWT
|
||||
#if MYNEWT || ARDUINO
|
||||
nrf51_clock_hfxo_request();
|
||||
#else
|
||||
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||
@ -1518,7 +1518,7 @@ ble_phy_rfclk_enable(void)
|
||||
void
|
||||
ble_phy_rfclk_disable(void)
|
||||
{
|
||||
#if MYNEWT
|
||||
#if MYNEWT || ARDUINO
|
||||
nrf51_clock_hfxo_release();
|
||||
#else
|
||||
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
|
||||
|
||||
#include <stdint.h>
|
||||
@ -2100,7 +2100,7 @@ void ble_phy_disable_dtm(void)
|
||||
void
|
||||
ble_phy_rfclk_enable(void)
|
||||
{
|
||||
#if MYNEWT
|
||||
#if MYNEWT || ARDUINO
|
||||
nrf52_clock_hfxo_request();
|
||||
#else
|
||||
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||
@ -2110,7 +2110,7 @@ ble_phy_rfclk_enable(void)
|
||||
void
|
||||
ble_phy_rfclk_disable(void)
|
||||
{
|
||||
#if MYNEWT
|
||||
#if MYNEWT || ARDUINO
|
||||
nrf52_clock_hfxo_release();
|
||||
#else
|
||||
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
|
||||
|
@ -39,41 +39,47 @@ extern "C" {
|
||||
struct hci_le_conn_complete;
|
||||
struct hci_conn_update;
|
||||
|
||||
#define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10)
|
||||
|
||||
/** 30 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30)
|
||||
|
||||
/** 60 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60)
|
||||
|
||||
/** 100 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN (100 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100)
|
||||
|
||||
/** 150 ms. */
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX (150 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150)
|
||||
|
||||
/** 30 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN BLE_GAP_SCAN_ITVL_MS(30)
|
||||
|
||||
/** 60 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX BLE_GAP_SCAN_ITVL_MS(60)
|
||||
|
||||
/** 11.25 ms; limited discovery interval. */
|
||||
#define BLE_GAP_LIM_DISC_SCAN_INT (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_LIM_DISC_SCAN_INT BLE_GAP_SCAN_ITVL_MS(11.25)
|
||||
|
||||
/** 11.25 ms; limited discovery window (not from the spec). */
|
||||
#define BLE_GAP_LIM_DISC_SCAN_WINDOW (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_LIM_DISC_SCAN_WINDOW BLE_GAP_SCAN_WIN_MS(11.25)
|
||||
|
||||
/** 30 ms; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_WINDOW (30 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30)
|
||||
|
||||
/* 30.72 seconds; active scanning. */
|
||||
#define BLE_GAP_SCAN_FAST_PERIOD (30.72 * 1000)
|
||||
#define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72)
|
||||
|
||||
/** 1.28 seconds; background scanning. */
|
||||
#define BLE_GAP_SCAN_SLOW_INTERVAL1 (1280 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_SLOW_INTERVAL1 BLE_GAP_SCAN_ITVL_MS(1280)
|
||||
|
||||
/** 11.25 ms; background scanning. */
|
||||
#define BLE_GAP_SCAN_SLOW_WINDOW1 (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
|
||||
#define BLE_GAP_SCAN_SLOW_WINDOW1 BLE_GAP_SCAN_WIN_MS(11.25)
|
||||
|
||||
/** 10.24 seconds. */
|
||||
#define BLE_GAP_DISC_DUR_DFLT (10.24 * 1000)
|
||||
@ -88,10 +94,10 @@ struct hci_conn_update;
|
||||
#define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000)
|
||||
|
||||
/* 30 ms. */
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MIN (30 * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30)
|
||||
|
||||
/* 50 ms. */
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MAX (50 * 1000 / BLE_HCI_CONN_ITVL)
|
||||
#define BLE_GAP_INITIAL_CONN_ITVL_MAX BLE_GAP_CONN_ITVL_MS(50)
|
||||
|
||||
/** Default channels mask: all three channels are used. */
|
||||
#define BLE_GAP_ADV_DFLT_CHANNEL_MAP 0x07
|
||||
@ -1156,6 +1162,38 @@ int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);
|
||||
int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
|
||||
uint16_t tx_time);
|
||||
|
||||
/**
|
||||
* Read host's suggested values for the controller's maximum transmitted number of payload octets
|
||||
* and maximum packet transmission time (OGF = 0x08, OCF = 0x0024).
|
||||
*
|
||||
* @param out_sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
|
||||
* number of payload octets in LL Data PDUs to be used for new
|
||||
* connections. (Range 0x001B-0x00FB).
|
||||
* @param out_sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
|
||||
* transmission time for packets containing LL Data PDUs to be used
|
||||
* for new connections. (Range 0x0148-0x4290).
|
||||
*
|
||||
* @return 0 on success,
|
||||
* other error code on failure.
|
||||
*/
|
||||
int ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
|
||||
uint16_t *out_sugg_max_tx_time);
|
||||
/**
|
||||
* Configure host's suggested maximum transmitted number of payload octets and maximum packet
|
||||
* transmission time in controller (OGF = 0x08, OCF = 0x0024).
|
||||
*
|
||||
* @param sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
|
||||
* number of payload octets in LL Data PDUs to be used for new
|
||||
* connections. (Range 0x001B-0x00FB).
|
||||
* @param sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
|
||||
* transmission time for packets containing LL Data PDUs to be used
|
||||
* for new connections. (Range 0x0148-0x4290).
|
||||
*
|
||||
* @return 0 on success,
|
||||
* other error code on failure.
|
||||
*/
|
||||
int ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time);
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/** @brief Extended advertising parameters */
|
||||
struct ble_gap_ext_adv_params {
|
||||
@ -1837,6 +1875,37 @@ int ble_gap_update_params(uint16_t conn_handle,
|
||||
*/
|
||||
int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time);
|
||||
|
||||
/**
|
||||
* Read LE Suggested Default Data Length in controller (OGF = 0x08, OCF = 0x0024).
|
||||
*
|
||||
* @param out_sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
|
||||
* number of payload octets in LL Data PDUs to be used for new
|
||||
* connections. (Range 0x001B-0x00FB).
|
||||
* @param out_sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
|
||||
* transmission time for packets containing LL Data PDUs to be used
|
||||
* for new connections. (Range 0x0148-0x4290).
|
||||
*
|
||||
* @return 0 on success,
|
||||
* other error code on failure.
|
||||
*/
|
||||
int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
|
||||
uint16_t *out_sugg_max_tx_time);
|
||||
|
||||
/**
|
||||
* Configure LE Suggested Default Data Length in controller (OGF = 0x08, OCF = 0x0024).
|
||||
*
|
||||
* @param sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
|
||||
* number of payload octets in LL Data PDUs to be used for new
|
||||
* connections. (Range 0x001B-0x00FB).
|
||||
* @param sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
|
||||
* transmission time for packets containing LL Data PDUs to be used
|
||||
* for new connections. (Range 0x0148-0x4290).
|
||||
*
|
||||
* @return 0 on success,
|
||||
* other error code on failure.
|
||||
*/
|
||||
int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time);
|
||||
|
||||
/**
|
||||
* Initiates the GAP security procedure.
|
||||
*
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define H_BLE_HS_LOG_
|
||||
|
||||
#include "nimble/porting/nimble/include/modlog/modlog.h"
|
||||
#include "nimble/porting/nimble/include/log/log.h"
|
||||
|
||||
/* Only include the logcfg header if this version of newt can generate it. */
|
||||
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
|
||||
|
@ -32,6 +32,7 @@ extern "C" {
|
||||
int ble_monitor_log(int level, const char *fmt, ...);
|
||||
|
||||
int ble_monitor_out(int c);
|
||||
void ble_monitor_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -28,14 +28,23 @@ extern "C" {
|
||||
#define BT_MESH_ADDR_RELAYS 0xfffe
|
||||
|
||||
#define BT_MESH_KEY_UNUSED 0xffff
|
||||
#define BT_MESH_KEY_ANY 0xffff
|
||||
#define BT_MESH_KEY_DEV 0xfffe
|
||||
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
|
||||
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
|
||||
#define BT_MESH_KEY_DEV_ANY 0xfffc
|
||||
|
||||
#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
|
||||
#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
|
||||
#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
|
||||
#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
|
||||
|
||||
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
|
||||
key == BT_MESH_KEY_DEV_REMOTE)
|
||||
|
||||
#define BT_MESH_APP_SEG_SDU_MAX 12
|
||||
#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
|
||||
#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
|
||||
/** Helper to define a mesh element within an array.
|
||||
*
|
||||
* In case the element has no SIG or Vendor models the helper
|
||||
@ -57,13 +66,13 @@ extern "C" {
|
||||
/** Abstraction that describes a Mesh Element */
|
||||
struct bt_mesh_elem {
|
||||
/* Unicast Address. Set at runtime during provisioning. */
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
|
||||
const u16_t loc;
|
||||
const uint16_t loc;
|
||||
|
||||
const u8_t model_count;
|
||||
const u8_t vnd_model_count;
|
||||
const uint8_t model_count;
|
||||
const uint8_t vnd_model_count;
|
||||
|
||||
struct bt_mesh_model * const models;
|
||||
struct bt_mesh_model * const vnd_models;
|
||||
@ -132,33 +141,33 @@ struct bt_mesh_elem {
|
||||
/** Message sending context. */
|
||||
struct bt_mesh_msg_ctx {
|
||||
/** NetKey Index of the subnet to send the message on. */
|
||||
u16_t net_idx;
|
||||
uint16_t net_idx;
|
||||
|
||||
/** AppKey Index to encrypt the message with. */
|
||||
u16_t app_idx;
|
||||
uint16_t app_idx;
|
||||
|
||||
/** Remote address. */
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
|
||||
/** Destination address of a received message. Not used for sending. */
|
||||
u16_t recv_dst;
|
||||
uint16_t recv_dst;
|
||||
|
||||
/** RSSI of received packet. Not used for sending. */
|
||||
s8_t recv_rssi;
|
||||
int8_t recv_rssi;
|
||||
|
||||
/** Received TTL value. Not used for sending. */
|
||||
u8_t recv_ttl;
|
||||
uint8_t recv_ttl;
|
||||
|
||||
/** Force sending reliably by using segment acknowledgement */
|
||||
bool send_rel;
|
||||
|
||||
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
|
||||
u8_t send_ttl;
|
||||
uint8_t send_ttl;
|
||||
};
|
||||
|
||||
struct bt_mesh_model_op {
|
||||
/* OpCode encoded using the BT_MESH_MODEL_OP_* macros */
|
||||
const u32_t opcode;
|
||||
const uint32_t opcode;
|
||||
|
||||
/* Minimum required message length */
|
||||
const size_t min_len;
|
||||
@ -324,7 +333,7 @@ struct bt_mesh_model_op {
|
||||
*
|
||||
* @return Transmission count (actual transmissions is N + 1).
|
||||
*/
|
||||
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (u8_t)BIT_MASK(3)))
|
||||
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
|
||||
|
||||
/** @def BT_MESH_TRANSMIT_INT
|
||||
*
|
||||
@ -375,23 +384,24 @@ struct bt_mesh_model_pub {
|
||||
/** The model the context belongs to. Initialized by the stack. */
|
||||
struct bt_mesh_model *mod;
|
||||
|
||||
u16_t addr; /**< Publish Address. */
|
||||
u16_t key; /**< Publish AppKey Index. */
|
||||
uint16_t addr; /**< Publish Address. */
|
||||
uint16_t key; /**< Publish AppKey Index. */
|
||||
|
||||
u8_t ttl; /**< Publish Time to Live. */
|
||||
u8_t retransmit; /**< Retransmit Count & Interval Steps. */
|
||||
u8_t period; /**< Publish Period. */
|
||||
u8_t period_div:4, /**< Divisor for the Period. */
|
||||
uint8_t ttl; /**< Publish Time to Live. */
|
||||
uint8_t retransmit; /**< Retransmit Count & Interval Steps. */
|
||||
uint8_t period; /**< Publish Period. */
|
||||
uint8_t period_div:4, /**< Divisor for the Period. */
|
||||
cred:1, /**< Friendship Credentials Flag. */
|
||||
send_rel:1,
|
||||
fast_period:1,/**< Use FastPeriodDivisor */
|
||||
count:3; /**< Retransmissions left. */
|
||||
|
||||
u32_t period_start; /**< Start of the current period. */
|
||||
uint32_t period_start; /**< Start of the current period. */
|
||||
|
||||
/** @brief Publication buffer, containing the publication message.
|
||||
*
|
||||
* The application is expected to initialize this with
|
||||
* a valid net_buf_simple pointer, with the help of e.g.
|
||||
* a valid os_mbuf pointer, with the help of e.g.
|
||||
* the NET_BUF_SIMPLE() macro. The publication buffer must
|
||||
* contain a valid publication message before calling the
|
||||
* bt_mesh_model_publish() API or after the publication's
|
||||
@ -414,6 +424,10 @@ struct bt_mesh_model_pub {
|
||||
* will be called periodically and is expected to update
|
||||
* @ref bt_mesh_model_pub.msg with a valid publication
|
||||
* message.
|
||||
*
|
||||
* If the callback returns non-zero, the publication is skipped
|
||||
* and will resume on the next periodic publishing interval.
|
||||
*
|
||||
*
|
||||
* @param mod The Model the Publication Context belogs to.
|
||||
*
|
||||
@ -432,16 +446,18 @@ struct bt_mesh_model_cb {
|
||||
* @sa settings_handler::h_set
|
||||
*
|
||||
* @param model Model to set the persistent data of.
|
||||
* @param name Name/key of the settings item.
|
||||
* @param val Data from the backend.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_set)(struct bt_mesh_model *model, char *val);
|
||||
int (*const settings_set)(struct bt_mesh_model *model,
|
||||
const char *name, char *val);
|
||||
|
||||
/** @brief Callback called when all settings have been loaded.
|
||||
/** @brief Callback called when the mesh is started.
|
||||
*
|
||||
* This handler gets called after the settings have been loaded in
|
||||
* full.
|
||||
* This handler gets called after the node has been provisioned, or
|
||||
* after all mesh data has been loaded from persistent storage.
|
||||
*
|
||||
* @sa settings_handler::h_commit
|
||||
*
|
||||
@ -449,12 +465,17 @@ struct bt_mesh_model_cb {
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
*/
|
||||
int (*const settings_commit)(struct bt_mesh_model *model);
|
||||
int (*const start)(struct bt_mesh_model *model);
|
||||
|
||||
/** @brief Model init callback.
|
||||
*
|
||||
* Called on every model instance during mesh initialization.
|
||||
*
|
||||
*
|
||||
* If any of the model init callbacks return an error, the Mesh
|
||||
* subsystem initialization will be aborted, and the error will be
|
||||
* returned to the caller of @ref bt_mesh_init.
|
||||
*
|
||||
* @param model Model to be initialized.
|
||||
*
|
||||
* @return 0 on success, error otherwise.
|
||||
@ -466,6 +487,9 @@ struct bt_mesh_model_cb {
|
||||
* Called when the mesh node is reset. All model data is deleted on
|
||||
* reset, and the model should clear its state.
|
||||
*
|
||||
* @note If the model stores any persistent data, this needs to be
|
||||
* erased manually.
|
||||
*
|
||||
* @param model Model this callback belongs to.
|
||||
*/
|
||||
void (*const reset)(struct bt_mesh_model *model);
|
||||
@ -474,26 +498,26 @@ struct bt_mesh_model_cb {
|
||||
/** Abstraction that describes a Mesh Model instance */
|
||||
struct bt_mesh_model {
|
||||
union {
|
||||
const u16_t id;
|
||||
const uint16_t id;
|
||||
struct {
|
||||
u16_t company;
|
||||
u16_t id;
|
||||
uint16_t company;
|
||||
uint16_t id;
|
||||
} vnd;
|
||||
};
|
||||
|
||||
/* Internal information, mainly for persistent storage */
|
||||
u8_t elem_idx; /* Belongs to Nth element */
|
||||
u8_t mod_idx; /* Is the Nth model in the element */
|
||||
u16_t flags; /* Model flags for internal bookkeeping */
|
||||
uint8_t elem_idx; /* Belongs to Nth element */
|
||||
uint8_t mod_idx; /* Is the Nth model in the element */
|
||||
uint16_t flags; /* Model flags for internal bookkeeping */
|
||||
|
||||
/* Model Publication */
|
||||
struct bt_mesh_model_pub * const pub;
|
||||
|
||||
/* AppKey List */
|
||||
u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
|
||||
uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
|
||||
|
||||
/* Subscription List (group or virtual addresses) */
|
||||
u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
|
||||
const struct bt_mesh_model_op * const op;
|
||||
|
||||
@ -511,11 +535,11 @@ struct bt_mesh_model {
|
||||
};
|
||||
|
||||
struct bt_mesh_send_cb {
|
||||
void (*start)(u16_t duration, int err, void *cb_data);
|
||||
void (*start)(uint16_t duration, int err, void *cb_data);
|
||||
void (*end)(int err, void *cb_data);
|
||||
};
|
||||
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode);
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode);
|
||||
|
||||
/** Special TTL value to request using configured default TTL */
|
||||
#define BT_MESH_TTL_DEFAULT 0xff
|
||||
@ -574,7 +598,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
|
||||
* if no SIG model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id);
|
||||
uint16_t id);
|
||||
|
||||
/** @brief Find a vendor model.
|
||||
*
|
||||
@ -586,7 +610,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
* if no vendor model with the given ID exists in the given element.
|
||||
*/
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id);
|
||||
uint16_t company, uint16_t id);
|
||||
|
||||
/** @brief Get whether the model is in the primary element of the device.
|
||||
*
|
||||
@ -603,13 +627,14 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
|
||||
*
|
||||
* @param mod Mesh model.
|
||||
* @param vnd This is a vendor model.
|
||||
* @param name Name/key of the settings item.
|
||||
* @param data Model data to store, or NULL to delete any model data.
|
||||
* @param data_len Length of the model data.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
|
||||
const void *data, size_t data_len);
|
||||
const char *name, const void *data, size_t data_len);
|
||||
|
||||
/** @brief Let a model extend another.
|
||||
*
|
||||
@ -637,9 +662,9 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod,
|
||||
|
||||
/** Node Composition */
|
||||
struct bt_mesh_comp {
|
||||
u16_t cid;
|
||||
u16_t pid;
|
||||
u16_t vid;
|
||||
uint16_t cid;
|
||||
uint16_t pid;
|
||||
uint16_t vid;
|
||||
|
||||
size_t elem_count;
|
||||
struct bt_mesh_elem *elem;
|
||||
|
@ -0,0 +1,409 @@
|
||||
/* atomic operations */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-2015, Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ATOMIC_H__
|
||||
#define __ATOMIC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef int atomic_t;
|
||||
typedef atomic_t atomic_val_t;
|
||||
|
||||
/**
|
||||
* @defgroup atomic_apis Atomic Services APIs
|
||||
* @ingroup kernel_apis
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Atomic compare-and-set.
|
||||
*
|
||||
* This routine performs an atomic compare-and-set on @a target. If the current
|
||||
* value of @a target equals @a old_value, @a target is set to @a new_value.
|
||||
* If the current value of @a target does not equal @a old_value, @a target
|
||||
* is left unchanged.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param old_value Original value to compare against.
|
||||
* @param new_value New value to store.
|
||||
* @return 1 if @a new_value is written, 0 otherwise.
|
||||
*/
|
||||
static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
|
||||
atomic_val_t new_value)
|
||||
{
|
||||
return __atomic_compare_exchange_n(target, &old_value, new_value,
|
||||
0, __ATOMIC_SEQ_CST,
|
||||
__ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic addition.
|
||||
*
|
||||
* This routine performs an atomic addition on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to add.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic subtraction.
|
||||
*
|
||||
* This routine performs an atomic subtraction on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to subtract.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic increment.
|
||||
*
|
||||
* This routine performs an atomic increment by 1 on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_inc(atomic_t *target)
|
||||
{
|
||||
return atomic_add(target, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic decrement.
|
||||
*
|
||||
* This routine performs an atomic decrement by 1 on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_dec(atomic_t *target)
|
||||
{
|
||||
return atomic_sub(target, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic get.
|
||||
*
|
||||
* This routine performs an atomic read on @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_get(const atomic_t *target)
|
||||
{
|
||||
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic get-and-set.
|
||||
*
|
||||
* This routine atomically sets @a target to @a value and returns
|
||||
* the previous value of @a target.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to write to @a target.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
/* This builtin, as described by Intel, is not a traditional
|
||||
* test-and-set operation, but rather an atomic exchange operation. It
|
||||
* writes value into *ptr, and returns the previous contents of *ptr.
|
||||
*/
|
||||
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic clear.
|
||||
*
|
||||
* This routine atomically sets @a target to zero and returns its previous
|
||||
* value. (Hence, it is equivalent to atomic_set(target, 0).)
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_clear(atomic_t *target)
|
||||
{
|
||||
return atomic_set(target, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise inclusive OR.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise inclusive OR of
|
||||
* @a target and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to OR.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise exclusive OR (XOR).
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
|
||||
* @a target and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to XOR
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise AND.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise AND of @a target
|
||||
* and @a value.
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to AND.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomic bitwise NAND.
|
||||
*
|
||||
* This routine atomically sets @a target to the bitwise NAND of @a target
|
||||
* and @a value. (This operation is equivalent to target = ~(target & value).)
|
||||
*
|
||||
* @param target Address of atomic variable.
|
||||
* @param value Value to NAND.
|
||||
*
|
||||
* @return Previous value of @a target.
|
||||
*/
|
||||
|
||||
static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
|
||||
{
|
||||
return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize an atomic variable.
|
||||
*
|
||||
* This macro can be used to initialize an atomic variable. For example,
|
||||
* @code atomic_t my_var = ATOMIC_INIT(75); @endcode
|
||||
*
|
||||
* @param i Value to assign to atomic variable.
|
||||
*/
|
||||
#define ATOMIC_INIT(i) (i)
|
||||
|
||||
/**
|
||||
* @cond INTERNAL_HIDDEN
|
||||
*/
|
||||
|
||||
#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
|
||||
#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
|
||||
#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
|
||||
|
||||
/**
|
||||
* INTERNAL_HIDDEN @endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define an array of atomic variables.
|
||||
*
|
||||
* This macro defines an array of atomic variables containing at least
|
||||
* @a num_bits bits.
|
||||
*
|
||||
* @note
|
||||
* If used from file scope, the bits of the array are initialized to zero;
|
||||
* if used from within a function, the bits are left uninitialized.
|
||||
*
|
||||
* @param name Name of array of atomic variables.
|
||||
* @param num_bits Number of bits needed.
|
||||
*/
|
||||
#define ATOMIC_DEFINE(name, num_bits) \
|
||||
atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
|
||||
|
||||
/**
|
||||
* @brief Atomically test a bit.
|
||||
*
|
||||
* This routine tests whether bit number @a bit of @a target is set or not.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_bit(const atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
|
||||
|
||||
return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically test and clear a bit.
|
||||
*
|
||||
* Atomically clear bit number @a bit of @a target and return its old value.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_and_clear_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
atomic_val_t old;
|
||||
|
||||
old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target and return its old value.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return 1 if the bit was set, 0 if it wasn't.
|
||||
*/
|
||||
static inline int
|
||||
atomic_test_and_set_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
atomic_val_t old;
|
||||
|
||||
old = atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically clear a bit.
|
||||
*
|
||||
* Atomically clear bit number @a bit of @a target.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void
|
||||
atomic_clear_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void
|
||||
atomic_set_bit(atomic_t *target, int bit)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Atomically set a bit to a given value.
|
||||
*
|
||||
* Atomically set bit number @a bit of @a target to value @a val.
|
||||
* The target may be a single atomic variable or an array of them.
|
||||
*
|
||||
* @param target Address of atomic variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
* @param val true for 1, false for 0.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
|
||||
{
|
||||
atomic_val_t mask = ATOMIC_MASK(bit);
|
||||
|
||||
if (val) {
|
||||
(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
|
||||
} else {
|
||||
(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ATOMIC_H__ */
|
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Tobias Svehagen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BLUETOOTH_MESH_CDB_H_
|
||||
#define _BLUETOOTH_MESH_CDB_H_
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_CDB)
|
||||
#define NODE_COUNT CONFIG_BT_MESH_NODE_COUNT
|
||||
#define SUBNET_COUNT CONFIG_BT_MESH_SUBNET_COUNT
|
||||
#define APP_KEY_COUNT CONFIG_BT_MESH_APP_KEY_COUNT
|
||||
#else
|
||||
#define NODE_COUNT 0
|
||||
#define SUBNET_COUNT 0
|
||||
#define APP_KEY_COUNT 0
|
||||
#endif
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_NODE_CONFIGURED,
|
||||
BT_MESH_CDB_NODE_BLACKLISTED,
|
||||
|
||||
BT_MESH_CDB_NODE_FLAG_COUNT
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_node {
|
||||
uint8_t uuid[16];
|
||||
uint16_t addr;
|
||||
uint16_t net_idx;
|
||||
uint8_t num_elem;
|
||||
uint8_t dev_key[16];
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_subnet {
|
||||
uint16_t net_idx;
|
||||
|
||||
bool kr_flag;
|
||||
uint8_t kr_phase;
|
||||
|
||||
struct {
|
||||
uint8_t net_key[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb_app_key {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
|
||||
struct {
|
||||
uint8_t app_key[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_VALID,
|
||||
BT_MESH_CDB_SUBNET_PENDING,
|
||||
BT_MESH_CDB_KEYS_PENDING,
|
||||
BT_MESH_CDB_NODES_PENDING,
|
||||
BT_MESH_CDB_IVU_IN_PROGRESS,
|
||||
|
||||
BT_MESH_CDB_FLAG_COUNT,
|
||||
};
|
||||
|
||||
struct bt_mesh_cdb {
|
||||
uint32_t iv_index;
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
|
||||
|
||||
struct bt_mesh_cdb_node nodes[NODE_COUNT];
|
||||
struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
|
||||
struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
|
||||
};
|
||||
|
||||
extern struct bt_mesh_cdb bt_mesh_cdb;
|
||||
|
||||
/** @brief Create the Mesh Configuration Database.
|
||||
*
|
||||
* Create and initialize the Mesh Configuration Database. A primary subnet,
|
||||
* ie one with NetIdx 0, will be added and the provided key will be used as
|
||||
* NetKey for that subnet.
|
||||
*
|
||||
* @param key The NetKey to be used for the primary subnet.
|
||||
*
|
||||
* @return 0 on success or negative error code on failure.
|
||||
*/
|
||||
int bt_mesh_cdb_create(const uint8_t key[16]);
|
||||
|
||||
/** @brief Clear the Mesh Configuration Database.
|
||||
*
|
||||
* Remove all nodes, subnets and app-keys stored in the database and mark
|
||||
* the database as invalid. The data will be cleared from persistent storage
|
||||
* if CONFIG_BT_SETTINGS is enabled.
|
||||
*/
|
||||
void bt_mesh_cdb_clear(void);
|
||||
|
||||
/** @brief Set and store the IV Index and IV Update flag.
|
||||
*
|
||||
* The IV Index stored in the CDB will be the one used during provisioning
|
||||
* of new nodes. This function is generally only used from inside the stack.
|
||||
*
|
||||
* This function will store the data to persistent storage if
|
||||
* CONFIG_BT_SETTINGS is enabled.
|
||||
*
|
||||
* @param iv_index The new IV Index to use.
|
||||
* @param iv_update True if there is an ongoing IV Update procedure.
|
||||
*/
|
||||
void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
|
||||
|
||||
/** @brief Allocate a node.
|
||||
*
|
||||
* Allocate a new node in the CDB.
|
||||
*
|
||||
* @param uuid UUID of the node.
|
||||
* @param addr Address of the node's primary element. If 0, the lowest
|
||||
* possible address available will be assigned to the node.
|
||||
* @param num_elem Number of elements that the node has.
|
||||
* @param net_idx NetIdx that the node was provisioned to.
|
||||
*
|
||||
* @return The new node or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
|
||||
uint8_t num_elem, uint16_t net_idx);
|
||||
|
||||
/** @brief Delete a node.
|
||||
*
|
||||
* Delete a node from the CDB.
|
||||
*
|
||||
* @param node The node to be deleted.
|
||||
* @param store If true, the node will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
|
||||
|
||||
/** @brief Get a node by address.
|
||||
*
|
||||
* Try to find the node that has the provided address assigned to one of its
|
||||
* elements.
|
||||
*
|
||||
* @param addr Address of the element to look for.
|
||||
*
|
||||
* @return The node that has an element with address addr or NULL if no such
|
||||
* node exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
|
||||
|
||||
/** @brief Store node to persistent storage.
|
||||
*
|
||||
* @param node Node to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
|
||||
|
||||
enum {
|
||||
BT_MESH_CDB_ITER_STOP = 0,
|
||||
BT_MESH_CDB_ITER_CONTINUE,
|
||||
};
|
||||
|
||||
/** @typedef bt_mesh_cdb_node_func_t
|
||||
* @brief Node iterator callback.
|
||||
*
|
||||
* @param node Node found.
|
||||
* @param user_data Data given.
|
||||
*
|
||||
* @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
|
||||
* or BT_MESH_CDB_ITER_STOP to stop.
|
||||
*/
|
||||
typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
|
||||
void *user_data);
|
||||
|
||||
/** @brief Node iterator.
|
||||
*
|
||||
* Iterate nodes in the Mesh Configuration Database. The callback function
|
||||
* will only be called for valid, ie allocated, nodes.
|
||||
*
|
||||
* @param func Callback function.
|
||||
* @param user_data Data to pass to the callback.
|
||||
*/
|
||||
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
|
||||
|
||||
/** @brief Allocate a subnet.
|
||||
*
|
||||
* Allocate a new subnet in the CDB.
|
||||
*
|
||||
* @param net_idx NetIdx of the subnet.
|
||||
*
|
||||
* @return The new subnet or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
|
||||
|
||||
/** @brief Delete a subnet.
|
||||
*
|
||||
* Delete a subnet from the CDB.
|
||||
*
|
||||
* @param sub The subnet to be deleted.
|
||||
* @param store If true, the subnet will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
|
||||
|
||||
/** @brief Get a subnet by NetIdx
|
||||
*
|
||||
* Try to find the subnet with the specified NetIdx.
|
||||
*
|
||||
* @param net_idx NetIdx of the subnet to look for.
|
||||
*
|
||||
* @return The subnet with the specified NetIdx or NULL if no such subnet
|
||||
* exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
|
||||
|
||||
/** @brief Store subnet to persistent storage.
|
||||
*
|
||||
* @param sub Subnet to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
|
||||
|
||||
/** @brief Get the flags for a subnet
|
||||
*
|
||||
* @param sub The subnet to get flags for.
|
||||
*
|
||||
* @return The flags for the subnet.
|
||||
*/
|
||||
uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
|
||||
|
||||
|
||||
/** @brief Allocate an application key.
|
||||
*
|
||||
* Allocate a new application key in the CDB.
|
||||
*
|
||||
* @param net_idx NetIdx of NetKey that the application key is bound to.
|
||||
* @param app_idx AppIdx of the application key.
|
||||
*
|
||||
* @return The new application key or NULL if it cannot be allocated.
|
||||
*/
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
|
||||
uint16_t app_idx);
|
||||
|
||||
/** @brief Delete an application key.
|
||||
*
|
||||
* Delete an application key from the CDB.
|
||||
*
|
||||
* @param key The application key to be deleted.
|
||||
* @param store If true, the key will be cleared from persistent storage.
|
||||
*/
|
||||
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
|
||||
|
||||
/** @brief Get an application key by AppIdx
|
||||
*
|
||||
* Try to find the application key with the specified AppIdx.
|
||||
*
|
||||
* @param app_idx AppIdx of the application key to look for.
|
||||
*
|
||||
* @return The application key with the specified AppIdx or NULL if no such key
|
||||
* exists.
|
||||
*/
|
||||
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
|
||||
|
||||
/** @brief Store application key to persistent storage.
|
||||
*
|
||||
* @param key Application key to be stored.
|
||||
*/
|
||||
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */
|
@ -0,0 +1,485 @@
|
||||
/** @file
|
||||
* @brief Bluetooth Mesh Runtime Configuration APIs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BT_MESH_CFG_H_
|
||||
#define _BT_MESH_CFG_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Runtime Configuration API
|
||||
* @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
|
||||
* @ingroup bt_mesh
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Bluetooth Mesh Feature states */
|
||||
enum bt_mesh_feat_state {
|
||||
/** Feature is supported, but disabled. */
|
||||
BT_MESH_FEATURE_DISABLED,
|
||||
/** Feature is supported and enabled. */
|
||||
BT_MESH_FEATURE_ENABLED,
|
||||
/** Feature is not supported, and cannot be enabled. */
|
||||
BT_MESH_FEATURE_NOT_SUPPORTED,
|
||||
};
|
||||
|
||||
/* Legacy feature defines */
|
||||
#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_RELAY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_BEACON_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_BEACON_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
|
||||
#define BT_MESH_GATT_PROXY_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_GATT_PROXY_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_GATT_PROXY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_FRIEND_DISABLED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_FRIEND_ENABLED BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_FRIEND_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
#define BT_MESH_NODE_IDENTITY_STOPPED BT_MESH_FEATURE_DISABLED
|
||||
#define BT_MESH_NODE_IDENTITY_RUNNING BT_MESH_FEATURE_ENABLED
|
||||
#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
|
||||
|
||||
/** @brief Enable or disable sending of the Secure Network Beacon.
|
||||
*
|
||||
* @param beacon New Secure Network Beacon state.
|
||||
*/
|
||||
void bt_mesh_beacon_set(bool beacon);
|
||||
|
||||
/** @brief Get the current Secure Network Beacon state.
|
||||
*
|
||||
* @returns Whether the Secure Network Beacon feature is enabled.
|
||||
*/
|
||||
bool bt_mesh_beacon_enabled(void);
|
||||
|
||||
/** @brief Set the default TTL value.
|
||||
*
|
||||
* The default TTL value is used when no explicit TTL value is set. Models will
|
||||
* use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
|
||||
* @ref BT_MESH_TTL_DEFAULT.
|
||||
*
|
||||
* @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
|
||||
* to @ref BT_MESH_TTL_MAX.
|
||||
*
|
||||
* @retval 0 Successfully set the default TTL value.
|
||||
* @retval -EINVAL Invalid TTL value.
|
||||
*/
|
||||
int bt_mesh_default_ttl_set(uint8_t default_ttl);
|
||||
|
||||
/** @brief Get the current default TTL value.
|
||||
*
|
||||
* @return The current default TTL value.
|
||||
*/
|
||||
uint8_t bt_mesh_default_ttl_get(void);
|
||||
|
||||
/** @brief Set the Network Transmit parameters.
|
||||
*
|
||||
* The Network Transmit parameters determine the parameters local messages are
|
||||
* transmitted with.
|
||||
*
|
||||
* @see BT_MESH_TRANSMIT
|
||||
*
|
||||
* @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
|
||||
* encoding.
|
||||
*/
|
||||
void bt_mesh_net_transmit_set(uint8_t xmit);
|
||||
|
||||
/** @brief Get the current Network Transmit parameters.
|
||||
*
|
||||
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
|
||||
* used to decode the Network Transmit parameters.
|
||||
*
|
||||
* @return The current Network Transmit parameters.
|
||||
*/
|
||||
uint8_t bt_mesh_net_transmit_get(void);
|
||||
|
||||
/** @brief Configure the Relay feature.
|
||||
*
|
||||
* Enable or disable the Relay feature, and configure the parameters to
|
||||
* transmit relayed messages with.
|
||||
*
|
||||
* Support for the Relay feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_RELAY configuration option.
|
||||
*
|
||||
* @see BT_MESH_TRANSMIT
|
||||
*
|
||||
* @param relay New Relay feature state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
* @param xmit New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
|
||||
* encoding.
|
||||
*
|
||||
* @retval 0 Successfully changed the Relay configuration.
|
||||
* @retval -ENOTSUP The Relay feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already using the given parameters.
|
||||
*/
|
||||
int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
|
||||
|
||||
/** @brief Get the current Relay feature state.
|
||||
*
|
||||
* @returns The Relay feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_relay_get(void);
|
||||
|
||||
/** @brief Get the current Relay Retransmit parameters.
|
||||
*
|
||||
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
|
||||
* used to decode the Relay Retransmit parameters.
|
||||
*
|
||||
* @return The current Relay Retransmit parameters, or 0 if relay is not
|
||||
* supported.
|
||||
*/
|
||||
uint8_t bt_mesh_relay_retransmit_get(void);
|
||||
|
||||
/** @brief Enable or disable the GATT Proxy feature.
|
||||
*
|
||||
* Support for the GATT Proxy feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_GATT_PROXY configuration option.
|
||||
*
|
||||
* @note The GATT Proxy feature only controls a Proxy node's ability to relay
|
||||
* messages to the mesh network. A node that supports GATT Proxy will
|
||||
* still advertise Connectable Proxy beacons, even if the feature is
|
||||
* disabled. The Proxy feature can only be fully disabled through compile
|
||||
* time configuration.
|
||||
*
|
||||
* @param gatt_proxy New GATT Proxy state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval 0 Successfully changed the GATT Proxy feature state.
|
||||
* @retval -ENOTSUP The GATT Proxy feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already in the given state.
|
||||
*/
|
||||
int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
|
||||
|
||||
/** @brief Get the current GATT Proxy state.
|
||||
*
|
||||
* @returns The GATT Proxy feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
|
||||
|
||||
/** @brief Enable or disable the Friend feature.
|
||||
*
|
||||
* Any active friendships will be terminated immediately if the Friend feature
|
||||
* is disabled.
|
||||
*
|
||||
* Support for the Friend feature must be enabled through the
|
||||
* @c CONFIG_BT_MESH_FRIEND configuration option.
|
||||
*
|
||||
* @param friendship New Friend feature state. Must be one of
|
||||
* @ref BT_MESH_FEATURE_ENABLED and
|
||||
* @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval 0 Successfully changed the Friend feature state.
|
||||
* @retval -ENOTSUP The Friend feature is not supported.
|
||||
* @retval -EINVAL Invalid parameter.
|
||||
* @retval -EALREADY Already in the given state.
|
||||
*/
|
||||
int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
|
||||
|
||||
/** @brief Get the current Friend state.
|
||||
*
|
||||
* @returns The Friend feature state.
|
||||
*/
|
||||
enum bt_mesh_feat_state bt_mesh_friend_get(void);
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Subnet Configuration
|
||||
* @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Add a Subnet.
|
||||
*
|
||||
* Adds a subnet with the given network index and network key to the list of
|
||||
* known Subnets. All messages sent on the given Subnet will be processed by
|
||||
* this node, and the node may send and receive Network Beacons on the given
|
||||
* Subnet.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param key Root network key of the Subnet. All other keys are derived
|
||||
* from this.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was successfully added.
|
||||
* @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
|
||||
* @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
|
||||
|
||||
/** @brief Update the given Subnet.
|
||||
*
|
||||
* Starts the Key Refresh procedure for this Subnet by adding a second set of
|
||||
* encryption keys. The Subnet will continue sending with the old key (but
|
||||
* receiving messages using both) until the Subnet enters Key Refresh phase 2.
|
||||
*
|
||||
* This allows a network configurator to replace old network and application
|
||||
* keys for the entire network, effectively removing access for all nodes that
|
||||
* aren't given the new keys.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param key New root network key of the Subnet.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was updated with a second key.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
|
||||
* current key.
|
||||
* @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
|
||||
|
||||
/** @brief Delete a Subnet.
|
||||
*
|
||||
* Removes the Subnet with the given network index from the node. The node will
|
||||
* stop sending Network Beacons with the given Subnet, and can no longer
|
||||
* process messages on this Subnet.
|
||||
*
|
||||
* All Applications bound to this Subnet are also deleted.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Subnet was deleted.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_del(uint16_t net_idx);
|
||||
|
||||
/** @brief Check whether a Subnet is known.
|
||||
*
|
||||
* @param net_idx Network index
|
||||
*
|
||||
* @return true if a Subnet with the given index exists, false otherwise.
|
||||
*/
|
||||
bool bt_mesh_subnet_exists(uint16_t net_idx);
|
||||
|
||||
/** @brief Set the Subnet's Key Refresh phase.
|
||||
*
|
||||
* The Key Refresh procedure is started by updating the Subnet keys through
|
||||
* @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
|
||||
* Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
|
||||
* activated through this function to start transmitting with the new network
|
||||
* key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
|
||||
* removes the old keys from the node, and returns the Subnet back to normal
|
||||
* single-key operation with the new key set.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param phase Pointer to the new Key Refresh phase. Will return the actual
|
||||
* Key Refresh phase after updating.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
|
||||
* changed.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
|
||||
|
||||
/** @brief Get the Subnet's Key Refresh phase.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param phase Pointer to the Key Refresh variable to fill.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully populated the @c phase variable.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
|
||||
|
||||
/** @brief Set the Node Identity state of the Subnet.
|
||||
*
|
||||
* The Node Identity state of a Subnet determines whether the Subnet advertises
|
||||
* connectable Node Identity beacons for Proxy Clients to connect to.
|
||||
* Once started, the Node Identity beacon runs for 60 seconds, or until it is
|
||||
* stopped.
|
||||
*
|
||||
* This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
|
||||
* but only acts on a single Subnet.
|
||||
*
|
||||
* GATT Proxy support must be enabled through
|
||||
* @option{CONFIG_BT_MESH_GATT_PROXY}.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param node_id New Node Identity state, must be either @ref
|
||||
* BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully set the Node Identity state of the
|
||||
* Subnet.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
|
||||
* @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
|
||||
enum bt_mesh_feat_state node_id);
|
||||
|
||||
/** @brief Get the Node Identity state of the Subnet.
|
||||
*
|
||||
* @param net_idx Network index.
|
||||
* @param node_id Node Identity variable to fill.
|
||||
*
|
||||
* @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
*/
|
||||
uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
|
||||
enum bt_mesh_feat_state *node_id);
|
||||
|
||||
/** @brief Get a list of all known Subnet indexes.
|
||||
*
|
||||
* Builds a list of all known Subnet indexes in the @c net_idxs array.
|
||||
* If the @c net_idxs array is smaller than the list of known Subnets, this
|
||||
* function fills all available entries and returns @c -ENOMEM. In this
|
||||
* case, the next @c max entries of the list can be read out by calling
|
||||
* @code
|
||||
* bt_mesh_subnets_get(list, max, max);
|
||||
* @endcode
|
||||
*
|
||||
* Note that any changes to the Subnet list between calls to this function
|
||||
* could change the order and number of entries in the list.
|
||||
*
|
||||
* @param net_idxs Array to fill.
|
||||
* @param max Max number of indexes to return.
|
||||
* @param skip Number of indexes to skip. Enables batched processing of the
|
||||
* list.
|
||||
*
|
||||
* @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
|
||||
* if the number of known Subnets exceeds the @c max parameter.
|
||||
*/
|
||||
ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh Application Configuration
|
||||
* @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Add an Application key.
|
||||
*
|
||||
* Adds the Application with the given index to the list of known applications.
|
||||
* Allows the node to send and receive model messages encrypted with this
|
||||
* Application key.
|
||||
*
|
||||
* Every Application is bound to a specific Subnet. The node must know the
|
||||
* Subnet the Application is bound to before it can add the Application.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index the Application is bound to.
|
||||
* @param key Application key value.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application was successfully added.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INSUFF_RESOURCES There's no room for storing this
|
||||
* Application.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
|
||||
* Subnet.
|
||||
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
|
||||
* different key value.
|
||||
* @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16]);
|
||||
|
||||
/** @brief Update an Application key.
|
||||
*
|
||||
* Update an Application with a second Application key, as part of the
|
||||
* Key Refresh procedure of the bound Subnet. The node will continue
|
||||
* transmitting with the old application key (but receiving on both) until the
|
||||
* Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
|
||||
* 3, the old application key will be deleted.
|
||||
*
|
||||
* @note The Application key can only be updated if the bound Subnet is in Key
|
||||
* Refresh phase 1.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index the Application is bound to, or
|
||||
* @ref BT_MESH_KEY_ANY to skip the binding check.
|
||||
* @param key New key value.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application key was successfully updated.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
|
||||
* @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
|
||||
* reason.
|
||||
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
|
||||
* different key value.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16]);
|
||||
|
||||
/** @brief Delete an Application key.
|
||||
*
|
||||
* All models bound to this application will remove this binding.
|
||||
* All models publishing with this application will stop publishing.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
* @param net_idx Network index.
|
||||
*
|
||||
* @retval STATUS_SUCCESS The Application key was successfully deleted.
|
||||
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
|
||||
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
|
||||
*/
|
||||
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
|
||||
|
||||
/** @brief Check if an Application key is known.
|
||||
*
|
||||
* @param app_idx Application index.
|
||||
*
|
||||
* @return true if the Application is known, false otherwise.
|
||||
*/
|
||||
bool bt_mesh_app_key_exists(uint16_t app_idx);
|
||||
|
||||
/** @brief Get a list of all known Application key indexes.
|
||||
*
|
||||
* Builds a list of all Application indexes for the given network index in the
|
||||
* @c app_idxs array. If the @c app_idxs array cannot fit all bound
|
||||
* Applications, this function fills all available entries and returns @c
|
||||
* -ENOMEM. In this case, the next @c max entries of the list can be read out
|
||||
* by calling
|
||||
* @code
|
||||
* bt_mesh_app_keys_get(net_idx, list, max, max);
|
||||
* @endcode
|
||||
*
|
||||
* Note that any changes to the Application key list between calls to this
|
||||
* function could change the order and number of entries in the list.
|
||||
*
|
||||
* @param net_idx Network Index to get the Applications of, or @ref
|
||||
* BT_MESH_KEY_ANY to get all Applications.
|
||||
* @param app_idxs Array to fill.
|
||||
* @param max Max number of indexes to return.
|
||||
* @param skip Number of indexes to skip. Enables batched processing of the
|
||||
* list.
|
||||
*
|
||||
* @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
|
||||
* if the number of known Applications exceeds the @c max parameter.
|
||||
*/
|
||||
ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
|
||||
off_t skip);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _BT_MESH_CFG_H_ */
|
@ -26,7 +26,7 @@ struct bt_mesh_cfg_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@ -37,45 +37,81 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
|
||||
cli_data, &bt_mesh_cfg_cli_cb)
|
||||
|
||||
int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
|
||||
u8_t *status, struct os_mbuf *comp);
|
||||
int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status);
|
||||
|
||||
int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
|
||||
uint8_t *status, struct os_mbuf *comp);
|
||||
|
||||
int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
|
||||
int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl);
|
||||
int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl);
|
||||
int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
|
||||
|
||||
int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
|
||||
|
||||
int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
|
||||
int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status);
|
||||
int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
|
||||
u8_t *transmit);
|
||||
int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
|
||||
u8_t new_transmit, u8_t *status, u8_t *transmit);
|
||||
int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
|
||||
uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
||||
const u8_t net_key[16], u8_t *status);
|
||||
int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
|
||||
uint8_t val, uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
|
||||
u16_t key_app_idx, const u8_t app_key[16],
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
|
||||
uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_app_idx, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
|
||||
uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
const uint8_t net_key[16], uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
|
||||
size_t *key_cnt);
|
||||
|
||||
int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t key_net_idx, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
uint16_t key_app_idx, const uint8_t app_key[16],
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
|
||||
uint8_t *status, uint16_t *keys, size_t *key_cnt);
|
||||
|
||||
int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t mod_app_idx,
|
||||
uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
|
||||
uint16_t cid, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint8_t *status, uint16_t *apps,
|
||||
size_t *app_cnt);
|
||||
|
||||
int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status,
|
||||
uint16_t *apps, size_t *app_cnt);
|
||||
|
||||
/** @def BT_MESH_PUB_PERIOD_100MS
|
||||
*
|
||||
@ -120,109 +156,117 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
|
||||
|
||||
struct bt_mesh_cfg_mod_pub {
|
||||
u16_t addr;
|
||||
u16_t app_idx;
|
||||
uint16_t addr;
|
||||
uint16_t app_idx;
|
||||
bool cred_flag;
|
||||
u8_t ttl;
|
||||
u8_t period;
|
||||
u8_t transmit;
|
||||
uint8_t ttl;
|
||||
uint8_t period;
|
||||
uint8_t transmit;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t mod_id, u16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u16_t cid,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
u16_t sub_addr, u16_t mod_id, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, u16_t sub_addr,
|
||||
u16_t mod_id, u16_t cid, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, uint16_t sub_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t cid, u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
|
||||
const u8_t label[16], u16_t mod_id,
|
||||
u16_t cid, u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
const uint8_t label[16], uint16_t mod_id,
|
||||
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, const u8_t label[16],
|
||||
u16_t mod_id, u16_t *virt_addr,
|
||||
u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, const uint8_t label[16],
|
||||
uint16_t mod_id, uint16_t *virt_addr,
|
||||
uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
|
||||
u16_t elem_addr, const u8_t label[16],
|
||||
u16_t mod_id, u16_t cid,
|
||||
u16_t *virt_addr, u8_t *status);
|
||||
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
|
||||
uint16_t elem_addr, const uint8_t label[16],
|
||||
uint16_t mod_id, uint16_t cid,
|
||||
uint16_t *virt_addr, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint8_t *status, uint16_t *subs,
|
||||
size_t *sub_cnt);
|
||||
|
||||
int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
|
||||
uint16_t mod_id, uint16_t cid, uint8_t *status,
|
||||
uint16_t *subs, size_t *sub_cnt);
|
||||
|
||||
struct bt_mesh_cfg_hb_sub {
|
||||
u16_t src;
|
||||
u16_t dst;
|
||||
u8_t period;
|
||||
u8_t count;
|
||||
u8_t min;
|
||||
u8_t max;
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
uint8_t period;
|
||||
uint8_t count;
|
||||
uint8_t min;
|
||||
uint8_t max;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
|
||||
|
||||
struct bt_mesh_cfg_hb_pub {
|
||||
u16_t dst;
|
||||
u8_t count;
|
||||
u8_t period;
|
||||
u8_t ttl;
|
||||
u16_t feat;
|
||||
u16_t net_idx;
|
||||
uint16_t dst;
|
||||
uint8_t count;
|
||||
uint8_t period;
|
||||
uint8_t ttl;
|
||||
uint16_t feat;
|
||||
uint16_t net_idx;
|
||||
};
|
||||
|
||||
int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
|
||||
const struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
|
||||
const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
|
||||
|
||||
int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
|
||||
struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
|
||||
int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
|
||||
struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
|
||||
|
||||
s32_t bt_mesh_cfg_cli_timeout_get(void);
|
||||
void bt_mesh_cfg_cli_timeout_set(s32_t timeout);
|
||||
int32_t bt_mesh_cfg_cli_timeout_get(void);
|
||||
void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -21,51 +21,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Mesh Configuration Server Model Context */
|
||||
struct bt_mesh_cfg_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
u8_t net_transmit; /* Network Transmit state */
|
||||
u8_t relay; /* Relay Mode state */
|
||||
u8_t relay_retransmit; /* Relay Retransmit state */
|
||||
u8_t beacon; /* Secure Network Beacon state */
|
||||
u8_t gatt_proxy; /* GATT Proxy state */
|
||||
u8_t frnd; /* Friend state */
|
||||
u8_t default_ttl; /* Default TTL */
|
||||
|
||||
/* Heartbeat Publication */
|
||||
struct bt_mesh_hb_pub {
|
||||
struct k_delayed_work timer;
|
||||
|
||||
u16_t dst;
|
||||
u16_t count;
|
||||
u8_t period;
|
||||
u8_t ttl;
|
||||
u16_t feat;
|
||||
u16_t net_idx;
|
||||
} hb_pub;
|
||||
|
||||
/* Heartbeat Subscription */
|
||||
struct bt_mesh_hb_sub {
|
||||
s64_t expiry;
|
||||
|
||||
u16_t src;
|
||||
u16_t dst;
|
||||
u16_t count;
|
||||
u8_t min_hops;
|
||||
u8_t max_hops;
|
||||
|
||||
/* Optional subscription tracking function */
|
||||
void (*func)(u8_t hops, u16_t feat);
|
||||
} hb_sub;
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
|
||||
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
|
||||
|
||||
#define BT_MESH_MODEL_CFG_SRV(srv_data) \
|
||||
#define BT_MESH_MODEL_CFG_SRV \
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
|
||||
srv_data, &bt_mesh_cfg_srv_cb)
|
||||
NULL, &bt_mesh_cfg_srv_cb)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -62,15 +62,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define u8_t uint8_t
|
||||
#define s8_t int8_t
|
||||
#define u16_t uint16_t
|
||||
#define s16_t int16_t
|
||||
#define u32_t uint32_t
|
||||
#define u64_t uint64_t
|
||||
#define s64_t int64_t
|
||||
#define s32_t int32_t
|
||||
|
||||
/** @brief Helper to declare elements of bt_data arrays
|
||||
*
|
||||
* This macro is mainly for creating an array of struct bt_data
|
||||
@ -84,7 +75,7 @@ extern "C" {
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.data_len = (_data_len), \
|
||||
.data = (const u8_t *)(_data), \
|
||||
.data = (const uint8_t *)(_data), \
|
||||
}
|
||||
|
||||
/** @brief Helper to declare elements of bt_data arrays
|
||||
@ -96,8 +87,8 @@ extern "C" {
|
||||
* @param _bytes Variable number of single-byte parameters
|
||||
*/
|
||||
#define BT_DATA_BYTES(_type, _bytes...) \
|
||||
BT_DATA(_type, ((u8_t []) { _bytes }), \
|
||||
sizeof((u8_t []) { _bytes }))
|
||||
BT_DATA(_type, ((uint8_t []) { _bytes }), \
|
||||
sizeof((uint8_t []) { _bytes }))
|
||||
|
||||
/* EIR/AD data type definitions */
|
||||
#define BT_DATA_FLAGS 0x01 /* AD flags */
|
||||
@ -130,9 +121,13 @@ extern "C" {
|
||||
|
||||
#define sys_put_be16(a,b) put_be16(b, a)
|
||||
#define sys_put_le16(a,b) put_le16(b, a)
|
||||
#define sys_put_le24(a,b) put_le24(b, a)
|
||||
#define sys_put_be24(a,b) put_be24(b, a)
|
||||
#define sys_put_be32(a,b) put_be32(b, a)
|
||||
#define sys_get_be16(a) get_be16(a)
|
||||
#define sys_get_be24(a) get_be24(a)
|
||||
#define sys_get_le16(a) get_le16(a)
|
||||
#define sys_get_le24(a) get_le24(a)
|
||||
#define sys_get_be32(a) get_be32(a)
|
||||
#define sys_cpu_to_be16(a) htobe16(a)
|
||||
#define sys_cpu_to_be32(a) htobe32(a)
|
||||
@ -207,9 +202,9 @@ typedef ble_addr_t bt_addr_le_t;
|
||||
|
||||
struct net_buf_simple_state {
|
||||
/** Offset of the data pointer from the beginning of the storage */
|
||||
u16_t offset;
|
||||
uint16_t offset;
|
||||
/** Length of data */
|
||||
u16_t len;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
|
||||
@ -249,6 +244,14 @@ static inline void net_buf_simple_init(struct os_mbuf *buf,
|
||||
buf->om_len = 0;
|
||||
}
|
||||
|
||||
#define net_buf_simple_init_with_data(buf, data, size) \
|
||||
os_mbuf_copyinto(buf, 0, data, size);
|
||||
|
||||
static inline void net_buf_simple_reset(struct os_mbuf *om)
|
||||
{
|
||||
net_buf_simple_init(om, 0);
|
||||
}
|
||||
|
||||
void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf);
|
||||
void * net_buf_ref(struct os_mbuf *om);
|
||||
void net_buf_unref(struct os_mbuf *om);
|
||||
@ -259,18 +262,20 @@ uint32_t net_buf_simple_pull_le32(struct os_mbuf *om);
|
||||
uint8_t net_buf_simple_pull_u8(struct os_mbuf *om);
|
||||
void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val);
|
||||
void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_add_zeros(struct os_mbuf *om, uint8_t len);
|
||||
void net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val);
|
||||
void net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val);
|
||||
void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val);
|
||||
void *net_buf_simple_pull(struct os_mbuf *om, uint8_t len);
|
||||
void *net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len);
|
||||
void *net_buf_simple_add(struct os_mbuf *om, uint8_t len);
|
||||
bool k_fifo_is_empty(struct ble_npl_eventq *q);
|
||||
void *net_buf_get(struct ble_npl_eventq *fifo,s32_t t);
|
||||
void *net_buf_get(struct ble_npl_eventq *fifo,int32_t t);
|
||||
uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len);
|
||||
void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
|
||||
@ -282,7 +287,7 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
#define net_buf_clone(a, b) os_mbuf_dup(a)
|
||||
#define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b)
|
||||
#define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b)
|
||||
#define net_buf_pull(a, b) net_buf_simple_pull(a, b)
|
||||
#define net_buf_pull(a, b) net_buf_simple_pull_mem(a, b)
|
||||
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
|
||||
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
|
||||
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
|
||||
@ -290,14 +295,22 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
|
||||
|
||||
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/** Description of different data types that can be encoded into
|
||||
* advertising data. Used to form arrays that are passed to the
|
||||
* bt_le_adv_start() function.
|
||||
*/
|
||||
struct bt_data {
|
||||
u8_t type;
|
||||
u8_t data_len;
|
||||
const u8_t *data;
|
||||
uint8_t type;
|
||||
uint8_t data_len;
|
||||
const uint8_t *data;
|
||||
};
|
||||
|
||||
struct bt_pub_key_cb {
|
||||
@ -309,18 +322,24 @@ struct bt_pub_key_cb {
|
||||
*
|
||||
* @param key The local public key, or NULL in case of no key.
|
||||
*/
|
||||
void (*func)(const u8_t key[64]);
|
||||
void (*func)(const uint8_t key[64]);
|
||||
|
||||
struct bt_pub_key_cb *_next;
|
||||
};
|
||||
|
||||
typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
|
||||
int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
|
||||
typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]);
|
||||
int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb);
|
||||
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb);
|
||||
uint8_t *bt_pub_key_get(void);
|
||||
int bt_rand(void *buf, size_t len);
|
||||
const char * bt_hex(const void *buf, size_t len);
|
||||
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
|
||||
int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
|
||||
size_t len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *plaintext, size_t mic_size);
|
||||
void bt_mesh_register_gatt(void);
|
||||
int bt_le_adv_start(const struct ble_gap_adv_params *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
@ -334,9 +353,10 @@ struct k_delayed_work {
|
||||
void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler);
|
||||
void k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f);
|
||||
void k_delayed_work_cancel(struct k_delayed_work *w);
|
||||
bool k_delayed_work_pending(struct k_delayed_work *w);
|
||||
void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms);
|
||||
int64_t k_uptime_get(void);
|
||||
u32_t k_uptime_get_32(void);
|
||||
uint32_t k_uptime_get_32(void);
|
||||
void k_sleep(int32_t duration);
|
||||
void k_work_submit(struct ble_npl_callout *w);
|
||||
void k_work_add_arg(struct ble_npl_callout *w, void *arg);
|
||||
@ -366,18 +386,18 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||
src += length - 1;
|
||||
|
||||
for (; length > 0; length--) {
|
||||
*((u8_t *)dst++) = *((u8_t *)src--);
|
||||
*((uint8_t *)dst++) = *((uint8_t *)src--);
|
||||
}
|
||||
}
|
||||
|
||||
#define popcount(x) __builtin_popcount(x)
|
||||
|
||||
static inline unsigned int find_lsb_set(u32_t op)
|
||||
static inline unsigned int find_lsb_set(uint32_t op)
|
||||
{
|
||||
return __builtin_ffs(op);
|
||||
}
|
||||
|
||||
static inline unsigned int find_msb_set(u32_t op)
|
||||
static inline unsigned int find_msb_set(uint32_t op)
|
||||
{
|
||||
if (!op)
|
||||
return 0;
|
||||
@ -385,43 +405,61 @@ static inline unsigned int find_msb_set(u32_t op)
|
||||
return 32 - __builtin_clz(op);
|
||||
}
|
||||
|
||||
#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
|
||||
#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
|
||||
#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
|
||||
#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
|
||||
#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
|
||||
#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
|
||||
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
|
||||
#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
|
||||
#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
|
||||
#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
|
||||
#define CONFIG_BT_TESTING BLE_MESH_TESTING
|
||||
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
|
||||
#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
|
||||
#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
|
||||
#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
|
||||
#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
|
||||
#define CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR BLE_MESH_LPN_SUB_ALL_NODES_ADDR
|
||||
#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
|
||||
#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
|
||||
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
|
||||
#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
|
||||
#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
|
||||
#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
|
||||
#define CONFIG_BT_TESTING BLE_MESH_TESTING
|
||||
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
|
||||
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
|
||||
#define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE
|
||||
#define CONFIG_BT_MESH_CDB BLE_MESH_CDB
|
||||
|
||||
/* Above flags are used with IS_ENABLED macro */
|
||||
#define IS_ENABLED(config) MYNEWT_VAL(config)
|
||||
|
||||
#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
|
||||
#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
|
||||
#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
|
||||
#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
|
||||
#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
|
||||
#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
|
||||
#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
|
||||
#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
|
||||
#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
|
||||
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
|
||||
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
|
||||
#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
|
||||
#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
|
||||
#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS )
|
||||
#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
|
||||
#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
|
||||
#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
|
||||
#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
|
||||
#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
|
||||
#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
|
||||
#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
|
||||
#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
|
||||
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
|
||||
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
|
||||
#define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
|
||||
#define CONFIG_BT_MESH_RX_SEG_MSG_COUNT MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)
|
||||
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
|
||||
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)
|
||||
#define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
|
||||
#define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL)
|
||||
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_COUNT)
|
||||
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_INTERVAL)
|
||||
#define CONFIG_BT_MESH_RELAY_ENABLED MYNEWT_VAL(BLE_MESH_RELAY_ENABLED)
|
||||
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_INTERVAL)
|
||||
#define CONFIG_BT_MESH_BEACON_ENABLED MYNEWT_VAL(BLE_MESH_BEACON_ENABLED)
|
||||
#define CONFIG_BT_MESH_FRIEND_ENABLED MYNEWT_VAL(BLE_MESH_FRIEND_ENABLED)
|
||||
#define CONFIG_BT_MESH_RELAY MYNEWT_VAL(BLE_MESH_RELAY)
|
||||
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_COUNT)
|
||||
#define CONFIG_BT_MESH_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
|
||||
|
||||
#define printk console_printf
|
||||
|
||||
@ -437,7 +475,7 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
|
||||
ble_npl_sem_init(sem, initial_count);
|
||||
}
|
||||
|
||||
static inline int k_sem_take(struct k_sem *sem, s32_t timeout)
|
||||
static inline int k_sem_take(struct k_sem *sem, int32_t timeout)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
@ -459,8 +497,8 @@ static inline void k_sem_give(struct k_sem *sem)
|
||||
static inline int net_buf_id(struct os_mbuf *buf)
|
||||
{
|
||||
struct os_mbuf_pool *pool = buf->om_omp;
|
||||
u8_t *pool_start = (u8_t *)pool->omp_pool->mp_membuf_addr;
|
||||
u8_t *buf_ptr = (u8_t *)buf;
|
||||
uint8_t *pool_start = (uint8_t *)pool->omp_pool->mp_membuf_addr;
|
||||
uint8_t *buf_ptr = (uint8_t *)buf;
|
||||
|
||||
return (buf_ptr - pool_start) / BUF_SIZE(pool);
|
||||
}
|
||||
@ -506,6 +544,46 @@ settings_load(void)
|
||||
|
||||
#define BUILD_ASSERT(cond) _Static_assert(cond, "")
|
||||
|
||||
|
||||
/* Memory slabs/blocks */
|
||||
|
||||
/** Memory slab structure */
|
||||
struct k_mem_slab {
|
||||
/**
|
||||
* _wait_q_t is not required now, as we don't implement zephyr timeouts -
|
||||
* if slab couldn't be allocated, we simply return error
|
||||
*/
|
||||
uint32_t num_blocks; /** number of memory blocks available for allocation */
|
||||
size_t block_size; /** size of single block */
|
||||
/**
|
||||
* buffer for blocks - must be alligned to N-byte, where N is a power of 2.
|
||||
* Minimal size of buffer is num_blocks * block_size
|
||||
*/
|
||||
char *buffer;
|
||||
char *free_list; /** list of free memory blocks */
|
||||
uint32_t num_used; /** count of used memory blocks */
|
||||
};
|
||||
|
||||
struct k_mem_block_id {
|
||||
uint32_t pool : 8;
|
||||
uint32_t level : 4;
|
||||
uint32_t block : 20;
|
||||
};
|
||||
|
||||
struct k_mem_block {
|
||||
void *data;
|
||||
struct k_mem_block_id id;
|
||||
};
|
||||
|
||||
extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
|
||||
extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem);
|
||||
static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
|
||||
{
|
||||
return slab->num_blocks - slab->num_used;
|
||||
}
|
||||
|
||||
int create_free_list(struct k_mem_slab *slab);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -25,12 +25,12 @@ extern "C" {
|
||||
struct bt_mesh_health_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
void (*current_status)(struct bt_mesh_health_cli *cli, u16_t addr,
|
||||
u8_t test_id, u16_t cid, u8_t *faults,
|
||||
void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
|
||||
uint8_t test_id, uint16_t cid, uint8_t *faults,
|
||||
size_t fault_count);
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@ -43,32 +43,30 @@ extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
|
||||
|
||||
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
|
||||
|
||||
int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t *test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u16_t cid, u8_t test_id, u8_t *faults,
|
||||
size_t *fault_count);
|
||||
int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
|
||||
uint8_t test_id, uint8_t *faults,
|
||||
size_t *fault_count);
|
||||
|
||||
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *divisor);
|
||||
int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
|
||||
|
||||
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t divisor, u8_t *updated_divisor);
|
||||
int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
|
||||
uint8_t *updated_divisor);
|
||||
|
||||
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *attention);
|
||||
int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
|
||||
|
||||
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t attention, u8_t *updated_attention);
|
||||
int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
|
||||
uint8_t *updated_attention);
|
||||
|
||||
s32_t bt_mesh_health_cli_timeout_get(void);
|
||||
void bt_mesh_health_cli_timeout_set(s32_t timeout);
|
||||
int32_t bt_mesh_health_cli_timeout_get(void);
|
||||
void bt_mesh_health_cli_timeout_set(int32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -23,21 +23,21 @@ extern "C" {
|
||||
|
||||
struct bt_mesh_health_srv_cb {
|
||||
/* Fetch current faults */
|
||||
int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id,
|
||||
u16_t *company_id, u8_t *faults,
|
||||
u8_t *fault_count);
|
||||
int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id,
|
||||
uint16_t *company_id, uint8_t *faults,
|
||||
uint8_t *fault_count);
|
||||
|
||||
/* Fetch registered faults */
|
||||
int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id,
|
||||
u8_t *test_id, u8_t *faults,
|
||||
u8_t *fault_count);
|
||||
int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id,
|
||||
uint8_t *test_id, uint8_t *faults,
|
||||
uint8_t *fault_count);
|
||||
|
||||
/* Clear registered faults */
|
||||
int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id);
|
||||
int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id);
|
||||
|
||||
/* Run a specific test */
|
||||
int (*fault_test)(struct bt_mesh_model *model, u8_t test_id,
|
||||
u16_t company_id);
|
||||
int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id,
|
||||
uint16_t company_id);
|
||||
|
||||
/* Attention on */
|
||||
void (*attn_on)(struct bt_mesh_model *model);
|
||||
@ -52,7 +52,7 @@ struct bt_mesh_health_srv_cb {
|
||||
*
|
||||
* @param max_faults Maximum number of faults the element can have.
|
||||
*
|
||||
* @return a New net_buf_simple of the needed size.
|
||||
* @return a New os_mbuf of the needed size.
|
||||
*/
|
||||
#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \
|
||||
NET_BUF_SIMPLE(1 + 3 + (max_faults))
|
||||
|
@ -0,0 +1,123 @@
|
||||
/** @file
|
||||
* @brief Bluetooth Mesh Heartbeat API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _BLUETOOTH_MESH_HEARTBEAT_H_
|
||||
#define _BLUETOOTH_MESH_HEARTBEAT_H_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Mesh
|
||||
* @defgroup bt_mesh_heartbeat Bluetooth Mesh Heartbeat
|
||||
* @ingroup bt_mesh
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Heartbeat Publication parameters */
|
||||
struct bt_mesh_hb_pub {
|
||||
/** Destination address. */
|
||||
uint16_t dst;
|
||||
/** Remaining publish count. */
|
||||
uint16_t count;
|
||||
/** Time To Live value. */
|
||||
uint8_t ttl;
|
||||
/**
|
||||
* Bitmap of features that trigger a Heartbeat publication if
|
||||
* they change. Legal values are @ref BT_MESH_FEAT_RELAY,
|
||||
* @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and
|
||||
* @ref BT_MESH_FEAT_LOW_POWER.
|
||||
*/
|
||||
uint16_t feat;
|
||||
/** Network index used for publishing. */
|
||||
uint16_t net_idx;
|
||||
/** Publication period in seconds. */
|
||||
uint32_t period;
|
||||
};
|
||||
|
||||
/** Heartbeat Subscription parameters. */
|
||||
struct bt_mesh_hb_sub {
|
||||
/** Subscription period in seconds. */
|
||||
uint32_t period;
|
||||
/** Remaining subscription time in seconds. */
|
||||
uint32_t remaining;
|
||||
/** Source address to receive Heartbeats from. */
|
||||
uint16_t src;
|
||||
/** Destination address to received Heartbeats on. */
|
||||
uint16_t dst;
|
||||
/** The number of received Heartbeat messages so far. */
|
||||
uint16_t count;
|
||||
/**
|
||||
* Minimum hops in received messages, ie the shortest registered
|
||||
* path from the publishing node to the subscribing node. A
|
||||
* Heartbeat received from an immediate neighbor has hop
|
||||
* count = 1.
|
||||
*/
|
||||
uint8_t min_hops;
|
||||
/**
|
||||
* Maximum hops in received messages, ie the longest registered
|
||||
* path from the publishing node to the subscribing node. A
|
||||
* Heartbeat received from an immediate neighbor has hop
|
||||
* count = 1.
|
||||
*/
|
||||
uint8_t max_hops;
|
||||
};
|
||||
|
||||
/** Heartbeat callback structure */
|
||||
struct bt_mesh_hb_cb {
|
||||
/** @brief Receive callback for heartbeats.
|
||||
*
|
||||
* Gets called on every received Heartbeat that matches the current
|
||||
* Heartbeat subscription parameters.
|
||||
*
|
||||
* @param sub Current Heartbeat subscription parameters.
|
||||
* @param hops The number of hops the Heartbeat was received
|
||||
* with.
|
||||
* @param feat The feature set of the publishing node. The
|
||||
* value is a bitmap of @ref BT_MESH_FEAT_RELAY,
|
||||
* @ref BT_MESH_FEAT_PROXY,
|
||||
* @ref BT_MESH_FEAT_FRIEND and
|
||||
* @ref BT_MESH_FEAT_LOW_POWER.
|
||||
*/
|
||||
void (*recv)(const struct bt_mesh_hb_sub *sub, uint8_t hops,
|
||||
uint16_t feat);
|
||||
|
||||
/** @brief Subscription end callback for heartbeats.
|
||||
*
|
||||
* Gets called when the subscription period ends, providing a summary
|
||||
* of the received heartbeat messages.
|
||||
*
|
||||
* @param sub Current Heartbeat subscription parameters.
|
||||
*/
|
||||
void (*sub_end)(const struct bt_mesh_hb_sub *sub);
|
||||
};
|
||||
|
||||
/** @brief Get the current Heartbeat publication parameters.
|
||||
*
|
||||
* @param get Heartbeat publication parameters return buffer.
|
||||
*/
|
||||
void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get);
|
||||
|
||||
/** @brief Get the current Heartbeat subscription parameters.
|
||||
*
|
||||
* @param get Heartbeat subscription parameters return buffer.
|
||||
*/
|
||||
void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get);
|
||||
|
||||
extern struct bt_mesh_hb_cb hb_cb;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */
|
@ -59,10 +59,37 @@ typedef enum {
|
||||
BT_MESH_PROV_OOB_ON_DEV = BIT(15),
|
||||
} bt_mesh_prov_oob_info_t;
|
||||
|
||||
/** Device Capabilities. */
|
||||
struct bt_mesh_dev_capabilities {
|
||||
/** Number of elements supported by the device */
|
||||
uint8_t elem_count;
|
||||
|
||||
/** Supported algorithms and other capabilities */
|
||||
uint16_t algorithms;
|
||||
|
||||
/** Supported public key types */
|
||||
uint8_t pub_key_type;
|
||||
|
||||
/** Supported static OOB Types */
|
||||
uint8_t static_oob;
|
||||
|
||||
/** Supported Output OOB Actions */
|
||||
bt_mesh_output_action_t output_actions;
|
||||
|
||||
/** Supported Input OOB Actions */
|
||||
bt_mesh_input_action_t input_actions;
|
||||
|
||||
/** Maximum size of Output OOB supported */
|
||||
uint8_t output_size;
|
||||
|
||||
/** Maximum size in octets of Input OOB supported */
|
||||
uint8_t input_size;
|
||||
};
|
||||
|
||||
/** Provisioning properties & capabilities. */
|
||||
struct bt_mesh_prov {
|
||||
/** The UUID that's used when advertising as unprovisioned */
|
||||
const u8_t *uuid;
|
||||
const uint8_t *uuid;
|
||||
|
||||
/** Optional URI. This will be advertised separately from the
|
||||
* unprovisioned beacon, however the unprovisioned beacon will
|
||||
@ -75,19 +102,34 @@ struct bt_mesh_prov {
|
||||
bt_mesh_prov_oob_info_t oob_info;
|
||||
|
||||
/** Static OOB value */
|
||||
const u8_t *static_val;
|
||||
const uint8_t *static_val;
|
||||
/** Static OOB value length */
|
||||
u8_t static_val_len;
|
||||
uint8_t static_val_len;
|
||||
|
||||
/** Maximum size of Output OOB supported */
|
||||
u8_t output_size;
|
||||
uint8_t output_size;
|
||||
/** Supported Output OOB Actions */
|
||||
u16_t output_actions;
|
||||
uint16_t output_actions;
|
||||
|
||||
/* Maximum size of Input OOB supported */
|
||||
u8_t input_size;
|
||||
uint8_t input_size;
|
||||
/** Supported Input OOB Actions */
|
||||
u16_t input_actions;
|
||||
uint16_t input_actions;
|
||||
|
||||
/** @brief Provisioning Capabilities.
|
||||
*
|
||||
* This callback notifies the application that the provisioning capabilities
|
||||
* of the unprovisioned device has been received.
|
||||
*
|
||||
* The application can consequently call bt_mesh_auth_method_set_<*> to
|
||||
* select suitable provisioning oob authentication method.
|
||||
*
|
||||
* When this callback returns, the provisioner will start authentication with
|
||||
* the chosen method.
|
||||
*
|
||||
* @param cap capabilities supported by device.
|
||||
*/
|
||||
void (*capabilities)(const struct bt_mesh_dev_capabilities *cap);
|
||||
|
||||
/** @brief Output of a number is requested.
|
||||
*
|
||||
@ -99,7 +141,7 @@ struct bt_mesh_prov {
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int (*output_number)(bt_mesh_output_action_t act, u32_t num);
|
||||
int (*output_number)(bt_mesh_output_action_t act, uint32_t num);
|
||||
|
||||
/** @brief Output of a string is requested.
|
||||
*
|
||||
@ -126,7 +168,7 @@ struct bt_mesh_prov {
|
||||
*
|
||||
* @return Zero on success or negative error code otherwise
|
||||
*/
|
||||
int (*input)(bt_mesh_input_action_t act, u8_t size);
|
||||
int (*input)(bt_mesh_input_action_t act, uint8_t size);
|
||||
|
||||
/** @brief The other device finished their OOB input.
|
||||
*
|
||||
@ -146,9 +188,9 @@ struct bt_mesh_prov {
|
||||
* @param uri_hash Pointer to URI Hash value. NULL if no hash was
|
||||
* present in the beacon.
|
||||
*/
|
||||
void (*unprovisioned_beacon)(u8_t uuid[16],
|
||||
void (*unprovisioned_beacon)(uint8_t uuid[16],
|
||||
bt_mesh_prov_oob_info_t oob_info,
|
||||
u32_t *uri_hash);
|
||||
uint32_t *uri_hash);
|
||||
|
||||
/** @brief Provisioning link has been opened.
|
||||
*
|
||||
@ -177,7 +219,7 @@ struct bt_mesh_prov {
|
||||
* @param net_idx NetKeyIndex given during provisioning.
|
||||
* @param addr Primary element address.
|
||||
*/
|
||||
void (*complete)(u16_t net_idx, u16_t addr);
|
||||
void (*complete)(uint16_t net_idx, uint16_t addr);
|
||||
|
||||
/** @brief A new node has been added to the provisioning database.
|
||||
*
|
||||
@ -186,10 +228,12 @@ struct bt_mesh_prov {
|
||||
* the specified NetKeyIndex and primary element address.
|
||||
*
|
||||
* @param net_idx NetKeyIndex given during provisioning.
|
||||
* @param uuid UUID of the added node
|
||||
* @param addr Primary element address.
|
||||
* @param num_elem Number of elements that this node has.
|
||||
*/
|
||||
void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
|
||||
void (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
|
||||
uint8_t num_elem);
|
||||
|
||||
/** @brief Node has been reset.
|
||||
*
|
||||
@ -222,7 +266,90 @@ int bt_mesh_input_string(const char *str);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_input_number(u32_t num);
|
||||
int bt_mesh_input_number(uint32_t num);
|
||||
|
||||
/** @brief Provide Device public key.
|
||||
*
|
||||
* @param public_key Device public key.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]);
|
||||
|
||||
/** @brief Use Input OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use the specified Input OOB
|
||||
* authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or
|
||||
* @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is
|
||||
* called with a random number that has to be entered on the unprovisioned
|
||||
* device.
|
||||
*
|
||||
* When using @ref BT_MESH_ENTER_STRING, the @ref bt_mesh_prov::output_string
|
||||
* callback is called with a random string that has to be entered on the
|
||||
* unprovisioned device.
|
||||
*
|
||||
* @param action Authentication action used by the unprovisioned device.
|
||||
* @param size Authentication size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size);
|
||||
|
||||
/** @brief Use Output OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use the specified Output OOB
|
||||
* authentication action. The @ref bt_mesh_prov::input callback will
|
||||
* be called.
|
||||
*
|
||||
* When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE
|
||||
* or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call
|
||||
* @ref bt_mesh_input_number with the random number indicated by
|
||||
* the unprovisioned device.
|
||||
*
|
||||
* When using @ref BT_MESH_DISPLAY_STRING, the application has to call
|
||||
* @ref bt_mesh_input_string with the random string displayed by the
|
||||
* unprovisioned device.
|
||||
*
|
||||
* @param action Authentication action used by the unprovisioned device.
|
||||
* @param size Authentication size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size);
|
||||
|
||||
/** @brief Use static OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Instruct the unprovisioned device to use static OOB authentication, and use
|
||||
* the given static authentication value when provisioning.
|
||||
*
|
||||
* @param static_val Static OOB value.
|
||||
* @param size Static OOB value size.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size);
|
||||
|
||||
/** @brief Don't use OOB authentication.
|
||||
*
|
||||
* Provisioner only.
|
||||
*
|
||||
* Don't use any authentication when provisioning new devices. This is the
|
||||
* default behavior.
|
||||
*
|
||||
* @warning Not using any authentication exposes the mesh network to
|
||||
* impersonation attacks, where attackers can pretend to be the
|
||||
* unprovisioned device to gain access to the network. Authentication
|
||||
* is strongly encouraged.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_auth_method_set_none(void);
|
||||
|
||||
/** @brief Enable specific provisioning bearers
|
||||
*
|
||||
@ -258,25 +385,6 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
|
||||
/* Primary Network Key index */
|
||||
#define BT_MESH_NET_PRIMARY 0x000
|
||||
|
||||
#define BT_MESH_RELAY_DISABLED 0x00
|
||||
#define BT_MESH_RELAY_ENABLED 0x01
|
||||
#define BT_MESH_RELAY_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_BEACON_DISABLED 0x00
|
||||
#define BT_MESH_BEACON_ENABLED 0x01
|
||||
|
||||
#define BT_MESH_GATT_PROXY_DISABLED 0x00
|
||||
#define BT_MESH_GATT_PROXY_ENABLED 0x01
|
||||
#define BT_MESH_GATT_PROXY_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_FRIEND_DISABLED 0x00
|
||||
#define BT_MESH_FRIEND_ENABLED 0x01
|
||||
#define BT_MESH_FRIEND_NOT_SUPPORTED 0x02
|
||||
|
||||
#define BT_MESH_NODE_IDENTITY_STOPPED 0x00
|
||||
#define BT_MESH_NODE_IDENTITY_RUNNING 0x01
|
||||
#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02
|
||||
|
||||
/* Features */
|
||||
#define BT_MESH_FEAT_RELAY BIT(0)
|
||||
#define BT_MESH_FEAT_PROXY BIT(1)
|
||||
@ -299,7 +407,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_init(u8_t own_addr_type,
|
||||
int bt_mesh_init(uint8_t own_addr_type,
|
||||
const struct bt_mesh_prov *prov,
|
||||
const struct bt_mesh_comp *comp);
|
||||
|
||||
@ -351,9 +459,9 @@ int bt_mesh_resume(void);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
u8_t flags, u32_t iv_index, u16_t addr,
|
||||
const u8_t dev_key[16]);
|
||||
int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
|
||||
uint8_t flags, uint32_t iv_index, uint16_t addr,
|
||||
const uint8_t dev_key[16]);
|
||||
|
||||
/** @brief Provision a Mesh Node using PB-ADV
|
||||
*
|
||||
@ -365,8 +473,8 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
|
||||
u8_t attention_duration);
|
||||
int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
|
||||
uint8_t attention_duration);
|
||||
|
||||
/** @brief Check if the local node has been provisioned.
|
||||
*
|
||||
@ -428,7 +536,17 @@ int bt_mesh_lpn_poll(void);
|
||||
*
|
||||
* @param cb Function to call when the Friendship status changes.
|
||||
*/
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established));
|
||||
void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
|
||||
|
||||
/** @brief Terminate Friendship.
|
||||
*
|
||||
* Terminated Friendship for given LPN.
|
||||
*
|
||||
* @param lpn_addr Low Power Node address.
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_mesh_friend_terminate(uint16_t lpn_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -17,10 +17,15 @@
|
||||
#include "glue.h"
|
||||
#include "access.h"
|
||||
#include "main.h"
|
||||
#include "cfg.h"
|
||||
#include "cfg_srv.h"
|
||||
#include "health_srv.h"
|
||||
#include "cfg_cli.h"
|
||||
#include "health_cli.h"
|
||||
#include "proxy.h"
|
||||
#include "cdb.h"
|
||||
#include "cfg.h"
|
||||
#include "heartbeat.h"
|
||||
#include "../../src/app_keys.h"
|
||||
|
||||
#endif /* __BT_MESH_H */
|
||||
|
@ -15,7 +15,7 @@ struct bt_mesh_gen_model_cli {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
struct k_sem op_sync;
|
||||
u32_t op_pending;
|
||||
uint32_t op_pending;
|
||||
void *op_param;
|
||||
};
|
||||
|
||||
@ -33,14 +33,14 @@ extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\
|
||||
cli_data, &bt_mesh_gen_level_cli_cb)
|
||||
|
||||
int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t *state);
|
||||
int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
u8_t val, u8_t *state);
|
||||
int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t *level);
|
||||
int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
|
||||
s16_t val, s16_t *state);
|
||||
int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t *state);
|
||||
int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
uint8_t val, uint8_t *state);
|
||||
int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t *level);
|
||||
int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
|
||||
int16_t val, int16_t *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ extern "C" {
|
||||
struct bt_mesh_gen_onoff_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, u8_t *state);
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state);
|
||||
int (*get)(struct bt_mesh_model *model, uint8_t *state);
|
||||
int (*set)(struct bt_mesh_model *model, uint8_t state);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_onoff_srv_op[];
|
||||
@ -28,8 +28,8 @@ extern const struct bt_mesh_model_cb gen_onoff_srv_cb;
|
||||
struct bt_mesh_gen_level_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
int (*get)(struct bt_mesh_model *model, int16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op gen_level_srv_op[];
|
||||
@ -42,8 +42,8 @@ extern const struct bt_mesh_model_cb gen_level_srv_cb;
|
||||
struct bt_mesh_light_lightness_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
int (*get)(struct bt_mesh_model *model, s16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level);
|
||||
int (*get)(struct bt_mesh_model *model, int16_t *level);
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level);
|
||||
};
|
||||
|
||||
extern const struct bt_mesh_model_op light_lightness_srv_op[];
|
||||
@ -53,12 +53,12 @@ extern const struct bt_mesh_model_cb light_lightness_srv_cb;
|
||||
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
|
||||
light_lightness_srv_op, pub, srv, &light_lightness_srv_cb)
|
||||
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, u8_t state));
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, s16_t level));
|
||||
void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
|
||||
int (*set)(struct bt_mesh_model *model, uint8_t state));
|
||||
void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level));
|
||||
void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
|
||||
int (*set)(struct bt_mesh_model *model, int16_t level));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -33,13 +33,13 @@ extern "C" {
|
||||
* Allows access to Bluetooth stack internals, not exposed by public API.
|
||||
*/
|
||||
struct bt_test_cb {
|
||||
void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
||||
void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
|
||||
const void *payload, size_t payload_len);
|
||||
void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model,
|
||||
u16_t key_idx);
|
||||
void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model,
|
||||
u16_t key_idx);
|
||||
void (*mesh_prov_invalid_bearer)(u8_t opcode);
|
||||
void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model,
|
||||
uint16_t key_idx);
|
||||
void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model,
|
||||
uint16_t key_idx);
|
||||
void (*mesh_prov_invalid_bearer)(uint8_t opcode);
|
||||
void (*mesh_trans_incomp_timer_exp)(void);
|
||||
|
||||
sys_snode_t node;
|
||||
@ -66,7 +66,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_test_mesh_lpn_group_add(u16_t group);
|
||||
int bt_test_mesh_lpn_group_add(uint16_t group);
|
||||
|
||||
/** Send Friend Subscription List Remove message.
|
||||
*
|
||||
@ -79,7 +79,7 @@ int bt_test_mesh_lpn_group_add(u16_t group);
|
||||
*
|
||||
* @return Zero on success or (negative) error code otherwise.
|
||||
*/
|
||||
int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
|
||||
int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count);
|
||||
|
||||
/** Clear replay protection list cache.
|
||||
*
|
||||
@ -87,12 +87,12 @@ int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
|
||||
*/
|
||||
int bt_test_mesh_rpl_clear(void);
|
||||
|
||||
u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx);
|
||||
u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store);
|
||||
uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx);
|
||||
uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store);
|
||||
int cmd_mesh_init(int argc, char *argv[]);
|
||||
|
||||
int bt_test_shell_init(void);
|
||||
int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id);
|
||||
int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,7 +28,7 @@
|
||||
#endif
|
||||
|
||||
static const struct bt_mesh_comp *dev_comp;
|
||||
static u16_t dev_primary_addr;
|
||||
static uint16_t dev_primary_addr;
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
@ -55,7 +55,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
}
|
||||
}
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
{
|
||||
int period;
|
||||
|
||||
@ -91,10 +91,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
||||
}
|
||||
}
|
||||
|
||||
static s32_t next_period(struct bt_mesh_model *mod)
|
||||
static int32_t next_period(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
u32_t elapsed, period;
|
||||
uint32_t elapsed, period;
|
||||
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
if (!period) {
|
||||
@ -117,7 +117,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
|
||||
static void publish_sent(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
s32_t delay;
|
||||
int32_t delay;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
@ -133,7 +133,7 @@ static void publish_sent(int err, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static void publish_start(u16_t duration, int err, void *user_data)
|
||||
static void publish_start(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
@ -158,30 +158,18 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
.app_idx = pub->key,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_model_elem(mod)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = pub->cred,
|
||||
};
|
||||
int err;
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tx.sub = bt_mesh_subnet_get(key->net_idx);
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
|
||||
|
||||
@ -189,15 +177,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
|
||||
err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
|
||||
|
||||
done:
|
||||
os_mbuf_free_chain(sdu);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
|
||||
{
|
||||
/* Cancel all retransmits for this publish attempt */
|
||||
pub->count = 0U;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, pub->mod);
|
||||
}
|
||||
|
||||
static void mod_publish(struct ble_npl_event *work)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
|
||||
s32_t period_ms;
|
||||
int32_t period_ms;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
@ -229,7 +224,10 @@ static void mod_publish(struct ble_npl_event *work)
|
||||
|
||||
err = pub->update(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to update publication message");
|
||||
/* Cancel this publish attempt. */
|
||||
BT_DBG("Update failed, skipping publish (err: %d)", err);
|
||||
pub->period_start = k_uptime_get_32();
|
||||
publish_retransmit_end(err, pub);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -244,7 +242,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
|
||||
return &dev_comp->elem[mod->elem_idx];
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
|
||||
{
|
||||
struct bt_mesh_elem *elem;
|
||||
|
||||
@ -276,6 +274,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
int i;
|
||||
int *err = user_data;
|
||||
|
||||
if (*err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod->pub) {
|
||||
mod->pub->mod = mod;
|
||||
@ -295,12 +298,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
}
|
||||
|
||||
if (mod->cb && mod->cb->init) {
|
||||
mod->cb->init(mod);
|
||||
*err = mod->cb->init(mod);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* There must be at least one element */
|
||||
if (!comp->elem_count) {
|
||||
return -EINVAL;
|
||||
@ -308,12 +313,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
|
||||
|
||||
dev_comp = comp;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
err = 0;
|
||||
bt_mesh_model_foreach(mod_init, &err);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr)
|
||||
void bt_mesh_comp_provision(uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -336,16 +342,14 @@ void bt_mesh_comp_unprovision(void)
|
||||
BT_DBG("");
|
||||
|
||||
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
bt_mesh_model_foreach(mod_init, NULL);
|
||||
}
|
||||
|
||||
u16_t bt_mesh_primary_addr(void)
|
||||
uint16_t bt_mesh_primary_addr(void)
|
||||
{
|
||||
return dev_primary_addr;
|
||||
}
|
||||
|
||||
static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
|
||||
static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -359,13 +363,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
|
||||
}
|
||||
|
||||
struct find_group_visitor_ctx {
|
||||
u16_t *entry;
|
||||
uint16_t *entry;
|
||||
struct bt_mesh_model *mod;
|
||||
u16_t addr;
|
||||
uint16_t addr;
|
||||
};
|
||||
|
||||
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
|
||||
u32_t depth, void *user_data)
|
||||
uint32_t depth, void *user_data)
|
||||
{
|
||||
struct find_group_visitor_ctx *ctx = user_data;
|
||||
|
||||
@ -382,7 +386,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
|
||||
return BT_MESH_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
|
||||
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
|
||||
{
|
||||
struct find_group_visitor_ctx ctx = {
|
||||
.mod = *mod,
|
||||
@ -398,10 +402,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
|
||||
}
|
||||
|
||||
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
u16_t group_addr)
|
||||
uint16_t group_addr)
|
||||
{
|
||||
struct bt_mesh_model *model;
|
||||
u16_t *match;
|
||||
uint16_t *match;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
@ -425,9 +429,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
|
||||
{
|
||||
u16_t index;
|
||||
uint16_t index;
|
||||
|
||||
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
|
||||
index = (addr - dev_comp->elem[0].addr);
|
||||
@ -449,12 +453,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8_t bt_mesh_elem_count(void)
|
||||
uint8_t bt_mesh_elem_count(void)
|
||||
{
|
||||
return dev_comp->elem_count;
|
||||
}
|
||||
|
||||
static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
||||
static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -469,22 +473,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
|
||||
static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
|
||||
{
|
||||
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
|
||||
return (dev_comp->elem[mod->elem_idx].addr == dst);
|
||||
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
|
||||
return bt_mesh_model_find_group(&mod, dst);
|
||||
return !!bt_mesh_model_find_group(&mod, dst);
|
||||
}
|
||||
|
||||
return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
|
||||
/* If a message with a fixed group address is sent to the access layer,
|
||||
* the lower layers have already confirmed that we are subscribing to
|
||||
* it. All models on the primary element should receive the message.
|
||||
*/
|
||||
return mod->elem_idx == 0;
|
||||
}
|
||||
|
||||
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
u8_t model_count, u32_t opcode,
|
||||
uint8_t model_count, uint32_t opcode,
|
||||
struct bt_mesh_model **model)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < model_count; i++) {
|
||||
const struct bt_mesh_model_op *op;
|
||||
@ -502,7 +510,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
static int get_opcode(struct os_mbuf *buf, uint32_t *opcode)
|
||||
{
|
||||
switch (buf->om_data[0] >> 6) {
|
||||
case 0x00:
|
||||
@ -529,6 +537,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_u8(buf) << 16;
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
*opcode |= net_buf_simple_pull_le16(buf);
|
||||
return 0;
|
||||
}
|
||||
@ -536,29 +548,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr)
|
||||
{
|
||||
/* Check for fixed group addresses */
|
||||
switch (addr) {
|
||||
case BT_MESH_ADDR_ALL_NODES:
|
||||
return true;
|
||||
case BT_MESH_ADDR_PROXIES:
|
||||
return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
|
||||
case BT_MESH_ADDR_FRIENDS:
|
||||
return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
|
||||
case BT_MESH_ADDR_RELAYS:
|
||||
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
{
|
||||
struct bt_mesh_model *models, *model;
|
||||
const struct bt_mesh_model_op *op;
|
||||
u32_t opcode;
|
||||
u8_t count;
|
||||
uint32_t opcode;
|
||||
uint8_t count;
|
||||
int i;
|
||||
|
||||
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
|
||||
@ -617,7 +612,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
|
||||
void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode)
|
||||
{
|
||||
net_buf_simple_init(msg, 0);
|
||||
|
||||
@ -630,6 +625,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
|
||||
break;
|
||||
case 3:
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
break;
|
||||
default:
|
||||
@ -676,11 +675,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(ctx->net_idx),
|
||||
.ctx = ctx,
|
||||
.src = bt_mesh_model_elem(model)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = 0,
|
||||
};
|
||||
|
||||
return model_send(model, &tx, false, msg, cb, cb_data);
|
||||
@ -690,13 +686,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
{
|
||||
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_model_pub *pub = model->pub;
|
||||
struct bt_mesh_app_key *key;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
.send_rel = pub->send_rel,
|
||||
.app_idx = pub->key,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = bt_mesh_model_elem(model)->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
};
|
||||
int err;
|
||||
|
||||
@ -712,12 +710,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
goto done;
|
||||
}
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
|
||||
BT_ERR("Message does not fit maximum SDU size");
|
||||
err = -EMSGSIZE;
|
||||
@ -732,13 +724,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
|
||||
|
||||
ctx.addr = pub->addr;
|
||||
ctx.send_ttl = pub->ttl;
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
tx.friend_cred = pub->cred;
|
||||
tx.sub = bt_mesh_subnet_get(ctx.net_idx),
|
||||
|
||||
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
|
||||
|
||||
@ -747,10 +733,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
|
||||
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
|
||||
if (err) {
|
||||
/* Don't try retransmissions for this publish attempt */
|
||||
pub->count = 0;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, model);
|
||||
publish_retransmit_end(err, pub);
|
||||
}
|
||||
|
||||
done:
|
||||
@ -759,9 +742,9 @@ done:
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
u16_t company, u16_t id)
|
||||
uint16_t company, uint16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < elem->vnd_model_count; i++) {
|
||||
if (elem->vnd_models[i].vnd.company == company &&
|
||||
@ -774,9 +757,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
|
||||
u16_t id)
|
||||
uint16_t id)
|
||||
{
|
||||
u8_t i;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < elem->model_count; i++) {
|
||||
if (elem->models[i].id == id) {
|
||||
@ -804,29 +787,38 @@ struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
|
||||
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
uint32_t depth,
|
||||
void *user_data),
|
||||
void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *m = root;
|
||||
u32_t depth = 0;
|
||||
int depth = 0;
|
||||
/* 'skip' is set to true when we ascend from child to parent node.
|
||||
* In that case, we want to skip calling the callback on the parent
|
||||
* node and we don't want to descend onto a child node as those
|
||||
* nodes have already been visited.
|
||||
*/
|
||||
bool skip = false;
|
||||
|
||||
do {
|
||||
if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
|
||||
if (!skip &&
|
||||
cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) {
|
||||
return;
|
||||
}
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
if (m->extends) {
|
||||
if (!skip && m->extends) {
|
||||
m = m->extends;
|
||||
depth++;
|
||||
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
|
||||
m = m->next->next;
|
||||
m = m->next;
|
||||
depth--;
|
||||
skip = true;
|
||||
} else {
|
||||
m = m->next;
|
||||
skip = false;
|
||||
}
|
||||
#endif
|
||||
} while (m && m != root);
|
||||
} while (m && depth > 0);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
|
||||
|
@ -16,8 +16,7 @@ enum {
|
||||
BT_MESH_MOD_BIND_PENDING = BIT(0),
|
||||
BT_MESH_MOD_SUB_PENDING = BIT(1),
|
||||
BT_MESH_MOD_PUB_PENDING = BIT(2),
|
||||
BT_MESH_MOD_DATA_PRESENT = BIT(3),
|
||||
BT_MESH_MOD_NEXT_IS_PARENT = BIT(4),
|
||||
BT_MESH_MOD_NEXT_IS_PARENT = BIT(3),
|
||||
};
|
||||
|
||||
/* Tree walk return codes */
|
||||
@ -26,23 +25,21 @@ enum bt_mesh_walk {
|
||||
BT_MESH_WALK_CONTINUE,
|
||||
};
|
||||
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
|
||||
|
||||
u8_t bt_mesh_elem_count(void);
|
||||
uint8_t bt_mesh_elem_count(void);
|
||||
|
||||
/* Find local element based on unicast or group address */
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
|
||||
struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
|
||||
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
|
||||
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
|
||||
u32_t depth,
|
||||
uint32_t depth,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr);
|
||||
|
||||
bool bt_mesh_fixed_group_match(u16_t addr);
|
||||
uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr);
|
||||
|
||||
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem,
|
||||
@ -50,16 +47,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
|
||||
s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
|
||||
int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
|
||||
|
||||
void bt_mesh_comp_provision(u16_t addr);
|
||||
void bt_mesh_comp_provision(uint16_t addr);
|
||||
void bt_mesh_comp_unprovision(void);
|
||||
|
||||
u16_t bt_mesh_primary_addr(void);
|
||||
uint16_t bt_mesh_primary_addr(void);
|
||||
|
||||
const struct bt_mesh_comp *bt_mesh_comp_get(void);
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx);
|
||||
struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx);
|
||||
|
||||
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
|
||||
|
||||
|
@ -40,21 +40,20 @@
|
||||
#define ADV_INT_DEFAULT_MS 100
|
||||
#define ADV_INT_FAST_MS 20
|
||||
|
||||
static s32_t adv_int_min = ADV_INT_DEFAULT_MS;
|
||||
static int32_t adv_int_min = ADV_INT_DEFAULT_MS;
|
||||
|
||||
/* TinyCrypt PRNG consumes a lot of stack space, so we need to have
|
||||
* an increased call stack whenever it's used.
|
||||
*/
|
||||
#if MYNEWT
|
||||
#define ADV_STACK_SIZE 768
|
||||
OS_TASK_STACK_DEFINE(g_blemesh_stack, ADV_STACK_SIZE);
|
||||
OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
|
||||
struct os_task adv_task;
|
||||
#else
|
||||
static TaskHandle_t adv_task_h;
|
||||
#endif
|
||||
|
||||
static struct ble_npl_eventq adv_queue;
|
||||
extern u8_t g_mesh_addr_type;
|
||||
extern uint8_t g_mesh_addr_type;
|
||||
static int adv_initialized = false;
|
||||
|
||||
static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
|
||||
@ -64,14 +63,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
|
||||
struct os_mbuf_pool adv_os_mbuf_pool;
|
||||
static struct os_mempool adv_buf_mempool;
|
||||
|
||||
static const u8_t adv_type[] = {
|
||||
[BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
|
||||
[BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
|
||||
[BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
|
||||
[BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
|
||||
};
|
||||
|
||||
|
||||
static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
|
||||
|
||||
static struct bt_mesh_adv *adv_alloc(int id)
|
||||
@ -79,7 +70,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
|
||||
return &adv_pool[id];
|
||||
}
|
||||
|
||||
static inline void adv_send_start(u16_t duration, int err,
|
||||
static inline void adv_send_start(uint16_t duration, int err,
|
||||
const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data)
|
||||
{
|
||||
@ -98,10 +89,17 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
|
||||
|
||||
static inline void adv_send(struct os_mbuf *buf)
|
||||
{
|
||||
static const uint8_t adv_type[] = {
|
||||
[BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
|
||||
[BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
|
||||
[BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
|
||||
[BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
|
||||
} ;
|
||||
|
||||
const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
|
||||
void *cb_data = BT_MESH_ADV(buf)->cb_data;
|
||||
struct ble_gap_adv_params param = { 0 };
|
||||
u16_t duration, adv_int;
|
||||
uint16_t duration, adv_int;
|
||||
struct bt_data ad;
|
||||
int err;
|
||||
|
||||
@ -158,7 +156,7 @@ mesh_adv_thread(void *args)
|
||||
static struct ble_npl_event *ev;
|
||||
struct os_mbuf *buf;
|
||||
#if (MYNEWT_VAL(BLE_MESH_PROXY))
|
||||
s32_t timeout;
|
||||
int32_t timeout;
|
||||
#endif
|
||||
|
||||
BT_DBG("started");
|
||||
@ -212,7 +210,7 @@ void bt_mesh_adv_update(void)
|
||||
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit, s32_t timeout)
|
||||
uint8_t xmit, int32_t timeout)
|
||||
{
|
||||
struct bt_mesh_adv *adv;
|
||||
struct os_mbuf *buf;
|
||||
@ -241,8 +239,8 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||
s32_t timeout)
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
|
||||
int32_t timeout)
|
||||
{
|
||||
return bt_mesh_adv_create_from_pool(&adv_os_mbuf_pool, adv_alloc, type,
|
||||
xmit, timeout);
|
||||
@ -261,8 +259,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
|
||||
net_buf_put(&adv_queue, net_buf_ref(buf));
|
||||
}
|
||||
|
||||
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
u8_t adv_type, struct os_mbuf *buf)
|
||||
static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
|
||||
uint8_t adv_type, struct os_mbuf *buf)
|
||||
{
|
||||
if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||
return;
|
||||
@ -274,7 +272,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
|
||||
while (buf->om_len > 1) {
|
||||
struct net_buf_simple_state state;
|
||||
u8_t len, type;
|
||||
uint8_t len, type;
|
||||
|
||||
len = net_buf_simple_pull_u8(buf);
|
||||
/* Check for early termination */
|
||||
@ -308,7 +306,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
|
||||
}
|
||||
|
||||
net_buf_simple_restore(buf, &state);
|
||||
net_buf_simple_pull(buf, len);
|
||||
net_buf_simple_pull_mem(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,7 +335,7 @@ void bt_mesh_adv_init(void)
|
||||
#if MYNEWT
|
||||
os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL,
|
||||
MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER,
|
||||
g_blemesh_stack, ADV_STACK_SIZE);
|
||||
g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
|
||||
#elif ESP_PLATFORM
|
||||
xTaskCreatePinnedToCore(mesh_adv_thread, "mesh_adv", 2768,
|
||||
NULL, (configMAX_PRIORITIES - 5), &adv_task_h, NIMBLE_CORE);
|
||||
|
@ -31,23 +31,18 @@ enum bt_mesh_adv_type
|
||||
BT_MESH_ADV_URI,
|
||||
};
|
||||
|
||||
typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration,
|
||||
typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration,
|
||||
int err, void *user_data);
|
||||
|
||||
struct bt_mesh_adv {
|
||||
const struct bt_mesh_send_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
u8_t type:2,
|
||||
uint8_t type:2,
|
||||
busy:1;
|
||||
u8_t xmit;
|
||||
uint8_t xmit;
|
||||
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
|
||||
u8_t flags;
|
||||
uint8_t flags;
|
||||
|
||||
int ref_cnt;
|
||||
struct ble_npl_event ev;
|
||||
@ -56,13 +51,13 @@ struct bt_mesh_adv {
|
||||
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
|
||||
|
||||
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
|
||||
s32_t timeout);
|
||||
struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
|
||||
int32_t timeout);
|
||||
|
||||
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
|
||||
bt_mesh_adv_alloc_t get_id,
|
||||
enum bt_mesh_adv_type type,
|
||||
u8_t xmit, s32_t timeout);
|
||||
uint8_t xmit, int32_t timeout);
|
||||
|
||||
void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data);
|
||||
|
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#if MYNEWT_VAL(BLE_MESH)
|
||||
|
||||
#include "crypto.h"
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
|
||||
static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
dst[0] = a[0] ^ b[0];
|
||||
dst[1] = a[1] ^ b[1];
|
||||
dst[2] = a[2] ^ b[2];
|
||||
dst[3] = a[3] ^ b[3];
|
||||
dst[4] = a[4] ^ b[4];
|
||||
dst[5] = a[5] ^ b[5];
|
||||
dst[6] = a[6] ^ b[6];
|
||||
dst[7] = a[7] ^ b[7];
|
||||
dst[8] = a[8] ^ b[8];
|
||||
dst[9] = a[9] ^ b[9];
|
||||
dst[10] = a[10] ^ b[10];
|
||||
dst[11] = a[11] ^ b[11];
|
||||
dst[12] = a[12] ^ b[12];
|
||||
dst[13] = a[13] ^ b[13];
|
||||
dst[14] = a[14] ^ b[14];
|
||||
dst[15] = a[15] ^ b[15];
|
||||
}
|
||||
|
||||
/* pmsg is assumed to have the nonce already present in bytes 1-13 */
|
||||
static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
|
||||
size_t mic_size, uint8_t msg_len, uint8_t b[16],
|
||||
uint8_t X0[16])
|
||||
{
|
||||
int i, j, err;
|
||||
|
||||
/* X_0 = e(AppKey, flags || nonce || length) */
|
||||
b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
|
||||
|
||||
sys_put_be16(msg_len, b + 14);
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If AAD is being used to authenticate, include it here */
|
||||
if (aad_len) {
|
||||
sys_put_be16(aad_len, b);
|
||||
|
||||
for (i = 0; i < sizeof(uint16_t); i++) {
|
||||
b[i] = X0[i] ^ b[i];
|
||||
}
|
||||
|
||||
j = 0;
|
||||
aad_len += sizeof(uint16_t);
|
||||
while (aad_len > 16) {
|
||||
do {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
i++, j++;
|
||||
} while (i < 16);
|
||||
|
||||
aad_len -= 16;
|
||||
i = 0;
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aad_len; i++, j++) {
|
||||
b[i] = X0[i] ^ aad[j];
|
||||
}
|
||||
|
||||
for (i = aad_len; i < 16; i++) {
|
||||
b[i] = X0[i];
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, b, X0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
|
||||
const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
|
||||
size_t aad_len, uint8_t *mic, size_t mic_size)
|
||||
{
|
||||
uint8_t b[16], Xn[16], s0[16];
|
||||
uint16_t blk_cnt, last_blk;
|
||||
int err, j, i;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
b[0] = 0x01;
|
||||
memcpy(b + 1, nonce, 13);
|
||||
|
||||
/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
|
||||
sys_put_be16(0x0000, &b[14]);
|
||||
|
||||
err = bt_encrypt_be(key, b, s0);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
|
||||
if (j + 1 == blk_cnt) {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
|
||||
}
|
||||
|
||||
memcpy(&b[i], &Xn[i], 16 - i);
|
||||
} else {
|
||||
xor16(b, Xn, &cleartext_msg[j * 16]);
|
||||
}
|
||||
|
||||
err = bt_encrypt_be(key, b, Xn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* MIC = C_mic ^ X_1 */
|
||||
for (i = 0; i < mic_size; i++) {
|
||||
mic[i] = s0[i] ^ Xn[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
|
||||
const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
|
||||
{
|
||||
uint8_t a_i[16], s_i[16];
|
||||
uint16_t last_blk, blk_cnt;
|
||||
size_t i, j;
|
||||
int err;
|
||||
|
||||
last_blk = msg_len % 16;
|
||||
blk_cnt = (msg_len + 15) / 16;
|
||||
if (!last_blk) {
|
||||
last_blk = 16U;
|
||||
}
|
||||
|
||||
a_i[0] = 0x01;
|
||||
memcpy(&a_i[1], nonce, 13);
|
||||
|
||||
for (j = 0; j < blk_cnt; j++) {
|
||||
/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
|
||||
sys_put_be16(j + 1, &a_i[14]);
|
||||
|
||||
err = bt_encrypt_be(key, a_i, s_i);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypted = Payload[0-15] ^ C_1 */
|
||||
if (j < blk_cnt - 1) {
|
||||
xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
|
||||
} else {
|
||||
for (i = 0; i < last_blk; i++) {
|
||||
out_msg[(j * 16) + i] =
|
||||
in_msg[(j * 16) + i] ^ s_i[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t mic[16];
|
||||
|
||||
if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
|
||||
|
||||
ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
if (memcmp(mic, enc_msg + msg_len, mic_size)) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
|
||||
size_t msg_len, const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *out_msg, size_t mic_size)
|
||||
{
|
||||
uint8_t *mic = out_msg + msg_len;
|
||||
|
||||
BT_DBG("key %s", bt_hex(key, 16));
|
||||
BT_DBG("nonce %s", bt_hex(nonce, 13));
|
||||
BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
|
||||
BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
|
||||
|
||||
/* Unsupported AAD size */
|
||||
if (aad_len >= 0xff00 || mic_size > 16) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
|
||||
|
||||
ccm_crypt(key, nonce, msg, out_msg, msg_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH) */
|
@ -0,0 +1,512 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#if MYNEWT_VAL(BLE_MESH)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "../include/mesh/mesh.h"
|
||||
#include "mesh_priv.h"
|
||||
#include "net.h"
|
||||
#include "app_keys.h"
|
||||
#include "rpl.h"
|
||||
#include "settings.h"
|
||||
#include "crypto.h"
|
||||
#include "adv.h"
|
||||
#include "proxy.h"
|
||||
#include "friend.h"
|
||||
#include "foundation.h"
|
||||
#include "access.h"
|
||||
#include "subnet.h"
|
||||
|
||||
#define MESH_LOG_MODULE BLE_MESH_LOG
|
||||
#include "nimble/porting/nimble/include/log/log.h"
|
||||
|
||||
static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
|
||||
[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
|
||||
.app_idx = BT_MESH_KEY_UNUSED,
|
||||
.net_idx = BT_MESH_KEY_UNUSED,
|
||||
}
|
||||
};
|
||||
|
||||
static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) {
|
||||
if (bt_mesh_app_key_cb_list[i]) {
|
||||
BT_DBG("app_key_evt %d", i);
|
||||
bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *app_get(uint16_t app_idx)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return &apps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
/* Check for already existing app_key */
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return &apps[i];
|
||||
}
|
||||
|
||||
if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) {
|
||||
app = &apps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
static void app_key_del(struct bt_mesh_app_key *app)
|
||||
{
|
||||
BT_DBG("AppIdx 0x%03x", app->app_idx);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_DELETED);
|
||||
|
||||
app->net_idx = BT_MESH_KEY_UNUSED;
|
||||
app->app_idx = BT_MESH_KEY_UNUSED;
|
||||
(void)memset(app->keys, 0, sizeof(app->keys));
|
||||
}
|
||||
|
||||
static void app_key_revoke(struct bt_mesh_app_key *app)
|
||||
{
|
||||
if (!app->updated) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0]));
|
||||
memset(&app->keys[1], 0, sizeof(app->keys[1]));
|
||||
app->updated = false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_REVOKED);
|
||||
}
|
||||
|
||||
|
||||
static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
|
||||
{
|
||||
if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (app->net_idx != sub->net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (evt == BT_MESH_KEY_DELETED) {
|
||||
app_key_del(app);
|
||||
} else if (evt == BT_MESH_KEY_REVOKED) {
|
||||
app_key_revoke(app);
|
||||
} else if (evt == BT_MESH_KEY_SWAPPED && app->updated) {
|
||||
app_key_evt(app, BT_MESH_KEY_SWAPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
if (!bt_mesh_subnet_cb_list[0]) {
|
||||
bt_mesh_subnet_cb_list[0] = subnet_evt;
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
bt_hex(key, 16));
|
||||
|
||||
if (!bt_mesh_subnet_get(net_idx)) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
app = app_key_alloc(app_idx);
|
||||
if (!app) {
|
||||
return STATUS_INSUFF_RESOURCES;
|
||||
}
|
||||
|
||||
if (app->app_idx == app_idx) {
|
||||
if (app->net_idx != net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
if (memcmp(key, app->keys[0].val, 16)) {
|
||||
return STATUS_IDX_ALREADY_STORED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (bt_mesh_app_id(key, &app->keys[0].id)) {
|
||||
return STATUS_CANNOT_SET;
|
||||
}
|
||||
|
||||
BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
|
||||
|
||||
app->net_idx = net_idx;
|
||||
app->app_idx = app_idx;
|
||||
app->updated = false;
|
||||
memcpy(app->keys[0].val, key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_ADDED);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (app) {
|
||||
return app;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct bt_mesh_subnet *sub;
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
|
||||
bt_hex(key, 16));
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (!app) {
|
||||
return STATUS_INVALID_APPKEY;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
sub = bt_mesh_subnet_get(app->net_idx);
|
||||
if (!sub) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
/* The AppKey Update message shall generate an error when node
|
||||
* is in normal operation, Phase 2, or Phase 3 or in Phase 1
|
||||
* when the AppKey Update message on a valid AppKeyIndex when
|
||||
* the AppKey value is different.
|
||||
*/
|
||||
if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
|
||||
return STATUS_CANNOT_UPDATE;
|
||||
}
|
||||
|
||||
if (app->updated) {
|
||||
if (memcmp(app->keys[1].val, key, 16)) {
|
||||
return STATUS_IDX_ALREADY_STORED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (bt_mesh_app_id(key, &app->keys[1].id)) {
|
||||
return STATUS_CANNOT_UPDATE;
|
||||
}
|
||||
|
||||
BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id);
|
||||
|
||||
app->updated = true;
|
||||
memcpy(app->keys[1].val, key, 16);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Storing AppKey persistently");
|
||||
bt_mesh_store_app_key(app->app_idx);
|
||||
}
|
||||
|
||||
app_key_evt(app, BT_MESH_KEY_UPDATED);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
BT_DBG("AppIdx 0x%03x", app_idx);
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) {
|
||||
return STATUS_INVALID_NETKEY;
|
||||
}
|
||||
|
||||
app = app_get(app_idx);
|
||||
if (!app) {
|
||||
/* This could be a retry of a previous attempt that had its
|
||||
* response lost, so pretend that it was a success.
|
||||
*/
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) {
|
||||
return STATUS_INVALID_BINDING;
|
||||
}
|
||||
|
||||
app_key_del(app);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t old_key[16], const uint8_t new_key[16])
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
|
||||
app = app_key_alloc(app_idx);
|
||||
if (!app) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (app->app_idx == app_idx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
|
||||
|
||||
memcpy(app->keys[0].val, old_key, 16);
|
||||
if (bt_mesh_app_id(old_key, &app->keys[0].id)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (new_key) {
|
||||
memcpy(app->keys[1].val, new_key, 16);
|
||||
if (bt_mesh_app_id(new_key, &app->keys[1].id)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
app->net_idx = net_idx;
|
||||
app->app_idx = app_idx;
|
||||
app->updated = !!new_key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bt_mesh_app_key_exists(uint16_t app_idx)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
if (apps[i].app_idx == app_idx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
|
||||
off_t skip)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count >= max) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
app_idxs[count++] = app->app_idx;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
|
||||
struct bt_mesh_subnet **sub,
|
||||
const uint8_t **app_key, uint8_t *aid)
|
||||
{
|
||||
struct bt_mesh_app_key *app = NULL;
|
||||
|
||||
if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
|
||||
/* With device keys, the application has to decide which subnet
|
||||
* to send on.
|
||||
*/
|
||||
*sub = bt_mesh_subnet_get(ctx->net_idx);
|
||||
if (!*sub) {
|
||||
BT_WARN("Unknown NetKey 0x%03x", ctx->net_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE &&
|
||||
!bt_mesh_elem_find(ctx->addr)) {
|
||||
struct bt_mesh_cdb_node *node;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
|
||||
BT_WARN("No DevKey for 0x%04x", ctx->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
node = bt_mesh_cdb_node_get(ctx->addr);
|
||||
if (!node) {
|
||||
BT_WARN("No DevKey for 0x%04x", ctx->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*app_key = node->dev_key;
|
||||
} else {
|
||||
*app_key = bt_mesh.dev_key;
|
||||
}
|
||||
|
||||
*aid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
app = app_get(ctx->app_idx);
|
||||
if (!app) {
|
||||
BT_WARN("Unknown AppKey 0x%03x", ctx->app_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*sub = bt_mesh_subnet_get(app->net_idx);
|
||||
if (!*sub) {
|
||||
BT_WARN("Unknown NetKey 0x%03x", app->net_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) {
|
||||
*aid = app->keys[1].id;
|
||||
*app_key = app->keys[1].val;
|
||||
} else {
|
||||
*aid = app->keys[0].id;
|
||||
*app_key = app->keys[0].val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
int (*cb)(struct bt_mesh_net_rx *rx,
|
||||
const uint8_t key[16], void *cb_data),
|
||||
void *cb_data)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
if (dev_key) {
|
||||
/* Attempt remote dev key first, as that is only available for
|
||||
* provisioner devices, which normally don't interact with nodes
|
||||
* that know their local dev key.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
|
||||
rx->net_if != BT_MESH_NET_IF_LOCAL) {
|
||||
struct bt_mesh_cdb_node *node;
|
||||
|
||||
node = bt_mesh_cdb_node_get(rx->ctx.addr);
|
||||
if (node && !cb(rx, node->dev_key, cb_data)) {
|
||||
return BT_MESH_KEY_DEV_REMOTE;
|
||||
}
|
||||
}
|
||||
|
||||
/** Bluetooth Mesh Specification v1.0.1, section 3.4.3:
|
||||
* The Device key is only valid for unicast addresses.
|
||||
*/
|
||||
if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
|
||||
err = cb(rx, bt_mesh.dev_key, cb_data);
|
||||
if (!err) {
|
||||
return BT_MESH_KEY_DEV_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
return BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
const struct bt_mesh_app_key *app = &apps[i];
|
||||
const struct bt_mesh_app_cred *cred;
|
||||
|
||||
if (app->app_idx == BT_MESH_KEY_UNUSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (app->net_idx != rx->sub->net_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rx->new_key && app->updated) {
|
||||
cred = &app->keys[1];
|
||||
} else {
|
||||
cred = &app->keys[0];
|
||||
}
|
||||
|
||||
if (cred->id != aid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = cb(rx, cred->val, cb_data);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return app->app_idx;
|
||||
}
|
||||
|
||||
return BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
|
||||
void bt_mesh_app_keys_reset(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(apps); i++) {
|
||||
struct bt_mesh_app_key *app = &apps[i];
|
||||
|
||||
if (app->app_idx != BT_MESH_KEY_UNUSED) {
|
||||
app_key_del(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MYNEWT_VAL(BLE_MESH) */
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BT_MESH_APP_KEYS_H_
|
||||
#define _BT_MESH_APP_KEYS_H_
|
||||
|
||||
#include "../include/mesh/mesh.h"
|
||||
#include "subnet.h"
|
||||
|
||||
/** Mesh Application. */
|
||||
struct bt_mesh_app_key {
|
||||
uint16_t net_idx;
|
||||
uint16_t app_idx;
|
||||
bool updated;
|
||||
struct bt_mesh_app_cred {
|
||||
uint8_t id;
|
||||
uint8_t val[16];
|
||||
} keys[2];
|
||||
};
|
||||
|
||||
/** @brief Reset the app keys module. */
|
||||
void bt_mesh_app_keys_reset(void);
|
||||
|
||||
/** @brief Get the application key with the given AppIdx.
|
||||
*
|
||||
* @param app_idx App index.
|
||||
*
|
||||
* @return The matching application, or NULL if the application isn't known.
|
||||
*/
|
||||
struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx);
|
||||
|
||||
/** @brief Initialize a new application key with the given parameters.
|
||||
*
|
||||
* @param app_idx AppIndex.
|
||||
* @param net_idx NetIndex the application is bound to.
|
||||
* @param old_key Current application key.
|
||||
* @param new_key Updated application key, or NULL if not known.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
|
||||
const uint8_t old_key[16], const uint8_t new_key[16]);
|
||||
|
||||
/** @brief Resolve the message encryption keys, given a message context.
|
||||
*
|
||||
* Will use the @c ctx::app_idx and @c ctx::net_idx fields to find a pair of
|
||||
* message encryption keys. If @c ctx::app_idx represents a device key, the
|
||||
* @c ctx::net_idx will be used to determine the net key. Otherwise, the
|
||||
* @c ctx::net_idx parameter will be ignored.
|
||||
*
|
||||
* @param ctx Message context.
|
||||
* @param sub Subnet return parameter.
|
||||
* @param app_key Application return parameter.
|
||||
* @param aid Application ID return parameter.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
|
||||
struct bt_mesh_subnet **sub,
|
||||
const uint8_t **app_key, uint8_t *aid);
|
||||
|
||||
/** @brief Iterate through all matching application keys and call @c cb on each.
|
||||
*
|
||||
* @param dev_key Whether to return device keys.
|
||||
* @param aid 7 bit application ID to match.
|
||||
* @param rx RX structure to match against.
|
||||
* @param cb Callback to call for every valid app key.
|
||||
* @param cb_data Callback data to pass to the callback.
|
||||
*
|
||||
* @return The AppIdx that yielded a 0-return from the callback.
|
||||
*/
|
||||
uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
|
||||
struct bt_mesh_net_rx *rx,
|
||||
int (*cb)(struct bt_mesh_net_rx *rx,
|
||||
const uint8_t key[16], void *cb_data),
|
||||
void *cb_data);
|
||||
|
||||
struct bt_mesh_app_key *app_get(uint16_t app_idx);
|
||||
|
||||
extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
|
||||
enum bt_mesh_key_evt evt);
|
||||
|
||||
#endif /* _BT_MESH_APP_KEYS_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user