diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..e7355499
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,136 @@
+---
+Language: Cpp
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveMacros: true
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortLambdasOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: true
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 140
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 2
+Cpp11BracedListStyle: true
+DeriveLineEnding: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentCaseLabels: true
+IndentGotoLabels: true
+IndentPPDirectives: BeforeHash
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: All
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: false
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: true
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatementsExceptForEachMacros
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+# Needs new Clang: SpaceAroundPointerQualifiers: After
+Standard: Latest
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 8
+UseCRLF: false
+UseTab: Never
+...
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 00000000..d6036802
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,26 @@
+Checks: '*,
+ -llvmlibc-callee-namespace,
+ -llvm-header-guard,
+ -llvm-namespace-comment,
+ -google-build-using-namespace,
+ -google-runtime-int,
+ -google-readability-namespace-comments,
+ -fuchsia-statically-constructed-objects,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-pro-bounds-constant-array-index,
+ -cppcoreguidelines-pro-type-union-access,
+ -cppcoreguidelines-pro-type-cstyle-cast,
+ -cppcoreguidelines-pro-type-vararg,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-avoid-non-const-global-variables,
+ -cppcoreguidelines-avoid-c-arrays,
+ -readability-magic-numbers,
+ -readability-uppercase-literal-suffix,
+ -modernize-use-trailing-return-type,
+ -modernize-avoid-c-arrays,
+ -hicpp-signed-bitwise,
+ -hicpp-no-assembler,
+ -hicpp-avoid-c-arrays,
+ -hicpp-uppercase-literal-suffix,
+ -cert-err58-cpp,
+ -cert-err60-cpp'
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..2257cac4
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,15 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.c text
+*.cpp text
+*.h text
+*.hpp text
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.bin binary
+*.jpg binary
+*.jpeg binary
diff --git a/.gitconfig b/.gitconfig
new file mode 100644
index 00000000..b2274475
--- /dev/null
+++ b/.gitconfig
@@ -0,0 +1,5 @@
+[core]
+ whitespace = blank-at-eol,blank-at-eof,space-before-tab
+ autocrlf = input
+[apply]
+ whitespace = fix
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..3af8fb9e
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+liberapay: JF002
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7bdfbcb1..60a86f76 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -8,10 +8,30 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -27,5 +47,8 @@
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4234b983..bb7a8b73 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(pinetime VERSION 0.11.0 LANGUAGES C CXX ASM)
+project(pinetime VERSION 0.12.0 LANGUAGES C CXX ASM)
set(NRF_TARGET "nrf52")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..a6fa6828
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,33 @@
+This contribution guide is in progress, improvements are welcome.
+
+### Code style
+
+Any C++ code PRs should aim to follow the style of existing code in the project.
+
+Using an autoformatter is heavily recommended, but make sure it's configured properly.
+
+There's currently preconfigured autoformatter rules for:
+
+ * CLion (IntelliJ) in .idea/codeStyles/Project.xml
+
+You can use those to configure your own IDE if it's not already on the list.
+
+#### Linting errors and compiler warnings
+
+Try to avoid any currently enabled warnings and try to reduce the amount of linter errors.
+
+#### Spelling
+
+Make sure you spellcheck your code before commiting it.
+
+#### TODO, FIXME
+
+Check before commiting that you haven't forgotten anything, preferably don't leave these in your commits.
+
+#### Licence headers
+
+You should add your name to the comma-space separated list of contributors if there's a license header.
+
+### License
+
+By contributing you agree to licence your code under the repository's general license (which is currently GPL-v3+).
diff --git a/README.md b/README.md
index e1819d0f..f8b05bd6 100644
--- a/README.md
+++ b/README.md
@@ -34,14 +34,18 @@ As of now, here is the list of achievements of this project:
- Time synchronization via BLE
- Notification via BLE
- Multiple 'apps' :
- * Clock (displays the date, time, battery level, BLE connection status, heart rate and step count)
- * Heart rate
- * Motion
- * System info (displays various info : BLE MAC, build date/time, uptime, version, ...)
- * Brightness (allows the user to configure the brightness of the display)
+ * Clock (displays the date, time, battery level, ble connection status, heart rate)
+ * System info (displays various info : BLE MAC, build date/time, uptime, version,...)
+ * Brightess (allows the user to configure the brightness of the display)
+ * Music (control the playback of the music on your phone)
+ * Heart rate (controls the heart rate sensor and display current heartbeat)
+ * Navigation (displays navigation instructions coming from the companion app)
+ * Notification (displays the last notification received)
+ * Paddle (single player pong-like game)
+ * Two (2048 clone game)
- Supported by 2 companion apps (development is in progress):
* [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android)
- * [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS)
+ * [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS and Linux)
- **[Experimental]** OTA (Over-the-air) update via BLE
- **[Experimental]** Bootloader based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/)
diff --git a/bootloader/ota-dfu-python/unpacker.py b/bootloader/ota-dfu-python/unpacker.py
index 960ef9de..ab2ecbc5 100644
--- a/bootloader/ota-dfu-python/unpacker.py
+++ b/bootloader/ota-dfu-python/unpacker.py
@@ -13,7 +13,7 @@ class Unpacker(object):
#
#--------------------------------------------------------------------------
def entropy(self, length):
- return ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for i in range (length))
+ return ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for i in range (length))
#--------------------------------------------------------------------------
#
diff --git a/docker/build.sh b/docker/build.sh
index f35c2f3a..8f0d0fa9 100755
--- a/docker/build.sh
+++ b/docker/build.sh
@@ -31,8 +31,8 @@ main() {
CmakeGenerate
CmakeBuild $target
-
- if [[ "$DISABLE_POSTBUILD" != "true" ]]; then
+ BUILD_RESULT=$?
+ if [ "$DISABLE_POSTBUILD" != "true" -a "$BUILD_RESULT" == 0 ]; then
source "$BUILD_DIR/post_build.sh"
fi
}
@@ -70,7 +70,9 @@ CmakeGenerate() {
CmakeBuild() {
local target="$1"
[[ -n "$target" ]] && target="--target $target"
- cmake --build "$BUILD_DIR" --config $BUILD_TYPE $target -- -j$(nproc)
+ if cmake --build "$BUILD_DIR" --config $BUILD_TYPE $target -- -j$(nproc)
+ then return 0; else return 1;
+ fi
}
[[ $SOURCED == "false" ]] && main "$@" || echo "Sourced!"
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5955d393..4580609a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -610,7 +610,7 @@ include_directories(
"${NRF5_SDK_PATH}/modules/nrfx/drivers/include"
"${NRF5_SDK_PATH}/modules/nrfx/hal"
"${NRF5_SDK_PATH}/modules/nrfx/mdk"
- ${NRF5_SDK_PATH}/external/freertos/source/include
+ "${NRF5_SDK_PATH}/external/freertos/source/include"
"${NRF5_SDK_PATH}/components/toolchain/cmsis/include"
"${NRF5_SDK_PATH}/components/libraries/atomic"
"${NRF5_SDK_PATH}/components/libraries/atomic_fifo"
diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp
index f7d895c2..bc66ff72 100644
--- a/src/components/ble/BatteryInformationService.cpp
+++ b/src/components/ble/BatteryInformationService.cpp
@@ -1,3 +1,4 @@
+#include
#include "BatteryInformationService.h"
#include "components/battery/BatteryController.h"
diff --git a/src/components/ble/CurrentTimeClient.cpp b/src/components/ble/CurrentTimeClient.cpp
index be50fede..758f636c 100644
--- a/src/components/ble/CurrentTimeClient.cpp
+++ b/src/components/ble/CurrentTimeClient.cpp
@@ -1,5 +1,6 @@
#include "CurrentTimeClient.h"
#include
+#include
#include "components/datetime/DateTimeController.h"
using namespace Pinetime::Controllers;
diff --git a/src/components/ble/CurrentTimeService.cpp b/src/components/ble/CurrentTimeService.cpp
index 3a6264e2..9f14edc7 100644
--- a/src/components/ble/CurrentTimeService.cpp
+++ b/src/components/ble/CurrentTimeService.cpp
@@ -1,5 +1,6 @@
#include "CurrentTimeService.h"
#include
+#include
using namespace Pinetime::Controllers;
diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h
index 053caccb..a487a952 100644
--- a/src/drivers/St7789.h
+++ b/src/drivers/St7789.h
@@ -58,7 +58,7 @@ namespace Pinetime {
ColumnAddressSet = 0x2a,
RowAddressSet = 0x2b,
WriteToRam = 0x2c,
- MemoryDataAccessControl = 036,
+ MemoryDataAccessControl = 0x36,
VerticalScrollDefinition = 0x33,
VerticalScrollStartAddress = 0x37,
ColMod = 0x3a,
diff --git a/src/heartratetask/HeartRateTask.cpp b/src/heartratetask/HeartRateTask.cpp
index 5a6d2a5e..95d7837e 100644
--- a/src/heartratetask/HeartRateTask.cpp
+++ b/src/heartratetask/HeartRateTask.cpp
@@ -14,8 +14,8 @@ HeartRateTask::HeartRateTask(Drivers::Hrs3300 &heartRateSensor, Controllers::Hea
}
void HeartRateTask::Start() {
- if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle))
- APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
+ //if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle))
+ // APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
void HeartRateTask::Process(void *instance) {
diff --git a/src/libs/mynewt-nimble/apps/README.md b/src/libs/mynewt-nimble/apps/README.md
new file mode 100644
index 00000000..f36a836a
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/README.md
@@ -0,0 +1,54 @@
+
+
+# Sample applications
+
+## advertiser
+
+This is the simplest example of advertising. Application sets NRPA, configures
+advertisement parameters: general discoverable and not connectable and fills
+advertisement fields. Transmited data contains only flags, tx power level and
+device name, which fits in 31B limit of single package. With this data set,
+device advertises for 10 seconds, terminates advertisement and repeats process
+again infinitely.
+
+## scanner
+
+This application shows how to perform simple scan. Device performs discovery
+procedure, during which receives advertising reports (if any devices are
+advertising nearby). These reports are being parsed and results are printed to
+serial port. Applicaton starts new discovery every second.
+
+## peripheral
+
+Peripheral application is based on advertiser, but has added capability of
+connecting with other devices. As peripheral, device doesn't initiate any
+connection by itself; instead, advertises infinitely and accepts any connection
+request it receives. Because we cannot use any 16 or 32 bit UUIDs, as these are
+reserved by Bluetooth SIG, we are forced to use 128-bit one. Including such
+long UUID in advertising data consumes large part of available payload, so this
+data is split in advertising data and response data.
+
+## central
+
+This application works in pair with peripheral. It's based on scanner
+application - the difference is, that if there was detected device with UUID
+fitting to the one predefined in central application, connection is initiated.
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/apps/blemesh/src/main.c b/src/libs/mynewt-nimble/apps/blemesh/src/main.c
index 24c9950e..65270554 100644
--- a/src/libs/mynewt-nimble/apps/blemesh/src/main.c
+++ b/src/libs/mynewt-nimble/apps/blemesh/src/main.c
@@ -42,26 +42,6 @@ static int recent_test_id = STANDARD_TEST_ID;
static bool has_reg_fault = true;
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_DISABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if MYNEWT_VAL(BLE_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_ENABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
-#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
static int
fault_get_cur(struct bt_mesh_model *model,
uint8_t *test_id,
@@ -327,7 +307,7 @@ static const struct bt_mesh_model_op gen_level_op[] = {
};
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
&gen_onoff_pub, NULL),
@@ -385,7 +365,7 @@ static int output_number(bt_mesh_output_action_t action, uint32_t number)
return 0;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
console_printf("Local node provisioned, primary address 0x%04x\n", addr);
}
diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c
index 8b00e2c0..f666fe26 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c
@@ -48,10 +48,10 @@ static uint16_t top_val;
static uint32_t neopixel[WS2812_NUM_LED];
#endif
-static u8_t gen_onoff_state;
-static s16_t gen_level_state;
+static uint8_t gen_onoff_state;
+static int16_t gen_level_state;
-static void light_set_lightness(u8_t percentage)
+static void light_set_lightness(uint8_t percentage)
{
#if (!MYNEWT_VAL(USE_NEOPIXEL))
int rc;
@@ -76,10 +76,10 @@ static void light_set_lightness(u8_t percentage)
#endif
#else
int i;
- u32_t lightness;
- u8_t max_lightness = 0x1f;
+ uint32_t lightness;
+ uint8_t max_lightness = 0x1f;
- lightness = (u8_t) (percentage * max_lightness / 100);
+ lightness = (uint8_t) (percentage * max_lightness / 100);
for (i = 0; i < WS2812_NUM_LED; i++) {
neopixel[i] = (lightness | lightness << 8 | lightness << 16);
@@ -90,7 +90,7 @@ static void light_set_lightness(u8_t percentage)
static void update_light_state(void)
{
- u16_t level = (u16_t)gen_level_state;
+ uint16_t level = (uint16_t)gen_level_state;
int percent = 100 * level / 0xffff;
if (gen_onoff_state == 0) {
@@ -99,44 +99,44 @@ static void update_light_state(void)
light_set_lightness((uint8_t) percent);
}
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
{
*state = gen_onoff_state;
return 0;
}
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
{
gen_onoff_state = state;
update_light_state();
return 0;
}
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
{
*level = gen_level_state;
return 0;
}
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
{
gen_level_state = level;
- if ((u16_t)gen_level_state > 0x0000) {
+ if ((uint16_t)gen_level_state > 0x0000) {
gen_onoff_state = 1;
}
- if ((u16_t)gen_level_state == 0x0000) {
+ if ((uint16_t)gen_level_state == 0x0000) {
gen_onoff_state = 0;
}
update_light_state();
return 0;
}
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
{
return light_model_gen_level_get(model, lightness);
}
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
{
return light_model_gen_level_set(model, lightness);
}
diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h
index 7fcdd0c3..1f6f3c44 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h
+++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h
@@ -26,12 +26,12 @@
#include "syscfg/syscfg.h"
#include "mesh/mesh.h"
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
int light_model_init(void);
#endif
diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c
index 51d86eb5..70deede1 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c
@@ -31,8 +31,8 @@
#include "light_model.h"
-static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
int rc;
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c
index ef398c9f..736d4d32 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c
@@ -84,30 +84,6 @@ static void gen_onoff_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf);
-/*
- * Server Configuration Declaration
- */
-
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_DISABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if defined(CONFIG_BT_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_ENABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-#if defined(CONFIG_BT_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
/*
* Client Configuration Declaration
*/
@@ -213,9 +189,9 @@ static const struct bt_mesh_model_op gen_onoff_cli_op[] = {
};
struct onoff_state {
- u8_t current;
- u8_t previous;
- u8_t led_gpio_pin;
+ uint8_t current;
+ uint8_t previous;
+ uint8_t led_gpio_pin;
};
/*
@@ -238,7 +214,7 @@ static struct onoff_state onoff_state_arr[] = {
*/
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
@@ -320,20 +296,20 @@ static const struct bt_mesh_comp comp = {
};
struct sw {
- u8_t sw_num;
- u8_t onoff_state;
+ uint8_t sw_num;
+ uint8_t onoff_state;
struct os_callout button_work;
struct os_callout button_timer;
};
-static u8_t button_press_cnt;
+static uint8_t button_press_cnt;
static struct sw sw;
-static u8_t trans_id;
-static u32_t time, last_time;
-static u16_t primary_addr;
-static u16_t primary_net_idx;
+static uint8_t trans_id;
+static uint32_t time, last_time;
+static uint16_t primary_addr;
+static uint16_t primary_net_idx;
/*
* Generic OnOff Model Server Message Handlers
@@ -416,7 +392,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t state;
+ uint8_t state;
state = net_buf_simple_pull_u8(buf);
@@ -424,7 +400,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
bt_mesh_model_elem(model)->addr, ctx->addr, state);
}
-static int output_number(bt_mesh_output_action_t action, u32_t number)
+static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
BT_INFO("OOB Number %u", number);
return 0;
@@ -436,7 +412,7 @@ static int output_string(const char *str)
return 0;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
BT_INFO("provisioning complete for net_idx 0x%04x addr 0x%04x",
net_idx, addr);
@@ -449,7 +425,7 @@ static void prov_reset(void)
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
}
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
#define BUTTON_DEBOUNCE_DELAY_MS 250
@@ -528,7 +504,7 @@ static void button_pressed_worker(struct os_event *work)
struct bt_mesh_model *mod_cli, *mod_srv;
struct bt_mesh_model_pub *pub_cli, *pub_srv;
struct sw *sw = work->ev_arg;
- u8_t sw_idx = sw->sw_num;
+ uint8_t sw_idx = sw->sw_num;
int err;
mod_cli = mod_cli_sw[sw_idx];
@@ -599,7 +575,7 @@ static const struct bt_mesh_prov prov = {
.reset = prov_reset,
};
-void init_led(u8_t dev)
+void init_led(uint8_t dev)
{
hal_gpio_init_out(onoff_state_arr[dev].led_gpio_pin, 1);
}
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c
index 86d4c515..021d8e08 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c
@@ -34,7 +34,7 @@
#ifdef OOB_AUTH_ENABLE
-static int output_number(bt_mesh_output_action_t action, u32_t number)
+static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
printk("OOB Number: %lu\n", number);
return 0;
@@ -48,7 +48,7 @@ static int output_string(const char *str)
#endif
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
printk("Local node provisioned, primary address 0x%04x\n", addr);
}
@@ -58,7 +58,7 @@ static void prov_reset(void)
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
}
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
static const struct bt_mesh_prov prov = {
.uuid = dev_uuid,
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c
index b638b861..5dfeaf8e 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c
@@ -36,31 +36,6 @@
#include "state_binding.h"
#include "transition.h"
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_ENABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-
-#if defined(CONFIG_BT_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_ENABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-
-#if defined(CONFIG_BT_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
-
- .default_ttl = 7,
-
- /* 2 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
-
- /* 3 transmissions with 20ms interval */
- .relay_retransmit = BT_MESH_TRANSMIT(3, 20),
-};
-
static struct bt_mesh_health_srv health_srv = {
};
@@ -224,8 +199,8 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, onoff, tt, delay;
- s64_t now;
+ uint8_t tid, onoff, tt, delay;
+ int64_t now;
struct generic_onoff_state *state = model->user_data;
onoff = net_buf_simple_pull_u8(buf);
@@ -290,8 +265,8 @@ static void gen_onoff_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, onoff, tt, delay;
- s64_t now;
+ uint8_t tid, onoff, tt, delay;
+ int64_t now;
struct generic_onoff_state *state = model->user_data;
onoff = net_buf_simple_pull_u8(buf);
@@ -422,12 +397,12 @@ static void gen_level_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t level;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t level;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- level = (s16_t) net_buf_simple_pull_le16(buf);
+ level = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -494,12 +469,12 @@ static void gen_level_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t level;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t level;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- level = (s16_t) net_buf_simple_pull_le16(buf);
+ level = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -569,12 +544,12 @@ static void gen_delta_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s32_t tmp32, delta;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int32_t tmp32, delta;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- delta = (s32_t) net_buf_simple_pull_le32(buf);
+ delta = (int32_t) net_buf_simple_pull_le32(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -658,12 +633,12 @@ static void gen_delta_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s32_t tmp32, delta;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int32_t tmp32, delta;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- delta = (s32_t) net_buf_simple_pull_le32(buf);
+ delta = (int32_t) net_buf_simple_pull_le32(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -805,13 +780,13 @@ static void gen_move_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta;
- s32_t tmp32;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta;
+ int32_t tmp32;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- delta = (s16_t) net_buf_simple_pull_le16(buf);
+ delta = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -886,13 +861,13 @@ static void gen_move_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta;
- s32_t tmp32;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta;
+ int32_t tmp32;
+ int64_t now;
struct generic_level_state *state = model->user_data;
- delta = (s16_t) net_buf_simple_pull_le16(buf);
+ delta = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@@ -1021,7 +996,7 @@ static bool gen_def_trans_time_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tt;
+ uint8_t tt;
struct gen_def_trans_time_state *state = model->user_data;
tt = net_buf_simple_pull_u8(buf);
@@ -1122,7 +1097,7 @@ static bool gen_onpowerup_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t onpowerup;
+ uint8_t onpowerup;
struct generic_onpowerup_state *state = model->user_data;
onpowerup = net_buf_simple_pull_u8(buf);
@@ -1187,9 +1162,9 @@ static void vnd_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid;
+ uint8_t tid;
int current;
- s64_t now;
+ int64_t now;
struct vendor_state *state = model->user_data;
current = net_buf_simple_pull_le16(buf);
@@ -1290,9 +1265,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- u16_t actual;
- s64_t now;
+ uint8_t tid, tt, delay;
+ uint16_t actual;
+ int64_t now;
struct light_lightness_state *state = model->user_data;
actual = net_buf_simple_pull_le16(buf);
@@ -1360,9 +1335,9 @@ static void light_lightness_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- u16_t actual;
- s64_t now;
+ uint8_t tid, tt, delay;
+ uint16_t actual;
+ int64_t now;
struct light_lightness_state *state = model->user_data;
actual = net_buf_simple_pull_le16(buf);
@@ -1483,9 +1458,9 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- u16_t linear;
- s64_t now;
+ uint8_t tid, tt, delay;
+ uint16_t linear;
+ int64_t now;
struct light_lightness_state *state = model->user_data;
linear = net_buf_simple_pull_le16(buf);
@@ -1546,9 +1521,9 @@ static void light_lightness_linear_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- u16_t linear;
- s64_t now;
+ uint8_t tid, tt, delay;
+ uint16_t linear;
+ int64_t now;
struct light_lightness_state *state = model->user_data;
linear = net_buf_simple_pull_le16(buf);
@@ -1690,7 +1665,7 @@ static void light_lightness_default_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t lightness;
+ uint16_t lightness;
struct light_lightness_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
@@ -1741,7 +1716,7 @@ static bool light_lightness_range_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t min, max;
+ uint16_t min, max;
struct light_lightness_state *state = model->user_data;
min = net_buf_simple_pull_le16(buf);
@@ -1908,15 +1883,15 @@ static void light_ctl_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta_uv;
- u16_t lightness, temp;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta_uv;
+ uint16_t lightness, temp;
+ int64_t now;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
- delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@@ -1991,15 +1966,15 @@ static void light_ctl_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta_uv;
- u16_t lightness, temp;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta_uv;
+ uint16_t lightness, temp;
+ int64_t now;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
- delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@@ -2140,13 +2115,13 @@ static bool light_ctl_default_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t lightness, temp;
- s16_t delta_uv;
+ uint16_t lightness, temp;
+ int16_t delta_uv;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
- delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
/* Here, Model specification is silent about tid implementation */
@@ -2216,7 +2191,7 @@ static bool light_ctl_temp_range_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t min, max;
+ uint16_t min, max;
struct light_ctl_state *state = model->user_data;
min = net_buf_simple_pull_le16(buf);
@@ -2384,14 +2359,14 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta_uv;
- u16_t temp;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta_uv;
+ uint16_t temp;
+ int64_t now;
struct light_ctl_state *state = model->user_data;
temp = net_buf_simple_pull_le16(buf);
- delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@@ -2463,14 +2438,14 @@ static void light_ctl_temp_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t tid, tt, delay;
- s16_t delta_uv;
- u16_t temp;
- s64_t now;
+ uint8_t tid, tt, delay;
+ int16_t delta_uv;
+ uint16_t temp;
+ int64_t now;
struct light_ctl_state *state = model->user_data;
temp = net_buf_simple_pull_le16(buf);
- delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@@ -2689,7 +2664,7 @@ static const struct bt_mesh_model_op vnd_ops[] = {
};
struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h
index 38507195..d0f054ee 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h
@@ -46,109 +46,109 @@
#define CANNOT_SET_RANGE_MAX 0x02
struct generic_onoff_state {
- u8_t onoff;
- u8_t target_onoff;
+ uint8_t onoff;
+ uint8_t target_onoff;
- u8_t last_tid;
- u16_t last_src_addr;
- u16_t last_dst_addr;
- s64_t last_msg_timestamp;
+ uint8_t last_tid;
+ uint16_t last_src_addr;
+ uint16_t last_dst_addr;
+ int64_t last_msg_timestamp;
- s32_t tt_delta;
+ int32_t tt_delta;
struct transition *transition;
};
struct generic_level_state {
- s16_t level;
- s16_t target_level;
+ int16_t level;
+ int16_t target_level;
- s16_t last_level;
- s32_t last_delta;
+ int16_t last_level;
+ int32_t last_delta;
- u8_t last_tid;
- u16_t last_src_addr;
- u16_t last_dst_addr;
- s64_t last_msg_timestamp;
+ uint8_t last_tid;
+ uint16_t last_src_addr;
+ uint16_t last_dst_addr;
+ int64_t last_msg_timestamp;
- s32_t tt_delta;
+ int32_t tt_delta;
struct transition *transition;
};
struct generic_onpowerup_state {
- u8_t onpowerup;
+ uint8_t onpowerup;
};
struct gen_def_trans_time_state {
- u8_t tt;
+ uint8_t tt;
};
struct vendor_state {
int current;
- u32_t response;
- u8_t last_tid;
- u16_t last_src_addr;
- u16_t last_dst_addr;
- s64_t last_msg_timestamp;
+ uint32_t response;
+ uint8_t last_tid;
+ uint16_t last_src_addr;
+ uint16_t last_dst_addr;
+ int64_t last_msg_timestamp;
};
struct light_lightness_state {
- u16_t linear;
- u16_t target_linear;
+ uint16_t linear;
+ uint16_t target_linear;
- u16_t actual;
- u16_t target_actual;
+ uint16_t actual;
+ uint16_t target_actual;
- u16_t last;
- u16_t def;
+ uint16_t last;
+ uint16_t def;
- u8_t status_code;
- u16_t light_range_min;
- u16_t light_range_max;
- u32_t lightness_range;
+ uint8_t status_code;
+ uint16_t light_range_min;
+ uint16_t light_range_max;
+ uint32_t lightness_range;
- u8_t last_tid;
- u16_t last_src_addr;
- u16_t last_dst_addr;
- s64_t last_msg_timestamp;
+ uint8_t last_tid;
+ uint16_t last_src_addr;
+ uint16_t last_dst_addr;
+ int64_t last_msg_timestamp;
- s32_t tt_delta_actual;
- s32_t tt_delta_linear;
+ int32_t tt_delta_actual;
+ int32_t tt_delta_linear;
struct transition *transition;
};
struct light_ctl_state {
- u16_t lightness;
- u16_t target_lightness;
+ uint16_t lightness;
+ uint16_t target_lightness;
- u16_t temp;
- u16_t target_temp;
+ uint16_t temp;
+ uint16_t target_temp;
- s16_t delta_uv;
- s16_t target_delta_uv;
+ int16_t delta_uv;
+ int16_t target_delta_uv;
- u8_t status_code;
- u16_t temp_range_min;
- u16_t temp_range_max;
- u32_t temperature_range;
+ uint8_t status_code;
+ uint16_t temp_range_min;
+ uint16_t temp_range_max;
+ uint32_t temperature_range;
- u16_t lightness_def;
- u16_t temp_def;
- u32_t lightness_temp_def;
- s16_t delta_uv_def;
+ uint16_t lightness_def;
+ uint16_t temp_def;
+ uint32_t lightness_temp_def;
+ int16_t delta_uv_def;
- u32_t lightness_temp_last;
+ uint32_t lightness_temp_last;
- u8_t last_tid;
- u16_t last_src_addr;
- u16_t last_dst_addr;
- s64_t last_msg_timestamp;
+ uint8_t last_tid;
+ uint16_t last_src_addr;
+ uint16_t last_dst_addr;
+ int64_t last_msg_timestamp;
- s32_t tt_delta_lightness;
- s32_t tt_delta_temp;
- s32_t tt_delta_duv;
+ int32_t tt_delta_lightness;
+ int32_t tt_delta_temp;
+ int32_t tt_delta_duv;
struct transition *transition;
};
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c
index 7c8d65e6..741367b4 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c
@@ -59,14 +59,14 @@ static void light_default_var_init(void)
light_ctl_srv_user_data.temp_def = TEMP_MIN;
light_ctl_srv_user_data.lightness_temp_last =
- (u32_t) ((LIGHTNESS_MAX << 16) | TEMP_MIN);
+ (uint32_t) ((LIGHTNESS_MAX << 16) | TEMP_MIN);
}
static void light_default_status_init(void)
{
- u16_t lightness;
+ uint16_t lightness;
- lightness = (u16_t) (light_ctl_srv_user_data.lightness_temp_last >> 16);
+ lightness = (uint16_t) (light_ctl_srv_user_data.lightness_temp_last >> 16);
if (lightness) {
gen_onoff_srv_root_user_data.onoff = STATE_ON;
@@ -77,10 +77,10 @@ static void light_default_status_init(void)
/* Retrieve Default Lightness & Temperature Values */
if (light_ctl_srv_user_data.lightness_temp_def) {
- light_ctl_srv_user_data.lightness_def = (u16_t)
+ light_ctl_srv_user_data.lightness_def = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_def >> 16);
- light_ctl_srv_user_data.temp_def = (u16_t)
+ light_ctl_srv_user_data.temp_def = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_def);
}
@@ -92,18 +92,18 @@ static void light_default_status_init(void)
/* Retrieve Range of Lightness & Temperature */
if (light_lightness_srv_user_data.lightness_range) {
- light_lightness_srv_user_data.light_range_max = (u16_t)
+ light_lightness_srv_user_data.light_range_max = (uint16_t)
(light_lightness_srv_user_data.lightness_range >> 16);
- light_lightness_srv_user_data.light_range_min = (u16_t)
+ light_lightness_srv_user_data.light_range_min = (uint16_t)
(light_lightness_srv_user_data.lightness_range);
}
if (light_ctl_srv_user_data.temperature_range) {
- light_ctl_srv_user_data.temp_range_max = (u16_t)
+ light_ctl_srv_user_data.temp_range_max = (uint16_t)
(light_ctl_srv_user_data.temperature_range >> 16);
- light_ctl_srv_user_data.temp_range_min = (u16_t)
+ light_ctl_srv_user_data.temp_range_min = (uint16_t)
(light_ctl_srv_user_data.temperature_range);
}
@@ -117,11 +117,11 @@ static void light_default_status_init(void)
state_binding(ONOFF, ONOFF_TEMP);
break;
case STATE_RESTORE:
- light_lightness_srv_user_data.last = (u16_t)
+ light_lightness_srv_user_data.last = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_last >> 16);
light_ctl_srv_user_data.temp =
- (u16_t) (light_ctl_srv_user_data.lightness_temp_last);
+ (uint16_t) (light_ctl_srv_user_data.lightness_temp_last);
state_binding(ONPOWERUP, ONOFF_TEMP);
break;
@@ -132,7 +132,7 @@ static void light_default_status_init(void)
void update_light_state(void)
{
- u8_t power, color;
+ uint8_t power, color;
power = 100 * ((float) lightness / 65535);
color = 100 * ((float) (temperature + 32768) / 65535);
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c
index 21364b81..f8cf849d 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c
@@ -41,12 +41,12 @@
static bool is_randomization_of_TIDs_done;
#if (defined(ONOFF) || defined(ONOFF_TT))
-static u8_t tid_onoff;
+static uint8_t tid_onoff;
#elif defined(VND_MODEL_TEST)
-static u8_t tid_vnd;
+static uint8_t tid_vnd;
#endif
-static u8_t tid_level;
+static uint8_t tid_level;
void randomize_publishers_TID(void)
{
@@ -61,7 +61,7 @@ void randomize_publishers_TID(void)
is_randomization_of_TIDs_done = true;
}
-static u32_t button_read(int button)
+static uint32_t button_read(int button)
{
return (uint32_t) hal_gpio_read(button);
}
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c
index ae539433..0778f787 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c
@@ -32,14 +32,14 @@
#include "transition.h"
-u16_t lightness, target_lightness;
-s16_t temperature, target_temperature;
+uint16_t lightness, target_lightness;
+int16_t temperature, target_temperature;
-static s32_t ceiling(float num)
+static int32_t ceiling(float num)
{
- s32_t inum;
+ int32_t inum;
- inum = (s32_t) num;
+ inum = (int32_t) num;
if (num == (float) inum) {
return inum;
}
@@ -47,21 +47,21 @@ static s32_t ceiling(float num)
return inum + 1;
}
-u16_t actual_to_linear(u16_t val)
+uint16_t actual_to_linear(uint16_t val)
{
float tmp;
tmp = ((float) val / 65535);
- return (u16_t) ceiling(65535 * tmp * tmp);
+ return (uint16_t) ceiling(65535 * tmp * tmp);
}
-u16_t linear_to_actual(u16_t val)
+uint16_t linear_to_actual(uint16_t val)
{
- return (u16_t) (65535 * sqrt(((float) val / 65535)));
+ return (uint16_t) (65535 * sqrt(((float) val / 65535)));
}
-static void constrain_lightness(u16_t var)
+static void constrain_lightness(uint16_t var)
{
if (var > 0 && var < light_lightness_srv_user_data.light_range_min) {
var = light_lightness_srv_user_data.light_range_min;
@@ -72,7 +72,7 @@ static void constrain_lightness(u16_t var)
lightness = var;
}
-static void constrain_lightness2(u16_t var)
+static void constrain_lightness2(uint16_t var)
{
/* This is as per Mesh Model Specification 3.3.2.2.3 */
if (var > 0 && var < light_lightness_srv_user_data.light_range_min) {
@@ -88,7 +88,7 @@ static void constrain_lightness2(u16_t var)
lightness = var;
}
-static void constrain_target_lightness(u16_t var)
+static void constrain_target_lightness(uint16_t var)
{
if (var > 0 &&
var < light_lightness_srv_user_data.light_range_min) {
@@ -100,7 +100,7 @@ static void constrain_target_lightness(u16_t var)
target_lightness = var;
}
-static s16_t light_ctl_temp_to_level(u16_t temp)
+static int16_t light_ctl_temp_to_level(uint16_t temp)
{
float tmp;
@@ -111,14 +111,14 @@ static s16_t light_ctl_temp_to_level(u16_t temp)
tmp = tmp / (light_ctl_srv_user_data.temp_range_max -
light_ctl_srv_user_data.temp_range_min);
- return (s16_t) (tmp - 32768);
+ return (int16_t) (tmp - 32768);
/* 6.1.3.1.1 2nd formula end */
}
-static u16_t level_to_light_ctl_temp(s16_t level)
+static uint16_t level_to_light_ctl_temp(int16_t level)
{
- u16_t tmp;
+ uint16_t tmp;
float diff;
/* Mesh Model Specification 6.1.3.1.1 1st formula start */
@@ -126,14 +126,14 @@ static u16_t level_to_light_ctl_temp(s16_t level)
light_ctl_srv_user_data.temp_range_min) / 65535;
- tmp = (u16_t) ((level + 32768) * diff);
+ tmp = (uint16_t) ((level + 32768) * diff);
return (light_ctl_srv_user_data.temp_range_min + tmp);
/* 6.1.3.1.1 1st formula end */
}
-void state_binding(u8_t light, u8_t temp)
+void state_binding(uint8_t light, uint8_t temp)
{
switch (temp) {
case ONOFF_TEMP:
@@ -211,10 +211,10 @@ jump:
light_ctl_srv_user_data.lightness = lightness;
}
-void calculate_lightness_target_values(u8_t type)
+void calculate_lightness_target_values(uint8_t type)
{
bool set_light_ctl_temp_target_value;
- u16_t tmp;
+ uint16_t tmp;
set_light_ctl_temp_target_value = true;
@@ -274,7 +274,7 @@ void calculate_lightness_target_values(u8_t type)
}
}
-void calculate_temp_target_values(u8_t type)
+void calculate_temp_target_values(uint8_t type)
{
bool set_light_ctl_delta_uv_target_value;
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h
index db1f2a2e..0498e5c6 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h
@@ -43,11 +43,11 @@ enum state_binding {
IGNORE_TEMP
};
-extern u16_t lightness, target_lightness;
-extern s16_t temperature, target_temperature;
+extern uint16_t lightness, target_lightness;
+extern int16_t temperature, target_temperature;
-void state_binding(u8_t lightness, u8_t temperature);
-void calculate_lightness_target_values(u8_t type);
-void calculate_temp_target_values(u8_t type);
+void state_binding(uint8_t lightness, uint8_t temperature);
+void calculate_lightness_target_values(uint8_t type);
+void calculate_temp_target_values(uint8_t type);
#endif
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c
index 86fec7cc..d0ef980a 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c
@@ -32,8 +32,8 @@
#include "device_composition.h"
#include "storage.h"
-static u8_t storage_id;
-u8_t reset_counter;
+static uint8_t storage_id;
+uint8_t reset_counter;
static void save_reset_counter(void)
{
@@ -76,7 +76,7 @@ static void save_lightness_temp_def_state(void)
char buf[12];
light_ctl_srv_user_data.lightness_temp_def =
- (u32_t) ((light_ctl_srv_user_data.lightness_def << 16) |
+ (uint32_t) ((light_ctl_srv_user_data.lightness_def << 16) |
light_ctl_srv_user_data.temp_def);
settings_str_from_bytes(&light_ctl_srv_user_data.lightness_temp_def,
@@ -91,7 +91,7 @@ static void save_lightness_temp_last_state(void)
char buf[12];
light_ctl_srv_user_data.lightness_temp_last =
- (u32_t) ((light_ctl_srv_user_data.lightness << 16) |
+ (uint32_t) ((light_ctl_srv_user_data.lightness << 16) |
light_ctl_srv_user_data.temp);
settings_str_from_bytes(&light_ctl_srv_user_data.lightness_temp_last,
@@ -108,7 +108,7 @@ static void save_lightness_range(void)
char buf[12];
light_lightness_srv_user_data.lightness_range =
- (u32_t) ((light_lightness_srv_user_data.light_range_max << 16) |
+ (uint32_t) ((light_lightness_srv_user_data.light_range_max << 16) |
light_lightness_srv_user_data.light_range_min);
settings_str_from_bytes(&light_lightness_srv_user_data.lightness_range,
@@ -123,7 +123,7 @@ static void save_temperature_range(void)
char buf[12];
light_ctl_srv_user_data.temperature_range =
- (u32_t) ((light_ctl_srv_user_data.temp_range_max << 16) |
+ (uint32_t) ((light_ctl_srv_user_data.temp_range_max << 16) |
light_ctl_srv_user_data.temp_range_min);
settings_str_from_bytes(&light_ctl_srv_user_data.temperature_range,
@@ -162,7 +162,7 @@ static void storage_work_handler(struct os_event *work)
struct os_callout storage_work;
-void save_on_flash(u8_t id)
+void save_on_flash(uint8_t id)
{
storage_id = id;
os_callout_reset(&storage_work, 0);
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h
index e2905048..5e636f62 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h
@@ -37,11 +37,11 @@ enum ps_variables_id {
TEMPERATURE_RANGE
};
-extern u8_t reset_counter;
+extern uint8_t reset_counter;
extern struct os_callout storage_work;
int ps_settings_init(void);
-void save_on_flash(u8_t id);
+void save_on_flash(uint8_t id);
#endif
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c
index c9463e10..e31af75d 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c
@@ -40,8 +40,8 @@ struct os_callout light_ctl_temp_work;
struct os_callout dummy_timer;
-u8_t transition_type, default_tt;
-u32_t *ptr_counter;
+uint8_t transition_type, default_tt;
+uint32_t *ptr_counter;
struct os_callout *ptr_timer = &dummy_timer;
struct transition lightness_transition, temp_transition;
@@ -50,9 +50,9 @@ struct transition lightness_transition, temp_transition;
void calculate_rt(struct transition *transition)
{
- u8_t steps, resolution;
- s32_t duration_remainder;
- s64_t now;
+ uint8_t steps, resolution;
+ int32_t duration_remainder;
+ int64_t now;
if (transition->just_started) {
transition->rt = transition->tt;
@@ -88,7 +88,7 @@ void calculate_rt(struct transition *transition)
/* Function to calculate Remaining Time (End) */
-static void bound_states_transition_type_reassignment(u8_t type)
+static void bound_states_transition_type_reassignment(uint8_t type)
{
switch (type) {
case ONOFF:
@@ -113,7 +113,7 @@ static void bound_states_transition_type_reassignment(u8_t type)
static void tt_values_calculator(struct transition *transition)
{
- u8_t steps_multiplier, resolution;
+ uint8_t steps_multiplier, resolution;
resolution = (transition->tt >> 6);
steps_multiplier = (transition->tt & 0x3F);
@@ -142,7 +142,7 @@ static void tt_values_calculator(struct transition *transition)
ptr_counter = &transition->counter;
}
-void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay)
+void onoff_tt_values(struct generic_onoff_state *state, uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(ONOFF);
calculate_lightness_target_values(ONOFF);
@@ -162,7 +162,7 @@ void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay)
state->transition->counter);
}
-void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay)
+void level_tt_values(struct generic_level_state *state, uint8_t tt, uint8_t delay)
{
if (state == &gen_level_srv_root_user_data) {
bound_states_transition_type_reassignment(LEVEL);
@@ -188,7 +188,7 @@ void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay)
}
void light_lightness_actual_tt_values(struct light_lightness_state *state,
- u8_t tt, u8_t delay)
+ uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(ACTUAL);
calculate_lightness_target_values(ACTUAL);
@@ -210,7 +210,7 @@ void light_lightness_actual_tt_values(struct light_lightness_state *state,
}
void light_lightness_linear_tt_values(struct light_lightness_state *state,
- u8_t tt, u8_t delay)
+ uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(LINEAR);
calculate_lightness_target_values(LINEAR);
@@ -231,7 +231,7 @@ void light_lightness_linear_tt_values(struct light_lightness_state *state,
state->transition->counter);
}
-void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay)
+void light_ctl_tt_values(struct light_ctl_state *state, uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(CTL);
calculate_lightness_target_values(CTL);
@@ -261,7 +261,7 @@ void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay)
}
void light_ctl_temp_tt_values(struct light_ctl_state *state,
- u8_t tt, u8_t delay)
+ uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(CTL_TEMP);
calculate_temp_target_values(CTL_TEMP);
@@ -331,7 +331,7 @@ static void onoff_work_handler(struct os_event *work)
static void level_lightness_work_handler(struct os_event *work)
{
- u8_t level;
+ uint8_t level;
struct generic_level_state *state = &gen_level_srv_root_user_data;
switch (transition_type) {
diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h
index 84101395..dc3e8da1 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h
+++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h
@@ -42,19 +42,19 @@ enum level_transition_types {
struct transition {
bool just_started;
- u8_t tt;
- u8_t rt;
- u8_t delay;
- u32_t quo_tt;
- u32_t counter;
- u32_t total_duration;
- s64_t start_timestamp;
+ uint8_t tt;
+ uint8_t rt;
+ uint8_t delay;
+ uint32_t quo_tt;
+ uint32_t counter;
+ uint32_t total_duration;
+ int64_t start_timestamp;
struct os_callout timer;
};
-extern u8_t transition_type, default_tt;
-extern u32_t *ptr_counter;
+extern uint8_t transition_type, default_tt;
+extern uint32_t *ptr_counter;
extern struct os_callout *ptr_timer;
extern struct transition lightness_transition, temp_transition;
@@ -64,15 +64,15 @@ extern struct os_callout dummy_timer;
void calculate_rt(struct transition *transition);
-void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay);
-void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay);
+void onoff_tt_values(struct generic_onoff_state *state, uint8_t tt, uint8_t delay);
+void level_tt_values(struct generic_level_state *state, uint8_t tt, uint8_t delay);
void light_lightness_actual_tt_values(struct light_lightness_state *state,
- u8_t tt, u8_t delay);
+ uint8_t tt, uint8_t delay);
void light_lightness_linear_tt_values(struct light_lightness_state *state,
- u8_t tt, u8_t delay);
-void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay);
+ uint8_t tt, uint8_t delay);
+void light_ctl_tt_values(struct light_ctl_state *state, uint8_t tt, uint8_t delay);
void light_ctl_temp_tt_values(struct light_ctl_state *state,
- u8_t tt, u8_t delay);
+ uint8_t tt, uint8_t delay);
void onoff_handler(struct generic_onoff_state *state);
void level_lightness_handler(struct generic_level_state *state);
diff --git a/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c
index 4ad23e1d..fcf80127 100644
--- a/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c
+++ b/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c
@@ -44,21 +44,21 @@ void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
payload_len);
}
-static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
console_printf("Model bound: remote addr 0x%04x key_idx 0x%04x model %p\n",
addr, key_idx, model);
}
-static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
console_printf("Model unbound: remote addr 0x%04x key_idx 0x%04x "
"model %p\n", addr, key_idx, model);
}
-static void invalid_bearer_cb(u8_t opcode)
+static void invalid_bearer_cb(uint8_t opcode)
{
console_printf("Invalid bearer: opcode 0x%02x\n", opcode);
}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c
index a4253ce6..440966ad 100644
--- a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c
+++ b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c
@@ -837,14 +837,6 @@ rx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
MODLOG_DFLT(INFO, "Data buf %s\n", data_buf ? "OK" : "NOK");
assert(data_buf != NULL);
- /* The first 2 bytes of data is the size of appended pattern data. */
- rc = os_mbuf_append(data_buf, (uint8_t[]) {data_len >> 8, data_len},
- 2);
- if (rc) {
- os_mbuf_free_chain(data_buf);
- assert(0);
- }
-
/* Fill mbuf with the pattern */
stress_fill_mbuf_with_pattern(data_buf, data_len);
@@ -852,8 +844,13 @@ rx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
rc = ble_l2cap_send(rx_stress_ctx->chan, data_buf);
MODLOG_DFLT(INFO, "Return code=%d\n", rc);
if (rc) {
- MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n");
- stalled = true;
+ if (rc == BLE_HS_ESTALLED) {
+ MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n");
+ stalled = true;
+ } else {
+ MODLOG_DFLT(INFO, "Sending data via L2CAP failed with error "
+ "code %d\n", rc);
+ }
}
MODLOG_DFLT(INFO, " %d, %d\n", ++send_cnt, data_len);
@@ -1365,7 +1362,7 @@ rx_stress_start(int test_num)
break;
case 10:
console_printf("Stress L2CAP send\033[0m\n");
- rc = ble_l2cap_create_server(1, STRESS_COC_MTU,
+ rc = ble_l2cap_create_server(TEST_PSM, STRESS_COC_MTU,
rx_stress_10_l2cap_event, NULL);
assert(rc == 0);
rx_stress_simple_adv(&rx_stress_adv_sets[10]);
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.c b/src/libs/mynewt-nimble/apps/blestress/src/stress.c
index 6f5badf0..1bdbafa9 100644
--- a/src/libs/mynewt-nimble/apps/blestress/src/stress.c
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.c
@@ -19,6 +19,8 @@
#include "stress.h"
+static struct os_callout stress_timer_callout;
+
void
com_stress_print_report(const struct com_stress_test_ctx *test_ctxs)
{
@@ -119,7 +121,7 @@ stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len)
rest = len % STRESS_PAT_LEN;
for (i = 0; i < mul; ++i) {
- rc = os_mbuf_append(om, &test_6_pattern[29], STRESS_PAT_LEN);
+ rc = os_mbuf_append(om, &test_6_pattern[0], STRESS_PAT_LEN);
if (rc) {
os_mbuf_free_chain(om);
@@ -127,7 +129,7 @@ stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len)
}
}
- rc = os_mbuf_append(om, &test_6_pattern[29], rest);
+ rc = os_mbuf_append(om, &test_6_pattern[0], rest);
if (rc) {
os_mbuf_free_chain(om);
@@ -176,6 +178,7 @@ void
stress_start_timer(uint32_t timeout_ms, os_event_fn *ev_cb)
{
int rc;
+
os_callout_stop(&stress_timer_callout);
os_callout_init(&stress_timer_callout, os_eventq_dflt_get(), ev_cb, NULL);
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.h b/src/libs/mynewt-nimble/apps/blestress/src/stress.h
index 91ab4f47..db4fbb36 100644
--- a/src/libs/mynewt-nimble/apps/blestress/src/stress.h
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.h
@@ -44,8 +44,9 @@ extern "C" {
#define STRESS_FIND_SRV 1
#define STRESS_FIND_CHR 2
#define STRESS_FIND_DSC 3
+/* L2CAP PSM */
+#define TEST_PSM 0x80
-struct os_callout stress_timer_callout;
struct stress_gatt_search_ctx;
typedef void stress_gatt_disc_end_fn(struct stress_gatt_search_ctx *search_ctx);
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c
index b73adc8a..4416c568 100644
--- a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c
+++ b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c
@@ -1127,7 +1127,7 @@ tx_stress_10_gap_event(struct ble_gap_event *event, void *arg)
assert(sdu_rx != NULL);
tx_stress_ctx->conn_handle = event->connect.conn_handle;
- rc = ble_l2cap_connect(event->connect.conn_handle, 1,
+ rc = ble_l2cap_connect(event->connect.conn_handle, TEST_PSM,
STRESS_COC_MTU, sdu_rx,
tx_stress_10_l2cap_event, NULL);
assert(rc == 0);
@@ -1292,17 +1292,16 @@ tx_stress_14_subs_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
assert(error->status == 0);
/* If the first subscription after finding cccd */
- if(arg == NULL) {
+ if (arg == NULL) {
return 0;
}
- sub = (bool*)arg;
+ sub = (bool *)arg;
/* Enable notifications */
- if(*sub == 0) {
+ if (*sub == 0) {
*sub = true;
- om = ble_hs_mbuf_from_flat(
- (uint8_t[]) {0x01, 0x00}, 2);
+ om = ble_hs_mbuf_from_flat((uint8_t[]) {0x01, 0x00}, 2);
tx_stress_ctx->begin_us = tx_stress_ctx->end_us;
@@ -1415,7 +1414,7 @@ tx_stress_14_gap_event(struct ble_gap_event *event, void *arg)
static int
tx_stress_15_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
- struct ble_gatt_attr *attr, void *arg)
+ struct ble_gatt_attr *attr, void *arg)
{
/* Disconnect */
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
@@ -1464,7 +1463,7 @@ tx_stress_15_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_DISCONNECT:
/* Perform use case specified number of times */
- if(tx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ if (tx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
tx_stress_on_test_finish(15);
return 0;
}
@@ -1473,7 +1472,7 @@ tx_stress_15_gap_event(struct ble_gap_event *event, void *arg)
return 0;
default:
- MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
return 0;
}
}
@@ -1607,7 +1606,8 @@ tx_stress_test_perform(int test_num)
}
static void
-tx_stress_read_command_cb(void) {
+tx_stress_read_command_cb(void)
+{
console_printf("Start testing\n");
os_sem_release(&tx_stress_main_sem);
}
@@ -1642,7 +1642,7 @@ tx_stress_main_task_fn(void *arg)
/* Wait for the scan to find the test. Then 1 token will be
* released allowing to pass through semaphore. */
os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
- if(tx_stress_ctx->scan_timeout) {
+ if (tx_stress_ctx->scan_timeout) {
break;
}
diff --git a/src/libs/mynewt-nimble/apps/btshell/src/cmd.c b/src/libs/mynewt-nimble/apps/btshell/src/cmd.c
index 2713443e..28aa87f2 100644
--- a/src/libs/mynewt-nimble/apps/btshell/src/cmd.c
+++ b/src/libs/mynewt-nimble/apps/btshell/src/cmd.c
@@ -2691,15 +2691,28 @@ cmd_security_unpair(int argc, char **argv)
{
ble_addr_t peer;
int rc;
+ int oldest;
rc = parse_arg_all(argc - 1, argv + 1);
if (rc != 0) {
return rc;
}
+ rc = parse_arg_bool_dflt("oldest", 0, &oldest);
+ if (rc != 0) {
+ console_printf("invalid 'oldest' parameter\n");
+ return rc;
+ }
+
+ if (oldest) {
+ rc = ble_gap_unpair_oldest_peer();
+ console_printf("Unpair oldest status: 0x%02x\n", rc);
+ return 0;
+ }
+
rc = parse_dev_addr("peer_", cmd_peer_addr_types, &peer);
if (rc != 0) {
- console_printf("invalid 'peer_addr' parameter\n");
+ console_printf("invalid peer address\n");
return rc;
}
@@ -2714,6 +2727,7 @@ cmd_security_unpair(int argc, char **argv)
#if MYNEWT_VAL(SHELL_CMD_HELP)
static const struct shell_param security_unpair_params[] = {
+ {"oldest", "usage: =[true|false], default: false"},
{"peer_addr_type", "usage: =[public|random|public_id|random_id], default: public"},
{"peer_addr", "usage: =[XX:XX:XX:XX:XX:XX]"},
{NULL, NULL}
diff --git a/src/libs/mynewt-nimble/apps/bttester/pkg.yml b/src/libs/mynewt-nimble/apps/bttester/pkg.yml
index 00e7a760..ba2b7fb1 100644
--- a/src/libs/mynewt-nimble/apps/bttester/pkg.yml
+++ b/src/libs/mynewt-nimble/apps/bttester/pkg.yml
@@ -37,7 +37,7 @@ pkg.deps:
- "@apache-mynewt-nimble/nimble/host/services/gap"
- "@apache-mynewt-nimble/nimble/host/services/gatt"
- "@apache-mynewt-nimble/nimble/host/services/dis"
- - "@apache-mynewt-nimble/nimble/host/store/ram"
+ - "@apache-mynewt-nimble/nimble/host/store/config"
- "@apache-mynewt-nimble/nimble/transport/ram"
- "@apache-mynewt-core/hw/drivers/uart"
- "@apache-mynewt-core/hw/drivers/rtt"
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester.c b/src/libs/mynewt-nimble/apps/bttester/src/bttester.c
index 54b14daa..5ddc2954 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/bttester.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester.c
@@ -44,16 +44,16 @@ static struct os_event bttester_ev[CMD_QUEUED];
struct btp_buf {
struct os_event *ev;
union {
- u8_t data[BTP_MTU];
+ uint8_t data[BTP_MTU];
struct btp_hdr hdr;
};
};
static struct btp_buf cmd_buf[CMD_QUEUED];
-static void supported_commands(u8_t *data, u16_t len)
+static void supported_commands(uint8_t *data, uint16_t len)
{
- u8_t buf[1];
+ uint8_t buf[1];
struct core_read_supported_commands_rp *rp = (void *) buf;
memset(buf, 0, sizeof(buf));
@@ -64,12 +64,12 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(buf, CORE_UNREGISTER_SERVICE);
tester_send(BTP_SERVICE_ID_CORE, CORE_READ_SUPPORTED_COMMANDS,
- BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
+ BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
-static void supported_services(u8_t *data, u16_t len)
+static void supported_services(uint8_t *data, uint16_t len)
{
- u8_t buf[1];
+ uint8_t buf[1];
struct core_read_supported_services_rp *rp = (void *) buf;
memset(buf, 0, sizeof(buf));
@@ -85,13 +85,13 @@ static void supported_services(u8_t *data, u16_t len)
#endif /* MYNEWT_VAL(BLE_MESH) */
tester_send(BTP_SERVICE_ID_CORE, CORE_READ_SUPPORTED_SERVICES,
- BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
+ BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
-static void register_service(u8_t *data, u16_t len)
+static void register_service(uint8_t *data, uint16_t len)
{
struct core_register_service_cmd *cmd = (void *) data;
- u8_t status;
+ uint8_t status;
switch (cmd->id) {
case BTP_SERVICE_ID_GAP:
@@ -124,10 +124,10 @@ rsp:
status);
}
-static void unregister_service(u8_t *data, u16_t len)
+static void unregister_service(uint8_t *data, uint16_t len)
{
struct core_unregister_service_cmd *cmd = (void *) data;
- u8_t status;
+ uint8_t status;
switch (cmd->id) {
case BTP_SERVICE_ID_GAP:
@@ -155,8 +155,8 @@ static void unregister_service(u8_t *data, u16_t len)
status);
}
-static void handle_core(u8_t opcode, u8_t index, u8_t *data,
- u16_t len)
+static void handle_core(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len)
{
if (index != BTP_INDEX_NONE) {
tester_rsp(BTP_SERVICE_ID_CORE, opcode, index,
@@ -186,7 +186,7 @@ static void handle_core(u8_t opcode, u8_t index, u8_t *data,
static void cmd_handler(struct os_event *ev)
{
- u16_t len;
+ uint16_t len;
struct btp_buf *cmd;
if (!ev || !ev->ev_arg) {
@@ -241,12 +241,12 @@ static void cmd_handler(struct os_event *ev)
os_eventq_put(&avail_queue, ev);
}
-static u8_t *recv_cb(u8_t *buf, size_t *off)
+static uint8_t *recv_cb(uint8_t *buf, size_t *off)
{
struct btp_hdr *cmd = (void *) buf;
struct os_event *new_ev;
struct btp_buf *new_buf, *old_buf;
- u16_t len;
+ uint16_t len;
if (*off < sizeof(*cmd)) {
return buf;
@@ -319,7 +319,7 @@ void tester_init(void)
NULL, 0);
}
-void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
+void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data,
size_t len)
{
struct btp_hdr msg;
@@ -329,7 +329,7 @@ void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
msg.index = index;
msg.len = len;
- bttester_pipe_send((u8_t *)&msg, sizeof(msg));
+ bttester_pipe_send((uint8_t *)&msg, sizeof(msg));
if (data && len) {
bttester_pipe_send(data, len);
}
@@ -344,7 +344,7 @@ void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
}
}
-void tester_send_buf(u8_t service, u8_t opcode, u8_t index,
+void tester_send_buf(uint8_t service, uint8_t opcode, uint8_t index,
struct os_mbuf *data)
{
struct btp_hdr msg;
@@ -354,13 +354,13 @@ void tester_send_buf(u8_t service, u8_t opcode, u8_t index,
msg.index = index;
msg.len = os_mbuf_len(data);
- bttester_pipe_send((u8_t *)&msg, sizeof(msg));
+ bttester_pipe_send((uint8_t *)&msg, sizeof(msg));
if (data && msg.len) {
bttester_pipe_send_buf(data);
}
}
-void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status)
+void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status)
{
struct btp_status s;
@@ -370,5 +370,5 @@ void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status)
}
s.code = status;
- tester_send(service, BTP_STATUS, index, (u8_t *) &s, sizeof(s));
+ tester_send(service, BTP_STATUS, index, (uint8_t *) &s, sizeof(s));
}
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester.h b/src/libs/mynewt-nimble/apps/bttester/src/bttester.h
index f4e66a6f..6761681e 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/bttester.h
+++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester.h
@@ -71,37 +71,37 @@
#define sys_cpu_to_le16 htole16
struct btp_hdr {
- u8_t service;
- u8_t opcode;
- u8_t index;
- u16_t len;
- u8_t data[0];
+ uint8_t service;
+ uint8_t opcode;
+ uint8_t index;
+ uint16_t len;
+ uint8_t data[0];
} __packed;
#define BTP_STATUS 0x00
struct btp_status {
- u8_t code;
+ uint8_t code;
} __packed;
/* Core Service */
#define CORE_READ_SUPPORTED_COMMANDS 0x01
struct core_read_supported_commands_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define CORE_READ_SUPPORTED_SERVICES 0x02
struct core_read_supported_services_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define CORE_REGISTER_SERVICE 0x03
struct core_register_service_cmd {
- u8_t id;
+ uint8_t id;
} __packed;
#define CORE_UNREGISTER_SERVICE 0x04
struct core_unregister_service_cmd {
- u8_t id;
+ uint8_t id;
} __packed;
/* events */
@@ -111,13 +111,13 @@ struct core_unregister_service_cmd {
/* commands */
#define GAP_READ_SUPPORTED_COMMANDS 0x01
struct gap_read_supported_commands_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define GAP_READ_CONTROLLER_INDEX_LIST 0x02
struct gap_read_controller_index_list_rp {
- u8_t num;
- u8_t index[0];
+ uint8_t num;
+ uint8_t index[0];
} __packed;
#define GAP_SETTINGS_POWERED 0
@@ -139,41 +139,41 @@ struct gap_read_controller_index_list_rp {
#define GAP_READ_CONTROLLER_INFO 0x03
struct gap_read_controller_info_rp {
- u8_t address[6];
- u32_t supported_settings;
- u32_t current_settings;
- u8_t cod[3];
- u8_t name[249];
- u8_t short_name[11];
+ uint8_t address[6];
+ uint32_t supported_settings;
+ uint32_t current_settings;
+ uint8_t cod[3];
+ uint8_t name[249];
+ uint8_t short_name[11];
} __packed;
#define GAP_RESET 0x04
struct gap_reset_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_SET_POWERED 0x05
struct gap_set_powered_cmd {
- u8_t powered;
+ uint8_t powered;
} __packed;
struct gap_set_powered_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_SET_CONNECTABLE 0x06
struct gap_set_connectable_cmd {
- u8_t connectable;
+ uint8_t connectable;
} __packed;
struct gap_set_connectable_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_SET_FAST_CONNECTABLE 0x07
struct gap_set_fast_connectable_cmd {
- u8_t fast_connectable;
+ uint8_t fast_connectable;
} __packed;
struct gap_set_fast_connectable_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_NON_DISCOVERABLE 0x00
@@ -182,34 +182,34 @@ struct gap_set_fast_connectable_rp {
#define GAP_SET_DISCOVERABLE 0x08
struct gap_set_discoverable_cmd {
- u8_t discoverable;
+ uint8_t discoverable;
} __packed;
struct gap_set_discoverable_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_SET_BONDABLE 0x09
struct gap_set_bondable_cmd {
- u8_t bondable;
+ uint8_t bondable;
} __packed;
struct gap_set_bondable_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_START_ADVERTISING 0x0a
struct gap_start_advertising_cmd {
- u8_t adv_data_len;
- u8_t scan_rsp_len;
- u8_t adv_data[0];
- u8_t scan_rsp[0];
+ uint8_t adv_data_len;
+ uint8_t scan_rsp_len;
+ uint8_t adv_data[0];
+ uint8_t scan_rsp[0];
} __packed;
struct gap_start_advertising_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_STOP_ADVERTISING 0x0b
struct gap_stop_advertising_rp {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_DISCOVERY_FLAG_LE 0x01
@@ -220,21 +220,21 @@ struct gap_stop_advertising_rp {
#define GAP_START_DISCOVERY 0x0c
struct gap_start_discovery_cmd {
- u8_t flags;
+ uint8_t flags;
} __packed;
#define GAP_STOP_DISCOVERY 0x0d
#define GAP_CONNECT 0x0e
struct gap_connect_cmd {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_DISCONNECT 0x0f
struct gap_disconnect_cmd {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_IO_CAP_DISPLAY_ONLY 0
@@ -245,85 +245,85 @@ struct gap_disconnect_cmd {
#define GAP_SET_IO_CAP 0x10
struct gap_set_io_cap_cmd {
- u8_t io_cap;
+ uint8_t io_cap;
} __packed;
#define GAP_PAIR 0x11
struct gap_pair_cmd {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_UNPAIR 0x12
struct gap_unpair_cmd {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_PASSKEY_ENTRY 0x13
struct gap_passkey_entry_cmd {
- u8_t address_type;
- u8_t address[6];
- u32_t passkey;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint32_t passkey;
} __packed;
#define GAP_PASSKEY_CONFIRM 0x14
struct gap_passkey_confirm_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t match;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t match;
} __packed;
#define GAP_START_DIRECT_ADV 0x15
struct gap_start_direct_adv_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t high_duty;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t high_duty;
} __packed;
#define GAP_CONN_PARAM_UPDATE 0x16
struct gap_conn_param_update_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t conn_itvl_min;
- u16_t conn_itvl_max;
- u16_t conn_latency;
- u16_t supervision_timeout;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t conn_itvl_min;
+ uint16_t conn_itvl_max;
+ uint16_t conn_latency;
+ uint16_t supervision_timeout;
} __packed;
#define GAP_PAIRING_CONSENT_RSP 0x17
struct gap_pairing_consent_rsp_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t consent;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t consent;
} __packed;
#define GAP_OOB_LEGACY_SET_DATA 0x18
struct gap_oob_legacy_set_data_cmd {
- u8_t oob_data[16];
+ uint8_t oob_data[16];
} __packed;
#define GAP_OOB_SC_GET_LOCAL_DATA 0x19
struct gap_oob_sc_get_local_data_rp {
- u8_t r[16];
- u8_t c[16];
+ uint8_t r[16];
+ uint8_t c[16];
} __packed;
#define GAP_OOB_SC_SET_REMOTE_DATA 0x1a
struct gap_oob_sc_set_remote_data_cmd {
- u8_t r[16];
- u8_t c[16];
+ uint8_t r[16];
+ uint8_t c[16];
} __packed;
#define GAP_SET_MITM 0x1b
struct gap_set_mitm_cmd {
- u8_t mitm;
+ uint8_t mitm;
} __packed;
/* events */
#define GAP_EV_NEW_SETTINGS 0x80
struct gap_new_settings_ev {
- u32_t current_settings;
+ uint32_t current_settings;
} __packed;
#define GAP_DEVICE_FOUND_FLAG_RSSI 0x01
@@ -332,84 +332,84 @@ struct gap_new_settings_ev {
#define GAP_EV_DEVICE_FOUND 0x81
struct gap_device_found_ev {
- u8_t address_type;
- u8_t address[6];
- s8_t rssi;
- u8_t flags;
- u16_t eir_data_len;
- u8_t eir_data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ int8_t rssi;
+ uint8_t flags;
+ uint16_t eir_data_len;
+ uint8_t eir_data[0];
} __packed;
#define GAP_EV_DEVICE_CONNECTED 0x82
struct gap_device_connected_ev {
- u8_t address_type;
- u8_t address[6];
- u16_t conn_itvl;
- u16_t conn_latency;
- u16_t supervision_timeout;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t conn_itvl;
+ uint16_t conn_latency;
+ uint16_t supervision_timeout;
} __packed;
#define GAP_EV_DEVICE_DISCONNECTED 0x83
struct gap_device_disconnected_ev {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_EV_PASSKEY_DISPLAY 0x84
struct gap_passkey_display_ev {
- u8_t address_type;
- u8_t address[6];
- u32_t passkey;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint32_t passkey;
} __packed;
#define GAP_EV_PASSKEY_ENTRY_REQ 0x85
struct gap_passkey_entry_req_ev {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define GAP_EV_PASSKEY_CONFIRM_REQ 0x86
struct gap_passkey_confirm_req_ev {
- u8_t address_type;
- u8_t address[6];
- u32_t passkey;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint32_t passkey;
} __packed;
#define GAP_EV_IDENTITY_RESOLVED 0x87
struct gap_identity_resolved_ev {
- u8_t address_type;
- u8_t address[6];
- u8_t identity_address_type;
- u8_t identity_address[6];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t identity_address_type;
+ uint8_t identity_address[6];
} __packed;
#define GAP_EV_CONN_PARAM_UPDATE 0x88
struct gap_conn_param_update_ev {
- u8_t address_type;
- u8_t address[6];
- u16_t conn_itvl;
- u16_t conn_latency;
- u16_t supervision_timeout;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t conn_itvl;
+ uint16_t conn_latency;
+ uint16_t supervision_timeout;
} __packed;
#define GAP_EV_SEC_LEVEL_CHANGED 0x89
struct gap_sec_level_changed_ev {
- u8_t address_type;
- u8_t address[6];
- u8_t level;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t level;
} __packed;
#define GAP_EV_PAIRING_CONSENT_REQ 0x8a
struct gap_pairing_consent_req_ev {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
/* GATT Service */
/* commands */
#define GATT_READ_SUPPORTED_COMMANDS 0x01
struct gatt_read_supported_commands_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define GATT_SERVICE_PRIMARY 0x00
@@ -417,320 +417,320 @@ struct gatt_read_supported_commands_rp {
#define GATT_ADD_SERVICE 0x02
struct gatt_add_service_cmd {
- u8_t type;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint8_t type;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_add_service_rp {
- u16_t svc_id;
+ uint16_t svc_id;
} __packed;
#define GATT_ADD_CHARACTERISTIC 0x03
struct gatt_add_characteristic_cmd {
- u16_t svc_id;
- u8_t properties;
- u8_t permissions;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint16_t svc_id;
+ uint8_t properties;
+ uint8_t permissions;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_add_characteristic_rp {
- u16_t char_id;
+ uint16_t char_id;
} __packed;
#define GATT_ADD_DESCRIPTOR 0x04
struct gatt_add_descriptor_cmd {
- u16_t char_id;
- u8_t permissions;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint16_t char_id;
+ uint8_t permissions;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_add_descriptor_rp {
- u16_t desc_id;
+ uint16_t desc_id;
} __packed;
#define GATT_ADD_INCLUDED_SERVICE 0x05
struct gatt_add_included_service_cmd {
- u16_t svc_id;
+ uint16_t svc_id;
} __packed;
struct gatt_add_included_service_rp {
- u16_t included_service_id;
+ uint16_t included_service_id;
} __packed;
#define GATT_SET_VALUE 0x06
struct gatt_set_value_cmd {
- u16_t attr_id;
- u16_t len;
- u8_t value[0];
+ uint16_t attr_id;
+ uint16_t len;
+ uint8_t value[0];
} __packed;
#define GATT_START_SERVER 0x07
struct gatt_start_server_rp {
- u16_t db_attr_off;
- u8_t db_attr_cnt;
+ uint16_t db_attr_off;
+ uint8_t db_attr_cnt;
} __packed;
#define GATT_SET_ENC_KEY_SIZE 0x09
struct gatt_set_enc_key_size_cmd {
- u16_t attr_id;
- u8_t key_size;
+ uint16_t attr_id;
+ uint8_t key_size;
} __packed;
/* Gatt Client */
struct gatt_service {
- u16_t start_handle;
- u16_t end_handle;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_included {
- u16_t included_handle;
+ uint16_t included_handle;
struct gatt_service service;
} __packed;
struct gatt_characteristic {
- u16_t characteristic_handle;
- u16_t value_handle;
- u8_t properties;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint16_t characteristic_handle;
+ uint16_t value_handle;
+ uint8_t properties;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_descriptor {
- u16_t descriptor_handle;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint16_t descriptor_handle;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
#define GATT_EXCHANGE_MTU 0x0a
#define GATT_DISC_ALL_PRIM_SVCS 0x0b
struct gatt_disc_all_prim_svcs_cmd {
- u8_t address_type;
- u8_t address[6];
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
struct gatt_disc_all_prim_svcs_rp {
- u8_t services_count;
+ uint8_t services_count;
struct gatt_service services[0];
} __packed;
#define GATT_DISC_PRIM_UUID 0x0c
struct gatt_disc_prim_uuid_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t uuid_length;
- u8_t uuid[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
struct gatt_disc_prim_uuid_rp {
- u8_t services_count;
+ uint8_t services_count;
struct gatt_service services[0];
} __packed;
#define GATT_FIND_INCLUDED 0x0d
struct gatt_find_included_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t start_handle;
- u16_t end_handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t start_handle;
+ uint16_t end_handle;
} __packed;
struct gatt_find_included_rp {
- u8_t services_count;
+ uint8_t services_count;
struct gatt_included included[0];
} __packed;
#define GATT_DISC_ALL_CHRC 0x0e
struct gatt_disc_all_chrc_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t start_handle;
- u16_t end_handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t start_handle;
+ uint16_t end_handle;
} __packed;
struct gatt_disc_chrc_rp {
- u8_t characteristics_count;
+ uint8_t characteristics_count;
struct gatt_characteristic characteristics[0];
} __packed;
#define GATT_DISC_CHRC_UUID 0x0f
struct gatt_disc_chrc_uuid_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t start_handle;
- u16_t end_handle;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
#define GATT_DISC_ALL_DESC 0x10
struct gatt_disc_all_desc_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t start_handle;
- u16_t end_handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t start_handle;
+ uint16_t end_handle;
} __packed;
struct gatt_disc_all_desc_rp {
- u8_t descriptors_count;
+ uint8_t descriptors_count;
struct gatt_descriptor descriptors[0];
} __packed;
#define GATT_READ 0x11
struct gatt_read_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
} __packed;
struct gatt_read_rp {
- u8_t att_response;
- u16_t data_length;
- u8_t data[0];
+ uint8_t att_response;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_READ_UUID 0x12
struct gatt_read_uuid_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t start_handle;
- u16_t end_handle;
- u8_t uuid_length;
- u8_t uuid[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t uuid_length;
+ uint8_t uuid[0];
} __packed;
#define GATT_READ_LONG 0x13
struct gatt_read_long_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t offset;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t offset;
} __packed;
#define GATT_READ_MULTIPLE 0x14
struct gatt_read_multiple_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t handles_count;
- u16_t handles[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t handles_count;
+ uint16_t handles[0];
} __packed;
#define GATT_WRITE_WITHOUT_RSP 0x15
struct gatt_write_without_rsp_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_SIGNED_WRITE_WITHOUT_RSP 0x16
struct gatt_signed_write_without_rsp_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_WRITE 0x17
struct gatt_write_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_WRITE_LONG 0x18
struct gatt_write_long_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t offset;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t offset;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_RELIABLE_WRITE 0x19
struct gatt_reliable_write_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
- u16_t offset;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
+ uint16_t offset;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_CFG_NOTIFY 0x1a
#define GATT_CFG_INDICATE 0x1b
struct gatt_cfg_notify_cmd {
- u8_t address_type;
- u8_t address[6];
- u8_t enable;
- u16_t ccc_handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t enable;
+ uint16_t ccc_handle;
} __packed;
#define GATT_GET_ATTRIBUTES 0x1c
struct gatt_get_attributes_cmd {
- u16_t start_handle;
- u16_t end_handle;
- u8_t type_length;
- u8_t type[0];
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t type_length;
+ uint8_t type[0];
} __packed;
struct gatt_get_attributes_rp {
- u8_t attrs_count;
- u8_t attrs[0];
+ uint8_t attrs_count;
+ uint8_t attrs[0];
} __packed;
struct gatt_attr {
- u16_t handle;
- u8_t permission;
- u8_t type_length;
- u8_t type[0];
+ uint16_t handle;
+ uint8_t permission;
+ uint8_t type_length;
+ uint8_t type[0];
} __packed;
#define GATT_GET_ATTRIBUTE_VALUE 0x1d
struct gatt_get_attribute_value_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t handle;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t handle;
} __packed;
struct gatt_get_attribute_value_rp {
- u8_t att_response;
- u16_t value_length;
- u8_t value[0];
+ uint8_t att_response;
+ uint16_t value_length;
+ uint8_t value[0];
} __packed;
#define GATT_CHANGE_DATABASE 0x1e
struct gatt_change_database {
- u16_t start_handle;
- u16_t end_handle;
- u8_t visibility;
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint8_t visibility;
} __packed;
/* GATT events */
#define GATT_EV_NOTIFICATION 0x80
struct gatt_notification_ev {
- u8_t address_type;
- u8_t address[6];
- u8_t type;
- u16_t handle;
- u16_t data_length;
- u8_t data[0];
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t type;
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
#define GATT_EV_ATTR_VALUE_CHANGED 0x81
struct gatt_attr_value_changed_ev {
- u16_t handle;
- u16_t data_length;
- u8_t data[0];
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
} __packed;
-static inline void tester_set_bit(u8_t *addr, unsigned int bit)
+static inline void tester_set_bit(uint8_t *addr, unsigned int bit)
{
- u8_t *p = addr + (bit / 8);
+ uint8_t *p = addr + (bit / 8);
*p |= BIT(bit % 8);
}
-static inline u8_t tester_test_bit(const u8_t *addr, unsigned int bit)
+static inline uint8_t tester_test_bit(const uint8_t *addr, unsigned int bit)
{
- const u8_t *p = addr + (bit / 8);
+ const uint8_t *p = addr + (bit / 8);
return *p & BIT(bit % 8);
}
@@ -739,30 +739,33 @@ static inline u8_t tester_test_bit(const u8_t *addr, unsigned int bit)
/* commands */
#define L2CAP_READ_SUPPORTED_COMMANDS 0x01
struct l2cap_read_supported_commands_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define L2CAP_CONNECT 0x02
struct l2cap_connect_cmd {
- u8_t address_type;
- u8_t address[6];
- u16_t psm;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t psm;
+ uint16_t mtu;
+ uint8_t num;
} __packed;
struct l2cap_connect_rp {
- u8_t chan_id;
+ uint8_t num;
+ uint8_t chan_ids[0];
} __packed;
#define L2CAP_DISCONNECT 0x03
struct l2cap_disconnect_cmd {
- u8_t chan_id;
+ uint8_t chan_id;
} __packed;
#define L2CAP_SEND_DATA 0x04
struct l2cap_send_data_cmd {
- u8_t chan_id;
- u16_t data_len;
- u8_t data[];
+ uint8_t chan_id;
+ uint16_t data_len;
+ uint8_t data[];
} __packed;
#define L2CAP_TRANSPORT_BREDR 0x00
@@ -770,54 +773,78 @@ struct l2cap_send_data_cmd {
#define L2CAP_LISTEN 0x05
struct l2cap_listen_cmd {
- u16_t psm;
- u8_t transport;
+ uint16_t psm;
+ uint8_t transport;
+ uint16_t mtu;
+ uint16_t response;
} __packed;
#define L2CAP_ACCEPT_CONNECTION 0x06
struct l2cap_accept_connection_cmd {
- u8_t chan_id;
- u16_t result;
+ uint8_t chan_id;
+ uint16_t result;
+} __packed;
+
+#define L2CAP_RECONFIGURE 0x07
+struct l2cap_reconfigure_cmd {
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t mtu;
+ uint8_t num;
+ uint8_t idxs[];
} __packed;
/* events */
#define L2CAP_EV_CONNECTION_REQ 0x80
struct l2cap_connection_req_ev {
- u8_t chan_id;
- u16_t psm;
- u8_t address_type;
- u8_t address[6];
+ uint8_t chan_id;
+ uint16_t psm;
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define L2CAP_EV_CONNECTED 0x81
struct l2cap_connected_ev {
- u8_t chan_id;
- u16_t psm;
- u8_t address_type;
- u8_t address[6];
+ uint8_t chan_id;
+ uint16_t psm;
+ uint16_t peer_mtu;
+ uint16_t peer_mps;
+ uint16_t our_mtu;
+ uint16_t our_mps;
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define L2CAP_EV_DISCONNECTED 0x82
struct l2cap_disconnected_ev {
- u16_t result;
- u8_t chan_id;
- u16_t psm;
- u8_t address_type;
- u8_t address[6];
+ uint16_t result;
+ uint8_t chan_id;
+ uint16_t psm;
+ uint8_t address_type;
+ uint8_t address[6];
} __packed;
#define L2CAP_EV_DATA_RECEIVED 0x83
struct l2cap_data_received_ev {
- u8_t chan_id;
- u16_t data_length;
- u8_t data[0];
+ uint8_t chan_id;
+ uint16_t data_length;
+ uint8_t data[0];
+} __packed;
+
+#define L2CAP_EV_RECONFIGURED 0x84
+struct l2cap_reconfigured_ev {
+ uint8_t chan_id;
+ uint16_t peer_mtu;
+ uint16_t peer_mps;
+ uint16_t our_mtu;
+ uint16_t our_mps;
} __packed;
/* MESH Service */
/* commands */
#define MESH_READ_SUPPORTED_COMMANDS 0x01
struct mesh_read_supported_commands_rp {
- u8_t data[0];
+ uint8_t data[0];
} __packed;
#define MESH_OUT_BLINK BIT(0)
@@ -833,88 +860,88 @@ struct mesh_read_supported_commands_rp {
#define MESH_CONFIG_PROVISIONING 0x02
struct mesh_config_provisioning_cmd {
- u8_t uuid[16];
- u8_t static_auth[16];
- u8_t out_size;
- u16_t out_actions;
- u8_t in_size;
- u16_t in_actions;
+ uint8_t uuid[16];
+ uint8_t static_auth[16];
+ uint8_t out_size;
+ uint16_t out_actions;
+ uint8_t in_size;
+ uint16_t in_actions;
} __packed;
#define MESH_PROVISION_NODE 0x03
struct mesh_provision_node_cmd {
- u8_t net_key[16];
- u16_t net_key_idx;
- u8_t flags;
- u32_t iv_index;
- u32_t seq_num;
- u16_t addr;
- u8_t dev_key[16];
+ uint8_t net_key[16];
+ uint16_t net_key_idx;
+ uint8_t flags;
+ uint32_t iv_index;
+ uint32_t seq_num;
+ uint16_t addr;
+ uint8_t dev_key[16];
} __packed;
#define MESH_INIT 0x04
#define MESH_RESET 0x05
#define MESH_INPUT_NUMBER 0x06
struct mesh_input_number_cmd {
- u32_t number;
+ uint32_t number;
} __packed;
#define MESH_INPUT_STRING 0x07
struct mesh_input_string_cmd {
- u8_t string_len;
- u8_t string[0];
+ uint8_t string_len;
+ uint8_t string[0];
} __packed;
#define MESH_IVU_TEST_MODE 0x08
struct mesh_ivu_test_mode_cmd {
- u8_t enable;
+ uint8_t enable;
} __packed;
#define MESH_IVU_TOGGLE_STATE 0x09
#define MESH_NET_SEND 0x0a
struct mesh_net_send_cmd {
- u8_t ttl;
- u16_t src;
- u16_t dst;
- u8_t payload_len;
- u8_t payload[0];
+ uint8_t ttl;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
} __packed;
#define MESH_HEALTH_GENERATE_FAULTS 0x0b
struct mesh_health_generate_faults_rp {
- u8_t test_id;
- u8_t cur_faults_count;
- u8_t reg_faults_count;
- u8_t current_faults[0];
- u8_t registered_faults[0];
+ uint8_t test_id;
+ uint8_t cur_faults_count;
+ uint8_t reg_faults_count;
+ uint8_t current_faults[0];
+ uint8_t registered_faults[0];
} __packed;
#define MESH_HEALTH_CLEAR_FAULTS 0x0c
#define MESH_LPN 0x0d
struct mesh_lpn_set_cmd {
- u8_t enable;
+ uint8_t enable;
} __packed;
#define MESH_LPN_POLL 0x0e
#define MESH_MODEL_SEND 0x0f
struct mesh_model_send_cmd {
- u16_t src;
- u16_t dst;
- u8_t payload_len;
- u8_t payload[0];
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
} __packed;
#define MESH_LPN_SUBSCRIBE 0x10
struct mesh_lpn_subscribe_cmd {
- u16_t address;
+ uint16_t address;
} __packed;
#define MESH_LPN_UNSUBSCRIBE 0x11
struct mesh_lpn_unsubscribe_cmd {
- u16_t address;
+ uint16_t address;
} __packed;
#define MESH_RPL_CLEAR 0x12
@@ -923,20 +950,20 @@ struct mesh_lpn_unsubscribe_cmd {
/* events */
#define MESH_EV_OUT_NUMBER_ACTION 0x80
struct mesh_out_number_action_ev {
- u16_t action;
- u32_t number;
+ uint16_t action;
+ uint32_t number;
} __packed;
#define MESH_EV_OUT_STRING_ACTION 0x81
struct mesh_out_string_action_ev {
- u8_t string_len;
- u8_t string[0];
+ uint8_t string_len;
+ uint8_t string[0];
} __packed;
#define MESH_EV_IN_ACTION 0x82
struct mesh_in_action_ev {
- u16_t action;
- u8_t size;
+ uint16_t action;
+ uint8_t size;
} __packed;
#define MESH_EV_PROVISIONED 0x83
@@ -945,63 +972,63 @@ struct mesh_in_action_ev {
#define MESH_PROV_BEARER_PB_GATT 0x01
#define MESH_EV_PROV_LINK_OPEN 0x84
struct mesh_prov_link_open_ev {
- u8_t bearer;
+ uint8_t bearer;
} __packed;
#define MESH_EV_PROV_LINK_CLOSED 0x85
struct mesh_prov_link_closed_ev {
- u8_t bearer;
+ uint8_t bearer;
} __packed;
#define MESH_EV_NET_RECV 0x86
struct mesh_net_recv_ev {
- u8_t ttl;
- u8_t ctl;
- u16_t src;
- u16_t dst;
- u8_t payload_len;
- u8_t payload[0];
+ uint8_t ttl;
+ uint8_t ctl;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
} __packed;
#define MESH_EV_INVALID_BEARER 0x87
struct mesh_invalid_bearer_ev {
- u8_t opcode;
+ uint8_t opcode;
} __packed;
#define MESH_EV_INCOMP_TIMER_EXP 0x88
void tester_init(void);
-void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status);
-void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
+void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status);
+void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data,
size_t len);
-void tester_send_buf(u8_t service, u8_t opcode, u8_t index,
+void tester_send_buf(uint8_t service, uint8_t opcode, uint8_t index,
struct os_mbuf *buf);
-u8_t tester_init_gap(void);
-u8_t tester_unregister_gap(void);
-void tester_handle_gap(u8_t opcode, u8_t index, u8_t *data,
- u16_t len);
-u8_t tester_init_gatt(void);
-u8_t tester_unregister_gatt(void);
-void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
- u16_t len);
-int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
- u8_t indication, struct os_mbuf *om);
-int tester_gatt_subscribe_ev(u16_t conn_handle, u16_t attr_handle, u8_t reason,
- u8_t prev_notify, u8_t cur_notify,
- u8_t prev_indicate, u8_t cur_indicate);
+uint8_t tester_init_gap(void);
+uint8_t tester_unregister_gap(void);
+void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len);
+uint8_t tester_init_gatt(void);
+uint8_t tester_unregister_gatt(void);
+void tester_handle_gatt(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len);
+int tester_gatt_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t indication, struct os_mbuf *om);
+int tester_gatt_subscribe_ev(uint16_t conn_handle, uint16_t attr_handle, uint8_t reason,
+ uint8_t prev_notify, uint8_t cur_notify,
+ uint8_t prev_indicate, uint8_t cur_indicate);
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
-u8_t tester_init_l2cap(void);
-u8_t tester_unregister_l2cap(void);
-void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
- u16_t len);
+uint8_t tester_init_l2cap(void);
+uint8_t tester_unregister_l2cap(void);
+void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len);
#endif
#if MYNEWT_VAL(BLE_MESH)
-u8_t tester_init_mesh(void);
-u8_t tester_unregister_mesh(void);
-void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len);
+uint8_t tester_init_mesh(void);
+uint8_t tester_unregister_mesh(void);
+void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len);
#endif /* MYNEWT_VAL(BLE_MESH) */
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h b/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h
index c54d42de..64b63cd6 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h
+++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h
@@ -27,9 +27,9 @@
extern "C" {
#endif
-typedef u8_t *(*bttester_pipe_recv_cb)(u8_t *buf, size_t *off);
-void bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb);
-int bttester_pipe_send(const u8_t *data, int len);
+typedef uint8_t *(*bttester_pipe_recv_cb)(uint8_t *buf, size_t *off);
+void bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb);
+int bttester_pipe_send(const uint8_t *data, int len);
int bttester_pipe_send_buf(struct os_mbuf *buf);
int bttester_pipe_init(void);
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/gap.c b/src/libs/mynewt-nimble/apps/bttester/src/gap.c
index 9d6de043..acac9989 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/gap.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/gap.c
@@ -51,7 +51,7 @@ static struct ble_sm_sc_oob_data oob_data_local;
static struct ble_sm_sc_oob_data oob_data_remote;
static uint16_t current_settings;
-u8_t own_addr_type;
+uint8_t own_addr_type;
static ble_addr_t peer_id_addr;
static ble_addr_t peer_ota_addr;
static bool encrypted = false;
@@ -109,9 +109,9 @@ static int gap_conn_find_by_addr(const ble_addr_t *dev_addr,
static int gap_event_cb(struct ble_gap_event *event, void *arg);
-static void supported_commands(u8_t *data, u16_t len)
+static void supported_commands(uint8_t *data, uint16_t len)
{
- u8_t cmds[3];
+ uint8_t cmds[3];
struct gap_read_supported_commands_rp *rp = (void *) &cmds;
SYS_LOG_DBG("");
@@ -143,13 +143,13 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, GAP_SET_MITM);
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_SUPPORTED_COMMANDS,
- CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
+ CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
-static void controller_index_list(u8_t *data, u16_t len)
+static void controller_index_list(uint8_t *data, uint16_t len)
{
struct gap_read_controller_index_list_rp *rp;
- u8_t buf[sizeof(*rp) + 1];
+ uint8_t buf[sizeof(*rp) + 1];
SYS_LOG_DBG("");
@@ -159,7 +159,7 @@ static void controller_index_list(u8_t *data, u16_t len)
rp->index[0] = CONTROLLER_INDEX;
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INDEX_LIST,
- BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
+ BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
static int check_pub_addr_unassigned(void)
@@ -174,10 +174,10 @@ static int check_pub_addr_unassigned(void)
#endif
}
-static void controller_info(u8_t *data, u16_t len)
+static void controller_info(uint8_t *data, uint16_t len)
{
struct gap_read_controller_info_rp rp;
- u32_t supported_settings = 0;
+ uint32_t supported_settings = 0;
ble_addr_t addr;
int rc;
@@ -240,7 +240,7 @@ static void controller_info(u8_t *data, u16_t len)
memcpy(rp.name, CONTROLLER_NAME, sizeof(CONTROLLER_NAME));
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INFO,
- CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
+ CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
}
static struct ble_gap_adv_params adv_params = {
@@ -248,7 +248,7 @@ static struct ble_gap_adv_params adv_params = {
.disc_mode = BLE_GAP_DISC_MODE_NON,
};
-static void set_connectable(u8_t *data, u16_t len)
+static void set_connectable(uint8_t *data, uint16_t len)
{
const struct gap_set_connectable_cmd *cmd = (void *) data;
struct gap_set_connectable_rp rp;
@@ -266,12 +266,12 @@ static void set_connectable(u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_CONNECTABLE, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
}
-static u8_t ad_flags = BLE_HS_ADV_F_BREDR_UNSUP;
+static uint8_t ad_flags = BLE_HS_ADV_F_BREDR_UNSUP;
-static void set_discoverable(u8_t *data, u16_t len)
+static void set_discoverable(uint8_t *data, uint16_t len)
{
const struct gap_set_discoverable_cmd *cmd = (void *) data;
struct gap_set_discoverable_rp rp;
@@ -305,10 +305,10 @@ static void set_discoverable(u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_DISCOVERABLE, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
}
-static void set_bondable(const u8_t *data, u16_t len)
+static void set_bondable(const uint8_t *data, uint16_t len)
{
const struct gap_set_bondable_cmd *cmd = (void *) data;
struct gap_set_bondable_rp rp;
@@ -325,7 +325,7 @@ static void set_bondable(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_BONDABLE, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
}
static struct bt_data ad[10] = {
@@ -334,7 +334,7 @@ static struct bt_data ad[10] = {
static struct bt_data sd[10];
static int set_ad(const struct bt_data *ad, size_t ad_len,
- u8_t *buf, u8_t *buf_len)
+ uint8_t *buf, uint8_t *buf_len)
{
int i;
@@ -350,14 +350,14 @@ static int set_ad(const struct bt_data *ad, size_t ad_len,
return 0;
}
-static void start_advertising(const u8_t *data, u16_t len)
+static void start_advertising(const uint8_t *data, uint16_t len)
{
const struct gap_start_advertising_cmd *cmd = (void *) data;
struct gap_start_advertising_rp rp;
int32_t duration_ms = BLE_HS_FOREVER;
uint8_t buf[BLE_HS_ADV_MAX_SZ];
uint8_t buf_len = 0;
- u8_t adv_len, sd_len;
+ uint8_t adv_len, sd_len;
int err;
int i;
@@ -429,14 +429,14 @@ static void start_advertising(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
return;
fail:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX,
BTP_STATUS_FAILED);
}
-static void stop_advertising(const u8_t *data, u16_t len)
+static void stop_advertising(const uint8_t *data, uint16_t len)
{
struct gap_stop_advertising_rp rp;
@@ -452,12 +452,12 @@ static void stop_advertising(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_STOP_ADVERTISING, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
}
-static u8_t get_ad_flags(const u8_t *data, u8_t data_len)
+static uint8_t get_ad_flags(const uint8_t *data, uint8_t data_len)
{
- u8_t len, i;
+ uint8_t len, i;
/* Parse advertisement to get flags */
for (i = 0; i < data_len; i += len - 1) {
@@ -482,11 +482,11 @@ static u8_t get_ad_flags(const u8_t *data, u8_t data_len)
return 0;
}
-static u8_t discovery_flags;
+static uint8_t discovery_flags;
static struct os_mbuf *adv_buf;
-static void store_adv(const ble_addr_t *addr, s8_t rssi,
- const u8_t *data, u8_t len)
+static void store_adv(const ble_addr_t *addr, int8_t rssi,
+ const uint8_t *data, uint8_t len)
{
struct gap_device_found_ev *ev;
@@ -503,8 +503,8 @@ static void store_adv(const ble_addr_t *addr, s8_t rssi,
memcpy(net_buf_simple_add(adv_buf, len), data, len);
}
-static void device_found(ble_addr_t *addr, s8_t rssi, u8_t evtype,
- const u8_t *data, u8_t len)
+static void device_found(ble_addr_t *addr, int8_t rssi, uint8_t evtype,
+ const uint8_t *data, uint8_t len)
{
struct gap_device_found_ev *ev;
ble_addr_t a;
@@ -512,7 +512,7 @@ static void device_found(ble_addr_t *addr, s8_t rssi, u8_t evtype,
/* if General/Limited Discovery - parse Advertising data to get flags */
if (!(discovery_flags & GAP_DISCOVERY_FLAG_LE_OBSERVE) &&
(evtype != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
- u8_t flags = get_ad_flags(data, len);
+ uint8_t flags = get_ad_flags(data, len);
/* ignore non-discoverable devices */
if (!(flags & BLE_AD_DISCOV_MASK)) {
@@ -593,11 +593,11 @@ static int discovery_cb(struct ble_gap_event *event, void *arg)
return 0;
}
-static void start_discovery(const u8_t *data, u16_t len)
+static void start_discovery(const uint8_t *data, uint16_t len)
{
const struct gap_start_discovery_cmd *cmd = (void *) data;
struct ble_gap_disc_params params = {0};
- u8_t status;
+ uint8_t status;
SYS_LOG_DBG("");
@@ -626,9 +626,9 @@ reply:
status);
}
-static void stop_discovery(const u8_t *data, u16_t len)
+static void stop_discovery(const uint8_t *data, uint16_t len)
{
- u8_t status = BTP_STATUS_SUCCESS;
+ uint8_t status = BTP_STATUS_SUCCESS;
SYS_LOG_DBG("");
@@ -680,13 +680,13 @@ static void device_connected_ev_send(struct os_event *ev)
}
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
- CONTROLLER_INDEX, (u8_t *) &connected_ev,
+ CONTROLLER_INDEX, (uint8_t *) &connected_ev,
sizeof(connected_ev));
periph_privacy(desc);
}
-static void le_connected(u16_t conn_handle, int status)
+static void le_connected(uint16_t conn_handle, int status)
{
struct ble_gap_conn_desc desc;
ble_addr_t *addr;
@@ -720,7 +720,7 @@ static void le_connected(u16_t conn_handle, int status)
CONNECTED_EV_DELAY_MS(desc.conn_itvl)));
#else
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
- CONTROLLER_INDEX, (u8_t *) &connected_ev,
+ CONTROLLER_INDEX, (uint8_t *) &connected_ev,
sizeof(connected_ev));
#endif
}
@@ -763,10 +763,10 @@ static void le_disconnected(struct ble_gap_conn_desc *conn, int reason)
ev.address_type = addr->type;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_DISCONNECTED,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
-static void auth_passkey_oob(u16_t conn_handle)
+static void auth_passkey_oob(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
@@ -786,7 +786,7 @@ static void auth_passkey_oob(u16_t conn_handle)
assert(rc == 0);
}
-static void auth_passkey_display(u16_t conn_handle, unsigned int passkey)
+static void auth_passkey_display(uint16_t conn_handle, unsigned int passkey)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_display_ev ev;
@@ -817,10 +817,10 @@ static void auth_passkey_display(u16_t conn_handle, unsigned int passkey)
ev.passkey = sys_cpu_to_le32(pk.passkey);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_DISPLAY,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
-static void auth_passkey_entry(u16_t conn_handle)
+static void auth_passkey_entry(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_entry_req_ev ev;
@@ -840,10 +840,10 @@ static void auth_passkey_entry(u16_t conn_handle)
ev.address_type = addr->type;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_ENTRY_REQ,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
-static void auth_passkey_numcmp(u16_t conn_handle, unsigned int passkey)
+static void auth_passkey_numcmp(uint16_t conn_handle, unsigned int passkey)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_confirm_req_ev ev;
@@ -864,10 +864,10 @@ static void auth_passkey_numcmp(u16_t conn_handle, unsigned int passkey)
ev.passkey = sys_cpu_to_le32(passkey);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_CONFIRM_REQ,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
-static void auth_passkey_oob_sc(u16_t conn_handle)
+static void auth_passkey_oob_sc(uint16_t conn_handle)
{
int rc;
struct ble_sm_io pk;
@@ -889,7 +889,7 @@ static void auth_passkey_oob_sc(u16_t conn_handle)
}
}
-static void le_passkey_action(u16_t conn_handle,
+static void le_passkey_action(uint16_t conn_handle,
struct ble_gap_passkey_params *params)
{
SYS_LOG_DBG("");
@@ -917,7 +917,7 @@ static void le_passkey_action(u16_t conn_handle,
}
}
-static void le_identity_resolved(u16_t conn_handle)
+static void le_identity_resolved(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct gap_identity_resolved_ev ev;
@@ -941,7 +941,7 @@ static void le_identity_resolved(u16_t conn_handle)
sizeof(ev.identity_address));
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_IDENTITY_RESOLVED,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void le_conn_param_update(struct ble_gap_conn_desc *desc)
@@ -958,7 +958,7 @@ static void le_conn_param_update(struct ble_gap_conn_desc *desc)
ev.supervision_timeout = desc->supervision_timeout;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_CONN_PARAM_UPDATE,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void le_encryption_changed(struct ble_gap_conn_desc *desc)
@@ -986,7 +986,7 @@ static void le_encryption_changed(struct ble_gap_conn_desc *desc)
}
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_SEC_LEVEL_CHANGED,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void print_bytes(const uint8_t *bytes, int len)
@@ -1055,7 +1055,7 @@ static void adv_complete(void)
ev.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_NEW_SETTINGS, CONTROLLER_INDEX,
- (u8_t *) &ev, sizeof(ev));
+ (uint8_t *) &ev, sizeof(ev));
}
static int gap_event_cb(struct ble_gap_event *event, void *arg)
@@ -1197,9 +1197,9 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
-static void connect(const u8_t *data, u16_t len)
+static void connect(const uint8_t *data, uint16_t len)
{
- u8_t status = BTP_STATUS_SUCCESS;
+ uint8_t status = BTP_STATUS_SUCCESS;
SYS_LOG_DBG("");
@@ -1211,10 +1211,10 @@ static void connect(const u8_t *data, u16_t len)
tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status);
}
-static void disconnect(const u8_t *data, u16_t len)
+static void disconnect(const uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc desc;
- u8_t status;
+ uint8_t status;
int rc;
SYS_LOG_DBG("");
@@ -1236,10 +1236,10 @@ rsp:
status);
}
-static void set_io_cap(const u8_t *data, u16_t len)
+static void set_io_cap(const uint8_t *data, uint16_t len)
{
const struct gap_set_io_cap_cmd *cmd = (void *) data;
- u8_t status;
+ uint8_t status;
SYS_LOG_DBG("");
@@ -1276,10 +1276,10 @@ rsp:
status);
}
-static void pair(const u8_t *data, u16_t len)
+static void pair(const uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc desc;
- u8_t status;
+ uint8_t status;
int rc;
SYS_LOG_DBG("");
@@ -1301,9 +1301,9 @@ rsp:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status);
}
-static void unpair(const u8_t *data, u16_t len)
+static void unpair(const uint8_t *data, uint16_t len)
{
- u8_t status;
+ uint8_t status;
int err;
SYS_LOG_DBG("");
@@ -1313,12 +1313,12 @@ static void unpair(const u8_t *data, u16_t len)
tester_rsp(BTP_SERVICE_ID_GAP, GAP_UNPAIR, CONTROLLER_INDEX, status);
}
-static void passkey_entry(const u8_t *data, u16_t len)
+static void passkey_entry(const uint8_t *data, uint16_t len)
{
const struct gap_passkey_entry_cmd *cmd = (void *) data;
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
- u8_t status;
+ uint8_t status;
int rc;
SYS_LOG_DBG("");
@@ -1345,12 +1345,12 @@ rsp:
status);
}
-static void passkey_confirm(const u8_t *data, u16_t len)
+static void passkey_confirm(const uint8_t *data, uint16_t len)
{
const struct gap_passkey_confirm_cmd *cmd = (void *) data;
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
- u8_t status;
+ uint8_t status;
int rc;
SYS_LOG_DBG("");
@@ -1378,7 +1378,7 @@ rsp:
status);
}
-static void start_direct_adv(const u8_t *data, u16_t len)
+static void start_direct_adv(const uint8_t *data, uint16_t len)
{
const struct gap_start_direct_adv_cmd *cmd = (void *) data;
struct gap_start_advertising_rp rp;
@@ -1403,7 +1403,7 @@ static void start_direct_adv(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
return;
fail:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
@@ -1416,7 +1416,7 @@ static void conn_param_update_cb(uint16_t conn_handle, int status, void *arg)
conn_handle, status);
}
-static int conn_param_update_slave(u16_t conn_handle,
+static int conn_param_update_slave(uint16_t conn_handle,
const struct gap_conn_param_update_cmd *cmd)
{
int rc;
@@ -1436,7 +1436,7 @@ static int conn_param_update_slave(u16_t conn_handle,
return 0;
}
-static int conn_param_update_master(u16_t conn_handle,
+static int conn_param_update_master(uint16_t conn_handle,
const struct gap_conn_param_update_cmd *cmd)
{
int rc;
@@ -1489,7 +1489,7 @@ rsp:
SYS_LOG_ERR("Conn param update fail; rc=%d", rc);
}
-static void conn_param_update_async(const u8_t *data, u16_t len)
+static void conn_param_update_async(const uint8_t *data, uint16_t len)
{
const struct gap_conn_param_update_cmd *cmd = (void *) data;
update_params = *cmd;
@@ -1500,7 +1500,7 @@ static void conn_param_update_async(const u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
-static void oob_legacy_set_data(const u8_t *data, u16_t len)
+static void oob_legacy_set_data(const uint8_t *data, uint16_t len)
{
const struct gap_oob_legacy_set_data_cmd *cmd = (void *) data;
@@ -1511,7 +1511,7 @@ static void oob_legacy_set_data(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-static void oob_sc_get_local_data(const u8_t *data, u16_t len)
+static void oob_sc_get_local_data(const uint8_t *data, uint16_t len)
{
struct gap_oob_sc_get_local_data_rp rp;
@@ -1519,10 +1519,10 @@ static void oob_sc_get_local_data(const u8_t *data, u16_t len)
memcpy(rp.c, oob_data_local.c, 16);
tester_send(BTP_SERVICE_ID_GAP, GAP_OOB_SC_GET_LOCAL_DATA,
- CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
+ CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
}
-static void oob_sc_set_remote_data(const u8_t *data, u16_t len)
+static void oob_sc_set_remote_data(const uint8_t *data, uint16_t len)
{
const struct gap_oob_sc_set_remote_data_cmd *cmd = (void *) data;
@@ -1534,7 +1534,7 @@ static void oob_sc_set_remote_data(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-static void set_mitm(const u8_t *data, u16_t len)
+static void set_mitm(const uint8_t *data, uint16_t len)
{
const struct gap_set_mitm_cmd *cmd = (void *) data;
@@ -1544,8 +1544,8 @@ static void set_mitm(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-void tester_handle_gap(u8_t opcode, u8_t index, u8_t *data,
- u16_t len)
+void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len)
{
switch (opcode) {
case GAP_READ_SUPPORTED_COMMANDS:
@@ -1664,7 +1664,7 @@ static void tester_init_gap_cb(int err)
BTP_STATUS_SUCCESS);
}
-u8_t tester_init_gap(void)
+uint8_t tester_init_gap(void)
{
#if MYNEWT_VAL(BLE_SM_SC)
int rc;
@@ -1682,7 +1682,7 @@ u8_t tester_init_gap(void)
return BTP_STATUS_SUCCESS;
}
-u8_t tester_unregister_gap(void)
+uint8_t tester_unregister_gap(void)
{
return BTP_STATUS_SUCCESS;
}
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/gatt.c b/src/libs/mynewt-nimble/apps/bttester/src/gatt.c
index 7e7d1d3b..d40de262 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/gatt.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/gatt.c
@@ -76,8 +76,8 @@
static uint8_t gatt_svr_pts_static_long_val[300];
static uint8_t gatt_svr_pts_static_val[30];
static uint8_t gatt_svr_pts_static_short_val;
-static u8_t notify_state;
-static u8_t indicate_state;
+static uint8_t notify_state;
+static uint8_t indicate_state;
static uint16_t myconn_handle;
static struct os_callout notify_tx_timer;
uint16_t notify_handle;
@@ -253,7 +253,7 @@ static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
},
};
-static void attr_value_changed_ev(u16_t handle, struct os_mbuf *data)
+static void attr_value_changed_ev(uint16_t handle, struct os_mbuf *data)
{
struct gatt_attr_value_changed_ev *ev;
struct os_mbuf *buf = os_msys_get(0, 0);
@@ -569,7 +569,7 @@ gatt_svr_rel_write_test(uint16_t conn_handle, uint16_t attr_handle,
}
}
-static void start_server(u8_t *data, u16_t len)
+static void start_server(uint8_t *data, uint16_t len)
{
struct gatt_start_server_rp rp;
@@ -583,14 +583,14 @@ static void start_server(u8_t *data, u16_t len)
rp.db_attr_cnt = 0;
tester_send(BTP_SERVICE_ID_GATT, GATT_START_SERVER, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) &rp, sizeof(rp));
}
/* Convert UUID from BTP command to bt_uuid */
-static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
+static uint8_t btp2bt_uuid(const uint8_t *uuid, uint8_t len,
ble_uuid_any_t *bt_uuid)
{
- u16_t le16;
+ uint16_t le16;
switch (len) {
case 0x02: /* UUID 16 */
@@ -614,8 +614,8 @@ static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
* It is not intended to be used by client and server at the same time.
*/
static struct {
- u16_t len;
- u8_t buf[MAX_BUFFER_SIZE];
+ uint16_t len;
+ uint8_t buf[MAX_BUFFER_SIZE];
} gatt_buf;
static void *gatt_buf_add(const void *data, size_t len)
@@ -665,7 +665,7 @@ static int read_cb(uint16_t conn_handle,
void *arg)
{
struct gatt_read_rp *rp = (void *) gatt_buf.buf;
- u8_t btp_opcode = (uint8_t) (int) arg;
+ uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("status=%d", error->status);
@@ -692,7 +692,7 @@ static int read_cb(uint16_t conn_handle,
return 0;
}
-static void read(u8_t *data, u16_t len)
+static void read(uint8_t *data, uint16_t len)
{
const struct gatt_read_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -731,7 +731,7 @@ static int read_long_cb(uint16_t conn_handle,
void *arg)
{
struct gatt_read_rp *rp = (void *) gatt_buf.buf;
- u8_t btp_opcode = (uint8_t) (int) arg;
+ uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("status=%d", error->status);
@@ -762,7 +762,7 @@ static int read_long_cb(uint16_t conn_handle,
return 0;
}
-static void read_long(u8_t *data, u16_t len)
+static void read_long(uint8_t *data, uint16_t len)
{
const struct gatt_read_long_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -797,10 +797,10 @@ fail:
BTP_STATUS_FAILED);
}
-static void read_multiple(u8_t *data, u16_t len)
+static void read_multiple(uint8_t *data, uint16_t len)
{
const struct gatt_read_multiple_cmd *cmd = (void *) data;
- u16_t handles[cmd->handles_count];
+ uint16_t handles[cmd->handles_count];
struct ble_gap_conn_desc conn;
int rc, i;
@@ -836,11 +836,11 @@ fail:
BTP_STATUS_FAILED);
}
-static void write_without_rsp(u8_t *data, u16_t len, u8_t op, bool sign)
+static void write_without_rsp(uint8_t *data, uint16_t len, uint8_t op, bool sign)
{
const struct gatt_write_without_rsp_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
- u8_t status = BTP_STATUS_SUCCESS;
+ uint8_t status = BTP_STATUS_SUCCESS;
int rc;
SYS_LOG_DBG("");
@@ -866,7 +866,7 @@ static int write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error,
void *arg)
{
uint8_t err = (uint8_t) error->status;
- u8_t btp_opcode = (uint8_t) (int) arg;
+ uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("");
@@ -875,7 +875,7 @@ static int write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error,
return 0;
}
-static void write(u8_t *data, u16_t len)
+static void write(uint8_t *data, uint16_t len)
{
const struct gatt_write_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -901,7 +901,7 @@ fail:
BTP_STATUS_FAILED);
}
-static void write_long(u8_t *data, u16_t len)
+static void write_long(uint8_t *data, uint16_t len)
{
const struct gatt_write_long_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -952,7 +952,7 @@ static int reliable_write_rsp(uint16_t conn_handle,
return 0;
}
-static void reliable_write(u8_t *data, u16_t len)
+static void reliable_write(uint8_t *data, uint16_t len)
{
const struct gatt_reliable_write_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -994,12 +994,12 @@ fail:
}
static struct bt_gatt_subscribe_params {
- u16_t ccc_handle;
- u16_t value;
- u16_t value_handle;
+ uint16_t ccc_handle;
+ uint16_t value;
+ uint16_t value_handle;
} subscribe_params;
-static void read_uuid(u8_t *data, u16_t len)
+static void read_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_read_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1046,8 +1046,8 @@ static int disc_prim_uuid_cb(uint16_t conn_handle,
struct gatt_disc_prim_uuid_rp *rp = (void *) gatt_buf.buf;
struct gatt_service *service;
const ble_uuid_any_t *uuid;
- u8_t uuid_length;
- u8_t opcode = (u8_t) (int) arg;
+ uint8_t uuid_length;
+ uint8_t opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("");
@@ -1081,7 +1081,7 @@ static int disc_prim_uuid_cb(uint16_t conn_handle,
service->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
- u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+ uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(service->uuid, &u16, uuid_length);
} else {
memcpy(service->uuid, BLE_UUID128(uuid)->value,
@@ -1102,7 +1102,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
struct gatt_disc_all_desc_rp *rp = (void *) gatt_buf.buf;
struct gatt_descriptor *dsc;
const ble_uuid_any_t *uuid;
- u8_t uuid_length;
+ uint8_t uuid_length;
SYS_LOG_DBG("");
@@ -1135,7 +1135,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
dsc->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
- u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+ uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(dsc->uuid, &u16, uuid_length);
} else {
memcpy(dsc->uuid, BLE_UUID128(uuid)->value, uuid_length);
@@ -1146,7 +1146,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
return 0;
}
-static void disc_all_prim_svcs(u8_t *data, u16_t len)
+static void disc_all_prim_svcs(uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc conn;
int rc;
@@ -1175,7 +1175,7 @@ fail:
CONTROLLER_INDEX, BTP_STATUS_FAILED);
}
-static void disc_all_desc(u8_t *data, u16_t len)
+static void disc_all_desc(uint8_t *data, uint16_t len)
{
const struct gatt_disc_all_desc_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1221,7 +1221,7 @@ static int find_included_cb(uint16_t conn_handle,
struct gatt_included *included;
const ble_uuid_any_t *uuid;
int service_handle = (int) arg;
- u8_t uuid_length;
+ uint8_t uuid_length;
SYS_LOG_DBG("");
@@ -1259,7 +1259,7 @@ static int find_included_cb(uint16_t conn_handle,
included->service.uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
- u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+ uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(included->service.uuid, &u16, uuid_length);
} else {
memcpy(included->service.uuid, BLE_UUID128(uuid)->value,
@@ -1278,8 +1278,8 @@ static int disc_chrc_cb(uint16_t conn_handle,
struct gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf;
struct gatt_characteristic *chrc;
const ble_uuid_any_t *uuid;
- u8_t btp_opcode = (uint8_t) (int) arg;
- u8_t uuid_length;
+ uint8_t btp_opcode = (uint8_t) (int) arg;
+ uint8_t uuid_length;
SYS_LOG_DBG("");
@@ -1314,7 +1314,7 @@ static int disc_chrc_cb(uint16_t conn_handle,
chrc->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
- u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+ uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(chrc->uuid, &u16, uuid_length);
} else {
memcpy(chrc->uuid, BLE_UUID128(uuid)->value,
@@ -1326,7 +1326,7 @@ static int disc_chrc_cb(uint16_t conn_handle,
return 0;
}
-static void disc_chrc_uuid(u8_t *data, u16_t len)
+static void disc_chrc_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_disc_chrc_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1366,7 +1366,7 @@ fail:
BTP_STATUS_FAILED);
}
-static void disc_prim_uuid(u8_t *data, u16_t len)
+static void disc_prim_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_disc_prim_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1402,7 +1402,7 @@ fail:
BTP_STATUS_FAILED);
}
-static void disc_all_chrc(u8_t *data, u16_t len)
+static void disc_all_chrc(uint8_t *data, uint16_t len)
{
const struct gatt_disc_all_chrc_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1439,7 +1439,7 @@ fail:
BTP_STATUS_FAILED);
}
-static void find_included(u8_t *data, u16_t len)
+static void find_included(uint8_t *data, uint16_t len)
{
const struct gatt_find_included_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@@ -1495,7 +1495,7 @@ static int exchange_func(uint16_t conn_handle,
return 0;
}
-static void exchange_mtu(u8_t *data, u16_t len)
+static void exchange_mtu(uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc conn;
int rc;
@@ -1517,10 +1517,10 @@ fail:
CONTROLLER_INDEX, BTP_STATUS_FAILED);
}
-static int enable_subscription(u16_t conn_handle, u16_t ccc_handle,
- u16_t value)
+static int enable_subscription(uint16_t conn_handle, uint16_t ccc_handle,
+ uint16_t value)
{
- u8_t op;
+ uint8_t op;
SYS_LOG_DBG("");
@@ -1538,9 +1538,9 @@ static int enable_subscription(u16_t conn_handle, u16_t ccc_handle,
return 0;
}
-static int disable_subscription(u16_t conn_handle, u16_t ccc_handle)
+static int disable_subscription(uint16_t conn_handle, uint16_t ccc_handle)
{
- u16_t value = 0x00;
+ uint16_t value = 0x00;
SYS_LOG_DBG("");
@@ -1559,12 +1559,12 @@ static int disable_subscription(u16_t conn_handle, u16_t ccc_handle)
return 0;
}
-static void config_subscription(u8_t *data, u16_t len, u8_t op)
+static void config_subscription(uint8_t *data, uint16_t len, uint8_t op)
{
const struct gatt_cfg_notify_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
- u16_t ccc_handle = sys_le16_to_cpu(cmd->ccc_handle);
- u8_t status;
+ uint16_t ccc_handle = sys_le16_to_cpu(cmd->ccc_handle);
+ uint8_t status;
int rc;
SYS_LOG_DBG("");
@@ -1577,7 +1577,7 @@ static void config_subscription(u8_t *data, u16_t len, u8_t op)
}
if (cmd->enable) {
- u16_t value;
+ uint16_t value;
if (op == GATT_CFG_NOTIFY) {
value = 0x0001;
@@ -1625,10 +1625,10 @@ static int flags_hs2btp_map[] = {
BTP_PERM_F_WRITE_AUTHOR,
};
-static u8_t flags_hs2btp(u8_t flags)
+static uint8_t flags_hs2btp(uint8_t flags)
{
int i;
- u8_t ret = 0;
+ uint8_t ret = 0;
for (i = 0; i < 8; ++i) {
if (flags & BIT(i)) {
@@ -1639,17 +1639,17 @@ static u8_t flags_hs2btp(u8_t flags)
return ret;
}
-static void get_attrs(u8_t *data, u16_t len)
+static void get_attrs(uint8_t *data, uint16_t len)
{
const struct gatt_get_attributes_cmd *cmd = (void *) data;
struct gatt_get_attributes_rp *rp;
struct gatt_attr *gatt_attr;
struct os_mbuf *buf = os_msys_get(0, 0);
- u16_t start_handle, end_handle;
+ uint16_t start_handle, end_handle;
struct ble_att_svr_entry *entry = NULL;
ble_uuid_any_t uuid;
ble_uuid_t *uuid_ptr = NULL;
- u8_t count = 0;
+ uint8_t count = 0;
char str[BLE_UUID_STR_LEN];
SYS_LOG_DBG("");
@@ -1718,13 +1718,13 @@ free:
os_mbuf_free_chain(buf);
}
-static void get_attr_val(u8_t *data, u16_t len)
+static void get_attr_val(uint8_t *data, uint16_t len)
{
const struct gatt_get_attribute_value_cmd *cmd = (void *) data;
struct gatt_get_attribute_value_rp *rp;
struct ble_gap_conn_desc conn;
struct os_mbuf *buf = os_msys_get(0, 0);
- u16_t handle = sys_cpu_to_le16(cmd->handle);
+ uint16_t handle = sys_cpu_to_le16(cmd->handle);
uint8_t out_att_err;
int conn_status;
@@ -1766,7 +1766,7 @@ free:
os_mbuf_free_chain(buf);
}
-static void change_database(u8_t *data, u16_t len)
+static void change_database(uint8_t *data, uint16_t len)
{
const struct gatt_change_database *cmd = (void *) data;
@@ -1782,9 +1782,9 @@ static void change_database(u8_t *data, u16_t len)
return;
}
-static void supported_commands(u8_t *data, u16_t len)
+static void supported_commands(uint8_t *data, uint16_t len)
{
- u8_t cmds[4];
+ uint8_t cmds[4];
struct gatt_read_supported_commands_rp *rp = (void *) cmds;
SYS_LOG_DBG("");
@@ -1816,7 +1816,7 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, GATT_CHANGE_DATABASE);
tester_send(BTP_SERVICE_ID_GATT, GATT_READ_SUPPORTED_COMMANDS,
- CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
+ CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
enum attr_type {
@@ -1825,8 +1825,8 @@ enum attr_type {
BLE_GATT_ATTR_DSC,
};
-void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
- u16_t len)
+void tester_handle_gatt(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len)
{
switch (opcode) {
case GATT_READ_SUPPORTED_COMMANDS:
@@ -1905,8 +1905,8 @@ void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
}
}
-int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
- u8_t indication, struct os_mbuf *om)
+int tester_gatt_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t indication, struct os_mbuf *om)
{
struct gatt_notification_ev *ev;
struct ble_gap_conn_desc conn;
@@ -1930,7 +1930,7 @@ int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
ev->address_type = addr->type;
memcpy(ev->address, addr->val, sizeof(ev->address));
- ev->type = (u8_t) (indication ? 0x02 : 0x01);
+ ev->type = (uint8_t) (indication ? 0x02 : 0x01);
ev->handle = sys_cpu_to_le16(attr_handle);
ev->data_length = sys_cpu_to_le16(os_mbuf_len(om));
os_mbuf_appendfrom(buf, om, 0, os_mbuf_len(om));
@@ -1988,9 +1988,9 @@ void notify_test(struct os_event *ev)
}
}
-int tester_gatt_subscribe_ev(u16_t conn_handle, u16_t attr_handle, u8_t reason,
- u8_t prev_notify, u8_t cur_notify,
- u8_t prev_indicate, u8_t cur_indicate)
+int tester_gatt_subscribe_ev(uint16_t conn_handle, uint16_t attr_handle, uint8_t reason,
+ uint8_t prev_notify, uint8_t cur_notify,
+ uint8_t prev_indicate, uint8_t cur_indicate)
{
SYS_LOG_DBG("");
myconn_handle = conn_handle;
@@ -2084,7 +2084,7 @@ int gatt_svr_init(void)
return 0;
}
-u8_t tester_init_gatt(void)
+uint8_t tester_init_gatt(void)
{
os_callout_init(¬ify_tx_timer, os_eventq_dflt_get(),
notify_test, NULL);
@@ -2092,7 +2092,7 @@ u8_t tester_init_gatt(void)
return BTP_STATUS_SUCCESS;
}
-u8_t tester_unregister_gatt(void)
+uint8_t tester_unregister_gatt(void)
{
return BTP_STATUS_SUCCESS;
}
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/glue.c b/src/libs/mynewt-nimble/apps/bttester/src/glue.c
index 6cd7643c..3e606062 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/glue.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/glue.c
@@ -33,8 +33,8 @@ const char *bt_hex(const void *buf, size_t len)
{
static const char hex[] = "0123456789abcdef";
static char hexbufs[4][137];
- static u8_t curbuf;
- const u8_t *b = buf;
+ static uint8_t curbuf;
+ const uint8_t *b = buf;
char *str;
int i;
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/glue.h b/src/libs/mynewt-nimble/apps/bttester/src/glue.h
index e563331e..65085601 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/glue.h
+++ b/src/libs/mynewt-nimble/apps/bttester/src/glue.h
@@ -22,11 +22,11 @@
#include "os/endian.h"
-#define u8_t uint8_t
-#define s8_t int8_t
-#define u16_t uint16_t
-#define u32_t uint32_t
-#define s32_t int32_t
+#define uint8_t uint8_t
+#define int8_t int8_t
+#define uint16_t uint16_t
+#define uint32_t uint32_t
+#define int32_t int32_t
#ifndef BIT
#define BIT(n) (1UL << (n))
@@ -37,16 +37,16 @@
#define sys_le16_to_cpu le16toh
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;
};
#define BT_DATA(_type, _data, _data_len) \
{ \
.type = (_type), \
.data_len = (_data_len), \
- .data = (const u8_t *)(_data), \
+ .data = (const uint8_t *)(_data), \
}
struct os_mbuf * NET_BUF_SIMPLE(uint16_t size);
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c b/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c
index 45b904a1..5c4fc712 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c
@@ -33,11 +33,13 @@
#include "host/ble_gap.h"
#include "host/ble_l2cap.h"
+#include "../../../nimble/host/src/ble_l2cap_priv.h"
+
#include "bttester.h"
#define CONTROLLER_INDEX 0
#define CHANNELS MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
-#define TESTER_COC_MTU (230)
+#define TESTER_COC_MTU MYNEWT_VAL(BTTESTER_L2CAP_COC_MTU)
#define TESTER_COC_BUF_COUNT (3 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM))
static os_membuf_t tester_sdu_coc_mem[
@@ -48,14 +50,34 @@ struct os_mbuf_pool sdu_os_mbuf_pool;
static struct os_mempool sdu_coc_mbuf_mempool;
static struct channel {
- u8_t chan_id; /* Internal number that identifies L2CAP channel. */
- u8_t state;
+ uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
+ uint8_t state;
struct ble_l2cap_chan *chan;
} channels[CHANNELS];
-static u8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)];
+static uint8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)];
-struct channel *find_channel(struct ble_l2cap_chan *chan) {
+static struct channel *get_free_channel(void)
+{
+ uint8_t i;
+ struct channel *chan;
+
+ for (i = 0; i < CHANNELS; i++) {
+ if (channels[i].state) {
+ continue;
+ }
+
+ chan = &channels[i];
+ chan->chan_id = i;
+
+ return chan;
+ }
+
+ return NULL;
+}
+
+struct channel *find_channel(struct ble_l2cap_chan *chan)
+{
int i;
for (i = 0; i < CHANNELS; ++i) {
@@ -67,6 +89,15 @@ struct channel *find_channel(struct ble_l2cap_chan *chan) {
return NULL;
}
+struct channel *get_channel(uint8_t chan_id)
+{
+ if (chan_id >= CHANNELS) {
+ return NULL;
+ }
+
+ return &channels[chan_id];
+}
+
static void
tester_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
{
@@ -84,14 +115,20 @@ static void recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
struct os_mbuf *buf, void *arg)
{
struct l2cap_data_received_ev *ev = (void *) recv_cb_buf;
- struct channel *channel = arg;
+ struct channel *channel = find_channel(chan);
+ assert(channel != NULL);
ev->chan_id = channel->chan_id;
- ev->data_length = buf->om_len;
- memcpy(ev->data, buf->om_data, buf->om_len);
+ ev->data_length = OS_MBUF_PKTLEN(buf);
+
+ if (ev->data_length > TESTER_COC_MTU) {
+ SYS_LOG_ERR("Too large sdu received, truncating data");
+ ev->data_length = TESTER_COC_MTU;
+ }
+ os_mbuf_copydata(buf, 0, ev->data_length, ev->data);
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
- CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->om_len);
+ CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + ev->data_length);
tester_l2cap_coc_recv(chan, buf);
}
@@ -108,44 +145,49 @@ static void unstalled_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
}
-static struct channel *get_free_channel(void)
+static void reconfigured_ev(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ struct ble_l2cap_chan_info *chan_info,
+ int status)
{
- u8_t i;
- struct channel *chan;
+ struct l2cap_reconfigured_ev ev;
+ struct channel *channel;
- for (i = 0; i < CHANNELS; i++) {
- if (channels[i].state) {
- continue;
- }
-
- chan = &channels[i];
- chan->chan_id = i;
-
- return chan;
+ if (status != 0) {
+ return;
}
- return NULL;
+ channel = find_channel(chan);
+ assert(channel != NULL);
+
+ ev.chan_id = channel->chan_id;
+ ev.peer_mtu = chan_info->peer_coc_mtu;
+ ev.peer_mps = chan_info->peer_l2cap_mtu;
+ ev.our_mtu = chan_info->our_coc_mtu;
+ ev.our_mps = chan_info->our_l2cap_mtu;
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED,
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- void *arg)
+ struct ble_l2cap_chan_info *chan_info, void *arg)
{
struct l2cap_connected_ev ev;
struct ble_gap_conn_desc desc;
- struct channel *channel;
+ struct channel *channel = find_channel(chan);
- channel = get_free_channel();
- if (!channel) {
- assert(0);
+ if (channel == NULL) {
+ channel = get_free_channel();
}
- channel->chan = chan;
- channel->state = 0;
-
ev.chan_id = channel->chan_id;
+ ev.psm = chan_info->psm;
+ ev.peer_mtu = chan_info->peer_coc_mtu;
+ ev.peer_mps = chan_info->peer_l2cap_mtu;
+ ev.our_mtu = chan_info->our_coc_mtu;
+ ev.our_mps = chan_info->our_l2cap_mtu;
channel->state = 1;
channel->chan = chan;
- /* TODO: ev.psm */
if (!ble_gap_conn_find(conn_handle, &desc)) {
ev.address_type = desc.peer_ota_addr.type;
@@ -154,11 +196,11 @@ static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_CONNECTED, CONTROLLER_INDEX,
- (u8_t *) &ev, sizeof(ev));
+ (uint8_t *) &ev, sizeof(ev));
}
static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- void *arg)
+ struct ble_l2cap_chan_info *chan_info, void *arg)
{
struct l2cap_disconnected_ev ev;
struct ble_gap_conn_desc desc;
@@ -167,14 +209,12 @@ static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
channel = find_channel(chan);
- if (channel != NULL) {
- channel->state = 0;
- channel->chan = chan;
+ assert(channel != NULL);
- ev.chan_id = channel->chan_id;
- /* TODO: ev.result */
- /* TODO: ev.psm */
- }
+ channel->state = 0;
+ channel->chan = chan;
+ ev.chan_id = channel->chan_id;
+ ev.psm = chan_info->psm;
if (!ble_gap_conn_find(conn_handle, &desc)) {
ev.address_type = desc.peer_ota_addr.type;
@@ -183,7 +223,7 @@ static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DISCONNECTED,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static int accept_cb(uint16_t conn_handle, uint16_t peer_mtu,
@@ -208,39 +248,51 @@ static int
tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
{
struct ble_l2cap_chan_info chan_info;
+ int accept_response;
switch (event->type) {
- case BLE_L2CAP_EVENT_COC_CONNECTED:
+ case BLE_L2CAP_EVENT_COC_CONNECTED:
+ if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
+ assert(0);
+ }
+
if (event->connect.status) {
console_printf("LE COC error: %d\n", event->connect.status);
disconnected_cb(event->connect.conn_handle,
- event->connect.chan, arg);
+ event->connect.chan, &chan_info, arg);
return 0;
}
- ble_l2cap_get_chan_info(event->connect.chan, &chan_info);
-
- console_printf("LE COC connected, conn: %d, chan: 0x%08lx, scid: 0x%04x, "
- "dcid: 0x%04x, our_mtu: 0x%04x, peer_mtu: 0x%04x\n",
- event->connect.conn_handle,
- (uint32_t) event->connect.chan,
- chan_info.scid,
- chan_info.dcid,
- chan_info.our_l2cap_mtu,
- chan_info.peer_l2cap_mtu);
+ console_printf("LE COC connected, conn: %d, chan: 0x%08lx, "
+ "psm: 0x%02x, scid: 0x%04x, dcid: 0x%04x, "
+ "our_mps: %d, our_mtu: %d, peer_mps: %d, "
+ "peer_mtu: %d\n", event->connect.conn_handle,
+ (uint32_t) event->connect.chan, chan_info.psm,
+ chan_info.scid, chan_info.dcid,
+ chan_info.our_l2cap_mtu, chan_info.our_coc_mtu,
+ chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
connected_cb(event->connect.conn_handle,
- event->connect.chan, arg);
+ event->connect.chan, &chan_info, arg);
return 0;
case BLE_L2CAP_EVENT_COC_DISCONNECTED:
+ if (ble_l2cap_get_chan_info(event->disconnect.chan,
+ &chan_info)) {
+ assert(0);
+ }
console_printf("LE CoC disconnected, chan: 0x%08lx\n",
(uint32_t) event->disconnect.chan);
disconnected_cb(event->disconnect.conn_handle,
- event->disconnect.chan, arg);
+ event->disconnect.chan, &chan_info, arg);
return 0;
case BLE_L2CAP_EVENT_COC_ACCEPT:
+ accept_response = POINTER_TO_INT(arg);
+ if (accept_response) {
+ return accept_response;
+ }
+
console_printf("LE CoC accept, chan: 0x%08lx, handle: %u, sdu_size: %u\n",
(uint32_t) event->accept.chan,
event->accept.conn_handle,
@@ -254,7 +306,8 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
console_printf("LE CoC data received, chan: 0x%08lx, handle: %u, sdu_len: %u\n",
(uint32_t) event->receive.chan,
event->receive.conn_handle,
- event->receive.sdu_rx->om_len);
+ OS_MBUF_PKTLEN(event->receive.sdu_rx));
+
recv_cb(event->receive.conn_handle, event->receive.chan,
event->receive.sdu_rx, arg);
return 0;
@@ -263,57 +316,118 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
(uint32_t) event->tx_unstalled.chan,
event->tx_unstalled.conn_handle,
event->tx_unstalled.status);
+
unstalled_cb(event->tx_unstalled.conn_handle,
event->tx_unstalled.chan,
event->tx_unstalled.status, arg);
return 0;
+ case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
+ if (ble_l2cap_get_chan_info(event->reconfigured.chan,
+ &chan_info)) {
+ assert(0);
+ }
+ console_printf("LE CoC reconfigure completed status 0x%02x, "
+ "chan: 0x%08lx\n", event->reconfigured.status,
+ (uint32_t) event->reconfigured.chan);
+
+ if (event->reconfigured.status == 0) {
+ console_printf("\t our_mps: %d our_mtu %d\n",
+ chan_info.our_l2cap_mtu, chan_info.our_coc_mtu);
+ }
+
+ reconfigured_ev(event->reconfigured.conn_handle,
+ event->reconfigured.chan,
+ &chan_info,
+ event->reconfigured.status);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED:
+ if (ble_l2cap_get_chan_info(event->reconfigured.chan,
+ &chan_info)) {
+ assert(0);
+ }
+ console_printf("LE CoC peer reconfigured status 0x%02x, "
+ "chan: 0x%08lx\n", event->reconfigured.status,
+ (uint32_t) event->reconfigured.chan);
+
+ if (event->reconfigured.status == 0) {
+ console_printf("\t peer_mps: %d peer_mtu %d\n",
+ chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
+ }
+
+ reconfigured_ev(event->reconfigured.conn_handle,
+ event->reconfigured.chan,
+ &chan_info,
+ event->reconfigured.status);
+ return 0;
default:
return 0;
}
}
-static void connect(u8_t *data, u16_t len)
+static void connect(uint8_t *data, uint16_t len)
{
const struct l2cap_connect_cmd *cmd = (void *) data;
- struct l2cap_connect_rp rp;
+ uint8_t rp_buf[sizeof(struct l2cap_connect_rp) + cmd->num];
+ struct l2cap_connect_rp *rp = (void *) rp_buf;
struct ble_gap_conn_desc desc;
struct channel *chan;
- struct os_mbuf *sdu_rx;
+ struct os_mbuf *sdu_rx[cmd->num];
ble_addr_t *addr = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
int rc;
+ int i;
SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6));
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
rc = ble_gap_conn_find_by_addr(addr, &desc);
if (rc) {
SYS_LOG_ERR("GAP conn find failed");
goto fail;
}
- chan = get_free_channel();
- if (!chan) {
- SYS_LOG_ERR("No free channels");
+ rp->num = cmd->num;
+
+ for (i = 0; i < cmd->num; i++) {
+ chan = get_free_channel();
+ if (!chan) {
+ SYS_LOG_ERR("No free channels");
+ goto fail;
+ }
+
+ rp->chan_ids[i] = chan->chan_id;
+
+ sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ if (sdu_rx[i] == NULL) {
+ SYS_LOG_ERR("Failed to alloc buf");
+ goto fail;
+ }
+ }
+
+ if (cmd->num == 1) {
+ rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm),
+ mtu, sdu_rx[0],
+ tester_l2cap_event, NULL);
+ } else if (cmd->num > 1) {
+ rc = ble_l2cap_enhanced_connect(desc.conn_handle,
+ htole16(cmd->psm), mtu,
+ cmd->num, sdu_rx,
+ tester_l2cap_event, NULL);
+ } else {
+ SYS_LOG_ERR("Invalid 'num' parameter value");
goto fail;
}
- sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
- if (sdu_rx == NULL) {
- SYS_LOG_ERR("Failed to alloc buf");
- goto fail;
- }
-
- rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm),
- TESTER_COC_MTU, sdu_rx,
- tester_l2cap_event, chan);
if (rc) {
SYS_LOG_ERR("L2CAP connect failed\n");
goto fail;
}
- rp.chan_id = chan->chan_id;
-
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
- (u8_t *) &rp, sizeof(rp));
+ (uint8_t *) rp, sizeof(rp_buf));
return;
@@ -322,16 +436,17 @@ fail:
BTP_STATUS_FAILED);
}
-static void disconnect(u8_t *data, u16_t len)
+static void disconnect(const uint8_t *data, uint16_t len)
{
const struct l2cap_disconnect_cmd *cmd = (void *) data;
struct channel *chan;
- u8_t status;
+ uint8_t status;
int err;
SYS_LOG_DBG("");
- chan = &channels[cmd->chan_id];
+ chan = get_channel(cmd->chan_id);
+ assert(chan != NULL);
err = ble_l2cap_disconnect(chan->chan);
if (err) {
@@ -346,16 +461,21 @@ rsp:
status);
}
-static void send_data(u8_t *data, u16_t len)
+static void send_data(const uint8_t *data, uint16_t len)
{
const struct l2cap_send_data_cmd *cmd = (void *) data;
- struct channel *chan = &channels[cmd->chan_id];
struct os_mbuf *sdu_tx = NULL;
int rc;
- u16_t data_len = sys_le16_to_cpu(cmd->data_len);
+ uint16_t data_len = sys_le16_to_cpu(cmd->data_len);
+ struct channel *chan = get_channel(cmd->chan_id);
SYS_LOG_DBG("cmd->chan_id=%d", cmd->chan_id);
+ if (!chan) {
+ SYS_LOG_ERR("Invalid channel\n");
+ goto fail;
+ }
+
/* FIXME: For now, fail if data length exceeds buffer length */
if (data_len > TESTER_COC_MTU) {
SYS_LOG_ERR("Data length exceeds buffer length");
@@ -386,16 +506,48 @@ fail:
BTP_STATUS_FAILED);
}
-static void listen(u8_t *data, u16_t len)
+static int
+l2cap_coc_err2hs_err(uint16_t coc_err)
+{
+ switch (coc_err) {
+ case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM:
+ return BLE_HS_ENOTSUP;
+ case BLE_L2CAP_COC_ERR_NO_RESOURCES:
+ return BLE_HS_ENOMEM;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN:
+ return BLE_HS_EAUTHEN;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR:
+ return BLE_HS_EAUTHOR;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC:
+ return BLE_HS_EENCRYPT;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ:
+ return BLE_HS_EENCRYPT_KEY_SZ;
+ case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS:
+ return BLE_HS_EINVAL;
+ default:
+ return 0;
+ }
+}
+
+
+static void listen(const uint8_t *data, uint16_t len)
{
const struct l2cap_listen_cmd *cmd = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
+ uint16_t rsp = htole16(cmd->response);
int rc;
SYS_LOG_DBG("");
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
+ rsp = l2cap_coc_err2hs_err(rsp);
+
/* TODO: Handle cmd->transport flag */
- rc = ble_l2cap_create_server(cmd->psm, TESTER_COC_MTU,
- tester_l2cap_event, NULL);
+ rc = ble_l2cap_create_server(cmd->psm, mtu, tester_l2cap_event,
+ INT_TO_POINTER(rsp));
if (rc) {
goto fail;
}
@@ -409,9 +561,54 @@ fail:
BTP_STATUS_FAILED);
}
-static void supported_commands(u8_t *data, u16_t len)
+static void reconfigure(const uint8_t *data, uint16_t len)
{
- u8_t cmds[1];
+ const struct l2cap_reconfigure_cmd *cmd = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
+ struct ble_gap_conn_desc desc;
+ ble_addr_t *addr = (void *) data;
+ struct ble_l2cap_chan *chans[cmd->num];
+ struct channel *channel;
+ int rc;
+ int i;
+
+ SYS_LOG_DBG("");
+
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
+ rc = ble_gap_conn_find_by_addr(addr, &desc);
+ if (rc) {
+ SYS_LOG_ERR("GAP conn find failed");
+ goto fail;
+ }
+
+ for (i = 0; i < cmd->num; ++i) {
+ channel = get_channel(cmd->idxs[i]);
+ if (channel == NULL) {
+ goto fail;
+ }
+ chans[i] = channel->chan;
+ }
+
+ rc = ble_l2cap_reconfig(chans, cmd->num, mtu);
+ if (rc) {
+ goto fail;
+ }
+
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
+ BTP_STATUS_SUCCESS);
+ return;
+
+fail:
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
+ BTP_STATUS_FAILED);
+}
+
+static void supported_commands(uint8_t *data, uint16_t len)
+{
+ uint8_t cmds[1];
struct l2cap_read_supported_commands_rp *rp = (void *) cmds;
memset(cmds, 0, sizeof(cmds));
@@ -421,13 +618,14 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, L2CAP_DISCONNECT);
tester_set_bit(cmds, L2CAP_LISTEN);
tester_set_bit(cmds, L2CAP_SEND_DATA);
+ tester_set_bit(cmds, L2CAP_RECONFIGURE);
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_READ_SUPPORTED_COMMANDS,
- CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
+ CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
-void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
- u16_t len)
+void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len)
{
switch (opcode) {
case L2CAP_READ_SUPPORTED_COMMANDS:
@@ -445,6 +643,9 @@ void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
case L2CAP_LISTEN:
listen(data, len);
return;
+ case L2CAP_RECONFIGURE:
+ reconfigure(data, len);
+ return;
default:
tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index,
BTP_STATUS_UNKNOWN_CMD);
@@ -452,7 +653,7 @@ void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
}
}
-u8_t tester_init_l2cap(void)
+uint8_t tester_init_l2cap(void)
{
int rc;
@@ -469,7 +670,7 @@ u8_t tester_init_l2cap(void)
return BTP_STATUS_SUCCESS;
}
-u8_t tester_unregister_l2cap(void)
+uint8_t tester_unregister_l2cap(void)
{
return BTP_STATUS_SUCCESS;
}
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/mesh.c b/src/libs/mynewt-nimble/apps/bttester/src/mesh.c
index e18a2a4e..8226fe99 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/mesh.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/mesh.c
@@ -38,7 +38,7 @@
#include "bttester.h"
-extern u8_t own_addr_type;
+extern uint8_t own_addr_type;
#define CONTROLLER_INDEX 0
#define CID_LOCAL 0xffff
@@ -47,21 +47,21 @@ extern u8_t own_addr_type;
#define CUR_FAULTS_MAX 4
#define HEALTH_TEST_ID 0x00
-static u8_t cur_faults[CUR_FAULTS_MAX];
-static u8_t reg_faults[CUR_FAULTS_MAX * 2];
+static uint8_t cur_faults[CUR_FAULTS_MAX];
+static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
/* Provision node data */
-static u8_t net_key[16];
-static u16_t net_key_idx;
-static u8_t flags;
-static u32_t iv_index;
-static u16_t addr;
-static u8_t dev_key[16];
-static u8_t input_size;
+static uint8_t net_key[16];
+static uint16_t net_key_idx;
+static uint8_t flags;
+static uint32_t iv_index;
+static uint16_t addr;
+static uint8_t dev_key[16];
+static uint8_t input_size;
/* Configured provisioning data */
-static u8_t dev_uuid[16];
-static u8_t static_auth[16];
+static uint8_t dev_uuid[16];
+static uint8_t static_auth[16];
/* Vendor Model data */
#define VND_MODEL_ID_1 0x1234
@@ -71,20 +71,20 @@ static u8_t static_auth[16];
static struct model_data {
struct bt_mesh_model *model;
- u16_t addr;
- u16_t appkey_idx;
+ uint16_t addr;
+ uint16_t appkey_idx;
} model_bound[MODEL_BOUNDS_MAX];
static struct {
- u16_t local;
- u16_t dst;
- u16_t net_idx;
+ uint16_t local;
+ uint16_t dst;
+ uint16_t net_idx;
} net = {
.local = BT_MESH_ADDR_UNASSIGNED,
.dst = BT_MESH_ADDR_UNASSIGNED,
};
-static void supported_commands(u8_t *data, u16_t len)
+static void supported_commands(uint8_t *data, uint16_t len)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE);
@@ -121,29 +121,9 @@ static void supported_commands(u8_t *data, u16_t len)
CONTROLLER_INDEX, buf);
}
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_ENABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if MYNEWT_VAL(BLE_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_ENABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
-static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
+static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
{
- u8_t i, limit = *count;
+ uint8_t i, limit = *count;
for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
if (faults[i]) {
@@ -153,8 +133,8 @@ static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
}
}
-static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
{
SYS_LOG_DBG("");
@@ -166,8 +146,8 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
return 0;
}
-static int fault_get_reg(struct bt_mesh_model *model, u16_t company_id,
- u8_t *test_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id,
+ uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
{
SYS_LOG_DBG("company_id 0x%04x", company_id);
@@ -229,7 +209,7 @@ health_pub_init(void)
static struct bt_mesh_cfg_cli cfg_cli = {
};
-void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
+void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
{
size_t i;
@@ -247,8 +227,8 @@ void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
}
}
-static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+static void health_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)
{
SYS_LOG_DBG("Health Current Status from 0x%04x", addr);
@@ -260,7 +240,7 @@ static struct bt_mesh_health_cli health_cli = {
};
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL_HEALTH_CLI(&health_cli),
@@ -295,7 +275,7 @@ static void link_open(bt_mesh_prov_bearer_t bearer)
}
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_OPEN,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void link_close(bt_mesh_prov_bearer_t bearer)
@@ -318,10 +298,10 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
}
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_CLOSED,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
-static int output_number(bt_mesh_output_action_t action, u32_t number)
+static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
struct mesh_out_number_action_ev ev;
@@ -331,7 +311,7 @@ static int output_number(bt_mesh_output_action_t action, u32_t number)
ev.number = sys_cpu_to_le32(number);
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_OUT_NUMBER_ACTION,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
return 0;
}
@@ -357,7 +337,7 @@ static int output_string(const char *str)
return 0;
}
-static int input(bt_mesh_input_action_t action, u8_t size)
+static int input(bt_mesh_input_action_t action, uint8_t size)
{
struct mesh_in_action_ev ev;
@@ -369,12 +349,15 @@ static int input(bt_mesh_input_action_t action, u8_t size)
ev.size = size;
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_IN_ACTION, CONTROLLER_INDEX,
- (u8_t *) &ev, sizeof(ev));
+ (uint8_t *) &ev, sizeof(ev));
return 0;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static uint8_t vnd_app_key[16];
+static uint16_t vnd_app_key_idx = 0x000f;
+
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
SYS_LOG_DBG("net_idx 0x%04x addr 0x%04x", net_idx, addr);
@@ -412,7 +395,7 @@ static struct bt_mesh_prov prov = {
.reset = prov_reset,
};
-static void config_prov(u8_t *data, u16_t len)
+static void config_prov(uint8_t *data, uint16_t len)
{
const struct mesh_config_provisioning_cmd *cmd = (void *) data;
@@ -430,7 +413,7 @@ static void config_prov(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-static void provision_node(u8_t *data, u16_t len)
+static void provision_node(uint8_t *data, uint16_t len)
{
const struct mesh_provision_node_cmd *cmd = (void *) data;
@@ -448,9 +431,9 @@ static void provision_node(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-static void init(u8_t *data, u16_t len)
+static void init(uint8_t *data, uint16_t len)
{
- u8_t status = BTP_STATUS_SUCCESS;
+ uint8_t status = BTP_STATUS_SUCCESS;
int err;
SYS_LOG_DBG("");
@@ -475,15 +458,12 @@ static void init(u8_t *data, u16_t len)
}
}
- /* Set device key for vendor model */
- vnd_models[0].keys[0] = BT_MESH_KEY_DEV;
-
rsp:
tester_rsp(BTP_SERVICE_ID_MESH, MESH_INIT, CONTROLLER_INDEX,
status);
}
-static void reset(u8_t *data, u16_t len)
+static void reset(uint8_t *data, uint16_t len)
{
SYS_LOG_DBG("");
@@ -493,11 +473,11 @@ static void reset(u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
-static void input_number(u8_t *data, u16_t len)
+static void input_number(uint8_t *data, uint16_t len)
{
const struct mesh_input_number_cmd *cmd = (void *) data;
- u8_t status = BTP_STATUS_SUCCESS;
- u32_t number;
+ uint8_t status = BTP_STATUS_SUCCESS;
+ uint32_t number;
int err;
number = sys_le32_to_cpu(cmd->number);
@@ -513,11 +493,11 @@ static void input_number(u8_t *data, u16_t len)
status);
}
-static void input_string(u8_t *data, u16_t len)
+static void input_string(uint8_t *data, uint16_t len)
{
const struct mesh_input_string_cmd *cmd = (void *) data;
- u8_t status = BTP_STATUS_SUCCESS;
- u8_t str_auth[16];
+ uint8_t status = BTP_STATUS_SUCCESS;
+ uint8_t str_auth[16];
int err;
SYS_LOG_DBG("");
@@ -544,7 +524,7 @@ rsp:
status);
}
-static void ivu_test_mode(u8_t *data, u16_t len)
+static void ivu_test_mode(uint8_t *data, uint16_t len)
{
const struct mesh_ivu_test_mode_cmd *cmd = (void *) data;
@@ -556,7 +536,7 @@ static void ivu_test_mode(u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
-static void ivu_toggle_state(u8_t *data, u16_t len)
+static void ivu_toggle_state(uint8_t *data, uint16_t len)
{
bool result;
@@ -571,7 +551,7 @@ static void ivu_toggle_state(u8_t *data, u16_t len)
result ? BTP_STATUS_SUCCESS : BTP_STATUS_FAILED);
}
-static void lpn(u8_t *data, u16_t len)
+static void lpn(uint8_t *data, uint16_t len)
{
struct mesh_lpn_set_cmd *cmd = (void *) data;
bool enable;
@@ -589,7 +569,7 @@ static void lpn(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
-static void lpn_poll(u8_t *data, u16_t len)
+static void lpn_poll(uint8_t *data, uint16_t len)
{
int err;
@@ -604,13 +584,13 @@ static void lpn_poll(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
-static void net_send(u8_t *data, u16_t len)
+static void net_send(uint8_t *data, uint16_t len)
{
struct mesh_net_send_cmd *cmd = (void *) data;
- struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX);
+ struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX);
struct bt_mesh_msg_ctx ctx = {
.net_idx = net.net_idx,
- .app_idx = BT_MESH_KEY_DEV,
+ .app_idx = vnd_app_key_idx,
.addr = sys_le16_to_cpu(cmd->dst),
.send_ttl = cmd->ttl,
};
@@ -619,6 +599,12 @@ static void net_send(u8_t *data, u16_t len)
SYS_LOG_DBG("ttl 0x%02x dst 0x%04x payload_len %d", ctx.send_ttl,
ctx.addr, cmd->payload_len);
+ if (!bt_mesh_app_key_get(vnd_app_key_idx)) {
+ (void)bt_mesh_app_key_add(vnd_app_key_idx, net.net_idx,
+ vnd_app_key);
+ vnd_models[0].keys[0] = vnd_app_key_idx;
+ }
+
net_buf_simple_add_mem(msg, cmd->payload, cmd->payload_len);
err = bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL);
@@ -632,13 +618,13 @@ static void net_send(u8_t *data, u16_t len)
os_mbuf_free_chain(msg);
}
-static void health_generate_faults(u8_t *data, u16_t len)
+static void health_generate_faults(uint8_t *data, uint16_t len)
{
struct mesh_health_generate_faults_rp *rp;
struct os_mbuf *buf = NET_BUF_SIMPLE(sizeof(*rp) + sizeof(cur_faults) +
sizeof(reg_faults));
- u8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 };
- u8_t cur_faults_count, reg_faults_count;
+ uint8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 };
+ uint8_t cur_faults_count, reg_faults_count;
rp = net_buf_simple_add(buf, sizeof(*rp));
@@ -658,7 +644,7 @@ static void health_generate_faults(u8_t *data, u16_t len)
CONTROLLER_INDEX, buf);
}
-static void health_clear_faults(u8_t *data, u16_t len)
+static void health_clear_faults(uint8_t *data, uint16_t len)
{
SYS_LOG_DBG("");
@@ -671,7 +657,7 @@ static void health_clear_faults(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
-static void model_send(u8_t *data, u16_t len)
+static void model_send(uint8_t *data, uint16_t len)
{
struct mesh_model_send_cmd *cmd = (void *) data;
struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX);
@@ -683,7 +669,7 @@ static void model_send(u8_t *data, u16_t len)
};
struct bt_mesh_model *model = NULL;
int err, i;
- u16_t src = sys_le16_to_cpu(cmd->src);
+ uint16_t src = sys_le16_to_cpu(cmd->src);
/* Lookup source address */
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
@@ -720,10 +706,10 @@ fail:
}
#if MYNEWT_VAL(BLE_MESH_TESTING)
-static void lpn_subscribe(u8_t *data, u16_t len)
+static void lpn_subscribe(uint8_t *data, uint16_t len)
{
struct mesh_lpn_subscribe_cmd *cmd = (void *) data;
- u16_t address = sys_le16_to_cpu(cmd->address);
+ uint16_t address = sys_le16_to_cpu(cmd->address);
int err;
SYS_LOG_DBG("address 0x%04x", address);
@@ -737,10 +723,10 @@ static void lpn_subscribe(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
-static void lpn_unsubscribe(u8_t *data, u16_t len)
+static void lpn_unsubscribe(uint8_t *data, uint16_t len)
{
struct mesh_lpn_unsubscribe_cmd *cmd = (void *) data;
- u16_t address = sys_le16_to_cpu(cmd->address);
+ uint16_t address = sys_le16_to_cpu(cmd->address);
int err;
SYS_LOG_DBG("address 0x%04x", address);
@@ -754,7 +740,7 @@ static void lpn_unsubscribe(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
-static void rpl_clear(u8_t *data, u16_t len)
+static void rpl_clear(uint8_t *data, uint16_t len)
{
int err;
@@ -770,7 +756,7 @@ static void rpl_clear(u8_t *data, u16_t len)
}
#endif /* MYNEWT_VAL(BLE_MESH_TESTING) */
-static void proxy_identity_enable(u8_t *data, u16_t len)
+static void proxy_identity_enable(uint8_t *data, uint16_t len)
{
int err;
@@ -785,7 +771,7 @@ static void proxy_identity_enable(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
-void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
+void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len)
{
switch (opcode) {
case MESH_READ_SUPPORTED_COMMANDS:
@@ -854,7 +840,7 @@ void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
}
}
-void net_recv_ev(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, const void *payload,
+void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload,
size_t payload_len)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(UINT8_MAX);
@@ -883,8 +869,8 @@ done:
os_mbuf_free_chain(buf);
}
-static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
int i;
@@ -904,8 +890,8 @@ static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
SYS_LOG_ERR("model_bound is full");
}
-static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
int i;
@@ -925,7 +911,7 @@ static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
SYS_LOG_INF("model not found");
}
-static void invalid_bearer_cb(u8_t opcode)
+static void invalid_bearer_cb(uint8_t opcode)
{
struct mesh_invalid_bearer_ev ev = {
.opcode = opcode,
@@ -934,7 +920,7 @@ static void invalid_bearer_cb(u8_t opcode)
SYS_LOG_DBG("opcode 0x%02x", opcode);
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INVALID_BEARER,
- CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void incomp_timer_exp_cb(void)
@@ -951,7 +937,7 @@ static struct bt_test_cb bt_test_cb = {
.mesh_trans_incomp_timer_exp = incomp_timer_exp_cb,
};
-u8_t tester_init_mesh(void)
+uint8_t tester_init_mesh(void)
{
health_pub_init();
@@ -962,7 +948,7 @@ u8_t tester_init_mesh(void)
return BTP_STATUS_SUCCESS;
}
-u8_t tester_unregister_mesh(void)
+uint8_t tester_unregister_mesh(void)
{
return BTP_STATUS_SUCCESS;
}
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c b/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c
index 379345a0..4e667709 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c
@@ -31,7 +31,7 @@ static struct hal_timer rtt_timer;
static bttester_pipe_recv_cb app_cb;
-static u8_t *recv_buf;
+static uint8_t *recv_buf;
static size_t recv_buf_len;
static size_t recv_off;
@@ -74,7 +74,7 @@ rtt_pipe_poll_func(void *arg)
itvl_ms = min(itvl_ms, RTT_INPUT_POLL_INTERVAL_MAX);
} else {
while (key >= 0 && avail > 0) {
- recv_buf[recv_off] = (u8_t) key;
+ recv_buf[recv_off] = (uint8_t) key;
recv_off++;
avail = recv_buf_len - recv_off;
key = rtt_pipe_get_char((unsigned int) rtt_index_down);
@@ -93,14 +93,14 @@ rtt_pipe_poll_func(void *arg)
}
int
-bttester_pipe_send(const u8_t *data, int len)
+bttester_pipe_send(const uint8_t *data, int len)
{
SEGGER_RTT_Write((unsigned int) rtt_index_up, data, (unsigned int) len);
return 0;
}
void
-bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb)
+bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb)
{
recv_buf = buf;
recv_buf_len = len;
diff --git a/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c b/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c
index ecbefa02..1118d9af 100644
--- a/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c
+++ b/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c
@@ -26,7 +26,7 @@
#include "bttester_pipe.h"
-static u8_t *recv_buf;
+static uint8_t *recv_buf;
static size_t recv_buf_len;
static bttester_pipe_recv_cb app_cb;
static size_t recv_off;
@@ -144,7 +144,7 @@ uart_console_rx_char(void *arg, uint8_t byte)
static int
uart_pipe_handle_char(int key)
{
- recv_buf[recv_off] = (u8_t) key;
+ recv_buf[recv_off] = (uint8_t) key;
recv_off++;
return 0;
@@ -194,7 +194,7 @@ uart_console_rx_char_event(struct os_event *ev)
}
int
-bttester_pipe_send(const u8_t *data, int len)
+bttester_pipe_send(const uint8_t *data, int len)
{
int i;
@@ -272,7 +272,7 @@ bttester_pipe_init(void)
}
void
-bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb)
+bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb)
{
recv_buf = buf;
recv_buf_len = len;
diff --git a/src/libs/mynewt-nimble/apps/bttester/syscfg.yml b/src/libs/mynewt-nimble/apps/bttester/syscfg.yml
index d0fffe13..db869c34 100644
--- a/src/libs/mynewt-nimble/apps/bttester/syscfg.yml
+++ b/src/libs/mynewt-nimble/apps/bttester/syscfg.yml
@@ -53,7 +53,7 @@ syscfg.defs:
BTTESTER_CONN_RETRY:
description: Retry connections when connection failed to be established
- value: 3
+ value: 0
BTTESTER_BTP_DATA_SIZE_MAX:
description: Maximum BTP payload
@@ -71,12 +71,16 @@ syscfg.defs:
description: Enable logging BTP traffic
value: 0
+ BTTESTER_L2CAP_COC_MTU:
+ description: Maximum MTU size the application can handle
+ value: 230
+
syscfg.vals:
OS_MAIN_STACK_SIZE: 512
SHELL_TASK: 0
SHELL_NEWTMGR: 0
LOG_LEVEL: 12
- MSYS_1_BLOCK_COUNT: 48
+ MSYS_1_BLOCK_COUNT: 80
BLE_MONITOR_RTT: 1
CONSOLE_RTT: 0
@@ -86,6 +90,8 @@ syscfg.vals:
BLE_L2CAP_COC_MAX_NUM: 2
BLE_L2CAP_SIG_MAX_PROCS: 2
+ BLE_L2CAP_ENHANCED_COC: 1
+ BLE_VERSION: 52
# Some testcases require MPS < MTU
BLE_L2CAP_COC_MPS: 100
BLE_RPA_TIMEOUT: 30
@@ -98,6 +104,9 @@ syscfg.vals:
BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9
BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30
BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000
+ BLE_SVC_GAP_APPEARANCE_WRITE_PERM: 0
+ BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM: 0
+ BLE_STORE_CONFIG_PERSIST: 0
BLE_MESH: 1
BLE_MESH_SHELL: 0
@@ -117,6 +126,11 @@ syscfg.vals:
BLE_MESH_FRIEND: 1
BLE_MESH_CFG_CLI: 1
BLE_MESH_RX_SDU_MAX: 110
+ BLE_MESH_HEALTH_CLI: 1
+ BLE_MESH_FRIEND_QUEUE_SIZE: 32
+ BLE_MESH_RX_SEG_MAX: 13
+ BLE_MESH_TX_SEG_MSG_COUNT: 2
+ BLE_MAX_CONNECTIONS: 8
BLE_MESH_ADV_BUF_COUNT: 20
BLE_MESH_TX_SEG_MAX: 6
diff --git a/src/libs/mynewt-nimble/apps/central/pkg.yml b/src/libs/mynewt-nimble/apps/central/pkg.yml
new file mode 100755
index 00000000..c10ad933
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/central/pkg.yml
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+pkg.name: "apps/central"
+pkg.type: app
+pkg.description: "Basic central application"
+pkg.author: "Krzysztof Kopyściński "
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/stats/full"
+ - "@apache-mynewt-core/sys/log/modlog"
+ - "@apache-mynewt-nimble/nimble/host"
+ - "@apache-mynewt-nimble/nimble/host/util/"
+ - "@apache-mynewt-nimble/nimble/host/store/config"
+ - "@apache-mynewt-nimble/nimble/transport"
diff --git a/src/libs/mynewt-nimble/apps/central/src/main.c b/src/libs/mynewt-nimble/apps/central/src/main.c
new file mode 100755
index 00000000..b2370359
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/central/src/main.c
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "console/console.h"
+#include "host/ble_hs.h"
+#include "host/util/util.h"
+#include "console/console.h"
+#include "log/log.h"
+
+static uint8_t g_own_addr_type;
+
+static void
+ble_app_set_addr(void)
+{
+ ble_addr_t addr;
+ int rc;
+
+ /* generate new non-resolvable private address */
+ rc = ble_hs_id_gen_rnd(0, &addr);
+ assert(rc == 0);
+
+ /* set generated address */
+ rc = ble_hs_id_set_rnd(addr.val);
+ assert(rc == 0);
+}
+
+/* scan_event() calls scan(), so forward declaration is required */
+static void scan(void);
+
+/* connection has separate event handler from scan */
+static int
+conn_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO,"Connection was established\n");
+ ble_gap_terminate(event->connect.conn_handle, 0x13);
+ } else {
+ MODLOG_DFLT(INFO,"Connection failed, error code: %i\n",
+ event->connect.status);
+ }
+ break;
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO,"Disconnected, reason code: %i\n",
+ event->disconnect.reason);
+ scan();
+ break;
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ MODLOG_DFLT(INFO,"Connection update request received\n");
+ break;
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status == 0) {
+ MODLOG_DFLT(INFO,"Connection update successful\n");
+ } else {
+ MODLOG_DFLT(INFO,"Connection update failed; reson: %d\n",
+ event->conn_update.status);
+ }
+ break;
+ default:
+ MODLOG_DFLT(INFO,"Connection event type not supported, %d\n",
+ event->type);
+ break;
+ }
+ return 0;
+}
+
+static int
+scan_event(struct ble_gap_event *event, void *arg)
+{
+ /* predef_uuid stores information about UUID of device,
+ that we connect to */
+ const ble_uuid128_t predef_uuid =
+ BLE_UUID128_INIT(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff);
+ struct ble_hs_adv_fields parsed_fields;
+ int uuid_cmp_result;
+
+ memset(&parsed_fields, 0, sizeof(parsed_fields));
+
+ switch (event->type) {
+ /* advertising report has been received during discovery procedure */
+ case BLE_GAP_EVENT_DISC:
+ MODLOG_DFLT(INFO, "Advertising report received! Checking UUID...\n");
+ ble_hs_adv_parse_fields(&parsed_fields, event->disc.data,
+ event->disc.length_data);
+ /* Predefined UUID is compared to recieved one;
+ if doesn't fit - end procedure and go back to scanning,
+ else - connect. */
+ uuid_cmp_result = ble_uuid_cmp(&predef_uuid.u, &parsed_fields.uuids128->u);
+ if (uuid_cmp_result) {
+ MODLOG_DFLT(INFO, "UUID doesn't fit\n");
+ } else {
+ MODLOG_DFLT(INFO, "UUID fits, connecting...\n");
+ ble_gap_disc_cancel();
+ ble_gap_connect(g_own_addr_type, &(event->disc.addr), 10000,
+ NULL, conn_event, NULL);
+ }
+ break;
+ case BLE_GAP_EVENT_DISC_COMPLETE:
+ MODLOG_DFLT(INFO,"Discovery completed, reason: %d\n",
+ event->disc_complete.reason);
+ scan();
+ break;
+ default:
+ MODLOG_DFLT(ERROR, "Discovery event not handled\n");
+ break;
+ }
+ return 0;
+}
+
+static void
+scan(void)
+{
+ int rc;
+
+ /* set scan parameters:
+ - scan interval in 0.625ms units
+ - scan window in 0.625ms units
+ - filter policy - 0 if whitelisting not used
+ - limited - should limited discovery be used
+ - passive - should passive scan be used
+ - filter duplicates - 1 enables filtering duplicated advertisements */
+ const struct ble_gap_disc_params scan_params = {10000, 200, 0, 0, 0, 1};
+
+ /* performs discovery procedure */
+ rc = ble_gap_disc(g_own_addr_type, 10000, &scan_params,scan_event, NULL);
+ assert(rc == 0);
+}
+
+static void
+on_sync(void)
+{
+ int rc;
+ /* Generate a non-resolvable private address. */
+ ble_app_set_addr();
+
+ /* g_own_addr_type will store type of addres our BSP uses */
+
+ rc = ble_hs_util_ensure_addr(0);
+ rc = ble_hs_id_infer_auto(0, &g_own_addr_type);
+ assert(rc == 0);
+ /* begin scanning */
+ scan();
+}
+
+static void
+on_reset(int reason)
+{
+ console_printf("Resetting state; reason=%d\n", reason);
+}
+
+int
+main(int argc, char **argv)
+{
+ /* Initialize all packages. */
+ sysinit();
+
+ ble_hs_cfg.sync_cb = on_sync;
+ ble_hs_cfg.reset_cb = on_reset;
+
+ /* As the last thing, process events from default event queue. */
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/README.md b/src/libs/mynewt-nimble/apps/mesh_badge/README.md
new file mode 100644
index 00000000..8d2b3fa3
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/README.md
@@ -0,0 +1,48 @@
+### Mesh Badge
+
+
+##### Overview
+********
+
+This sample app for the reel board showcases Bluetooth Mesh
+
+The app starts off as a regular Bluetooth GATT peripheral application.
+Install the the "nRF Connect" app on your phone (available both for
+Android and iOS) to access the service that the app exposes. The service
+can also be accessed with any Bluetooth LE GATT client from your PC,
+however these instructions focus on the necessary steps for phones.
+
+##### Steps to set up
+***************
+
+* On your phone, use the nRF Connect app to Scan for devices and look
+ for "reel board"
+* Connect to the device. You'll see a single service - select it
+* Request to write to the characteristic by pressing on the upward pointing
+ arrow symbol
+* Select "Text" to enter text instead of hex
+* Enter your name (or any other arbitrary text). Multiple words
+ separated by spaces are possible. The font used on the reel display
+ allows three rows of up to 12 characters
+ wide text. You can force line breaks with a comma.
+* Press "Send" - this will trigger pairing since this is a protected
+ characteristic. The passkey for the pairing will be shown on the board's
+ display. Enter the passkey in your phone.
+* Once pairing is complete the board will show the text you sent. If
+ you're not happy with it you can try writing something else.
+* When you're happy with the text, disconnect from the board (exit the app or
+ go back to the device scan page)
+* Once disconnected the board switches over to Bluetooth Mesh mode, and you
+ can't connect to it anymore over GATT.
+
+If you configure multiple boards like this they can communicate with
+each other over mesh: by pressing the user button on the board the first
+word (name) of the stored text will be sent to all other boards in
+the network and cause the other boards to display " says hi!".
+
+To reset a board to its initial state (disable mesh, erase the stored
+text, and make it connectable over GATT):
+
+* Keep the user button pressed when powering on (or press the reset button
+ when powered)
+* Wait until "Reseting Device" is shown
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml b/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml
new file mode 100644
index 00000000..0718236f
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml
@@ -0,0 +1,39 @@
+# 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.
+#
+pkg.name: apps/mesh_badge
+pkg.type: app
+pkg.description: Sample app for the reel board that showcases Bluetooth Mesh
+pkg.author: "Apache Mynewt "
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/drivers/display/cfb"
+ - "@apache-mynewt-core/hw/drivers/display/ssd1673"
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/log/modlog"
+ - "@apache-mynewt-core/sys/stats/full"
+ - "@apache-mynewt-core/sys/shell"
+ - nimble/controller
+ - nimble/host
+ - nimble/host/services/gap
+ - nimble/host/services/gatt
+ - nimble/host/store/config
+ - nimble/transport/ram
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h
new file mode 100644
index 00000000..af77e0b4
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018 Phytec Messtechnik GmbH
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/mesh.h"
+
+void board_refresh_display(void);
+void board_show_text(const char *text, bool center, int32_t duration);
+void board_blink_leds(void);
+void board_add_hello(uint16_t addr, const char *name);
+void board_add_heartbeat(uint16_t addr, uint8_t hops);
+int board_init(void);
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c
new file mode 100644
index 00000000..c6005a68
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+
+#include "services/gap/ble_svc_gap.h"
+#include "bsp/bsp.h"
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+
+#include "mesh.h"
+#include "board.h"
+#include "mesh_badge.h"
+
+static const ble_uuid16_t gatt_cud_uuid = BLE_UUID16_INIT(0x2901);
+static const ble_uuid16_t gatt_cpf_uuid = BLE_UUID16_INIT(0x2904);
+
+/** @brief GATT Characteristic Presentation Format Attribute Value. */
+struct bt_gatt_cpf {
+ /** Format of the value of the characteristic */
+ uint8_t format;
+ /** Exponent field to determine how the value of this characteristic is further formatted */
+ int8_t exponent;
+ /** Unit of the characteristic */
+ uint16_t unit;
+ /** Name space of the description */
+ uint8_t name_space;
+ /** Description of the characteristic as defined in a higher layer profile */
+ uint16_t description;
+} __packed;
+
+#define CPF_FORMAT_UTF8 0x19
+
+static const struct bt_gatt_cpf name_cpf = {
+ .format = CPF_FORMAT_UTF8,
+};
+
+static const ble_uuid128_t name_uuid = BLE_UUID128_INIT(
+ 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static const ble_uuid128_t name_enc_uuid = BLE_UUID128_INIT(
+ 0xf1, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static int
+gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+ {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = &name_uuid.u,
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = &name_enc_uuid.u,
+ .access_cb = gatt_svr_chr_access,
+ .flags = BLE_GATT_CHR_F_READ |
+ BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
+ .descriptors = (struct ble_gatt_dsc_def[]) { {
+ .uuid = &gatt_cud_uuid.u,
+ .access_cb = gatt_svr_chr_access,
+ .att_flags = BLE_ATT_F_READ,
+ }, {
+ .uuid = &gatt_cpf_uuid.u,
+ .access_cb = gatt_svr_chr_access,
+ .att_flags = BLE_ATT_F_READ,
+ }, {
+ 0, /* No more descriptors in this characteristic. */
+ } }
+ }, {
+ 0, /* No more characteristics in this service. */
+ } },
+ },
+
+ {
+ 0, /* No more services. */
+ },
+};
+
+static int read_name(struct os_mbuf *om)
+{
+ const char *value = bt_get_name();
+ int rc;
+
+ rc = os_mbuf_append(om, value, (uint16_t) strlen(value));
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+}
+
+static int write_name(struct os_mbuf *om)
+{
+ char name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
+ uint16_t len;
+ uint16_t om_len;
+ int rc;
+
+ om_len = OS_MBUF_PKTLEN(om);
+ if (om_len >= sizeof(name)) {
+ return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+ }
+
+ rc = ble_hs_mbuf_to_flat(om, name, sizeof(name) - 1, &len);
+ if (rc != 0) {
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+
+ name[len] = '\0';
+
+ rc = bt_set_name(name);
+ if (rc) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+
+ board_refresh_display();
+
+ return 0;
+}
+
+static int
+gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg)
+{
+ const ble_uuid_t *uuid;
+ int rc;
+
+ uuid = ctxt->chr->uuid;
+
+ if (ble_uuid_cmp(uuid, &name_enc_uuid.u) == 0) {
+ switch (ctxt->op) {
+ case BLE_GATT_ACCESS_OP_READ_CHR:
+ rc = read_name(ctxt->om);
+ return rc;
+
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ rc = write_name(ctxt->om);
+ return rc;
+
+ default:
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+ } else if (ble_uuid_cmp(uuid, &gatt_cud_uuid.u) == 0) {
+ rc = os_mbuf_append(ctxt->om, "Badge Name",
+ (uint16_t) strlen("Badge Name"));
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+ } else if (ble_uuid_cmp(uuid, &gatt_cpf_uuid.u) == 0) {
+ rc = os_mbuf_append(ctxt->om, &name_cpf,
+ (uint16_t) sizeof(name_cpf));
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+
+ /* Unknown characteristic; the nimble stack should not have called this
+ * function.
+ */
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
+}
+
+void
+gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+ char buf[BLE_UUID_STR_LEN];
+
+ switch (ctxt->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
+ ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+ ctxt->svc.handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ MODLOG_DFLT(DEBUG, "registering characteristic %s with "
+ "def_handle=%d val_handle=%d\n",
+ ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+ ctxt->chr.def_handle,
+ ctxt->chr.val_handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
+ ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+ ctxt->dsc.handle);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+int
+gatt_svr_init(void)
+{
+ int rc;
+
+ rc = ble_gatts_count_cfg(gatt_svr_svcs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_gatts_add_svcs(gatt_svr_svcs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c
new file mode 100644
index 00000000..d856d816
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+#include "host/ble_gap.h"
+#include "mesh/glue.h"
+#include "services/gap/ble_svc_gap.h"
+#include "base64/base64.h"
+
+#include "mesh_badge.h"
+#include "mesh.h"
+#include "board.h"
+
+static char badge_name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
+
+#define MESH_BADGE_NAME_ENCODE_SIZE \
+ BASE64_ENCODE_SIZE(sizeof(badge_name))
+
+static bool reset_mesh;
+
+void print_addr(const void *addr)
+{
+ const uint8_t *u8p;
+
+ u8p = addr;
+ MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
+ u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+}
+
+static void
+print_conn_desc(struct ble_gap_conn_desc *desc)
+{
+ MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=",
+ desc->conn_handle, desc->our_ota_addr.type);
+ print_addr(desc->our_ota_addr.val);
+ MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=",
+ desc->our_id_addr.type);
+ print_addr(desc->our_id_addr.val);
+ MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=",
+ desc->peer_ota_addr.type);
+ print_addr(desc->peer_ota_addr.val);
+ MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=",
+ desc->peer_id_addr.type);
+ print_addr(desc->peer_id_addr.val);
+ MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+ "encrypted=%d authenticated=%d bonded=%d\n",
+ desc->conn_itvl, desc->conn_latency,
+ desc->supervision_timeout,
+ desc->sec_state.encrypted,
+ desc->sec_state.authenticated,
+ desc->sec_state.bonded);
+}
+
+static int gap_event(struct ble_gap_event *event, void *arg);
+
+static void advertise(void)
+{
+ uint8_t own_addr_type;
+ struct ble_gap_adv_params adv_params;
+ struct ble_hs_adv_fields fields;
+ const char *name;
+ int rc;
+
+ /* Figure out address to use while advertising (no privacy for now) */
+ rc = ble_hs_id_infer_auto(0, &own_addr_type);
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
+ return;
+ }
+
+ /**
+ * Set the advertisement data included in our advertisements:
+ * o Flags (indicates advertisement type and other general info).
+ * o Advertising tx power.
+ * o Device name.
+ * o 16-bit service UUIDs (alert notifications).
+ */
+
+ memset(&fields, 0, sizeof fields);
+
+ /* Advertise two flags:
+ * o Discoverability in forthcoming advertisement (general)
+ * o BLE-only (BR/EDR unsupported).
+ */
+ fields.flags = BLE_HS_ADV_F_DISC_GEN |
+ BLE_HS_ADV_F_BREDR_UNSUP;
+
+#if 0
+ /* Indicate that the TX power level field should be included; have the
+ * stack fill this value automatically. This is done by assiging the
+ * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
+ */
+ fields.tx_pwr_lvl_is_present = 1;
+ fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+#endif
+
+ name = ble_svc_gap_device_name();
+ fields.name = (uint8_t *)name;
+ fields.name_len = (uint8_t) strlen(name);
+ fields.name_is_complete = 1;
+
+ rc = ble_gap_adv_set_fields(&fields);
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
+ return;
+ }
+
+ /* Begin advertising. */
+ memset(&adv_params, 0, sizeof adv_params);
+ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+ adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
+ rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
+ &adv_params, gap_event, NULL);
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
+ return;
+ }
+}
+
+static void passkey_display(uint16_t conn_handle)
+{
+ char buf[20];
+ struct ble_sm_io pk;
+ int rc;
+
+ bt_rand(&pk.passkey, sizeof(pk.passkey));
+ /* Max value is 999999 */
+ pk.passkey %= 1000000;
+ pk.action = BLE_SM_IOACT_DISP;
+
+ rc = ble_sm_inject_io(conn_handle, &pk);
+ assert(rc == 0);
+
+ snprintk(buf, sizeof(buf), "Passkey:\n%06lu", pk.passkey);
+
+ printk("%s\n", buf);
+ board_show_text(buf, false, K_FOREVER);
+}
+
+static void pairing_complete(uint16_t conn_handle, bool bonded)
+{
+ printk("Pairing Complete\n");
+ board_show_text("Pairing Complete", false, K_SECONDS(2));
+}
+
+static void pairing_failed(uint16_t conn_handle)
+{
+ printk("Pairing Failed\n");
+ board_show_text("Pairing Failed", false, K_SECONDS(2));
+}
+
+static void connected(uint16_t conn_handle, int err)
+{
+ printk("Connected (err 0x%02x)\n", err);
+
+ if (err) {
+ board_show_text("Connection failed", false, K_SECONDS(2));
+ } else {
+ board_show_text("Connected", false, K_FOREVER);
+ }
+}
+
+static void disconnected(uint16_t conn_handle, int reason)
+{
+ printk("Disconnected (reason 0x%02x)\n", reason);
+
+ if (strcmp(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME), bt_get_name()) != 0 &&
+ !mesh_is_initialized()) {
+ /* Mesh will take over advertising control */
+ ble_gap_adv_stop();
+ mesh_start();
+ } else {
+ board_show_text("Disconnected", false, K_SECONDS(2));
+ }
+}
+
+static int gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ MODLOG_DFLT(INFO, "connection %s; status=%d ",
+ event->connect.status == 0 ? "established" : "failed",
+ event->connect.status);
+ if (event->connect.status == 0) {
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ print_conn_desc(&desc);
+ connected(event->connect.conn_handle,
+ event->connect.status);
+ }
+ MODLOG_DFLT(INFO, "\n");
+
+ if (event->connect.status != 0) {
+ /* Connection failed; resume advertising. */
+ advertise();
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
+ print_conn_desc(&event->disconnect.conn);
+ MODLOG_DFLT(INFO, "\n");
+
+ /* Connection terminated; resume advertising. */
+ advertise();
+
+ disconnected(event->disconnect.conn.conn_handle,
+ event->disconnect.reason);
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ /* The central has updated the connection parameters. */
+ MODLOG_DFLT(INFO, "connection updated; status=%d ",
+ event->conn_update.status);
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ print_conn_desc(&desc);
+ MODLOG_DFLT(INFO, "\n");
+ return 0;
+
+ case BLE_GAP_EVENT_ENC_CHANGE:
+ /* Encryption has been enabled or disabled for this connection. */
+ MODLOG_DFLT(INFO, "encryption change event; status=%d ",
+ event->enc_change.status);
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ print_conn_desc(&desc);
+ MODLOG_DFLT(INFO, "\n");
+
+ if (desc.sec_state.bonded) {
+ pairing_complete(event->enc_change.conn_handle, true);
+ } else if(desc.sec_state.encrypted) {
+ pairing_complete(event->enc_change.conn_handle, false);
+ } else {
+ pairing_failed(event->enc_change.conn_handle);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_PASSKEY_ACTION:
+ MODLOG_DFLT(INFO, "passkey action event; conn_handle=%d action=%d numcmp=%d\n",
+ event->passkey.conn_handle,
+ event->passkey.params.action,
+ event->passkey.params.numcmp);
+ passkey_display(event->passkey.conn_handle);
+ return 0;
+
+ case BLE_GAP_EVENT_REPEAT_PAIRING:
+ /* We already have a bond with the peer, but it is attempting to
+ * establish a new secure link. This app sacrifices security for
+ * convenience: just throw away the old bond and accept the new link.
+ */
+
+ /* Delete the old bond. */
+ rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
+ assert(rc == 0);
+ ble_store_util_delete_peer(&desc.peer_id_addr);
+
+ /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
+ * continue with the pairing operation.
+ */
+ return BLE_GAP_REPEAT_PAIRING_RETRY;
+
+ }
+
+ return 0;
+}
+
+static void on_sync(void)
+{
+ int err;
+ ble_addr_t addr;
+
+ /* Use NRPA */
+ err = ble_hs_id_gen_rnd(1, &addr);
+ assert(err == 0);
+ err = ble_hs_id_set_rnd(addr.val);
+ assert(err == 0);
+
+ printk("Bluetooth initialized\n");
+
+ err = mesh_init(addr.type);
+ if (err) {
+ printk("Initializing mesh failed (err %d)\n", err);
+ return;
+ }
+
+ printk("Mesh initialized\n");
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ settings_load();
+ }
+
+ if (reset_mesh) {
+ bt_mesh_reset();
+ reset_mesh = false;
+ }
+
+ if (!mesh_is_initialized()) {
+ advertise();
+ } else {
+ printk("Already provisioned\n");
+ ble_svc_gap_device_name_set(bt_get_name());
+ }
+
+ board_refresh_display();
+
+ printk("Board started\n");
+}
+
+void schedule_mesh_reset(void)
+{
+ reset_mesh = true;
+}
+
+static void on_reset(int reason)
+{
+ MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
+}
+
+const char *bt_get_name(void)
+{
+ char buf[MESH_BADGE_NAME_ENCODE_SIZE];
+ int rc, len;
+
+ rc = conf_get_stored_value("mesh_badge/badge_name",
+ buf, sizeof(buf));
+ if (rc == OS_ENOENT) {
+ bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
+ } else {
+ assert(rc == 0);
+ }
+
+ memset(badge_name, '\0', sizeof(badge_name));
+ len = base64_decode(buf, badge_name);
+ if (len < 0) {
+ bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
+ }
+
+ return badge_name;
+}
+
+int bt_set_name(const char *name)
+{
+ char buf[MESH_BADGE_NAME_ENCODE_SIZE];
+ int rc;
+
+ memset(badge_name, '\0', sizeof(badge_name));
+ memcpy(badge_name, name, strlen(name));
+ base64_encode(badge_name, sizeof(badge_name), buf, 1);
+ rc = conf_save_one("mesh_badge/badge_name", buf);
+ assert(rc == 0);
+
+ return 0;
+}
+
+int main(void)
+{
+ int err;
+
+ /* Initialize OS */
+ sysinit();
+
+ err = board_init();
+ if (err) {
+ printk("board init failed (err %d)\n", err);
+ assert(err == 0);
+ }
+
+ /* Initialize the NimBLE host configuration. */
+ ble_hs_cfg.reset_cb = on_reset;
+ ble_hs_cfg.sync_cb = on_sync;
+ ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
+ ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+ ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
+
+ err = gatt_svr_init();
+ assert(err == 0);
+
+ /*
+ * As the last thing, process events from default event queue.
+ */
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c
new file mode 100644
index 00000000..ee999172
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+#include "mesh/mesh.h"
+
+#include "mesh_badge.h"
+#include "mesh.h"
+#include "board.h"
+
+#define BT_COMP_ID_LF 0x05f1
+
+#define MOD_LF 0x0000
+#define OP_HELLO 0xbb
+#define OP_HEARTBEAT 0xbc
+#define OP_VND_HELLO BT_MESH_MODEL_OP_3(OP_HELLO, BT_COMP_ID_LF)
+#define OP_VND_HEARTBEAT BT_MESH_MODEL_OP_3(OP_HEARTBEAT, BT_COMP_ID_LF)
+
+#define DEFAULT_TTL 31
+#define GROUP_ADDR 0xc123
+#define NET_IDX 0x000
+#define APP_IDX 0x000
+#define FLAGS 0
+static struct ble_npl_callout hello_work;
+static struct ble_npl_callout mesh_start_work;
+
+static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
+ uint16_t feat)
+{
+ board_show_text("Heartbeat Received", false, K_SECONDS(2));
+}
+
+static struct bt_mesh_cfg_cli cfg_cli = {
+};
+
+static void attention_on(struct bt_mesh_model *model)
+{
+ board_show_text("Attention!", false, K_SECONDS(2));
+}
+
+static void attention_off(struct bt_mesh_model *model)
+{
+ board_refresh_display();
+}
+
+static const struct bt_mesh_health_srv_cb health_srv_cb = {
+ .attn_on = attention_on,
+ .attn_off = attention_off,
+};
+
+static struct bt_mesh_health_srv health_srv = {
+ .cb = &health_srv_cb,
+};
+
+static struct os_mbuf *bt_mesh_pub_msg_health_pub;
+static struct bt_mesh_model_pub health_pub;
+
+static struct bt_mesh_model root_models[] = {
+ BT_MESH_MODEL_CFG_SRV,
+ BT_MESH_MODEL_CFG_CLI(&cfg_cli),
+ BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
+};
+
+static void vnd_hello(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ char str[32];
+ size_t len;
+
+ printk("Hello message from 0x%04x\n", ctx->addr);
+
+ if (ctx->addr == bt_mesh_model_elem(model)->addr) {
+ printk("Ignoring message from self\n");
+ return;
+ }
+
+ len = min(buf->om_len, 8);
+ memcpy(str, buf->om_data, len);
+ str[len] = '\0';
+
+ board_add_hello(ctx->addr, str);
+
+ strcpy(str + len, " says hi!");
+
+ board_show_text(str, false, K_SECONDS(3));
+
+ board_blink_leds();
+}
+
+static void vnd_heartbeat(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ uint8_t init_ttl, hops;
+
+ /* Ignore messages from self */
+ if (ctx->addr == bt_mesh_model_elem(model)->addr) {
+ return;
+ }
+
+ init_ttl = net_buf_simple_pull_u8(buf);
+ hops = init_ttl - ctx->recv_ttl + 1;
+
+ printk("Heartbeat from 0x%04x over %u hop%s\n", ctx->addr,
+ hops, hops == 1 ? "" : "s");
+
+ board_add_heartbeat(ctx->addr, hops);
+}
+
+static const struct bt_mesh_model_op vnd_ops[] = {
+ { OP_VND_HELLO, 1, vnd_hello },
+ { OP_VND_HEARTBEAT, 1, vnd_heartbeat },
+ BT_MESH_MODEL_OP_END,
+};
+
+static int pub_update(struct bt_mesh_model *mod)
+{
+ struct os_mbuf *msg = mod->pub->msg;
+
+ printk("Preparing to send heartbeat\n");
+
+ bt_mesh_model_msg_init(msg, OP_VND_HEARTBEAT);
+ net_buf_simple_add_u8(msg, DEFAULT_TTL);
+
+ return 0;
+}
+
+static struct os_mbuf *bt_mesh_pub_msg_vnd_pub;
+static struct bt_mesh_model_pub vnd_pub;
+
+static struct bt_mesh_model vnd_models[] = {
+ BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, NULL),
+};
+
+static struct bt_mesh_elem elements[] = {
+ BT_MESH_ELEM(0, root_models, vnd_models),
+};
+
+static const struct bt_mesh_comp comp = {
+ .cid = BT_COMP_ID_LF,
+ .elem = elements,
+ .elem_count = ARRAY_SIZE(elements),
+};
+
+static size_t first_name_len(const char *name)
+{
+ size_t len;
+
+ for (len = 0; *name; name++, len++) {
+ switch (*name) {
+ case ' ':
+ case ',':
+ case '\n':
+ return len;
+ }
+ }
+
+ return len;
+}
+
+static void send_hello(struct ble_npl_event *work)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 8 + 4);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = NET_IDX,
+ .app_idx = APP_IDX,
+ .addr = GROUP_ADDR,
+ .send_ttl = DEFAULT_TTL,
+ };
+ const char *name = bt_get_name();
+
+ bt_mesh_model_msg_init(msg, OP_VND_HELLO);
+ net_buf_simple_add_mem(msg, name, first_name_len(name));
+
+ if (bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL) == 0) {
+ board_show_text("Saying \"hi!\" to everyone", false,
+ K_SECONDS(2));
+ } else {
+ board_show_text("Sending Failed!", false, K_SECONDS(2));
+ }
+
+ os_mbuf_free_chain(msg);
+}
+
+void mesh_send_hello(void)
+{
+ k_work_submit(&hello_work);
+}
+
+static int provision_and_configure(void)
+{
+ static const uint8_t net_key[16] = {
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ };
+ static const uint8_t app_key[16] = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ };
+ static const uint16_t iv_index;
+ struct bt_mesh_cfg_mod_pub pub = {
+ .addr = GROUP_ADDR,
+ .app_idx = APP_IDX,
+ .ttl = DEFAULT_TTL,
+ .period = BT_MESH_PUB_PERIOD_SEC(10),
+ };
+ uint8_t dev_key[16];
+ uint16_t addr;
+ int err;
+
+ err = bt_rand(dev_key, sizeof(dev_key));
+ if (err) {
+ return err;
+ }
+
+ do {
+ err = bt_rand(&addr, sizeof(addr));
+ if (err) {
+ return err;
+ }
+ } while (!addr);
+
+ /* Make sure it's a unicast address (highest bit unset) */
+ addr &= ~0x8000;
+
+ err = bt_mesh_provision(net_key, NET_IDX, FLAGS, iv_index, addr,
+ dev_key);
+ if (err) {
+ return err;
+ }
+
+ printk("Configuring...\n");
+
+ /* Add Application Key */
+ bt_mesh_cfg_app_key_add(NET_IDX, addr, NET_IDX, APP_IDX, app_key, NULL);
+
+ /* Bind to vendor model */
+ bt_mesh_cfg_mod_app_bind_vnd(NET_IDX, addr, addr, APP_IDX,
+ MOD_LF, BT_COMP_ID_LF, NULL);
+
+ /* Bind to Health model */
+ bt_mesh_cfg_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
+ BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
+
+ /* Add model subscription */
+ bt_mesh_cfg_mod_sub_add_vnd(NET_IDX, addr, addr, GROUP_ADDR,
+ MOD_LF, BT_COMP_ID_LF, NULL);
+
+ bt_mesh_cfg_mod_pub_set_vnd(NET_IDX, addr, addr, MOD_LF, BT_COMP_ID_LF,
+ &pub, NULL);
+
+ printk("Configuration complete\n");
+
+ return addr;
+}
+
+static void start_mesh(struct ble_npl_event *work)
+{
+ int err;
+
+ err = provision_and_configure();
+ if (err < 0) {
+ board_show_text("Starting Mesh Failed", false,
+ K_SECONDS(2));
+ } else {
+ char buf[32];
+
+ snprintk(buf, sizeof(buf),
+ "Mesh Started\nAddr: 0x%04x", err);
+ board_show_text(buf, false, K_SECONDS(4));
+ }
+}
+
+void mesh_start(void)
+{
+ k_work_submit(&mesh_start_work);
+}
+
+bool mesh_is_initialized(void)
+{
+ return bt_mesh_is_provisioned();
+}
+
+uint16_t mesh_get_addr(void)
+{
+ return elements[0].addr;
+}
+
+int mesh_init(uint8_t addr_type)
+{
+ static const uint8_t dev_uuid[16] = { 0xc0, 0xff, 0xee };
+ static const struct bt_mesh_prov prov = {
+ .uuid = dev_uuid,
+ };
+
+ hb_cb = { .recv = heartbeat };
+
+ bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(0);
+ health_pub.msg = bt_mesh_pub_msg_health_pub;
+
+ bt_mesh_pub_msg_vnd_pub = NET_BUF_SIMPLE(3 + 1);
+ vnd_pub.msg = bt_mesh_pub_msg_vnd_pub;
+ vnd_pub.update = pub_update;
+
+ k_work_init(&hello_work, send_hello);
+ k_work_init(&mesh_start_work, start_mesh);
+
+ return bt_mesh_init(addr_type, &prov, &comp);
+}
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h
new file mode 100644
index 00000000..33ee7cd2
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/mesh.h"
+
+void mesh_send_hello(void);
+
+uint16_t mesh_get_addr(void);
+bool mesh_is_initialized(void);
+void mesh_start(void);
+int mesh_init(uint8_t addr_type);
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h
new file mode 100644
index 00000000..a156f1ce
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+struct ble_gatt_register_ctxt;
+
+void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+int gatt_svr_init(void);
+
+void schedule_mesh_reset(void);
+const char *bt_get_name(void);
+int bt_set_name(const char *);
+
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c
new file mode 100644
index 00000000..bc822937
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2018 Phytec Messtechnik GmbH
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "os/mynewt.h"
+#include "bsp/bsp.h"
+#include "console/console.h"
+#include "hal/hal_flash.h"
+#include "hal/hal_gpio.h"
+#include "mesh/glue.h"
+#include "services/gap/ble_svc_gap.h"
+
+#include "mesh_badge.h"
+#include "display/cfb.h"
+#include "mesh.h"
+#include "board.h"
+
+#define printk console_printf
+
+enum font_size {
+ FONT_BIG = 0,
+ FONT_MEDIUM = 1,
+ FONT_SMALL = 2,
+};
+
+struct font_info {
+ uint8_t columns;
+} fonts[] = {
+ [FONT_BIG] = { .columns = 12 },
+ [FONT_MEDIUM] = { .columns = 16 },
+ [FONT_SMALL] = { .columns = 25 },
+};
+
+#define LONG_PRESS_TIMEOUT K_SECONDS(1)
+
+#define STAT_COUNT 128
+
+#define EDGE (GPIO_INT_EDGE | GPIO_INT_DOUBLE_EDGE)
+
+#ifdef SW0_GPIO_FLAGS
+#define PULL_UP SW0_GPIO_FLAGS
+#else
+#define PULL_UP 0
+#endif
+
+static struct os_dev *epd_dev;
+static bool pressed;
+static bool stats_view;
+static struct k_delayed_work epd_work;
+static struct k_delayed_work long_press_work;
+
+static struct {
+ int pin;
+} leds[] = {
+ { .pin = LED_1, },
+ { .pin = RGB_LED_RED, },
+ { .pin = RGB_LED_GRN, },
+ { .pin = RGB_LED_BLU, },
+};
+
+struct k_delayed_work led_timer;
+
+static size_t print_line(enum font_size font_size, int row, const char *text,
+ size_t len, bool center)
+{
+ uint8_t font_height, font_width;
+ char line[fonts[FONT_SMALL].columns + 1];
+ int pad;
+
+ cfb_framebuffer_set_font(epd_dev, font_size);
+
+ len = min(len, fonts[font_size].columns);
+ memcpy(line, text, len);
+ line[len] = '\0';
+
+ if (center) {
+ pad = (fonts[font_size].columns - len) / 2;
+ } else {
+ pad = 0;
+ }
+
+ cfb_get_font_size(epd_dev, font_size, &font_width, &font_height);
+
+ if (cfb_print(epd_dev, line, font_width * pad, font_height * row)) {
+ printk("Failed to print a string\n");
+ }
+
+ return len;
+}
+
+static size_t get_len(enum font_size font, const char *text)
+{
+ const char *space = NULL;
+ size_t i;
+
+ for (i = 0; i <= fonts[font].columns; i++) {
+ switch (text[i]) {
+ case '\n':
+ case '\0':
+ return i;
+ case ' ':
+ space = &text[i];
+ break;
+ default:
+ continue;
+ }
+ }
+
+ /* If we got more characters than fits a line, and a space was
+ * encountered, fall back to the last space.
+ */
+ if (space) {
+ return space - text;
+ }
+
+ return fonts[font].columns;
+}
+
+void board_blink_leds(void)
+{
+ k_delayed_work_submit(&led_timer, K_MSEC(100));
+}
+
+void board_show_text(const char *text, bool center, int32_t duration)
+{
+ int i;
+
+ cfb_framebuffer_clear(epd_dev, false);
+
+ for (i = 0; i < 3; i++) {
+ size_t len;
+
+ while (*text == ' ' || *text == '\n') {
+ text++;
+ }
+
+ len = get_len(FONT_BIG, text);
+ if (!len) {
+ break;
+ }
+
+ text += print_line(FONT_BIG, i, text, len, center);
+ if (!*text) {
+ break;
+ }
+ }
+
+ cfb_framebuffer_finalize(epd_dev);
+
+ if (duration != K_FOREVER) {
+ k_delayed_work_submit(&epd_work, duration);
+ }
+}
+
+static struct stat {
+ uint16_t addr;
+ char name[9];
+ uint8_t min_hops;
+ uint8_t max_hops;
+ uint16_t hello_count;
+ uint16_t heartbeat_count;
+} stats[STAT_COUNT] = {
+ [0 ... (STAT_COUNT - 1)] = {
+ .min_hops = BT_MESH_TTL_MAX,
+ .max_hops = 0,
+ },
+};
+
+static uint32_t stat_count;
+
+#define NO_UPDATE -1
+
+static int add_hello(uint16_t addr, const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stats); i++) {
+ struct stat *stat = &stats[i];
+
+ if (!stat->addr) {
+ stat->addr = addr;
+ strncpy(stat->name, name, sizeof(stat->name) - 1);
+ stat->hello_count = 1;
+ stat_count++;
+ return i;
+ }
+
+ if (stat->addr == addr) {
+ /* Update name, incase it has changed */
+ strncpy(stat->name, name, sizeof(stat->name) - 1);
+
+ if (stat->hello_count < 0xffff) {
+ stat->hello_count++;
+ return i;
+ }
+
+ return NO_UPDATE;
+ }
+ }
+
+ return NO_UPDATE;
+}
+
+static int add_heartbeat(uint16_t addr, uint8_t hops)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stats); i++) {
+ struct stat *stat = &stats[i];
+
+ if (!stat->addr) {
+ stat->addr = addr;
+ stat->heartbeat_count = 1;
+ stat->min_hops = hops;
+ stat->max_hops = hops;
+ stat_count++;
+ return i;
+ }
+
+ if (stat->addr == addr) {
+ if (hops < stat->min_hops) {
+ stat->min_hops = hops;
+ } else if (hops > stat->max_hops) {
+ stat->max_hops = hops;
+ }
+
+ if (stat->heartbeat_count < 0xffff) {
+ stat->heartbeat_count++;
+ return i;
+ }
+
+ return NO_UPDATE;
+ }
+ }
+
+ return NO_UPDATE;
+}
+
+void board_add_hello(uint16_t addr, const char *name)
+{
+ uint32_t sort_i;
+
+ sort_i = add_hello(addr, name);
+ if (sort_i != NO_UPDATE) {
+ }
+}
+
+void board_add_heartbeat(uint16_t addr, uint8_t hops)
+{
+ uint32_t sort_i;
+
+ sort_i = add_heartbeat(addr, hops);
+ if (sort_i != NO_UPDATE) {
+ }
+}
+
+static void show_statistics(void)
+{
+ int top[4] = { -1, -1, -1, -1 };
+ int len, i, line = 0;
+ struct stat *stat;
+ char str[32];
+
+ cfb_framebuffer_clear(epd_dev, false);
+
+ len = snprintk(str, sizeof(str),
+ "Own Address: 0x%04x", mesh_get_addr());
+ print_line(FONT_SMALL, line++, str, len, false);
+
+ len = snprintk(str, sizeof(str),
+ "Node Count: %lu", stat_count + 1);
+ print_line(FONT_SMALL, line++, str, len, false);
+
+ /* Find the top sender */
+ for (i = 0; i < ARRAY_SIZE(stats); i++) {
+ int j;
+
+ stat = &stats[i];
+ if (!stat->addr) {
+ break;
+ }
+
+ if (!stat->hello_count) {
+ continue;
+ }
+
+ for (j = 0; j < ARRAY_SIZE(top); j++) {
+ if (top[j] < 0) {
+ top[j] = i;
+ break;
+ }
+
+ if (stat->hello_count <= stats[top[j]].hello_count) {
+ continue;
+ }
+
+ /* Move other elements down the list */
+ if (j < ARRAY_SIZE(top) - 1) {
+ memmove(&top[j + 1], &top[j],
+ ((ARRAY_SIZE(top) - j - 1) *
+ sizeof(top[j])));
+ }
+
+ top[j] = i;
+ break;
+ }
+ }
+
+ if (stat_count >= 0) {
+ len = snprintk(str, sizeof(str), "Most messages from:");
+ print_line(FONT_SMALL, line++, str, len, false);
+
+ for (i = 0; i < ARRAY_SIZE(top); i++) {
+ if (top[i] < 0) {
+ break;
+ }
+
+ stat = &stats[top[i]];
+
+ len = snprintk(str, sizeof(str), "%-3u 0x%04x %s",
+ stat->hello_count, stat->addr,
+ stat->name);
+ print_line(FONT_SMALL, line++, str, len, false);
+ }
+ }
+
+ cfb_framebuffer_finalize(epd_dev);
+}
+
+static void epd_update(struct ble_npl_event *work)
+{
+ char buf[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
+ int i;
+
+ if (stats_view) {
+ show_statistics();
+ return;
+ }
+
+ strncpy(buf, bt_get_name(), sizeof(buf));
+
+ /* Convert commas to newlines */
+ for (i = 0; buf[i] != '\0'; i++) {
+ if (buf[i] == ',') {
+ buf[i] = '\n';
+ }
+ }
+
+ board_show_text(buf, true, K_FOREVER);
+}
+
+static void long_press(struct ble_npl_event *work)
+{
+ /* Treat as release so actual release doesn't send messages */
+ pressed = false;
+ stats_view = !stats_view;
+ board_refresh_display();
+}
+
+static bool button_is_pressed(void)
+{
+ uint32_t val;
+
+ val = (uint32_t) hal_gpio_read(BUTTON_1);
+
+ return !val;
+}
+
+static void button_interrupt(struct os_event *ev)
+{
+ int pin_pos = (int ) ev->ev_arg;
+
+ if (button_is_pressed() == pressed) {
+ return;
+ }
+
+ pressed = !pressed;
+ printk("Button %s\n", pressed ? "pressed" : "released");
+
+ if (pressed) {
+ k_delayed_work_submit(&long_press_work, LONG_PRESS_TIMEOUT);
+ return;
+ }
+
+ k_delayed_work_cancel(&long_press_work);
+
+ if (!mesh_is_initialized()) {
+ return;
+ }
+
+ /* Short press does currently nothing in statistics view */
+ if (stats_view) {
+ return;
+ }
+
+ if (pin_pos == BUTTON_1) {
+ mesh_send_hello();
+ }
+}
+
+static struct os_event button_event;
+
+static void
+gpio_irq_handler(void *arg)
+{
+ button_event.ev_arg = arg;
+ os_eventq_put(os_eventq_dflt_get(), &button_event);
+}
+
+static int configure_button(void)
+{
+ button_event.ev_cb = button_interrupt;
+
+ hal_gpio_irq_init(BUTTON_1, gpio_irq_handler, (void *) BUTTON_1,
+ HAL_GPIO_TRIG_BOTH, HAL_GPIO_PULL_UP);
+ hal_gpio_irq_enable(BUTTON_1);
+
+ return 0;
+}
+
+static void led_timeout(struct ble_npl_event *work)
+{
+ static int led_cntr;
+ int i;
+
+ /* Disable all LEDs */
+ for (i = 0; i < ARRAY_SIZE(leds); i++) {
+ hal_gpio_write(leds[i].pin, 1);
+ }
+
+ /* Stop after 5 iterations */
+ if (led_cntr > (ARRAY_SIZE(leds) * 5)) {
+ led_cntr = 0;
+ return;
+ }
+
+ /* Select and enable current LED */
+ i = led_cntr++ % ARRAY_SIZE(leds);
+ hal_gpio_write(leds[i].pin, 0);
+
+ k_delayed_work_submit(&led_timer, K_MSEC(100));
+}
+
+static int configure_leds(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++) {
+ hal_gpio_init_out(leds[i].pin, 1);
+ }
+
+ k_delayed_work_init(&led_timer, led_timeout);
+ return 0;
+}
+
+static int erase_storage(void)
+{
+ bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
+ ble_store_clear();
+ schedule_mesh_reset();
+ return 0;
+}
+
+void board_refresh_display(void)
+{
+ k_delayed_work_submit(&epd_work, K_NO_WAIT);
+}
+
+int board_init(void)
+{
+ epd_dev = os_dev_lookup(MYNEWT_VAL(SSD1673_OS_DEV_NAME));
+ if (epd_dev == NULL) {
+ printk("SSD1673 device not found\n");
+ return -ENODEV;
+ }
+
+ if (cfb_framebuffer_init(epd_dev)) {
+ printk("Framebuffer initialization failed\n");
+ return -EIO;
+ }
+
+ cfb_framebuffer_clear(epd_dev, true);
+
+ if (configure_button()) {
+ printk("Failed to configure button\n");
+ return -EIO;
+ }
+
+ if (configure_leds()) {
+ printk("LED init failed\n");
+ return -EIO;
+ }
+
+ k_delayed_work_init(&epd_work, epd_update);
+ k_delayed_work_init(&long_press_work, long_press);
+
+ pressed = button_is_pressed();
+ if (pressed) {
+ printk("Erasing storage\n");
+ board_show_text("Resetting Device", false, K_SECONDS(4));
+ erase_storage();
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml b/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml
new file mode 100644
index 00000000..0c60c016
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml
@@ -0,0 +1,58 @@
+# 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.
+#
+
+# Package: apps/mesh_badge
+
+syscfg.vals:
+ # Enable the shell task.
+ SHELL_TASK: 1
+
+ # Set log level to info (disable debug logging).
+ LOG_LEVEL: 1
+
+ # Default task settings
+ OS_MAIN_STACK_SIZE: 768
+
+ # Newtmgr is not supported in this app, so disable newtmgr-over-shell.
+ SHELL_NEWTMGR: 0
+
+ REEL_BOARD_ENABLE_ACTIVE_MODE: 1
+ SPI_0_MASTER: 1
+
+ BLE_MESH: 1
+ MSYS_1_BLOCK_COUNT: 48
+
+ BLE_SVC_GAP_DEVICE_NAME: '"reel board"'
+
+ BLE_SM_SC: 1
+ BLE_SM_BONDING: 1
+ BLE_MESH_RELAY: 1
+ BLE_MESH_GATT_PROXY: 0
+ BLE_MESH_PB_ADV: 0
+ BLE_MESH_PB_GATT: 0
+ BLE_MESH_ADV_BUF_COUNT: 30
+ BLE_MESH_LABEL_COUNT: 0
+ BLE_MESH_CFG_CLI: 1
+ BLE_MESH_TX_SEG_MAX: 6
+ BLE_MESH_TX_SEG_MSG_COUNT: 3
+ BLE_MESH_RX_SEG_MSG_COUNT: 3
+ BLE_MESH_CRPL: 128
+ BLE_MESH_RPL_STORE_TIMEOUT: 120
+ BLE_MESH_SETTINGS: 1
+ CONFIG_NFFS: 1
+ BLE_MESH_PB_ADV: 1
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h
index d3340445..1c43e69f 100644
--- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h
@@ -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)
@@ -545,6 +574,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)
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h
index 26c99265..d7db6878 100644
--- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h
@@ -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;
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h
index b0da1e73..15a45b2a 100644
--- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -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
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h
index abef8746..6a9e48e5 100644
--- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h
@@ -27,7 +27,7 @@ extern "C" {
#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. */
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h
new file mode 100644
index 00000000..2944b074
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h
@@ -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
+
+#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
diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h
index cabb0adb..cd8350d6 100644
--- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h
+++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h
@@ -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;
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c
index 996ad9c3..a5c48978 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c
@@ -247,9 +247,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] =
@@ -1206,8 +1203,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);
@@ -1305,10 +1300,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;
}
@@ -1372,6 +1363,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
@@ -1388,6 +1393,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();
@@ -1447,23 +1455,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)
{
@@ -1678,16 +1669,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),
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c
index 4ffbe206..72c4e7d6 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c
@@ -131,6 +131,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];
@@ -685,7 +686,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);
@@ -1269,7 +1270,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)
@@ -1304,7 +1305,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 */
@@ -1322,7 +1323,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;
}
@@ -1377,7 +1379,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
@@ -1554,6 +1556,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);
@@ -1853,7 +1856,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
@@ -2544,11 +2547,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);
@@ -2737,7 +2740,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);
@@ -4019,8 +4022,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));
@@ -4836,6 +4839,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);
}
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c
index 1b17a0d2..b8352f4a 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c
@@ -225,6 +225,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
@@ -332,7 +492,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;
@@ -855,8 +1015,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;
@@ -991,10 +1157,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:
@@ -1450,10 +1616,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;
@@ -1462,7 +1628,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;
@@ -1861,6 +2027,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);
@@ -3239,6 +3409,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
@@ -3452,129 +3629,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);
}
@@ -3595,7 +3785,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;
@@ -3609,14 +3798,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
@@ -3624,14 +3842,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;
@@ -3693,9 +3911,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];
}
@@ -3784,7 +4000,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 =
@@ -3803,8 +4019,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];
}
@@ -4226,6 +4443,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 */
@@ -4265,6 +4488,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();
}
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c
index 1350fdc0..9936b9d3 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c
@@ -1128,16 +1128,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);
@@ -1565,6 +1560,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)
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h
index f2f72d17..53358c4a 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h
@@ -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);
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c
index ea2ba834..c4ac6504 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c
@@ -112,6 +112,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
};
/**
@@ -505,6 +509,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;
@@ -836,6 +846,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)
@@ -1040,11 +1064,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.
*
@@ -1250,6 +1333,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.
*
@@ -1351,7 +1443,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;
@@ -1676,6 +1768,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;
}
@@ -2138,6 +2236,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);
@@ -2568,6 +2678,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);
@@ -2709,6 +2839,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:
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c
index b82adc2e..a3da98d9 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c
@@ -33,6 +33,7 @@
#include "controller/ble_ll_whitelist.h"
#include "controller/ble_ll_resolv.h"
#include "controller/ble_ll_sync.h"
+#include "controller/ble_ll_iso.h"
#include "ble_ll_priv.h"
#include "ble_ll_conn_priv.h"
@@ -327,6 +328,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
@@ -618,6 +644,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:
@@ -1149,10 +1178,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;
@@ -1174,6 +1270,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:
@@ -1194,7 +1310,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;
@@ -1227,6 +1343,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)
{
@@ -1259,6 +1433,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;
@@ -1454,9 +1644,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;
@@ -1465,7 +1679,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;
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c
index dbc50db9..0d6da9a0 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c
@@ -461,6 +461,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)
{
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c
new file mode 100644
index 00000000..a6186fe1
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include
+#include "syscfg/syscfg.h"
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#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
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c
index 7b384e9d..8aa71271 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c
@@ -17,6 +17,9 @@
* under the License.
*/
+/* for jrand48 */
+#define _XOPEN_SOURCE
+#include
#include
#include
#include
@@ -120,6 +123,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
*
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c
index 84747db7..0cbcb376 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c
@@ -293,7 +293,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);
}
@@ -305,7 +305,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;
@@ -617,7 +617,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)
@@ -1125,6 +1125,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 */
@@ -1149,22 +1165,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);
@@ -1991,10 +1991,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
@@ -2227,6 +2227,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;
@@ -2234,6 +2235,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;
}
@@ -3019,7 +3021,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;
}
@@ -3058,10 +3061,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;
}
@@ -3077,7 +3076,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);
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c
index 370faddf..d01f10ed 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c
@@ -83,14 +83,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;
}
}
@@ -111,7 +111,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;
}
}
@@ -178,7 +178,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;
}
@@ -216,7 +216,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;
@@ -468,7 +468,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);
@@ -655,7 +655,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);
@@ -770,7 +770,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;
@@ -1047,7 +1047,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;
}
@@ -1111,7 +1111,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;
}
@@ -1200,7 +1200,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;
}
@@ -1233,7 +1233,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);
@@ -1266,7 +1266,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;
@@ -1580,7 +1580,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;
}
@@ -1670,7 +1670,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;
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c
index 834e0095..cae9eb7d 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c
@@ -36,7 +36,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)
@@ -404,10 +419,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 */
@@ -455,4 +537,7 @@ 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,
};
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c
index 75f18bf2..df806082 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c
@@ -2091,10 +2091,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));
diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c
index 7fbb18f1..ccdf3775 100644
--- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c
+++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c
@@ -50,8 +50,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) {
@@ -292,8 +292,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;
}
diff --git a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml
index 85049cb0..2c7c2cb2 100644
--- a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml
@@ -38,35 +38,10 @@ syscfg.defs:
type: 'task_priority'
value: 0
- # Sleep clock accuracy (sca). This is the amount of drift in the system
- # during when the device is sleeping (in parts per million).
- #
- # NOTE: 'the' master sca is an enumerated value based on the sca. Rather
- # than have a piece of code calculate this value, the developer must set
- # this value based on the value of the SCA using the following table:
- #
- # SCA between 251 and 500 ppm (inclusive); master sca = 0
- # SCA between 151 and 250 ppm (inclusive); master sca = 1
- # SCA between 101 and 150 ppm (inclusive); master sca = 2
- # SCA between 76 and 100 ppm (inclusive); master sca = 3
- # SCA between 51 and 75 ppm (inclusive); master sca = 4
- # SCA between 31 and 50 ppm (inclusive); master sca = 5
- # SCA between 21 and 30 ppm (inclusive); master sca = 6
- # SCA between 0 and 20 ppm (inclusive); master sca = 7
- #
- # For example:
- # if your clock drift is 101 ppm, your master should be set to 2.
- # if your clock drift is 20, your master sca should be set to 7.
- #
- # The values provided below are merely meant to be an example and should
- # be replaced by values appropriate for your platform.
- BLE_LL_OUR_SCA:
- description: 'The system clock accuracy of the device.'
- value: '60' # in ppm
-
- BLE_LL_MASTER_SCA:
- description: 'Enumerated value based on our sca'
- value: '4'
+ BLE_LL_SCA:
+ description: Sleep clock accuracy of our device (in ppm)
+ value: MYNEWT_VAL(BLE_LL_OUR_SCA)
+ range: 0..500
BLE_LL_TX_PWR_DBM:
description: 'Transmit power level.'
@@ -285,6 +260,35 @@ syscfg.defs:
Advertising Sync Transfer Feature.
value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+ BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL:
+ description: >
+ Enable controller-to-host flow control support. This allows host to
+ limit number of ACL packets sent at once from controller to avoid
+ congestion on HCI transport if feature is also supported by host.
+ value: 0
+
+ BLE_LL_CFG_FEAT_LL_SCA_UPDATE:
+ description: >
+ This option is used to enable/disable support for SCA update procedure
+ value: 0
+ restrictions:
+ - '(BLE_VERSION >= 52) if 1'
+
+ BLE_LL_CFG_FEAT_LL_ISO:
+ description: >
+ This option is used to enable/disable support for LE Isochronous Channels
+ as per Bluetooth v5.2 channels
+ value: MYNEWT_VAL(BLE_ISO)
+ restrictions:
+ - '(BLE_VERSION >= 52) if 1'
+
+ BLE_LL_CFG_FEAT_LL_ISO_TEST:
+ description: >
+ This option is used to enable/disbale test commands for ISO support
+ value: MYNEWT_VAL(BLE_ISO_TEST)
+ restrictions:
+ - 'BLE_LL_CFG_FEAT_LL_ISO if 1'
+
BLE_LL_EXT_ADV_AUX_PTR_CNT:
description: >
This option configure a max number of scheduled outstanding auxiliary
@@ -404,6 +408,10 @@ syscfg.defs:
description: use BLE_LL_RFMGMT_ENABLE_TIME instead
value: 0
deprecated: 1
+ BLE_LL_OUR_SCA:
+ description: use BLE_LL_SCA instead
+ value: 60
+ deprecated: 1
# defunct settings (to be removed eventually)
BLE_DEVICE:
@@ -418,6 +426,10 @@ syscfg.defs:
description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS
value: '(2 * OS_TICKS_PER_SEC)'
defunct: 1
+ BLE_LL_MASTER_SCA:
+ description: use BLE_LL_SCA instead
+ value: 4
+ defunct: 1
syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV:
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md
new file mode 100644
index 00000000..2e76e2c1
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md
@@ -0,0 +1,68 @@
+
+
+## How to run NimBLE controller on Dialog DA1469x
+
+Dialog DA1469x has separate Cortex-M0+ core inside CMAC hw block which can run
+NimBLE controller. This means DA1469x can run full NimBLE stack: host is running
+on M33 core while controller is running on M0+ core. Both communicate using
+standard HCI H4 protocol exchanged over mailboxes located in shared memory.
+
+### Basic setup
+
+In order to run full NimBLE stack on DA1469x you will need two newt targets: one
+for M33 (e.g. `dialog_da1469x-dk-pro` BSP) and one for M0+ (`dialog_cmac` BSP).
+
+Once everything is configured properly, you only need to build target for M33.
+Target configured for M0+ will be build automatically and image is linked with
+M33 image so everything can be flashed at once just as if there is only single
+target used.
+
+Target for M33 should be set and configured as any other BLE application. In
+order to use NimBLE controller on CMAC, set proper HCI transport via syscfg:
+
+ BLE_HCI_TRANSPORT: dialog_cmac
+
+This will include proper transport, driver and add M0+ target to build process.
+
+For M0+, there is sample target provided in `targets/dialog_cmac` and it's used
+by default unless overrided by syscfg in M33 target:
+
+ CMAC_IMAGE_TARGET_NAME: "@apache-mynewt-nimble/targets/dialog_cmac"
+
+If you wish to create own target for M0+, make sure your target is set the same
+way (`app`, `bsp` and `build_profile`) as sample. Also it is recommended to use
+syscfg settings from sample target in new target.
+
+### NimBLE configuration
+
+Since host and controller are running on different cores, they both use separate
+configuration: host configuration is in M33 target, controller configuration is
+in M0+ target. There is currently no way to automatically synchronize both, so
+care needs to be taken when enabling features in either of targets.
+
+A possible workaround is to use separate `.yml` file with all the NimBLE syscfg
+values settings and include it in both targets using `$import` directive which
+is supported by recent versions of `newt` tool.
+
+### Advanced settings
+
+(tbd)
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h
new file mode 100644
index 00000000..e4e741c5
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h
@@ -0,0 +1,39 @@
+/*
+ * 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_XCVR_
+#define H_BLE_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XCVR_TX_SCHED_DELAY_USECS (250)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE (8)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_XCVR_ */
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml
new file mode 100644
index 00000000..9cf63ffc
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+pkg.name: nimble/drivers/dialog_cmac
+pkg.description: BLE driver for Dialog CMAC
+pkg.author: "Apache Mynewt "
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+pkg.deps:
+ - "@apache-mynewt-nimble/nimble/controller"
+ - "@apache-mynewt-core/crypto/tinycrypt"
+pkg.apis:
+ - ble_driver
+pkg.req_apis:
+ - ble_transport
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c
new file mode 100644
index 00000000..98c8144b
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include "mcu/mcu.h"
+#include "nimble/ble.h"
+#include "controller/ble_hw.h"
+#include "CMAC.h"
+#include "cmac_driver/cmac_shared.h"
+#include "mcu/mcu.h"
+#include "tinycrypt/aes.h"
+
+static struct tc_aes_key_sched_struct g_ctx;
+
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+ cmac_rand_set_isr_cb(cb);
+ return 0;
+}
+
+int
+ble_hw_rng_start(void)
+{
+ /* Chime the M33 in case we need random numbers generated */
+ cmac_rand_start();
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
+ return 0;
+}
+
+int
+ble_hw_rng_stop(void)
+{
+ cmac_rand_stop();
+ return 0;
+}
+
+#define BLE_HW_RESOLV_LIST_SIZE (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+
+struct ble_hw_resolv_irk {
+ uint32_t key[4];
+};
+
+struct ble_hw_resolv_list {
+ uint8_t count;
+ struct ble_hw_resolv_irk irk[BLE_HW_RESOLV_LIST_SIZE];
+};
+
+struct ble_hw_resolv_proc {
+ uint32_t hash;
+ uint8_t f_configured;
+ uint8_t f_active;
+ uint8_t f_match;
+ uint8_t f_done;
+ struct ble_hw_resolv_irk *irk;
+ struct ble_hw_resolv_irk *irk_end;
+ uint32_t crypto_prand_in[4];
+ uint32_t crypto_e_out[4];
+};
+
+static struct ble_hw_resolv_list g_ble_hw_resolv_list;
+static struct ble_hw_resolv_proc g_ble_hw_resolv_proc;
+
+int
+ble_hw_get_public_addr(ble_addr_t *addr)
+{
+ return -1;
+}
+
+int
+ble_hw_get_static_addr(ble_addr_t *addr)
+{
+ return -1;
+}
+
+void
+ble_hw_whitelist_clear(void)
+{
+}
+
+int
+ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
+{
+ return 0;
+}
+
+void
+ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
+{
+}
+
+uint8_t
+ble_hw_whitelist_size(void)
+{
+ return 0;
+}
+
+void
+ble_hw_whitelist_enable(void)
+{
+}
+
+
+void
+ble_hw_whitelist_disable(void)
+{
+}
+
+int
+ble_hw_whitelist_match(void)
+{
+ return 0;
+}
+
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+ uint32_t in_addr;
+ uint32_t out_addr;
+
+ /*
+ * The following code bears some explanation. This function is called by
+ * the LL task to encrypt blocks and calculate session keys. Address
+ * resolution also calls this function. Furthermore, during connections,
+ * the M0 crypto accelerator is used but this function is not called when
+ * using it. During the entire connection event, the M0 crypto block cannot
+ * be used as the crypto state (some of it) needs to remain un-changed.
+ * Note that this is also true when address resolution is enabled: the
+ * HW crypto block is set up and cannot be modified.
+ *
+ * Rather than attempt to share the M0 crypto block between the various
+ * controller features which require it, we decided to use software to
+ * perform the encryption task for anything being done at the link-layer
+ * (outside of an ISR). If this function is called inside an ISR, and it
+ * is when resolving addresses, the crypto accelerator is not being used
+ * by a connection event. Thus, we check to see if we are inside of an ISR.
+ * If so, we use the M0 crypto block. If outside of an ISR, we use the M33
+ */
+ if (!os_arch_in_isr()) {
+ tc_aes128_set_encrypt_key(&g_ctx, ecb->key);
+ tc_aes_encrypt(ecb->cipher_text, ecb->plain_text, &g_ctx);
+ return 0;
+ }
+
+ /* Need to retain state of in/out pointers */
+ in_addr = CMAC->CM_CRYPTO_IN_ADR2_REG;
+ out_addr = CMAC->CM_CRYPTO_OUT_ADR_REG;
+
+ while (CMAC->CM_CRYPTO_STAT_REG & CMAC_CM_CRYPTO_STAT_REG_CM_CRYPTO_BUSY_Msk);
+
+ /* RECB, memory in/out, encryption */
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
+
+ CMAC->CM_CRYPTO_KEY_31_0_REG = get_le32(&ecb->key[0]);
+ CMAC->CM_CRYPTO_KEY_63_32_REG = get_le32(&ecb->key[4]);
+ CMAC->CM_CRYPTO_KEY_95_64_REG = get_le32(&ecb->key[8]);
+ CMAC->CM_CRYPTO_KEY_127_96_REG = get_le32(&ecb->key[12]);
+ CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)ecb->plain_text;
+ CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)ecb->cipher_text;
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
+ while (!(CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk));
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
+
+ CMAC->CM_CRYPTO_IN_ADR2_REG = in_addr;
+ CMAC->CM_CRYPTO_OUT_ADR_REG = out_addr;
+
+ return 0;
+}
+
+void
+ble_hw_resolv_list_clear(void)
+{
+ g_ble_hw_resolv_list.count = 0;
+}
+
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+ struct ble_hw_resolv_irk *e;
+
+ if (g_ble_hw_resolv_list.count == BLE_HW_RESOLV_LIST_SIZE) {
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ e = &g_ble_hw_resolv_list.irk[g_ble_hw_resolv_list.count];
+ /* Prepare key here so we do not need to do it during resolving */
+ e->key[0] = get_le32(&irk[0]);
+ e->key[1] = get_le32(&irk[4]);
+ e->key[2] = get_le32(&irk[8]);
+ e->key[3] = get_le32(&irk[12]);
+
+ g_ble_hw_resolv_list.count++;
+
+ return BLE_ERR_SUCCESS;
+}
+
+void
+ble_hw_resolv_list_rmv(int index)
+{
+ struct ble_hw_resolv_irk *e;
+
+ if (index < g_ble_hw_resolv_list.count) {
+ g_ble_hw_resolv_list.count--;
+
+ e = &g_ble_hw_resolv_list.irk[index];
+ memmove(e, e + 1, (g_ble_hw_resolv_list.count - index) * sizeof(e->key));
+ }
+}
+
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+ return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+int
+ble_hw_resolv_list_match(void)
+{
+ return g_ble_hw_resolv_proc.f_match ?
+ g_ble_hw_resolv_proc.irk - g_ble_hw_resolv_list.irk : -1;
+}
+
+static void
+ble_hw_resolv_proc_next(void)
+{
+ void *src = &g_ble_hw_resolv_proc.irk->key;
+
+ if (g_ble_hw_resolv_proc.irk == g_ble_hw_resolv_proc.irk_end) {
+ g_ble_hw_resolv_proc.f_done = 1;
+ g_ble_hw_resolv_proc.f_active = 0;
+ } else {
+ __asm__ volatile (".syntax unified \n"
+ " ldm %[ptr]!, {r1, r2, r3, r4} \n"
+ " ldr %[ptr], =%[reg] \n"
+ " stm %[ptr]!, {r1, r2, r3, r4} \n"
+ : [ptr] "+l" (src)
+ : [reg] "i" (&CMAC->CM_CRYPTO_KEY_31_0_REG)
+ : "r1", "r2", "r3", "r4", "memory");
+
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
+ }
+}
+
+void
+ble_hw_resolv_proc_enable(void)
+{
+ assert(!g_ble_hw_resolv_proc.f_active);
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_ABORT_Msk;
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
+
+ CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_prand_in;
+ CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_e_out;
+
+ g_ble_hw_resolv_proc.irk = g_ble_hw_resolv_list.irk;
+ g_ble_hw_resolv_proc.irk_end = g_ble_hw_resolv_list.irk +
+ g_ble_hw_resolv_list.count;
+ g_ble_hw_resolv_proc.f_configured = 1;
+ g_ble_hw_resolv_proc.f_active = 0;
+
+ /*
+ * It would be better to enable IRQ in ble_hw_resolv_proc_start, but this
+ * would introduce a bit of latency when starting resolving procedure and
+ * we need to save every us possible there in order to be able to resolve
+ * RPA on time.
+ */
+ NVIC_ClearPendingIRQ(CRYPTO_IRQn);
+ NVIC_EnableIRQ(CRYPTO_IRQn);
+}
+
+void
+ble_hw_resolv_proc_disable(void)
+{
+ g_ble_hw_resolv_proc.f_configured = 0;
+ g_ble_hw_resolv_proc.f_active = 0;
+ g_ble_hw_resolv_proc.f_match = 0;
+ g_ble_hw_resolv_proc.f_done = 1;
+
+ NVIC_DisableIRQ(CRYPTO_IRQn);
+}
+
+void
+ble_hw_resolv_proc_start(const uint8_t *addr)
+{
+ assert(g_ble_hw_resolv_proc.f_configured);
+
+ /* crypto_prand_in is already zeroed so prand is properly padded */
+ g_ble_hw_resolv_proc.crypto_prand_in[3] = get_be24(&addr[3]) << 8;
+ g_ble_hw_resolv_proc.hash = get_be24(&addr[0]);
+
+ g_ble_hw_resolv_proc.f_match = 0;
+ g_ble_hw_resolv_proc.f_done = 0;
+ g_ble_hw_resolv_proc.f_active = 1;
+
+ ble_hw_resolv_proc_next();
+}
+
+void
+CRYPTO_IRQHandler(void)
+{
+ uint32_t hash;
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
+
+ hash = g_ble_hw_resolv_proc.crypto_e_out[3] >> 8;
+ if (g_ble_hw_resolv_proc.hash == hash) {
+ g_ble_hw_resolv_proc.f_active = 0;
+ g_ble_hw_resolv_proc.f_match = 1;
+ g_ble_hw_resolv_proc.f_done = 1;
+ } else {
+ g_ble_hw_resolv_proc.irk++;
+ ble_hw_resolv_proc_next();
+ }
+}
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h
new file mode 100644
index 00000000..627994ff
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h
@@ -0,0 +1,29 @@
+/*
+ * 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 _BLE_HW_PRIV_H_
+#define _BLE_HW_PRIV_H_
+
+#include
+
+void ble_hw_resolv_proc_enable(void);
+void ble_hw_resolv_proc_disable(void);
+void ble_hw_resolv_proc_start(const uint8_t *addr);
+
+#endif /* _BLE_HW_PRIV_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c
new file mode 100644
index 00000000..d5767c56
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c
@@ -0,0 +1,1798 @@
+/*
+ * 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.
+ */
+
+#include "syscfg/syscfg.h"
+#if !MYNEWT_VAL(BLE_PHY_DEBUG_DSER)
+#define MCU_DIAG_SER_DISABLE
+#endif
+
+#include
+#include
+#include
+#include "nimble/ble.h"
+#include "mcu/mcu.h"
+#include "mcu/cmac_timer.h"
+#include "cmac_driver/cmac_shared.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+#include "stats/stats.h"
+#include "CMAC.h"
+#include "ble_hw_priv.h"
+#include "ble_rf_priv.h"
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+#error LE Coded PHY cannot be enabled on DA1469x
+#endif
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+ STATS_SECT_ENTRY(phy_isrs)
+ STATS_SECT_ENTRY(tx_good)
+ STATS_SECT_ENTRY(tx_fail)
+ STATS_SECT_ENTRY(tx_late)
+ STATS_SECT_ENTRY(tx_bytes)
+ STATS_SECT_ENTRY(rx_starts)
+ STATS_SECT_ENTRY(rx_aborts)
+ STATS_SECT_ENTRY(rx_valid)
+ STATS_SECT_ENTRY(rx_crc_err)
+ STATS_SECT_ENTRY(rx_late)
+ STATS_SECT_ENTRY(radio_state_errs)
+ STATS_SECT_ENTRY(rx_hw_err)
+ STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+ STATS_NAME(ble_phy_stats, phy_isrs)
+ STATS_NAME(ble_phy_stats, tx_good)
+ STATS_NAME(ble_phy_stats, tx_fail)
+ STATS_NAME(ble_phy_stats, tx_late)
+ STATS_NAME(ble_phy_stats, tx_bytes)
+ STATS_NAME(ble_phy_stats, rx_starts)
+ STATS_NAME(ble_phy_stats, rx_aborts)
+ STATS_NAME(ble_phy_stats, rx_valid)
+ STATS_NAME(ble_phy_stats, rx_crc_err)
+ STATS_NAME(ble_phy_stats, rx_late)
+ STATS_NAME(ble_phy_stats, radio_state_errs)
+ STATS_NAME(ble_phy_stats, rx_hw_err)
+ STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+#error LE Coded PHY is not supported
+#endif
+
+/* An easy way to get and set bit field value in CMAC registers */
+#define CMAC_SETREGF(_reg, _field, _val) \
+ CMAC->_reg = (CMAC->_reg & ~(CMAC_ ## _reg ## _ ## _field ## _Msk)) | \
+ ((_val) << (CMAC_ ## _reg ## _ ## _field ## _Pos));
+#define CMAC_GETREGF(_reg, _field) \
+ (CMAC->_reg & (CMAC_ ## _reg ## _ ## _field ## _Msk)) >> \
+ (CMAC_ ## _reg ## _ ## _field ## _Pos)
+
+/* Definitions for fields queue */
+#define FIELD_DATA_REG_DMA_TX(_offset, _len) \
+ ((uint32_t)&g_ble_phy_tx_buf[(_offset)] & 0x3ffff) | ((_len) << 20)
+#define FIELD_DATA_REG_DMA_RX(_offset, _len) \
+ ((uint32_t)&g_ble_phy_rx_buf[(_offset)] & 0x3ffff) | ((_len) << 20)
+
+#if MYNEWT_VAL(BLE_LL_DTM)
+#define PHY_WHITENING (g_ble_phy_data.phy_whitening)
+#else
+#define PHY_WHITENING (1)
+#endif
+
+#define FIELD_CTRL_REG_TX_PREAMBLE \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \
+ (g_ble_phy_data.phy_mode_pre_len << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos)
+#define FIELD_CTRL_REG_TX_ACCESS_ADDR \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \
+ (31 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos)
+#define FIELD_CTRL_REG_TX_PAYLOAD \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (PHY_WHITENING << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos);
+#define FIELD_CTRL_REG_TX_ENC_PAYLOAD \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos)
+#define FIELD_CTRL_REG_TX_MIC \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos)
+#define FIELD_CTRL_REG_TX_CRC \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (PHY_WHITENING << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_LAST_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_MSB_FIRST_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \
+ (23 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos)
+#define FIELD_CTRL_REG_RX_ACCESS_ADDR \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CORR_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \
+ (31 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos)
+#define FIELD_CTRL_REG_RX_HEADER \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (PHY_WHITENING << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos)
+#define FIELD_CTRL_REG_RX_CRC \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (PHY_WHITENING << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_LAST_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_MSB_FIRST_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos)
+#define FIELD_CTRL_REG_RX_PAYLOAD \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (PHY_WHITENING << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos)
+#define FIELD_CTRL_REG_RX_PAYLOAD_WITH_EXC \
+ FIELD_CTRL_REG_RX_PAYLOAD | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos)
+#define FIELD_CTRL_REG_RX_ENC_PAYLOAD \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \
+ (g_ble_phy_data.phy_mode_evpsym << \
+ CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \
+ (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos)
+
+/* RF power up/down delays */
+#define PHY_DELAY_POWER_DN_RX (23)
+#define PHY_DELAY_POWER_DN_TX (23)
+#define PHY_DELAY_POWER_UP_RX (90)
+#define PHY_DELAY_POWER_UP_TX (75)
+#define PHY_DELAY_TX_RX ((PHY_DELAY_POWER_DN_TX) + (PHY_DELAY_POWER_UP_RX))
+#define PHY_DELAY_RX_TX ((PHY_DELAY_POWER_DN_RX) + (PHY_DELAY_POWER_UP_TX))
+
+/* RF TX/RX path delays */
+static const uint8_t g_ble_phy_path_delay_tx[2] = {
+ 4, /* 1M = 3.8us */
+ 0, /* 2M = 0.2us */
+};
+static const uint8_t g_ble_phy_path_delay_rx[2] = {
+ 2, /* 1M = 2.2us */
+ 1, /* 2M = 0.8us */
+};
+
+/* Measured and pre-calculated offsets for transitions */
+static const uint8_t g_ble_phy_frame_offset_txrx[4] = {
+ ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (4)), /* 2M/1M */
+ ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (5)), /* 1M/1M */
+ ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (4)), /* 2M/2M */
+ ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (5)), /* 1M/2M */
+};
+static const uint8_t g_ble_phy_frame_offset_rxtx[4] = {
+ ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (5)), /* 2M/1M */
+ ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (6)), /* 1M/1M */
+ ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (3)), /* 2M/2M */
+ ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (5)), /* 1M/2M */
+};
+
+/* packet start offsets (in usecs) */
+static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { 376, 40, 24, 376 };
+
+struct ble_phy_data {
+ uint8_t phy_state; /* Current state */
+ uint8_t channel; /* Current PHY channel */
+ uint8_t phy_mode_cur; /* Current PHY mode */
+ uint8_t phy_mode_tx; /* TX PHY mode */
+ uint8_t phy_mode_rx; /* RX PHY mode */
+ uint8_t phy_mode_pre_len; /* Preamble length - 1 */
+ uint8_t phy_mode_evpsym; /* EVPSYMBOL_LUT value for fields */
+ uint8_t end_transition; /* Scheduled transition */
+ uint8_t path_delay_tx;
+ uint8_t path_delay_rx;
+ uint8_t frame_offset_txrx;
+ uint8_t frame_offset_rxtx;
+ uint8_t phy_rx_started;
+ uint8_t phy_encrypted;
+ uint8_t phy_privacy;
+#if MYNEWT_VAL(BLE_LL_DTM)
+ uint8_t phy_whitening; /* Whitening state (disabled for DTM) */
+#endif
+ uint32_t access_addr; /* Current access address */
+ uint32_t crc_init;
+ uint32_t llt_at_cputime;
+ uint32_t cputime_at_llt;
+ uint64_t start_llt;
+ struct ble_mbuf_hdr rxhdr;
+ ble_phy_tx_end_func txend_cb;
+ void *txend_arg;
+};
+
+static struct ble_phy_data g_ble_phy_data;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+/* Encryption related variables */
+struct ble_phy_encrypt_obj {
+ uint8_t key[16];
+ uint8_t b0[16];
+ uint8_t b1[16];
+ uint8_t ai[16];
+};
+
+struct ble_phy_encrypt_obj g_ble_phy_encrypt_data;
+
+static void ble_phy_tx_enc_start(void);
+static void ble_phy_rx_enc_start(uint8_t len);
+#endif
+
+#define SW_MAC_EXC_NONE (0)
+#define SW_MAC_EXC_LL_RX_END (1)
+#define SW_MAC_EXC_TXEND_CB (2)
+#define SW_MAC_EXC_LL_RX_START (3)
+#define SW_MAC_EXC_WFR_TIMER_EXP (4)
+
+static volatile uint8_t g_sw_mac_exc;
+
+/* Channel index to RF channel mapping */
+static const uint8_t g_ble_phy_chan_to_rf[BLE_PHY_NUM_CHANS] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, /* 0-9 */
+ 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, /* 10-19 */
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 20-29 */
+ 32, 33, 34, 35, 36, 37, 38, 0, 12, 39, /* 30-39 */
+};
+
+__attribute__((aligned(4)))
+static uint8_t g_ble_phy_tx_buf[BLE_PHY_MAX_PDU_LEN + 3];
+__attribute__((aligned(4)))
+static uint8_t g_ble_phy_rx_buf[BLE_PHY_MAX_PDU_LEN + 3];
+
+static void ble_phy_irq_field_tx(void);
+static void ble_phy_irq_field_rx(void);
+static void ble_phy_irq_frame_tx(void);
+static void ble_phy_irq_frame_rx(void);
+static bool ble_phy_rx_start_isr(void);
+static void ble_phy_rx_setup_fields(void);
+static void ble_phy_rx_setup_xcvr(void);
+static void ble_phy_mode_apply(uint8_t phy_mode);
+
+void
+FIELD_IRQHandler(void)
+{
+ MCU_DIAG_SER('E');
+
+ switch (g_ble_phy_data.phy_state) {
+ case BLE_PHY_STATE_TX:
+ ble_phy_irq_field_tx();
+ break;
+ case BLE_PHY_STATE_RX:
+ ble_phy_irq_field_rx();
+ break;
+ default:
+ STATS_INC(ble_phy_stats, radio_state_errs);
+ CMAC->CM_EXC_STAT_REG = 0xfffffffe;
+ break;
+ }
+
+ MCU_DIAG_SER('e');
+}
+
+void
+CALLBACK_IRQHandler(void)
+{
+ MCU_DIAG_SER('C');
+
+ /* XXX: clear these for now. */
+ (void)CMAC->CM_BS_SMPL_D_REG;
+
+ /* Clear IRQ*/
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CALLBACK_VALID_CLR_Msk;
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk;
+
+ /*
+ * Program next frame for transition to TX. CM_EV_LINKUP_REG register to
+ * enable actual transition can be set later, we just need to make sure 2nd
+ * frame is already set before current frame is finished - this guarantees
+ * that frame for transition will be moved to 1st frame once current frame
+ * is popped off the queue.
+ */
+ CMAC->CM_FRAME_2_REG = CMAC_CM_FRAME_2_REG_FRAME_VALID_Msk |
+ CMAC_CM_FRAME_2_REG_FRAME_TX_Msk |
+ CMAC_CM_FRAME_2_REG_FRAME_EXC_ON_BS_START_Msk |
+ ((g_ble_phy_data.frame_offset_rxtx) <<
+ CMAC_CM_FRAME_2_REG_FRAME_START_OFFSET_Pos);
+
+ /*
+ * We just got an access address match so do this as early as possible
+ * to save time in the field rx isr.
+ */
+ ble_phy_rx_start_isr();
+
+ MCU_DIAG_SER('c');
+}
+
+void
+FRAME_IRQHandler(void)
+{
+ MCU_DIAG_SER('F');
+
+ switch (g_ble_phy_data.phy_state) {
+ case BLE_PHY_STATE_TX:
+ ble_phy_irq_frame_tx();
+ break;
+ case BLE_PHY_STATE_RX:
+ ble_phy_irq_frame_rx();
+ break;
+ default:
+ STATS_INC(ble_phy_stats, radio_state_errs);
+ CMAC->CM_EXC_STAT_REG = 0xfffffffe;
+ break;
+ }
+
+ MCU_DIAG_SER('f');
+}
+
+void
+SW_MAC_IRQHandler(void)
+{
+ uint8_t exc;
+ int rc;
+
+ MCU_DIAG_SER('S');
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_SW_MAC_Msk;
+ assert(g_sw_mac_exc);
+
+ exc = g_sw_mac_exc;
+ g_sw_mac_exc = 0;
+
+ MCU_DIAG_SER('0' + exc);
+
+ /* Next SW_MAC handover can now be queued */
+ os_arch_cmac_bs_ctrl_irq_unblock();
+
+ switch (exc) {
+ case SW_MAC_EXC_TXEND_CB:
+ assert(g_ble_phy_data.txend_cb);
+ g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg);
+ break;
+ case SW_MAC_EXC_WFR_TIMER_EXP:
+ ble_ll_wfr_timer_exp(NULL);
+ break;
+ case SW_MAC_EXC_LL_RX_START:
+ /* Call Link Layer receive start function */
+ rc = ble_ll_rx_start(&g_ble_phy_rx_buf[0], g_ble_phy_data.channel,
+ &g_ble_phy_data.rxhdr);
+ if (rc == 0) {
+ /* Set rx started flag and enable rx end ISR */
+ g_ble_phy_data.phy_rx_started = 1;
+
+ /* No transition */
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_NONE_Msk |
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk;
+ } else if (rc > 0) {
+ g_ble_phy_data.phy_rx_started = 1;
+
+ /* Setup transition */
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk |
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_PHY_TO_IDLE_Msk;
+ } else {
+ /* Disable PHY */
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, rx_aborts);
+ }
+ break;
+ case SW_MAC_EXC_LL_RX_END:
+ /* Call LL end processing */
+ rc = ble_ll_rx_end(&g_ble_phy_rx_buf[0], &g_ble_phy_data.rxhdr);
+ if (rc < 0) {
+ ble_phy_disable();
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ MCU_DIAG_SER('s');
+}
+
+static inline uint32_t
+ble_phy_convert_and_record_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ uint64_t ll_val;
+
+ ll_val = cmac_timer_convert_hal2llt(cputime);
+
+ /*
+ * Since we just converted cputime to the LL timer, record both these
+ * values as they will be used to calculate packet reception start time.
+ */
+ g_ble_phy_data.cputime_at_llt = cputime;
+ g_ble_phy_data.llt_at_cputime = ll_val;
+ g_ble_phy_data.start_llt = ll_val + rem_usecs;
+
+ return ll_val;
+}
+
+static inline void
+ble_phy_sw_mac_handover(uint8_t exc)
+{
+ assert(!g_sw_mac_exc);
+
+ g_sw_mac_exc = exc;
+
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_SW_MAC_Msk;
+
+ /*
+ * We want SW_MAC to be fired just after BS_CTRL interrupt so we block
+ * BS_CTRL temporarily and SW_MAC is next in order of interrupts priority.
+ */
+ os_arch_cmac_bs_ctrl_irq_block();
+}
+
+static void
+ble_phy_rx_end_isr(void)
+{
+ struct ble_mbuf_hdr *ble_hdr;
+
+ /* XXX just clear captured timer for now. Handle rx end time */
+ (void)CMAC->CM_TS1_REG;
+
+ /* Set RSSI and CRC status flag in header */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+
+ /* Count PHY crc errors and valid packets */
+ if (CMAC->CM_CRC_REG != 0) {
+ STATS_INC(ble_phy_stats, rx_crc_err);
+ } else {
+ STATS_INC(ble_phy_stats, rx_valid);
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ /* Only set MIC failure flag if frame is not zero length */
+ if (g_ble_phy_rx_buf[1] != 0) {
+ if (CMAC->CM_CRYPTO_STAT_REG != 0) {
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
+ } else {
+ g_ble_phy_rx_buf[1] = g_ble_phy_rx_buf[1] - 4;
+ }
+ }
+ }
+#endif
+ }
+
+ ble_phy_sw_mac_handover(SW_MAC_EXC_LL_RX_END);
+}
+
+static bool
+ble_phy_rx_start_isr(void)
+{
+ uint32_t llt32;
+ uint32_t llt_10_0;
+ uint32_t llt_10_0_mask;
+ uint32_t timestamp;
+ uint32_t ticks;
+ uint32_t usecs;
+ struct ble_mbuf_hdr *ble_hdr;
+
+ /* Initialize the ble mbuf header */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ ble_hdr->rxinfo.flags = ble_ll_state_get();
+ ble_hdr->rxinfo.channel = g_ble_phy_data.channel;
+ ble_hdr->rxinfo.handle = 0;
+ ble_hdr->rxinfo.phy = ble_phy_get_cur_phy();
+ ble_hdr->rxinfo.phy_mode = g_ble_phy_data.phy_mode_rx;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+ ble_hdr->rxinfo.user_data = NULL;
+#endif
+
+ /* Read the latched RSSI value */
+ ble_hdr->rxinfo.rssi = ble_rf_get_rssi();
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ g_cmac_shared_data.debug.last_rx_rssi = ble_hdr->rxinfo.rssi;
+#endif
+
+ /* Count rx starts */
+ STATS_INC(ble_phy_stats, rx_starts);
+
+ /*
+ * Calculate packet start time. Note that we have only received the
+ * access address at this point but we should have the 1st symbol and
+ * thus the timestamp should be set (this is based on looking at the diag
+ * signals). For now, lets make sure that the dirty bit is set. The
+ * dirty bit means that the timestamp was set since the last time cleared.
+ * Note that we need to read the timestamp first to guarantee it was set
+ * before reading the LL timer.
+ */
+ timestamp = CMAC->CM_TS1_REG;
+ assert((timestamp & CMAC_CM_TS1_REG_TS1_DIRTY_Msk) != 0);
+
+ /* Get the LL timer (only need 32 bits) */
+ llt32 = cmac_timer_read32();
+
+ /*
+ * We assume that the timestamp was set within 11 bits, or 2047 usecs, of
+ * when we read the ll timer. We assume this because we need to calculate
+ * the LL timer value at the timestamp. If the low 11 bits of the LL timer
+ * are greater than the timestamp, it means that the upper bits of the
+ * timestamp are correct. If the timestamp value is greater, it means the
+ * timer wrapped the 11 bits and we need to adjust the LL timer value.
+ */
+ llt_10_0_mask = (CMAC_CM_TS1_REG_TS1_TIMER1_9_0_Msk |
+ CMAC_CM_TS1_REG_TS1_TIMER1_10_Msk);
+ timestamp &= llt_10_0_mask;
+ llt_10_0 = llt32 & llt_10_0_mask;
+ llt32 &= ~llt_10_0_mask;
+ if (timestamp > llt_10_0) {
+ llt32 -= 2048;
+ }
+ llt32 |= timestamp;
+
+ /* Actual RX start time needs to account for preamble and access address */
+ llt32 -= g_ble_phy_mode_pkt_start_off[g_ble_phy_data.phy_mode_rx] +
+ g_ble_phy_data.path_delay_rx;
+
+ if (llt32 < g_ble_phy_data.llt_at_cputime) {
+ g_ble_phy_data.llt_at_cputime -= 31;
+ g_ble_phy_data.cputime_at_llt--;
+ }
+
+ /*
+ * We now have the LL timer when the packet was received. Get the cputime
+ * and the leftover usecs.
+ */
+ usecs = llt32 - g_ble_phy_data.llt_at_cputime;
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ ble_hdr->beg_cputime = g_ble_phy_data.cputime_at_llt + ticks;
+ ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+
+ return true;
+}
+
+static void
+ble_phy_irq_field_tx_exc_bs_start_4this(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk;
+
+ if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
+ /*
+ * Setup 2nd frame that will start after current one.
+ * -2us offset to adjust for allowed active clock accuracy.
+ */
+ CMAC->CM_FRAME_2_REG = CMAC_CM_FRAME_2_REG_FRAME_VALID_Msk |
+ (((g_ble_phy_data.frame_offset_txrx) - 2) <<
+ CMAC_CM_FRAME_2_REG_FRAME_START_OFFSET_Pos);
+
+ /* Next frame starts automatically on phy2idle */
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk |
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_PHY_TO_IDLE_Msk;
+
+ ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, g_ble_phy_data.phy_mode_rx, 0);
+ } else {
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk |
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk;
+ }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted && (g_ble_phy_tx_buf[1] != 0)) {
+ ble_phy_tx_enc_start();
+ }
+#endif
+}
+
+static void
+ble_phy_irq_field_tx_exc_field_on_thr_exp(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk;
+ (void)CMAC->CM_TS1_REG;
+
+ /* Set up remaining field (CRC) */
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_CRC;
+}
+
+static void
+ble_phy_irq_field_tx(void)
+{
+ uint32_t stat;
+
+ stat = CMAC->CM_EXC_STAT_REG;
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk) {
+ MCU_DIAG_SER('6');
+ ble_phy_irq_field_tx_exc_bs_start_4this();
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) {
+ MCU_DIAG_SER('7');
+ ble_phy_irq_field_tx_exc_field_on_thr_exp();
+ }
+}
+
+static void
+ble_phy_irq_frame_tx_exc_bs_stop(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk;
+
+ /* Clear latched timestamp so we do not have error on next frame */
+ (void)CMAC->CM_TS1_REG;
+
+ if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx);
+#endif
+ ble_phy_rx_setup_fields();
+ } else {
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk |
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk;
+ }
+
+ if (g_ble_phy_data.txend_cb) {
+ ble_phy_sw_mac_handover(SW_MAC_EXC_TXEND_CB);
+ return;
+ }
+}
+
+static void
+ble_phy_irq_frame_tx_exc_phy_to_idle_4this(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk;
+
+ if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) {
+ ble_phy_rx_setup_xcvr();
+
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+ } else {
+ /*
+ * Disable explicitly in case RX-TX was done (we cannot setup for auto
+ * disable in such case) */
+ ble_rf_stop();
+
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+ }
+
+ g_ble_phy_data.end_transition = BLE_PHY_TRANSITION_NONE;
+}
+
+static void
+ble_phy_irq_frame_tx(void)
+{
+ uint32_t stat;
+
+ stat = CMAC->CM_EXC_STAT_REG;
+
+ /*
+ * In case of phy2idle this should be first and only exception we handle
+ * here. This is because in case of TX-RX transition frame_start will occur
+ * at the same as phy2idle so we will have 2 exceptions here. To handle this
+ * properly we first need to handle phy2idle in TX state and keep frame_start
+ * pending so it will be called again in RX state.
+ */
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk) {
+ MCU_DIAG_SER('6');
+ ble_phy_irq_frame_tx_exc_phy_to_idle_4this();
+ return;
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) {
+ MCU_DIAG_SER('7');
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk;
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk) {
+ MCU_DIAG_SER('8');
+ ble_phy_irq_frame_tx_exc_bs_stop();
+ }
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+static void
+ble_phy_field_rx_encrypted(uint32_t len)
+{
+ if (len) {
+ /*
+ * An encrypted frame should have a minimum length of 5
+ * bytes (at least one for payload and 4 for MIC). If the
+ * length is less than 5 this frame is bogus and will most
+ * likely fail CRC. We still need to process this frame
+ * though as we need to call the handover function with
+ * the frame. If this happens we will not bother to
+ * run the remaining bytes through the accelerator; just
+ * process them like normal and generate (a hopefully
+ * incorrect) CRC.
+ */
+ if (len >= 5) {
+ /* Start the crypto accelerator */
+ ble_phy_rx_enc_start(len);
+
+ /*
+ * We have already processed one byte; process remaining
+ * payload and MIC. Note: length contains MIC.
+ */
+ len -= 2;
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, len);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ENC_PAYLOAD;
+
+ /* CRC */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 3);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC;
+ } else {
+ /* We have processed one byte so far. Send remaining
+ payload bytes to normal rx payload processing */
+ len -= 2;
+ if (len) {
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, len);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD;
+ }
+
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 3);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC;
+
+ /* Clear crypto pre-buffer */
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk;
+ }
+ } else {
+ /* We programmed one byte, so get next two bytes for CRC */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, 1);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC;
+ }
+}
+#endif
+
+static void
+ble_phy_field_rx_unencrypted(uint32_t len)
+{
+ uint8_t pduhdr;
+ uint8_t adva_thr;
+
+ if (len) {
+ pduhdr = g_ble_phy_rx_buf[0];
+ adva_thr = 0;
+
+ /*
+ * Setup interrupt after AdvA to start address resolving if
+ * privacy is enabled and TxAdd bit is set.
+ */
+ if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) &&
+ g_ble_phy_data.phy_privacy && (pduhdr & 0x40)) {
+
+ /*
+ * For legacy advertising AdvA ends at 6th byte.
+ * For extended advertising AdvA ends at 8th byte.
+ * We already programmed 2 bytes of payload so need
+ * to adjust threshold accordingly or just reset it
+ * in case there is not enough bytes in PDU to fit AdvA.
+ */
+ adva_thr = (pduhdr & 0x0f) == 0x07 ? 6 : 4;
+ if (len >= adva_thr + 2) {
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, adva_thr);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD_WITH_EXC;
+ } else {
+ adva_thr = 0;
+ }
+ }
+
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + adva_thr,
+ len - adva_thr);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD;
+ }
+
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 1);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC;
+}
+
+static void
+ble_phy_irq_field_rx_exc_field_on_thr_exp(void)
+{
+ uint32_t len;
+ uint32_t smpl;
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk;
+
+ smpl = CMAC->CM_BS_SMPL_ST_REG;
+
+ if ((smpl & CMAC_CM_BS_SMPL_ST_REG_FIELD_CNT_LATCHED_Msk) == 1) {
+ assert(g_ble_phy_data.phy_rx_started == 0);
+
+ /* Clear this */
+ (void)CMAC->CM_TS1_REG;
+
+ /* Read length of frame */
+ len = CMAC->CM_BS_SMPL_D_REG;
+ len = len & 0xFF;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ ble_phy_field_rx_encrypted(len);
+ } else {
+ ble_phy_field_rx_unencrypted(len);
+ }
+#else
+ ble_phy_field_rx_unencrypted(len);
+#endif
+
+ ble_phy_sw_mac_handover(SW_MAC_EXC_LL_RX_START);
+ } else if ((smpl & CMAC_CM_BS_SMPL_ST_REG_FIELD_CNT_LATCHED_Msk) == 3) {
+ (void)CMAC->CM_BS_SMPL_D_REG;
+
+ assert(g_ble_phy_data.phy_privacy);
+
+ /*
+ * Resolve only if RPA is received. AdvA is at different offset
+ * in ExtAdv PDU. TxAdd was already checked before programming
+ * field threshold.
+ */
+ if ((g_ble_phy_rx_buf[0] & 0x0f) == 0x07) {
+ if ((g_ble_phy_rx_buf[9] & 0xc0) == 0x40) {
+ ble_hw_resolv_proc_start(&g_ble_phy_rx_buf[4]);
+ }
+ } else {
+ if ((g_ble_phy_rx_buf[7] & 0xc0) == 0x40) {
+ ble_hw_resolv_proc_start(&g_ble_phy_rx_buf[2]);
+ }
+ }
+ } else {
+ assert(0);
+ }
+}
+
+static void
+ble_phy_irq_field_rx_exc_stat_reg_exc_corr_timeout(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk;
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk;
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk;
+
+ ble_phy_sw_mac_handover(SW_MAC_EXC_WFR_TIMER_EXP);
+}
+
+static void
+ble_phy_irq_field_rx(void)
+{
+ uint32_t stat;
+
+ stat = CMAC->CM_EXC_STAT_REG;
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) {
+ MCU_DIAG_SER('1');
+ ble_phy_irq_field_rx_exc_field_on_thr_exp();
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk) {
+ MCU_DIAG_SER('2');
+ ble_phy_irq_field_rx_exc_stat_reg_exc_corr_timeout();
+ }
+}
+
+static void
+ble_phy_irq_frame_rx_exc_phy_to_idle_4this(void)
+{
+ uint8_t rf_chan;
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk;
+
+ /* We are here only on transition, so switch to TX */
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_mode_tx);
+#endif
+ rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel];
+ ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx);
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+}
+
+static void
+ble_phy_irq_frame_rx_exc_frame_start(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk;
+}
+
+static void
+ble_phy_irq_frame_rx_exc_bs_stop(void)
+{
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk;
+ ble_phy_rx_end_isr();
+}
+
+static void
+ble_phy_irq_frame_rx(void)
+{
+ uint32_t stat;
+
+ stat = CMAC->CM_EXC_STAT_REG;
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk) {
+ MCU_DIAG_SER('3');
+ ble_phy_irq_frame_rx_exc_phy_to_idle_4this();
+ return;
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) {
+ MCU_DIAG_SER('1');
+ ble_phy_irq_frame_rx_exc_frame_start();
+ }
+
+ if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk) {
+ MCU_DIAG_SER('2');
+ ble_phy_irq_frame_rx_exc_bs_stop();
+ }
+}
+
+static void
+ble_phy_mode_apply(uint8_t phy_mode)
+{
+ if (phy_mode == g_ble_phy_data.phy_mode_cur) {
+ return;
+ }
+
+ switch (phy_mode) {
+ case BLE_PHY_MODE_1M:
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_CLK_MODE, 3);
+#endif
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_MODE, 1);
+ g_ble_phy_data.phy_mode_evpsym = 1; /* 1000 ns per symbol */
+ g_ble_phy_data.phy_mode_pre_len = 7;
+ break;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+ case BLE_PHY_MODE_2M:
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_CLK_MODE, 2);
+#endif
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_MODE, 0);
+ g_ble_phy_data.phy_mode_evpsym = 0; /* 500 ns per symbol */
+ g_ble_phy_data.phy_mode_pre_len = 15;
+ break;
+#endif
+ default:
+ assert(0);
+ return;
+ }
+
+ g_ble_phy_data.phy_mode_cur = phy_mode;
+}
+
+void
+ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode)
+{
+ uint8_t txrx;
+ uint8_t rxtx;
+
+ g_ble_phy_data.phy_mode_tx = tx_phy_mode;
+ g_ble_phy_data.phy_mode_rx = rx_phy_mode;
+
+ g_ble_phy_data.path_delay_tx = g_ble_phy_path_delay_tx[tx_phy_mode - 1];
+ g_ble_phy_data.path_delay_rx = g_ble_phy_path_delay_rx[rx_phy_mode - 1];
+
+ /*
+ * Calculate index of transition in frame offset array without tons of
+ * branches. Note that transitions have to be in specific order in array.
+ *
+ * phy_mode 1M = 01b
+ * phy_mode 2M = 10b
+ *
+ * 1M/1M = 01b | 00b = 01b
+ * 1M/2M = 01b | 10b = 11b
+ * 2M/1M = 00b | 00b = 00b
+ * 2M/2M = 00b | 10b = 10b
+ */
+ txrx = (tx_phy_mode & 0x01) | (rx_phy_mode & 0x02);
+ rxtx = (rx_phy_mode & 0x01) | (tx_phy_mode & 0x02);
+ g_ble_phy_data.frame_offset_txrx = g_ble_phy_frame_offset_txrx[txrx];
+ g_ble_phy_data.frame_offset_rxtx = g_ble_phy_frame_offset_rxtx[rxtx];
+}
+
+int
+ble_phy_get_cur_phy(void)
+{
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ switch (g_ble_phy_data.phy_mode_cur) {
+ case BLE_PHY_MODE_1M:
+ return BLE_PHY_1M;
+ case BLE_PHY_MODE_2M:
+ return BLE_PHY_2M;
+ default:
+ assert(0);
+ return -1;
+ }
+#else
+ return BLE_PHY_1M;
+#endif
+}
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+ uint32_t rem_len;
+ uint32_t copy_len;
+ uint32_t block_len;
+ uint32_t block_rem_len;
+ void *dst;
+ void *src;
+ struct os_mbuf * om;
+
+ /* Better be aligned */
+ assert(((uint32_t)dptr & 3) == 0);
+
+ block_len = rxpdu->om_omp->omp_databuf_len;
+ rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len;
+ src = dptr;
+
+ /*
+ * Setup for copying from first mbuf which is shorter due to packet header
+ * and extra leading space
+ */
+ copy_len = block_len - rxpdu->om_pkthdr_len - 4;
+ om = rxpdu;
+ dst = om->om_data;
+
+ while (om) {
+ /*
+ * Always copy blocks of length aligned to word size, only last mbuf
+ * will have remaining non-word size bytes appended.
+ */
+ block_rem_len = copy_len;
+ copy_len = min(copy_len, rem_len);
+ copy_len &= ~3;
+
+ dst = om->om_data;
+ om->om_len = copy_len;
+ rem_len -= copy_len;
+ block_rem_len -= copy_len;
+
+ __asm__ volatile (".syntax unified \n"
+ " mov r4, %[len] \n"
+ " b 2f \n"
+ "1: ldr r3, [%[src], %[len]] \n"
+ " str r3, [%[dst], %[len]] \n"
+ "2: subs %[len], #4 \n"
+ " bpl 1b \n"
+ " adds %[src], %[src], r4 \n"
+ " adds %[dst], %[dst], r4 \n"
+ : [dst] "+l" (dst), [src] "+l" (src),
+ [len] "+l" (copy_len)
+ :
+ : "r3", "r4", "memory");
+
+ if ((rem_len < 4) && (block_rem_len >= rem_len)) {
+ break;
+ }
+
+ /* Move to next mbuf */
+ om = SLIST_NEXT(om, om_next);
+ copy_len = block_len;
+ }
+
+ /* Copy remaining bytes, if any, to last mbuf */
+ om->om_len += rem_len;
+ __asm__ volatile (".syntax unified \n"
+ " b 2f \n"
+ "1: ldrb r3, [%[src], %[len]] \n"
+ " strb r3, [%[dst], %[len]] \n"
+ "2: subs %[len], #1 \n"
+ " bpl 1b \n"
+ : [len] "+l" (rem_len)
+ : [dst] "l" (dst), [src] "l" (src)
+ : "r3", "memory");
+
+ /* Copy header */
+ memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr,
+ sizeof(struct ble_mbuf_hdr));
+}
+
+void
+ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
+{
+ uint64_t llt;
+ uint32_t corr_window;
+ uint32_t llt_z_ticks;
+ uint32_t aa_time;
+
+ /*
+ * RX is started 2us earlier due to allowed clock accuracy and it should end
+ * 2us later for the same reason. Preamble is always 8us (8 symbols on 1M,
+ * 16 symbols on 2M) and Access Address is 32us on 1M and 16us on 2M. Add
+ * 1us just in case...
+ */
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+ aa_time = 2 + (g_ble_phy_data.phy_mode_rx == BLE_PHY_MODE_1M ? 40 : 24) + 2 + 1;
+#else
+ aa_time = 45;
+#endif
+
+ if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, aa_time);
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_CORR_START_Msk;
+ } else if (wfr_usecs < 16384) {
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, wfr_usecs + aa_time);
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_CORR_START_Msk;
+ } else {
+ wfr_usecs += aa_time;
+ llt = g_ble_phy_data.start_llt;
+
+ /*
+ * wfr is outside range of CORR_WINDOW so we need to use LLT to start
+ * correlator timeout with some delay. Let's use ~10ms as new CORR_WINDOW
+ * value (does not really matter, just had to pick something) so need to
+ * calculate how many hi-Z ticks of delay we need.
+ */
+ llt_z_ticks = (wfr_usecs - 10000) / 1024;
+
+ /* New CORR_WINDOW is wfr adjusted by hi-Z ticks and remainder of 1st tick. */
+ corr_window = wfr_usecs;
+ corr_window -= llt_z_ticks * 1024;
+ corr_window -= 1024 - (llt & 0x3ff);
+
+ CMAC->CM_LL_TIMER1_36_10_EQ_Z_REG = (llt >> 10) + llt_z_ticks;
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, corr_window);
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_TMR1_36_10_EQ_Z_Msk;
+ }
+}
+
+int
+ble_phy_init(void)
+{
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+#if MYNEWT_VAL(BLE_LL_DTM)
+ g_ble_phy_data.phy_whitening = 1;
+#endif
+
+ ble_rf_init();
+
+ /*
+ * 9_0_EQ_X can be linked to start RX/TX so we'll use this one for
+ * scheduling TX/RX start - make sure it's not linked to LL_TIMER2LLC
+ */
+ CMAC->CM_LL_INT_SEL_REG &= ~CMAC_CM_LL_INT_SEL_REG_LL_TIMER1_9_0_EQ_X_SEL_Msk;
+
+ CMAC->CM_PHY_CTRL_REG = ((PHY_DELAY_POWER_DN_RX - 1) << 24) |
+ ((PHY_DELAY_POWER_DN_TX - 1) << 16) |
+ ((PHY_DELAY_POWER_UP_RX - 1) << 8) |
+ ((PHY_DELAY_POWER_UP_TX - 1));
+
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ CMAC->CM_PHY_CTRL2_REG = CMAC_CM_PHY_CTRL2_REG_PHY_MODE_Msk |
+ (3 << CMAC_CM_PHY_CTRL2_REG_CORR_CLK_MODE_Pos);
+#else
+ CMAC->CM_PHY_CTRL2_REG = CMAC_CM_PHY_CTRL2_REG_PHY_MODE_Msk |
+ (2 << CMAC_CM_PHY_CTRL2_REG_CORR_CLK_MODE_Pos);
+#endif
+
+ CMAC_SETREGF(CM_CTRL2_REG, WHITENING_MODE, 0);
+ CMAC_SETREGF(CM_CTRL2_REG, CRC_MODE, 0);
+
+ /* Setup for 1M by default */
+ ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M);
+ ble_phy_mode_apply(BLE_PHY_MODE_1M);
+
+ NVIC_SetPriority(FIELD_IRQn, 0);
+ NVIC_SetPriority(CALLBACK_IRQn, 0);
+ NVIC_SetPriority(FRAME_IRQn, 0);
+ NVIC_SetPriority(CRYPTO_IRQn, 1);
+ NVIC_SetPriority(SW_MAC_IRQn, 1);
+ NVIC_EnableIRQ(FIELD_IRQn);
+ NVIC_EnableIRQ(CALLBACK_IRQn);
+ NVIC_EnableIRQ(FRAME_IRQn);
+ NVIC_EnableIRQ(SW_MAC_IRQn);
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ /* Initialize non-zero fixed values in CCM blocks */
+ g_ble_phy_encrypt_data.b0[0] = 0x49;
+ g_ble_phy_encrypt_data.b1[1] = 0x01;
+ g_ble_phy_encrypt_data.ai[0] = 0x01;
+#endif
+
+ return 0;
+}
+
+void
+ble_phy_disable(void)
+{
+ MCU_DIAG_SER('D');
+
+ __disable_irq();
+
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_BS_CLEAR_Msk;
+
+ __NOP();
+ __NOP();
+ __NOP();
+ __NOP();
+ __NOP();
+
+ CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk |
+ CMAC_CM_EXC_STAT_REG_EXC_SW_MAC_Msk;
+
+ NVIC->ICPR[0] = (1 << FIELD_IRQn) | (1 << CALLBACK_IRQn) |
+ (1 << FRAME_IRQn) | (1 << SW_MAC_IRQn);
+
+ os_arch_cmac_bs_ctrl_irq_unblock();
+ g_sw_mac_exc = 0;
+
+ CMAC->CM_ERROR_DIS_REG = 0;
+
+ ble_rf_stop();
+
+ /*
+ * If ble_phy_disable is called precisely when access address was matched,
+ * ts1_dirty may not be cleared properly. This is because bs_clear will
+ * cause bitstream controller to be stopped and we won't get callback_irq,
+ * but seems like demodulator is still active for a while and will trigger
+ * ev1c_ts1_trigger on 1st symbol which will set ts1_dirty. We do not expect
+ * ts1_dirty to be set after bs_clear so we won't clear it. To workaround
+ * his, we can just clear it explicitly here after everything is already
+ * disabled.
+ */
+ (void)CMAC->CM_TS1_REG;
+
+ __enable_irq();
+
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+static void
+ble_phy_rx_setup_fields(void)
+{
+ /* Make sure CRC LFSR initial value is set */
+ CMAC_SETREGF(CM_CRC_REG, CRC_INIT_VAL, g_ble_phy_data.crc_init);
+
+ CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr;
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ACCESS_ADDR;
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(0, 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_HEADER;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ /* Only program one byte for encrypted payloads */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ENC_PAYLOAD;
+ } else {
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD;
+ }
+#else
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD;
+#endif
+}
+
+static void
+ble_phy_rx_setup_xcvr(void)
+{
+ uint8_t rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel];
+
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CALLBACK_VALID_SET_Msk;
+
+ ble_rf_setup_rx(rf_chan, g_ble_phy_data.phy_mode_rx);
+
+ g_ble_phy_data.phy_rx_started = 0;
+}
+
+int
+ble_phy_rx(void)
+{
+ MCU_DIAG_SER('R');
+
+ ble_rf_configure();
+ ble_phy_rx_setup_xcvr();
+
+ CMAC->CM_FRAME_1_REG = CMAC_CM_FRAME_1_REG_FRAME_VALID_Msk;
+
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, 0);
+
+ ble_phy_rx_setup_fields();
+
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+ return 0;
+}
+
+int
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ uint32_t ll_val32;
+ int32_t time_till_start;
+
+ MCU_DIAG_SER('r');
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx);
+#endif
+
+ assert(ble_rf_is_enabled());
+
+ ble_phy_rx();
+
+ /* Get LL timer at cputime */
+ ll_val32 = ble_phy_convert_and_record_start_time(cputime, rem_usecs);
+
+ /* Add remaining usecs to get exact receive start time */
+ ll_val32 += rem_usecs;
+
+ /* Adjust start time for rx delays */
+ ll_val32 -= PHY_DELAY_POWER_UP_RX - g_ble_phy_data.path_delay_rx;
+
+ __disable_irq();
+ CMAC->CM_LL_TIMER1_9_0_EQ_X_REG = ll_val32;
+ CMAC->CM_EV_LINKUP_REG =
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_TMR1_9_0_EQ_X_Msk;
+
+ time_till_start = (int32_t)(ll_val32 - cmac_timer_read32());
+ if (time_till_start <= 0) {
+ /*
+ * Possible we missed the frame start! If we have, we need to start
+ * ASAP.
+ */
+ if ((CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) == 0) {
+ /* We missed start. Start now */
+ CMAC->CM_EV_LINKUP_REG =
+ CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_ASAP_Msk;
+ }
+ }
+ __enable_irq();
+
+ return 0;
+}
+
+int
+ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
+{
+ uint8_t *txbuf = g_ble_phy_tx_buf;
+ int rc;
+
+ MCU_DIAG_SER('T');
+
+ assert(CMAC->CM_FRAME_1_REG & CMAC_CM_FRAME_1_REG_FRAME_TX_Msk);
+
+ g_ble_phy_data.end_transition = end_trans;
+
+ /*
+ * Program required fields now so in worst case TX can continue while we
+ * are still preparing header and payload.
+ */
+ CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr & 1 ? 0x5555 : 0xaaaa;
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PREAMBLE;
+ CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr;
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_ACCESS_ADDR;
+
+ /* Make sure CRC LFSR initial value is set */
+ CMAC_SETREGF(CM_CRC_REG, CRC_INIT_VAL, g_ble_phy_data.crc_init);
+
+ /* txbuf[0] is hdr_byte, txbuf[1] is pkt_len */
+ txbuf[1] = pducb(&txbuf[2], pducb_arg, &txbuf[0]);
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted && (txbuf[1] != 0)) {
+ /* We have to add the MIC to the length */
+ txbuf[1] += BLE_LL_DATA_MIC_LEN;
+
+ /* Program header field */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD;
+
+ /* Program payload (and MIC) */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(2, txbuf[1]);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_ENC_PAYLOAD;
+ } else {
+ /* Program header and payload fields */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, txbuf[1] + 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD;
+ }
+#else
+ /* Program header and payload fields */
+ CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, txbuf[1] + 2);
+ CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD;
+#endif
+
+ /*
+ * If there was FIELD_ON_THR exception it means access address was already
+ * sent and we are likely too late here - abort.
+ */
+ if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) {
+ ble_phy_disable();
+ g_ble_phy_data.end_transition = BLE_PHY_TRANSITION_NONE;
+ STATS_INC(ble_phy_stats, tx_late);
+ rc = BLE_PHY_ERR_RADIO_STATE;
+ } else {
+ if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) {
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+ }
+ STATS_INC(ble_phy_stats, tx_good);
+ STATS_INCN(ble_phy_stats, tx_bytes, txbuf[1] + 2);
+ rc = BLE_ERR_SUCCESS;
+ }
+
+ /* Now we can handle BS_CTRL */
+ CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk;
+ NVIC_EnableIRQ(FRAME_IRQn);
+ NVIC_EnableIRQ(FIELD_IRQn);
+
+ return rc;
+}
+
+int
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ uint8_t rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel];
+ uint32_t ll_val32;
+ int rc;
+
+ MCU_DIAG_SER('t');
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_mode_tx);
+#endif
+
+ assert(ble_rf_is_enabled());
+
+ ble_rf_configure();
+ ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx);
+
+ ll_val32 = ble_phy_convert_and_record_start_time(cputime, rem_usecs);
+ ll_val32 += rem_usecs;
+ ll_val32 -= PHY_DELAY_POWER_UP_TX + g_ble_phy_data.path_delay_tx;
+ /* we can schedule TX only up to 1023us in advance */
+ assert((int32_t)(ll_val32 - cmac_timer_read32()) < 1024);
+
+ /*
+ * We do not want FIELD/FRAME interrupts or FIELD1_ERR until ble_phy_tx()
+ * has finished pushing all the fields. Also we do not want premature
+ * FRAME_ERR so disable it until we program FRAME1 properly. If we won't
+ * make configuration on time, assume tx_late and abort TX.
+ */
+ NVIC_DisableIRQ(FRAME_IRQn);
+ NVIC_DisableIRQ(FIELD_IRQn);
+ CMAC->CM_ERROR_DIS_REG |= CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk |
+ CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk;
+
+ CMAC->CM_LL_TIMER1_9_0_EQ_X_REG = ll_val32;
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_TMR1_9_0_EQ_X_Msk;
+
+ if ((int32_t)(ll_val32 - cmac_timer_read32()) < 0) {
+ goto tx_late;
+ }
+
+ /*
+ * Program frame now since it needs to be ready for FRAME_START, we can
+ * push fields later
+ */
+ CMAC->CM_FRAME_1_REG = CMAC_CM_FRAME_1_REG_FRAME_VALID_Msk |
+ CMAC_CM_FRAME_1_REG_FRAME_TX_Msk |
+ CMAC_CM_FRAME_1_REG_FRAME_EXC_ON_BS_START_Msk;
+
+ /*
+ * There should be no EXC_FRAME_START here so if it already happened we
+ * need to assume tx_late and abort.
+ */
+ if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) {
+ goto tx_late;
+ }
+
+ CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk;
+ rc = 0;
+
+ goto done;
+
+tx_late:
+ STATS_INC(ble_phy_stats, tx_late);
+ ble_phy_disable();
+ NVIC_EnableIRQ(FRAME_IRQn);
+ NVIC_EnableIRQ(FIELD_IRQn);
+ rc = BLE_PHY_ERR_TX_LATE;
+
+done:
+ return rc;
+}
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+ g_ble_phy_data.txend_cb = txend_cb;
+ g_ble_phy_data.txend_arg = arg;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+void
+ble_phy_tx_enc_start(void)
+{
+ struct ble_phy_encrypt_obj *enc;
+
+ enc = &g_ble_phy_encrypt_data;
+ enc->b0[15] = g_ble_phy_tx_buf[1] - 4;
+ enc->b1[2] = g_ble_phy_tx_buf[0] & BLE_LL_DATA_HDR_LLID_MASK;
+
+ /* XXX: should we check for busy? */
+ /* XXX: might not be needed, but for now terminate any crypto operations. */
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_ABORT_Msk;
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_MAC_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_PLD_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_AUTH_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
+
+ /* Start crypto */
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
+}
+
+void
+ble_phy_rx_enc_start(uint8_t len)
+{
+ struct ble_phy_encrypt_obj *enc;
+
+ enc = &g_ble_phy_encrypt_data;
+ enc->b0[15] = len - 4; /* length without MIC as length includes MIC */
+ enc->b1[2] = g_ble_phy_rx_buf[0] & BLE_LL_DATA_HDR_LLID_MASK;
+
+ /* XXX: should we check for busy? */
+ /* XXX: might not be needed, but for now terminate any crypto operations. */
+ //CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_ABORT_Msk;
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_MAC_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_PLD_EN_Msk |
+ CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_AUTH_EN_Msk;
+
+ /* Start crypto */
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
+}
+
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+ uint8_t is_master)
+{
+ struct ble_phy_encrypt_obj *enc;
+
+ enc = &g_ble_phy_encrypt_data;
+ memcpy(enc->key, key, 16);
+ memcpy(&enc->b0[6], iv, 8);
+ put_le32(&enc->b0[1], pkt_counter);
+ enc->b0[5] = is_master ? 0x80 : 0;
+ memcpy(&enc->ai[6], iv, 8);
+ put_le32(&enc->ai[1], pkt_counter);
+ enc->ai[5] = enc->b0[5];
+
+ g_ble_phy_data.phy_encrypted = 1;
+
+ /* Program key registers */
+ CMAC->CM_CRYPTO_KEY_31_0_REG = get_le32(&enc->key[0]);
+ CMAC->CM_CRYPTO_KEY_63_32_REG = get_le32(&enc->key[4]);
+ CMAC->CM_CRYPTO_KEY_95_64_REG = get_le32(&enc->key[8]);
+ CMAC->CM_CRYPTO_KEY_127_96_REG = get_le32(&enc->key[12]);
+
+ /* Program ADRx registers */
+ CMAC->CM_CRYPTO_IN_ADR0_REG = (uint32_t)enc->b1;
+ CMAC->CM_CRYPTO_IN_ADR1_REG = (uint32_t)enc->b0;
+ CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)&g_ble_phy_tx_buf[2];
+ CMAC->CM_CRYPTO_IN_ADR3_REG = (uint32_t)enc->ai;
+ CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)&g_ble_phy_rx_buf[2];
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk;
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+ struct ble_phy_encrypt_obj *enc;
+
+ enc = &g_ble_phy_encrypt_data;
+ put_le32(&enc->b0[1], pkt_counter);
+ enc->b0[5] = dir ? 0x80 : 0;
+ put_le32(&enc->ai[1], pkt_counter);
+ enc->ai[5] = enc->b0[5];
+
+ CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk;
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+ g_ble_phy_data.phy_encrypted = 0;
+}
+#endif
+
+int
+ble_phy_txpwr_set(int dbm)
+{
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ if (g_cmac_shared_data.debug.tx_power_override != INT8_MAX) {
+ ble_rf_set_tx_power(g_cmac_shared_data.debug.tx_power_override);
+ } else {
+ ble_rf_set_tx_power(dbm);
+ }
+#else
+ ble_rf_set_tx_power(dbm);
+#endif
+
+ return 0;
+}
+
+int
+ble_phy_txpower_round(int dbm)
+{
+ return 0;
+}
+
+void
+ble_phy_set_rx_pwr_compensation(int8_t compensation)
+{
+}
+
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crc_init)
+{
+ uint8_t rf_chan = g_ble_phy_chan_to_rf[chan];
+
+ assert(chan < BLE_PHY_NUM_CHANS);
+
+ if (chan >= BLE_PHY_NUM_CHANS) {
+ return BLE_PHY_ERR_INV_PARAM;
+ }
+
+ g_ble_phy_data.channel = chan;
+ g_ble_phy_data.access_addr = access_addr;
+ g_ble_phy_data.crc_init = crc_init;
+
+ CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_RF_CHANNEL, rf_chan);
+
+ return 0;
+}
+
+void
+ble_phy_restart_rx(void)
+{
+ /* XXX: for now, we will disable the phy using ble_phy_disable and then
+ re-enable it
+ */
+ ble_phy_disable();
+
+ /* Apply mode before starting RX */
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx);
+#endif
+
+ /* Setup phy to rx again */
+ ble_phy_rx();
+
+ /* Start reception now */
+ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_ASAP_Msk;
+}
+
+uint32_t
+ble_phy_access_addr_get(void)
+{
+ return g_ble_phy_data.access_addr;
+}
+
+int
+ble_phy_state_get(void)
+{
+ return g_ble_phy_data.phy_state;
+}
+
+int
+ble_phy_rx_started(void)
+{
+ return g_ble_phy_data.phy_rx_started;
+}
+
+uint8_t
+ble_phy_xcvr_state_get(void)
+{
+ return ble_rf_is_enabled();
+}
+
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+ return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+void
+ble_phy_resolv_list_enable(void)
+{
+ g_ble_phy_data.phy_privacy = 1;
+
+ ble_hw_resolv_proc_enable();
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+ ble_hw_resolv_proc_disable();
+
+ g_ble_phy_data.phy_privacy = 0;
+}
+
+void
+ble_phy_rfclk_enable(void)
+{
+ ble_rf_enable();
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+ /* XXX We can't disable RF while PHY_BUSY is asserted so let's wait a bit */
+ while (CMAC->CM_DIAG_WORD2_REG & CMAC_CM_DIAG_WORD2_REG_DIAG2_PHY_BUSY_BUF_Msk);
+
+ ble_rf_disable();
+}
+
+#if MYNEWT_VAL(BLE_LL_DTM)
+void
+ble_phy_enable_dtm(void)
+{
+ g_ble_phy_data.phy_whitening = 0;
+}
+
+void
+ble_phy_disable_dtm(void)
+{
+ g_ble_phy_data.phy_whitening = 1;
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c
new file mode 100644
index 00000000..806f4ea8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c
@@ -0,0 +1,747 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include "mcu/mcu.h"
+#include "mcu/cmac_timer.h"
+#include "controller/ble_phy.h"
+#include "cmac_driver/cmac_shared.h"
+#include "ble_rf_priv.h"
+
+#define RF_CALIBRATION_0 (0x01)
+#define RF_CALIBRATION_1 (0x02)
+#define RF_CALIBRATION_2 (0x04)
+
+static const int8_t g_ble_rf_power_lvls[] = {
+ -18, -12, -8, -6, -3, -2, -1, 0, 1, 2, 3, 4, 4, 5, 6
+};
+
+struct ble_phy_rf_data {
+ uint8_t tx_power_cfg0;
+ uint8_t tx_power_cfg1;
+ uint8_t tx_power_cfg2;
+ uint8_t tx_power_cfg3;
+ uint32_t cal_res_1;
+ uint32_t cal_res_2;
+ uint32_t trim_val1_tx_1;
+ uint32_t trim_val1_tx_2;
+ uint32_t trim_val2_tx;
+ uint32_t trim_val2_rx;
+ uint8_t calibrate_req;
+};
+
+static struct ble_phy_rf_data g_ble_phy_rf_data;
+
+static inline uint32_t
+get_reg32(uint32_t addr)
+{
+ volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+ return *reg;
+}
+
+static inline uint32_t
+get_reg32_bits(uint32_t addr, uint32_t mask)
+{
+ volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+ return (*reg & mask) >> __builtin_ctz(mask);
+}
+
+static inline void
+set_reg8(uint32_t addr, uint8_t val)
+{
+ volatile uint8_t *reg = (volatile uint8_t *)addr;
+
+ *reg = val;
+}
+
+static inline void
+set_reg16(uint32_t addr, uint16_t val)
+{
+ volatile uint16_t *reg = (volatile uint16_t *)addr;
+
+ *reg = val;
+}
+
+static inline void
+set_reg32(uint32_t addr, uint32_t val)
+{
+ volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+ *reg = val;
+}
+
+static inline void
+set_reg32_bits(uint32_t addr, uint32_t mask, uint32_t val)
+{
+ volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+ *reg = (*reg & (~mask)) | (val << __builtin_ctz(mask));
+}
+
+static inline void
+set_reg32_mask(uint32_t addr, uint32_t mask, uint32_t val)
+{
+ volatile uint32_t *reg = (volatile uint32_t *)addr;
+
+ *reg = (*reg & (~mask)) | (val & mask);
+}
+
+static inline void
+set_reg16_mask(uint32_t addr, uint16_t mask, uint16_t val)
+{
+ volatile uint16_t *reg = (volatile uint16_t *)addr;
+
+ *reg = (*reg & (~mask)) | (val & mask);
+}
+
+static void
+delay_us(uint32_t delay_us)
+{
+ while (delay_us--) {
+ __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
+ __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
+ __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
+ __NOP(); __NOP(); __NOP(); __NOP();
+ }
+}
+
+static void
+ble_rf_apply_trim(volatile uint32_t *tv, unsigned len)
+{
+ while (len) {
+ *(volatile uint32_t *)tv[0] = tv[1];
+ len -= 2;
+ tv += 2;
+ }
+}
+
+static void
+ble_rf_apply_calibration(void)
+{
+ set_reg32(0x40020094, g_ble_phy_rf_data.cal_res_1);
+ if (g_ble_phy_rf_data.cal_res_2) {
+ set_reg32_bits(0x40022018, 0xff800000, g_ble_phy_rf_data.cal_res_2);
+ set_reg32_bits(0x40022018, 0x00007fc0, g_ble_phy_rf_data.cal_res_2);
+ }
+}
+
+static inline void
+ble_rf_ldo_on(void)
+{
+ set_reg8(0x40020004, 9);
+}
+
+static inline void
+ble_rf_ldo_off(void)
+{
+ set_reg8(0x40020004, 0);
+}
+
+static inline void
+ble_rf_rfcu_enable(void)
+{
+ set_reg32_bits(0x50000010, 0x00000020, 1);
+}
+
+static inline void
+ble_rf_rfcu_disable(void)
+{
+ set_reg32_bits(0x50000010, 0x00000020, 0);
+}
+
+static void
+ble_rf_rfcu_apply_recommended_settings(void)
+{
+ set_reg16_mask(0x400200a0, 0x0001, 0x0001);
+ set_reg16_mask(0x40021020, 0x03f0, 0x02f5);
+ set_reg32_mask(0x40021018, 0x001fffff, 0x005a5809);
+ set_reg32_mask(0x4002101c, 0x00001e01, 0x0040128c);
+ set_reg32_mask(0x40021004, 0xffffff1f, 0x64442404);
+ set_reg32_mask(0x40021008, 0xfcfcffff, 0x6b676665);
+ set_reg32_mask(0x4002100c, 0x00fcfcfc, 0x9793736f);
+ set_reg32_mask(0x40021010, 0x1f1f1c1f, 0x04072646);
+ set_reg32_mask(0x40020000, 0x001ff000, 0x0f099820);
+ set_reg16_mask(0x40020348, 0x00ff, 0x0855);
+ set_reg16(0x40020350, 0x0234);
+ set_reg16(0x40020354, 0x0a34);
+ set_reg16(0x40020358, 0x0851);
+ set_reg16(0x4002035c, 0x0a26);
+ set_reg16(0x40020360, 0x0858);
+ set_reg16(0x4002102c, 0xdfe7);
+ set_reg32_mask(0x4002103c, 0x00c00000, 0x0024a19f);
+ set_reg16_mask(0x40021000, 0x0008, 0x000b);
+ set_reg16_mask(0x40020238, 0x03e0, 0x02c0);
+ set_reg16_mask(0x4002023c, 0x03e0, 0x02c0);
+ set_reg16_mask(0x40020244, 0x03e0, 0x0250);
+ set_reg16_mask(0x40020248, 0x03e0, 0x02a0);
+ set_reg16_mask(0x4002024c, 0x03e0, 0x02c0);
+ set_reg16_mask(0x40020288, 0x03e0, 0x0300);
+ set_reg16_mask(0x4002029c, 0x001f, 0x0019);
+ set_reg16_mask(0x4002003c, 0x6000, 0x0788);
+ set_reg16_mask(0x40020074, 0x7f00, 0x2007);
+ set_reg32_mask(0x40020080, 0x00333330, 0x00222224);
+ set_reg32_mask(0x40020068, 0x00000f0f, 0x00000f0d);
+}
+
+static void
+ble_rf_rfcu_apply_settings(void)
+{
+ ble_rf_apply_trim(g_cmac_shared_data.trim.rfcu,
+ g_cmac_shared_data.trim.rfcu_len);
+ ble_rf_rfcu_apply_recommended_settings();
+}
+
+static inline void
+ble_rf_synth_enable(void)
+{
+ set_reg8(0x40020005, 3);
+}
+
+static inline void
+ble_rf_synth_disable(void)
+{
+ set_reg8(0x40020005, 0);
+ __NOP();
+ __NOP();
+}
+
+static bool
+ble_rf_synth_is_enabled(void)
+{
+ return get_reg32_bits(0x40020004, 256);
+}
+
+static void
+ble_rf_synth_apply_recommended_settings(void)
+{
+ set_reg32_mask(0x40022048, 0x0000000c, 0x000000d5);
+ set_reg32_mask(0x40022050, 0x00000300, 0x00000300);
+ set_reg16_mask(0x40022024, 0x0001, 0x0001);
+}
+
+static void
+ble_rf_synth_apply_settings(void)
+{
+ ble_rf_apply_trim(g_cmac_shared_data.trim.synth,
+ g_cmac_shared_data.trim.synth_len);
+ ble_rf_synth_apply_recommended_settings();
+}
+
+static void
+ble_rf_calibration_0(void)
+{
+ uint32_t bkp[10];
+
+ bkp[0] = get_reg32(0x40020208);
+ bkp[1] = get_reg32(0x40020250);
+ bkp[2] = get_reg32(0x40020254);
+ bkp[3] = get_reg32(0x40021028);
+ bkp[4] = get_reg32(0x40020020);
+ bkp[5] = get_reg32(0x40020294);
+ bkp[6] = get_reg32(0x4002103C);
+ bkp[7] = get_reg32(0x400200A8);
+ bkp[8] = get_reg32(0x40020000);
+ bkp[9] = get_reg32(0x40022000);
+
+ set_reg32_bits(0x40020000, 0x00000002, 0);
+ set_reg32_bits(0x40022000, 0x00000001, 0);
+ set_reg32_mask(0x4002103C, 0x00201c00, 0x00001c00);
+ set_reg32_bits(0x400200A8, 0x00000001, 1);
+ set_reg8(0x40020006, 1);
+ set_reg32(0x40020208, 0);
+ set_reg32(0x40020250, 0);
+ set_reg32(0x40020254, 0);
+ set_reg32(0x40021028, 0x00F8A494);
+ set_reg32(0x40020020, 8);
+ set_reg32(0x40020294, 0);
+ set_reg32(0x40020024, 0);
+
+ delay_us(5);
+ if (get_reg32_bits(0x40020020, 0x00000002)) {
+ goto done;
+ }
+
+ set_reg32_bits(0x40020020, 0x00000001, 1);
+ delay_us(15);
+ if (!get_reg32_bits(0x40020020, 0x00000001)) {
+ goto done;
+ }
+
+ delay_us(300);
+ if (get_reg32_bits(0x40020020, 0x00000001)) {
+ goto done;
+ }
+
+done:
+ set_reg32(0x40020024, 0);
+ set_reg32(0x40020208, bkp[0]);
+ set_reg32(0x40020250, bkp[1]);
+ set_reg32(0x40020254, bkp[2]);
+ set_reg32(0x40021028, bkp[3]);
+ set_reg32(0x40020020, bkp[4]);
+ set_reg32(0x40020294, bkp[5]);
+ set_reg32(0x4002103C, bkp[6]);
+ set_reg32(0x400200A8, bkp[7]);
+ set_reg32(0x40020000, bkp[8]);
+ set_reg32(0x40022000, bkp[9]);
+}
+
+static void
+ble_rf_calibration_1(void)
+{
+ uint32_t bkp[12];
+ uint32_t val;
+
+ bkp[0] = get_reg32(0x40020020);
+ bkp[1] = get_reg32(0x40020208);
+ bkp[2] = get_reg32(0x40020250);
+ bkp[3] = get_reg32(0x40020254);
+ bkp[4] = get_reg32(0x40020218);
+ bkp[5] = get_reg32(0x4002021c);
+ bkp[6] = get_reg32(0x40020220);
+ bkp[7] = get_reg32(0x40020270);
+ bkp[8] = get_reg32(0x4002027c);
+ bkp[9] = get_reg32(0x4002101c);
+ bkp[10] = get_reg32(0x40020000);
+ bkp[11] = get_reg32(0x40022000);
+
+ set_reg32(0x4002103c, 0x0124a21f);
+ set_reg32(0x40020208, 0);
+ set_reg32(0x40020250, 0);
+ set_reg32(0x40020254, 0);
+ set_reg32(0x40020218, 0);
+ set_reg32(0x4002021c, 0);
+ set_reg32(0x40020220, 0);
+ set_reg32(0x40020270, 0);
+ set_reg32(0x4002027c, 0);
+ set_reg32(0x40020000, 0x0f168820);
+ set_reg32_bits(0x40022000, 0x00000001, 0);
+ set_reg32_bits(0x4002101c, 0x00001e00, 0);
+ set_reg32_bits(0x4002001c, 0x0000003f, 47);
+ set_reg8(0x40020006, 1);
+ set_reg32(0x40020020, 16);
+ set_reg32_bits(0x4002003c, 0x00000800, 1);
+ set_reg32(0x40020024, 0);
+
+ delay_us(5);
+ if (get_reg32_bits(0x40020020, 0x00000002)) {
+ goto done;
+ }
+
+ set_reg32_bits(0x40020020, 0x00000001, 1);
+ delay_us(15);
+ if (!get_reg32_bits(0x40020020, 0x00000001)) {
+ goto done;
+ }
+
+ delay_us(300);
+ if (get_reg32_bits(0x40020020, 0x00000001)) {
+ goto done;
+ }
+
+ val = get_reg32(0x40020090);
+ set_reg32_bits(0x40020094, 0x0000000f, val);
+ set_reg32_bits(0x40020094, 0x00000f00, val);
+ set_reg32_bits(0x40020094, 0x000f0000, val);
+ set_reg32_bits(0x40020094, 0x0f000000, val);
+ g_ble_phy_rf_data.cal_res_1 = get_reg32(0x40020094);
+
+done:
+ set_reg32(0x40020024, 0);
+ set_reg32(0x40020020, bkp[0]);
+ set_reg32(0x40020208, bkp[1]);
+ set_reg32(0x40020250, bkp[2]);
+ set_reg32(0x40020254, bkp[3]);
+ set_reg32(0x40020218, bkp[4]);
+ set_reg32(0x4002021c, bkp[5]);
+ set_reg32(0x40020220, bkp[6]);
+ set_reg32(0x40020270, bkp[7]);
+ set_reg32(0x4002027c, bkp[8]);
+ set_reg32(0x4002101c, bkp[9]);
+ set_reg32(0x40020000, bkp[10]);
+ set_reg32(0x40022000, bkp[11]);
+ set_reg32_bits(0x4002003c, 0x00000800, 0);
+}
+
+static void
+ble_rf_calibration_2(void)
+{
+ uint32_t bkp[2];
+ uint32_t k1;
+
+ set_reg8(0x40020005, 3);
+ set_reg32(0x40022000, 0x00000300);
+ set_reg32_bits(0x40022004, 0x0000007f, 20);
+ bkp[0] = get_reg32(0x40022040);
+ set_reg32(0x40022040, 0xffffffff);
+ set_reg32_bits(0x40022018, 0x0000003f, 0);
+ set_reg32_bits(0x40022018, 0x00008000, 0);
+ set_reg32_bits(0x4002201c, 0x00000600, 2);
+ set_reg32_bits(0x4002201c, 0x00000070, 4);
+ set_reg32_bits(0x40022030, 0x3f000000, 22);
+ set_reg32_bits(0x40022030, 0x00000fc0, 24);
+ set_reg32_bits(0x40022030, 0x0000003f, 24);
+ set_reg8(0x4002201c, 0x43);
+ set_reg8(0x40020006, 2);
+ delay_us(2);
+ bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
+ set_reg32_bits(0x4002024c, 0x000003e0, 0);
+ set_reg8(0x40020006, 1);
+ set_reg32_bits(0x400200ac, 0x00000003, 3);
+ delay_us(30);
+ delay_us(100);
+ set_reg8(0x40020005, 3);
+ k1 = get_reg32_bits(0x40022088, 0x000001ff);
+ set_reg32(0x400200ac, 0);
+ delay_us(20);
+ set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
+ delay_us(10);
+
+ set_reg32_bits(0x40022018, 0xff800000, k1);
+ set_reg32_bits(0x40022018, 0x00007fc0, k1);
+ set_reg8(0x4002201c, 0x41);
+ set_reg32_bits(0x4002201c, 0x00000600, 2);
+ set_reg8(0x40020006, 2);
+ delay_us(2);
+ bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
+ set_reg32_bits(0x4002024c, 0x000003e0, 0);
+ set_reg8(0x40020006, 1);
+ set_reg32_bits(0x400200ac, 0x00000003, 3);
+ delay_us(30);
+ delay_us(100);
+ set_reg8(0x40020005, 3);
+ k1 = get_reg32_bits(0x40022088, 0x1ff);
+ set_reg32(0x400200ac, 0);
+ delay_us(20);
+ set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
+ delay_us(10);
+
+ set_reg32_bits(0x40022018, 0xff800000, k1);
+ set_reg32_bits(0x40022018, 0x00007fc0, k1);
+ set_reg8(0x4002201c, 0x41);
+ set_reg32_bits(0x4002201c, 0x00000600, 2);
+ set_reg8(0x40020006, 2);
+ delay_us(2);
+ bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
+ set_reg32_bits(0x4002024c, 0x000003e0, 0);
+ set_reg8(0x40020006, 1);
+ set_reg32_bits(0x400200ac, 0x00000003, 3);
+ delay_us(30);
+ delay_us(100);
+ set_reg8(0x40020005, 3);
+ k1 = get_reg32_bits(0x40022088, 0x000001ff);
+ set_reg32_bits(0x40022018, 0xff800000, k1);
+ set_reg32_bits(0x40022018, 0x00007fc0, k1);
+ set_reg32_bits(0x4002201c, 0x00000001, 0);
+ set_reg32(0x40022040, bkp[0]);
+ set_reg32_bits(0x40022018, 0x0000003f, 0x1c);
+ set_reg32_bits(0x40022018, 0x00008000, 0);
+ set_reg32_bits(0x40022030, 0x3f000000, 28);
+ set_reg32_bits(0x40022030, 0x00000fc0, 30);
+ set_reg32_bits(0x40022030, 0x0000003f, 30);
+ set_reg32(0x400200ac, 0);
+ delay_us(20);
+ set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
+ delay_us(10);
+
+ g_ble_phy_rf_data.cal_res_2 = k1;
+}
+
+static void
+ble_rf_calibrate_int(uint8_t mask)
+{
+ __disable_irq();
+
+ ble_rf_enable();
+ delay_us(20);
+
+ ble_rf_synth_disable();
+ ble_rf_synth_enable();
+ ble_rf_synth_apply_settings();
+ set_reg8(0x40020005, 1);
+
+ if (mask & RF_CALIBRATION_0) {
+ ble_rf_calibration_0();
+ }
+ if (mask & RF_CALIBRATION_1) {
+ ble_rf_calibration_1();
+ }
+ if (mask & RF_CALIBRATION_2) {
+ ble_rf_calibration_2();
+ }
+
+ ble_rf_disable();
+
+ __enable_irq();
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ g_cmac_shared_data.debug.cal_res_1 = g_ble_phy_rf_data.cal_res_1;
+ g_cmac_shared_data.debug.cal_res_2 = g_ble_phy_rf_data.cal_res_2;
+#endif
+}
+
+bool
+ble_rf_try_recalibrate(uint32_t idle_time_us)
+{
+ /* Run recalibration if we have at least 1ms of time to spare and RF is
+ * currently disabled. Calibration is much shorter than 1ms, but that gives
+ * us good margin to make sure we can finish before next event.
+ */
+ if (!g_ble_phy_rf_data.calibrate_req || (idle_time_us < 1000) ||
+ ble_rf_is_enabled()) {
+ return false;
+ }
+
+ ble_rf_calibrate_int(RF_CALIBRATION_2);
+
+ g_ble_phy_rf_data.calibrate_req = 0;
+
+ return true;
+}
+
+static uint32_t
+ble_rf_find_trim_reg(volatile uint32_t *tv, unsigned len, uint32_t reg)
+{
+ while (len) {
+ if (tv[0] == reg) {
+ return tv[1];
+ }
+ len -= 2;
+ tv += 2;
+ }
+
+ return 0;
+}
+
+void
+ble_rf_init(void)
+{
+ static bool done = false;
+ uint32_t val;
+
+ ble_rf_disable();
+
+ if (done) {
+ return;
+ }
+
+ val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode1,
+ g_cmac_shared_data.trim.rfcu_mode1_len,
+ 0x4002004c);
+ g_ble_phy_rf_data.trim_val1_tx_1 = val;
+
+ val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode2,
+ g_cmac_shared_data.trim.rfcu_mode2_len,
+ 0x4002004c);
+ g_ble_phy_rf_data.trim_val1_tx_2 = val;
+
+ if (!g_ble_phy_rf_data.trim_val1_tx_1 || !g_ble_phy_rf_data.trim_val1_tx_2) {
+ val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu,
+ g_cmac_shared_data.trim.rfcu_len,
+ 0x4002004c);
+ if (!val) {
+ val = 0x0300;
+ }
+ g_ble_phy_rf_data.trim_val1_tx_1 = val;
+ g_ble_phy_rf_data.trim_val1_tx_2 = val;
+ }
+
+ val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.synth,
+ g_cmac_shared_data.trim.synth_len,
+ 0x40022038);
+ if (!val) {
+ val = 0x0198ff03;
+ }
+ g_ble_phy_rf_data.trim_val2_rx = val;
+ g_ble_phy_rf_data.trim_val2_tx = val;
+ set_reg32_bits((uint32_t)&g_ble_phy_rf_data.trim_val2_tx, 0x0001ff00, 0x87);
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ g_cmac_shared_data.debug.trim_val1_tx_1 = g_ble_phy_rf_data.trim_val1_tx_1;
+ g_cmac_shared_data.debug.trim_val1_tx_2 = g_ble_phy_rf_data.trim_val1_tx_2;
+ g_cmac_shared_data.debug.trim_val2_tx = g_ble_phy_rf_data.trim_val2_tx;
+ g_cmac_shared_data.debug.trim_val2_rx = g_ble_phy_rf_data.trim_val2_rx;
+#endif
+
+ ble_rf_rfcu_enable();
+ ble_rf_rfcu_apply_settings();
+ g_ble_phy_rf_data.tx_power_cfg1 = get_reg32_bits(0x500000a4, 0xf0);
+ g_ble_phy_rf_data.tx_power_cfg2 = get_reg32_bits(0x40020238, 0x000003e0);
+ g_ble_phy_rf_data.tx_power_cfg3 = 0;
+ ble_rf_rfcu_disable();
+
+ ble_rf_calibrate_int(RF_CALIBRATION_0 | RF_CALIBRATION_1 | RF_CALIBRATION_2);
+
+ done = true;
+}
+
+void
+ble_rf_enable(void)
+{
+ if (ble_rf_is_enabled()) {
+ return;
+ }
+
+ ble_rf_rfcu_enable();
+ ble_rf_rfcu_apply_settings();
+ ble_rf_ldo_on();
+}
+
+void
+ble_rf_configure(void)
+{
+ if (ble_rf_synth_is_enabled()) {
+ return;
+ }
+
+ ble_rf_synth_enable();
+ ble_rf_synth_apply_settings();
+}
+
+void
+ble_rf_stop(void)
+{
+ ble_rf_synth_disable();
+ set_reg8(0x40020006, 0);
+}
+
+void
+ble_rf_disable(void)
+{
+ ble_rf_stop();
+ ble_rf_ldo_off();
+ ble_rf_rfcu_disable();
+}
+
+bool
+ble_rf_is_enabled(void)
+{
+ return get_reg32_bits(0x40020008, 5) == 5;
+}
+
+void
+ble_rf_calibrate_req(void)
+{
+ g_ble_phy_rf_data.calibrate_req = 1;
+}
+
+void
+ble_rf_setup_tx(uint8_t rf_chan, uint8_t phy_mode)
+{
+ set_reg32_bits(0x40020000, 0x0f000000, g_ble_phy_rf_data.tx_power_cfg0);
+ set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
+ set_reg32_bits(0x40020238, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg2);
+ set_reg32_bits(0x40020234, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg3);
+
+ if (g_ble_phy_rf_data.tx_power_cfg0 < 13) {
+ set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_1);
+ } else {
+ set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_2);
+ }
+ set_reg8(0x40020005, 3);
+ set_reg8(0x40022004, rf_chan);
+ if (phy_mode == BLE_PHY_MODE_2M) {
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ set_reg32(0x40022000, 0x00000303);
+#else
+ set_reg32(0x40022000, 0x00000003);
+#endif
+ } else {
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ set_reg32(0x40022000, 0x00000300);
+#else
+ set_reg32(0x40022000, 0x00000000);
+#endif
+ }
+
+ ble_rf_apply_calibration();
+
+ set_reg32_bits(0x40022050, 0x00000200, 1);
+ set_reg32_bits(0x40022050, 0x00000100, 0);
+ set_reg32_bits(0x40022048, 0x01ffff00, 0x7700);
+ set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_tx);
+
+ set_reg8(0x40020006, 3);
+}
+
+void
+ble_rf_setup_rx(uint8_t rf_chan, uint8_t phy_mode)
+{
+ set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
+ set_reg8(0x40020005, 3);
+ set_reg8(0x40022004, rf_chan);
+ if (phy_mode == BLE_PHY_MODE_2M) {
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ set_reg32(0x40022000, 0x00000303);
+ set_reg32(0x40020000, 0x0f11b823);
+ set_reg32(0x4002103c, 0x0125261b);
+#else
+ set_reg32(0x40022000, 0x00000003);
+ set_reg32(0x40020000, 0x0f0c2803);
+ set_reg32(0x4002103c, 0x0125a61b);
+#endif
+ set_reg32(0x40021020, 0x000002f5);
+ set_reg32(0x4002102c, 0x0000d1d5);
+ } else {
+#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
+ set_reg32(0x40022000, 0x00000300);
+ set_reg32(0x40020000, 0x0f099820);
+ set_reg32(0x4002103c, 0x0124a21f);
+#else
+ set_reg32(0x40022000, 0x00000000);
+ set_reg32(0x40020000, 0x0f062800);
+ set_reg32(0x4002103c, 0x01051e1f);
+#endif
+ set_reg32(0x40021020, 0x000002f5);
+ set_reg32(0x4002102c, 0x0000dfe7);
+ }
+
+ ble_rf_apply_calibration();
+
+ set_reg32_bits(0x40022050, 0x00000200, 1);
+ set_reg32_bits(0x40022050, 0x00000100, 1);
+ set_reg32_bits(0x40022048, 0x01ffff00, 0);
+ set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_rx);
+
+ set_reg8(0x40020006, 3);
+}
+
+void
+ble_rf_set_tx_power(int dbm)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(g_ble_rf_power_lvls); i++) {
+ if (g_ble_rf_power_lvls[i] >= dbm) {
+ break;
+ }
+ }
+
+ g_ble_phy_rf_data.tx_power_cfg0 = i + 1;
+}
+
+int8_t
+ble_rf_get_rssi(void)
+{
+ return (501 * get_reg32_bits(0x40021038, 0x000003ff) - 493000) / 4096;
+}
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h
new file mode 100644
index 00000000..50c2e4a7
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h
@@ -0,0 +1,38 @@
+/*
+ * 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 _BLE_RF_PRIV_H_
+#define _BLE_RF_PRIV_H_
+
+void ble_rf_init(void);
+void ble_rf_enable(void);
+void ble_rf_stop(void);
+void ble_rf_disable(void);
+bool ble_rf_is_enabled(void);
+void ble_rf_configure(void);
+
+void ble_rf_calibrate(void);
+
+void ble_rf_setup_tx(uint8_t rf_chan, uint8_t mode);
+void ble_rf_setup_rx(uint8_t rf_chan, uint8_t mode);
+
+void ble_rf_set_tx_power(int dbm);
+int8_t ble_rf_get_rssi(void);
+
+#endif /* _BLE_RF_PRIV_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml
new file mode 100644
index 00000000..a82b62e5
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml
@@ -0,0 +1,29 @@
+# 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.
+#
+
+syscfg.defs:
+ BLE_PHY_RF_HP_MODE:
+ description: Enable high-performance RF mode.
+ value: 1
+
+ BLE_PHY_DEBUG_DSER:
+ description: Enable DSER output from PHY
+ value: 0
+
+syscfg.restrictions:
+ - BLE_LL_RFMGMT_ENABLE_TIME == 0 || BLE_LL_RFMGMT_ENABLE_TIME >= 20
diff --git a/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c
index 5eb1eb95..8aa29d32 100644
--- a/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c
+++ b/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c
@@ -20,6 +20,8 @@
#include
#include
#include
+#include
+#include
#include "syscfg/syscfg.h"
#include "os/os.h"
#include "nimble/ble.h"
@@ -32,6 +34,9 @@
/* We use this to keep track of which entries are set to valid addresses */
static uint8_t g_ble_hw_whitelist_mask;
+static ble_rng_isr_cb_t rng_cb;
+static bool rng_started;
+
/* Returns public device address or -1 if not present */
int
ble_hw_get_public_addr(ble_addr_t *addr)
@@ -143,7 +148,8 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb)
int
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
{
- return -1;
+ rng_cb = cb;
+ return 0;
}
/**
@@ -154,7 +160,15 @@ ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
int
ble_hw_rng_start(void)
{
- return -1;
+ rng_started = true;
+
+ if (rng_cb) {
+ while (rng_started) {
+ rng_cb(rand());
+ }
+ }
+
+ return 0;
}
/**
@@ -165,7 +179,8 @@ ble_hw_rng_start(void)
int
ble_hw_rng_stop(void)
{
- return -1;
+ rng_started = false;
+ return 0;
}
/**
@@ -176,7 +191,7 @@ ble_hw_rng_stop(void)
uint8_t
ble_hw_rng_read(void)
{
- return 0;
+ return rand();
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h
new file mode 100644
index 00000000..df6ef700
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h
@@ -0,0 +1,50 @@
+/*
+ * 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_XCVR_
+#define H_BLE_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XCVR_RX_RADIO_RAMPUP_USECS (40)
+#define XCVR_TX_RADIO_RAMPUP_USECS (40)
+
+/*
+ * NOTE: we have to account for the RTC output compare issue. We want it to be
+ * 5 ticks.
+ */
+#define XCVR_PROC_DELAY_USECS (153)
+#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS)
+#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS)
+#define XCVR_TX_SCHED_DELAY_USECS (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE (8)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_XCVR_ */
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml
new file mode 100644
index 00000000..3ff44212
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: nimble/drivers/nrf5340
+pkg.description: BLE driver for nRF5340 systems.
+pkg.author: "Apache Mynewt "
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+ - nimble
+ - nimble/controller
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c
new file mode 100644
index 00000000..bbe61697
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c
@@ -0,0 +1,475 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+/* Total number of resolving list elements */
+#define BLE_HW_RESOLV_LIST_SIZE (16)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Random number generator isr callback */
+static ble_rng_isr_cb_t ble_rng_isr_cb;
+
+/* If LL privacy is enabled, allocate memory for AAR */
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+
+/* The NRF5340 supports up to 16 IRK entries */
+#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
+#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+#else
+#define NRF_IRK_LIST_ENTRIES (16)
+#endif
+
+/* NOTE: each entry is 16 bytes long. */
+uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
+
+/* Current number of IRK entries */
+uint8_t g_nrf_num_irks;
+
+#endif
+
+/* Returns public device address or -1 if not present */
+int
+ble_hw_get_public_addr(ble_addr_t *addr)
+{
+ uint32_t addr_high;
+ uint32_t addr_low;
+
+ /* Does FICR have a public address */
+ if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) != 0) {
+ return -1;
+ }
+
+ /* Copy into device address. We can do this because we know platform */
+ addr_low = NRF_FICR_NS->DEVICEADDR[0];
+ addr_high = NRF_FICR_NS->DEVICEADDR[1];
+ memcpy(addr->val, &addr_low, 4);
+ memcpy(&addr->val[4], &addr_high, 2);
+ addr->type = BLE_ADDR_PUBLIC;
+
+ return 0;
+}
+
+/* Returns random static address or -1 if not present */
+int
+ble_hw_get_static_addr(ble_addr_t *addr)
+{
+ int rc;
+
+ if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) == 1) {
+ memcpy(addr->val, (void *)&NRF_FICR_NS->DEVICEADDR[0], 4);
+ memcpy(&addr->val[4], (void *)&NRF_FICR_NS->DEVICEADDR[1], 2);
+ addr->val[5] |= 0xc0;
+ addr->type = BLE_ADDR_RANDOM;
+ rc = 0;
+ } else {
+ rc = -1;
+ }
+
+ return rc;
+}
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+ NRF_RADIO_NS->DACNF = 0;
+ g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
+{
+ int i;
+ uint32_t mask;
+
+ /* Find first ununsed device address match element */
+ mask = 0x01;
+ for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+ if ((mask & g_ble_hw_whitelist_mask) == 0) {
+ NRF_RADIO_NS->DAB[i] = get_le32(addr);
+ NRF_RADIO_NS->DAP[i] = get_le16(addr + 4);
+ if (addr_type == BLE_ADDR_RANDOM) {
+ NRF_RADIO_NS->DACNF |= (mask << 8);
+ }
+ g_ble_hw_whitelist_mask |= mask;
+ return BLE_ERR_SUCCESS;
+ }
+ mask <<= 1;
+ }
+
+ return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
+{
+ int i;
+ uint16_t dap;
+ uint16_t txadd;
+ uint32_t dab;
+ uint32_t mask;
+
+ /* Find first ununsed device address match element */
+ dab = get_le32(addr);
+ dap = get_le16(addr + 4);
+ txadd = NRF_RADIO_NS->DACNF >> 8;
+ mask = 0x01;
+ for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+ if (mask & g_ble_hw_whitelist_mask) {
+ if ((dab == NRF_RADIO_NS->DAB[i]) && (dap == NRF_RADIO_NS->DAP[i])) {
+ if (addr_type == !!(txadd & mask)) {
+ break;
+ }
+ }
+ }
+ mask <<= 1;
+ }
+
+ if (i < BLE_HW_WHITE_LIST_SIZE) {
+ g_ble_hw_whitelist_mask &= ~mask;
+ NRF_RADIO_NS->DACNF &= ~mask;
+ }
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+ return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+ /* Enable the configured device addresses */
+ NRF_RADIO_NS->DACNF |= g_ble_hw_whitelist_mask;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+ /* Disable all whitelist devices */
+ NRF_RADIO_NS->DACNF &= 0x0000ff00;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+ return NRF_RADIO_NS->EVENTS_DEVMATCH;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+ int rc;
+ uint32_t end;
+ uint32_t err;
+
+ /* Stop ECB */
+ NRF_ECB_NS->TASKS_STOPECB = 1;
+ /* XXX: does task stop clear these counters? Anyway to do this quicker? */
+ NRF_ECB_NS->EVENTS_ENDECB = 0;
+ NRF_ECB_NS->EVENTS_ERRORECB = 0;
+ NRF_ECB_NS->ECBDATAPTR = (uint32_t)ecb;
+
+ /* Start ECB */
+ NRF_ECB_NS->TASKS_STARTECB = 1;
+
+ /* Wait till error or done */
+ rc = 0;
+ while (1) {
+ end = NRF_ECB_NS->EVENTS_ENDECB;
+ err = NRF_ECB_NS->EVENTS_ERRORECB;
+ if (end || err) {
+ if (err) {
+ rc = -1;
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Random number generator ISR.
+ */
+static void
+ble_rng_isr(void)
+{
+ uint8_t rnum;
+
+ os_trace_isr_enter();
+
+ /* No callback? Clear and disable interrupts */
+ if (ble_rng_isr_cb == NULL) {
+ NRF_RNG_NS->INTENCLR = 1;
+ NRF_RNG_NS->EVENTS_VALRDY = 0;
+ (void)NRF_RNG_NS->SHORTS;
+ os_trace_isr_exit();
+ return;
+ }
+
+ /* If there is a value ready grab it */
+ if (NRF_RNG_NS->EVENTS_VALRDY) {
+ NRF_RNG_NS->EVENTS_VALRDY = 0;
+ rnum = (uint8_t)NRF_RNG_NS->VALUE;
+ (*ble_rng_isr_cb)(rnum);
+ }
+
+ os_trace_isr_exit();
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+ /* Set bias */
+ if (bias) {
+ NRF_RNG_NS->CONFIG = 1;
+ } else {
+ NRF_RNG_NS->CONFIG = 0;
+ }
+
+ /* If we were passed a function pointer we need to enable the interrupt */
+ if (cb != NULL) {
+#ifndef RIOT_VERSION
+ NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+#endif
+#if MYNEWT
+ NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
+#else
+ ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr);
+#endif
+ NVIC_EnableIRQ(RNG_IRQn);
+ ble_rng_isr_cb = cb;
+ }
+
+ return 0;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+ os_sr_t sr;
+
+ /* No need for interrupt if there is no callback */
+ OS_ENTER_CRITICAL(sr);
+ NRF_RNG_NS->EVENTS_VALRDY = 0;
+ if (ble_rng_isr_cb) {
+ NRF_RNG_NS->INTENSET = 1;
+ }
+ NRF_RNG_NS->TASKS_START = 1;
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+ os_sr_t sr;
+
+ /* No need for interrupt if there is no callback */
+ OS_ENTER_CRITICAL(sr);
+ NRF_RNG_NS->INTENCLR = 1;
+ NRF_RNG_NS->TASKS_STOP = 1;
+ NRF_RNG_NS->EVENTS_VALRDY = 0;
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+ uint8_t rnum;
+
+ /* Wait for a sample */
+ while (NRF_RNG_NS->EVENTS_VALRDY == 0) {
+ }
+
+ NRF_RNG_NS->EVENTS_VALRDY = 0;
+ rnum = (uint8_t)NRF_RNG_NS->VALUE;
+
+ return rnum;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+ g_nrf_num_irks = 0;
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+ uint32_t *nrf_entry;
+
+ /* Find first ununsed device address match element */
+ if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ /* Copy into irk list */
+ nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
+ memcpy(nrf_entry, irk, 16);
+
+ /* Add to total */
+ ++g_nrf_num_irks;
+ return BLE_ERR_SUCCESS;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+ uint32_t *irk_entry;
+
+ if (index < g_nrf_num_irks) {
+ --g_nrf_num_irks;
+ irk_entry = &g_nrf_irk_list[index];
+ if (g_nrf_num_irks > index) {
+ memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index));
+ }
+ }
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+ return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int Negative values indicate unresolved address; positive values
+ * indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+ uint32_t index;
+
+ if (NRF_AAR_NS->EVENTS_END) {
+ if (NRF_AAR_NS->EVENTS_RESOLVED) {
+ index = NRF_AAR_NS->STATUS;
+ return (int)index;
+ }
+ }
+
+ return -1;
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c
new file mode 100644
index 00000000..e07bbaa1
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c
@@ -0,0 +1,1820 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * NOTE: This code uses 0-5 DPPI channels so care should be taken when using
+ * DPPI somewhere else.
+ * TODO maybe we could reduce number of used channels if we reuse same channel
+ * for mutually exclusive events but for now make it simpler to debug.
+ */
+
+#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0
+#define DPPI_CH_TIMER0_EVENTS_COMPARE_3 1
+#define DPPI_CH_RADIO_EVENTS_END 2
+#define DPPI_CH_RADIO_EVENTS_BCMATCH 3
+#define DPPI_CH_RADIO_EVENTS_ADDRESS 4
+#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5
+
+#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | DPPIC_CHEN_CH2_Msk | \
+ DPPIC_CHEN_CH3_Msk | DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk)
+
+#define DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_0 ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << TIMER_PUBLISH_COMPARE_CHIDX_Pos) | \
+ (TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos))
+#define DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_3 ((DPPI_CH_TIMER0_EVENTS_COMPARE_3 << TIMER_PUBLISH_COMPARE_CHIDX_Pos) | \
+ (TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos))
+#define DPPI_PUBLISH_RADIO_EVENTS_END ((DPPI_CH_RADIO_EVENTS_END << RADIO_PUBLISH_END_CHIDX_Pos) | \
+ (RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos))
+#define DPPI_PUBLISH_RADIO_EVENTS_BCMATCH ((DPPI_CH_RADIO_EVENTS_BCMATCH << RADIO_PUBLISH_BCMATCH_CHIDX_Pos) | \
+ (RADIO_PUBLISH_BCMATCH_EN_Enabled << RADIO_PUBLISH_BCMATCH_EN_Pos))
+#define DPPI_PUBLISH_RADIO_EVENTS_ADDRESS ((DPPI_CH_RADIO_EVENTS_ADDRESS << RADIO_PUBLISH_ADDRESS_CHIDX_Pos) | \
+ (RADIO_PUBLISH_ADDRESS_EN_Enabled << RADIO_PUBLISH_ADDRESS_EN_Pos))
+#define DPPI_PUBLISH_RTC0_EVENTS_COMPARE_0 ((DPPI_CH_RTC0_EVENTS_COMPARE_0 << RTC_PUBLISH_COMPARE_CHIDX_Pos) | \
+ (RTC_PUBLISH_COMPARE_EN_Enabled << RTC_PUBLISH_COMPARE_EN_Pos))
+
+#define DPPI_SUBSCRIBE_TIMER0_TASKS_START(_enable) ((DPPI_CH_RTC0_EVENTS_COMPARE_0 << TIMER_SUBSCRIBE_START_CHIDX_Pos) | \
+ ((_enable) << TIMER_SUBSCRIBE_START_EN_Pos))
+#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE1(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \
+ ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos))
+#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE2(_enable) ((DPPI_CH_RADIO_EVENTS_END << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \
+ ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos))
+#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \
+ ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos))
+#define DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_3 << RADIO_SUBSCRIBE_DISABLE_CHIDX_Pos) | \
+ ((_enable) << RADIO_SUBSCRIBE_DISABLE_EN_Pos))
+#define DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << RADIO_SUBSCRIBE_RXEN_CHIDX_Pos) | \
+ ((_enable) << RADIO_SUBSCRIBE_RXEN_EN_Pos))
+#define DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << RADIO_SUBSCRIBE_TXEN_CHIDX_Pos) | \
+ ((_enable) << RADIO_SUBSCRIBE_TXEN_EN_Pos))
+#define DPPI_SUBSCRIBE_AAR_TASKS_START(_enable) ((DPPI_CH_RADIO_EVENTS_BCMATCH << AAR_SUBSCRIBE_START_CHIDX_Pos) | \
+ ((_enable) << AAR_SUBSCRIBE_START_EN_Pos))
+#define DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << CCM_SUBSCRIBE_CRYPT_CHIDX_Pos) | \
+ ((_enable) << CCM_SUBSCRIBE_CRYPT_EN_Pos))
+
+extern uint8_t g_nrf_num_irks;
+extern uint32_t g_nrf_irk_list[];
+
+/* To disable all radio interrupts */
+#define NRF_RADIO_IRQ_MASK_ALL (0x34FF)
+
+/*
+ * We configure the nrf with a 1 byte S0 field, 8 bit length field, and
+ * zero bit S1 field. The preamble is 8 bits long.
+ */
+#define NRF_LFLEN_BITS (8)
+#define NRF_S0LEN (1)
+#define NRF_S1LEN_BITS (0)
+#define NRF_CILEN_BITS (2)
+#define NRF_TERMLEN_BITS (3)
+
+/* Maximum length of frames */
+#define NRF_MAXLEN (255)
+#define NRF_BALEN (3) /* For base address of 3 bytes */
+
+/* NRF_RADIO_NS->PCNF0 configuration values */
+#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \
+ (RADIO_PCNF0_S1INCL_Msk) | \
+ (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \
+ (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos)
+#define NRF_PCNF0_1M (NRF_PCNF0) | \
+ (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos)
+#define NRF_PCNF0_2M (NRF_PCNF0) | \
+ (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos)
+#define NRF_PCNF0_CODED (NRF_PCNF0) | \
+ (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \
+ (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \
+ (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos)
+
+/* BLE PHY data structure */
+struct ble_phy_obj {
+ uint8_t phy_stats_initialized;
+ int8_t phy_txpwr_dbm;
+ uint8_t phy_chan;
+ uint8_t phy_state;
+ uint8_t phy_transition;
+ uint8_t phy_transition_late;
+ uint8_t phy_rx_started;
+ uint8_t phy_encrypted;
+ uint8_t phy_privacy;
+ uint8_t phy_tx_pyld_len;
+ uint8_t phy_cur_phy_mode;
+ uint8_t phy_tx_phy_mode;
+ uint8_t phy_rx_phy_mode;
+ uint8_t phy_bcc_offset;
+ int8_t rx_pwr_compensation;
+ uint32_t phy_aar_scratch;
+ uint32_t phy_access_address;
+ struct ble_mbuf_hdr rxhdr;
+ void *txend_arg;
+ ble_phy_tx_end_func txend_cb;
+ uint32_t phy_start_cputime;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* XXX: if 27 byte packets desired we can make this smaller */
+/* Global transmit/receive buffer */
+static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+/* Make sure word-aligned for faster copies */
+static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+#endif
+
+/* RF center frequency for each channel index (offset from 2400 MHz) */
+static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = {
+ 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */
+ 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */
+ 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */
+ 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */
+};
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/* packet start offsets (in usecs) */
+static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = {
+ [BLE_PHY_MODE_1M] = 40,
+ [BLE_PHY_MODE_2M] = 24,
+ [BLE_PHY_MODE_CODED_125KBPS] = 376,
+ [BLE_PHY_MODE_CODED_500KBPS] = 376
+};
+#endif
+
+/* Various radio timings */
+/* Radio ramp-up times in usecs (fast mode) */
+#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS)
+#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS)
+
+/* delay between EVENTS_READY and start of tx */
+static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = {
+ [BLE_PHY_MODE_1M] = 4,
+ [BLE_PHY_MODE_2M] = 3,
+ [BLE_PHY_MODE_CODED_125KBPS] = 5,
+ [BLE_PHY_MODE_CODED_500KBPS] = 5
+};
+/* delay between EVENTS_END and end of txd packet */
+static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = {
+ [BLE_PHY_MODE_1M] = 4,
+ [BLE_PHY_MODE_2M] = 3,
+ [BLE_PHY_MODE_CODED_125KBPS] = 9,
+ [BLE_PHY_MODE_CODED_500KBPS] = 3
+};
+/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */
+static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = {
+ [BLE_PHY_MODE_1M] = 6,
+ [BLE_PHY_MODE_2M] = 2,
+ [BLE_PHY_MODE_CODED_125KBPS] = 17,
+ [BLE_PHY_MODE_CODED_500KBPS] = 17
+};
+/* delay between end of rxd packet and EVENTS_END */
+static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = {
+ [BLE_PHY_MODE_1M] = 6,
+ [BLE_PHY_MODE_2M] = 2,
+ [BLE_PHY_MODE_CODED_125KBPS] = 27,
+ [BLE_PHY_MODE_CODED_500KBPS] = 22
+};
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+STATS_SECT_ENTRY(phy_isrs)
+STATS_SECT_ENTRY(tx_good)
+STATS_SECT_ENTRY(tx_fail)
+STATS_SECT_ENTRY(tx_late)
+STATS_SECT_ENTRY(tx_bytes)
+STATS_SECT_ENTRY(rx_starts)
+STATS_SECT_ENTRY(rx_aborts)
+STATS_SECT_ENTRY(rx_valid)
+STATS_SECT_ENTRY(rx_crc_err)
+STATS_SECT_ENTRY(rx_late)
+STATS_SECT_ENTRY(radio_state_errs)
+STATS_SECT_ENTRY(rx_hw_err)
+STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+STATS_NAME(ble_phy_stats, phy_isrs)
+STATS_NAME(ble_phy_stats, tx_good)
+STATS_NAME(ble_phy_stats, tx_fail)
+STATS_NAME(ble_phy_stats, tx_late)
+STATS_NAME(ble_phy_stats, tx_bytes)
+STATS_NAME(ble_phy_stats, rx_starts)
+STATS_NAME(ble_phy_stats, rx_aborts)
+STATS_NAME(ble_phy_stats, rx_valid)
+STATS_NAME(ble_phy_stats, rx_crc_err)
+STATS_NAME(ble_phy_stats, rx_late)
+STATS_NAME(ble_phy_stats, radio_state_errs)
+STATS_NAME(ble_phy_stats, rx_hw_err)
+STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+/*
+ * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE.
+ * However, when I used a smaller size it still overwrote the scratchpad. Until
+ * I figure this out I am just going to allocate 67 words so we have enough
+ * space for 267 bytes of scratch. I used 268 bytes since not sure if this
+ * needs to be aligned and burning a byte is no big deal.
+ *
+ *#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4)
+ */
+#define NRF_ENC_SCRATCH_WORDS (67)
+
+static uint32_t nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS];
+
+struct nrf_ccm_data {
+ uint8_t key[16];
+ uint64_t pkt_counter;
+ uint8_t dir_bit;
+ uint8_t iv[8];
+} __attribute__((packed));
+
+static struct nrf_ccm_data nrf_ccm_data;
+#endif
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+
+uint32_t
+ble_phy_mode_pdu_start_off(int phy_mode)
+{
+ return g_ble_phy_mode_pkt_start_off[phy_mode];
+}
+
+static void
+ble_phy_mode_apply(uint8_t phy_mode)
+{
+ if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) {
+ return;
+ }
+
+ switch (phy_mode) {
+ case BLE_PHY_MODE_1M:
+ NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+ NRF_RADIO_NS->PCNF0 = NRF_PCNF0_1M;
+ break;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+ case BLE_PHY_MODE_2M:
+ NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_2Mbit;
+ NRF_RADIO_NS->PCNF0 = NRF_PCNF0_2M;
+ break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ case BLE_PHY_MODE_CODED_125KBPS:
+ NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR125Kbit;
+ NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED;
+ break;
+ case BLE_PHY_MODE_CODED_500KBPS:
+ NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR500Kbit;
+ NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED;
+ break;
+#endif
+ default:
+ assert(0);
+ }
+
+ g_ble_phy_data.phy_cur_phy_mode = phy_mode;
+}
+#endif
+
+void
+ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode)
+{
+ g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode;
+ g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode;
+}
+
+int
+ble_phy_get_cur_phy(void)
+{
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ switch (g_ble_phy_data.phy_cur_phy_mode) {
+ case BLE_PHY_MODE_1M:
+ return BLE_PHY_1M;
+ case BLE_PHY_MODE_2M:
+ return BLE_PHY_2M;
+ case BLE_PHY_MODE_CODED_125KBPS:
+ case BLE_PHY_MODE_CODED_500KBPS:
+ return BLE_PHY_CODED;
+ default:
+ assert(0);
+ return -1;
+ }
+#else
+ return BLE_PHY_1M;
+#endif
+}
+
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+ uint32_t rem_len;
+ uint32_t copy_len;
+ uint32_t block_len;
+ uint32_t block_rem_len;
+ void *dst;
+ void *src;
+ struct os_mbuf * om;
+
+ /* Better be aligned */
+ assert(((uint32_t)dptr & 3) == 0);
+
+ block_len = rxpdu->om_omp->omp_databuf_len;
+ rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len;
+ src = dptr;
+
+ /*
+ * Setup for copying from first mbuf which is shorter due to packet header
+ * and extra leading space
+ */
+ copy_len = block_len - rxpdu->om_pkthdr_len - 4;
+ om = rxpdu;
+ dst = om->om_data;
+
+ while (true) {
+ /*
+ * Always copy blocks of length aligned to word size, only last mbuf
+ * will have remaining non-word size bytes appended.
+ */
+ block_rem_len = copy_len;
+ copy_len = min(copy_len, rem_len);
+ copy_len &= ~3;
+
+ dst = om->om_data;
+ om->om_len = copy_len;
+ rem_len -= copy_len;
+ block_rem_len -= copy_len;
+
+ __asm__ volatile (".syntax unified \n"
+ " mov r4, %[len] \n"
+ " b 2f \n"
+ "1: ldr r3, [%[src], %[len]] \n"
+ " str r3, [%[dst], %[len]] \n"
+ "2: subs %[len], #4 \n"
+ " bpl 1b \n"
+ " adds %[src], %[src], r4 \n"
+ " adds %[dst], %[dst], r4 \n"
+ : [dst] "+r" (dst), [src] "+r" (src),
+ [len] "+r" (copy_len)
+ :
+ : "r3", "r4", "memory"
+ );
+
+ if ((rem_len < 4) && (block_rem_len >= rem_len)) {
+ break;
+ }
+
+ /* Move to next mbuf */
+ om = SLIST_NEXT(om, om_next);
+ copy_len = block_len;
+ }
+
+ /* Copy remaining bytes, if any, to last mbuf */
+ om->om_len += rem_len;
+ __asm__ volatile (".syntax unified \n"
+ " b 2f \n"
+ "1: ldrb r3, [%[src], %[len]] \n"
+ " strb r3, [%[dst], %[len]] \n"
+ "2: subs %[len], #1 \n"
+ " bpl 1b \n"
+ : [len] "+r" (rem_len)
+ : [dst] "r" (dst), [src] "r" (src)
+ : "r3", "memory"
+ );
+
+ /* Copy header */
+ memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr,
+ sizeof(struct ble_mbuf_hdr));
+}
+
+/**
+ * Called when we want to wait if the radio is in either the rx or tx
+ * disable states. We want to wait until that state is over before doing
+ * anything to the radio
+ */
+static void
+nrf_wait_disabled(void)
+{
+ uint32_t state;
+
+ state = NRF_RADIO_NS->STATE;
+ if (state != RADIO_STATE_STATE_Disabled) {
+ if ((state == RADIO_STATE_STATE_RxDisable) ||
+ (state == RADIO_STATE_STATE_TxDisable)) {
+ /* This will end within a short time (6 usecs). Just poll */
+ while (NRF_RADIO_NS->STATE == state) {
+ /* If this fails, something is really wrong. Should last
+ * no more than 6 usecs
+ */
+ }
+ }
+ }
+}
+
+static int
+ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx)
+{
+ uint32_t next_cc;
+ uint32_t cur_cc;
+ uint32_t cntr;
+ uint32_t delta;
+
+ /*
+ * We need to adjust start time to include radio ramp-up and TX pipeline
+ * delay (the latter only if applicable, so only for TX).
+ *
+ * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on
+ * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate
+ * using TIMER0 with 1 usec precision.
+ */
+
+ cputime -= 2;
+ rem_usecs += 61;
+ if (tx) {
+ rem_usecs -= BLE_PHY_T_TXENFAST;
+ rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode];
+ } else {
+ rem_usecs -= BLE_PHY_T_RXENFAST;
+ }
+
+ /*
+ * rem_usecs will be no more than 2 ticks, but if it is more than single
+ * tick then we should better count one more low-power tick rather than
+ * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the
+ * compare won't occur.
+ */
+
+ if (rem_usecs > 30) {
+ cputime++;
+ rem_usecs -= 30;
+ }
+
+ /*
+ * Can we set the RTC compare to start TIMER0? We can do it if:
+ * a) Current compare value is not N+1 or N+2 ticks from current
+ * counter.
+ * b) The value we want to set is not at least N+2 from current
+ * counter.
+ *
+ * NOTE: since the counter can tick 1 while we do these calculations we
+ * need to account for it.
+ */
+ next_cc = cputime & 0xffffff;
+ cur_cc = NRF_RTC0_NS->CC[0];
+ cntr = NRF_RTC0_NS->COUNTER;
+
+ delta = (cur_cc - cntr) & 0xffffff;
+ if ((delta <= 3) && (delta != 0)) {
+ return -1;
+ }
+ delta = (next_cc - cntr) & 0xffffff;
+ if ((delta & 0x800000) || (delta < 3)) {
+ return -1;
+ }
+
+ /* Clear and set TIMER0 to fire off at proper time */
+ NRF_TIMER0_NS->TASKS_CLEAR = 1;
+ NRF_TIMER0_NS->CC[0] = rem_usecs;
+ NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0;
+
+ /* Set RTC compare to start TIMER0 */
+ NRF_RTC0_NS->EVENTS_COMPARE[0] = 0;
+ NRF_RTC0_NS->CC[0] = next_cc;
+ NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+ /* Enable PPI */
+ NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(1);
+
+ /* Store the cputime at which we set the RTC */
+ g_ble_phy_data.phy_start_cputime = cputime;
+
+ return 0;
+}
+
+static int
+ble_phy_set_start_now(void)
+{
+ os_sr_t sr;
+ uint32_t now;
+
+ OS_ENTER_CRITICAL(sr);
+
+ /*
+ * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not
+ * occur in such case.
+ */
+ NRF_TIMER0_NS->TASKS_CLEAR = 1;
+ NRF_TIMER0_NS->CC[0] = 1;
+ NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0;
+
+ /*
+ * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks
+ * from current value to guarantee triggering compare event, but let's set
+ * it to N+3 to account for possible extra tick on RTC0 during these
+ * operations.
+ */
+ now = os_cputime_get32();
+ NRF_RTC0_NS->EVENTS_COMPARE[0] = 0;
+ NRF_RTC0_NS->CC[0] = now + 3;
+ NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+ /* Enable PPI */
+ NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(1);
+
+ /*
+ * Store the cputime at which we set the RTC
+ *
+ * XXX Compare event may be triggered on previous CC value (if it was set to
+ * less than N+2) so in rare cases actual start time may be 2 ticks earlier
+ * than what we expect. Since this is only used on RX, it may cause AUX scan
+ * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable
+ * for now.
+ */
+ g_ble_phy_data.phy_start_cputime = now + 3;
+
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+}
+
+void
+ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
+{
+ uint32_t end_time;
+ uint8_t phy;
+
+ phy = g_ble_phy_data.phy_cur_phy_mode;
+
+ if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+ /* RX shall start exactly T_IFS after TX end captured in CC[2] */
+ end_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS;
+ /* Adjust for delay between EVENT_END and actual TX end time */
+ end_time += g_ble_phy_t_txenddelay[tx_phy_mode];
+ /* Wait a bit longer due to allowed active clock accuracy */
+ end_time += 2;
+ /*
+ * It's possible that we'll capture PDU start time at the end of timer
+ * cycle and since wfr expires at the beginning of calculated timer
+ * cycle it can be almost 1 usec too early. Let's compensate for this
+ * by waiting 1 usec more.
+ */
+ end_time += 1;
+ } else {
+ /*
+ * RX shall start no later than wfr_usecs after RX enabled.
+ * CC[0] is the time of RXEN so adjust for radio ram-up.
+ * Do not add jitter since this is already covered by LL.
+ */
+ end_time = NRF_TIMER0_NS->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs;
+ }
+
+ /*
+ * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so
+ * we are actually calculating relative to start of packet payload
+ * which is fine.
+ */
+
+ /* Adjust for receiving access address since this triggers EVENT_ADDRESS */
+ end_time += ble_phy_mode_pdu_start_off(phy);
+ /* Adjust for delay between actual access address RX and EVENT_ADDRESS */
+ end_time += g_ble_phy_t_rxaddrdelay[phy];
+
+ /* wfr_secs is the time from rxen until timeout */
+ NRF_TIMER0_NS->CC[3] = end_time;
+ NRF_TIMER0_NS->EVENTS_COMPARE[3] = 0;
+
+ /* Subscribe for wait for response events */
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(1);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(1);
+
+ /* Enable the disabled interrupt so we time out on events compare */
+ NRF_RADIO_NS->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+
+ /*
+ * It may happen that if CPU is halted for a brief moment (e.g. during flash
+ * erase or write), TIMER0 already counted past CC[3] and thus wfr will not
+ * fire as expected. In case this happened, let's just disable PPIs for wfr
+ * and trigger wfr manually (i.e. disable radio).
+ *
+ * Note that the same applies to RX start time set in CC[0] but since it
+ * should fire earlier than wfr, fixing wfr is enough.
+ *
+ * CC[1] is only used as a reference on RX start, we do not need it here so
+ * it can be used to read TIMER0 counter.
+ */
+ NRF_TIMER0_NS->TASKS_CAPTURE[1] = 1;
+ if (NRF_TIMER0_NS->CC[1] > NRF_TIMER0_NS->CC[3]) {
+ /* Unsubscribe from wfr events */
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0);
+
+ NRF_RADIO_NS->TASKS_DISABLE = 1;
+ }
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+static uint32_t
+ble_phy_get_ccm_datarate(void)
+{
+#if BLE_LL_BT5_PHY_SUPPORTED
+ switch (g_ble_phy_data.phy_cur_phy_mode) {
+ case BLE_PHY_MODE_1M:
+ return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos;
+ case BLE_PHY_MODE_2M:
+ return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ case BLE_PHY_MODE_CODED_125KBPS:
+ return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos;
+ case BLE_PHY_MODE_CODED_500KBPS:
+ return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos;
+#endif
+ }
+
+ assert(0);
+ return 0;
+#else
+ return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos;
+#endif
+}
+#endif
+
+/**
+ * Setup transceiver for receive.
+ */
+static void
+ble_phy_rx_xcvr_setup(void)
+{
+ uint8_t *dptr;
+
+ dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+ dptr += 3;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ NRF_RADIO_NS->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+ NRF_CCM_NS->INPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+ NRF_CCM_NS->OUTPTR = (uint32_t)dptr;
+ NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0];
+ NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption |
+ ble_phy_get_ccm_datarate();
+ NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data;
+ NRF_CCM_NS->SHORTS = 0;
+ NRF_CCM_NS->EVENTS_ERROR = 0;
+ NRF_CCM_NS->EVENTS_ENDCRYPT = 0;
+ NRF_CCM_NS->TASKS_KSGEN = 1;
+
+ /* Subscribe to radio address event */
+ NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(1);
+ } else {
+ NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr;
+ }
+#else
+ NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr;
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ if (g_ble_phy_data.phy_privacy) {
+ NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Enabled;
+ NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+ NRF_AAR_NS->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch;
+ NRF_AAR_NS->EVENTS_END = 0;
+ NRF_AAR_NS->EVENTS_RESOLVED = 0;
+ NRF_AAR_NS->EVENTS_NOTRESOLVED = 0;
+ } else {
+ if (g_ble_phy_data.phy_encrypted == 0) {
+ NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+ }
+ }
+#endif
+
+ /* Turn off trigger TXEN on output compare match and AAR on bcmatch */
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0);
+ NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0);
+
+ /* Reset the rx started flag. Used for the wait for response */
+ g_ble_phy_data.phy_rx_started = 0;
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+#if BLE_LL_BT5_PHY_SUPPORTED
+ /*
+ * On Coded PHY there are CI and TERM1 fields before PDU starts so we need
+ * to take this into account when setting up BCC.
+ */
+ if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS ||
+ g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) {
+ g_ble_phy_data.phy_bcc_offset = 5;
+ } else {
+ g_ble_phy_data.phy_bcc_offset = 0;
+ }
+#else
+ g_ble_phy_data.phy_bcc_offset = 0;
+#endif
+
+ /* I want to know when 1st byte received (after address) */
+ NRF_RADIO_NS->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */
+ NRF_RADIO_NS->EVENTS_ADDRESS = 0;
+ NRF_RADIO_NS->EVENTS_DEVMATCH = 0;
+ NRF_RADIO_NS->EVENTS_BCMATCH = 0;
+ NRF_RADIO_NS->EVENTS_RSSIEND = 0;
+ NRF_RADIO_NS->EVENTS_CRCOK = 0;
+ NRF_RADIO_NS->SHORTS = RADIO_SHORTS_END_DISABLE_Msk |
+ RADIO_SHORTS_READY_START_Msk |
+ RADIO_SHORTS_ADDRESS_BCSTART_Msk |
+ RADIO_SHORTS_ADDRESS_RSSISTART_Msk |
+ RADIO_SHORTS_DISABLED_RSSISTOP_Msk;
+
+ NRF_RADIO_NS->INTENSET = RADIO_INTENSET_ADDRESS_Msk;
+}
+
+/**
+ * Called from interrupt context when the transmit ends
+ *
+ */
+static void
+ble_phy_tx_end_isr(void)
+{
+ uint8_t tx_phy_mode;
+ uint8_t was_encrypted;
+ uint8_t transition;
+ uint32_t rx_time;
+ uint32_t wfr_time;
+
+ /* Store PHY on which we've just transmitted smth */
+ tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode;
+
+ /* If this transmission was encrypted we need to remember it */
+ was_encrypted = g_ble_phy_data.phy_encrypted;
+ (void)was_encrypted;
+
+ /* Better be in TX state! */
+ assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+
+ /* Clear events and clear interrupt on disabled event */
+ NRF_RADIO_NS->EVENTS_DISABLED = 0;
+ NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
+ NRF_RADIO_NS->EVENTS_END = 0;
+ wfr_time = NRF_RADIO_NS->SHORTS;
+ (void)wfr_time;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ /*
+ * XXX: not sure what to do. We had a HW error during transmission.
+ * For now I just count a stat but continue on like all is good.
+ */
+ if (was_encrypted) {
+ if (NRF_CCM_NS->EVENTS_ERROR) {
+ STATS_INC(ble_phy_stats, tx_hw_err);
+ NRF_CCM_NS->EVENTS_ERROR = 0;
+ }
+ }
+#endif
+
+ /* Call transmit end callback */
+ if (g_ble_phy_data.txend_cb) {
+ g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg);
+ }
+
+ transition = g_ble_phy_data.phy_transition;
+ if (transition == BLE_PHY_TRANSITION_TX_RX) {
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode);
+#endif
+
+ /* Packet pointer needs to be reset. */
+ ble_phy_rx_xcvr_setup();
+
+ ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0);
+
+ /* Schedule RX exactly T_IFS after TX end captured in CC[2] */
+ rx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS;
+ /* Adjust for delay between EVENT_END and actual TX end time */
+ rx_time += g_ble_phy_t_txenddelay[tx_phy_mode];
+ /* Adjust for radio ramp-up */
+ rx_time -= BLE_PHY_T_RXENFAST;
+ /* Start listening a bit earlier due to allowed active clock accuracy */
+ rx_time -= 2;
+
+ NRF_TIMER0_NS->CC[0] = rx_time;
+ NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0;
+
+ /* Start radio on timer */
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1);
+
+ } else {
+ NRF_TIMER0_NS->TASKS_STOP = 1;
+ NRF_TIMER0_NS->TASKS_SHUTDOWN = 1;
+
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0);
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0);
+ NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(0);
+
+ assert(transition == BLE_PHY_TRANSITION_NONE);
+ }
+}
+
+static inline uint8_t
+ble_phy_get_cur_rx_phy_mode(void)
+{
+ uint8_t phy;
+
+ phy = g_ble_phy_data.phy_cur_phy_mode;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ /*
+ * For Coded PHY mode can be set to either codings since actual coding is
+ * set in packet header. However, here we need actual coding of received
+ * packet as this determines pipeline delays so need to figure this out
+ * using CI field.
+ */
+ if ((phy == BLE_PHY_MODE_CODED_125KBPS) ||
+ (phy == BLE_PHY_MODE_CODED_500KBPS)) {
+ phy = NRF_RADIO_NS->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ?
+ BLE_PHY_MODE_CODED_500KBPS : BLE_PHY_MODE_CODED_125KBPS;
+ }
+#endif
+
+ return phy;
+}
+
+static void
+ble_phy_rx_end_isr(void)
+{
+ int rc;
+ uint8_t *dptr;
+ uint8_t crcok;
+ uint32_t tx_time;
+ struct ble_mbuf_hdr *ble_hdr;
+
+ /* Clear events and clear interrupt */
+ NRF_RADIO_NS->EVENTS_END = 0;
+ NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_END_Msk;
+
+ /* Disable automatic RXEN */
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0);
+
+ /* Set RSSI and CRC status flag in header */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ assert(NRF_RADIO_NS->EVENTS_RSSIEND != 0);
+ ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO_NS->RSSISAMPLE) +
+ g_ble_phy_data.rx_pwr_compensation;
+
+ dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+ dptr += 3;
+
+ /* Count PHY crc errors and valid packets */
+ crcok = NRF_RADIO_NS->EVENTS_CRCOK;
+ if (!crcok) {
+ STATS_INC(ble_phy_stats, rx_crc_err);
+ } else {
+ STATS_INC(ble_phy_stats, rx_valid);
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ /* Only set MIC failure flag if frame is not zero length */
+ if ((dptr[1] != 0) && (NRF_CCM_NS->MICSTATUS == 0)) {
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
+ }
+
+ /*
+ * XXX: not sure how to deal with this. This should not
+ * be a MIC failure but we should not hand it up. I guess
+ * this is just some form of rx error and that is how we
+ * handle it? For now, just set CRC error flags
+ */
+ if (NRF_CCM_NS->EVENTS_ERROR) {
+ STATS_INC(ble_phy_stats, rx_hw_err);
+ ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+ }
+
+ /*
+ * XXX: This is a total hack work-around for now but I dont
+ * know what else to do. If ENDCRYPT is not set and we are
+ * encrypted we need to not trust this frame and drop it.
+ */
+ if (NRF_CCM_NS->EVENTS_ENDCRYPT == 0) {
+ STATS_INC(ble_phy_stats, rx_hw_err);
+ ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+ }
+ }
+#endif
+ }
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode);
+#endif
+
+ /*
+ * Let's schedule TX now and we will just cancel it after processing RXed
+ * packet if we don't need TX.
+ *
+ * We need this to initiate connection in case AUX_CONNECT_REQ was sent on
+ * LE Coded S8. In this case the time we process RXed packet is roughly the
+ * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI
+ * armed) so we may simply miss the slot and set the timer in the past.
+ *
+ * When TX is scheduled in advance, we may event process packet a bit longer
+ * during radio ramp-up - this gives us extra 40 usecs which is more than
+ * enough.
+ */
+
+ /* Schedule TX exactly T_IFS after RX end captured in CC[2] */
+ tx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS;
+ /* Adjust for delay between actual RX end time and EVENT_END */
+ tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode];
+ /* Adjust for radio ramp-up */
+ tx_time -= BLE_PHY_T_TXENFAST;
+ /* Adjust for delay between EVENT_READY and actual TX start time */
+ tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode];
+
+ NRF_TIMER0_NS->CC[0] = tx_time;
+ NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0;
+
+ /* Enable automatic TX */
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(1);
+
+ /*
+ * XXX: Hack warning!
+ *
+ * It may happen (during flash erase) that CPU is stopped for a moment and
+ * TIMER0 already counted past CC[0]. In such case we will be stuck waiting
+ * for TX to start since EVENTS_COMPARE[0] will not happen any time soon.
+ * For now let's set a flag denoting that we are late in RX-TX transition so
+ * ble_phy_tx() will fail - this allows everything to cleanup nicely without
+ * the need for extra handling in many places.
+ *
+ * Note: CC[3] is used only for wfr which we do not need here.
+ */
+ NRF_TIMER0_NS->TASKS_CAPTURE[3] = 1;
+ if (NRF_TIMER0_NS->CC[3] > NRF_TIMER0_NS->CC[0]) {
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0);
+
+ g_ble_phy_data.phy_transition_late = 1;
+ }
+
+ /*
+ * XXX: This is a horrible ugly hack to deal with the RAM S1 byte
+ * that is not sent over the air but is present here. Simply move the
+ * data pointer to deal with it. Fix this later.
+ */
+ dptr[2] = dptr[1];
+ dptr[1] = dptr[0];
+ rc = ble_ll_rx_end(dptr + 1, ble_hdr);
+ if (rc < 0) {
+ ble_phy_disable();
+ }
+}
+
+static bool
+ble_phy_rx_start_isr(void)
+{
+ int rc;
+ uint32_t state;
+ uint32_t usecs;
+ uint32_t pdu_usecs;
+ uint32_t ticks;
+ struct ble_mbuf_hdr *ble_hdr;
+ uint8_t *dptr;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ int adva_offset;
+#endif
+
+ dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+
+ /* Clear events and clear interrupt */
+ NRF_RADIO_NS->EVENTS_ADDRESS = 0;
+
+ /* Clear wfr timer channels and DISABLED interrupt */
+ NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk;
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0);
+
+ /* Initialize the ble mbuf header */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ ble_hdr->rxinfo.flags = ble_ll_state_get();
+ ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+ ble_hdr->rxinfo.handle = 0;
+ ble_hdr->rxinfo.phy = ble_phy_get_cur_phy();
+ ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode();
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+ ble_hdr->rxinfo.user_data = NULL;
+#endif
+
+ /*
+ * Calculate accurate packets start time (with remainder)
+ *
+ * We may start receiving packet somewhere during preamble in which case
+ * it is possible that actual transmission started before TIMER0 was
+ * running - need to take this into account.
+ */
+ ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime;
+
+ usecs = NRF_TIMER0_NS->CC[1];
+ pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) +
+ g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode];
+ if (usecs < pdu_usecs) {
+ g_ble_phy_data.phy_start_cputime--;
+ usecs += 30;
+ }
+ usecs -= pdu_usecs;
+
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ usecs -= os_cputime_ticks_to_usecs(ticks);
+ if (usecs == 31) {
+ usecs = 0;
+ ++ticks;
+ }
+
+ ble_hdr->beg_cputime += ticks;
+ ble_hdr->rem_usecs = usecs;
+
+ /* Wait to get 1st byte of frame */
+ while (1) {
+ state = NRF_RADIO_NS->STATE;
+ if (NRF_RADIO_NS->EVENTS_BCMATCH != 0) {
+ break;
+ }
+
+ /*
+ * If state is disabled, we should have the BCMATCH. If not,
+ * something is wrong!
+ */
+ if (state == RADIO_STATE_STATE_Disabled) {
+ NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+ NRF_RADIO_NS->SHORTS = 0;
+ return false;
+ }
+ }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ /*
+ * If privacy is enabled and received PDU has TxAdd bit set (i.e. random
+ * address) we try to resolve address using AAR.
+ */
+ if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) {
+ /*
+ * AdvA is located at 4th octet in RX buffer (after S0, length an S1
+ * fields). In case of extended advertising PDU we need to add 2 more
+ * octets for extended header.
+ */
+ adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0;
+ NRF_AAR_NS->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset);
+
+ /* Trigger AAR after last bit of AdvA is received */
+ NRF_RADIO_NS->EVENTS_BCMATCH = 0;
+ NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(1);
+ NRF_RADIO_NS->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 +
+ g_ble_phy_data.phy_bcc_offset;
+ }
+#endif
+
+ /* Call Link Layer receive start function */
+ rc = ble_ll_rx_start(dptr + 3,
+ g_ble_phy_data.phy_chan,
+ &g_ble_phy_data.rxhdr);
+ if (rc >= 0) {
+ /* Set rx started flag and enable rx end ISR */
+ g_ble_phy_data.phy_rx_started = 1;
+ NRF_RADIO_NS->INTENSET = RADIO_INTENSET_END_Msk;
+ } else {
+ /* Disable PHY */
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, rx_aborts);
+ }
+
+ /* Count rx starts */
+ STATS_INC(ble_phy_stats, rx_starts);
+
+ return true;
+}
+
+static void
+ble_phy_isr(void)
+{
+ uint32_t irq_en;
+
+ os_trace_isr_enter();
+
+ /* Read irq register to determine which interrupts are enabled */
+ irq_en = NRF_RADIO_NS->INTENCLR;
+
+ /*
+ * NOTE: order of checking is important! Possible, if things get delayed,
+ * we have both an ADDRESS and DISABLED interrupt in rx state. If we get
+ * an address, we disable the DISABLED interrupt.
+ */
+
+ /* We get this if we have started to receive a frame */
+ if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO_NS->EVENTS_ADDRESS) {
+ /*
+ * wfr timer is calculated to expire at the exact time we should start
+ * receiving a packet (with 1 usec precision) so it is possible it will
+ * fire at the same time as EVENT_ADDRESS. If this happens, radio will
+ * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte
+ * of payload is received and ble_phy_rx_start_isr() will fail. In this
+ * case we should not clear DISABLED irq mask so it will be handled as
+ * regular radio disabled event below. In other case radio was disabled
+ * on purpose and there's nothing more to handle so we can clear mask.
+ */
+ if (ble_phy_rx_start_isr()) {
+ irq_en &= ~RADIO_INTENCLR_DISABLED_Msk;
+ }
+ }
+
+ /* Check for disabled event. This only happens for transmits now */
+ if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO_NS->EVENTS_DISABLED) {
+ if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) {
+ NRF_RADIO_NS->EVENTS_DISABLED = 0;
+ ble_ll_wfr_timer_exp(NULL);
+ } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) {
+ assert(0);
+ } else {
+ ble_phy_tx_end_isr();
+ }
+ }
+
+ /* Receive packet end (we dont enable this for transmit) */
+ if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO_NS->EVENTS_END) {
+ ble_phy_rx_end_isr();
+ }
+
+ g_ble_phy_data.phy_transition_late = 0;
+
+ /* Ensures IRQ is cleared */
+ irq_en = NRF_RADIO_NS->SHORTS;
+
+ /* Count # of interrupts */
+ STATS_INC(ble_phy_stats, phy_isrs);
+
+ os_trace_isr_exit();
+}
+
+int
+ble_phy_init(void)
+{
+ int rc;
+
+ /* Default phy to use is 1M */
+ g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M;
+ g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M;
+ g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M;
+
+ g_ble_phy_data.rx_pwr_compensation = 0;
+
+ /* Set phy channel to an invalid channel so first set channel works */
+ g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+ /* Toggle peripheral power to reset (just in case) */
+ NRF_RADIO_NS->POWER = 0;
+ NRF_RADIO_NS->POWER = 1;
+
+ /* Errata 16 - RADIO: POWER register is not functional
+ * Workaround: Reset all RADIO registers in firmware.
+ */
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = 0;
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = 0;
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = 0;
+
+ /* Disable all interrupts */
+ NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+ /* Set configuration registers */
+ NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+ NRF_RADIO_NS->PCNF0 = NRF_PCNF0;
+
+ /* XXX: should maxlen be 251 for encryption? */
+ NRF_RADIO_NS->PCNF1 = NRF_MAXLEN |
+ (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) |
+ (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) |
+ RADIO_PCNF1_WHITEEN_Msk;
+
+ /* Enable radio fast ramp-up */
+ NRF_RADIO_NS->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & RADIO_MODECNF0_RU_Msk;
+
+ /* Set logical address 1 for TX and RX */
+ NRF_RADIO_NS->TXADDRESS = 0;
+ NRF_RADIO_NS->RXADDRESSES = (1 << 0);
+
+ /* Configure the CRC registers */
+ NRF_RADIO_NS->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three;
+
+ /* Configure BLE poly */
+ NRF_RADIO_NS->CRCPOLY = 0x0000065B;
+
+ /* Configure IFS */
+ NRF_RADIO_NS->TIFS = BLE_LL_IFS;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ NRF_CCM_NS->INTENCLR = 0xffffffff;
+ NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
+ NRF_CCM_NS->EVENTS_ERROR = 0;
+ memset(nrf_encrypt_scratchpad, 0, sizeof(nrf_encrypt_scratchpad));
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ g_ble_phy_data.phy_aar_scratch = 0;
+ NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+ NRF_AAR_NS->INTENCLR = 0xffffffff;
+ NRF_AAR_NS->EVENTS_END = 0;
+ NRF_AAR_NS->EVENTS_RESOLVED = 0;
+ NRF_AAR_NS->EVENTS_NOTRESOLVED = 0;
+ NRF_AAR_NS->NIRK = 0;
+#endif
+
+ /* TIMER0 setup for PHY when using RTC */
+ NRF_TIMER0_NS->TASKS_STOP = 1;
+ NRF_TIMER0_NS->TASKS_SHUTDOWN = 1;
+ NRF_TIMER0_NS->BITMODE = 3; /* 32-bit timer */
+ NRF_TIMER0_NS->MODE = 0; /* Timer mode */
+ NRF_TIMER0_NS->PRESCALER = 4; /* gives us 1 MHz */
+
+ /* Publish events */
+ NRF_TIMER0_NS->PUBLISH_COMPARE[0] = DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_0;
+ NRF_TIMER0_NS->PUBLISH_COMPARE[3] = DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_3;
+ NRF_RADIO_NS->PUBLISH_END = DPPI_PUBLISH_RADIO_EVENTS_END;
+ NRF_RADIO_NS->PUBLISH_BCMATCH = DPPI_PUBLISH_RADIO_EVENTS_BCMATCH;
+ NRF_RADIO_NS->PUBLISH_ADDRESS = DPPI_PUBLISH_RADIO_EVENTS_ADDRESS;
+ NRF_RTC0_NS->PUBLISH_COMPARE[0] = DPPI_PUBLISH_RTC0_EVENTS_COMPARE_0;
+
+ /* Enable channels we publish on */
+ NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_ALL;
+
+ /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[1] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE1(1);
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[2] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE2(1);
+
+ /* Set isr in vector table and enable interrupt */
+#ifndef RIOT_VERSION
+ NVIC_SetPriority(RADIO_IRQn, 0);
+#endif
+#if MYNEWT
+ NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
+#else
+ ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr);
+#endif
+ NVIC_EnableIRQ(RADIO_IRQn);
+
+ /* Register phy statistics */
+ if (!g_ble_phy_data.phy_stats_initialized) {
+ rc = stats_init_and_reg(STATS_HDR(ble_phy_stats),
+ STATS_SIZE_INIT_PARMS(ble_phy_stats,
+ STATS_SIZE_32),
+ STATS_NAME_INIT_PARMS(ble_phy_stats),
+ "ble_phy");
+ assert(rc == 0);
+
+ g_ble_phy_data.phy_stats_initialized = 1;
+ }
+
+ return 0;
+}
+
+int
+ble_phy_rx(void)
+{
+ /*
+ * Check radio state.
+ *
+ * In case radio is now disabling we'll wait for it to finish, but if for
+ * any reason it's just in idle state we proceed with RX as usual since
+ * nRF52 radio can ramp-up from idle state as well.
+ *
+ * Note that TX and RX states values are the same except for 3rd bit so we
+ * can make a shortcut here when checking for idle state.
+ */
+ nrf_wait_disabled();
+ if ((NRF_RADIO_NS->STATE != RADIO_STATE_STATE_Disabled) &&
+ ((NRF_RADIO_NS->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) {
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, radio_state_errs);
+ return BLE_PHY_ERR_RADIO_STATE;
+ }
+
+ /* Make sure all interrupts are disabled */
+ NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+ /* Clear events prior to enabling receive */
+ NRF_RADIO_NS->EVENTS_END = 0;
+ NRF_RADIO_NS->EVENTS_DISABLED = 0;
+
+ /* Setup for rx */
+ ble_phy_rx_xcvr_setup();
+
+ /* task to start RX should be subscribed here */
+ assert(NRF_RADIO_NS->SUBSCRIBE_RXEN & DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1));
+
+ return 0;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+ uint8_t is_master)
+{
+ memcpy(nrf_ccm_data.key, key, 16);
+ nrf_ccm_data.pkt_counter = pkt_counter;
+ memcpy(nrf_ccm_data.iv, iv, 8);
+ nrf_ccm_data.dir_bit = is_master;
+ g_ble_phy_data.phy_encrypted = 1;
+ /* Enable the module (AAR cannot be on while CCM on) */
+ NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+ NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Enabled;
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+ nrf_ccm_data.pkt_counter = pkt_counter;
+ nrf_ccm_data.dir_bit = dir;
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+ NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0);
+ NRF_CCM_NS->TASKS_STOP = 1;
+ NRF_CCM_NS->EVENTS_ERROR = 0;
+ NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Disabled;
+
+ g_ble_phy_data.phy_encrypted = 0;
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+ /* Set transmit end callback and arg */
+ g_ble_phy_data.txend_cb = txend_cb;
+ g_ble_phy_data.txend_arg = arg;
+}
+
+int
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ int rc;
+
+ ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs);
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode);
+#endif
+
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to RXEN since we are transmitting */
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0);
+
+ if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) {
+ STATS_INC(ble_phy_stats, tx_late);
+ ble_phy_disable();
+ rc = BLE_PHY_ERR_TX_LATE;
+ } else {
+ /* Enable PPI to automatically start TXEN */
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(1);
+ rc = 0;
+ }
+ return rc;
+}
+
+int
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ bool late = false;
+ int rc = 0;
+
+ ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs);
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+ ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode);
+#endif
+
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to TXEN since we are transmitting */
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0);
+
+ if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) {
+ STATS_INC(ble_phy_stats, rx_late);
+
+ /* We're late so let's just try to start RX as soon as possible */
+ ble_phy_set_start_now();
+
+ late = true;
+ }
+
+ /* Enable PPI to automatically start RXEN */
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1);
+
+ /* Start rx */
+ rc = ble_phy_rx();
+
+ /*
+ * If we enabled receiver but were late, let's return proper error code so
+ * caller can handle this.
+ */
+ if (!rc && late) {
+ rc = BLE_PHY_ERR_RX_LATE;
+ }
+
+ return rc;
+}
+
+int
+ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
+{
+ int rc;
+ uint8_t *dptr;
+ uint8_t *pktptr;
+ uint8_t payload_len;
+ uint8_t hdr_byte;
+ uint32_t state;
+ uint32_t shortcuts;
+
+ if (g_ble_phy_data.phy_transition_late) {
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, tx_late);
+ return BLE_PHY_ERR_TX_LATE;
+ }
+
+ /*
+ * This check is to make sure that the radio is not in a state where
+ * it is moving to disabled state. If so, let it get there.
+ */
+ nrf_wait_disabled();
+
+ /*
+ * XXX: Although we may not have to do this here, I clear all the PPI
+ * that should not be used when transmitting. Some of them are only enabled
+ * if encryption and/or privacy is on, but I dont care. Better to be
+ * paranoid, and if you are going to clear one, might as well clear them
+ * all.
+ */
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0);
+ NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0);
+ NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0);
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ if (g_ble_phy_data.phy_encrypted) {
+ dptr = (uint8_t *)&g_ble_phy_enc_buf[0];
+ pktptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+ NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
+ NRF_CCM_NS->INPTR = (uint32_t)dptr;
+ NRF_CCM_NS->OUTPTR = (uint32_t)pktptr;
+ NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0];
+ NRF_CCM_NS->EVENTS_ERROR = 0;
+ NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate();
+ NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data;
+ } else {
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+ NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+#endif
+ dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+ pktptr = dptr;
+ }
+#else
+ dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+ pktptr = dptr;
+#endif
+
+ /* Set PDU payload */
+ payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte);
+
+ /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */
+ dptr[0] = hdr_byte;
+ dptr[1] = payload_len;
+ dptr[2] = 0;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ /* Start key-stream generation and encryption (via short) */
+ if (g_ble_phy_data.phy_encrypted) {
+ NRF_CCM_NS->TASKS_KSGEN = 1;
+ }
+#endif
+
+ NRF_RADIO_NS->PACKETPTR = (uint32_t)pktptr;
+
+ /* Clear the ready, end and disabled events */
+ NRF_RADIO_NS->EVENTS_READY = 0;
+ NRF_RADIO_NS->EVENTS_END = 0;
+ NRF_RADIO_NS->EVENTS_DISABLED = 0;
+
+ /* Enable shortcuts for transmit start/end. */
+ shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk;
+ NRF_RADIO_NS->SHORTS = shortcuts;
+ NRF_RADIO_NS->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+
+ /* Set the PHY transition */
+ g_ble_phy_data.phy_transition = end_trans;
+
+ /* Set transmitted payload length */
+ g_ble_phy_data.phy_tx_pyld_len = payload_len;
+
+ /* If we already started transmitting, abort it! */
+ state = NRF_RADIO_NS->STATE;
+ if (state != RADIO_STATE_STATE_Tx) {
+ /* Set phy state to transmitting and count packet statistics */
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+ STATS_INC(ble_phy_stats, tx_good);
+ STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN);
+ rc = BLE_ERR_SUCCESS;
+ } else {
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, tx_late);
+ rc = BLE_PHY_ERR_RADIO_STATE;
+ }
+
+ return rc;
+}
+
+int
+ble_phy_txpwr_set(int dbm)
+{
+ /* "Rail" power level if outside supported range */
+ dbm = ble_phy_txpower_round(dbm);
+
+ NRF_RADIO_NS->TXPOWER = dbm;
+ g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+ return 0;
+}
+
+int
+ble_phy_txpower_round(int dbm)
+{
+ /* "Rail" power level if outside supported range */
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm;
+ }
+
+ if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) {
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm;
+ }
+
+ return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static int
+ble_phy_set_access_addr(uint32_t access_addr)
+{
+ NRF_RADIO_NS->BASE0 = (access_addr << 8);
+ NRF_RADIO_NS->PREFIX0 = (NRF_RADIO_NS->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24);
+
+ g_ble_phy_data.phy_access_address = access_addr;
+
+ return 0;
+}
+
+int
+ble_phy_txpwr_get(void)
+{
+ return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+void
+ble_phy_set_rx_pwr_compensation(int8_t compensation)
+{
+ g_ble_phy_data.rx_pwr_compensation = compensation;
+}
+
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+ assert(chan < BLE_PHY_NUM_CHANS);
+
+ /* Check for valid channel range */
+ if (chan >= BLE_PHY_NUM_CHANS) {
+ return BLE_PHY_ERR_INV_PARAM;
+ }
+
+ /* Set current access address */
+ ble_phy_set_access_addr(access_addr);
+
+ /* Configure crcinit */
+ NRF_RADIO_NS->CRCINIT = crcinit;
+
+ /* Set the frequency and the data whitening initial value */
+ g_ble_phy_data.phy_chan = chan;
+ NRF_RADIO_NS->FREQUENCY = g_ble_phy_chan_freq[chan];
+ NRF_RADIO_NS->DATAWHITEIV = chan;
+
+ return 0;
+}
+
+/**
+ * Stop the timer used to count microseconds when using RTC for cputime
+ */
+static void
+ble_phy_stop_usec_timer(void)
+{
+ NRF_TIMER0_NS->TASKS_STOP = 1;
+ NRF_TIMER0_NS->TASKS_SHUTDOWN = 1;
+ NRF_RTC0_NS->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+}
+
+/**
+ * ble phy disable irq and ppi
+ *
+ * This routine is to be called when reception was stopped due to either a
+ * wait for response timeout or a packet being received and the phy is to be
+ * restarted in receive mode. Generally, the disable routine is called to stop
+ * the phy.
+ */
+static void
+ble_phy_disable_irq_and_ppi(void)
+{
+ NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+ NRF_RADIO_NS->SHORTS = 0;
+ NRF_RADIO_NS->TASKS_DISABLE = 1;
+
+ NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(0);
+ NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0);
+ NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0);
+ NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0);
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0);
+ NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0);
+ NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0);
+
+ NVIC_ClearPendingIRQ(RADIO_IRQn);
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+void
+ble_phy_restart_rx(void)
+{
+ ble_phy_stop_usec_timer();
+ ble_phy_disable_irq_and_ppi();
+
+ ble_phy_set_start_now();
+ /* Enable PPI to automatically start RXEN */
+ NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1);
+
+ ble_phy_rx();
+}
+
+void
+ble_phy_disable(void)
+{
+ ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE);
+
+ ble_phy_stop_usec_timer();
+ ble_phy_disable_irq_and_ppi();
+}
+
+uint32_t
+ble_phy_access_addr_get(void)
+{
+ return g_ble_phy_data.phy_access_address;
+}
+
+int
+ble_phy_state_get(void)
+{
+ return g_ble_phy_data.phy_state;
+}
+
+int
+ble_phy_rx_started(void)
+{
+ return g_ble_phy_data.phy_rx_started;
+}
+
+uint8_t
+ble_phy_xcvr_state_get(void)
+{
+ uint32_t state;
+ state = NRF_RADIO_NS->STATE;
+ return (uint8_t)state;
+}
+
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+ return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+void
+ble_phy_resolv_list_enable(void)
+{
+ NRF_AAR_NS->NIRK = (uint32_t)g_nrf_num_irks;
+ g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+ g_ble_phy_data.phy_privacy = 0;
+}
+#endif
+
+#if MYNEWT_VAL(BLE_LL_DTM)
+void
+ble_phy_enable_dtm(void)
+{
+ /* When DTM is enabled we need to disable whitening as per
+ * Bluetooth v5.0 Vol 6. Part F. 4.1.1
+ */
+ NRF_RADIO_NS->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk;
+}
+
+void
+ble_phy_disable_dtm(void)
+{
+ /* Enable whitening */
+ NRF_RADIO_NS->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk;
+}
+#endif
+
+void
+ble_phy_rfclk_enable(void)
+{
+#if MYNEWT
+ nrf5340_net_clock_hfxo_request();
+#else
+ NRF_CLOCK_NS->TASKS_HFCLKSTART = 1;
+#endif
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+#if MYNEWT
+ nrf5340_net_clock_hfxo_release();
+#else
+ NRF_CLOCK_NS->TASKS_HFCLKSTOP = 1;
+#endif
+}
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c
new file mode 100644
index 00000000..6967c3f7
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+
+#if MYNEWT_VAL(BLE_PHY_SYSVIEW)
+
+static os_trace_module_t g_ble_phy_trace_mod;
+uint32_t ble_phy_trace_off;
+
+static void
+ble_phy_trace_module_send_desc(void)
+{
+ os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u");
+ os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u");
+ os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable");
+}
+
+void
+ble_phy_trace_init(void)
+{
+ ble_phy_trace_off =
+ os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3,
+ ble_phy_trace_module_send_desc);
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml
new file mode 100644
index 00000000..dd8b9304
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml
@@ -0,0 +1,23 @@
+# 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.
+#
+
+syscfg.defs:
+ BLE_PHY_SYSVIEW:
+ description: >
+ Enable SystemView tracing module for radio driver.
+ value: 0
diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
index 20e7dab7..20f9e30d 100644
--- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
+++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
@@ -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,18 +94,18 @@ 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
#define BLE_GAP_INITIAL_CONN_LATENCY 0
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
-#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
-#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
+#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
+#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
#define BLE_GAP_ROLE_MASTER 0
#define BLE_GAP_ROLE_SLAVE 1
@@ -1896,6 +1902,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
*/
int ble_gap_unpair_oldest_peer(void);
+/**
+ * Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
+ * peer received in input parameters is not deleted.
+ *
+ * @param peer_addr Address of the peer (not to be deleted)
+ *
+ * @return 0 on success;
+ * A BLE host HCI return code if the controller
+ * rejected the request;
+ * A BLE host core return code on unexpected
+ * error.
+ */
+int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
+
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
index 8d0a4596..7b90eaf9 100644
--- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
+++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
@@ -21,6 +21,7 @@
#define H_BLE_HS_LOG_
#include "modlog/modlog.h"
+#include "log/log.h"
/* Only include the logcfg header if this version of newt can generate it. */
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
index 1f99f412..9f923cb9 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
@@ -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;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
new file mode 100644
index 00000000..2c731794
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
@@ -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__ */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h
new file mode 100644
index 00000000..8f9a6bc9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.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 "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_ */
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h
new file mode 100644
index 00000000..378f0a0a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.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
+#include
+#include
+
+/**
+ * @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_ */
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h
index 7dc237be..bd2f9fe5 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
index 14d8a295..5bf3f439 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
@@ -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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
index e37fcfbc..abe3dd53 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
@@ -51,15 +51,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
@@ -73,7 +64,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
@@ -85,8 +76,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 */
@@ -119,9 +110,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)
@@ -196,9 +191,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)
@@ -238,6 +233,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);
@@ -248,18 +251,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);
@@ -271,7 +276,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)
@@ -279,14 +284,16 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/** 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 {
@@ -298,18 +305,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,
@@ -323,9 +336,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);
@@ -355,18 +369,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;
@@ -374,43 +388,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
/* 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 CONFIG_BT_MESH_CDB BLE_MESH_CDB
#define printk console_printf
@@ -426,7 +458,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;
@@ -448,8 +480,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);
}
@@ -495,6 +527,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
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
index 8ab8d6d5..e9efe4b1 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
@@ -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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
index 83982376..ad79e368 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
@@ -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))
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
new file mode 100644
index 00000000..b9990f6f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
@@ -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_ */
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h
index 4a5bedba..2bcb05c8 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
index 9ba63ef0..b9bc24fb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
@@ -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 */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h
index f2e77a47..87e2dd2b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
index e498ad34..a23296b8 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
@@ -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
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
index 4c2b2a61..580aafe4 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
@@ -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);
/**
* @}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
index ff8e9999..da077182 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
@@ -26,7 +26,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,
@@ -53,7 +53,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;
@@ -89,10 +89,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) {
@@ -115,7 +115,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);
@@ -131,7 +131,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;
@@ -156,30 +156,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);
@@ -187,15 +175,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("");
@@ -227,7 +222,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;
}
@@ -242,7 +240,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;
@@ -274,6 +272,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;
@@ -293,12 +296,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;
@@ -306,12 +311,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;
@@ -334,16 +340,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;
@@ -357,13 +361,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;
@@ -380,7 +384,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,
@@ -396,10 +400,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++) {
@@ -423,9 +427,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);
@@ -447,12 +451,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;
@@ -467,22 +471,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;
@@ -500,7 +508,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:
@@ -527,6 +535,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;
}
@@ -534,29 +546,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,
@@ -615,7 +610,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);
@@ -628,6 +623,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:
@@ -674,11 +673,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);
@@ -688,13 +684,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;
@@ -710,12 +708,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;
@@ -730,13 +722,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);
@@ -745,10 +731,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:
@@ -757,9 +740,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 &&
@@ -772,9 +755,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) {
@@ -802,29 +785,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)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
index 48514983..affba538 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
@@ -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);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
index 4bd51cc1..4b372991 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
@@ -38,19 +38,18 @@
#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;
#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(
@@ -60,14 +59,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)
@@ -75,7 +66,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)
{
@@ -94,10 +85,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;
@@ -154,7 +152,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");
@@ -208,7 +206,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;
@@ -235,10 +233,11 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
ble_npl_event_set_arg(&adv->ev, buf);
return buf;
+ os_mbuf_free_chain(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);
@@ -257,8 +256,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;
@@ -270,7 +269,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 */
@@ -304,7 +303,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);
}
}
@@ -333,7 +332,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));
#endif
/* For BT5 controllers we can have fast advertising interval */
@@ -362,7 +361,7 @@ ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_EXT_DISC:
ext_desc = &event->ext_disc;
buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0);
- if (!buf || os_mbuf_append(buf, ext_desc->data, ext_desc->length_data)) {
+ if (!buf || os_mbuf_append(buf, ext_desc->om_data, ext_desc->length_data)) {
BT_ERR("Could not append data");
goto done;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
index 4d0f7d8b..779ee58e 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
@@ -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);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
new file mode 100644
index 00000000..ab23c264
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#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;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
new file mode 100644
index 00000000..a6c32bf3
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include
+#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 "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[16], 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
new file mode 100644
index 00000000..d007b785
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
@@ -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 "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[16], 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_ */
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
index cd540aa8..6a5fc5a1 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
@@ -21,8 +21,8 @@
#include "crypto.h"
#include "beacon.h"
#include "foundation.h"
+#include "atomic.h"
-#define UNPROVISIONED_INTERVAL (K_SECONDS(5))
#define PROVISIONED_INTERVAL (K_SECONDS(10))
#define BEACON_TYPE_UNPROVISIONED 0x00
@@ -36,26 +36,12 @@
static struct k_delayed_work beacon_timer;
-static struct bt_mesh_subnet *cache_check(u8_t data[21])
+static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (!memcmp(sub->beacon_cache, data, 21)) {
- return sub;
- }
- }
-
- return NULL;
+ return !memcmp(sub->beacon_cache, beacon_data, 21);
}
-static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
+static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub)
{
memcpy(sub->beacon_cache, data, 21);
}
@@ -72,16 +58,12 @@ static void beacon_complete(int err, void *user_data)
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf)
{
- u8_t flags = bt_mesh_net_flags(sub);
+ uint8_t flags = bt_mesh_net_flags(sub);
struct bt_mesh_subnet_keys *keys;
net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
- if (sub->kr_flag) {
- keys = &sub->keys[1];
- } else {
- keys = &sub->keys[0];
- }
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
net_buf_simple_add_u8(buf, flags);
@@ -103,53 +85,43 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
K_SECONDS(5))
-static int secure_beacon_send(void)
+static int secure_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
{
static const struct bt_mesh_send_cb send_cb = {
.end = beacon_complete,
};
- u32_t now = k_uptime_get_32();
- int i;
+ uint32_t now = k_uptime_get_32();
+ struct os_mbuf *buf;
+ uint32_t time_diff;
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- struct os_mbuf *buf;
- u32_t time_diff;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- time_diff = now - sub->beacon_sent;
- if (time_diff < K_SECONDS(600) &&
- time_diff < BEACON_THRESHOLD(sub)) {
- continue;
- }
-
- buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
- K_NO_WAIT);
- if (!buf) {
- BT_ERR("Unable to allocate beacon buffer");
- return -ENOBUFS;
- }
-
- bt_mesh_beacon_create(sub, buf);
-
- bt_mesh_adv_send(buf, &send_cb, sub);
- net_buf_unref(buf);
+ time_diff = now - sub->beacon_sent;
+ if (time_diff < (600 * MSEC_PER_SEC) &&
+ time_diff < BEACON_THRESHOLD(sub)) {
+ return 0;
}
+ buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT);
+ if (!buf) {
+ BT_ERR("Unable to allocate beacon buffer");
+ return -ENOMEM;
+ }
+
+ bt_mesh_beacon_create(sub, buf);
+
+ bt_mesh_adv_send(buf, &send_cb, sub);
+ net_buf_unref(buf);
+
return 0;
}
static int unprovisioned_beacon_send(void)
{
const struct bt_mesh_prov *prov;
- u8_t uri_hash[16] = { 0 };
+ uint8_t uri_hash[16] = { 0 };
struct os_mbuf *buf;
- u16_t oob_info;
+ uint16_t oob_info;
BT_DBG("unprovisioned_beacon_send");
@@ -202,12 +174,11 @@ static int unprovisioned_beacon_send(void)
static void unprovisioned_beacon_recv(struct os_mbuf *buf)
{
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
const struct bt_mesh_prov *prov;
- u8_t *uuid;
- u16_t oob_info;
- u32_t uri_hash_val;
- u32_t *uri_hash = NULL;
+ uint8_t *uuid;
+ uint16_t oob_info;
+ uint32_t uri_hash_val;
+ uint32_t *uri_hash = NULL;
if (buf->om_len != 18 && buf->om_len != 22) {
BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len);
@@ -231,13 +202,17 @@ static void unprovisioned_beacon_recv(struct os_mbuf *buf)
(bt_mesh_prov_oob_info_t)oob_info,
uri_hash);
}
-#endif
+}
+
+static void sub_update_beacon_observation(struct bt_mesh_subnet *sub)
+{
+ sub->beacons_last = sub->beacons_cur;
+ sub->beacons_cur = 0U;
}
static void update_beacon_observation(void)
{
static bool first_half;
- int i;
/* Observation period is 20 seconds, whereas the beacon timer
* runs every 10 seconds. We process what's happened during the
@@ -248,23 +223,15 @@ static void update_beacon_observation(void)
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = sub->beacons_cur;
- sub->beacons_cur = 0;
- }
+ bt_mesh_subnet_foreach(sub_update_beacon_observation);
}
static void beacon_send(struct ble_npl_event *work)
{
/* Don't send anything if we have an active provisioning link */
- if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) {
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) {
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
return;
}
@@ -272,34 +239,81 @@ static void beacon_send(struct ble_npl_event *work)
if (bt_mesh_is_provisioned()) {
update_beacon_observation();
- secure_beacon_send();
+ (void)bt_mesh_subnet_find(secure_beacon_send, NULL);
/* Only resubmit if beaconing is still enabled */
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
+ if (bt_mesh_beacon_enabled() ||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
k_delayed_work_submit(&beacon_timer,
PROVISIONED_INTERVAL);
}
- } else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
- unprovisioned_beacon_send();
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+
+ return;
}
+
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
+ unprovisioned_beacon_send();
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
+ }
+}
+
+struct beacon_params {
+ const uint8_t *net_id;
+ const uint8_t *auth;
+ uint32_t iv_index;
+ uint8_t flags;
+
+ bool new_key;
+};
+
+static bool auth_match(struct bt_mesh_subnet_keys *keys,
+ const struct beacon_params *params)
+{
+ uint8_t net_auth[8];
+
+ if (memcmp(params->net_id, keys->net_id, 8)) {
+ return false;
+ }
+
+ bt_mesh_beacon_auth(keys->beacon, params->flags, keys->net_id,
+ params->iv_index, net_auth);
+
+ if (memcmp(params->auth, net_auth, 8)) {
+ BT_WARN("Authentication Value %s != %s",
+ bt_hex(params->auth, 8), bt_hex(net_auth, 8));
+ return false;
+ }
+
+ return true;
+}
+
+static int subnet_by_id(struct bt_mesh_subnet *sub, void *cb_data)
+{
+ struct beacon_params *params = cb_data;
+
+ for (int i = 0; i < ARRAY_SIZE(sub->keys); i++) {
+ if (sub->keys[i].valid && auth_match(&sub->keys[i], params)) {
+ params->new_key = (i > 0);
+ return true;
+ }
+ }
+
+ return false;
}
static void secure_beacon_recv(struct os_mbuf *buf)
{
- u8_t *data, *net_id, *auth;
+ struct beacon_params params;
struct bt_mesh_subnet *sub;
- u32_t iv_index;
- bool new_key, kr_change, iv_change;
- u8_t flags;
+ uint8_t *data;
if (buf->om_len < 21) {
BT_ERR("Too short secure beacon (len %u)", buf->om_len);
return;
}
- sub = cache_check(buf->om_data);
+ sub = bt_mesh_subnet_find(cache_check, buf->om_data);
if (sub) {
/* We've seen this beacon before - just update the stats */
goto update_stats;
@@ -308,27 +322,30 @@ static void secure_beacon_recv(struct os_mbuf *buf)
/* So we can add to the cache if auth matches */
data = buf->om_data;
- flags = net_buf_simple_pull_u8(buf);
- net_id = net_buf_simple_pull_mem(buf, 8);
- iv_index = net_buf_simple_pull_be32(buf);
- auth = buf->om_data;
+ params.flags = net_buf_simple_pull_u8(buf);
+ params.net_id = net_buf_simple_pull_mem(buf, 8);
+ params.iv_index = net_buf_simple_pull_be32(buf);
+ params.auth = buf->om_data;
BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
- flags, bt_hex(net_id, 8), (unsigned) iv_index);
+ params.flags, bt_hex(params.net_id, 8), params.iv_index);
- sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
+ sub = bt_mesh_subnet_find(subnet_by_id, ¶ms);
if (!sub) {
BT_DBG("No subnet that matched beacon");
return;
}
- if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
+ if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !params.new_key) {
BT_WARN("Ignoring Phase 2 KR Update secured using old key");
return;
}
cache_add(data, sub);
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(params.flags),
+ params.new_key);
+
/* If we have NetKey0 accept initiation only from it */
if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
sub->net_idx != BT_MESH_KEY_PRIMARY) {
@@ -337,31 +354,18 @@ static void secure_beacon_recv(struct os_mbuf *buf)
}
BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
- sub->net_idx, (unsigned) iv_index, (unsigned) bt_mesh.iv_index);
+ sub->net_idx, params.iv_index, bt_mesh.iv_index);
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
- BT_MESH_IV_UPDATE(flags))) {
+ BT_MESH_IV_UPDATE(params.flags))) {
bt_mesh_beacon_ivu_initiator(false);
}
- iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
-
- kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
- if (kr_change) {
- bt_mesh_net_beacon_update(sub);
- }
-
- if (iv_change) {
- /* Update all subnets */
- bt_mesh_net_sec_update(NULL);
- } else if (kr_change) {
- /* Key Refresh without IV Update only impacts one subnet */
- bt_mesh_net_sec_update(sub);
- }
+ bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags));
update_stats:
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
+ if (bt_mesh_beacon_enabled() &&
sub->beacons_cur < 0xff) {
sub->beacons_cur++;
}
@@ -369,7 +373,7 @@ update_stats:
void bt_mesh_beacon_recv(struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
@@ -381,7 +385,9 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
type = net_buf_simple_pull_u8(buf);
switch (type) {
case BEACON_TYPE_UNPROVISIONED:
- unprovisioned_beacon_recv(buf);
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
+ unprovisioned_beacon_recv(buf);
+ }
break;
case BEACON_TYPE_SECURE:
secure_beacon_recv(buf);
@@ -392,8 +398,38 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
}
}
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub)
+{
+ uint8_t flags = bt_mesh_net_flags(sub);
+ struct bt_mesh_subnet_keys *keys;
+ int err;
+
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
+
+ BT_DBG("NetIndex 0x%03x Using %s key", sub->net_idx,
+ SUBNET_KEY_TX_IDX(sub) ? "new" : "current");
+ BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
+
+ err = bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
+ bt_mesh.iv_index, sub->auth);
+ if (err) {
+ BT_ERR("Failed updating net beacon for 0x%03x", sub->net_idx);
+ }
+}
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt != BT_MESH_KEY_DELETED) {
+ bt_mesh_beacon_update(sub);
+ }
+}
+
void bt_mesh_beacon_init(void)
{
+ if (!bt_mesh_subnet_cb_list[1]) {
+ bt_mesh_subnet_cb_list[1] = subnet_evt;
+ }
+
k_delayed_work_init(&beacon_timer, beacon_send);
}
@@ -402,35 +438,30 @@ void bt_mesh_beacon_ivu_initiator(bool enable)
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable);
if (enable) {
- k_work_submit(&beacon_timer.work);
- } else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
+ } else if (!bt_mesh_beacon_enabled()) {
k_delayed_work_cancel(&beacon_timer);
}
}
+static void subnet_beacon_enable(struct bt_mesh_subnet *sub)
+{
+ sub->beacons_last = 0U;
+ sub->beacons_cur = 0U;
+
+ bt_mesh_beacon_update(sub);
+}
+
void bt_mesh_beacon_enable(void)
{
- int i;
-
if (!bt_mesh_is_provisioned()) {
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+ bt_mesh_subnet_foreach(subnet_beacon_enable);
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = 0;
- sub->beacons_cur = 0;
-
- bt_mesh_net_beacon_update(sub);
- }
-
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
}
void bt_mesh_beacon_disable(void)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
index ac4bfed8..a6aa8cbb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
@@ -22,5 +22,6 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf);
void bt_mesh_beacon_init(void);
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
new file mode 100644
index 00000000..bcca3b90
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if BLE_MESH_CDB
+#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB)
+#define LOG_MODULE_NAME bt_mesh_cdb
+#include "log/log.h"
+
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+#include "mesh_priv.h"
+#include "mesh/glue.h"
+
+
+struct bt_mesh_cdb bt_mesh_cdb = {
+ .nodes = {
+ [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
+ .addr = BT_MESH_ADDR_UNASSIGNED,
+ }
+ },
+ .subnets = {
+ [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+ .app_keys = {
+ [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+};
+
+/*
+ * Check if an address range from addr_start for addr_start + num_elem - 1 is
+ * free for use. When a conflict is found, next will be set to the next address
+ * available after the conflicting range and -EAGAIN will be returned.
+ */
+static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
+{
+ uint16_t addr_end = addr_start + num_elem - 1;
+ uint16_t other_start, other_end;
+ int i;
+
+ if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
+ !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
+ num_elem == 0) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ other_start = node->addr;
+ other_end = other_start + node->num_elem - 1;
+
+ if (!(addr_end < other_start || addr_start > other_end)) {
+ if (next) {
+ *next = other_end + 1;
+ }
+
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Find the lowest possible starting address that can fit num_elem elements. If
+ * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
+ * returned. Otherwise the first address in the range is returned.
+ *
+ * NOTE: This is quite an ineffective algorithm as it might need to look
+ * through the array of nodes N+2 times. A more effective algorithm
+ * could be used if the nodes were stored in a sorted list.
+ */
+static uint16_t find_lowest_free_addr(uint8_t num_elem)
+{
+ uint16_t addr = 1, next = 0;
+ int err, i;
+
+ /*
+ * It takes a maximum of node count + 2 to find a free address if there
+ * is any. +1 for our own address and +1 for making sure that the
+ * address range is valid.
+ */
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
+ err = addr_is_free(addr, num_elem, &next);
+ if (err == 0) {
+ break;
+ } else if (err != -EAGAIN) {
+ addr = BT_MESH_ADDR_UNASSIGNED;
+ break;
+ }
+
+ addr = next;
+ }
+
+ return addr;
+}
+
+int bt_mesh_cdb_create(const uint8_t key[16])
+{
+ struct bt_mesh_cdb_subnet *sub;
+
+ if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ return -EALREADY;
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
+ if (sub == NULL) {
+ return -ENOMEM;
+ }
+
+ memcpy(sub->keys[0].net_key, key, 16);
+ bt_mesh_cdb.iv_index = 0;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ bt_mesh_store_cdb_subnet(sub);
+ }
+
+ return 0;
+}
+
+void bt_mesh_cdb_clear(void)
+{
+ int i;
+
+ atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
+ }
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
+{
+ BT_DBG("Updating IV index to %d\n", iv_index);
+
+ bt_mesh_cdb.iv_index = iv_index;
+
+ atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
+ iv_update);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
+{
+ struct bt_mesh_cdb_subnet *sub;
+ int i;
+
+ if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ sub = &bt_mesh_cdb.subnets[i];
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ sub->net_idx = net_idx;
+
+ return sub;
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
+{
+ BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_subnet(sub);
+ }
+
+ sub->net_idx = BT_MESH_KEY_UNUSED;
+ memset(sub->keys, 0, sizeof(sub->keys));
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
+ return &bt_mesh_cdb.subnets[i];
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_subnet(sub);
+ }
+}
+
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
+{
+ uint8_t flags = 0x00;
+
+ if (sub && sub->kr_flag) {
+ flags |= BT_MESH_NET_FLAG_KR;
+ }
+
+ if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
+ flags |= BT_MESH_NET_FLAG_IVU;
+ }
+
+ return flags;
+}
+
+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)
+{
+ int i;
+
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ addr = find_lowest_free_addr(num_elem);
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ return NULL;
+ }
+ } else if (addr_is_free(addr, num_elem, NULL) < 0) {
+ BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
+ addr + num_elem - 1);
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ memcpy(node->uuid, uuid, 16);
+ node->addr = addr;
+ node->num_elem = num_elem;
+ node->net_idx = net_idx;
+ atomic_set(node->flags, 0);
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
+{
+ BT_DBG("Node addr 0x%04x store %u", node->addr, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_node(node);
+ }
+
+ node->addr = BT_MESH_ADDR_UNASSIGNED;
+ memset(node->dev_key, 0, sizeof(node->dev_key));
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (addr >= node->addr &&
+ addr <= node->addr + node->num_elem - 1) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+}
+
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ if (func(&bt_mesh_cdb.nodes[i], user_data) ==
+ BT_MESH_CDB_ITER_STOP) {
+ break;
+ }
+ }
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+ uint16_t app_idx)
+{
+ struct bt_mesh_cdb_app_key *key;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ key->net_idx = net_idx;
+ key->app_idx = app_idx;
+
+ return key;
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
+{
+ BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_app_key(key);
+ }
+
+ key->net_idx = BT_MESH_ADDR_UNASSIGNED;
+ memset(key->keys, 0, sizeof(key->keys));
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
+ struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED &&
+ key->app_idx == app_idx) {
+ return key;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_app_key(key);
+ }
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
new file mode 100644
index 00000000..4e149255
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/mesh.h"
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "settings.h"
+#include "heartbeat.h"
+#include "friend.h"
+#include "cfg.h"
+#include "mesh/glue.h"
+
+void bt_mesh_beacon_set(bool beacon)
+{
+ if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
+ return;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
+
+ if (beacon) {
+ bt_mesh_beacon_enable();
+ } else {
+ bt_mesh_beacon_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+bool bt_mesh_beacon_enabled(void)
+{
+ return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
+}
+
+static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
+{
+ if (state != BT_MESH_FEATURE_DISABLED &&
+ state != BT_MESH_FEATURE_ENABLED) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
+ (state == BT_MESH_FEATURE_ENABLED)) {
+ return -EALREADY;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, feature_flag,
+ (state == BT_MESH_FEATURE_ENABLED));
+
+ return 0;
+}
+
+static enum bt_mesh_feat_state feature_get(int feature_flag)
+{
+ return atomic_test_bit(bt_mesh.flags, feature_flag) ?
+ BT_MESH_FEATURE_ENABLED :
+ BT_MESH_FEATURE_DISABLED;
+}
+
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_GATT_PROXY);
+}
+
+int bt_mesh_default_ttl_set(uint8_t default_ttl)
+{
+ if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
+ return -EINVAL;
+ }
+
+ if (default_ttl == bt_mesh.default_ttl) {
+ return 0;
+ }
+
+ bt_mesh.default_ttl = default_ttl;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+uint8_t bt_mesh_default_ttl_get(void)
+{
+ return bt_mesh.default_ttl;
+}
+
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_FRIEND, friendship);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ if (friendship == BT_MESH_FEATURE_DISABLED) {
+ bt_mesh_friends_clear();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_friend_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_FRIEND);
+}
+
+void bt_mesh_net_transmit_set(uint8_t xmit)
+{
+ if (bt_mesh.net_xmit == xmit) {
+ return;
+ }
+
+ bt_mesh.net_xmit = xmit;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+uint8_t bt_mesh_net_transmit_get(void)
+{
+ return bt_mesh.net_xmit;
+}
+
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
+{
+ int err;
+
+ if (!CONFIG_BT_MESH_RELAY) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_RELAY, relay);
+ if (err == -EINVAL) {
+ return err;
+ }
+
+ if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
+ return -EALREADY;
+ }
+
+ bt_mesh.relay_xmit = xmit;
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_relay_get(void)
+{
+ return feature_get(BT_MESH_RELAY);
+}
+
+uint8_t bt_mesh_relay_retransmit_get(void)
+{
+ if (!CONFIG_BT_MESH_RELAY) {
+ return 0;
+ }
+
+ return bt_mesh.relay_xmit;
+}
+
+bool bt_mesh_fixed_group_match(uint16_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_FEATURE_ENABLED);
+ case BT_MESH_ADDR_FRIENDS:
+ return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
+ case BT_MESH_ADDR_RELAYS:
+ return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
+ default:
+ return false;
+ }
+}
+
+void bt_mesh_cfg_init(void)
+{
+ bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
+ bt_mesh.net_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
+ CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
+
+#if defined(CONFIG_BT_MESH_RELAY)
+ bt_mesh.relay_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
+ CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
+#endif
+
+ if (CONFIG_BT_MESH_RELAY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
+ }
+
+ if (CONFIG_BT_MESH_BEACON_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
+ }
+
+ if (CONFIG_BT_MESH_GATT_PROXY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
+ }
+
+ if (CONFIG_BT_MESH_FRIEND_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
+ }
+}
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
new file mode 100644
index 00000000..6f58acf8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_mesh_cfg_init(void);
+
+bool bt_mesh_fixed_group_match(uint16_t addr);
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
index 2c2f6c3f..a87cd7bb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
@@ -25,11 +25,11 @@
#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff)
struct comp_data {
- u8_t *status;
+ uint8_t *status;
struct os_mbuf *comp;
};
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_cfg_cli *cli;
@@ -61,9 +61,9 @@ static void comp_data_status(struct bt_mesh_model *model,
static void state_status_u8(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf,
- u32_t expect_status)
+ uint32_t expect_status)
{
- u8_t *status;
+ uint8_t *status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -110,8 +110,8 @@ static void gatt_proxy_status(struct bt_mesh_model *model,
}
struct relay_param {
- u8_t *status;
- u8_t *transmit;
+ uint8_t *status;
+ uint8_t *transmit;
};
static void relay_status(struct bt_mesh_model *model,
@@ -137,8 +137,8 @@ static void relay_status(struct bt_mesh_model *model,
}
struct net_key_param {
- u8_t *status;
- u16_t net_idx;
+ uint8_t *status;
+ uint16_t net_idx;
};
static void net_key_status(struct bt_mesh_model *model,
@@ -146,8 +146,8 @@ static void net_key_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct net_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -159,7 +159,7 @@ static void net_key_status(struct bt_mesh_model *model,
}
status = net_buf_simple_pull_u8(buf);
- key_idx_unpack(buf, &net_idx, &app_idx);
+ net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
param = cli->op_param;
if (param->net_idx != net_idx) {
@@ -174,10 +174,66 @@ static void net_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct net_key_list_param {
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void net_key_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct net_key_list_param *param;
+ int i;
+
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_NET_KEY_LIST) {
+ BT_WARN("Unexpected Net Key List message");
+ return;
+ }
+
+ param = cli->op_param;
+
+ for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) {
+ key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void node_reset_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf)
+{
+ bool *param = NULL;
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x",
+ ctx->net_idx, ctx->app_idx, ctx->addr);
+
+ if (cli->op_pending != OP_NODE_RESET_STATUS) {
+ BT_WARN("Unexpected Node Reset Status message");
+ return;
+ }
+
+ param = cli->op_param;
+
+ if (param) {
+ *param = true;
+ }
+ k_sem_give(&cli->op_sync);
+}
+
struct app_key_param {
- u8_t *status;
- u16_t net_idx;
- u16_t app_idx;
+ uint8_t *status;
+ uint16_t net_idx;
+ uint16_t app_idx;
};
static void app_key_status(struct bt_mesh_model *model,
@@ -185,8 +241,8 @@ static void app_key_status(struct bt_mesh_model *model,
struct os_mbuf*buf)
{
struct app_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx, app_idx;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -213,21 +269,71 @@ static void app_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct app_key_list_param {
+ uint16_t net_idx;
+ uint8_t *status;
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void app_key_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct app_key_list_param *param;
+ uint16_t net_idx;
+ uint8_t status;
+ int i;
+
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_APP_KEY_LIST) {
+ BT_WARN("Unexpected App Key List message");
+ return;
+ }
+
+ status = net_buf_simple_pull_u8(buf);
+ net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
+
+ param = cli->op_param;
+ if (param->net_idx != net_idx) {
+ BT_WARN("App Key List Net Key index did not match");
+ return;
+ }
+
+ for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) {
+ key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
struct mod_app_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t mod_app_idx;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_app_idx;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_app_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
struct mod_app_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -265,11 +371,92 @@ static void mod_app_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct mod_member_list_param {
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t *members;
+ size_t *member_cnt;
+};
+
+static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf, bool vnd)
+{
+ struct mod_member_list_param *param;
+ uint16_t elem_addr, mod_id, cid;
+ uint8_t status;
+ int i;
+
+ status = net_buf_simple_pull_u8(buf);
+ elem_addr = net_buf_simple_pull_le16(buf);
+ if (vnd) {
+ cid = net_buf_simple_pull_le16(buf);
+ }
+
+ mod_id = net_buf_simple_pull_le16(buf);
+
+ param = cli->op_param;
+ if (param->elem_addr != elem_addr || param->mod_id != mod_id ||
+ (vnd && param->cid != cid)) {
+ BT_WARN("Model Member List parameters did not match");
+ return;
+ }
+
+ if (buf->om_len % 2) {
+ BT_WARN("Model Member List invalid length");
+ return;
+ }
+
+ for (i = 0; i < *param->member_cnt && buf->om_len; i++) {
+ param->members[i] = net_buf_simple_pull_le16(buf);
+ }
+
+ *param->member_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void mod_app_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_SIG_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_app_list_vnd(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_VND_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct mod_pub_param {
- u16_t mod_id;
- u16_t cid;
- u16_t elem_addr;
- u8_t *status;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t elem_addr;
+ uint8_t *status;
struct bt_mesh_cfg_mod_pub *pub;
};
@@ -277,9 +464,9 @@ static void mod_pub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t mod_id, cid, elem_addr;
+ uint16_t mod_id, cid, elem_addr;
struct mod_pub_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -341,21 +528,21 @@ static void mod_pub_status(struct bt_mesh_model *model,
}
struct mod_sub_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t *sub_addr;
- u16_t *expect_sub;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t *sub_addr;
+ uint16_t *expect_sub;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_sub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, sub_addr, mod_id, cid;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
struct mod_sub_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -397,8 +584,40 @@ static void mod_sub_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+static void mod_sub_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST) {
+ BT_WARN("Unexpected Model Subscription List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_sub_list_vnd(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST_VND) {
+ BT_WARN("Unexpected Model Subscription List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct hb_sub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_sub *sub;
};
@@ -432,7 +651,7 @@ static void hb_sub_status(struct bt_mesh_model *model,
}
struct hb_pub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_pub *pub;
};
@@ -475,12 +694,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
{ OP_GATT_PROXY_STATUS, 1, gatt_proxy_status },
{ OP_RELAY_STATUS, 2, relay_status },
{ OP_NET_KEY_STATUS, 3, net_key_status },
+ { OP_NET_KEY_LIST, 0, net_key_list },
{ OP_APP_KEY_STATUS, 4, app_key_status },
+ { OP_APP_KEY_LIST, 3, app_key_list },
{ OP_MOD_APP_STATUS, 7, mod_app_status },
+ { OP_SIG_MOD_APP_LIST, 5, mod_app_list},
+ { OP_VND_MOD_APP_LIST, 7, mod_app_list_vnd},
{ OP_MOD_PUB_STATUS, 12, mod_pub_status },
{ OP_MOD_SUB_STATUS, 7, mod_sub_status },
+ { OP_MOD_SUB_LIST, 5, mod_sub_list},
+ { OP_MOD_SUB_LIST_VND, 7, mod_sub_list_vnd},
{ OP_HEARTBEAT_SUB_STATUS, 9, hb_sub_status },
{ OP_HEARTBEAT_PUB_STATUS, 10, hb_pub_status },
+ { OP_NODE_RESET_STATUS, 0, node_reset_status},
BT_MESH_MODEL_OP_END,
};
@@ -516,7 +742,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = {
.init = cfg_cli_init,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!cli) {
BT_ERR("No available Configuration Client context!");
@@ -551,8 +777,8 @@ static int cli_wait(void)
return err;
}
-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_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+ uint8_t *status, struct os_mbuf *comp)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -588,8 +814,8 @@ done:
return err;
}
-static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t *val)
+static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -620,8 +846,8 @@ done:
return err;
}
-static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t new_val, u8_t *val)
+static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t new_val, uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -653,57 +879,71 @@ done:
return err;
}
-int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS,
status);
}
-int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS,
val, status);
}
-int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl)
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl)
{
return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET,
OP_DEFAULT_TTL_STATUS, ttl);
}
-int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl)
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl)
{
return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET,
OP_DEFAULT_TTL_STATUS, val, ttl);
}
-int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_FRIEND_GET,
OP_FRIEND_STATUS, status);
}
-int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS,
val, status);
}
-int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET,
OP_GATT_PROXY_STATUS, 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_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+ uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET,
OP_GATT_PROXY_STATUS, val, status);
}
-int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
- u8_t *transmit)
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+ uint8_t val, uint8_t *transmit)
+{
+ return set_state_u8(net_idx, addr, OP_NET_TRANSMIT_SET,
+ OP_NET_TRANSMIT_STATUS, val, transmit);
+}
+
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+ uint8_t *transmit)
+{
+ return get_state_u8(net_idx, addr, OP_NET_TRANSMIT_GET,
+ OP_NET_TRANSMIT_STATUS, transmit);
+}
+
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+ uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -738,8 +978,8 @@ done:
return err;
}
-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_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+ uint8_t new_transmit, uint8_t *status, uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_SET, 2);
struct bt_mesh_msg_ctx ctx = {
@@ -776,8 +1016,8 @@ done:
return err;
}
-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_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ const uint8_t net_key[16], uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_ADD, 18);
struct bt_mesh_msg_ctx ctx = {
@@ -819,9 +1059,85 @@ done:
return err;
}
-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_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+ size_t *key_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_GET, 0);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct net_key_list_param param = {
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_NET_KEY_LIST);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_GET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_DEL, 2);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct net_key_param param = {
+ .status = status,
+ .net_idx = key_net_idx,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_NET_KEY_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_DEL);
+ net_buf_simple_add_le16(msg, key_net_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_ADD, 19);
struct bt_mesh_msg_ctx ctx = {
@@ -864,9 +1180,137 @@ done:
return err;
}
-static int mod_app_bind(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_node_reset(uint16_t net_idx, uint16_t addr, bool *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET, 0);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+
+ int err;
+
+ if (status) {
+ *status = false;
+ }
+
+ err = cli_prepare(status, OP_NODE_RESET_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NODE_RESET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return 0;
+ }
+}
+
+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)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_GET, 2);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct app_key_list_param param = {
+ .net_idx = key_net_idx,
+ .status = status,
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_APP_KEY_LIST);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_GET);
+ net_buf_simple_add_le16(msg, key_net_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+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)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_DEL, 3);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct app_key_param param = {
+ .status = status,
+ .net_idx = key_net_idx,
+ .app_idx = key_app_idx,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_APP_KEY_STATUS);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_DEL);
+ key_idx_pack(msg, key_net_idx, key_app_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ if (!status) {
+ cli_reset();
+ os_mbuf_free_chain(msg);
+ return 0;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+static int mod_app_bind(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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_BIND, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -917,16 +1361,16 @@ done:
return err;
}
-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_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)
{
return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
CID_NVAL, status);
}
-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_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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -936,8 +1380,160 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
status);
}
-static int mod_sub(u32_t op, 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)
+static int mod_app_unbind(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)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_UNBIND, 8);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct mod_app_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_app_idx = mod_app_idx,
+ .mod_id = mod_id,
+ .cid = cid,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_MOD_APP_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_MOD_APP_UNBIND);
+ net_buf_simple_add_le16(msg, elem_addr);
+ net_buf_simple_add_le16(msg, mod_app_idx);
+
+ if (cid != CID_NVAL) {
+ net_buf_simple_add_le16(msg, cid);
+ }
+
+ net_buf_simple_add_le16(msg, mod_id);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ err = 0;
+ goto done;
+ }
+
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return cli_wait();
+ }
+}
+
+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)
+{
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
+ CID_NVAL, 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)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx,
+ mod_id, cid, status);
+}
+
+static int mod_member_list_get(uint32_t op, uint32_t expect_op, 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)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 6);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct mod_member_list_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_id = mod_id,
+ .cid = cid,
+ .members = apps,
+ .member_cnt = app_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, expect_op);
+ if (err) {
+ goto done;
+ }
+
+ BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x",
+ net_idx, addr, elem_addr);
+ BT_DBG("mod_id 0x%04x cid 0x%04x op: %x", mod_id, cid, op);
+
+ bt_mesh_model_msg_init(msg, op);
+ net_buf_simple_add_le16(msg, elem_addr);
+
+ if (cid != CID_NVAL) {
+ net_buf_simple_add_le16(msg, cid);
+ }
+
+ net_buf_simple_add_le16(msg, mod_id);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+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)
+{
+ return mod_member_list_get(OP_SIG_MOD_APP_GET, OP_SIG_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, 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)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, app_cnt);
+}
+
+static int mod_sub(uint32_t op, 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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -979,6 +1575,7 @@ static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
if (!status) {
cli_reset();
+ err = 0;
goto done;
}
@@ -988,16 +1585,16 @@ done:
return err;
}
-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)
{
return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1007,16 +1604,16 @@ int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, 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)
{
return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1026,16 +1623,16 @@ int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, 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)
{
return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
sub_addr, mod_id, CID_NVAL, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1045,9 +1642,9 @@ int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
sub_addr, mod_id, cid, status);
}
-static int mod_sub_va(u32_t op, 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)
+static int mod_sub_va(uint32_t op, 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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 22);
struct bt_mesh_msg_ctx ctx = {
@@ -1102,17 +1699,17 @@ done:
return err;
}
-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)
{
return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1122,17 +1719,17 @@ int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, 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)
{
return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1142,19 +1739,19 @@ int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, 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)
{
return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
label, mod_id, CID_NVAL, virt_addr, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1164,9 +1761,31 @@ int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
label, mod_id, cid, virt_addr, status);
}
-static int mod_pub_get(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_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)
+{
+ return mod_member_list_get(OP_MOD_SUB_GET, OP_MOD_SUB_LIST, net_idx,
+ addr, elem_addr, mod_id, CID_NVAL, status,
+ subs, 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)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, subs, sub_cnt);
+}
+
+static int mod_pub_get(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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_GET, 6);
struct bt_mesh_msg_ctx ctx = {
@@ -1217,17 +1836,17 @@ done:
return err;
}
-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)
{
return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL,
pub, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1236,9 +1855,9 @@ int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-static int mod_pub_set(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)
+static int mod_pub_set(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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_SET, 13);
struct bt_mesh_msg_ctx ctx = {
@@ -1265,7 +1884,7 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
net_buf_simple_add_le16(msg, elem_addr);
net_buf_simple_add_le16(msg, pub->addr);
- net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12)));
+ net_buf_simple_add_le16(msg, (pub->app_idx & (pub->cred_flag << 12)));
net_buf_simple_add_u8(msg, pub->ttl);
net_buf_simple_add_u8(msg, pub->period);
net_buf_simple_add_u8(msg, pub->transmit);
@@ -1294,17 +1913,17 @@ done:
return err;
}
-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)
{
return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL,
pub, 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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1313,8 +1932,8 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_SET, 5);
struct bt_mesh_msg_ctx ctx = {
@@ -1357,8 +1976,8 @@ done:
return err;
}
-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 os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1398,8 +2017,8 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_SET, 9);
struct bt_mesh_msg_ctx ctx = {
@@ -1444,8 +2063,8 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1485,12 +2104,12 @@ done:
return err;
}
-s32_t bt_mesh_cfg_cli_timeout_get(void)
+int32_t bt_mesh_cfg_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_cfg_cli_timeout_set(s32_t timeout)
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
index 57aac90a..8a085bd7 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
@@ -17,9 +17,12 @@
#include "mesh_priv.h"
#include "adv.h"
+#include "app_keys.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "transport.h"
+#include "heartbeat.h"
#include "crypto.h"
#include "access.h"
#include "beacon.h"
@@ -28,12 +31,10 @@
#include "friend.h"
#include "testing.h"
#include "settings.h"
+#include "cfg.h"
-#define DEFAULT_TTL 7
-
-static struct bt_mesh_cfg_srv *conf;
-
-static struct label labels[CONFIG_BT_MESH_LABEL_COUNT];
+void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
bool primary)
@@ -42,7 +43,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
int i;
if (net_buf_simple_tailroom(buf) <
- 4 + (elem->model_count * 2) + (elem->vnd_model_count * 2)) {
+ 4 + (elem->model_count * 2) + (elem->vnd_model_count * 4)) {
BT_ERR("Too large device composition");
return -E2BIG;
}
@@ -68,7 +69,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
static int comp_get_page_0(struct os_mbuf *buf)
{
- u16_t feat = 0;
+ uint16_t feat = 0;
const struct bt_mesh_comp *comp;
int i;
@@ -113,7 +114,7 @@ static void dev_comp_data_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u8_t page;
+ uint8_t page;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -145,7 +146,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
struct os_mbuf *buf, bool *vnd)
{
if (buf->om_len < 4) {
- u16_t id;
+ uint16_t id;
id = net_buf_simple_pull_le16(buf);
@@ -155,7 +156,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
return bt_mesh_model_find(elem, id);
} else {
- u16_t company, id;
+ uint16_t company, id;
company = net_buf_simple_pull_le16(buf);
id = net_buf_simple_pull_le16(buf);
@@ -169,25 +170,9 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
}
}
-static bool app_key_is_valid(u16_t app_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != BT_MESH_KEY_UNUSED &&
- key->app_idx == app_idx) {
- return true;
- }
- }
-
- return false;
-}
-
-static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
- u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period,
- u8_t retransmit, bool store)
+static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
+ uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period,
+ uint8_t retransmit, bool store)
{
if (!model->pub) {
return STATUS_NVAL_PUB_PARAM;
@@ -225,10 +210,20 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
- if (!bt_mesh_app_key_find(app_idx)) {
+ if (!bt_mesh_app_key_exists(app_idx)) {
return STATUS_INVALID_APPKEY;
}
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+ if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) {
+ uint8_t *uuid = bt_mesh_va_label_get(model->pub->addr);
+
+ if (uuid) {
+ bt_mesh_va_del(uuid, NULL);
+ }
+ }
+#endif
+
model->pub->addr = pub_addr;
model->pub->key = app_idx;
model->pub->cred = cred_flag;
@@ -237,12 +232,12 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
model->pub->retransmit = retransmit;
if (model->pub->update) {
- s32_t period_ms;
+ int32_t period_ms;
period_ms = bt_mesh_model_pub_period_get(model);
BT_DBG("period %u ms", (unsigned) period_ms);
- if (period_ms) {
+ if (period_ms > 0) {
k_delayed_work_submit(&model->pub->timer, period_ms);
} else {
k_delayed_work_cancel(&model->pub->timer);
@@ -256,13 +251,13 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
-u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
+uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx)
{
int i;
BT_DBG("model %p key_idx 0x%03x", model, key_idx);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -288,13 +283,13 @@ u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
return STATUS_INSUFF_RESOURCES;
}
-u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
+uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store)
{
int i;
BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -318,240 +313,88 @@ u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
return STATUS_SUCCESS;
}
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx)
+static void send_app_key_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ uint8_t status,
+ uint16_t app_idx, uint16_t net_idx)
{
- int i;
+ struct os_mbuf *msg = NET_BUF_SIMPLE(
+ BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4));
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ key_idx_pack(msg, net_idx, app_idx);
- if (key->net_idx == BT_MESH_KEY_UNUSED) {
- return key;
- }
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send App Key Status response");
}
- return NULL;
-}
-
-static u8_t app_key_set(u16_t net_idx, u16_t app_idx, const u8_t val[16],
- bool update)
-{
- struct bt_mesh_app_keys *keys;
- struct bt_mesh_app_key *key;
- struct bt_mesh_subnet *sub;
-
- BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s",
- net_idx, app_idx, update, bt_hex(val, 16));
-
- sub = bt_mesh_subnet_get(net_idx);
- if (!sub) {
- return STATUS_INVALID_NETKEY;
- }
-
- key = bt_mesh_app_key_find(app_idx);
- if (update) {
- if (!key) {
- return STATUS_INVALID_APPKEY;
- }
-
- if (key->net_idx != net_idx) {
- return STATUS_INVALID_BINDING;
- }
-
- keys = &key->keys[1];
-
- /* 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 (key->updated) {
- if (memcmp(keys->val, val, 16)) {
- return STATUS_CANNOT_UPDATE;
- } else {
- return STATUS_SUCCESS;
- }
- }
-
- key->updated = true;
- } else {
- if (key) {
- if (key->net_idx == net_idx &&
- !memcmp(key->keys[0].val, val, 16)) {
- return STATUS_SUCCESS;
- }
-
- if (key->net_idx == net_idx) {
- return STATUS_IDX_ALREADY_STORED;
- } else {
- return STATUS_INVALID_NETKEY;
- }
- }
-
- key = bt_mesh_app_key_alloc(app_idx);
- if (!key) {
- return STATUS_INSUFF_RESOURCES;
- }
-
- keys = &key->keys[0];
- }
-
- if (bt_mesh_app_id(val, &keys->id)) {
- if (update) {
- key->updated = false;
- }
-
- return STATUS_STORAGE_FAIL;
- }
-
- BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id);
-
- key->net_idx = net_idx;
- key->app_idx = app_idx;
- memcpy(keys->val, val, 16);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing AppKey persistently");
- bt_mesh_store_app_key(key);
- }
-
- return STATUS_SUCCESS;
+ os_mbuf_free_chain(msg);
}
static void app_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
+ status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data);
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, false);
- BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
static void app_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, true);
+ status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data);
BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
-struct unbind_data {
- u16_t app_idx;
- bool store;
-};
-
-static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
- bool vnd, bool primary, void *user_data)
+static void mod_app_key_del(struct bt_mesh_model *mod,
+ struct bt_mesh_elem *elem, bool vnd, bool primary,
+ void *user_data)
{
- struct unbind_data *data = user_data;
+ uint16_t *app_idx = user_data;
- mod_unbind(mod, data->app_idx, data->store);
+ mod_unbind(mod, *app_idx, true);
}
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
+static void app_key_evt(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt)
{
- struct unbind_data data = { .app_idx = key->app_idx, .store = store };
-
- BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
-
- bt_mesh_model_foreach(_mod_unbind, &data);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_app_key(key);
+ if (evt == BT_MESH_KEY_DELETED) {
+ bt_mesh_model_foreach(&mod_app_key_del, &app_idx);
}
-
- key->net_idx = BT_MESH_KEY_UNUSED;
- memset(key->keys, 0, sizeof(key->keys));
}
static void app_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- struct bt_mesh_app_key *key;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- if (!bt_mesh_subnet_get(key_net_idx)) {
- status = STATUS_INVALID_NETKEY;
- goto send_status;
- }
+ status = bt_mesh_app_key_del(key_app_idx, key_net_idx);
- key = bt_mesh_app_key_find(key_app_idx);
- if (!key) {
- /* Treat as success since the client might have missed a
- * previous response and is resending the request.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
- if (key->net_idx != key_net_idx) {
- status = STATUS_INVALID_BINDING;
- goto send_status;
- }
-
- bt_mesh_app_key_del(key, true);
- status = STATUS_SUCCESS;
-
-send_status:
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
/* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */
@@ -564,8 +407,11 @@ static void app_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_APP_KEY_LIST,
3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
- u16_t get_idx, i, prev;
- u8_t status;
+ uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT];
+ uint16_t get_idx;
+ uint8_t status;
+ ssize_t count;
+ int i;
get_idx = net_buf_simple_pull_le16(buf);
if (get_idx > 0xfff) {
@@ -577,7 +423,7 @@ static void app_key_get(struct bt_mesh_model *model,
bt_mesh_model_msg_init(msg, OP_APP_KEY_LIST);
- if (!bt_mesh_subnet_get(get_idx)) {
+ if (!bt_mesh_subnet_exists(get_idx)) {
status = STATUS_INVALID_NETKEY;
} else {
status = STATUS_SUCCESS;
@@ -590,25 +436,17 @@ static void app_key_get(struct bt_mesh_model *model,
goto send_status;
}
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != get_idx) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = key->app_idx;
- continue;
- }
-
- key_idx_pack(msg, prev, key->app_idx);
- prev = BT_MESH_KEY_UNUSED;
+ count = bt_mesh_app_keys_get(get_idx, app_idx, ARRAY_SIZE(app_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(app_idx)) {
+ count = ARRAY_SIZE(app_idx);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, app_idx[i], app_idx[i + 1]);
+ }
+
+ if (i < count) {
+ net_buf_simple_add_le16(msg, app_idx[i]);
}
send_status:
@@ -631,7 +469,7 @@ static void beacon_get(struct bt_mesh_model *model,
bt_hex(buf->om_data, buf->om_len));
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, bt_mesh_beacon_enabled());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -644,35 +482,20 @@ static void beacon_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- if (buf->om_data[0] != cfg->beacon) {
- cfg->beacon = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- if (cfg->beacon) {
- bt_mesh_beacon_enable();
- } else {
- bt_mesh_beacon_disable();
- }
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]);
goto done;
}
+ bt_mesh_beacon_set(buf->om_data[0]);
+
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -709,29 +532,20 @@ static void default_ttl_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ int err;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] <= BT_MESH_TTL_MAX && buf->om_data[0] != 0x01) {
- if (cfg->default_ttl != buf->om_data[0]) {
- cfg->default_ttl = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
- } else {
+ err = bt_mesh_default_ttl_set(buf->om_data[0]);
+ if (err) {
BT_WARN("Prohibited Default TTL value 0x%02x", buf->om_data[0]);
goto done;
}
bt_mesh_model_msg_init(msg, OP_DEFAULT_TTL_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_default_ttl_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Default TTL Status response");
@@ -772,8 +586,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
@@ -783,35 +595,8 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
return;
}
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY)) ||
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
- goto send_status;
- }
+ (void)bt_mesh_gatt_proxy_set(buf->om_data[0]);
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
-
- BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->om_data[0]);
-
- if (cfg->gatt_proxy == buf->om_data[0]) {
- goto send_status;
- }
-
- cfg->gatt_proxy = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- bt_mesh_adv_update();
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_gatt_proxy_status(model, ctx);
}
@@ -841,7 +626,6 @@ static void net_transmit_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -851,18 +635,10 @@ static void net_transmit_set(struct bt_mesh_model *model,
BT_MESH_TRANSMIT_COUNT(buf->om_data[0]),
BT_MESH_TRANSMIT_INT(buf->om_data[0]));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else {
- cfg->net_transmit = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
+ bt_mesh_net_transmit_set(buf->om_data[0]);
bt_mesh_model_msg_init(msg, OP_NET_TRANSMIT_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_net_transmit_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Network Transmit Status");
@@ -898,43 +674,18 @@ static void relay_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- bool change;
-
- if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
- change = false;
- } else {
- change = (cfg->relay != buf->om_data[0]);
- cfg->relay = buf->om_data[0];
- cfg->relay_retransmit = buf->om_data[1];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
-
- BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)",
- cfg->relay, change ? "changed" : "not changed",
- cfg->relay_retransmit,
- BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
- BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
-
- if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) {
- bt_mesh_heartbeat_send();
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]);
goto done;
}
+ (void)bt_mesh_relay_set(buf->om_data[0], buf->om_data[1]);
+
bt_mesh_model_msg_init(msg, OP_RELAY_STATUS);
net_buf_simple_add_u8(msg, bt_mesh_relay_get());
net_buf_simple_add_u8(msg, bt_mesh_relay_retransmit_get());
@@ -950,9 +701,9 @@ done:
static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
struct bt_mesh_msg_ctx *ctx,
- u16_t elem_addr, u16_t pub_addr,
+ uint16_t elem_addr, uint16_t pub_addr,
bool vnd, struct bt_mesh_model *mod,
- u8_t status, u8_t *mod_id)
+ uint8_t status, uint8_t *mod_id)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14);
@@ -964,11 +715,11 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
if (status != STATUS_SUCCESS) {
memset(net_buf_simple_add(msg, 7), 0, 7);
} else {
- u16_t idx_cred;
+ uint16_t idx_cred;
net_buf_simple_add_le16(msg, pub_addr);
- idx_cred = mod->pub->key | (u16_t)mod->pub->cred << 12;
+ idx_cred = mod->pub->key | (uint16_t)mod->pub->cred << 12;
net_buf_simple_add_le16(msg, idx_cred);
net_buf_simple_add_u8(msg, mod->pub->ttl);
net_buf_simple_add_u8(msg, mod->pub->period);
@@ -992,10 +743,10 @@ static void mod_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, pub_addr = 0;
+ uint16_t elem_addr, pub_addr = 0;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1039,11 +790,11 @@ static void mod_pub_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1097,102 +848,9 @@ send_status:
status, mod_id);
}
-struct label *get_label(u16_t index)
-{
- if (index >= ARRAY_SIZE(labels)) {
- return NULL;
- }
-
- return &labels[index];
-}
-
-#if CONFIG_BT_MESH_LABEL_COUNT > 0
-static inline void va_store(struct label *store)
-{
- atomic_set_bit(store->flags, BT_MESH_VA_CHANGED);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_label();
- }
-}
-
-static struct label *va_find(const u8_t *label_uuid,
- struct label **free_slot)
-{
- struct label *match = NULL;
- int i;
-
- if (free_slot != NULL) {
- *free_slot = NULL;
- }
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].ref == 0) {
- if (free_slot != NULL) {
- *free_slot = &labels[i];
- }
- continue;
- }
-
- if (!memcmp(labels[i].uuid, label_uuid, 16)) {
- match = &labels[i];
- }
- }
-
- return match;
-}
-
-static u8_t va_add(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update, *free_slot = NULL;
-
- update = va_find(label_uuid, &free_slot);
- if (update) {
- update->ref++;
- va_store(update);
- return 0;
- }
-
- if (!free_slot) {
- return STATUS_INSUFF_RESOURCES;
- }
-
- if (bt_mesh_virtual_addr(label_uuid, addr) < 0) {
- return STATUS_UNSPECIFIED;
- }
-
- free_slot->ref = 1;
- free_slot->addr = *addr;
- memcpy(free_slot->uuid, label_uuid, 16);
- va_store(free_slot);
-
- return STATUS_SUCCESS;
-}
-
-static u8_t va_del(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update;
-
- update = va_find(label_uuid, NULL);
- if (update) {
- update->ref--;
-
- if (addr) {
- *addr = update->addr;
- }
-
- va_store(update);
- }
-
- if (addr) {
- *addr = BT_MESH_ADDR_UNASSIGNED;
- }
-
- return STATUS_CANNOT_REMOVE;
-}
-
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
{
- u8_t *label_uuid;
+ uint8_t *label_uuid;
size_t clear_count;
int i;
@@ -1207,13 +865,13 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
continue;
}
- label_uuid = bt_mesh_label_uuid_get(mod->groups[i]);
+ label_uuid = bt_mesh_va_label_get(mod->groups[i]);
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
clear_count++;
if (label_uuid) {
- va_del(label_uuid, NULL);
+ bt_mesh_va_del(label_uuid, NULL);
} else {
BT_ERR("Label UUID not found");
}
@@ -1226,12 +884,12 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1277,85 +935,25 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &pub_addr);
- if (status == STATUS_SUCCESS) {
- status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag,
- pub_ttl, pub_period, retransmit, true);
+ status = bt_mesh_va_add(label_uuid, &pub_addr);
+ if (status != STATUS_SUCCESS) {
+ goto send_status;
+ }
+
+ status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
+ pub_period, retransmit, true);
+ if (status != STATUS_SUCCESS) {
+ bt_mesh_va_del(label_uuid, NULL);
}
send_status:
send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
status, mod_id);
}
-#else
-static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
-{
- size_t clear_count;
- int i;
-
- /* Unref stored labels related to this model */
- for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
- if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
- mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
- clear_count++;
- }
- }
-
- return clear_count;
-}
-
-static void mod_pub_va_set(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- u8_t *mod_id, status;
- struct bt_mesh_model *mod;
- struct bt_mesh_elem *elem;
- u16_t elem_addr, pub_addr = 0;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
- mod_id = net_buf_simple_pull(buf, 4);
-
- BT_DBG("elem_addr 0x%04x", elem_addr);
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- if (!mod->pub) {
- status = STATUS_NVAL_PUB_PARAM;
- goto send_status;
- }
-
- pub_addr = mod->pub->addr;
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
- status, mod_id);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_mod_sub_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- u16_t elem_addr, u16_t sub_addr, u8_t *mod_id,
+ struct bt_mesh_msg_ctx *ctx, uint8_t status,
+ uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id,
bool vnd)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9);
@@ -1386,12 +984,12 @@ static void mod_sub_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
- u16_t *entry;
+ uint8_t *mod_id;
+ uint8_t status;
+ uint16_t *entry;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1459,12 +1057,12 @@ static void mod_sub_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1522,7 +1120,7 @@ send_status:
}
static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
@@ -1537,11 +1135,11 @@ static void mod_sub_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1605,9 +1203,9 @@ static void mod_sub_del_all(struct bt_mesh_model *model,
{
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
+ uint16_t elem_addr;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1649,12 +1247,12 @@ send_status:
}
struct mod_sub_list_ctx {
- u16_t elem_idx;
+ uint16_t elem_idx;
struct os_mbuf *msg;
};
static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *ctx)
+ uint32_t depth, void *ctx)
{
struct mod_sub_list_ctx *visit = ctx;
int count = 0;
@@ -1693,7 +1291,7 @@ static void mod_sub_get(struct bt_mesh_model *model,
struct mod_sub_list_ctx visit_ctx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t addr, id;
+ uint16_t addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1748,9 +1346,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
+ struct mod_sub_list_ctx visit_ctx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t company, addr, id;
+ uint16_t company, addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1789,8 +1388,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
net_buf_simple_add_le16(msg, company);
net_buf_simple_add_le16(msg, id);
+ visit_ctx.msg = msg;
+ visit_ctx.elem_idx = mod->elem_idx;
bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
- msg);
+ &visit_ctx);
send_list:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -1802,18 +1403,17 @@ done:
}
-#if MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0
static void mod_sub_va_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *entry;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *entry;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1843,7 +1443,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &sub_addr);
+ status = bt_mesh_va_add(label_uuid, &sub_addr);
if (status != STATUS_SUCCESS) {
goto send_status;
}
@@ -1851,6 +1451,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
if (bt_mesh_model_find_group(&mod, sub_addr)) {
/* Tried to add existing subscription */
status = STATUS_SUCCESS;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1858,6 +1459,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
if (!entry) {
status = STATUS_INSUFF_RESOURCES;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1882,13 +1484,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1919,7 +1521,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
goto send_status;
}
- status = va_del(label_uuid, &sub_addr);
+ status = bt_mesh_va_del(label_uuid, &sub_addr);
if (sub_addr == BT_MESH_ADDR_UNASSIGNED) {
goto send_status;
}
@@ -1950,12 +1552,12 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
+ uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1985,11 +1587,10 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
}
if (ARRAY_SIZE(mod->groups) > 0) {
- bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
- mod_sub_clear_visitor, NULL);
-
- status = va_add(label_uuid, &sub_addr);
+ status = bt_mesh_va_add(label_uuid, &sub_addr);
if (status == STATUS_SUCCESS) {
+ bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
+ mod_sub_clear_visitor, NULL);
mod->groups[0] = sub_addr;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -2008,131 +1609,10 @@ send_status:
send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
mod_id, vnd);
}
-#else
-static void mod_sub_va_add(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_model *mod;
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_del(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_overwrite(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 18);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_net_key_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t status)
+ uint16_t idx, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3);
@@ -2152,9 +1632,8 @@ static void net_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2164,72 +1643,16 @@ static void net_key_add(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- send_net_key_status(model, ctx, idx,
- STATUS_INSUFF_RESOURCES);
- return;
- }
- }
-
- /* Check for already existing subnet */
- if (sub->net_idx == idx) {
- u8_t status;
-
- if (memcmp(buf->om_data, sub->keys[0].net, 16)) {
- status = STATUS_IDX_ALREADY_STORED;
- } else {
- status = STATUS_SUCCESS;
- }
-
- send_net_key_status(model, ctx, idx, status);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[0], buf->om_data);
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->net_idx = idx;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- bt_mesh_proxy_beacon_send(sub);
- bt_mesh_adv_update();
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+ status = bt_mesh_subnet_add(idx, buf->om_data);
+ send_net_key_status(model, ctx, idx, status);
}
static void net_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2237,80 +1660,16 @@ static void net_key_update(struct bt_mesh_model *model,
return;
}
- BT_DBG("idx 0x%04x", idx);
+ status = bt_mesh_subnet_update(idx, buf->om_data);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY);
- return;
- }
-
- /* The node shall successfully process a NetKey Update message on a
- * valid NetKeyIndex when the NetKey value is different and the Key
- * Refresh procedure has not been started, or when the NetKey value is
- * the same in Phase 1. The NetKey Update message shall generate an
- * error when the node is in Phase 2, or Phase 3.
- */
- switch (sub->kr_phase) {
- case BT_MESH_KR_NORMAL:
- if (!memcmp(buf->om_data, sub->keys[0].net, 16)) {
- return;
- }
- break;
- case BT_MESH_KR_PHASE_1:
- if (!memcmp(buf->om_data, sub->keys[1].net, 16)) {
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
- return;
- }
- /* fall through */
- case BT_MESH_KR_PHASE_2:
- case BT_MESH_KR_PHASE_3:
- send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[1], buf->om_data);
- if (!err && ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND)))) {
- err = friend_cred_update(sub);
- }
-
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_1;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- bt_mesh_net_beacon_update(sub);
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
-}
-
-static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg)
-{
- BT_DBG("");
-
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_pub.count = 0;
- cfg->hb_pub.ttl = 0;
- cfg->hb_pub.period = 0;
-
- k_delayed_work_cancel(&cfg->hb_pub.timer);
+ send_net_key_status(model, ctx, idx, status);
}
static void net_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t del_idx;
- u8_t status;
+ uint16_t del_idx;
del_idx = net_buf_simple_pull_le16(buf);
if (del_idx > 0xfff) {
@@ -2320,28 +1679,18 @@ static void net_key_del(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", del_idx);
- sub = bt_mesh_subnet_get(del_idx);
- if (!sub) {
- /* This could be a retry of a previous attempt that had its
- * response lost, so pretend that it was a success.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
/* The key that the message was encrypted with cannot be removed.
* The NetKey List must contain a minimum of one NetKey.
*/
if (ctx->net_idx == del_idx) {
- status = STATUS_CANNOT_REMOVE;
- goto send_status;
+ send_net_key_status(model, ctx, del_idx,
+ STATUS_CANNOT_REMOVE);
+ return;
}
- bt_mesh_subnet_del(sub, true);
- status = STATUS_SUCCESS;
+ bt_mesh_subnet_del(del_idx);
-send_status:
- send_net_key_status(model, ctx, del_idx, status);
+ send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS);
}
static void net_key_get(struct bt_mesh_model *model,
@@ -2351,29 +1700,23 @@ static void net_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_NET_KEY_LIST,
IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
- u16_t prev, i;
+ uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT];
+ ssize_t count;
+ int i;
bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST);
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = sub->net_idx;
- continue;
- }
-
- key_idx_pack(msg, prev, sub->net_idx);
- prev = BT_MESH_KEY_UNUSED;
+ count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(net_idx)) {
+ count = ARRAY_SIZE(net_idx);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, net_idx[i], net_idx[i + 1]);
+ }
+
+ if (i < count) {
+ net_buf_simple_add_le16(msg, net_idx[i]);
}
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -2383,14 +1726,32 @@ static void net_key_get(struct bt_mesh_model *model,
os_mbuf_free_chain(msg);
}
+static void send_node_id_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ uint8_t status,
+ uint16_t net_idx, uint8_t node_id)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
+
+ bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ net_buf_simple_add_le16(msg, net_idx);
+ net_buf_simple_add_u8(msg, node_id);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send Node Identity Status");
+ }
+
+ os_mbuf_free_chain(msg);
+}
+
static void node_identity_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ enum bt_mesh_feat_state node_id;
+ uint8_t status;
+ uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -2399,39 +1760,20 @@ static void node_identity_get(struct bt_mesh_model *model,
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
- goto done;
+ return;
}
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
+ status = bt_mesh_subnet_node_id_get(idx, &node_id);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- node_id = 0x00;
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- node_id = sub->node_id;
- }
-
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
- }
-
-done:
- os_mbuf_free_chain(msg);
+ send_node_id_status(model, ctx, status, idx, node_id);
}
static void node_identity_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ uint8_t node_id, status;
+ uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -2440,51 +1782,36 @@ static void node_identity_set(struct bt_mesh_model *model,
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
BT_WARN("Invalid NetKeyIndex 0x%04x", idx);
- goto done;
+ return;
}
node_id = net_buf_simple_pull_u8(buf);
if (node_id != 0x00 && node_id != 0x01) {
BT_WARN("Invalid Node ID value 0x%02x", node_id);
- goto done;
+ return;
}
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- net_buf_simple_add_le16(msg, idx);
-
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) {
- if (node_id) {
- bt_mesh_proxy_identity_start(sub);
- } else {
- bt_mesh_proxy_identity_stop(sub);
- }
- bt_mesh_adv_update();
- }
-
- net_buf_simple_add_u8(msg, sub->node_id);
+ status = bt_mesh_subnet_node_id_set(idx, node_id);
+ if (status == STATUS_INVALID_NETKEY) {
+ send_node_id_status(model, ctx, status, idx,
+ BT_MESH_NODE_IDENTITY_STOPPED);
+ return;
}
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
+ if (status == STATUS_FEAT_NOT_SUPP) {
+ /* Should return success, even if feature isn't supported: */
+ send_node_id_status(model, ctx, STATUS_SUCCESS, idx,
+ BT_MESH_NODE_IDENTITY_NOT_SUPPORTED);
+ return;
}
-done:
- os_mbuf_free_chain(msg);
-
+ send_node_id_status(model, ctx, status, idx, node_id);
}
static void create_mod_app_status(struct os_mbuf *msg,
struct bt_mesh_model *mod, bool vnd,
- u16_t elem_addr, u16_t app_idx,
- u8_t status, u8_t *mod_id)
+ uint16_t elem_addr, uint16_t app_idx,
+ uint8_t status, uint8_t *mod_id)
{
bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS);
@@ -2504,10 +1831,10 @@ static void mod_app_bind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2565,10 +1892,10 @@ static void mod_app_unbind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2626,8 +1953,8 @@ static void mod_app_get(struct bt_mesh_model *model,
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
- u16_t elem_addr;
+ uint8_t *mod_id, status;
+ uint16_t elem_addr;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2694,6 +2021,8 @@ static void node_reset(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset};
+
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0);
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -2710,7 +2039,15 @@ static void node_reset(struct bt_mesh_model *model,
BT_ERR("Unable to send Node Reset Status");
}
- bt_mesh_reset();
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ bt_mesh_reset();
+ return;
+ }
+
+ /* If the response goes to a proxy node, we'll wait for the sending to
+ * complete before moving on.
+ */
+ bt_mesh_proxy_on_idle(&proxy_idle);
os_mbuf_free_chain(msg);
}
@@ -2718,10 +2055,9 @@ static void send_friend_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS);
- net_buf_simple_add_u8(msg, cfg->frnd);
+ net_buf_simple_add_u8(msg, bt_mesh_friend_get());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Friend Status");
@@ -2744,8 +2080,6 @@ static void friend_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
@@ -2755,34 +2089,8 @@ static void friend_set(struct bt_mesh_model *model,
return;
}
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
+ (void)bt_mesh_friend_set(buf->om_data[0]);
- BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->om_data[0]);
-
- if (cfg->frnd == buf->om_data[0]) {
- goto send_status;
- }
-
- if (MYNEWT_VAL(BLE_MESH_FRIEND)) {
- cfg->frnd = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
- }
- }
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_friend_status(model, ctx);
}
@@ -2792,8 +2100,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5);
struct bt_mesh_friend *frnd;
- u16_t lpn_addr;
- s32_t timeout;
+ uint16_t lpn_addr;
+ int32_t timeout;
lpn_addr = net_buf_simple_pull_le16(buf);
@@ -2823,9 +2131,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
timeout = k_delayed_work_remaining_get(&frnd->timer) / 100;
send_rsp:
- net_buf_simple_add_u8(msg, timeout);
- net_buf_simple_add_u8(msg, timeout >> 8);
- net_buf_simple_add_u8(msg, timeout >> 16);
+ net_buf_simple_add_le24(msg, timeout);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send LPN PollTimeout Status");
@@ -2837,7 +2143,7 @@ done:
static void send_krp_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t phase, u8_t status)
+ uint16_t idx, uint8_t phase, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4);
@@ -2857,8 +2163,8 @@ static void send_krp_status(struct bt_mesh_model *model,
static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
+ uint8_t kr_phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2868,21 +2174,16 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
- } else {
- send_krp_status(model, ctx, idx, sub->kr_phase,
- STATUS_SUCCESS);
- }
+ status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase);
+
+ send_krp_status(model, ctx, idx, kr_phase, status);
}
static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u8_t phase;
- u16_t idx;
+ uint8_t phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
phase = net_buf_simple_pull_u8(buf);
@@ -2892,56 +2193,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
return;
}
- BT_DBG("idx 0x%04x transition 0x%02x", idx, phase);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
+ status = bt_mesh_subnet_kr_phase_set(idx, &phase);
+ if (status == STATUS_CANNOT_UPDATE) {
+ BT_ERR("Invalid kr phase transition 0x%02x", phase);
return;
}
- BT_DBG("%u -> %u", sub->kr_phase, phase);
-
- if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 ||
- (sub->kr_phase == BT_MESH_KR_NORMAL &&
- phase == BT_MESH_KR_PHASE_2)) {
- BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase);
- return;
- }
-
- if (sub->kr_phase == BT_MESH_KR_PHASE_1 &&
- phase == BT_MESH_KR_PHASE_2) {
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- sub->kr_flag = 1;
- bt_mesh_net_beacon_update(sub);
- } else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 ||
- sub->kr_phase == BT_MESH_KR_PHASE_2) &&
- phase == BT_MESH_KR_PHASE_3) {
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(ctx->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- sub->kr_flag = 0;
- bt_mesh_net_beacon_update(sub);
- }
-
- send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS);
+ send_krp_status(model, ctx, idx, phase, status);
}
-static u8_t hb_log(u16_t val)
-{
- if (!val) {
- return 0x00;
- } else if (val == 0xffff) {
- return 0xff;
- } else {
- return 32 - __builtin_clz(val);
- }
-}
-
-static u8_t hb_pub_count_log(u16_t val)
+static uint8_t hb_pub_count_log(uint16_t val)
{
if (!val) {
return 0x00;
@@ -2954,32 +2215,20 @@ static u8_t hb_pub_count_log(u16_t val)
}
}
-static u16_t hb_pwr2(u8_t val, u8_t sub)
-{
- if (!val) {
- return 0x0000;
- } else if (val == 0xff || val == 0x11) {
- return 0xffff;
- } else {
- return (1 << (val - sub));
- }
-}
-
struct hb_pub_param {
- u16_t dst;
- u8_t count_log;
- u8_t period_log;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
+ uint16_t dst;
+ uint8_t count_log;
+ uint8_t period_log;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx;
} __packed;
static void hb_pub_send_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- struct hb_pub_param *orig_msg)
+ struct bt_mesh_msg_ctx *ctx, uint8_t status,
+ const struct bt_mesh_hb_pub *pub)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
@@ -2987,20 +2236,13 @@ static void hb_pub_send_status(struct bt_mesh_model *model,
net_buf_simple_add_u8(msg, status);
- if (orig_msg) {
- memcpy(net_buf_simple_add(msg, sizeof(*orig_msg)), orig_msg,
- sizeof(*orig_msg));
- goto send;
- }
+ net_buf_simple_add_le16(msg, pub->dst);
+ net_buf_simple_add_u8(msg, hb_pub_count_log(pub->count));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(pub->period));
+ net_buf_simple_add_u8(msg, pub->ttl);
+ net_buf_simple_add_le16(msg, pub->feat);
+ net_buf_simple_add_le16(msg, pub->net_idx);
- net_buf_simple_add_le16(msg, cfg->hb_pub.dst);
- net_buf_simple_add_u8(msg, hb_pub_count_log(cfg->hb_pub.count));
- net_buf_simple_add_u8(msg, cfg->hb_pub.period);
- net_buf_simple_add_u8(msg, cfg->hb_pub.ttl);
- net_buf_simple_add_le16(msg, cfg->hb_pub.feat);
- net_buf_simple_add_le16(msg, cfg->hb_pub.net_idx);
-
-send:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Heartbeat Publication Status");
}
@@ -3012,9 +2254,13 @@ static void heartbeat_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_pub pub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
+ bt_mesh_hb_pub_get(&pub);
+
+ hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub);
}
static void heartbeat_pub_set(struct bt_mesh_model *model,
@@ -3022,27 +2268,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct hb_pub_param *param = (void *)buf->om_data;
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t dst, feat, idx;
- u8_t status;
+ struct bt_mesh_hb_pub pub;
+ uint8_t status;
BT_DBG("src 0x%04x", ctx->addr);
- dst = sys_le16_to_cpu(param->dst);
+ pub.dst = sys_le16_to_cpu(param->dst);
+ pub.count = bt_mesh_hb_pwr2(param->count_log);
+ pub.period = bt_mesh_hb_pwr2(param->period_log);
+ pub.ttl = param->ttl;
+ pub.feat = sys_le16_to_cpu(param->feat);
+ pub.net_idx = sys_le16_to_cpu(param->net_idx);
+
/* All other address types but virtual are valid */
- if (BT_MESH_ADDR_IS_VIRTUAL(dst)) {
+ if (BT_MESH_ADDR_IS_VIRTUAL(pub.dst)) {
status = STATUS_INVALID_ADDRESS;
- goto failed;
+ goto rsp;
}
if (param->count_log > 0x11 && param->count_log != 0xff) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->period_log > 0x10) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) {
@@ -3050,84 +2301,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
return;
}
- feat = sys_le16_to_cpu(param->feat);
-
- idx = sys_le16_to_cpu(param->net_idx);
- if (idx > 0xfff) {
- BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+ if (pub.net_idx > 0xfff) {
+ BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx);
return;
}
- if (!bt_mesh_subnet_get(idx)) {
- status = STATUS_INVALID_NETKEY;
- goto failed;
- }
-
- cfg->hb_pub.dst = dst;
- cfg->hb_pub.period = param->period_log;
- cfg->hb_pub.feat = feat & BT_MESH_FEAT_SUPPORTED;
- cfg->hb_pub.net_idx = idx;
-
- if (dst == BT_MESH_ADDR_UNASSIGNED) {
- hb_pub_disable(cfg);
- } else {
- /* 2^(n-1) */
- cfg->hb_pub.count = hb_pwr2(param->count_log, 1);
- cfg->hb_pub.ttl = param->ttl;
-
- BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000);
-
- /* The first Heartbeat message shall be published as soon
- * as possible after the Heartbeat Publication Period state
- * has been configured for periodic publishing.
- */
- if (param->period_log && param->count_log) {
- k_work_submit(&cfg->hb_pub.timer.work);
- } else {
- k_delayed_work_cancel(&cfg->hb_pub.timer);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_hb_pub();
- }
-
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
-
- return;
-
-failed:
- hb_pub_send_status(model, ctx, status, param);
+ status = bt_mesh_hb_pub_set(&pub);
+rsp:
+ hb_pub_send_status(model, ctx, status, &pub);
}
static void hb_sub_send_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status)
+ struct bt_mesh_msg_ctx *ctx,
+ const struct bt_mesh_hb_sub *sub)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t period;
- s64_t uptime;
-
- BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
-
- uptime = k_uptime_get();
- if (uptime > cfg->hb_sub.expiry) {
- period = 0;
- } else {
- period = (cfg->hb_sub.expiry - uptime) / 1000;
- }
+ BT_DBG("src 0x%04x ", ctx->addr);
bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_STATUS);
- net_buf_simple_add_u8(msg, status);
-
- net_buf_simple_add_le16(msg, cfg->hb_sub.src);
- net_buf_simple_add_le16(msg, cfg->hb_sub.dst);
-
- net_buf_simple_add_u8(msg, hb_log(period));
- net_buf_simple_add_u8(msg, hb_log(cfg->hb_sub.count));
- net_buf_simple_add_u8(msg, cfg->hb_sub.min_hops);
- net_buf_simple_add_u8(msg, cfg->hb_sub.max_hops);
+ net_buf_simple_add_u8(msg, STATUS_SUCCESS);
+ net_buf_simple_add_le16(msg, sub->src);
+ net_buf_simple_add_le16(msg, sub->dst);
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->remaining));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->count));
+ net_buf_simple_add_u8(msg, sub->min_hops);
+ net_buf_simple_add_u8(msg, sub->max_hops);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -3141,92 +2340,58 @@ static void heartbeat_sub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_sub sub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
+
+ hb_sub_send_status(model, ctx, &sub);
}
static void heartbeat_sub_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t sub_src, sub_dst;
- u8_t sub_period;
- s32_t period_ms;
+ uint8_t period_log, status;
+ struct bt_mesh_hb_sub sub;
+ uint16_t sub_src, sub_dst;
+ uint32_t period;
BT_DBG("src 0x%04x", ctx->addr);
sub_src = net_buf_simple_pull_le16(buf);
sub_dst = net_buf_simple_pull_le16(buf);
- sub_period = net_buf_simple_pull_u8(buf);
+ period_log = net_buf_simple_pull_u8(buf);
BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x",
- sub_src, sub_dst, sub_period);
+ sub_src, sub_dst, period_log);
- if (sub_src != BT_MESH_ADDR_UNASSIGNED &&
- !BT_MESH_ADDR_IS_UNICAST(sub_src)) {
- BT_WARN("Prohibited source address");
+ if (period_log > 0x11) {
+ BT_WARN("Prohibited subscription period 0x%02x", period_log);
return;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(sub_dst) || BT_MESH_ADDR_IS_RFU(sub_dst) ||
- (BT_MESH_ADDR_IS_UNICAST(sub_dst) &&
- sub_dst != bt_mesh_primary_addr())) {
- BT_WARN("Prohibited destination address");
- return;
- }
+ period = bt_mesh_hb_pwr2(period_log);
- if (sub_period > 0x11) {
- BT_WARN("Prohibited subscription period 0x%02x", sub_period);
- return;
- }
-
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED ||
- sub_period == 0x00) {
- /* Only an explicit address change to unassigned should
- * trigger clearing of the values according to
- * MESH/NODE/CFG/HBS/BV-02-C.
+ status = bt_mesh_hb_sub_set(sub_src, sub_dst, period);
+ if (status != STATUS_SUCCESS) {
+ /* All errors are caused by invalid packets, which should be
+ * ignored.
*/
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED) {
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- }
-
- period_ms = 0;
- } else {
- cfg->hb_sub.src = sub_src;
- cfg->hb_sub.dst = sub_dst;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- period_ms = hb_pwr2(sub_period, 1) * 1000;
+ return;
}
- /* Let the transport layer know it needs to handle this address */
- bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst);
-
- BT_DBG("period_ms %u", (unsigned) period_ms);
-
- if (period_ms) {
- cfg->hb_sub.expiry = k_uptime_get() + period_ms;
- } else {
- cfg->hb_sub.expiry = 0;
- }
-
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
/* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after
* disabling subscription, but 0x00 for subsequent Get requests.
*/
- if (!period_ms) {
- cfg->hb_sub.min_hops = 0;
+ if (!period_log) {
+ sub.min_hops = BT_MESH_TTL_MAX;
}
+
+ hb_sub_send_status(model, ctx, &sub);
}
const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
@@ -3280,58 +2445,9 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
BT_MESH_MODEL_OP_END,
};
-static void hb_publish(struct ble_npl_event *work)
-{
- struct bt_mesh_cfg_srv *cfg = ble_npl_event_get_arg(work);
- struct bt_mesh_subnet *sub;
- u16_t period_ms;
-
- BT_DBG("hb_pub.count: %u", cfg->hb_pub.count);
-
- sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
- if (!sub) {
- BT_ERR("No matching subnet for idx 0x%02x",
- cfg->hb_pub.net_idx);
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- return;
- }
-
- if (cfg->hb_pub.count == 0) {
- return;
- }
-
- period_ms = hb_pwr2(cfg->hb_pub.period, 1) * 1000;
- if (period_ms && cfg->hb_pub.count > 1) {
- k_delayed_work_submit(&cfg->hb_pub.timer, period_ms);
- }
-
- bt_mesh_heartbeat_send();
-
- if (cfg->hb_pub.count != 0xffff) {
- cfg->hb_pub.count--;
- }
-}
-
-static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
-{
- if (cfg->relay > 0x02) {
- return false;
- }
-
- if (cfg->beacon > 0x01) {
- return false;
- }
-
- if (cfg->default_ttl > BT_MESH_TTL_MAX) {
- return false;
- }
-
- return true;
-}
-
static int cfg_srv_init(struct bt_mesh_model *model)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ bt_mesh_app_key_cb_list[0] = app_key_evt;
BT_DBG("");
@@ -3340,43 +2456,12 @@ static int cfg_srv_init(struct bt_mesh_model *model)
return -EINVAL;
}
- if (!cfg) {
- BT_ERR("No Configuration Server context provided");
- return -EINVAL;
- }
-
- if (!conf_is_valid(cfg)) {
- BT_ERR("Invalid values in configuration");
- return -EINVAL;
- }
-
/*
* Configuration Model security is device-key based and only the local
* device-key is allowed to access this model.
*/
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
- if (!(MYNEWT_VAL(BLE_MESH_RELAY))) {
- cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_FRIEND))) {
- cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED;
- }
-
- k_delayed_work_init(&cfg->hb_pub.timer, hb_publish);
- k_delayed_work_add_arg(&cfg->hb_pub.timer, cfg);
- cfg->hb_pub.net_idx = BT_MESH_KEY_UNUSED;
- cfg->hb_sub.expiry = 0;
-
- cfg->model = model;
-
- conf = cfg;
-
return 0;
}
@@ -3401,8 +2486,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
if (clear_count) {
bt_mesh_store_mod_sub(mod);
}
-
- bt_mesh_model_data_store(mod, vnd, NULL, 0);
}
if (mod->cb && mod->cb->reset) {
@@ -3412,208 +2495,5 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
void bt_mesh_cfg_reset(void)
{
- struct bt_mesh_cfg_srv *cfg = conf;
- int i;
-
- BT_DBG("");
-
- if (!cfg) {
- return;
- }
-
- bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED);
-
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.expiry = 0;
-
- /* Delete all net keys, which also takes care of all app keys which
- * are associated with each net key.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_subnet_del(sub, true);
- }
- }
-
bt_mesh_model_foreach(mod_reset, NULL);
-
- memset(labels, 0, sizeof(labels));
-}
-
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat)
-{
- struct bt_mesh_cfg_srv *cfg = conf;
-
- if (!cfg) {
- BT_WARN("No configuaration server context available");
- return;
- }
-
- if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
- BT_WARN("No subscription for received heartbeat");
- return;
- }
-
- if (k_uptime_get() > cfg->hb_sub.expiry) {
- BT_WARN("Heartbeat subscription period expired");
- return;
- }
-
- cfg->hb_sub.min_hops = min(cfg->hb_sub.min_hops, hops);
- cfg->hb_sub.max_hops = max(cfg->hb_sub.max_hops, hops);
-
- if (cfg->hb_sub.count < 0xffff) {
- cfg->hb_sub.count++;
- }
-
- BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
- dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
- cfg->hb_sub.count);
-
- if (cfg->hb_sub.func) {
- cfg->hb_sub.func(hops, feat);
- }
-}
-
-u8_t bt_mesh_net_transmit_get(void)
-{
- if (conf) {
- return conf->net_transmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_relay_get(void)
-{
- if (conf) {
- return conf->relay;
- }
-
- return BT_MESH_RELAY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_friend_get(void)
-{
- BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd);
-
- if (conf) {
- return conf->frnd;
- }
-
- return BT_MESH_FRIEND_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_relay_retransmit_get(void)
-{
- if (conf) {
- return conf->relay_retransmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_beacon_get(void)
-{
- if (conf) {
- return conf->beacon;
- }
-
- return BT_MESH_BEACON_DISABLED;
-}
-
-u8_t bt_mesh_gatt_proxy_get(void)
-{
- if (conf) {
- return conf->gatt_proxy;
- }
-
- return BT_MESH_GATT_PROXY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_default_ttl_get(void)
-{
- if (conf) {
- return conf->default_ttl;
- }
-
- return DEFAULT_TTL;
-}
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr)
-{
- int i;
-
- BT_DBG("addr 0x%04x", addr);
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].addr == addr) {
- BT_DBG("Found Label UUID for 0x%04x: %s", addr,
- bt_hex(labels[i].uuid, 16));
- return labels[i].uuid;
- }
- }
-
- BT_WARN("No matching Label UUID for 0x%04x", addr);
-
- return NULL;
-}
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
-{
- if (!conf) {
- return NULL;
- }
-
- return &conf->hb_pub;
-}
-
-void bt_mesh_hb_pub_disable(void)
-{
- if (conf) {
- hb_pub_disable(conf);
- }
-}
-
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
-{
- return conf;
-}
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
-{
- int i;
-
- BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
-
- if (conf && conf->hb_pub.net_idx == sub->net_idx) {
- hb_pub_disable(conf);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_store_hb_pub();
- }
- }
-
- /* Delete any app keys bound to this NetKey index */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx == sub->net_idx) {
- bt_mesh_app_key_del(key, store);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_clear_net_idx(sub->net_idx);
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_subnet(sub);
- }
-
- memset(sub, 0, sizeof(*sub));
- sub->net_idx = BT_MESH_KEY_UNUSED;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
index b6a0ba21..3111a6ef 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
@@ -24,8 +24,8 @@
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16])
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
@@ -48,8 +48,8 @@ int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
return 0;
}
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16])
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16])
{
int err;
@@ -61,14 +61,14 @@ int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
}
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16])
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16])
{
struct bt_mesh_sg sg[3];
- u8_t salt[16];
- u8_t out[16];
- u8_t t[16];
- u8_t pad;
+ uint8_t salt[16];
+ uint8_t out[16];
+ uint8_t t[16];
+ uint8_t pad;
int err;
BT_DBG("n %s", bt_hex(n, 16));
@@ -126,11 +126,11 @@ int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
return 0;
}
-int bt_mesh_k3(const u8_t n[16], u8_t out[8])
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8])
{
- u8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk3", tmp);
@@ -153,11 +153,11 @@ int bt_mesh_k3(const u8_t n[16], u8_t out[8])
return 0;
}
-int bt_mesh_k4(const u8_t n[16], u8_t out[1])
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1])
{
- u8_t id6[] = { 'i', 'd', '6', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id6[] = { 'i', 'd', '6', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk4", tmp);
@@ -180,10 +180,10 @@ int bt_mesh_k4(const u8_t n[16], u8_t out[1])
return 0;
}
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
{
const char *id128 = "id128\x01";
- u8_t salt[16];
+ uint8_t salt[16];
int err;
err = bt_mesh_s1(s, salt);
@@ -194,326 +194,8 @@ int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
return bt_mesh_k1(n, 16, salt, id128, out);
}
-static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *enc_msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16];
- u16_t last_blk, blk_cnt;
- size_t i, j;
- int err;
-
- if (msg_len < 1 || aad_len >= 0xff00) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, last_blk);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
- } else {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < 16; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, 16);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
- }
-
- if (memcmp(mic, enc_msg + msg_len, mic_size)) {
- return -EBADMSG;
- }
-
- return 0;
-}
-
-static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16];
- u16_t blk_cnt, last_blk;
- size_t i, j;
- int err;
-
- 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) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
- } else {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_N */
- for (i = 0; i < 16; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
-
- }
- }
-
- memcpy(out_msg + msg_len, mic, mic_size);
-
- return 0;
-}
-
-static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x03;
@@ -538,8 +220,8 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x00;
@@ -564,11 +246,11 @@ static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16])
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16])
{
- u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
- u8_t tmp[16];
+ uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
+ uint8_t tmp[16];
int err, i;
BT_DBG("IVIndex %u, PrivacyKey %s", (unsigned) iv_index,
@@ -591,11 +273,11 @@ int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
return 0;
}
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
int err;
BT_DBG("IVIndex %u EncKey %s mic_len %u", (unsigned) iv_index,
@@ -610,7 +292,7 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- err = bt_mesh_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ err = bt_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
if (!err) {
net_buf_simple_add(buf, mic_len);
@@ -619,11 +301,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
return err;
}
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
BT_DBG("PDU (%u bytes) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index,
@@ -639,118 +321,74 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
buf->om_len -= mic_len;
- return bt_mesh_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ return bt_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
}
-static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
- u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
+static void create_app_nonce(uint8_t nonce[13],
+ const struct bt_mesh_app_crypto_ctx *ctx)
{
- if (dev_key) {
+ if (ctx->dev_key) {
nonce[0] = 0x02;
} else {
nonce[0] = 0x01;
}
- sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]);
+ sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]);
- sys_put_be16(src, &nonce[5]);
- sys_put_be16(dst, &nonce[7]);
+ sys_put_be16(ctx->src, &nonce[5]);
+ sys_put_be16(ctx->dst, &nonce[7]);
- sys_put_be32(iv_index, &nonce[9]);
+ sys_put_be32(ctx->iv_index, &nonce[9]);
}
-static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf)
{
- u8_t nonce[13];
+ int err;
+ uint8_t nonce[13];
BT_DBG("AppKey %s", bt_hex(key, 16));
- BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
- BT_DBG("seq_num 0x%08x iv_index 0x%08x", (unsigned) seq_num,
- (unsigned) iv_index);
+ BT_DBG("dev_key %u src 0x%04x dst 0x%04x", ctx->dev_key, ctx->src,
+ ctx->dst);
+ BT_DBG("seq_num 0x%08x iv_index 0x%08x", ctx->seq_num, ctx->iv_index);
BT_DBG("Clear: %s", bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, buf->om_data,
- APP_MIC_LEN(aszmic));
-}
+ err = bt_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, buf->om_data,
+ APP_MIC_LEN(ctx->aszmic));
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- int err;
-
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
if (!err) {
+ net_buf_simple_add(buf, APP_MIC_LEN(ctx->aszmic));
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
}
return err;
}
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out)
{
+ uint8_t nonce[13];
int err;
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
-
- if (!err) {
- net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
- BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
- }
-
- return err;
-}
-
-static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst,
- u32_t seq_num, u32_t iv_index)
-{
- u8_t nonce[13];
-
BT_DBG("EncData (len %u) %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("AppKey %s", bt_hex(key, 16));
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, out->om_data,
- APP_MIC_LEN(aszmic));
-}
-
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- return mesh_app_decrypt(key, dev_key, aszmic, buf, buf,
- ad, src, dst, seq_num, iv_index);
-}
-
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
-{
- int err;
-
- err = mesh_app_decrypt(key, dev_key, aszmic, buf, out,
- ad, src, dst, seq_num, iv_index);
+ err = bt_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, out->om_data,
+ APP_MIC_LEN(ctx->aszmic));
if (!err) {
net_buf_simple_add(out, buf->om_len);
}
@@ -759,7 +397,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
}
/* reversed, 8-bit, poly=0x07 */
-static const u8_t crc_table[256] = {
+static const uint8_t crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
@@ -801,9 +439,9 @@ static const u8_t crc_table[256] = {
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len)
{
- u8_t fcs = 0xff;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -814,11 +452,11 @@ u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
return 0xff - fcs;
}
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs)
{
- const u8_t *data = buf->om_data;
- u16_t data_len = buf->om_len;
- u8_t fcs = 0xff;
+ const uint8_t *data = buf->om_data;
+ uint16_t data_len = buf->om_len;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -827,10 +465,10 @@ bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
return crc_table[fcs ^ received_fcs] == 0xcf;
}
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr)
{
- u8_t salt[16];
- u8_t tmp[16];
+ uint8_t salt[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_s1("vtad", salt);
@@ -848,21 +486,21 @@ int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
return 0;
}
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16])
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16])
{
- const u8_t conf_salt_key[16] = { 0 };
+ const uint8_t conf_salt_key[16] = { 0 };
return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
}
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16])
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16])
{
return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
}
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16])
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16])
{
struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
@@ -873,23 +511,23 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
}
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25])
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25])
{
- return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8])
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8])
{
- return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[8], u32_t iv_index,
- u8_t auth[8])
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[8], uint32_t iv_index,
+ uint8_t auth[8])
{
- u8_t msg[13], tmp[16];
+ uint8_t msg[13], tmp[16];
int err;
BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
index 745cf324..637d13e7 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
@@ -15,81 +15,81 @@ struct bt_mesh_sg {
size_t len;
};
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16]);
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16]);
-static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
- size_t len, u8_t mac[16])
+static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
+ size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
-static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
+static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
{
- const u8_t zero[16] = { 0 };
+ const uint8_t zero[16] = { 0 };
return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
}
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16]);
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16]);
#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
({ \
- const u8_t salt[16] = salt_str; \
+ const uint8_t salt[16] = salt_str; \
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
})
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]);
-int bt_mesh_k3(const u8_t n[16], u8_t out[8]);
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]);
-int bt_mesh_k4(const u8_t n[16], u8_t out[1]);
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]);
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]);
-static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
- u8_t resolving_key[16])
+static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16],
+ uint8_t resolving_key[16])
{
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
}
-static inline int bt_mesh_identity_key(const u8_t net_key[16],
- u8_t identity_key[16])
+static inline int bt_mesh_identity_key(const uint8_t net_key[16],
+ uint8_t identity_key[16])
{
return bt_mesh_id128(net_key, "nkik", identity_key);
}
-static inline int bt_mesh_beacon_key(const u8_t net_key[16],
- u8_t beacon_key[16])
+static inline int bt_mesh_beacon_key(const uint8_t net_key[16],
+ uint8_t beacon_key[16])
{
return bt_mesh_id128(net_key, "nkbk", beacon_key);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[16], u32_t iv_index,
- u8_t auth[8]);
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[16], uint32_t iv_index,
+ uint8_t auth[8]);
-static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
+static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1])
{
return bt_mesh_k4(app_key, app_id);
}
-static inline int bt_mesh_session_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t session_key[16])
+static inline int bt_mesh_session_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t session_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
}
-static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t nonce[13])
+static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t nonce[13])
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
@@ -100,19 +100,19 @@ static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
return err;
}
-static inline int bt_mesh_dev_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t dev_key[16])
+static inline int bt_mesh_dev_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t dev_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
}
-static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
- const u8_t prov_rand[16],
- const u8_t dev_rand[16],
- u8_t prov_salt[16])
+static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16],
+ const uint8_t prov_rand[16],
+ const uint8_t dev_rand[16],
+ uint8_t prov_salt[16])
{
- const u8_t prov_salt_key[16] = { 0 };
+ const uint8_t prov_salt_key[16] = { 0 };
struct bt_mesh_sg sg[] = {
{ conf_salt, 16 },
{ prov_rand, 16 },
@@ -122,49 +122,50 @@ static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16]);
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16]);
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
+struct bt_mesh_app_crypto_ctx {
+ bool dev_key;
+ uint8_t aszmic;
+ uint16_t src;
+ uint16_t dst;
+ uint32_t seq_num;
+ uint32_t iv_index;
+ const uint8_t *ad;
+};
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf);
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out);
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, struct os_mbuf*out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index);
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len);
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs);
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs);
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr);
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]);
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16]);
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16]);
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16]);
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16]);
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25]);
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25]);
-
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8]);
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8]);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
index ee615ae9..012afbbb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
@@ -115,57 +115,23 @@
#define STATUS_UNSPECIFIED 0x10
#define STATUS_INVALID_BINDING 0x11
-enum {
- BT_MESH_VA_CHANGED, /* Label information changed */
-};
-
-struct label {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
- atomic_t flags[1];
-};
-
void bt_mesh_cfg_reset(void);
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
-
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
-
-struct label *get_label(u16_t index);
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr);
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
-void bt_mesh_hb_pub_disable(void);
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
-
-u8_t bt_mesh_net_transmit_get(void);
-u8_t bt_mesh_relay_get(void);
-u8_t bt_mesh_friend_get(void);
-u8_t bt_mesh_relay_retransmit_get(void);
-u8_t bt_mesh_beacon_get(void);
-u8_t bt_mesh_gatt_proxy_get(void);
-u8_t bt_mesh_default_ttl_get(void);
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
-
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx);
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
static inline void key_idx_pack(struct os_mbuf *buf,
- u16_t idx1, u16_t idx2)
+ uint16_t idx1, uint16_t idx2)
{
net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
net_buf_simple_add_u8(buf, idx2 >> 4);
}
static inline void key_idx_unpack(struct os_mbuf *buf,
- u16_t *idx1, u16_t *idx2)
+ uint16_t *idx1, uint16_t *idx2)
{
*idx1 = sys_get_le16(&buf->om_data[0]) & 0xfff;
*idx2 = sys_get_le16(&buf->om_data[1]) >> 4;
- net_buf_simple_pull(buf, 3);
+ net_buf_simple_pull_mem(buf, 3);
}
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
index 9056a865..9a83c87f 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
@@ -7,7 +7,7 @@
*/
#include "syscfg/syscfg.h"
-#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG
+#define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -21,10 +21,12 @@
#include "crypto.h"
#include "adv.h"
#include "net.h"
+#include "app_keys.h"
#include "transport.h"
#include "access.h"
#include "foundation.h"
#include "friend.h"
+#include "subnet.h"
/* We reserve one extra buffer for each friendship, since we need to be able
* to resend the last sent PDU, which sits separately outside of the queue.
@@ -48,20 +50,20 @@ static struct os_mempool friend_buf_mempool;
#define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20)
struct friend_pdu_info {
- u16_t src;
- u16_t dst;
+ uint16_t src;
+ uint16_t dst;
- u8_t seq[3];
+ uint8_t seq[3];
- u8_t ttl:7,
+ uint8_t ttl:7,
ctl:1;
- u32_t iv_index;
+ uint32_t iv_index;
};
static struct friend_adv {
struct bt_mesh_adv adv;
- u16_t app_idx;
+ uint16_t app_idx;
} adv_pool[FRIEND_BUF_COUNT];
static struct bt_mesh_adv *adv_alloc(int id)
@@ -70,7 +72,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id].adv;
}
-static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
+static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
{
if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) {
return false;
@@ -79,7 +81,7 @@ static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem));
}
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established)
{
int i;
@@ -89,7 +91,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (valid && !frnd->valid) {
+ if (valid && !frnd->subnet) {
continue;
}
@@ -97,7 +99,8 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
continue;
}
- if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
+ if (net_idx != BT_MESH_KEY_ANY &&
+ (!frnd->subnet || frnd->subnet->net_idx != net_idx)) {
continue;
}
@@ -109,11 +112,18 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
return NULL;
}
+static int friend_cred_create(struct bt_mesh_friend *frnd, uint8_t idx)
+{
+ return bt_mesh_friend_cred_create(&frnd->cred[idx], frnd->lpn,
+ bt_mesh_primary_addr(),
+ frnd->lpn_counter, frnd->counter,
+ frnd->subnet->keys[idx].net);
+}
+
static void purge_buffers(struct net_buf_slist_t *list)
{
- struct os_mbuf *buf;
-
while (!net_buf_slist_is_empty(list)) {
+ struct os_mbuf *buf;
buf = (void *)net_buf_slist_get(list);
BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS;
net_buf_unref(buf);
@@ -125,10 +135,10 @@ static void purge_buffers(struct net_buf_slist_t *list)
* like the PTS, where the receiver might not have sufficiently compensated
* for internal latencies required to start scanning.
*/
-static s32_t recv_delay(struct bt_mesh_friend *frnd)
+static int32_t recv_delay(struct bt_mesh_friend *frnd)
{
#if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
- return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
+ return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
#else
return frnd->recv_delay;
#endif
@@ -142,7 +152,7 @@ static void friend_clear(struct bt_mesh_friend *frnd)
k_delayed_work_cancel(&frnd->timer);
- friend_cred_del(frnd->net_idx, frnd->lpn);
+ memset(frnd->cred, 0, sizeof(frnd->cred));
if (frnd->last) {
/* Cancel the sending if necessary */
@@ -163,7 +173,8 @@ static void friend_clear(struct bt_mesh_friend *frnd)
seg->seg_count = 0U;
}
- frnd->valid = 0;
+ frnd->counter++;
+ frnd->subnet = NULL;
frnd->established = 0;
frnd->pending_buf = 0;
frnd->fsn = 0;
@@ -172,26 +183,26 @@ static void friend_clear(struct bt_mesh_friend *frnd)
memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
}
-void bt_mesh_friend_clear_net_idx(u16_t net_idx)
+void bt_mesh_friends_clear(void)
{
int i;
- BT_DBG("net_idx 0x%04x", net_idx);
+ BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- friend_clear(frnd);
- }
+ friend_clear(frnd);
}
}
-void bt_mesh_friend_sec_update(u16_t net_idx)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md);
+
+void bt_mesh_friend_sec_update(uint16_t net_idx)
{
int i;
@@ -200,12 +211,13 @@ void bt_mesh_friend_sec_update(u16_t net_idx)
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- frnd->sec_update = 1;
+ if (net_idx == BT_MESH_KEY_ANY ||
+ frnd->subnet->net_idx == net_idx) {
+ enqueue_update(frnd, 0x00);
}
}
}
@@ -214,7 +226,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
struct bt_mesh_net_tx tx = {
.sub = rx->sub,
.ctx = &rx->ctx,
@@ -257,14 +269,14 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
cfm.lpn_counter = msg->lpn_counter;
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
- sizeof(cfm), NULL, NULL, NULL);
+ sizeof(cfm), NULL, NULL);
friend_clear(frnd);
return 0;
}
-static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -278,7 +290,7 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
BT_WARN("No space in friend subscription list");
}
-static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -322,38 +334,41 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
}
struct unseg_app_sdu_meta {
- struct bt_mesh_net_rx net;
- const u8_t *key;
+ struct bt_mesh_app_crypto_ctx crypto;
+ const uint8_t *key;
struct bt_mesh_subnet *subnet;
- bool is_dev_key;
- u8_t aid;
- u8_t *ad;
+ uint8_t aid;
};
static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
struct os_mbuf *buf,
struct unseg_app_sdu_meta *meta)
{
- u16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ uint16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ struct bt_mesh_net_rx net;
int err;
- meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
- meta->is_dev_key = (app_idx == BT_MESH_KEY_DEV);
- meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx);
- bt_mesh_net_header_parse(buf, &meta->net);
- err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst,
- &meta->key, &meta->aid);
+ meta->subnet = frnd->subnet;
+ bt_mesh_net_header_parse(buf, &net);
+ err = bt_mesh_keys_resolve(&net.ctx, &net.sub, &meta->key, &meta->aid);
if (err) {
return err;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
- meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
- if (!meta->ad) {
+ meta->crypto.src = net.ctx.addr;
+ meta->crypto.dst = net.ctx.recv_dst;
+ meta->crypto.iv_index = BT_MESH_NET_IVI_TX;
+ meta->crypto.dev_key = BT_MESH_IS_DEV_KEY(app_idx);
+ meta->crypto.seq_num = net.seq;
+ meta->crypto.aszmic = 0;
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(meta->crypto.dst)) {
+ meta->crypto.ad = bt_mesh_va_label_get(meta->crypto.dst);
+ if (!meta->crypto.ad) {
return -ENOENT;
}
} else {
- meta->ad = NULL;
+ meta->crypto.ad = NULL;
}
return 0;
@@ -372,12 +387,10 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_decrypt_in_place(meta->key, meta->is_dev_key,
- 0, buf, meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, meta->net.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_decrypt(meta->key, &meta->crypto, buf, buf);
net_buf_simple_restore(buf, &state);
+ net_buf_unref(buf);
return err;
}
@@ -394,10 +407,7 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_encrypt_in_place(meta->key, meta->is_dev_key, 0, buf,
- meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, bt_mesh.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf);
net_buf_simple_restore(buf, &state);
return err;
@@ -423,7 +433,7 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
/* No need to reencrypt the message if the sequence number is
* unchanged.
*/
- if (meta.net.seq == bt_mesh.seq) {
+ if (meta.crypto.seq_num == bt_mesh.seq) {
return 0;
}
@@ -444,28 +454,22 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
bool master_cred)
{
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
- const u8_t *enc, *priv;
- u32_t iv_index;
- u16_t src;
- u8_t nid;
+ const struct bt_mesh_net_cred *cred;
+ uint32_t iv_index;
+ uint16_t src;
int err;
if (master_cred) {
- enc = sub->keys[sub->kr_flag].enc;
- priv = sub->keys[sub->kr_flag].privacy;
- nid = sub->keys[sub->kr_flag].nid;
+ cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)]
+ .msg;
} else {
- if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
- BT_ERR("friend_cred_get failed");
- return -ENOENT;
- }
+ cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)];
}
src = sys_get_be16(&buf->om_data[5]);
if (bt_mesh_elem_find(src)) {
- u32_t seq;
+ uint32_t seq;
if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) {
err = unseg_app_sdu_prepare(frnd, buf);
@@ -475,25 +479,23 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
+ sys_put_be24(seq, &buf->om_data[2]);
iv_index = BT_MESH_NET_IVI_TX;
FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED;
} else {
- u8_t ivi = (buf->om_data[0] >> 7);
+ uint8_t ivi = (buf->om_data[0] >> 7);
iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
}
- buf->om_data[0] = (nid | (iv_index & 1) << 7);
+ buf->om_data[0] = (cred->nid | (iv_index & 1) << 7);
- if (bt_mesh_net_encrypt(enc, buf, iv_index, false)) {
+ if (bt_mesh_net_encrypt(cred->enc, buf, iv_index, false)) {
BT_ERR("Encrypting failed");
return -EINVAL;
}
- if (bt_mesh_net_obfuscate(buf->om_data, iv_index, priv)) {
+ if (bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy)) {
BT_ERR("Obfuscating failed");
return -EINVAL;
}
@@ -502,7 +504,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
- u8_t ctl_op,
+ uint8_t ctl_op,
struct os_mbuf *sdu)
{
struct friend_pdu_info info;
@@ -524,21 +526,20 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
return create_friend_pdu(frnd, &info, sdu);
}
-static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
+static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct bt_mesh_ctl_friend_update *upd;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd));
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct os_mbuf *buf;
- __ASSERT_NO_MSG(sub != NULL);
+ __ASSERT_NO_MSG(frnd->subnet);
BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
net_buf_simple_init(sdu, 1);
upd = net_buf_simple_add(sdu, sizeof(*upd));
- upd->flags = bt_mesh_net_flags(sub);
+ upd->flags = bt_mesh_net_flags(frnd->subnet);
upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
upd->md = md;
@@ -548,7 +549,7 @@ static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
return buf;
}
-static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
+static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact)
{
struct bt_mesh_ctl_friend_sub_confirm *cfm;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm));
@@ -585,16 +586,18 @@ done:
static void friend_recv_delay(struct bt_mesh_friend *frnd)
{
+ int32_t delay = recv_delay(frnd);
+
frnd->pending_req = 1;
- k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
- BT_DBG("Waiting RecvDelay of %d ms", (int) recv_delay(frnd));
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
+ BT_DBG("Waiting RecvDelay of %d ms", delay);
}
int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Add");
@@ -629,7 +632,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Remove");
@@ -666,7 +669,7 @@ static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf)
frnd->queue_size++;
}
-static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct os_mbuf *buf;
@@ -676,7 +679,6 @@ static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
return;
}
- frnd->sec_update = 0;
enqueue_buf(frnd, buf);
}
@@ -735,7 +737,7 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return 0;
}
-static struct bt_mesh_friend *find_clear(u16_t prev_friend)
+static struct bt_mesh_friend *find_clear(uint16_t prev_friend)
{
int i;
@@ -766,13 +768,13 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static void send_friend_clear(struct bt_mesh_friend *frnd)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = frnd->net_idx,
+ .net_idx = frnd->subnet->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = frnd->clear.frnd,
.send_ttl = BT_MESH_TTL_MAX,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = frnd->subnet,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
@@ -785,13 +787,13 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("");
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, frnd);
+ sizeof(req), &clear_sent_cb, frnd);
}
static void clear_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
- u32_t duration;
+ uint32_t duration;
BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
@@ -820,7 +822,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
BT_DBG("");
@@ -855,7 +857,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
+static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi)
{
struct bt_mesh_ctl_friend_offer *off;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off));
@@ -880,11 +882,9 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
}
if (encrypt_friend_pdu(frnd, buf, true)) {
- return;
+ goto done;
}
- frnd->counter++;
-
if (frnd->last) {
net_buf_unref(frnd->last);
}
@@ -897,43 +897,45 @@ done:
}
#define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN
-#define RSSI_FACT(crit) (((crit) >> 5) & (u8_t)BIT_MASK(2))
-#define RECV_WIN_FACT(crit) (((crit) >> 3) & (u8_t)BIT_MASK(2))
-#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (u8_t)BIT_MASK(3))
-#define MIN_QUEUE_SIZE(crit) ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
+#define RSSI_FACT(crit) (((crit) >> 5) & (uint8_t)BIT_MASK(2))
+#define RECV_WIN_FACT(crit) (((crit) >> 3) & (uint8_t)BIT_MASK(2))
+#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (uint8_t)BIT_MASK(3))
+#define MIN_QUEUE_SIZE(crit) ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
-static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit)
+static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit)
{
/* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
* want to avoid floating-point arithmetic.
*/
- static const u8_t fact[] = { 10, 15, 20, 25 };
- s32_t delay;
+ static const uint8_t fact[] = { 10, 15, 20, 25 };
+ int32_t delay;
BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
fact[RECV_WIN_FACT(crit)], RECV_WIN,
fact[RSSI_FACT(crit)], rssi);
/* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
- delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
- delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi;
+ delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
+ delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi;
delay /= 10;
BT_DBG("Local Delay calculated as %d ms", (int) delay);
- if (delay < 100) {
- return K_MSEC(100);
- }
-
- return K_MSEC(delay);
+ return MAX(delay, 100);
}
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd = NULL;
- u32_t poll_to;
- int i;
+ uint32_t poll_to;
+ int32_t delay;
+ int i, err;
+
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ BT_WARN("Ignoring Friend request from local interface");
+ return 0;
+ }
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Request");
@@ -945,9 +947,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return -EINVAL;
}
- poll_to = (((u32_t)msg->poll_to[0] << 16) |
- ((u32_t)msg->poll_to[1] << 8) |
- ((u32_t)msg->poll_to[2]));
+ poll_to = sys_get_be24(msg->poll_to);
if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
BT_WARN("Prohibited PollTimeout (0x%06x)", (unsigned) poll_to);
@@ -984,9 +984,8 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
- if (!bt_mesh.frnd[i].valid) {
+ if (!bt_mesh.frnd[i].subnet) {
frnd = &bt_mesh.frnd[i];
- frnd->valid = 1;
break;
}
}
@@ -999,12 +998,19 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
init_friend:
frnd->lpn = rx->ctx.addr;
frnd->num_elem = msg->num_elem;
- frnd->net_idx = rx->sub->net_idx;
+ frnd->subnet = rx->sub;
frnd->recv_delay = msg->recv_delay;
frnd->poll_to = poll_to * 100;
frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
+ err = friend_cred_create(frnd, SUBNET_KEY_TX_IDX(frnd->subnet));
+ if (err) {
+ BT_ERR("Failed to create friend credentials");
+ friend_clear(frnd);
+ return -EIO;
+ }
+
BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay,
(unsigned) frnd->poll_to);
@@ -1014,24 +1020,20 @@ init_friend:
clear_procedure_start(frnd);
}
- k_delayed_work_submit(&frnd->timer,
- offer_delay(frnd, rx->ctx.recv_rssi,
- msg->criteria));
-
- friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
- frnd->counter);
+ delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria);
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
enqueue_offer(frnd, rx->ctx.recv_rssi);
return 0;
}
-static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
+static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
{
struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
struct net_buf_simple_state state;
- u16_t buf_seq_zero;
- u16_t buf_src;
+ uint16_t buf_seq_zero;
+ uint16_t buf_src;
if (!buf) {
return false;
@@ -1048,8 +1050,8 @@ static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
}
static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
- u16_t src, u16_t seq_zero,
- u8_t seg_count)
+ uint16_t src, uint16_t seq_zero,
+ uint8_t seg_count)
{
struct bt_mesh_friend_seg *unassigned = NULL;
int i;
@@ -1075,7 +1077,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
enum bt_mesh_friend_pdu_type type,
- u16_t src, u8_t seg_count,
+ uint16_t src, uint8_t seg_count,
struct os_mbuf *buf)
{
struct bt_mesh_friend_seg *seg;
@@ -1083,15 +1085,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
BT_DBG("type %u", type);
if (type == BT_MESH_FRIEND_PDU_SINGLE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
enqueue_buf(frnd, buf);
return;
}
- u16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
+ uint16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
seg = get_seg(frnd, src, seq_zero, seg_count);
if (!seg) {
@@ -1103,10 +1101,6 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
net_buf_slist_put(&seg->queue, buf);
if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
frnd->queue_size += seg->seg_count;
@@ -1117,7 +1111,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
}
}
-static void buf_send_start(u16_t duration, int err, void *user_data)
+static void buf_send_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
@@ -1126,7 +1120,7 @@ static void buf_send_start(u16_t duration, int err, void *user_data)
frnd->pending_buf = 0;
/* Friend Offer doesn't follow the re-sending semantics */
- if (!frnd->established) {
+ if (!frnd->established && frnd->last) {
net_buf_unref(frnd->last);
frnd->last = NULL;
}
@@ -1154,6 +1148,38 @@ static void buf_send_end(int err, void *user_data)
}
}
+static void update_overwrite(struct os_mbuf *buf, uint8_t md)
+{
+ struct net_buf_simple_state state;
+ struct bt_mesh_ctl_friend_update *upd;
+
+ if (buf->om_len != 16) {
+ return;
+ }
+
+ net_buf_simple_save(buf, &state);
+
+ net_buf_skip(buf, 1); /* skip IVI, NID */
+
+ if (!(net_buf_pull_u8(buf) >> 7)) {
+ goto end;
+ }
+
+ net_buf_skip(buf, 7); /* skip seqnum src dec*/
+
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1))
+ != TRANS_CTL_OP_FRIEND_UPDATE) {
+ goto end;
+ }
+
+ upd = net_buf_pull_mem(buf, sizeof(*upd));
+ BT_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md);
+ upd->md = md;
+
+end:
+ net_buf_simple_restore(buf, &state);
+}
+
static void friend_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
@@ -1162,6 +1188,8 @@ static void friend_timeout(struct ble_npl_event *work)
.end = buf_send_end,
};
+ uint8_t md;
+
__ASSERT_NO_MSG(frnd->pending_buf == 0);
BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
@@ -1187,12 +1215,17 @@ static void friend_timeout(struct ble_npl_event *work)
return;
}
+ md = (uint8_t)(net_buf_slist_peek_head(&frnd->queue) != NULL);
+
+ update_overwrite(frnd->last, md);
+
if (encrypt_friend_pdu(frnd, frnd->last, false)) {
return;
}
/* Clear the flag we use for segment tracking */
BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS;
+ BT_MESH_ADV(frnd->last)->flags = 0;
BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
frnd->last, frnd->lpn);
@@ -1204,8 +1237,56 @@ send_last:
bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ int i, err;
+
+ if (evt == BT_MESH_KEY_ADDED) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+ struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+ if (frnd->subnet != sub) {
+ continue;
+ }
+
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ BT_DBG("Cleared network for 0x%04x", frnd->lpn);
+ friend_clear(frnd);
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("Generating new keys for 0x%04x", frnd->lpn);
+ err = friend_cred_create(frnd, 1);
+ if (err) {
+ BT_ERR("Failed updating friend cred for 0x%04x",
+ frnd->lpn);
+ friend_clear(frnd);
+ }
+ break;
+ case BT_MESH_KEY_SWAPPED:
+ enqueue_update(frnd, 0);
+ break;
+ case BT_MESH_KEY_REVOKED:
+ BT_DBG("Revoking old keys for 0x%04x", frnd->lpn);
+ memcpy(&frnd->cred[0], &frnd->cred[1],
+ sizeof(frnd->cred[0]));
+ memset(&frnd->cred[1], 0, sizeof(frnd->cred[1]));
+ enqueue_update(frnd, 0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
int bt_mesh_friend_init(void)
{
+ if (!bt_mesh_subnet_cb_list[3]) {
+ bt_mesh_subnet_cb_list[3] = subnet_evt;
+ }
int rc;
int i;
@@ -1223,8 +1304,6 @@ int bt_mesh_friend_init(void)
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
int j;
- frnd->net_idx = BT_MESH_KEY_UNUSED;
-
net_buf_slist_init(&frnd->queue);
k_delayed_work_init(&frnd->timer, friend_timeout);
@@ -1240,7 +1319,7 @@ int bt_mesh_friend_init(void)
return 0;
}
-static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
+static bool is_segack(struct os_mbuf *buf, uint64_t *seqauth, uint16_t src)
{
struct net_buf_simple_state state;
bool found = false;
@@ -1265,7 +1344,7 @@ static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
net_buf_skip(buf, 2); /* skip dst */
- if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
goto end;
}
@@ -1276,8 +1355,8 @@ end:
return found;
}
-static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
- u16_t src)
+static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth,
+ uint16_t src)
{
struct os_mbuf *cur, *prev = NULL;
@@ -1302,7 +1381,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1334,9 +1413,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
info.ctl = rx->ctl;
- info.seq[0] = (rx->seq >> 16);
- info.seq[1] = (rx->seq >> 8);
- info.seq[2] = rx->seq;
+ sys_put_be24(rx->seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_RX(rx);
@@ -1355,7 +1432,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1373,9 +1450,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
info.ttl = tx->ctx->send_ttl;
info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- info.seq[0] = (bt_mesh.seq >> 16);
- info.seq[1] = (bt_mesh.seq >> 8);
- info.seq[2] = bt_mesh.seq;
+ sys_put_be24(bt_mesh.seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_TX;
@@ -1398,8 +1473,8 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
}
-static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
- u16_t addr)
+static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx,
+ uint16_t addr)
{
int i;
@@ -1407,7 +1482,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
- if (net_idx != frnd->net_idx) {
+ if (net_idx != frnd->subnet->net_idx) {
return false;
}
@@ -1424,7 +1499,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr)
{
int i;
@@ -1443,10 +1518,10 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
return false;
}
-static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
- u32_t total = 0;
+ uint32_t total = 0;
int i;
if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) {
@@ -1474,8 +1549,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
}
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count)
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool someone_has_space = false, friend_match = false;
int i;
@@ -1509,11 +1584,11 @@ bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
return someone_has_space;
}
-static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool pending_segments;
- u8_t avail_space;
+ uint8_t avail_space;
if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
return false;
@@ -1547,7 +1622,7 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
int i;
@@ -1570,6 +1645,11 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
continue;
}
+ if (friend_lpn_matches(frnd, rx->sub->net_idx,
+ rx->ctx.addr)) {
+ continue;
+ }
+
if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth,
seg_count)) {
continue;
@@ -1582,7 +1662,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
bool matched = false;
@@ -1617,8 +1697,22 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
return matched;
}
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth)
+int bt_mesh_friend_terminate(uint16_t lpn_addr)
+{
+ struct bt_mesh_friend *frnd;
+
+ frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, false, false);
+ if (!frnd) {
+ return -ENOENT;
+ }
+
+ friend_clear(frnd);
+
+ return 0;
+}
+
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth)
{
int i;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
index 10ffa819..ee783f33 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
@@ -17,29 +17,29 @@ enum bt_mesh_friend_pdu_type {
BT_MESH_FRIEND_PDU_COMPLETE,
};
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr);
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established);
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count);
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count);
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth);
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth);
-void bt_mesh_friend_sec_update(u16_t net_idx);
+void bt_mesh_friend_sec_update(uint16_t net_idx);
-void bt_mesh_friend_clear_net_idx(u16_t net_idx);
+void bt_mesh_friends_clear(void);
int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
index 896f3d1a..aab7f374 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
@@ -30,7 +30,7 @@
#include "base64/base64.h"
#endif
-extern u8_t g_mesh_addr_type;
+extern uint8_t g_mesh_addr_type;
#if MYNEWT_VAL(BLE_EXT_ADV)
/* Store configuration for different bearers */
@@ -44,8 +44,8 @@ bt_hex(const void *buf, size_t len)
{
static const char hex[] = "0123456789abcdef";
static char hexbufs[4][137];
- static u8_t curbuf;
- const u8_t *b = buf;
+ static uint8_t curbuf;
+ const uint8_t *b = buf;
char *str;
int i;
@@ -214,6 +214,14 @@ net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val)
ASSERT_NOT_CHAIN(om);
}
+void
+net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val)
+{
+ val = htole32(val);
+ os_mbuf_append(om, &val, 3);
+ ASSERT_NOT_CHAIN(om);
+}
+
void
net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val)
{
@@ -269,6 +277,22 @@ net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val)
ASSERT_NOT_CHAIN(om);
}
+void
+net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val)
+{
+ uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len];
+
+ assert(headroom >= 3);
+ om->om_data -= 3;
+ put_be24(om->om_data, val);
+ om->om_len += 3;
+
+ if (om->om_pkthdr_len) {
+ OS_MBUF_PKTHDR(om)->omp_len += 3;
+ }
+ ASSERT_NOT_CHAIN(om);
+}
+
void
net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val)
{
@@ -333,7 +357,7 @@ k_fifo_is_empty(struct ble_npl_eventq *q)
return ble_npl_eventq_is_empty(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)
{
struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0);
@@ -384,6 +408,12 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f)
#endif
}
+bool
+k_delayed_work_pending(struct k_delayed_work *w)
+{
+ return ble_npl_callout_is_active(&w->work);
+}
+
void
k_delayed_work_cancel(struct k_delayed_work *w)
{
@@ -440,7 +470,7 @@ int64_t k_uptime_get(void)
return ble_npl_time_ticks_to_ms32(ble_npl_time_get());
}
-u32_t k_uptime_get_32(void)
+uint32_t k_uptime_get_32(void)
{
return k_uptime_get();
}
@@ -459,7 +489,7 @@ static uint8_t priv[32];
static bool has_pub = false;
int
-bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
+bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
{
uint8_t dh[32];
@@ -510,7 +540,7 @@ bt_pub_key_get(void)
}
static int
-set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len)
+set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len)
{
int i;
@@ -846,6 +876,52 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
}
}
+/** Memory slab methods */
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
+{
+ **(char ***)mem = slab->free_list;
+ slab->free_list = *(char **)mem;
+ slab->num_used--;
+}
+
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem)
+{
+ int result;
+
+ if (slab->free_list != NULL) {
+ /* take a free block */
+ *mem = slab->free_list;
+ slab->free_list = *(char **)(slab->free_list);
+ slab->num_used++;
+ result = 0;
+ } else {
+ *mem = NULL;
+ result = -ENOMEM;
+ }
+ return result;
+}
+
+int create_free_list(struct k_mem_slab *slab)
+{
+ uint32_t j;
+ char *p;
+
+ if(((slab->block_size | (uintptr_t)slab->buffer) &
+ (sizeof(void *) - 1)) != 0) {
+ return -EINVAL;
+ }
+
+ slab->free_list = NULL;
+ p = slab->buffer;
+
+ for (j = 0U; j < slab->num_blocks; j++) {
+ *(char **)p = slab->free_list;
+ slab->free_list = p;
+ p += slab->block_size;
+ }
+ return 0;
+}
+
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
int settings_bytes_from_str(char *val_str, void *vp, int *len)
@@ -867,4 +943,3 @@ char *settings_str_from_bytes(const void *vp, int vp_len,
}
#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */
-
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
index 193279c2..76d639c5 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
@@ -21,15 +21,15 @@
#include "foundation.h"
#include "mesh/health_cli.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_health_cli *health_cli;
struct health_fault_param {
- u16_t cid;
- u8_t *expect_test_id;
- u8_t *test_id;
- u8_t *faults;
+ uint16_t cid;
+ uint8_t *expect_test_id;
+ uint8_t *test_id;
+ uint8_t *faults;
size_t *fault_count;
};
@@ -38,8 +38,8 @@ static void health_fault_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct health_fault_param *param;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -84,8 +84,8 @@ static void health_current_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_cli *cli = model->user_data;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -106,7 +106,7 @@ static void health_current_status(struct bt_mesh_model *model,
}
struct health_period_param {
- u8_t *divisor;
+ uint8_t *divisor;
};
static void health_period_status(struct bt_mesh_model *model,
@@ -132,7 +132,7 @@ static void health_period_status(struct bt_mesh_model *model,
}
struct health_attention_param {
- u8_t *attention;
+ uint8_t *attention;
};
static void health_attention_status(struct bt_mesh_model *model,
@@ -167,7 +167,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
BT_MESH_MODEL_OP_END,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!health_cli) {
BT_ERR("No available Health Client context!");
@@ -202,12 +202,10 @@ static int cli_wait(void)
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -237,12 +235,11 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -283,12 +280,10 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -318,12 +313,11 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -364,13 +358,12 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -415,13 +408,12 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -465,13 +457,12 @@ done:
return err;
}
-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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -505,12 +496,12 @@ done:
return err;
}
-s32_t bt_mesh_health_cli_timeout_get(void)
+int32_t bt_mesh_health_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_health_cli_timeout_set(s32_t timeout)
+void bt_mesh_health_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
@@ -523,6 +514,7 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model)
}
health_cli = model->user_data;
+ msg_timeout = 2 * MSEC_PER_SEC;
return 0;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
index 16de83a9..dd90533b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
@@ -27,11 +27,11 @@
struct bt_mesh_health_srv *health_srv;
static void health_get_registered(struct bt_mesh_model *mod,
- u16_t company_id,
+ uint16_t company_id,
struct os_mbuf *msg)
{
struct bt_mesh_health_srv *srv = mod->user_data;
- u8_t *test_id;
+ uint8_t *test_id;
BT_DBG("Company ID 0x%04x", company_id);
@@ -41,7 +41,7 @@ static void health_get_registered(struct bt_mesh_model *mod,
net_buf_simple_add_le16(msg, company_id);
if (srv->cb && srv->cb->fault_get_reg) {
- u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
+ uint8_t fault_count = net_buf_simple_tailroom(msg) - 4;
int err;
err = srv->cb->fault_get_reg(mod, company_id, test_id,
@@ -64,9 +64,9 @@ static size_t health_get_current(struct bt_mesh_model *mod,
{
struct bt_mesh_health_srv *srv = mod->user_data;
const struct bt_mesh_comp *comp;
- u8_t *test_id, *company_ptr;
- u16_t company_id;
- u8_t fault_count;
+ uint8_t *test_id, *company_ptr;
+ uint16_t company_id;
+ uint8_t fault_count;
int err;
bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
@@ -104,7 +104,7 @@ static void health_fault_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -124,7 +124,7 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -141,7 +141,7 @@ static void health_fault_clear(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -165,8 +165,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
test_id = net_buf_simple_pull_u8(buf);
company_id = net_buf_simple_pull_le16(buf);
@@ -184,8 +184,8 @@ static void health_fault_test(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
BT_DBG("");
@@ -219,7 +219,7 @@ static void send_attention_status(struct bt_mesh_model *model,
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1);
struct bt_mesh_health_srv *srv = model->user_data;
- u8_t time;
+ uint8_t time;
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
@@ -248,7 +248,7 @@ static void attention_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t time;
+ uint8_t time;
time = net_buf_simple_pull_u8(buf);
@@ -297,7 +297,7 @@ static void health_period_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t period;
+ uint8_t period;
period = net_buf_simple_pull_u8(buf);
if (period > 15) {
@@ -389,10 +389,6 @@ static int health_srv_init(struct bt_mesh_model *model)
struct bt_mesh_health_srv *srv = model->user_data;
if (!srv) {
- if (!bt_mesh_model_in_primary(model)) {
- return 0;
- }
-
BT_ERR("No Health Server context provided");
return -EINVAL;
}
@@ -420,7 +416,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
.init = health_srv_init,
};
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time)
{
struct bt_mesh_health_srv *srv;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
new file mode 100644
index 00000000..538a1cb6
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG
+
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "access.h"
+#include "lpn.h"
+#include "settings.h"
+#include "transport.h"
+#include "heartbeat.h"
+#include "foundation.h"
+#include "mesh/glue.h"
+
+struct bt_mesh_hb_cb hb_cb;
+
+static struct bt_mesh_hb_pub pub;
+static struct bt_mesh_hb_sub sub;
+static struct k_delayed_work sub_timer;
+static struct k_delayed_work pub_timer;
+
+static int64_t sub_remaining(void)
+{
+ if (sub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ return k_delayed_work_remaining_get(&sub_timer) / MSEC_PER_SEC;
+}
+
+static void hb_publish_end_cb(int err, void *cb_data)
+{
+ if (pub.period && pub.count > 1) {
+ k_delayed_work_submit(&pub_timer, K_SECONDS(pub.period));
+ }
+
+ if (pub.count != 0xffff) {
+ pub.count--;
+ }
+}
+
+static void notify_recv(uint8_t hops, uint16_t feat)
+{
+ sub.remaining = sub_remaining();
+
+ if (hb_cb.recv != NULL) {
+ hb_cb.recv(&sub, hops, feat);
+ }
+}
+
+static void notify_sub_end(void)
+{
+ sub.remaining = 0;
+
+ if (hb_cb.sub_end != NULL) {
+ hb_cb.sub_end(&sub);
+ }
+}
+
+static void sub_end(struct ble_npl_event *work)
+{
+ notify_sub_end();
+}
+
+static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+ uint16_t feat = 0U;
+ struct __packed {
+ uint8_t init_ttl;
+ uint16_t feat;
+ } hb;
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = pub.net_idx,
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .addr = pub.dst,
+ .send_ttl = pub.ttl,
+ };
+ struct bt_mesh_net_tx tx = {
+ .sub = bt_mesh_subnet_get(pub.net_idx),
+ .ctx = &ctx,
+ .src = bt_mesh_primary_addr(),
+ .xmit = bt_mesh_net_transmit_get(),
+ };
+
+ /* Do nothing if heartbeat publication is not enabled */
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ hb.init_ttl = pub.ttl;
+
+ if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
+ feat |= BT_MESH_FEAT_RELAY;
+ }
+
+ if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+ feat |= BT_MESH_FEAT_PROXY;
+ }
+
+ if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
+ feat |= BT_MESH_FEAT_FRIEND;
+ }
+
+ if (bt_mesh_lpn_established()) {
+ feat |= BT_MESH_FEAT_LOW_POWER;
+ }
+
+ hb.feat = sys_cpu_to_be16(feat);
+
+ BT_DBG("InitTTL %u feat 0x%04x", pub.ttl, feat);
+
+ return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
+ cb, cb_data);
+}
+
+static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data)
+{
+ if (err) {
+ hb_publish_end_cb(err, cb_data);
+ }
+}
+
+static void hb_publish(struct ble_npl_event *work)
+{
+ static const struct bt_mesh_send_cb publish_cb = {
+ .start = hb_publish_start_cb,
+ .end = hb_publish_end_cb,
+ };
+ struct bt_mesh_subnet *sub;
+ int err;
+
+ BT_DBG("hb_pub.count: %u", pub.count);
+
+ sub = bt_mesh_subnet_get(pub.net_idx);
+ if (!sub) {
+ BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx);
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ return;
+ }
+
+ if (pub.count == 0U) {
+ return;
+ }
+
+ err = heartbeat_send(&publish_cb, NULL);
+ if (err) {
+ hb_publish_end_cb(err, NULL);
+ }
+}
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t init_ttl, hops;
+ uint16_t feat;
+
+ if (buf->om_len < 3) {
+ BT_ERR("Too short heartbeat message");
+ return -EINVAL;
+ }
+
+ init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
+ feat = net_buf_simple_pull_be16(buf);
+
+ hops = (init_ttl - rx->ctx.recv_ttl + 1);
+
+ if (rx->ctx.addr != sub.src || rx->ctx.recv_dst != sub.dst) {
+ BT_DBG("No subscription for received heartbeat");
+ return 0;
+ }
+
+ if (!k_delayed_work_pending(&sub_timer)) {
+ BT_DBG("Heartbeat subscription period expired");
+ return 0;
+ }
+
+ sub.min_hops = MIN(sub.min_hops, hops);
+ sub.max_hops = MAX(sub.max_hops, hops);
+
+ if (sub.count < 0xffff) {
+ sub.count++;
+ }
+
+ BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
+ rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
+ (hops == 1U) ? "" : "s", feat);
+
+ notify_recv(hops, feat);
+
+ return 0;
+}
+
+static void pub_disable(void)
+{
+ BT_DBG("");
+
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ pub.count = 0U;
+ pub.ttl = 0U;
+ pub.period = 0U;
+
+ k_delayed_work_cancel(&pub_timer);
+}
+
+uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub)
+{
+ if (!new_pub || new_pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ pub_disable();
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ bt_mesh_is_provisioned()) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (!bt_mesh_subnet_get(new_pub->net_idx)) {
+ BT_ERR("Unknown NetKey 0x%04x", new_pub->net_idx);
+ return STATUS_INVALID_NETKEY;
+ }
+
+ new_pub->feat &= BT_MESH_FEAT_SUPPORTED;
+ pub = *new_pub;
+
+ if (!bt_mesh_is_provisioned()) {
+ return STATUS_SUCCESS;
+ }
+
+ /* The first Heartbeat message shall be published as soon as possible
+ * after the Heartbeat Publication Period state has been configured for
+ * periodic publishing.
+ */
+ if (pub.period && pub.count) {
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ } else {
+ k_delayed_work_cancel(&pub_timer);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get)
+{
+ *get = pub;
+}
+
+uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period)
+{
+ if (src != BT_MESH_ADDR_UNASSIGNED && !BT_MESH_ADDR_IS_UNICAST(src)) {
+ BT_WARN("Prohibited source address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(dst) || BT_MESH_ADDR_IS_RFU(dst) ||
+ (BT_MESH_ADDR_IS_UNICAST(dst) && dst != bt_mesh_primary_addr())) {
+ BT_WARN("Prohibited destination address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (period > (1U << 16)) {
+ BT_WARN("Prohibited subscription period %u s", period);
+ return STATUS_CANNOT_SET;
+ }
+
+ /* Only an explicit address change to unassigned should trigger clearing
+ * of the values according to MESH/NODE/CFG/HBS/BV-02-C.
+ */
+ if (src == BT_MESH_ADDR_UNASSIGNED || dst == BT_MESH_ADDR_UNASSIGNED) {
+ sub.src = BT_MESH_ADDR_UNASSIGNED;
+ sub.dst = BT_MESH_ADDR_UNASSIGNED;
+ sub.min_hops = 0U;
+ sub.max_hops = 0U;
+ sub.count = 0U;
+ sub.period = sub.period - sub_remaining();
+ k_delayed_work_cancel(&sub_timer);
+ notify_sub_end();
+ } else if (period) {
+ sub.src = src;
+ sub.dst = dst;
+ sub.min_hops = BT_MESH_TTL_MAX;
+ sub.max_hops = 0U;
+ sub.count = 0U;
+ sub.period = period;
+ k_delayed_work_submit(&sub_timer, K_SECONDS(period));
+ } else {
+ /* Clearing the period should stop heartbeat subscription
+ * without clearing the parameters, so we can still read them.
+ */
+ sub.period = sub.period - sub_remaining();
+ k_delayed_work_cancel(&sub_timer);
+ notify_sub_end();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get)
+{
+ *get = sub;
+ get->remaining = sub_remaining();
+}
+
+void bt_mesh_hb_feature_changed(uint16_t features)
+{
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return;
+ }
+
+ if (!(pub.feat & features)) {
+ return;
+ }
+
+ heartbeat_send(NULL, NULL);
+}
+
+void bt_mesh_hb_init(void)
+{
+ pub.net_idx = BT_MESH_KEY_UNUSED;
+ k_delayed_work_init(&pub_timer, hb_publish);
+ k_delayed_work_init(&sub_timer, sub_end);
+}
+
+void bt_mesh_hb_start(void)
+{
+ if (pub.count && pub.period) {
+ BT_DBG("Starting heartbeat publication");
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ }
+}
+
+void bt_mesh_hb_suspend(void)
+{
+ k_delayed_work_cancel(&pub_timer);
+}
+
+void bt_mesh_hb_resume(void)
+{
+ if (pub.period && pub.count) {
+ BT_DBG("Starting heartbeat publication");
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ }
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
new file mode 100644
index 00000000..c43683fe
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/heartbeat.h"
+
+static inline uint16_t bt_mesh_hb_pwr2(uint8_t val)
+{
+ if (!val) {
+ return 0x0000;
+ } else if (val == 0xff || val == 0x11) {
+ return 0xffff;
+ } else {
+ return (1 << (val - 1));
+ }
+}
+
+static inline uint8_t bt_mesh_hb_log(uint32_t val)
+{
+ if (!val) {
+ return 0x00;
+ } else if (val == 0xffff) {
+ return 0xff;
+ } else {
+ return 32 - __builtin_clz(val);
+ }
+}
+
+void bt_mesh_hb_init(void);
+void bt_mesh_hb_start(void);
+void bt_mesh_hb_suspend(void);
+void bt_mesh_hb_resume(void);
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
+void bt_mesh_hb_feature_changed(uint16_t features);
+
+uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub);
+uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
index b6d83818..bc4792c6 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
@@ -6,52 +6,52 @@
#include "light_model.h"
-static u8_t gen_onoff_state;
-static s16_t gen_level_state;
+static uint8_t gen_onoff_state;
+static int16_t gen_level_state;
static void update_light_state(void)
{
- console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (u16_t)gen_level_state);
+ console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (uint16_t)gen_level_state);
}
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
{
*state = gen_onoff_state;
return 0;
}
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
{
gen_onoff_state = state;
update_light_state();
return 0;
}
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
{
*level = gen_level_state;
return 0;
}
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
{
gen_level_state = level;
- if ((u16_t)gen_level_state > 0x0000) {
+ if ((uint16_t)gen_level_state > 0x0000) {
gen_onoff_state = 1;
}
- if ((u16_t)gen_level_state == 0x0000) {
+ if ((uint16_t)gen_level_state == 0x0000) {
gen_onoff_state = 0;
}
update_light_state();
return 0;
}
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
{
return light_model_gen_level_get(model, lightness);
}
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
{
return light_model_gen_level_set(model, lightness);
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
index 95fcdb78..d5f95943 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
@@ -9,11 +9,11 @@
#include "syscfg/syscfg.h"
#include "mesh/mesh.h"
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
index ec012a5f..bd48c088 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
@@ -19,6 +19,7 @@
#include "adv.h"
#include "net.h"
#include "transport.h"
+#include "heartbeat.h"
#include "access.h"
#include "beacon.h"
#include "foundation.h"
@@ -42,27 +43,33 @@
#define POLL_RETRY_TIMEOUT K_MSEC(100)
-#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
- (lpn)->recv_win + POLL_RETRY_TIMEOUT))
+#define REQ_RETRY_DURATION(lpn) (LPN_RECV_DELAY + (lpn)->adv_duration + \
+ (lpn)->recv_win + POLL_RETRY_TIMEOUT)
#define POLL_TIMEOUT_INIT (MYNEWT_VAL(BLE_MESH_LPN_INIT_POLL_TIMEOUT) * 100)
-#define POLL_TIMEOUT_MAX(lpn) ((MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) * 100) - \
- REQ_RETRY_DURATION(lpn))
-#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
-#define CLEAR_ATTEMPTS 2
+#define POLL_TIMEOUT (MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) * 100)
+
+#define REQ_ATTEMPTS_MAX 6
+#define REQ_ATTEMPTS(lpn) MIN(REQ_ATTEMPTS_MAX, \
+ POLL_TIMEOUT / REQ_RETRY_DURATION(lpn))
+
+#define POLL_TIMEOUT_MAX(lpn) (POLL_TIMEOUT - \
+ (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
+
+#define CLEAR_ATTEMPTS 3
#define LPN_CRITERIA ((MYNEWT_VAL(BLE_MESH_LPN_MIN_QUEUE_SIZE)) | \
(MYNEWT_VAL(BLE_MESH_LPN_RSSI_FACTOR) << 3) | \
(MYNEWT_VAL(BLE_MESH_LPN_RECV_WIN_FACTOR) << 5))
-#define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) }
+#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
#define LPN_POLL_TO POLL_TO(MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT))
/* 2 transmissions, 20ms interval */
#define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
-static void (*lpn_cb)(u16_t friend_addr, bool established);
+static void (*lpn_cb)(uint16_t friend_addr, bool established);
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
static const char *state2str(int state)
@@ -145,10 +152,7 @@ static void friend_clear_sent(int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- /* We're switching away from Low Power behavior, so permanently
- * enable scanning.
- */
- bt_mesh_scan_enable();
+ /* Scanning will enable if lpn state still enabled */
lpn->req_attempts++;
@@ -170,31 +174,30 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static int send_friend_clear(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
};
struct bt_mesh_ctl_friend_clear req = {
.lpn_addr = sys_cpu_to_be16(tx.src),
- .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
+ .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter),
};
BT_DBG("");
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, NULL);
+ sizeof(req), &clear_sent_cb, NULL);
}
static void clear_friendship(bool force, bool disable)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
BT_DBG("force %u disable %u", force, disable);
@@ -210,8 +213,6 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_cancel(&lpn->timer);
- friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
-
if (lpn->clear_success) {
lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
} else {
@@ -231,6 +232,7 @@ static void clear_friendship(bool force, bool disable)
lpn->sent_req = 0;
lpn->established = 0;
lpn->clear_success = 0;
+ lpn->sub = NULL;
group_zero(lpn->added);
group_zero(lpn->pending);
@@ -242,9 +244,7 @@ static void clear_friendship(bool force, bool disable)
*/
lpn->groups_changed = 1;
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (disable) {
lpn_set_state(BT_MESH_LPN_DISABLED);
@@ -255,7 +255,7 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
}
-static void friend_req_sent(u16_t duration, int err, void *user_data)
+static void friend_req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -284,33 +284,43 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
{
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = BT_MESH_ADDR_FRIENDS,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
};
+
+ lpn->lpn_counter++;
+
struct bt_mesh_ctl_friend_req req = {
.criteria = LPN_CRITERIA,
.recv_delay = LPN_RECV_DELAY,
.poll_to = LPN_POLL_TO,
- .prev_addr = lpn->old_friend,
+ .prev_addr = sys_cpu_to_be16(lpn->old_friend),
.num_elem = comp->elem_count,
- .lpn_counter = sys_cpu_to_be16(lpn->counter),
+ .lpn_counter = sys_cpu_to_be16(lpn->lpn_counter),
};
BT_DBG("");
+ lpn->sub = bt_mesh_subnet_next(NULL);
+ if (!lpn->sub) {
+ BT_ERR("No subnets, can't start LPN mode");
+ return -ENOENT;
+ }
+
+ ctx.net_idx = lpn->sub->net_idx;
+ tx.sub = lpn->sub;
+
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
- sizeof(req), NULL, &friend_req_sent_cb, NULL);
+ sizeof(req), &friend_req_sent_cb, NULL);
}
-static void req_sent(u16_t duration, int err, void *user_data)
+static void req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -337,6 +347,7 @@ static void req_sent(u16_t duration, int err, void *user_data)
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY - SCAN_LATENCY);
} else {
+ lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY + duration +
lpn->recv_win);
@@ -350,20 +361,20 @@ static const struct bt_mesh_send_cb req_sent_cb = {
static int send_friend_poll(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
.friend_cred = true,
};
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u8_t fsn = lpn->fsn;
+ uint8_t fsn = lpn->fsn;
int err;
BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
@@ -377,7 +388,7 @@ static int send_friend_poll(void)
}
err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
- NULL, &req_sent_cb, NULL);
+ &req_sent_cb, NULL);
if (err == 0) {
lpn->pending_poll = 0;
lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
@@ -477,14 +488,22 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
send_friend_poll();
}
+static int friend_cred_create(struct bt_mesh_net_cred *cred,
+ const uint8_t key[16])
+{
+ struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+ return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(),
+ lpn->frnd, lpn->lpn_counter,
+ lpn->frnd_counter, key);
+}
+
int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_offer *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- struct bt_mesh_subnet *sub = rx->sub;
- struct friend_cred *cred;
- u16_t frnd_counter;
+ uint16_t frnd_counter;
int err;
if (buf->om_len < sizeof(*msg)) {
@@ -508,16 +527,24 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
frnd_counter);
+ lpn->frnd_counter = frnd_counter;
lpn->frnd = rx->ctx.addr;
- cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
- if (!cred) {
- lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
- return -ENOMEM;
+ /* Create friend credentials for each of the valid keys in the
+ * friendship subnet:
+ */
+ for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
+ if (!lpn->sub->keys[i].valid) {
+ continue;
+ }
+
+ err = friend_cred_create(&lpn->cred[i], lpn->sub->keys[i].net);
+ if (err) {
+ lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+ return err;
+ }
}
-
/* TODO: Add offer acceptance criteria check */
-
k_delayed_work_cancel(&lpn->timer);
lpn->recv_win = msg->recv_win;
@@ -525,15 +552,13 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
err = send_friend_poll();
if (err) {
- friend_cred_clear(cred);
+ lpn->sub = NULL;
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
lpn->recv_win = 0;
lpn->queue_size = 0;
return err;
}
- lpn->counter++;
-
return 0;
}
@@ -542,7 +567,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t addr, counter;
+ uint16_t addr, counter;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Clear Confirm");
@@ -559,7 +584,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
- if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
+ if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) {
BT_WARN("Invalid parameters in Friend Clear Confirm");
return 0;
}
@@ -570,10 +595,10 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void lpn_group_add(u16_t group)
+static void lpn_group_add(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t *free_slot = NULL;
+ uint16_t *free_slot = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
@@ -596,7 +621,7 @@ static void lpn_group_add(u16_t group)
lpn->groups_changed = 1;
}
-static void lpn_group_del(u16_t group)
+static void lpn_group_del(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int i;
@@ -627,18 +652,18 @@ static inline int group_popcount(atomic_t *target)
#endif
}
-static bool sub_update(u8_t op)
+static bool sub_update(uint8_t op)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int added_count = group_popcount(lpn->added);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = lpn->sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = lpn->frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = lpn->sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
@@ -688,8 +713,8 @@ static bool sub_update(u8_t op)
req.xact = lpn->xact_next++;
- if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
- &req_sent_cb, NULL) < 0) {
+ if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
+ &req_sent_cb, NULL) < 0) {
group_zero(lpn->pending);
return false;
}
@@ -711,7 +736,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn)
bt_mesh_scan_disable();
}
- if (lpn->req_attempts < 6) {
+ if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
BT_WARN("Retrying first Friend Poll");
lpn->sent_req = 0;
if (send_friend_poll() == 0) {
@@ -759,14 +784,14 @@ static void lpn_timeout(struct ble_npl_event *work)
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
bt_mesh_scan_disable();
}
- lpn->counter++;
+ lpn->lpn_counter++;
lpn_set_state(BT_MESH_LPN_ENABLED);
lpn->sent_req = 0U;
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
break;
case BT_MESH_LPN_ESTABLISHED:
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
- u8_t req = lpn->sent_req;
+ uint8_t req = lpn->sent_req;
lpn->sent_req = 0;
@@ -800,7 +825,7 @@ static void lpn_timeout(struct ble_npl_event *work)
}
}
-void bt_mesh_lpn_group_add(u16_t group)
+void bt_mesh_lpn_group_add(uint16_t group)
{
BT_DBG("group 0x%04x", group);
@@ -813,7 +838,7 @@ void bt_mesh_lpn_group_add(u16_t group)
sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
}
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
{
int i;
@@ -831,7 +856,7 @@ void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
}
-static s32_t poll_timeout(struct bt_mesh_lpn *lpn)
+static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
{
/* If we're waiting for segment acks keep polling at high freq */
if (bt_mesh_tx_in_progress()) {
@@ -908,7 +933,9 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -920,7 +947,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
struct bt_mesh_ctl_friend_update *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
struct bt_mesh_subnet *sub = rx->sub;
- u32_t iv_index;
+ uint32_t iv_index;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Update");
@@ -944,8 +971,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->established) {
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
-
/* This is normally checked on the transport layer, however
* in this state we're also still accepting master
* credentials so we need to ensure the right ones (Friend
@@ -960,9 +985,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (lpn_cb) {
lpn_cb(lpn->frnd, true);
@@ -980,11 +1003,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags,
(unsigned) iv_index, msg->md);
- if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
- rx->new_key)) {
- bt_mesh_net_beacon_update(sub);
- }
-
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key);
bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
if (lpn->groups_changed) {
@@ -1002,7 +1021,9 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -1019,17 +1040,41 @@ int bt_mesh_lpn_poll(void)
return send_friend_poll();
}
-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))
{
lpn_cb = cb;
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ if (sub == bt_mesh.lpn.sub) {
+ BT_DBG("NetKey deleted");
+ clear_friendship(true, false);
+ }
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("NetKey updated");
+ friend_cred_create(&bt_mesh.lpn.cred[1], sub->keys[1].net);
+ break;
+ default:
+ break;
+ }
+}
+
int bt_mesh_lpn_init(void)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+ if (!bt_mesh_subnet_cb_list[2]) {
+ bt_mesh_subnet_cb_list[2] = subnet_evt;
+ }
+
BT_DBG("");
+ lpn->groups_changed = 0;
+
k_delayed_work_init(&lpn->timer, lpn_timeout);
if (lpn->state == BT_MESH_LPN_ENABLED) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
index 0ff6c9cf..90de2ca0 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
@@ -28,7 +28,7 @@ static inline bool bt_mesh_lpn_established(void)
#endif
}
-static inline bool bt_mesh_lpn_match(u16_t addr)
+static inline bool bt_mesh_lpn_match(uint16_t addr)
{
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
if (bt_mesh_lpn_established()) {
@@ -58,8 +58,8 @@ static inline bool bt_mesh_lpn_timer(void)
void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
-void bt_mesh_lpn_group_add(u16_t group);
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count);
+void bt_mesh_lpn_group_add(uint16_t group);
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count);
void bt_mesh_lpn_disable(bool force);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
index 52fbdbf6..bfb0e1af 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
@@ -18,7 +18,12 @@
#include "adv.h"
#include "prov.h"
+#include "provisioner.h"
#include "net.h"
+#include "subnet.h"
+#include "app_keys.h"
+#include "rpl.h"
+#include "cfg.h"
#include "beacon.h"
#include "lpn.h"
#include "friend.h"
@@ -26,16 +31,18 @@
#include "access.h"
#include "foundation.h"
#include "proxy.h"
+#include "heartbeat.h"
#include "shell.h"
#include "mesh_priv.h"
#include "settings.h"
-u8_t g_mesh_addr_type;
+
+uint8_t g_mesh_addr_type;
static struct ble_gap_event_listener mesh_event_listener;
-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])
{
bool pb_gatt_enabled;
int err;
@@ -58,6 +65,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
pb_gatt_enabled = false;
}
+ /*
+ * FIXME:
+ * Should net_key and iv_index be over-ridden?
+ */
+ if (IS_ENABLED(BLE_MESH_CDB)) {
+ const struct bt_mesh_comp *comp;
+ const struct bt_mesh_prov *prov;
+ struct bt_mesh_cdb_node *node;
+
+ if (!atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ BT_ERR("No valid network");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -EINVAL;
+ }
+
+ comp = bt_mesh_comp_get();
+ if (comp == NULL) {
+ BT_ERR("Failed to get node composition");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -EINVAL;
+ }
+
+ if (!bt_mesh_cdb_subnet_get(net_idx)) {
+ BT_ERR("No subnet with idx %d", net_idx);
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOENT;
+ }
+
+ prov = bt_mesh_prov_get();
+ node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
+ comp->elem_count, net_idx);
+ if (node == NULL) {
+ BT_ERR("Failed to allocate database node");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOMEM;
+ }
+
+ addr = node->addr;
+ iv_index = bt_mesh_cdb.iv_index;
+ memcpy(node->dev_key, dev_key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+ }
+
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
if (err) {
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
@@ -75,20 +129,18 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
memcpy(bt_mesh.dev_key, dev_key, 16);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing network information persistently");
- bt_mesh_store_net();
- bt_mesh_store_subnet(&bt_mesh.sub[0]);
- bt_mesh_store_iv(false);
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+ IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES);
}
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
-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)
{
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
return -EINVAL;
@@ -122,25 +174,30 @@ void bt_mesh_reset(void)
bt_mesh_cfg_reset();
- bt_mesh_rx_reset();
- bt_mesh_tx_reset();
+ bt_mesh_trans_reset();
+ bt_mesh_app_keys_reset();
+ bt_mesh_net_keys_reset();
+
+ bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
+ if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ uint16_t group = BT_MESH_ADDR_ALL_NODES;
+
+ bt_mesh_lpn_group_del(&group, 1);
+ }
+
bt_mesh_lpn_disable(true);
}
if ((MYNEWT_VAL(BLE_MESH_FRIEND))) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
+ bt_mesh_friends_clear();
}
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
bt_mesh_proxy_gatt_disable();
}
- if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
- bt_mesh_proxy_prov_enable();
- }
-
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_clear_net();
}
@@ -162,55 +219,6 @@ bool bt_mesh_is_provisioned(void)
return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
}
-int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- char uuid_buf[BLE_UUID_STR_LEN];
- const struct bt_mesh_prov *prov = bt_mesh_prov_get();
- ble_uuid_t *uuid = BLE_UUID128_DECLARE();
-
- memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
- BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
- bt_mesh_beacon_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_enable();
- bt_mesh_adv_update();
- }
-
- return 0;
-}
-
-int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- bt_mesh_beacon_disable();
- bt_mesh_scan_disable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_disable(true);
- }
-
- return 0;
-}
static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg)
{
@@ -251,9 +259,9 @@ int bt_mesh_suspend(void)
return err;
}
- bt_mesh_hb_pub_disable();
+ bt_mesh_hb_suspend();
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_disable();
}
@@ -266,7 +274,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
if (mod->pub && mod->pub->update) {
- s32_t period_ms = bt_mesh_model_pub_period_get(mod);
+ int32_t period_ms = bt_mesh_model_pub_period_get(mod);
if (period_ms) {
k_delayed_work_submit(&mod->pub->timer, period_ms);
@@ -293,7 +301,9 @@ int bt_mesh_resume(void)
return err;
}
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ bt_mesh_hb_resume();
+
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_enable();
}
@@ -317,6 +327,10 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
return err;
}
+#if (MYNEWT_VAL(BLE_MESH_PROXY))
+ bt_mesh_proxy_init();
+#endif
+
#if (MYNEWT_VAL(BLE_MESH_PROV))
err = bt_mesh_prov_init(prov);
if (err) {
@@ -324,38 +338,65 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
}
#endif
-#if (MYNEWT_VAL(BLE_MESH_PROXY))
- bt_mesh_proxy_init();
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PROV))
- /* Need this to proper link.rx.buf allocation */
- bt_mesh_prov_reset_link();
-#endif
-
+ bt_mesh_cfg_init();
bt_mesh_net_init();
bt_mesh_trans_init();
+ bt_mesh_hb_init();
bt_mesh_beacon_init();
bt_mesh_adv_init();
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
-
- bt_mesh_beacon_enable();
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- bt_mesh_proxy_prov_enable();
-#endif
-
- ble_gap_event_listener_register(&mesh_event_listener,
- bt_mesh_gap_event, NULL);
-
#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
bt_mesh_settings_init();
#endif
+ ble_gap_event_listener_register(&mesh_event_listener,
+ bt_mesh_gap_event, NULL);
+
return 0;
}
+
+static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+ bool vnd, bool primary, void *user_data)
+{
+ if (mod->cb && mod->cb->start) {
+ mod->cb->start(mod);
+ }
+}
+
+int bt_mesh_start(void)
+{
+ if (bt_mesh_beacon_enabled()) {
+ bt_mesh_beacon_enable();
+ } else {
+ bt_mesh_beacon_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
+ bt_mesh_proxy_gatt_enable();
+ bt_mesh_adv_update();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+ bt_mesh_lpn_init();
+ } else {
+ bt_mesh_scan_enable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_init();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+ struct bt_mesh_subnet *sub = bt_mesh_subnet_next(NULL);
+ uint16_t addr = bt_mesh_primary_addr();
+
+ bt_mesh_prov_complete(sub->net_idx, addr);
+ }
+
+ bt_mesh_hb_start();
+
+ bt_mesh_model_foreach(model_start, NULL);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
index f09bb230..213f5437 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
@@ -8,14 +8,28 @@
#ifndef __MESH_PRIV_H
#define __MESH_PRIV_H
+#include
+#include
+
#define BT_MESH_KEY_PRIMARY 0x0000
#define BT_MESH_KEY_ANY 0xffff
-#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)
+enum bt_mesh_key_evt {
+ BT_MESH_KEY_ADDED, /* New key added */
+ BT_MESH_KEY_DELETED, /* Existing key deleted */
+ BT_MESH_KEY_UPDATED, /* KR phase 1, second key added */
+ BT_MESH_KEY_SWAPPED, /* KR phase 2, now sending on second key */
+ BT_MESH_KEY_REVOKED, /* KR phase 3, old key removed */
+};
+
+/** Appkey callback. Instantiate with @ref BT_MESH_APP_KEY_CB */
+struct bt_mesh_app_key_cb {
+ void (*evt_handler)(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
+};
+
struct bt_mesh_net;
+int bt_mesh_start(void);
#define OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
#define OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
index b00cfa52..9755ec1f 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
@@ -11,19 +11,19 @@
#include "mesh/model_cli.h"
#include "mesh_priv.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_gen_model_cli *gen_onoff_cli;
static struct bt_mesh_gen_model_cli *gen_level_cli;
-static u8_t transaction_id = 0;
+static uint8_t transaction_id = 0;
struct gen_onoff_param {
- u8_t *state;
+ uint8_t *state;
};
struct gen_level_param {
- s16_t *level;
+ int16_t *level;
};
static void gen_onoff_status(struct bt_mesh_model *model,
@@ -32,7 +32,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_onoff_param *param;
- u8_t state;
+ uint8_t state;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -62,7 +62,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_level_param *param;
- s16_t level;
+ int16_t level;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -138,7 +138,7 @@ const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
.init = level_cli_init,
};
-static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
+static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, uint32_t op)
{
int err;
@@ -155,8 +155,8 @@ static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
return err;
}
-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_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -184,8 +184,8 @@ done:
return err;
}
-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_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t val, uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -227,8 +227,8 @@ done:
return err;
}
-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_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t *level)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -256,8 +256,8 @@ done:
return err;
}
-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_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t val, int16_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
struct bt_mesh_msg_ctx ctx = {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
index 5f5a8df4..b6f34360 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
@@ -20,7 +20,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(3);
- u8_t *state;
+ uint8_t *state;
bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS);
state = net_buf_simple_add(msg, 1);
@@ -51,7 +51,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
- u8_t state;
+ uint8_t state;
state = buf->om_data[0];
@@ -77,7 +77,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_level_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *level;
+ int16_t *level;
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
level = net_buf_simple_add(msg, 2);
@@ -107,9 +107,9 @@ static void gen_level_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf) {
struct bt_mesh_gen_level_srv *cb = model->user_data;
- s16_t level;
+ int16_t level;
- level = (s16_t) net_buf_simple_pull_le16(buf);
+ level = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("level: %d", level);
if (cb && cb->set) {
@@ -130,7 +130,7 @@ static void light_lightness_status(struct bt_mesh_model *model,
{
struct bt_mesh_light_lightness_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *lightness;
+ int16_t *lightness;
bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS);
lightness = net_buf_simple_add(msg, 2);
@@ -160,9 +160,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf) {
struct bt_mesh_light_lightness_srv *cb = model->user_data;
- s16_t lightness;
+ int16_t lightness;
- lightness = (s16_t) net_buf_simple_pull_le16(buf);
+ lightness = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("lightness: %d", lightness);
if (cb && cb->set) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
index 240314d4..8b86935d 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
@@ -20,6 +20,7 @@
#include "adv.h"
#include "mesh_priv.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "proxy.h"
@@ -29,6 +30,9 @@
#include "beacon.h"
#include "settings.h"
#include "prov.h"
+#include "cfg.h"
+#include "mesh/glue.h"
+#include "mesh/slist.h"
/* Minimum valid Mesh Network PDU length. The Network headers
* themselves take up 9 bytes. After that there is a minumum of 1 byte
@@ -38,6 +42,10 @@
*/
#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8)
+#define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16)
+#define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *)
+#define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf))
+
/* Seq limit after IV Update is triggered */
#define IV_UPDATE_SEQ_LIMIT 8000000
@@ -45,54 +53,34 @@
#define NID(pdu) ((pdu)[0] & 0x7f)
#define CTL(pdu) ((pdu)[1] >> 7)
#define TTL(pdu) ((pdu)[1] & 0x7f)
-#define SEQ(pdu) (((u32_t)(pdu)[2] << 16) | \
- ((u32_t)(pdu)[3] << 8) | (u32_t)(pdu)[4]);
+#define SEQ(pdu) (sys_get_be24(&pdu[2]))
#define SRC(pdu) (sys_get_be16(&(pdu)[5]))
#define DST(pdu) (sys_get_be16(&(pdu)[7]))
-/* Determine how many friendship credentials we need */
-#if (MYNEWT_VAL(BLE_MESH_FRIEND))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)
-#elif (MYNEWT_VAL(BLE_MESH_LOW_POWER))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
-#else
-#define FRIEND_CRED_COUNT 0
-#endif
-
-static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
-
-static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
-static u16_t msg_cache_next;
+static struct {
+ uint32_t src : 15, /* MSb of source is always 0 */
+ seq : 17;
+} msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
+static uint16_t msg_cache_next;
/* Singleton network context (the implementation only supports one) */
struct bt_mesh_net bt_mesh = {
.local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue),
- .sub = {
- [0 ... (MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
- .app_keys = {
- [0 ... (MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- .nodes = {
- [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#endif
};
-static u32_t dup_cache[4];
+static struct os_mbuf_pool loopback_os_mbuf_pool;
+static struct os_mempool loopback_buf_mempool;
+os_membuf_t loopback_mbuf_membuf[
+ OS_MEMPOOL_SIZE(LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS))];
+
+static uint32_t dup_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
static int dup_cache_next;
static bool check_dup(struct os_mbuf *data)
{
- const u8_t *tail = net_buf_simple_tail(data);
- u32_t val;
+ const uint8_t *tail = net_buf_simple_tail(data);
+ uint32_t val;
int i;
val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8);
@@ -109,364 +97,52 @@ static bool check_dup(struct os_mbuf *data)
return false;
}
-static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu)
+static bool msg_cache_match(struct os_mbuf *pdu)
{
- u32_t hash1, hash2;
-
- /* Three least significant bytes of IVI + first byte of SEQ */
- hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2];
-
- /* Two last bytes of SEQ + SRC */
- memcpy(&hash2, &pdu->om_data[3], 4);
-
- return (u64_t)hash1 << 32 | (u64_t)hash2;
-}
-
-static bool msg_cache_match(struct bt_mesh_net_rx *rx,
- struct os_mbuf *pdu)
-{
- u64_t hash = msg_hash(rx, pdu);
- u16_t i;
+ uint16_t i;
for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
- if (msg_cache[i] == hash) {
+ if (msg_cache[i].src == SRC(pdu->om_data) &&
+ msg_cache[i].seq == (SEQ(pdu->om_data) & BIT_MASK(17))) {
return true;
}
}
- /* Add to the cache */
- rx->msg_cache_idx = msg_cache_next++;
- msg_cache[rx->msg_cache_idx] = hash;
- msg_cache_next %= ARRAY_SIZE(msg_cache);
-
return false;
}
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx)
+static void msg_cache_add(struct bt_mesh_net_rx *rx)
{
- int i;
-
- if (net_idx == BT_MESH_KEY_ANY) {
- return &bt_mesh.sub[0];
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == net_idx) {
- return &bt_mesh.sub[i];
- }
- }
-
- return NULL;
+ /* Add to the cache */
+ rx->msg_cache_idx = msg_cache_next++;
+ msg_cache[rx->msg_cache_idx].src = rx->ctx.addr;
+ msg_cache[rx->msg_cache_idx].seq = rx->seq;
+ msg_cache_next %= ARRAY_SIZE(msg_cache);
}
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16])
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index)
{
- u8_t p[] = { 0 };
- u8_t nid;
int err;
- err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
- if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
- return err;
- }
-
- memcpy(keys->net, key, 16);
-
- keys->nid = nid;
-
- BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
- BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));
-
- err = bt_mesh_k3(key, keys->net_id);
- if (err) {
- BT_ERR("Unable to generate Net ID");
- return err;
- }
-
- BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
-
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- err = bt_mesh_identity_key(key, keys->identity);
- if (err) {
- BT_ERR("Unable to generate IdentityKey");
- return err;
- }
-
- BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
-#endif /* GATT_PROXY */
-
- err = bt_mesh_beacon_key(key, keys->beacon);
- if (err) {
- BT_ERR("Unable to generate beacon key");
- return err;
- }
-
- BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
-
- return 0;
-}
-
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
-{
- u16_t lpn_addr, frnd_addr;
- int err;
- u8_t p[9];
-
-#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
- if (cred->addr == bt_mesh.lpn.frnd) {
- lpn_addr = bt_mesh_primary_addr();
- frnd_addr = cred->addr;
- } else {
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
- }
-#else
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
-#endif
-
- BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr);
- BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter,
- cred->frnd_counter);
-
- p[0] = 0x01;
- sys_put_be16(lpn_addr, p + 1);
- sys_put_be16(frnd_addr, p + 3);
- sys_put_be16(cred->lpn_counter, p + 5);
- sys_put_be16(cred->frnd_counter, p + 7);
-
- err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid,
- cred->cred[idx].enc, cred->cred[idx].privacy);
- if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
- return err;
- }
-
- BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid,
- bt_hex(cred->cred[idx].enc, 16));
- BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16));
-
- return 0;
-}
-
-void friend_cred_refresh(u16_t net_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr != BT_MESH_ADDR_UNASSIGNED &&
- cred->net_idx == net_idx) {
- memcpy(&cred->cred[0], &cred->cred[1],
- sizeof(cred->cred[0]));
- }
- }
-}
-
-int friend_cred_update(struct bt_mesh_subnet *sub)
-{
- int err, i;
-
- BT_DBG("net_idx 0x%04x", sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == BT_MESH_ADDR_UNASSIGNED ||
- cred->net_idx != sub->net_idx) {
- continue;
- }
-
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- return err;
- }
- }
-
- return 0;
-}
-
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter)
-{
- struct friend_cred *cred;
- int i, err;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
- (friend_cred[i].addr == addr &&
- friend_cred[i].net_idx == sub->net_idx)) {
- cred = &friend_cred[i];
- break;
- }
- }
-
- if (!cred) {
- BT_WARN("No free friend credential slots");
- return NULL;
- }
-
- cred->net_idx = sub->net_idx;
- cred->addr = addr;
- cred->lpn_counter = lpn_counter;
- cred->frnd_counter = frnd_counter;
-
- err = friend_cred_set(cred, 0, sub->keys[0].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
-
- if (sub->kr_flag) {
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
- }
-
- return cred;
-}
-
-void friend_cred_clear(struct friend_cred *cred)
-{
- cred->net_idx = BT_MESH_KEY_UNUSED;
- cred->addr = BT_MESH_ADDR_UNASSIGNED;
- cred->lpn_counter = 0;
- cred->frnd_counter = 0;
- memset(cred->cred, 0, sizeof(cred->cred));
-}
-
-int friend_cred_del(u16_t net_idx, u16_t addr)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == addr && cred->net_idx == net_idx) {
- friend_cred_clear(cred);
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv)
-{
- int i;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) {
- continue;
- }
-
- if (nid) {
- *nid = cred->cred[sub->kr_flag].nid;
- }
-
- if (enc) {
- *enc = cred->cred[sub->kr_flag].enc;
- }
-
- if (priv) {
- *priv = cred->cred[sub->kr_flag].privacy;
- }
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
-{
- u8_t flags = 0x00;
-
- if (sub && sub->kr_flag) {
- flags |= BT_MESH_NET_FLAG_KR;
- }
-
- if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
- flags |= BT_MESH_NET_FLAG_IVU;
- }
-
- return flags;
-}
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub)
-{
- u8_t flags = bt_mesh_net_flags(sub);
- struct bt_mesh_subnet_keys *keys;
-
- if (sub->kr_flag) {
- BT_DBG("NetIndex %u Using new key", sub->net_idx);
- keys = &sub->keys[1];
- } else {
- BT_DBG("NetIndex %u Using current key", sub->net_idx);
- keys = &sub->keys[0];
- }
-
- BT_DBG("flags 0x%02x, IVI 0x%08x", flags, (unsigned) bt_mesh.iv_index);
-
- return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
- bt_mesh.iv_index, sub->auth);
-}
-
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index)
-{
- struct bt_mesh_subnet *sub;
- int err;
-
- BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags,
- (unsigned) iv_index);
+ BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index);
BT_DBG("NetKey %s", bt_hex(key, 16));
+ if (BT_MESH_KEY_REFRESH(flags)) {
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_PHASE_2, NULL, key);
+ } else {
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_NORMAL, key, NULL);
+ }
+
+ if (err) {
+ BT_ERR("Failed creating subnet");
+ return err;
+ }
+
(void)memset(msg_cache, 0, sizeof(msg_cache));
msg_cache_next = 0U;
- sub = &bt_mesh.sub[0];
-
- sub->kr_flag = BT_MESH_KEY_REFRESH(flags);
- if (sub->kr_flag) {
- err = bt_mesh_net_keys_create(&sub->keys[1], key);
- if (err) {
- return -EIO;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- } else {
- err = bt_mesh_net_keys_create(&sub->keys[0], key);
- if (err) {
- return -EIO;
- }
- }
-
- sub->net_idx = idx;
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
bt_mesh.iv_index = iv_index;
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS,
BT_MESH_IV_UPDATE(flags));
@@ -477,96 +153,16 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
*/
bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing network information persistently");
+ bt_mesh_store_net();
+ bt_mesh_store_subnet(idx);
+ bt_mesh_store_iv(false);
+ }
return 0;
}
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub)
-{
- int i;
-
- BT_DBG("idx 0x%04x", sub->net_idx);
-
- memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != sub->net_idx || !key->updated) {
- continue;
- }
-
- memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0]));
- key->updated = false;
- }
-}
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key)
-{
- if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) {
- BT_WARN("KR change in normal operation. Are we blacklisted?");
- return false;
- }
-
- sub->kr_flag = new_kr;
-
- if (sub->kr_flag) {
- if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
- BT_DBG("Phase 1 -> Phase 2");
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- return true;
- }
- } else {
- switch (sub->kr_phase) {
- case BT_MESH_KR_PHASE_1:
- if (!new_key) {
- /* Ignore */
- break;
- }
- /* Upon receiving a Secure Network beacon with the KR flag set
- * to 0 using the new NetKey in Phase 1, the node shall
- * immediately transition to Phase 3, which effectively skips
- * Phase 2.
- *
- * Intentional fall-through.
- */
- case BT_MESH_KR_PHASE_2:
- BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase);
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(sub->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- return true;
- }
- }
-
- return false;
-}
-
-void bt_mesh_rpl_reset(void)
-{
- int i;
-
- /* Discard "old old" IV Index entries from RPL and flag
- * any other ones (which are valid) as old.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->src) {
- if (rpl->old_iv) {
- memset(rpl, 0, sizeof(*rpl));
- } else {
- rpl->old_iv = true;
- }
- }
- }
-}
-
#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
void bt_mesh_iv_update_test(bool enable)
{
@@ -588,29 +184,12 @@ bool bt_mesh_iv_update(void)
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
}
- bt_mesh_net_sec_update(NULL);
-
return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
}
#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
-/* Used for sending immediate beacons to Friend queues and GATT clients */
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
{
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
- bt_mesh_proxy_beacon_send(sub);
- }
-}
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
-{
- int i;
-
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
/* We're currently in IV Update mode */
@@ -644,7 +223,7 @@ bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
if (iv_index > bt_mesh.iv_index + 1) {
BT_WARN("Performing IV Index Recovery");
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+ bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0;
goto do_update;
@@ -694,10 +273,20 @@ do_update:
k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_net_beacon_update(&bt_mesh.sub[i]);
- }
+ /* Notify other modules */
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+ bt_mesh_proxy_beacon_send(NULL);
+ }
+
+ bt_mesh_subnet_foreach(bt_mesh_beacon_update);
+
+ if (MYNEWT_VAL(BLE_MESH_CDB)) {
+ bt_mesh_cdb_iv_update(iv_index, iv_update);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -707,9 +296,9 @@ do_update:
return true;
}
-u32_t bt_mesh_next_seq(void)
+uint32_t bt_mesh_next_seq(void)
{
- u32_t seq = bt_mesh.seq++;
+ uint32_t seq = bt_mesh.seq++;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_seq();
@@ -720,89 +309,63 @@ u32_t bt_mesh_next_seq(void)
bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) {
bt_mesh_beacon_ivu_initiator(true);
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
- bt_mesh_net_sec_update(NULL);
}
return seq;
}
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data)
-{
- const u8_t *enc, *priv;
- u32_t seq;
- u16_t dst;
- int err;
-
- BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
- buf->om_len);
-
- enc = sub->keys[new_key].enc;
- priv = sub->keys[new_key].privacy;
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("deobfuscate failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("decrypt failed (err %d)", err);
- return err;
- }
-
- seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
-
- /* Get destination, in case it's a proxy client */
- dst = DST(buf->om_data);
-
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("encrypt failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("obfuscate failed (err %d)", err);
- return err;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_proxy_relay(buf, dst)) {
- send_cb_finalize(cb, cb_data);
- } else {
- bt_mesh_adv_send(buf, cb, cb_data);
- }
-
- return 0;
-}
-
static void bt_mesh_net_local(struct ble_npl_event *work)
{
struct os_mbuf *buf;
while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
- BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
- bt_mesh_net_recv(buf, 0, BT_MESH_NET_IF_LOCAL);
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+ struct bt_mesh_net_rx rx = {
+ .ctx = {
+ .net_idx = sub->net_idx,
+ /* Initialize AppIdx to a sane value */
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .recv_ttl = TTL(buf->om_data),
+ /* TTL=1 only goes to local IF */
+ .send_ttl = 1U,
+ .addr = SRC(buf->om_data),
+ .recv_dst = DST(buf->om_data),
+ .recv_rssi = 0,
+ },
+ .net_if = BT_MESH_NET_IF_LOCAL,
+ .sub = sub,
+ .old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01)),
+ .ctl = CTL(buf->om_data),
+ .seq = SEQ(buf->om_data),
+ .new_key = SUBNET_KEY_TX_IDX(sub),
+ .local_match = 1U,
+ .friend_match = 0U,
+ };
+
+ BT_DBG("src: 0x%04x dst: 0x%04x seq 0x%06x sub %p", rx.ctx.addr,
+ rx.ctx.addr, rx.seq, sub);
+
+ (void) bt_mesh_trans_recv(buf, &rx);
net_buf_unref(buf);
}
}
-int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
- bool proxy)
+static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx)
+{
+#if defined(BLE_MESH_LOW_POWER)
+ if (tx->friend_cred && bt_mesh_lpn_established()) {
+ return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)];
+ }
+#endif
+
+ tx->friend_cred = 0U;
+ return &tx->sub->keys[SUBNET_KEY_TX_IDX(tx->sub)].msg;
+}
+
+static int net_header_encode(struct bt_mesh_net_tx *tx, uint8_t nid,
+ struct os_mbuf *buf)
{
const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- u32_t seq_val;
- u8_t nid;
- const u8_t *enc, *priv;
- u8_t *seq;
- int err;
if (ctl && net_buf_simple_tailroom(buf) < 8) {
BT_ERR("Insufficient MIC space for CTL PDU");
@@ -818,11 +381,7 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_be16(buf, tx->ctx->addr);
net_buf_simple_push_be16(buf, tx->src);
- seq = net_buf_simple_push(buf, 3);
- seq_val = bt_mesh_next_seq();
- seq[0] = seq_val >> 16;
- seq[1] = seq_val >> 8;
- seq[2] = seq_val;
+ net_buf_simple_push_be24(buf, bt_mesh_next_seq());
if (ctl) {
net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80);
@@ -830,37 +389,68 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
}
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) {
- if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED,
- &nid, &enc, &priv)) {
- BT_WARN("Falling back to master credentials");
-
- tx->friend_cred = 0;
-
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
- }
- } else {
- tx->friend_cred = 0;
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
- }
-
net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy);
+ return 0;
+}
+
+static int net_encrypt(struct os_mbuf *buf,
+ const struct bt_mesh_net_cred *cred, uint32_t iv_index,
+ bool proxy)
+{
+ int err;
+
+ err = bt_mesh_net_encrypt(cred->enc, buf, iv_index, proxy);
if (err) {
return err;
}
- return bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
+ return bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy);
+}
+
+int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
+ bool proxy)
+{
+ const struct bt_mesh_net_cred *cred;
+ int err;
+
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
+ if (err) {
+ return err;
+ }
+
+ return net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, proxy);
+}
+
+static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data,
+ size_t len)
+{
+ struct os_mbuf *buf;
+
+ buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, 0);
+ if (!buf) {
+ BT_WARN("Unable to allocate loopback");
+ return -ENOMEM;
+ }
+
+ BT_DBG("");
+
+ LOOPBACK_BUF_SUB(buf) = tx->sub;
+
+ net_buf_add_mem(buf, data, len);
+
+ net_buf_slist_put(&bt_mesh.local_queue, buf);
+
+ k_work_submit(&bt_mesh.local_work);
+
+ return 0;
}
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
+ const struct bt_mesh_net_cred *cred;
int err;
BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
@@ -869,11 +459,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("Seq 0x%06x", bt_mesh.seq);
- if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
- tx->ctx->send_ttl = bt_mesh_default_ttl_get();
- }
-
- err = bt_mesh_net_encode(tx, buf, false);
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
if (err) {
goto done;
}
@@ -881,225 +468,118 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Deliver to GATT Proxy Clients if necessary. Mesh spec 3.4.5.2:
- * "The output filter of the interface connected to advertising or
- * GATT bearers shall drop all messages with TTL value set to 1."
- */
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) &&
- tx->ctx->send_ttl != 1) {
- if (bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
- BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
- /* Notify completion if this only went
- * through the Mesh Proxy.
- */
- send_cb_finalize(cb, cb_data);
-
- err = 0;
- goto done;
- }
- }
-
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_elem_find(tx->ctx->addr)) {
- if (cb && cb->start) {
- cb->start(0, 0, cb_data);
+ err = loopback(tx, buf->om_data, buf->om_len);
+
+ /* Local unicast messages should not go out to network */
+ if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) ||
+ tx->ctx->send_ttl == 1U) {
+ if (!err) {
+ send_cb_finalize(cb, cb_data);
+ }
+
+ goto done;
}
- net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
- if (cb && cb->end) {
- cb->end(0, cb_data);
- }
- k_work_submit(&bt_mesh.local_work);
- } else if (tx->ctx->send_ttl != 1) {
- /* Deliver to to the advertising network interface. Mesh spec
- * 3.4.5.2: "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- bt_mesh_adv_send(buf, cb, cb_data);
}
+ /* Mesh spec 3.4.5.2: "The output filter of the interface connected to
+ * advertising or GATT bearers shall drop all messages with TTL value
+ * set to 1." If a TTL=1 packet wasn't for a local interface, it is
+ * invalid.
+ */
+ if (tx->ctx->send_ttl == 1U) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ err = net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, false);
+ if (err) {
+ goto done;
+ }
+
+ /* Deliver to GATT Proxy Clients if necessary. */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
+ BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
+ /* Notify completion if this only went through the Mesh Proxy */
+ send_cb_finalize(cb, cb_data);
+
+ err = 0;
+ goto done;
+ }
+
+ bt_mesh_adv_send(buf, cb, cb_data);
done:
net_buf_unref(buf);
return err;
}
-static bool auth_match(struct bt_mesh_subnet_keys *keys,
- const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8])
+void bt_mesh_net_loopback_clear(uint16_t net_idx)
{
- u8_t net_auth[8];
+ struct net_buf_slist_t new_list;
+ struct os_mbuf *buf;
- if (memcmp(net_id, keys->net_id, 8)) {
+ BT_DBG("0x%04x", net_idx);
+
+ net_buf_slist_init(&new_list);
+
+ while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+
+ if (net_idx == BT_MESH_KEY_ANY || net_idx == sub->net_idx) {
+ BT_DBG("Dropped 0x%06x", SEQ(buf->om_data));
+ net_buf_unref(buf);
+ } else {
+ net_buf_slist_put(&new_list, buf);
+ }
+ }
+
+ bt_mesh.local_queue = new_list;
+}
+
+static bool net_decrypt(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred)
+{
+ bool proxy = (rx->net_if == BT_MESH_NET_IF_PROXY_CFG);
+
+ if (NID(in->om_data) != cred->nid) {
return false;
}
- bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index,
- net_auth);
+ BT_DBG("NID 0x%02x", NID(in->om_data));
+ BT_DBG("IVI %u net->iv_index 0x%08x", IVI(in->om_data), bt_mesh.iv_index);
- if (memcmp(auth, net_auth, 8)) {
- BT_WARN("Authentication Value %s != %s",
- bt_hex(auth, 8), bt_hex(net_auth, 8));
+ rx->old_iv = (IVI(in->om_data) != (bt_mesh.iv_index & 0x01));
+ net_buf_simple_reset(out);
+ net_buf_simple_add_mem(out, in->om_data, in->om_len);
+
+ if (bt_mesh_net_obfuscate(out->om_data, BT_MESH_NET_IVI_RX(rx),
+ cred->privacy)) {
return false;
}
- return true;
-}
-
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) {
- *new_key = false;
- return sub;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) {
- *new_key = true;
- return sub;
- }
- }
-
- return NULL;
-}
-
-static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
- const u8_t *priv, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
- BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data),
- (unsigned) bt_mesh.iv_index);
-
- rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01));
-
- net_buf_simple_init(buf, 0);
- memcpy(net_buf_simple_add(buf, data_len), data, data_len);
-
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- return -ENOENT;
- }
-
- if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
- BT_WARN("Duplicate found in Network Message Cache");
- return -EALREADY;
- }
-
- rx->ctx.addr = SRC(buf->om_data);
+ rx->ctx.addr = SRC(out->om_data);
if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) {
- BT_WARN("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
- return -EINVAL;
+ BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
+ return false;
+ }
+
+ if (bt_mesh_elem_find(rx->ctx.addr)) {
+ BT_DBG("Dropping locally originated packet");
+ return false;
+ }
+
+ if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out)) {
+ BT_DBG("Duplicate found in Network Message Cache");
+ return false;
}
BT_DBG("src 0x%04x", rx->ctx.addr);
-
- if ((MYNEWT_VAL(BLE_MESH_PROXY)) &&
- rx->net_if == BT_MESH_NET_IF_PROXY_CFG) {
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx),
- true);
- }
-
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
-}
-
-static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- int i;
-
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (NID(data) == cred->cred[0].nid &&
- !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy,
- data, data_len, rx, buf)) {
- return 0;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == cred->cred[1].nid &&
- !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
- struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_subnet *sub;
- unsigned int i;
-
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- sub = &bt_mesh.sub[i];
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
- IS_ENABLED(CONFIG_BT_MESH_FRIEND)) &&
- !friend_decrypt(sub, data, data_len, rx, buf)) {
- rx->friend_cred = 1U;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (NID(data) == sub->keys[0].nid &&
- !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
- data, data_len, rx, buf)) {
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == sub->keys[1].nid &&
- !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
- }
-
- return false;
+ return bt_mesh_net_decrypt(cred->enc, out, BT_MESH_NET_IVI_RX(rx),
+ proxy) == 0;
}
/* Relaying from advertising to the advertising bearer should only happen
@@ -1110,8 +590,6 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
static bool relay_to_adv(enum bt_mesh_net_if net_if)
{
switch (net_if) {
- case BT_MESH_NET_IF_LOCAL:
- return true;
case BT_MESH_NET_IF_ADV:
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
case BT_MESH_NET_IF_PROXY:
@@ -1124,27 +602,16 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if)
static void bt_mesh_net_relay(struct os_mbuf *sbuf,
struct bt_mesh_net_rx *rx)
{
- const u8_t *enc, *priv;
+ const struct bt_mesh_net_cred *cred;
struct os_mbuf *buf;
- u8_t nid, transmit;
+ uint8_t transmit;
- if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
- /* Locally originated PDUs with TTL=1 will only be delivered
- * to local elements as per Mesh Profile 1.0 section 3.4.5.2:
- * "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- if (rx->ctx.recv_ttl == 1) {
- return;
- }
- } else {
- if (rx->ctx.recv_ttl <= 1) {
- return;
- }
+ if (rx->ctx.recv_ttl <= 1U) {
+ return;
}
if (rx->net_if == BT_MESH_NET_IF_ADV &&
+ !rx->friend_cred &&
bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED &&
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) {
return;
@@ -1157,7 +624,7 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
* Anything else (like GATT to adv, or locally originated packets)
* use the Network Transmit state.
*/
- if (rx->net_if == BT_MESH_NET_IF_ADV) {
+ if (rx->net_if == BT_MESH_NET_IF_ADV && !rx->friend_cred) {
transmit = bt_mesh_relay_retransmit_get();
} else {
transmit = bt_mesh_net_transmit_get();
@@ -1169,57 +636,45 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
return;
}
- /* Only decrement TTL for non-locally originated packets */
- if (rx->net_if != BT_MESH_NET_IF_LOCAL) {
- /* Leave CTL bit intact */
- sbuf->om_data[1] &= 0x80;
- sbuf->om_data[1] |= rx->ctx.recv_ttl - 1;
- }
+ /* Leave CTL bit intact */
+ sbuf->om_data[1] &= 0x80;
+ sbuf->om_data[1] |= rx->ctx.recv_ttl - 1U;
net_buf_add_mem(buf, sbuf->om_data, sbuf->om_len);
- enc = rx->sub->keys[rx->sub->kr_flag].enc;
- priv = rx->sub->keys[rx->sub->kr_flag].privacy;
- nid = rx->sub->keys[rx->sub->kr_flag].nid;
+ cred = &rx->sub->keys[SUBNET_KEY_TX_IDX(rx->sub)].msg;
BT_DBG("Relaying packet. TTL is now %u", TTL(buf->om_data));
/* Update NID if RX or RX was with friend credentials */
if (rx->friend_cred) {
buf->om_data[0] &= 0x80; /* Clear everything except IVI */
- buf->om_data[0] |= nid;
+ buf->om_data[0] |= cred->nid;
}
/* We re-encrypt and obfuscate using the received IVI rather than
* the normal TX IVI (which may be different) since the transport
* layer nonce includes the IVI.
*/
- if (bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false)) {
+ if (net_encrypt(buf, cred, BT_MESH_NET_IVI_RX(rx), false)) {
BT_ERR("Re-encrypting failed");
goto done;
}
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- BT_ERR("Re-obfuscating failed");
- goto done;
- }
-
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Sending to the GATT bearer should only happen if GATT Proxy
- * is enabled or the message originates from the local node.
+ /* When the Friend node relays message for lpn, the message will be
+ * retransmitted using the managed master security credentials and
+ * the Network PDU shall be retransmitted to all network interfaces.
*/
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
- rx->net_if == BT_MESH_NET_IF_LOCAL)) {
- if (bt_mesh_proxy_relay(buf, rx->ctx.recv_dst) &&
- BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
- goto done;
- }
+ (rx->friend_cred ||
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) {
+ bt_mesh_proxy_relay(buf, rx->ctx.recv_dst);
}
- if (relay_to_adv(rx->net_if)) {
+ if (relay_to_adv(rx->net_if) || rx->friend_cred) {
bt_mesh_adv_send(buf, NULL, NULL);
}
@@ -1238,26 +693,26 @@ void bt_mesh_net_header_parse(struct os_mbuf *buf,
rx->ctx.recv_dst = DST(buf->om_data);
}
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out)
{
- if (data->om_len < BT_MESH_NET_MIN_PDU_LEN) {
- BT_WARN("Dropping too short mesh packet (len %u)", data->om_len);
- BT_WARN("%s", bt_hex(data->om_data, data->om_len));
+ if (in->om_len < BT_MESH_NET_MIN_PDU_LEN) {
+ BT_WARN("Dropping too short mesh packet (len %u)", in->om_len);
+ BT_WARN("%s", bt_hex(in->om_data, in->om_len));
return -EINVAL;
}
- if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) {
- BT_DBG("duplicate packet; dropping %u bytes: %s", data->om_len,
- bt_hex(data->om_data, data->om_len));
+ if (net_if == BT_MESH_NET_IF_ADV && check_dup(in)) {
+ BT_DBG("duplicate packet; dropping %u bytes: %s", in->om_len,
+ bt_hex(in->om_data, in->om_len));
return -EINVAL;
}
- BT_DBG("%u bytes: %s", data->om_len, bt_hex(data->om_data, data->om_len));
+ BT_DBG("%u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len));
rx->net_if = net_if;
- if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) {
+ if (!bt_mesh_net_cred_find(rx, in, out, net_decrypt)) {
BT_DBG("Unable to find matching net for packet");
return -ENOENT;
}
@@ -1265,7 +720,7 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
/* Initialize AppIdx to a sane value */
rx->ctx.app_idx = BT_MESH_KEY_UNUSED;
- rx->ctx.recv_ttl = TTL(buf->om_data);
+ rx->ctx.recv_ttl = TTL(out->om_data);
/* Default to responding with TTL 0 for non-routed messages */
if (rx->ctx.recv_ttl == 0) {
@@ -1274,12 +729,12 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT;
}
- rx->ctl = CTL(buf->om_data);
- rx->seq = SEQ(buf->om_data);
- rx->ctx.recv_dst = DST(buf->om_data);
+ rx->ctl = CTL(out->om_data);
+ rx->seq = SEQ(out->om_data);
+ rx->ctx.recv_dst = DST(out->om_data);
- BT_DBG("Decryption successful. Payload len %u: %s", buf->om_len,
- bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("Decryption successful. Payload len %u: %s", out->om_len,
+ bt_hex(out->om_data, out->om_len));
if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
@@ -1287,24 +742,16 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
return -EBADMSG;
}
- if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) {
- BT_ERR("Destination address is RFU; dropping packet");
- return -EBADMSG;
- }
-
- if (net_if != BT_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) {
- BT_DBG("Dropping locally originated packet");
- return -EBADMSG;
- }
-
BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
rx->ctx.recv_ttl);
- BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("PDU: %s", bt_hex(out->om_data, out->om_len));
+
+ msg_cache_add(rx);
return 0;
}
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
enum bt_mesh_net_if net_if)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
@@ -1348,7 +795,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
*/
if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) {
BT_WARN("Removing rejected message from Network Message Cache");
- msg_cache[rx.msg_cache_idx] = 0ULL;
+ msg_cache[rx.msg_cache_idx].src = BT_MESH_ADDR_UNASSIGNED;
/* Rewind the next index now that we're not using this entry */
msg_cache_next = rx.msg_cache_idx;
}
@@ -1368,7 +815,8 @@ done:
static void ivu_refresh(struct ble_npl_event *work)
{
- bt_mesh.ivu_duration += BT_MESH_IVU_HOURS;
+ bt_mesh.ivu_duration = MIN(UINT8_MAX,
+ bt_mesh.ivu_duration + BT_MESH_IVU_HOURS);
BT_DBG("%s for %u hour%s",
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ?
@@ -1392,42 +840,22 @@ static void ivu_refresh(struct ble_npl_event *work)
}
}
-void bt_mesh_net_start(void)
-{
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
- bt_mesh_beacon_enable();
- } else {
- bt_mesh_beacon_disable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
- bt_mesh_proxy_gatt_enable();
- bt_mesh_adv_update();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
- bt_mesh_lpn_init();
- } else {
- bt_mesh_scan_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_init();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
- u16_t net_idx = bt_mesh.sub[0].net_idx;
- u16_t addr = bt_mesh_primary_addr();
-
- bt_mesh_prov_complete(net_idx, addr);
- }
-}
-
void bt_mesh_net_init(void)
{
+ int rc;
+
k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh);
k_work_init(&bt_mesh.local_work, bt_mesh_net_local);
net_buf_slist_init(&bt_mesh.local_queue);
+
+ rc = os_mempool_init(&loopback_buf_mempool, MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS),
+ LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ &loopback_mbuf_membuf[0], "loopback_buf_pool");
+ assert(rc == 0);
+
+ rc = os_mbuf_pool_init(&loopback_os_mbuf_pool, &loopback_buf_mempool,
+ LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS));
+ assert(rc == 0);
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
index 976da005..f4b1192b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
@@ -9,13 +9,7 @@
#ifndef __NET_H__
#define __NET_H__
-#define BT_MESH_NET_FLAG_KR BIT(0)
-#define BT_MESH_NET_FLAG_IVU BIT(1)
-
-#define BT_MESH_KR_NORMAL 0x00
-#define BT_MESH_KR_PHASE_1 0x01
-#define BT_MESH_KR_PHASE_2 0x02
-#define BT_MESH_KR_PHASE_3 0x03
+#include "subnet.h"
#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01)
#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
@@ -31,64 +25,13 @@
CONFIG_BT_MESH_IVU_DIVIDER)
#define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS)
-struct bt_mesh_app_key {
- u16_t net_idx;
- u16_t app_idx;
- bool updated;
- struct bt_mesh_app_keys {
- u8_t id;
- u8_t val[16];
- } keys[2];
-};
+struct bt_mesh_net_cred;
struct bt_mesh_node {
- u16_t addr;
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
-};
-
-struct bt_mesh_subnet {
- u32_t beacon_sent; /* Timestamp of last sent beacon */
- u8_t beacons_last; /* Number of beacons during last
- * observation window
- */
- u8_t beacons_cur; /* Number of beaconds observed during
- * currently ongoing window.
- */
-
- u8_t beacon_cache[21]; /* Cached last authenticated beacon */
-
- u16_t net_idx; /* NetKeyIndex */
-
- bool kr_flag; /* Key Refresh Flag */
- u8_t kr_phase; /* Key Refresh Phase */
-
- u8_t node_id; /* Node Identity State */
- u32_t node_id_start; /* Node Identity started timestamp */
-
- u8_t auth[8]; /* Beacon Authentication Value */
-
- struct bt_mesh_subnet_keys {
- u8_t net[16]; /* NetKey */
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t net_id[8]; /* Network ID */
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- u8_t identity[16]; /* IdentityKey */
-#endif
- u8_t privacy[16]; /* PrivacyKey */
- u8_t beacon[16]; /* BeaconKey */
- } keys[2];
-};
-
-struct bt_mesh_rpl {
- u16_t src;
- bool old_iv;
-#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
- bool store;
-#endif
- u32_t seq;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t dev_key[16];
+ uint8_t num_elem;
};
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -100,23 +43,23 @@ struct bt_mesh_rpl {
#endif
struct bt_mesh_friend {
- u16_t lpn;
- u8_t recv_delay;
- u8_t fsn:1,
+ uint16_t lpn;
+ uint8_t recv_delay;
+ uint8_t fsn:1,
send_last:1,
pending_req:1,
- sec_update:1,
pending_buf:1,
- valid:1,
established:1;
- s32_t poll_to;
- u8_t num_elem;
- u16_t lpn_counter;
- u16_t counter;
+ int32_t poll_to;
+ uint8_t num_elem;
+ uint16_t lpn_counter;
+ uint16_t counter;
- u16_t net_idx;
+ struct bt_mesh_subnet *subnet;
- u16_t sub_list[FRIEND_SUB_LIST_SIZE];
+ struct bt_mesh_net_cred cred[2];
+
+ uint16_t sub_list[FRIEND_SUB_LIST_SIZE];
struct k_delayed_work timer;
@@ -127,19 +70,19 @@ struct bt_mesh_friend {
* the current number of segments, in the queue. This is
* used for Friend Queue free space calculations.
*/
- u8_t seg_count;
+ uint8_t seg_count;
} seg[FRIEND_SEG_RX];
struct os_mbuf *last;
struct net_buf_slist_t queue;
- u32_t queue_size;
+ uint32_t queue_size;
/* Friend Clear Procedure */
struct {
- u32_t start; /* Clear Procedure start */
- u16_t frnd; /* Previous Friend's address */
- u16_t repeat_sec; /* Repeat timeout in seconds */
+ uint32_t start; /* Clear Procedure start */
+ uint16_t frnd; /* Previous Friend's address */
+ uint16_t repeat_sec; /* Repeat timeout in seconds */
struct k_delayed_work timer; /* Repeat timer */
} clear;
};
@@ -165,23 +108,23 @@ struct bt_mesh_lpn {
} state;
/* Transaction Number (used for subscription list) */
- u8_t xact_next;
- u8_t xact_pending;
- u8_t sent_req;
+ uint8_t xact_next;
+ uint8_t xact_pending;
+ uint8_t sent_req;
/* Address of our Friend when we're a LPN. Unassigned if we don't
* have a friend yet.
*/
- u16_t frnd;
+ uint16_t frnd;
/* Value from the friend offer */
- u8_t recv_win;
+ uint8_t recv_win;
- u8_t req_attempts; /* Number of Request attempts */
+ uint8_t req_attempts; /* Number of Request attempts */
- s32_t poll_timeout;
+ int32_t poll_timeout;
- u8_t groups_changed:1, /* Friend Subscription List needs updating */
+ uint8_t groups_changed:1, /* Friend Subscription List needs updating */
pending_poll:1, /* Poll to be sent after subscription */
disable:1, /* Disable LPN after clearing */
fsn:1, /* Friend Sequence Number */
@@ -189,22 +132,29 @@ struct bt_mesh_lpn {
clear_success:1; /* Friend Clear Confirm received */
/* Friend Queue Size */
- u8_t queue_size;
+ uint8_t queue_size;
+
+ /* FriendCounter */
+ uint16_t frnd_counter;
/* LPNCounter */
- u16_t counter;
+ uint16_t lpn_counter;
/* Previous Friend of this LPN */
- u16_t old_friend;
+ uint16_t old_friend;
/* Duration reported for last advertising packet */
- u16_t adv_duration;
+ uint16_t adv_duration;
/* Next LPN related action timer */
struct k_delayed_work timer;
/* Subscribed groups */
- u16_t groups[LPN_GROUPS];
+ uint16_t groups[LPN_GROUPS];
+
+ struct bt_mesh_subnet *sub;
+
+ struct bt_mesh_net_cred cred[2];
/* Bit fields for tracking which groups the Friend knows about */
ATOMIC_DEFINE(added, LPN_GROUPS);
@@ -231,15 +181,20 @@ enum {
BT_MESH_CFG_PENDING,
BT_MESH_MOD_PENDING,
BT_MESH_VA_PENDING,
- BT_MESH_NODES_PENDING,
+
+ /* Feature flags */
+ BT_MESH_RELAY,
+ BT_MESH_BEACON,
+ BT_MESH_GATT_PROXY,
+ BT_MESH_FRIEND,
/* Don't touch - intentionally last */
BT_MESH_FLAG_COUNT,
};
struct bt_mesh_net {
- u32_t iv_index; /* Current IV Index */
- u32_t seq; /* Next outgoing sequence number (24 bits) */
+ uint32_t iv_index; /* Current IV Index */
+ uint32_t seq; /* Next outgoing sequence number (24 bits) */
ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT);
@@ -257,22 +212,16 @@ struct bt_mesh_net {
#endif
/* Number of hours in current IV Update state */
- u8_t ivu_duration;
+ uint8_t ivu_duration;
+
+ uint8_t net_xmit;
+ uint8_t relay_xmit;
+ uint8_t default_ttl;
/* Timer to track duration in current IV Update state */
struct k_delayed_work ivu_timer;
- u8_t dev_key[16];
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)];
-#endif
-
- struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)];
-
- struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)];
-
- struct bt_mesh_rpl rpl[MYNEWT_VAL(BLE_MESH_CRPL)];
+ uint8_t dev_key[16];
};
/* Network interface */
@@ -287,24 +236,24 @@ enum bt_mesh_net_if {
struct bt_mesh_net_rx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx ctx;
- u32_t seq; /* Sequence Number */
- u8_t old_iv:1, /* iv_index - 1 was used */
+ uint32_t seq; /* Sequence Number */
+ uint8_t old_iv:1, /* iv_index - 1 was used */
new_key:1, /* Data was encrypted with updated key */
friend_cred:1, /* Data was encrypted with friend cred */
ctl:1, /* Network Control */
net_if:2, /* Network interface */
local_match:1, /* Matched a local element */
friend_match:1; /* Matched an LPN we're friends for */
- u16_t msg_cache_idx; /* Index of entry in message cache */
+ uint16_t msg_cache_idx; /* Index of entry in message cache */
};
/* Encoding context for Network/Transport data */
struct bt_mesh_net_tx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx *ctx;
- u16_t src;
- u8_t xmit;
- u8_t friend_cred:1,
+ uint16_t src;
+ uint8_t xmit;
+ uint8_t friend_cred:1,
aszmic:1,
aid:6;
};
@@ -318,80 +267,36 @@ extern struct bt_mesh_net bt_mesh;
#define BT_MESH_NET_HDR_LEN 9
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16]);
+static inline void *net_buf_user_data(const struct os_mbuf *buf)
+{
+ return (void *)buf->om_data;
+}
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index);
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index);
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key);
-
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
-
-void bt_mesh_rpl_reset(void);
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
-
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
-
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
-
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key);
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
bool proxy);
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out);
+
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data);
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data);
-
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
-
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
enum bt_mesh_net_if net_if);
-u32_t bt_mesh_next_seq(void);
+void bt_mesh_net_loopback_clear(uint16_t net_idx);
-void bt_mesh_net_start(void);
+uint32_t bt_mesh_next_seq(void);
void bt_mesh_net_init(void);
void bt_mesh_net_header_parse(struct os_mbuf *buf,
struct bt_mesh_net_rx *rx);
-/* Friendship Credential Management */
-struct friend_cred {
- u16_t net_idx;
- u16_t addr;
-
- u16_t lpn_counter;
- u16_t frnd_counter;
-
- struct {
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t privacy[16]; /* PrivacyKey */
- } cred[2];
-};
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv);
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]);
-void friend_cred_refresh(u16_t net_idx);
-int friend_cred_update(struct bt_mesh_subnet *sub);
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter);
-void friend_cred_clear(struct friend_cred *cred);
-int friend_cred_del(u16_t net_idx, u16_t addr);
static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
void *cb_data)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
new file mode 100644
index 00000000..28391b18
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
@@ -0,0 +1,888 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include
+#include
+#include "mesh/mesh.h"
+#include
+#include "testing.h"
+#include "net.h"
+#include "prov.h"
+#include "adv.h"
+#include "crypto.h"
+#include "beacon.h"
+#include "prov.h"
+#include "mesh/glue.h"
+
+#define GPCF(gpc) (gpc & 0x03)
+#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
+#define GPC_ACK 0x01
+#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
+#define GPC_CTL(op) (((op) << 2) | 0x03)
+
+#define START_PAYLOAD_MAX 20
+#define CONT_PAYLOAD_MAX 23
+
+#define START_LAST_SEG(gpc) (gpc >> 2)
+#define CONT_SEG_INDEX(gpc) (gpc >> 2)
+
+#define BEARER_CTL(gpc) (gpc >> 2)
+#define LINK_OPEN 0x00
+#define LINK_ACK 0x01
+#define LINK_CLOSE 0x02
+
+#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
+#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
+
+#define XACT_ID_MAX 0x7f
+#define XACT_ID_NVAL 0xff
+#define SEG_NVAL 0xff
+
+#define RETRANSMIT_TIMEOUT K_MSEC(MYNEWT_VAL(BLE_MESH_PB_ADV_RETRANS_TIMEOUT))
+#define BUF_TIMEOUT K_MSEC(400)
+#define CLOSING_TIMEOUT K_SECONDS(3)
+#define TRANSACTION_TIMEOUT K_SECONDS(30)
+
+/* Acked messages, will do retransmissions manually, taking acks into account:
+ */
+#define RETRANSMITS_RELIABLE 0
+/* Unacked messages: */
+#define RETRANSMITS_UNRELIABLE 2
+/* PDU acks: */
+#define RETRANSMITS_ACK 2
+
+enum {
+ ADV_LINK_ACTIVE, /* Link has been opened */
+ ADV_LINK_ACK_RECVD, /* Ack for link has been received */
+ ADV_LINK_CLOSING, /* Link is closing down */
+ ADV_LINK_INVALID, /* Error occurred during provisioning */
+ ADV_ACK_PENDING, /* An acknowledgment is being sent */
+ ADV_PROVISIONER, /* The link was opened as provisioner */
+
+ ADV_NUM_FLAGS,
+};
+
+struct pb_adv {
+ uint32_t id; /* Link ID */
+
+ ATOMIC_DEFINE(flags, ADV_NUM_FLAGS);
+
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+
+ struct {
+ uint8_t id; /* Most recent transaction ID */
+ uint8_t seg; /* Bit-field of unreceived segments */
+ uint8_t last_seg; /* Last segment (to check length) */
+ uint8_t fcs; /* Expected FCS value */
+ struct os_mbuf *buf;
+ } rx;
+
+ struct {
+ /* Start timestamp of the transaction */
+ int64_t start;
+
+ /* Transaction id */
+ uint8_t id;
+
+ /* Current ack id */
+ uint8_t pending_ack;
+
+ /* Pending outgoing buffer(s) */
+ struct os_mbuf *buf[3];
+
+ prov_bearer_send_complete_t cb;
+
+ void *cb_data;
+
+ /* Retransmit timer */
+ struct k_delayed_work retransmit;
+ } tx;
+
+ /* Protocol timeout */
+ struct k_delayed_work prot_timer;
+};
+
+struct prov_rx {
+ uint32_t link_id;
+ uint8_t xact_id;
+ uint8_t gpc;
+};
+
+static struct os_mbuf *rx_buf;
+static struct pb_adv link;
+
+static void gen_prov_ack_send(uint8_t xact_id);
+static void link_open(struct prov_rx *rx, struct os_mbuf *buf);
+static void link_ack(struct prov_rx *rx, struct os_mbuf *buf);
+static void link_close(struct prov_rx *rx, struct os_mbuf *buf);
+
+static void buf_sent(int err, void *user_data)
+{
+ BT_DBG("buf_send");
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ BT_DBG("submit retransmit");
+ k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
+}
+
+static struct bt_mesh_send_cb buf_sent_cb = {
+ .end = buf_sent,
+};
+
+static uint8_t last_seg(uint8_t len)
+{
+ if (len <= START_PAYLOAD_MAX) {
+ return 0;
+ }
+
+ len -= START_PAYLOAD_MAX;
+
+ return 1 + (len / CONT_PAYLOAD_MAX);
+}
+
+static void free_segments(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ link.tx.buf[i] = NULL;
+ /* Mark as canceled */
+ BT_MESH_ADV(buf)->busy = 0U;
+ net_buf_unref(buf);
+ }
+}
+
+static uint8_t next_transaction_id(uint8_t id)
+{
+ return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1)));
+}
+
+static void prov_clear_tx(void)
+{
+ BT_DBG("");
+
+ k_delayed_work_cancel(&link.tx.retransmit);
+
+ free_segments();
+}
+
+static void reset_adv_link(void)
+{
+ BT_DBG("");
+ prov_clear_tx();
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ /* Clear everything except the retransmit and protocol timer
+ * delayed work objects.
+ */
+ (void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit));
+ link.rx.id = XACT_ID_NVAL;
+ } else {
+ /* Accept another provisioning attempt */
+ link.id = 0;
+ atomic_clear(link.flags);
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ }
+ link.tx.pending_ack = XACT_ID_NVAL;
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+static void close_link(enum prov_bearer_link_status reason)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+ void *cb_data = link.cb_data;
+
+ reset_adv_link();
+ cb->link_closed(&pb_adv, cb_data, reason);
+}
+
+static struct os_mbuf *adv_buf_create(uint8_t retransmits)
+{
+ struct os_mbuf *buf;
+
+ buf = bt_mesh_adv_create(BT_MESH_ADV_PROV,
+ BT_MESH_TRANSMIT(retransmits, 20),
+ BUF_TIMEOUT);
+ if (!buf) {
+ BT_ERR("Out of provisioning buffers");
+ return NULL;
+ }
+
+ return buf;
+}
+
+static void ack_complete(uint16_t duration, int err, void *user_data)
+{
+ BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack);
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static bool ack_pending(void)
+{
+ return atomic_test_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static void prov_failed(uint8_t err)
+{
+ BT_DBG("%u", err);
+ link.cb->error(&pb_adv, link.cb_data, err);
+ atomic_set_bit(link.flags, ADV_LINK_INVALID);
+}
+
+static void prov_msg_recv(void)
+{
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
+ BT_ERR("Incorrect FCS");
+ return;
+ }
+
+ gen_prov_ack_send(link.rx.id);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) {
+ BT_WARN("Unexpected msg 0x%02x on invalidated link",
+ link.rx.buf->om_data[0]);
+ prov_failed(PROV_ERR_UNEXP_PDU);
+ return;
+ }
+
+ link.cb->recv(&pb_adv, link.cb_data, link.rx.buf);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("");
+
+ link.rx.seg = 0U;
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+/*******************************************************************************
+ * Generic provisioning
+ ******************************************************************************/
+
+static void gen_prov_ack_send(uint8_t xact_id)
+{
+ static const struct bt_mesh_send_cb cb = {
+ .start = ack_complete,
+ };
+ const struct bt_mesh_send_cb *complete;
+ struct os_mbuf *buf;
+ bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING);
+
+ BT_DBG("xact_id 0x%x", xact_id);
+
+ if (pending && link.tx.pending_ack == xact_id) {
+ BT_DBG("Not sending duplicate ack");
+ return;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_ACK);
+ if (!buf) {
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+ return;
+ }
+
+ if (pending) {
+ complete = NULL;
+ } else {
+ link.tx.pending_ack = xact_id;
+ complete = &cb;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, xact_id);
+ net_buf_add_u8(buf, GPC_ACK);
+
+ bt_mesh_adv_send(buf, complete, NULL);
+ net_buf_unref(buf);
+}
+
+static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = CONT_SEG_INDEX(rx->gpc);
+
+ BT_DBG("len %u, seg_index %u", buf->om_len, seg);
+
+ if (!link.rx.seg && link.rx.id == rx->xact_id) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!link.rx.seg &&
+ next_transaction_id(link.rx.id) == rx->xact_id) {
+ BT_DBG("Start segment lost");
+
+ link.rx.id = rx->xact_id;
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.seg = SEG_NVAL;
+ link.rx.last_seg = SEG_NVAL;
+
+ prov_clear_tx();
+ } else if (rx->xact_id != link.rx.id) {
+ BT_WARN("Data for unknown transaction (0x%x != 0x%x)",
+ rx->xact_id, link.rx.id);
+ return;
+ }
+
+ if (seg > link.rx.last_seg) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(seg))) {
+ BT_DBG("Ignoring already received segment");
+ return;
+ }
+
+ memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
+ XACT_SEG_RECV(seg);
+
+ if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) {
+ uint8_t expect_len;
+
+ expect_len = (link.rx.buf->om_len - 20U -
+ ((link.rx.last_seg - 1) * 23U));
+ if (expect_len != buf->om_len) {
+ BT_ERR("Incorrect last seg len: %u != %u", expect_len,
+ buf->om_len);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+ }
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ if (rx->xact_id == link.tx.id) {
+ /* Don't clear resending of link_close messages */
+ if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ prov_clear_tx();
+ }
+
+ if (link.tx.cb) {
+ link.tx.cb(0, link.tx.cb_data);
+ }
+ }
+}
+
+static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = SEG_NVAL;
+
+ if (rx->xact_id == link.rx.id) {
+ if (!link.rx.seg) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(0))) {
+ BT_DBG("Ignoring duplicate segment");
+ return;
+ }
+ } else if (rx->xact_id != next_transaction_id(link.rx.id)) {
+ BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id,
+ next_transaction_id(link.rx.id));
+ return;
+ }
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
+ link.rx.id = rx->xact_id;
+ link.rx.fcs = net_buf_simple_pull_u8(buf);
+
+ BT_DBG("%p len %u last_seg %u total_len %u fcs 0x%02x", link.rx.buf, buf->om_len,
+ START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
+
+ if (link.rx.buf->om_len < 1) {
+ BT_ERR("Ignoring zero-length provisioning PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20U) {
+ BT_ERR("Too small total length for multi-segment PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.rx.last_seg = START_LAST_SEG(rx->gpc);
+ if ((link.rx.seg & BIT(0)) &&
+ (find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (link.rx.seg) {
+ seg = link.rx.seg;
+ }
+
+ link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1);
+ memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
+ XACT_SEG_RECV(0);
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
+
+ switch (BEARER_CTL(rx->gpc)) {
+ case LINK_OPEN:
+ link_open(rx, buf);
+ break;
+ case LINK_ACK:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_ack(rx, buf);
+ break;
+ case LINK_CLOSE:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_close(rx, buf);
+ break;
+ default:
+ BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
+
+ if (IS_ENABLED(CONFIG_BT_TESTING)) {
+ bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
+ }
+
+ return;
+ }
+}
+
+static const struct {
+ void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
+ bool require_link;
+ uint8_t min_len;
+} gen_prov[] = {
+ { gen_prov_start, true, 3 },
+ { gen_prov_ack, true, 0 },
+ { gen_prov_cont, true, 0 },
+ { gen_prov_ctl, false, 0 },
+};
+
+static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
+ BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
+ return;
+ }
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) &&
+ gen_prov[GPCF(rx->gpc)].require_link) {
+ BT_DBG("Ignoring message that requires active link");
+ return;
+ }
+
+ gen_prov[GPCF(rx->gpc)].func(rx, buf);
+}
+
+/*******************************************************************************
+ * TX
+ ******************************************************************************/
+
+static void send_reliable(void)
+{
+ int i;
+
+ link.tx.start = k_uptime_get();
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+ bt_mesh_adv_send(buf, NULL, NULL);
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ }
+ }
+}
+
+static void prov_retransmit(struct ble_npl_event *work)
+{
+ int32_t timeout_ms;
+ int i;
+
+ BT_DBG("");
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ BT_WARN("Link not active");
+ return;
+ }
+
+ /*
+ * According to mesh profile spec (5.3.1.4.3), the close message should
+ * be restransmitted at least three times. Retransmit the link_close
+ * message until CLOSING_TIMEOUT has elapsed.
+ */
+ if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ timeout_ms = CLOSING_TIMEOUT;
+ } else {
+ timeout_ms = TRANSACTION_TIMEOUT;
+ }
+
+ if (k_uptime_get() - link.tx.start > timeout_ms) {
+ if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ close_link(PROV_BEARER_LINK_STATUS_SUCCESS);
+ } else {
+ BT_WARN("Giving up transaction");
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+ }
+
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ if (BT_MESH_ADV(buf)->busy) {
+ continue;
+ }
+
+ BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
+
+ if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+ bt_mesh_adv_send(buf, NULL, NULL);
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ }
+ }
+}
+
+static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len,
+ bool reliable)
+{
+ struct os_mbuf *buf;
+
+ BT_DBG("op 0x%02x data_len %u", op, data_len);
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE :
+ RETRANSMITS_UNRELIABLE);
+ if (!buf) {
+ return -ENOBUFS;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ /* Transaction ID, always 0 for Bearer messages */
+ net_buf_add_u8(buf, 0x00);
+ net_buf_add_u8(buf, GPC_CTL(op));
+ net_buf_add_mem(buf, data, data_len);
+
+ if (reliable) {
+ link.tx.buf[0] = buf;
+ send_reliable();
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ net_buf_unref(buf);
+ }
+
+ return 0;
+}
+
+static int prov_send_adv(struct os_mbuf *msg,
+ prov_bearer_send_complete_t cb, void *cb_data)
+{
+ struct os_mbuf *start, *buf;
+ uint8_t seg_len, seg_id;
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ start = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!start) {
+ return -ENOBUFS;
+ }
+
+ link.tx.id = next_transaction_id(link.tx.id);
+ net_buf_add_be32(start, link.id);
+ net_buf_add_u8(start, link.tx.id);
+
+ net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
+ net_buf_add_be16(start, msg->om_len);
+ net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
+
+ link.tx.buf[0] = start;
+ link.tx.cb = cb;
+ link.tx.cb_data = cb_data;
+
+ BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len);
+
+ seg_len = MIN(msg->om_len, START_PAYLOAD_MAX);
+ BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
+ net_buf_add_mem(start, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+
+ buf = start;
+ for (seg_id = 1U; msg->om_len > 0; seg_id++) {
+ if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
+ BT_ERR("Too big message");
+ free_segments();
+ return -E2BIG;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!buf) {
+ free_segments();
+ return -ENOBUFS;
+ }
+
+ link.tx.buf[seg_id] = buf;
+
+ seg_len = MIN(msg->om_len, CONT_PAYLOAD_MAX);
+
+ BT_DBG("seg %u len %u: %s", seg_id, seg_len,
+ bt_hex(msg->om_data, seg_len));
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, link.tx.id);
+ net_buf_add_u8(buf, GPC_CONT(seg_id));
+ net_buf_add_mem(buf, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+ }
+
+ send_reliable();
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Link management rx
+ ******************************************************************************/
+
+static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len < 16) {
+ BT_ERR("Too short bearer open message (len %u)", buf->om_len);
+ return;
+ }
+
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ /* Send another link ack if the provisioner missed the last */
+ if (link.id == rx->link_id) {
+ BT_DBG("Resending link ack");
+ bearer_ctl_send(LINK_ACK, NULL, 0, false);
+ } else {
+ BT_DBG("Ignoring bearer open: link already active");
+ }
+
+ return;
+ }
+
+ if (memcmp(buf->om_data, bt_mesh_prov_get()->uuid, 16)) {
+ BT_DBG("Bearer open message not for us");
+ return;
+ }
+
+ link.id = rx->link_id;
+ atomic_set_bit(link.flags, ADV_LINK_ACTIVE);
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_ACK, NULL, 0, false);
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+}
+
+static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) {
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+ }
+}
+
+static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len != 1) {
+ return;
+ }
+
+ close_link(net_buf_simple_pull_u8(buf));
+}
+
+/*******************************************************************************
+ * Higher level functionality
+ ******************************************************************************/
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
+{
+ struct prov_rx rx;
+
+ if (!link.cb) {
+ return;
+ }
+
+ if (buf->om_len < 6) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return;
+ }
+
+ rx.link_id = net_buf_simple_pull_be32(buf);
+ rx.xact_id = net_buf_simple_pull_u8(buf);
+ rx.gpc = net_buf_simple_pull_u8(buf);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) {
+ return;
+ }
+
+ BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id);
+
+ gen_prov_recv(&rx, buf);
+}
+
+static int prov_link_open(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data)
+{
+ BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(link.flags, ADV_PROVISIONER);
+
+ bt_rand(&link.id, sizeof(link.id));
+ link.tx.id = XACT_ID_MAX;
+ link.rx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_OPEN, uuid, 16, true);
+
+ return 0;
+}
+
+static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ /* Make sure we're scanning for provisioning inviations */
+ bt_mesh_scan_enable();
+ /* Enable unprovisioned beacon sending */
+ bt_mesh_beacon_enable();
+
+ return 0;
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) {
+ return;
+ }
+
+ bearer_ctl_send(LINK_CLOSE, &status, 1, true);
+}
+
+void pb_adv_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+ k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
+
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+void pb_adv_reset(void)
+{
+ reset_adv_link();
+}
+
+const struct prov_bearer pb_adv = {
+ .type = BT_MESH_PROV_ADV,
+ .link_open = prov_link_open,
+ .link_accept = prov_link_accept,
+ .link_close = prov_link_close,
+ .send = prov_send_adv,
+ .clear_tx = prov_clear_tx,
+};
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
new file mode 100644
index 00000000..a8f73787
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
@@ -0,0 +1,158 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "mesh/mesh.h"
+#include "prov.h"
+#include "net.h"
+#include "proxy.h"
+#include "adv.h"
+#include "prov.h"
+
+struct prov_link {
+ uint16_t conn_handle;
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+ struct {
+ uint8_t id; /* Transaction ID */
+ uint8_t prev_id; /* Previous Transaction ID */
+ uint8_t seg; /* Bit-field of unreceived segments */
+ uint8_t last_seg; /* Last segment (to check length) */
+ uint8_t fcs; /* Expected FCS value */
+ struct os_mbuf *buf;
+ } rx;
+ struct k_delayed_work prot_timer;
+};
+
+static struct prov_link link;
+
+static void reset_state(void)
+{
+ link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ link.rx.buf = bt_mesh_proxy_get_buf();
+}
+
+static void link_closed(enum prov_bearer_link_status status)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+
+ void *cb_data = link.cb_data;
+
+ reset_state();
+
+ cb->link_closed(&pb_gatt, cb_data, status);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("Protocol timeout");
+
+ link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+
+int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
+{
+ BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
+
+ if (link.conn_handle != conn_handle || !link.cb) {
+ BT_WARN("Data for unexpected connection");
+ return -ENOTCONN;
+ }
+
+ if (buf->om_len < 1) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return -EINVAL;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->recv(&pb_gatt, link.cb_data, buf);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_open(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle) {
+ return -EBUSY;
+ }
+
+ link.conn_handle = conn_handle;
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->link_opened(&pb_gatt, link.cb_data);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_close(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle != conn_handle) {
+ BT_DBG("Not connected");
+ return -ENOTCONN;
+ }
+
+ link.cb->link_closed(&pb_gatt, link.cb_data,
+ PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ reset_state();
+
+ return 0;
+}
+
+static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ bt_mesh_proxy_prov_enable();
+ bt_mesh_adv_update();
+
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ return 0;
+}
+
+static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data)
+{
+ if (!link.conn_handle) {
+ return -ENOTCONN;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf);
+}
+
+static void clear_tx(void)
+{
+ /* No action */
+}
+
+void pb_gatt_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+}
+
+void pb_gatt_reset(void)
+{
+ reset_state();
+}
+const struct prov_bearer pb_gatt = {
+ .type = BT_MESH_PROV_GATT,
+ .link_accept = link_accept,
+ .send = buf_send,
+ .clear_tx = clear_tx,
+};
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
index fe92c0e3..ba514dde 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
@@ -9,8 +9,6 @@
#include "syscfg/syscfg.h"
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
-#if MYNEWT_VAL(BLE_MESH_PROV)
-
#include
#include "mesh/mesh.h"
@@ -18,700 +16,52 @@
#include "crypto.h"
#include "atomic.h"
-#include "adv.h"
#include "net.h"
#include "access.h"
#include "foundation.h"
-#include "proxy.h"
#include "prov.h"
#include "testing.h"
-#include "settings.h"
-#include "nodes.h"
-/* 3 transmissions, 20ms interval */
-#define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
+struct bt_mesh_prov_link bt_mesh_prov_link;
+const struct bt_mesh_prov *bt_mesh_prov;
-#define AUTH_METHOD_NO_OOB 0x00
-#define AUTH_METHOD_STATIC 0x01
-#define AUTH_METHOD_OUTPUT 0x02
-#define AUTH_METHOD_INPUT 0x03
-
-#define OUTPUT_OOB_BLINK 0x00
-#define OUTPUT_OOB_BEEP 0x01
-#define OUTPUT_OOB_VIBRATE 0x02
-#define OUTPUT_OOB_NUMBER 0x03
-#define OUTPUT_OOB_STRING 0x04
-
-#define INPUT_OOB_PUSH 0x00
-#define INPUT_OOB_TWIST 0x01
-#define INPUT_OOB_NUMBER 0x02
-#define INPUT_OOB_STRING 0x03
-
-#define PUB_KEY_NO_OOB 0x00
-#define PUB_KEY_OOB 0x01
-
-#define PROV_ERR_NONE 0x00
-#define PROV_ERR_NVAL_PDU 0x01
-#define PROV_ERR_NVAL_FMT 0x02
-#define PROV_ERR_UNEXP_PDU 0x03
-#define PROV_ERR_CFM_FAILED 0x04
-#define PROV_ERR_RESOURCES 0x05
-#define PROV_ERR_DECRYPT 0x06
-#define PROV_ERR_UNEXP_ERR 0x07
-#define PROV_ERR_ADDR 0x08
-
-#define PROV_INVITE 0x00
-#define PROV_CAPABILITIES 0x01
-#define PROV_START 0x02
-#define PROV_PUB_KEY 0x03
-#define PROV_INPUT_COMPLETE 0x04
-#define PROV_CONFIRM 0x05
-#define PROV_RANDOM 0x06
-#define PROV_DATA 0x07
-#define PROV_COMPLETE 0x08
-#define PROV_FAILED 0x09
-
-#define PROV_NO_PDU 0xff
-
-#define PROV_ALG_P256 0x00
-
-#define GPCF(gpc) (gpc & 0x03)
-#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
-#define GPC_ACK 0x01
-#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
-#define GPC_CTL(op) (((op) << 2) | 0x03)
-
-#define START_PAYLOAD_MAX 20
-#define CONT_PAYLOAD_MAX 23
-
-#define START_LAST_SEG(gpc) (gpc >> 2)
-#define CONT_SEG_INDEX(gpc) (gpc >> 2)
-
-#define BEARER_CTL(gpc) (gpc >> 2)
-#define LINK_OPEN 0x00
-#define LINK_ACK 0x01
-#define LINK_CLOSE 0x02
-
-#define CLOSE_REASON_SUCCESS 0x00
-#define CLOSE_REASON_TIMEOUT 0x01
-#define CLOSE_REASON_FAILED 0x02
-
-#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
-#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
-
-#define XACT_NVAL 0xff
-
-enum {
- WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
- LINK_ACTIVE, /* Link has been opened */
- LINK_ACK_RECVD, /* Ack for link has been received */
- LINK_CLOSING, /* Link is closing down */
- SEND_PUB_KEY, /* Waiting to send PubKey */
- WAIT_NUMBER, /* Waiting for number input from user */
- WAIT_STRING, /* Waiting for string input from user */
- NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
- LINK_INVALID, /* Error occurred during provisioning */
- PROVISIONER, /* The link was opened as provisioner */
-
- NUM_FLAGS,
-};
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-#define PROVISIONER_LINK 1
-#else
-#define PROVISIONER_LINK 0
-#endif
-
-struct provisioner_link {
- struct bt_mesh_node *node;
- u16_t addr;
- u16_t net_idx;
- u8_t attention_duration;
-};
-
-struct prov_link {
- ATOMIC_DEFINE(flags, NUM_FLAGS);
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- uint16_t conn_handle; /* GATT connection */
-#endif
- struct provisioner_link provisioner[PROVISIONER_LINK];
-
- u8_t dhkey[32]; /* Calculated DHKey */
- u8_t expect; /* Next expected PDU */
-
- u8_t oob_method;
- u8_t oob_action;
- u8_t oob_size;
-
- u8_t conf[16]; /* Remote Confirmation */
- u8_t rand[16]; /* Local Random */
- u8_t auth[16]; /* Authentication Value */
-
- u8_t conf_salt[16]; /* ConfirmationSalt */
- u8_t conf_key[16]; /* ConfirmationKey */
- u8_t conf_inputs[145]; /* ConfirmationInputs */
- u8_t prov_salt[16]; /* Provisioning Salt */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- u32_t id; /* Link ID */
-
- struct {
- u8_t id; /* Transaction ID */
- u8_t prev_id; /* Previous Transaction ID */
- u8_t seg; /* Bit-field of unreceived segments */
- u8_t last_seg; /* Last segment (to check length) */
- u8_t fcs; /* Expected FCS value */
- struct os_mbuf *buf;
- } rx;
-
- struct {
- /* Start timestamp of the transaction */
- s64_t start;
-
- /* Transaction id*/
- u8_t id;
-
- /* Pending outgoing buffer(s) */
- struct os_mbuf *buf[3];
-
- /* Retransmit timer */
- struct k_delayed_work retransmit;
- } tx;
-#endif
-
- struct k_delayed_work prot_timer;
-};
-
-struct prov_rx {
- u32_t link_id;
- u8_t xact_id;
- u8_t gpc;
-};
-
-#define RETRANSMIT_TIMEOUT K_MSEC(500)
-#define BUF_TIMEOUT K_MSEC(400)
-#define CLOSING_TIMEOUT K_SECONDS(3)
-#define TRANSACTION_TIMEOUT K_SECONDS(30)
-#define PROTOCOL_TIMEOUT K_SECONDS(60)
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-#define PROV_BUF_HEADROOM 5
-#else
-#define PROV_BUF_HEADROOM 0
-static struct os_mbuf *rx_buf;
-#endif
-
-#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)
-
-static struct prov_link link;
-
-static const struct bt_mesh_prov *prov;
-
-static void pub_key_ready(const u8_t *pkey);
-
-static int reset_state(void)
+static void pub_key_ready(const uint8_t *pkey)
{
- static struct bt_pub_key_cb pub_key_cb = {
- .func = pub_key_ready,
- };
- int err;
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+ BT_DBG("Local public key ready");
+}
- k_delayed_work_cancel(&link.prot_timer);
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]))
+{
+ BT_DBG("bt_mesh_prov_reset_state");
+
+ int err;
+ static struct bt_pub_key_cb pub_key_cb;
+ const size_t offset = offsetof(struct bt_mesh_prov_link, dhkey);
+
+ pub_key_cb.func = func ? func : pub_key_ready;
/* Disable Attention Timer if it was set */
- if (link.conf_inputs[0]) {
+ if (bt_mesh_prov_link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- link.provisioner->node != NULL) {
- bt_mesh_node_del(link.provisioner->node, false);
- }
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Clear everything except the retransmit and protocol timer
- * delayed work objects.
- */
- (void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
- link.rx.prev_id = XACT_NVAL;
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- if (!rx_buf) {
- rx_buf = NET_BUF_SIMPLE(65);
- }
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif /* PB_GATT */
-
-#else /* !PB_ADV */
- /* Clear everything except the protocol timer (k_delayed_work) */
- (void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
-#endif /* PB_ADV */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-#endif
+ atomic_clear(bt_mesh_prov_link.flags);
+ (void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0,
+ sizeof(bt_mesh_prov_link) - offset);
err = bt_pub_key_gen(&pub_key_cb);
if (err) {
BT_ERR("Failed to generate public key (%d)", err);
return err;
}
-
return 0;
}
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void buf_sent(int err, void *user_data)
-{
- BT_DBG("buf_sent");
-
- if (!link.tx.buf[0]) {
- return;
- }
-
- k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
-}
-
-static struct bt_mesh_send_cb buf_sent_cb = {
- .end = buf_sent,
-};
-
-static void free_segments(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- link.tx.buf[i] = NULL;
- /* Mark as canceled */
- BT_MESH_ADV(buf)->busy = 0;
- net_buf_unref(buf);
- }
-}
-
-static void prov_clear_tx(void)
-{
- BT_DBG("");
-
- k_delayed_work_cancel(&link.tx.retransmit);
-
- free_segments();
-}
-
-static void reset_adv_link(void)
-{
- prov_clear_tx();
-
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_ADV);
- }
-
- reset_state();
-}
-
-static struct os_mbuf *adv_buf_create(void)
-{
- struct os_mbuf *buf;
-
- buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT, BUF_TIMEOUT);
- if (!buf) {
- BT_ERR("Out of provisioning buffers");
- assert(0);
- return NULL;
- }
-
- return buf;
-}
-
-static u8_t pending_ack = XACT_NVAL;
-
-static void ack_complete(u16_t duration, int err, void *user_data)
-{
- BT_DBG("xact %u complete", (u8_t)pending_ack);
- pending_ack = XACT_NVAL;
-}
-
-static void gen_prov_ack_send(u8_t xact_id)
-{
- static const struct bt_mesh_send_cb cb = {
- .start = ack_complete,
- };
- const struct bt_mesh_send_cb *complete;
- struct os_mbuf *buf;
-
- BT_DBG("xact_id %u", xact_id);
-
- if (pending_ack == xact_id) {
- BT_DBG("Not sending duplicate ack");
- return;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- return;
- }
-
- if (pending_ack == XACT_NVAL) {
- pending_ack = xact_id;
- complete = &cb;
- } else {
- complete = NULL;
- }
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_ACK);
-
- bt_mesh_adv_send(buf, complete, NULL);
- net_buf_unref(buf);
-}
-
-static void send_reliable(void)
-{
- int i;
-
- link.tx.start = k_uptime_get();
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
- bt_mesh_adv_send(buf, NULL, NULL);
- } else {
- bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
- }
- }
-}
-
-static int bearer_ctl_send(u8_t op, const void *data, u8_t data_len)
-{
- struct os_mbuf *buf;
-
- BT_DBG("op 0x%02x data_len %u", op, data_len);
-
- prov_clear_tx();
-
- buf = adv_buf_create();
- if (!buf) {
- return -ENOBUFS;
- }
-
- net_buf_add_be32(buf, link.id);
- /* Transaction ID, always 0 for Bearer messages */
- net_buf_add_u8(buf, 0x00);
- net_buf_add_u8(buf, GPC_CTL(op));
- net_buf_add_mem(buf, data, data_len);
-
- link.tx.buf[0] = buf;
- send_reliable();
-
- return 0;
-}
-
-static u8_t last_seg(u8_t len)
-{
- if (len <= START_PAYLOAD_MAX) {
- return 0;
- }
-
- len -= START_PAYLOAD_MAX;
-
- return 1 + (len / CONT_PAYLOAD_MAX);
-}
-
-static inline u8_t next_transaction_id(void)
-{
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- if (link.tx.id != 0x7F) {
- link.tx.id++;
- } else {
- link.tx.id = 0;
- }
- } else {
- if (link.tx.id != 0U && link.tx.id != 0xFF) {
- link.tx.id++;
- } else {
- link.tx.id = 0x80;
- }
- }
-
- return link.tx.id;
-}
-
-static int prov_send_adv(struct os_mbuf *msg)
-{
- struct os_mbuf *start, *buf;
- u8_t seg_len, seg_id;
- u8_t xact_id;
-
- BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
-
- prov_clear_tx();
-
- start = adv_buf_create();
- if (!start) {
- return -ENOBUFS;
- }
-
- xact_id = next_transaction_id();
- net_buf_add_be32(start, link.id);
- net_buf_add_u8(start, xact_id);
-
- net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
- net_buf_add_be16(start, msg->om_len);
- net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
-
- link.tx.buf[0] = start;
-
- seg_len = min(msg->om_len, START_PAYLOAD_MAX);
- BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
- net_buf_add_mem(start, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
-
- buf = start;
- for (seg_id = 1; msg->om_len > 0; seg_id++) {
- if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
- BT_ERR("Too big message");
- free_segments();
- return -E2BIG;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- free_segments();
- return -ENOBUFS;
- }
-
- link.tx.buf[seg_id] = buf;
-
- seg_len = min(msg->om_len, CONT_PAYLOAD_MAX);
-
- BT_DBG("seg_id %u len %u: %s", seg_id, seg_len,
- bt_hex(msg->om_data, seg_len));
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_CONT(seg_id));
- net_buf_add_mem(buf, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
- }
-
- send_reliable();
-
- return 0;
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static int prov_send_gatt(struct os_mbuf *msg)
-{
- if (link.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
- BT_ERR("No connection handle!?");
- return -ENOTCONN;
- }
-
- return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, msg);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
-static inline int prov_send(struct os_mbuf *buf)
-{
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- return prov_send_gatt(buf);
- }
-#endif
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- return prov_send_adv(buf);
-#else
- return 0;
-#endif
-}
-
-static void prov_buf_init(struct os_mbuf *buf, u8_t type)
-{
- net_buf_simple_init(buf, PROV_BUF_HEADROOM);
- net_buf_simple_add_u8(buf, type);
-}
-
-static void prov_send_fail_msg(u8_t err)
-{
- struct os_mbuf *buf = PROV_BUF(2);
-
- prov_buf_init(buf, PROV_FAILED);
- net_buf_simple_add_u8(buf, err);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Failed message");
- }
-
- atomic_set_bit(link.flags, LINK_INVALID);
-
- os_mbuf_free_chain(buf);
-}
-
-static void prov_invite(const u8_t *data)
-{
- struct os_mbuf *buf = PROV_BUF(12);
-
- BT_DBG("Attention Duration: %u seconds", data[0]);
-
- if (data[0]) {
- bt_mesh_attention(NULL, data[0]);
- }
-
- link.conf_inputs[0] = data[0];
-
- prov_buf_init(buf, PROV_CAPABILITIES);
-
- /* Number of Elements supported */
- net_buf_simple_add_u8(buf, bt_mesh_elem_count());
-
- /* Supported algorithms - FIPS P-256 Eliptic Curve */
- net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
-
- /* Public Key Type, Only "No OOB" Public Key is supported*/
- net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
-
- /* Static OOB Type */
- net_buf_simple_add_u8(buf, prov->static_val ? BIT(0) : 0x00);
-
- /* Output OOB Size */
- net_buf_simple_add_u8(buf, prov->output_size);
-
- /* Output OOB Action */
- net_buf_simple_add_be16(buf, prov->output_actions);
-
- /* Input OOB Size */
- net_buf_simple_add_u8(buf, prov->input_size);
-
- /* Input OOB Action */
- net_buf_simple_add_be16(buf, prov->input_actions);
-
- memcpy(&link.conf_inputs[1], &buf->om_data[1], 11);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send capabilities");
- goto done;
- }
-
- link.expect = PROV_START;
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
-static void send_invite(void)
-{
- struct os_mbuf *inv = PROV_BUF(2);
-
- BT_DBG("");
-
- prov_buf_init(inv, PROV_INVITE);
- net_buf_simple_add_u8(inv, link.provisioner->attention_duration);
-
- link.conf_inputs[0] = link.provisioner->attention_duration;
-
- if (prov_send(inv)) {
- BT_ERR("Failed to send invite");
- goto done;
- }
-
- link.expect = PROV_CAPABILITIES;
-
-done:
- os_mbuf_free_chain(inv);
-}
-#endif
-
-static void send_start(void)
-{
- struct os_mbuf *start = PROV_BUF(6);
-
- BT_DBG("");
-
- prov_buf_init(start, PROV_START);
-
- net_buf_simple_add_u8(start, PROV_ALG_P256);
- net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
- net_buf_simple_add_u8(start, AUTH_METHOD_NO_OOB);
- memset(link.auth, 0, sizeof(link.auth));
-
- net_buf_simple_add_u8(start, 0); /* Auth Action */
- net_buf_simple_add_u8(start, 0); /* Auth Size */
-
- memcpy(&link.conf_inputs[12], &start->om_data[1], 5);
-
- if (prov_send(start)) {
- BT_ERR("Failed to send start");
- }
-
- os_mbuf_free_chain(start);
-}
-
-static void prov_capabilities(const u8_t *data)
-{
- u16_t algorithms, output_action, input_action;
-
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- BT_DBG("Elements: %u", data[0]);
-
- algorithms = sys_get_be16(&data[1]);
- BT_DBG("Algorithms: %u", algorithms);
-
- BT_DBG("Public Key Type: 0x%02x", data[3]);
- BT_DBG("Static OOB Type: 0x%02x", data[4]);
- BT_DBG("Output OOB Size: %u", data[5]);
-
- output_action = sys_get_be16(&data[6]);
- BT_DBG("Output OOB Action: 0x%04x", output_action);
-
- BT_DBG("Input OOB Size: %u", data[8]);
-
- input_action = sys_get_be16(&data[9]);
- BT_DBG("Input OOB Action: 0x%04x", input_action);
-
- if (data[0] == 0) {
- BT_ERR("Invalid number of elements");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr,
- data[0],
- link.provisioner->net_idx);
- if (link.provisioner->node == NULL) {
- prov_send_fail_msg(PROV_ERR_RESOURCES);
- return;
- }
-
- memcpy(&link.conf_inputs[1], data, 11);
-
- atomic_set_bit(link.flags, SEND_PUB_KEY);
-
- send_start();
-}
-
-static bt_mesh_output_action_t output_action(u8_t action)
+static bt_mesh_output_action_t output_action(uint8_t action)
{
switch (action) {
case OUTPUT_OOB_BLINK:
@@ -729,7 +79,7 @@ static bt_mesh_output_action_t output_action(u8_t action)
}
}
-static bt_mesh_input_action_t input_action(u8_t action)
+static bt_mesh_input_action_t input_action(uint8_t action)
{
switch (action) {
case INPUT_OOB_PUSH:
@@ -745,7 +95,7 @@ static bt_mesh_input_action_t input_action(u8_t action)
}
}
-static int prov_auth(u8_t method, u8_t action, u8_t size)
+int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size)
{
bt_mesh_output_action_t output;
bt_mesh_input_action_t input;
@@ -756,16 +106,15 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- memset(link.auth, 0, sizeof(link.auth));
+ (void)memset(bt_mesh_prov_link.auth, 0, sizeof(bt_mesh_prov_link.auth));
return 0;
case AUTH_METHOD_STATIC:
if (action || size) {
return -EINVAL;
}
- memcpy(link.auth + 16 - prov->static_val_len,
- prov->static_val, prov->static_val_len);
- memset(link.auth, 0, sizeof(link.auth) - prov->static_val_len);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY);
+
return 0;
case AUTH_METHOD_OUTPUT:
@@ -774,19 +123,19 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->output_actions & output)) {
+ if (!(bt_mesh_prov->output_actions & output)) {
return -EINVAL;
}
- if (size > prov->output_size) {
+ if (size > bt_mesh_prov->output_size) {
return -EINVAL;
}
- atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE);
+ atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
if (output == BT_MESH_DISPLAY_STRING) {
unsigned char str[9];
- u8_t i;
+ uint8_t i;
bt_rand(str, size);
@@ -801,22 +150,23 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
}
str[size] = '\0';
- memcpy(link.auth, str, size);
- memset(link.auth + size, 0, sizeof(link.auth) - size);
+ memcpy(bt_mesh_prov_link.auth, str, size);
+ memset(bt_mesh_prov_link.auth + size, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
- return prov->output_string((char *)str);
+ return bt_mesh_prov->output_string((char *)str);
} else {
- u32_t div[8] = { 10, 100, 1000, 10000, 100000,
+ uint32_t div[8] = { 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000 };
- u32_t num;
+ uint32_t num;
bt_rand(&num, sizeof(num));
num %= div[size - 1];
- sys_put_be32(num, &link.auth[12]);
- memset(link.auth, 0, 12);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
+ memset(bt_mesh_prov_link.auth, 0, 12);
- return prov->output_number(output, num);
+ return bt_mesh_prov->output_number(output, num);
}
case AUTH_METHOD_INPUT:
@@ -825,140 +175,38 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->input_actions & input)) {
+ if (!(bt_mesh_prov->input_actions & input)) {
return -EINVAL;
}
- if (size > prov->input_size) {
+ if (size > bt_mesh_prov->input_size) {
return -EINVAL;
}
if (input == BT_MESH_ENTER_STRING) {
- atomic_set_bit(link.flags, WAIT_STRING);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING);
} else {
- atomic_set_bit(link.flags, WAIT_NUMBER);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER);
}
- return prov->input(input, size);
+ return bt_mesh_prov->input(input, size);
default:
return -EINVAL;
}
}
-static void prov_start(const u8_t *data)
-{
- BT_DBG("Algorithm: 0x%02x", data[0]);
- BT_DBG("Public Key: 0x%02x", data[1]);
- BT_DBG("Auth Method: 0x%02x", data[2]);
- BT_DBG("Auth Action: 0x%02x", data[3]);
- BT_DBG("Auth Size: 0x%02x", data[4]);
-
- if (data[0] != PROV_ALG_P256) {
- BT_ERR("Unknown algorithm 0x%02x", data[0]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (data[1] != PUB_KEY_NO_OOB) {
- BT_ERR("Invalid public key type: 0x%02x", data[1]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- memcpy(&link.conf_inputs[12], data, 5);
-
- /* TODO: reset link when auth fails? */
- link.expect = PROV_PUB_KEY;
-
- if (prov_auth(data[2], data[3], data[4]) < 0) {
- BT_ERR("Invalid authentication method: 0x%02x; "
- "action: 0x%02x; size: 0x%02x", data[2], data[3],
- data[4]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- }
-}
-
-static void send_confirm(void)
-{
- struct os_mbuf *cfm = PROV_BUF(17);
-
- BT_DBG("ConfInputs[0] %s", bt_hex(link.conf_inputs, 64));
- BT_DBG("ConfInputs[64] %s", bt_hex(&link.conf_inputs[64], 64));
- BT_DBG("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17));
-
- if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
- BT_ERR("Unable to generate confirmation salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
-
- if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
- BT_ERR("Unable to generate confirmation key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
-
- if (bt_rand(link.rand, 16)) {
- BT_ERR("Unable to generate random number");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("LocalRandom: %s", bt_hex(link.rand, 16));
-
- prov_buf_init(cfm, PROV_CONFIRM);
-
- if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
- net_buf_simple_add(cfm, 16))) {
- BT_ERR("Unable to generate confirmation value");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- if (prov_send(cfm)) {
- BT_ERR("Failed to send Provisioning Confirm");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_CONFIRM;
- } else {
- link.expect = PROV_RANDOM;
- }
-
-done:
- os_mbuf_free_chain(cfm);
-}
-
-static void send_input_complete(void)
-{
- struct os_mbuf *buf = PROV_BUF(1);
-
- prov_buf_init(buf, PROV_INPUT_COMPLETE);
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Input Complete");
- }
- link.expect = PROV_CONFIRM;
-
- os_mbuf_free_chain(buf);
-}
-
-int bt_mesh_input_number(u32_t num)
+int bt_mesh_input_number(uint32_t num)
{
BT_DBG("%u", (unsigned) num);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_NUMBER)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) {
return -EINVAL;
}
- sys_put_be32(num, &link.auth[12]);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
@@ -967,991 +215,145 @@ int bt_mesh_input_string(const char *str)
{
BT_DBG("%s", str);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_STRING)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
return -EINVAL;
}
- strncpy((char *)link.auth, str, prov->input_size);
+ strncpy((char *)bt_mesh_prov_link.auth, str, bt_mesh_prov->input_size);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
-static void send_pub_key(void)
-{
- struct os_mbuf *buf = PROV_BUF(65);
- const u8_t *key;
-
- key = bt_pub_key_get();
- if (!key) {
- BT_ERR("No public key available");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Local Public Key: %s", bt_hex(key, 64));
-
- prov_buf_init(buf, PROV_PUB_KEY);
-
- /* Swap X and Y halves independently to big-endian */
- sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
- sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], &buf->om_data[1], 64);
- } else {
- /* PublicKeyRemote */
- memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
- }
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Public Key");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_PUB_KEY;
- } else {
- if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
- atomic_test_bit(link.flags, WAIT_STRING)) {
- link.expect = PROV_NO_PDU; /* Wait for input */
- } else {
- link.expect = PROV_CONFIRM;
- }
- }
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-static void prov_dh_key_cb(const u8_t dhkey[32])
-{
- BT_DBG("%p", dhkey);
-
- if (!dhkey) {
- BT_ERR("DHKey generation failed");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- sys_memcpy_swap(link.dhkey, dhkey, 32);
-
- BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_confirm();
- } else {
- send_pub_key();
- }
-}
-
-static void prov_dh_key_gen(void)
-{
- u8_t remote_pk_le[64], *remote_pk;
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- remote_pk = &link.conf_inputs[81];
- } else {
- remote_pk = &link.conf_inputs[17];
- }
-
- /* Copy remote key in little-endian for bt_dh_key_gen().
- * X and Y halves are swapped independently. The bt_dh_key_gen()
- * will also take care of validating the remote public key.
- */
- sys_memcpy_swap(remote_pk_le, remote_pk, 32);
- sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
-
- if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
- BT_ERR("Failed to generate DHKey");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- }
-}
-
-static void prov_pub_key(const u8_t *data)
-{
- BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyDevice */
- memcpy(&link.conf_inputs[81], data, 64);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
- } else {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], data, 64);
-
- if (!bt_pub_key_get()) {
- /* Clear retransmit timer */
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
-
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- return;
- }
- }
-
- prov_dh_key_gen();
-}
-
-static void pub_key_ready(const u8_t *pkey)
-{
- if (!pkey) {
- BT_WARN("Public key not available");
- return;
- }
-
- BT_DBG("Local public key ready");
-
- if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) {
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_pub_key();
- } else {
- prov_dh_key_gen();
- }
- }
-}
-
-static void notify_input_complete(void)
-{
- if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) &&
- prov->input_complete) {
- prov->input_complete();
- }
-}
-
-static void prov_input_complete(const u8_t *data)
-{
- BT_DBG("");
- notify_input_complete();
-}
-
-static void send_prov_data(void)
-{
- struct os_mbuf *pdu = PROV_BUF(34);
- struct bt_mesh_subnet *sub;
- u8_t session_key[16];
- u8_t nonce[13];
- int err;
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt,
- link.provisioner->node->dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16));
-
- sub = bt_mesh_subnet_get(link.provisioner->node->net_idx);
- if (sub == NULL) {
- BT_ERR("No subnet with net_idx %u",
- link.provisioner->node->net_idx);
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- prov_buf_init(pdu, PROV_DATA);
- net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net, 16);
- net_buf_simple_add_be16(pdu, link.provisioner->node->net_idx);
- net_buf_simple_add_u8(pdu, bt_mesh_net_flags(sub));
- net_buf_simple_add_be32(pdu, bt_mesh.iv_index);
- net_buf_simple_add_be16(pdu, link.provisioner->node->addr);
- net_buf_simple_add(pdu, 8); /* For MIC */
-
- BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
- link.provisioner->node->net_idx, bt_mesh.iv_index,
- link.provisioner->node->addr);
-
- err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
- &pdu->om_data[1]);
- if (err) {
- BT_ERR("Unable to encrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- if (prov_send(pdu)) {
- BT_ERR("Failed to send Provisioning Data");
- goto done;
- }
-
- link.expect = PROV_COMPLETE;
-
-done:
- os_mbuf_free_chain(pdu);
-}
-
-static void prov_complete(const u8_t *data)
-{
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- struct bt_mesh_node *node = link.provisioner->node;
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_SUCCESS;
-#endif
-
- BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
- bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
- node->addr);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_node(node);
- }
-
- link.provisioner->node = NULL;
- link.expect = PROV_NO_PDU;
- atomic_set_bit(link.flags, LINK_CLOSING);
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
-#endif
-
- bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem);
-
- /*
- * According to mesh profile spec (5.3.1.4.3), the close message should
- * be restransmitted at least three times. Retransmit the LINK_CLOSE
- * message until CLOSING_TIMEOUT has elapsed instead of resetting the
- * link here.
- */
-}
-
-static void send_random(void)
-{
- struct os_mbuf *rnd = PROV_BUF(17);
-
- prov_buf_init(rnd, PROV_RANDOM);
- net_buf_simple_add_mem(rnd, link.rand, 16);
-
- if (prov_send(rnd)) {
- BT_ERR("Failed to send Provisioning Random");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_RANDOM;
- } else {
- link.expect = PROV_DATA;
- }
-
-done:
- os_mbuf_free_chain(rnd);
-}
-
-static void prov_random(const u8_t *data)
-{
- u8_t conf_verify[16];
- const u8_t *prov_rand, *dev_rand;
-
- BT_DBG("Remote Random: %s", bt_hex(data, 16));
-
- if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
- BT_ERR("Unable to calculate confirmation verification");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- if (memcmp(conf_verify, link.conf, 16)) {
- BT_ERR("Invalid confirmation value");
- BT_DBG("Received: %s", bt_hex(link.conf, 16));
- BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
- prov_send_fail_msg(PROV_ERR_CFM_FAILED);
- return;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- prov_rand = link.rand;
- dev_rand = data;
- } else {
- prov_rand = data;
- dev_rand = link.rand;
- }
-
- if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand,
- link.prov_salt)) {
- BT_ERR("Failed to generate provisioning salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- send_prov_data();
- } else {
- send_random();
- }
-}
-
-static void prov_confirm(const u8_t *data)
-{
- BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
-
- memcpy(link.conf, data, 16);
-
- notify_input_complete();
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_random();
- } else {
- send_confirm();
- }
-}
-
-static inline bool is_pb_gatt(void)
-{
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- return (link.conn_handle != BLE_HS_CONN_HANDLE_NONE);
-#else
- return false;
-#endif
-}
-
-static void prov_data(const u8_t *data)
-{
- struct os_mbuf *msg = PROV_BUF(1);
- u8_t session_key[16];
- u8_t nonce[13];
- u8_t dev_key[16];
- u8_t pdu[25];
- u8_t flags;
- u32_t iv_index;
- u16_t addr;
- u16_t net_idx;
- int err;
- bool identity_enable;
-
- BT_DBG("");
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
- if (err) {
- BT_ERR("Unable to decrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
-
- net_idx = sys_get_be16(&pdu[16]);
- flags = pdu[18];
- iv_index = sys_get_be32(&pdu[19]);
- addr = sys_get_be16(&pdu[23]);
-
- BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
- net_idx, (unsigned) iv_index, addr);
-
- prov_buf_init(msg, PROV_COMPLETE);
- if (prov_send(msg)) {
- BT_ERR("Failed to send Provisioning Complete");
- goto done;
- }
-
- /* Ignore any further PDUs on this link */
- link.expect = PROV_NO_PDU;
-
- /* Store info, since bt_mesh_provision() will end up clearing it */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- identity_enable = is_pb_gatt();
- } else {
- identity_enable = false;
- }
-
- err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
- if (err) {
- BT_ERR("Failed to provision (err %d)", err);
- goto done;
- }
-
- /* After PB-GATT provisioning we should start advertising
- * using Node Identity.
- */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
- bt_mesh_proxy_identity_enable();
- }
-
-done:
- os_mbuf_free_chain(msg);
-}
-
-static void prov_failed(const u8_t *data)
-{
- BT_WARN("Error: 0x%02x", data[0]);
-}
-
-static const struct {
- void (*func)(const u8_t *data);
- u16_t len;
-} prov_handlers[] = {
- { prov_invite, 1 },
- { prov_capabilities, 11 },
- { prov_start, 5, },
- { prov_pub_key, 64 },
- { prov_input_complete, 0 },
- { prov_confirm, 16 },
- { prov_random, 16 },
- { prov_data, 33 },
- { prov_complete, 0 },
- { prov_failed, 1 },
-};
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void prov_retransmit(struct ble_npl_event *work)
-{
- int i, timeout;
-
- BT_DBG("");
-
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- BT_WARN("Link not active");
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_CLOSING)) {
- timeout = CLOSING_TIMEOUT;
- } else {
- timeout = TRANSACTION_TIMEOUT;
- }
-
- if (k_uptime_get() - link.tx.start > timeout) {
- BT_WARN("Giving up transaction");
- reset_adv_link();
- return;
- }
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- if (BT_MESH_ADV(buf)->busy) {
- continue;
- }
-
- BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
- bt_mesh_adv_send(buf, NULL, NULL);
- } else {
- bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
- }
-
- }
-}
-
-static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("link open: len %u", buf->om_len);
-
- if (buf->om_len < 16) {
- BT_ERR("Too short bearer open message (len %u)", buf->om_len);
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE)) {
- /* Send another link ack if the provisioner missed the last */
- if (link.id == rx->link_id && link.expect == PROV_INVITE) {
- BT_DBG("Resending link ack");
- bearer_ctl_send(LINK_ACK, NULL, 0);
- } else {
- BT_WARN("Ignoring bearer open: link already active");
- }
-
- return;
- }
-
- if (memcmp(buf->om_data, prov->uuid, 16)) {
- BT_DBG("Bearer open message not for us");
- return;
- }
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- link.id = rx->link_id;
- atomic_set_bit(link.flags, LINK_ACTIVE);
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_ACK, NULL, 0);
-
- link.expect = PROV_INVITE;
-}
-
-static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("Link ack: len %u", buf->om_len);
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) {
- return;
- }
-
- prov_clear_tx();
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- send_invite();
- }
-}
-
-static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("Link close: len %u", buf->om_len);
-
- reset_adv_link();
-}
-
-static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
-
- switch (BEARER_CTL(rx->gpc)) {
- case LINK_OPEN:
- link_open(rx, buf);
- break;
- case LINK_ACK:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_ack(rx, buf);
- break;
- case LINK_CLOSE:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_close(rx, buf);
- break;
- default:
- BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
-
- if (IS_ENABLED(CONFIG_BT_TESTING)) {
- bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
- }
-
- return;
- }
-}
-
-static void prov_msg_recv(void)
-{
- u8_t type = link.rx.buf->om_data[0];
-
- BT_DBG("type 0x%02x len %u", type, link.rx.buf->om_len);
-
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
- if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
- BT_ERR("Incorrect FCS");
- return;
- }
-
- gen_prov_ack_send(link.rx.id);
- link.rx.prev_id = link.rx.id;
- link.rx.id = 0;
-
- if (atomic_test_bit(link.flags, LINK_INVALID)) {
- BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
-
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
-
- if (type >= ARRAY_SIZE(prov_handlers)) {
- BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- prov_send_fail_msg(PROV_ERR_NVAL_PDU);
- return;
- }
-
- if (1 + prov_handlers[type].len != link.rx.buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x",
- link.rx.buf->om_len, type);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- prov_handlers[type].func(&link.rx.buf->om_data[1]);
-}
-
-static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
-{
- u8_t seg = CONT_SEG_INDEX(rx->gpc);
-
- BT_DBG("len %u, seg_index %u", buf->om_len, seg);
-
- if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- if (rx->xact_id != link.rx.id) {
- BT_WARN("Data for unknown transaction (%u != %u)",
- rx->xact_id, link.rx.id);
- return;
- }
-
- if (seg > link.rx.last_seg) {
- BT_ERR("Invalid segment index %u", seg);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- } else if (seg == link.rx.last_seg) {
- u8_t expect_len;
-
- expect_len = (link.rx.buf->om_len - 20 -
- ((link.rx.last_seg - 1) * 23));
- if (expect_len != buf->om_len) {
- BT_ERR("Incorrect last seg len: %u != %u",
- expect_len, buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
- }
-
- if (!(link.rx.seg & BIT(seg))) {
- BT_WARN("Ignoring already received segment");
- return;
- }
-
- memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
- XACT_SEG_RECV(seg);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("len %u", buf->om_len);
-
- if (!link.tx.buf[0]) {
- return;
- }
-
- if (rx->xact_id == link.tx.id) {
- /* Don't clear resending of LINK_CLOSE messages */
- if (!atomic_test_bit(link.flags, LINK_CLOSING)) {
- prov_clear_tx();
- }
-
- /* Send the PubKey when the the Start message is ACK'ed */
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(link.flags, SEND_PUB_KEY)) {
- if (!bt_pub_key_get()) {
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- } else {
- send_pub_key();
- }
- }
- }
-}
-
-static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
-{
- u16_t trailing_space = 0;
-
- if (link.rx.seg) {
- BT_WARN("Got Start while there are unreceived segments");
- return;
- }
-
- if (link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- trailing_space = OS_MBUF_TRAILINGSPACE(link.rx.buf);
-
- link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
- link.rx.id = rx->xact_id;
- link.rx.fcs = net_buf_simple_pull_u8(buf);
-
- BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->om_len,
- START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
-
- if (link.rx.buf->om_len < 1) {
- BT_ERR("Ignoring zero-length provisioning PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (link.rx.buf->om_len > trailing_space) {
- BT_ERR("Too large provisioning PDU (%u bytes)",
- link.rx.buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20) {
- BT_ERR("Too small total length for multi-segment PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
- link.rx.last_seg = START_LAST_SEG(rx->gpc);
- memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
- XACT_SEG_RECV(0);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static const struct {
- void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
- bool require_link;
- u8_t min_len;
-} gen_prov[] = {
- { gen_prov_start, true, 3 },
- { gen_prov_ack, true, 0 },
- { gen_prov_cont, true, 0 },
- { gen_prov_ctl, false, 0 },
-};
-
-static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
-{
- if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
- BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
- return;
- }
-
- if (!atomic_test_bit(link.flags, LINK_ACTIVE) &&
- gen_prov[GPCF(rx->gpc)].require_link) {
- BT_DBG("Ignoring message that requires active link");
- return;
- }
-
- BT_DBG("prov_action: %d", GPCF(rx->gpc));
- gen_prov[GPCF(rx->gpc)].func(rx, buf);
-}
-
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
-{
- struct prov_rx rx;
-
- if (!bt_prov_active() && bt_mesh_is_provisioned()) {
- BT_DBG("Ignoring provisioning PDU - already provisioned");
- return;
- }
-
- if (buf->om_len < 6) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return;
- }
-
- rx.link_id = net_buf_simple_pull_be32(buf);
- rx.xact_id = net_buf_simple_pull_u8(buf);
- rx.gpc = net_buf_simple_pull_u8(buf);
-
- BT_DBG("link_id 0x%08x xact_id %u", (unsigned) rx.link_id, rx.xact_id);
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE) && link.id != rx.link_id) {
- BT_DBG("Ignoring mesh beacon for unknown link");
- return;
- }
-
- gen_prov_recv(&rx, buf);
-}
-
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration)
-{
- BT_DBG("uuid %s", bt_hex(uuid, 16));
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- return -EBUSY;
- }
-
- atomic_set_bit(link.flags, PROVISIONER);
-
- bt_rand(&link.id, sizeof(link.id));
- link.tx.id = 0x7F;
- link.provisioner->addr = addr;
- link.provisioner->net_idx = net_idx;
- link.provisioner->attention_duration = attention_duration;
-
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_OPEN, uuid, 16);
-
- return 0;
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
-{
- u8_t type;
-
- BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (link.conn_handle != conn_handle) {
- BT_WARN("Data for unexpected connection");
- return -ENOTCONN;
- }
-
- if (buf->om_len < 1) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return -EINVAL;
- }
-
- type = net_buf_simple_pull_u8(buf);
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return -EINVAL;
- }
-
- if (type >= ARRAY_SIZE(prov_handlers)) {
- BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- return -EINVAL;
- }
-
- if (prov_handlers[type].len != buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
- return -EINVAL;
- }
-
- prov_handlers[type].func(buf->om_data);
-
- return 0;
-}
-
-int bt_mesh_pb_gatt_open(uint16_t conn_handle)
-{
- BT_DBG("conn_handle %d", conn_handle);
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- BT_ERR("Link already opened?");
- return -EBUSY;
- }
-
- link.conn_handle = conn_handle;
- link.expect = PROV_INVITE;
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_GATT);
- }
-
- return 0;
-}
-
-int bt_mesh_pb_gatt_close(uint16_t conn_handle)
-{
- BT_DBG("conn_handle %d", conn_handle);
-
- if (link.conn_handle != conn_handle) {
- BT_ERR("Not connected");
- return -ENOTCONN;
- }
-
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_GATT);
- }
-
- return reset_state();
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
const struct bt_mesh_prov *bt_mesh_prov_get(void)
{
- return prov;
+ return bt_mesh_prov;
}
-bool bt_prov_active(void)
+bool bt_mesh_prov_active(void)
{
- return atomic_test_bit(link.flags, LINK_ACTIVE);
+ return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
}
-static void protocol_timeout(struct ble_npl_event *work)
+static void prov_recv(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf)
{
- BT_DBG("Protocol timeout");
+ static const uint8_t op_len[10] = {
+ [PROV_INVITE] = 1,
+ [PROV_CAPABILITIES] = 11,
+ [PROV_START] = 5,
+ [PROV_PUB_KEY] = 64,
+ [PROV_INPUT_COMPLETE] = 0,
+ [PROV_CONFIRM] = 16,
+ [PROV_RANDOM] = 16,
+ [PROV_DATA] = 33,
+ [PROV_COMPLETE] = 0,
+ [PROV_FAILED] = 1,
+ };
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- bt_mesh_pb_gatt_close(link.conn_handle);
+ uint8_t type = buf->om_data[0];
+ BT_DBG("type 0x%02x len %u", type, buf->om_len);
+
+ if (type >= ARRAY_SIZE(bt_mesh_prov_link.role->op)) {
+ BT_ERR("Unknown provisioning PDU type 0x%02x", type);
+ bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
return;
}
-#endif
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_TIMEOUT;
+ if ((type != PROV_FAILED && type != bt_mesh_prov_link.expect) ||
+ !bt_mesh_prov_link.role->op[type]) {
+ BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, bt_mesh_prov_link.expect);
+ bt_mesh_prov_link.role->error(PROV_ERR_UNEXP_PDU);
+ return;
+ }
- link.rx.seg = 0U;
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
+ if (1 + op_len[type] != buf->om_len) {
+ BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
+ bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
+ return;
+ }
- reset_state();
-#endif
+ bt_mesh_prov_link.role->op[type](&buf->om_data[1]);
+}
+
+static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
+
+ BT_ERR("bt_mesh_prov->link_open");
+ if (bt_mesh_prov->link_open) {
+ bt_mesh_prov->link_open(bearer->type);
+ }
+
+ BT_ERR("bt_mesh_prov_link.bearer");
+ bt_mesh_prov_link.bearer = bearer;
+
+ BT_ERR("bt_mesh_prov_link.role->link_opened");
+ BT_ERR("%p", bt_mesh_prov_link.role);
+ BT_ERR("%p", bt_mesh_prov_link.role->link_opened);
+ if (bt_mesh_prov_link.role->link_opened) {
+ bt_mesh_prov_link.role->link_opened();
+ }
+ BT_ERR("done");
+}
+
+static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason)
+{
+ if (bt_mesh_prov_link.role->link_closed) {
+ bt_mesh_prov_link.role->link_closed();
+ }
+
+ if (bt_mesh_prov->link_close) {
+ bt_mesh_prov->link_close(bearer->type);
+ }
+}
+
+static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err)
+{
+ if (bt_mesh_prov_link.role->error) {
+ bt_mesh_prov_link.role->error(err);
+ }
+}
+
+static const struct prov_bearer_cb prov_bearer_cb = {
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_bearer_error,
+ .recv = prov_recv,
+};
+
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void)
+{
+ return &prov_bearer_cb;
+}
+
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr)
+{
+ if (bt_mesh_prov->complete) {
+ bt_mesh_prov->complete(net_idx, addr);
+ }
+}
+
+void bt_mesh_prov_reset(void)
+{
+ BT_DBG("bt_mesh_prov_reset");
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_reset();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_reset();
+ }
+
+ bt_mesh_prov_reset_state(NULL);
+
+ if (bt_mesh_prov->reset) {
+ bt_mesh_prov->reset();
+ }
}
int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
@@ -1961,48 +363,14 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
return -EINVAL;
}
- k_delayed_work_init(&link.prot_timer, protocol_timeout);
+ bt_mesh_prov = prov_info;
- prov = prov_info;
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
-#endif
-
- return reset_state();
-}
-
-void bt_mesh_prov_reset_link(void)
-{
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif
-#endif
-}
-
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr)
-{
- if (prov->complete) {
- prov->complete(net_idx, addr);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_init();
}
-}
-
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
-{
- if (prov->node_added) {
- prov->node_added(net_idx, addr, num_elem);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_init();
}
-}
-void bt_mesh_prov_reset(void)
-{
- if (prov->reset) {
- prov->reset();
- }
+ return bt_mesh_prov_reset_state(NULL);
}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PROV) */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
index 96e5a447..89f02725 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
@@ -9,16 +9,131 @@
#ifndef __PROV_H__
#define __PROV_H__
+#include "prov_bearer.h"
#include "os/os_mbuf.h"
#include "mesh/mesh.h"
#include "../src/ble_hs_conn_priv.h"
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration);
+#define PROV_ERR_NONE 0x00
+#define PROV_ERR_NVAL_PDU 0x01
+#define PROV_ERR_NVAL_FMT 0x02
+#define PROV_ERR_UNEXP_PDU 0x03
+#define PROV_ERR_CFM_FAILED 0x04
+#define PROV_ERR_RESOURCES 0x05
+#define PROV_ERR_DECRYPT 0x06
+#define PROV_ERR_UNEXP_ERR 0x07
+#define PROV_ERR_ADDR 0x08
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+#define AUTH_METHOD_NO_OOB 0x00
+#define AUTH_METHOD_STATIC 0x01
+#define AUTH_METHOD_OUTPUT 0x02
+#define AUTH_METHOD_INPUT 0x03
-bool bt_prov_active(void);
+#define OUTPUT_OOB_BLINK 0x00
+#define OUTPUT_OOB_BEEP 0x01
+#define OUTPUT_OOB_VIBRATE 0x02
+#define OUTPUT_OOB_NUMBER 0x03
+#define OUTPUT_OOB_STRING 0x04
+
+#define INPUT_OOB_PUSH 0x00
+#define INPUT_OOB_TWIST 0x01
+#define INPUT_OOB_NUMBER 0x02
+#define INPUT_OOB_STRING 0x03
+
+#define PUB_KEY_NO_OOB 0x00
+#define PUB_KEY_OOB 0x01
+
+#define PROV_INVITE 0x00
+#define PROV_CAPABILITIES 0x01
+#define PROV_START 0x02
+#define PROV_PUB_KEY 0x03
+#define PROV_INPUT_COMPLETE 0x04
+#define PROV_CONFIRM 0x05
+#define PROV_RANDOM 0x06
+#define PROV_DATA 0x07
+#define PROV_COMPLETE 0x08
+#define PROV_FAILED 0x09
+
+#define PROV_NO_PDU 0xff
+
+#define PROV_ALG_P256 0x00
+
+#define PROV_BUF(len) \
+ NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len)
+
+enum {
+ WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
+ LINK_ACTIVE, /* Link has been opened */
+ WAIT_NUMBER, /* Waiting for number input from user */
+ WAIT_STRING, /* Waiting for string input from user */
+ NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
+ PROVISIONER, /* The link was opened as provisioner */
+ OOB_PUB_KEY, /* OOB Public key used */
+ PUB_KEY_SENT, /* Public key has been sent */
+ REMOTE_PUB_KEY, /* Remote key has been received */
+ INPUT_COMPLETE, /* Device input completed */
+ WAIT_CONFIRM, /* Wait for send confirm */
+ WAIT_AUTH, /* Wait for auth response */
+ OOB_STATIC_KEY, /* OOB Static Authentication */
+
+ NUM_FLAGS,
+};
+
+/** Provisioning role */
+struct bt_mesh_prov_role {
+ void (*link_opened)(void);
+
+ void (*link_closed)(void);
+
+ void (*error)(uint8_t reason);
+
+ void (*input_complete)(void);
+
+ void (*op[10])(const uint8_t *data);
+};
+
+struct bt_mesh_prov_link {
+ ATOMIC_DEFINE(flags, NUM_FLAGS);
+
+ const struct prov_bearer *bearer;
+ const struct bt_mesh_prov_role *role;
+
+ uint8_t oob_method; /* Authen method */
+ uint8_t oob_action; /* Authen action */
+ uint8_t oob_size; /* Authen size */
+ uint8_t auth[16]; /* Authen value */
+
+ uint8_t dhkey[32]; /* Calculated DHKey */
+ uint8_t expect; /* Next expected PDU */
+ uint8_t conf[16]; /* Remote Confirmation */
+ uint8_t rand[16]; /* Local Random */
+
+ uint8_t conf_salt[16]; /* ConfirmationSalt */
+ uint8_t conf_key[16]; /* ConfirmationKey */
+ uint8_t conf_inputs[145]; /* ConfirmationInputs */
+ uint8_t prov_salt[16]; /* Provisioning Salt */
+};
+
+extern struct bt_mesh_prov_link bt_mesh_prov_link;
+extern const struct bt_mesh_prov *bt_mesh_prov;
+
+static inline int bt_mesh_prov_send(struct os_mbuf *buf,
+ prov_bearer_send_complete_t cb)
+{
+ return bt_mesh_prov_link.bearer->send(buf, cb, NULL);
+}
+
+static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type)
+{
+ net_buf_reserve(buf, PROV_BEARER_BUF_HEADROOM);
+ net_buf_simple_add_u8(buf, type);
+}
+
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]));
+
+bool bt_mesh_prov_active(void);
+
+int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size);
int bt_mesh_pb_gatt_open(uint16_t conn_handle);
int bt_mesh_pb_gatt_close(uint16_t conn_handle);
@@ -26,12 +141,14 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf);
const struct bt_mesh_prov *bt_mesh_prov_get(void);
-int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
-
void bt_mesh_prov_reset_link(void);
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem);
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr);
void bt_mesh_prov_reset(void);
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void);
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
new file mode 100644
index 00000000..3e526831
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
@@ -0,0 +1,116 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define PROTOCOL_TIMEOUT K_SECONDS(60)
+
+/** @def PROV_BEARER_BUF_HEADROOM
+ *
+ * @brief Required headroom for the bearer packet buffers.
+ */
+#if MYNEWT_VAL(BLE_MESH_PB_GATT)
+#define PROV_BEARER_BUF_HEADROOM 5
+#else
+#define PROV_BEARER_BUF_HEADROOM 0
+#endif
+
+enum prov_bearer_link_status {
+ PROV_BEARER_LINK_STATUS_SUCCESS,
+ PROV_BEARER_LINK_STATUS_TIMEOUT,
+ PROV_BEARER_LINK_STATUS_FAIL,
+};
+
+struct prov_bearer;
+
+/** Callbacks from bearer to host */
+struct prov_bearer_cb {
+
+ void (*link_opened)(const struct prov_bearer *bearer, void *cb_data);
+
+ void (*link_closed)(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason);
+
+ void (*error)(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err);
+
+ void (*recv)(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf);
+};
+
+typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data);
+
+/** Provisioning bearer API */
+struct prov_bearer {
+ /** Provisioning bearer type. */
+ bt_mesh_prov_bearer_t type;
+
+ /** @brief Enable link establishment as a provisionee.
+ *
+ * Prompts the bearer to make itself visible to provisioners, and
+ * start accepting link open messages.
+ *
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Send a packet on an established link.
+ *
+ * @param buf Payload buffer. Requires @ref
+ * PROV_BEARER_BUF_HEADROOM bytes of headroom.
+ * @param cb Callback to call when sending is complete.
+ * @param cb_data Callback data.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*send)(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data);
+
+ /** @brief Clear any ongoing transmissions, if possible.
+ *
+ * Bearers that don't support tx clearing must implement this callback
+ * and leave it empty.
+ */
+ void (*clear_tx)(void);
+
+ /* Only available in provisioners: */
+
+ /** @brief Open a new link as a provisioner.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param uuid UUID of the node to establish a link to.
+ * @param timeout Protocol timeout.
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_open)(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Close the current link.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param status Link status for the link close message.
+ */
+ void (*link_close)(enum prov_bearer_link_status status);
+};
+
+extern const struct prov_bearer pb_adv;
+extern const struct prov_bearer pb_gatt;
+
+void pb_adv_init(void);
+void pb_gatt_init(void);
+
+void pb_adv_reset(void);
+void pb_gatt_reset(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
new file mode 100644
index 00000000..38a96e7a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
@@ -0,0 +1,569 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "testing.h"
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static void send_pub_key(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_send_fail_msg(uint8_t err)
+{
+ struct os_mbuf *buf = PROV_BUF(2);
+
+ BT_DBG("%u", err);
+
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_buf_init(buf, PROV_FAILED);
+ net_buf_simple_add_u8(buf, err);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Failed message");
+ }
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_send_fail_msg(reason);
+}
+
+static void prov_invite(const uint8_t *data)
+{
+ struct os_mbuf *buf = PROV_BUF(12);
+
+ BT_DBG("Attention Duration: %u seconds", data[0]);
+
+ if (data[0]) {
+ bt_mesh_attention(NULL, data[0]);
+ }
+
+ bt_mesh_prov_link.conf_inputs[0] = data[0];
+
+ bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES);
+
+ /* Number of Elements supported */
+ net_buf_simple_add_u8(buf, bt_mesh_elem_count());
+
+ /* Supported algorithms - FIPS P-256 Eliptic Curve */
+ net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
+
+ /* Public Key Type, Only "No OOB" Public Key is supported */
+ net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
+
+ /* Static OOB Type */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00);
+
+ /* Output OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->output_size);
+
+ /* Output OOB Action */
+ net_buf_simple_add_be16(buf, bt_mesh_prov->output_actions);
+
+ /* Input OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->input_size);
+
+ /* Input OOB Action */
+ net_buf_simple_add_be16(buf, bt_mesh_prov->input_actions);
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[1], &buf->om_data[1], 11);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send capabilities");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_START;
+}
+
+static void prov_start(const uint8_t *data)
+{
+ BT_DBG("Algorithm: 0x%02x", data[0]);
+ BT_DBG("Public Key: 0x%02x", data[1]);
+ BT_DBG("Auth Method: 0x%02x", data[2]);
+ BT_DBG("Auth Action: 0x%02x", data[3]);
+ BT_DBG("Auth Size: 0x%02x", data[4]);
+
+ if (data[0] != PROV_ALG_P256) {
+ BT_ERR("Unknown algorithm 0x%02x", data[0]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (data[1] != PUB_KEY_NO_OOB) {
+ BT_ERR("Invalid public key type: 0x%02x", data[1]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5);
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+
+ if (bt_mesh_prov_auth(data[2], data[3], data[4]) < 0) {
+ BT_ERR("Invalid authentication method: 0x%02x; "
+ "action: 0x%02x; size: 0x%02x", data[2], data[3],
+ data[4]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) {
+ memcpy(bt_mesh_prov_link.auth + 16 - bt_mesh_prov->static_val_len,
+ bt_mesh_prov->static_val, bt_mesh_prov->static_val_len);
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - bt_mesh_prov->static_val_len);
+ }
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
+ BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
+ BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, bt_mesh_prov_link.rand,
+ bt_mesh_prov_link.auth, net_buf_simple_add(cfm, 16))) {
+ BT_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+
+}
+
+static void send_input_complete(void)
+{
+ struct os_mbuf *buf = PROV_BUF(1);
+
+ bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE);
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Input Complete");
+ }
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE)) {
+ send_input_complete();
+ return;
+ }
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
+
+ /* Swap X and Y halves independently to big-endian */
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
+
+ /* PublicKeyRemote */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ return;
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
+ bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */
+ } else {
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
+
+ BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
+
+ send_pub_key();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[17];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * X and Y halves are swapped independently. The bt_dh_key_gen()
+ * will also take care of validating the remote public key.
+ */
+ sys_memcpy_swap(remote_pk_le, remote_pk, 32);
+ sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+ BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+ /* PublicKeyProvisioner */
+ memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64);
+
+ if (!bt_pub_key_get()) {
+ /* Clear retransmit timer */
+ bt_mesh_prov_link.bearer->clear_tx();
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
+ BT_WARN("Waiting for local public key");
+ return;
+ }
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ prov_dh_key_gen();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_DATA;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, data,
+ bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, data,
+ bt_mesh_prov_link.rand, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_random();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ notify_input_complete();
+
+ send_confirm();
+}
+
+static inline bool is_pb_gatt(void)
+{
+ return bt_mesh_prov_link.bearer &&
+ bt_mesh_prov_link.bearer->type == BT_MESH_PROV_GATT;
+}
+
+static void prov_data(const uint8_t *data)
+{
+ struct os_mbuf *msg = PROV_BUF(1);
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ uint8_t dev_key[16];
+ uint8_t pdu[25];
+ uint8_t flags;
+ uint32_t iv_index;
+ uint16_t addr;
+ uint16_t net_idx;
+ int err;
+ bool identity_enable;
+
+ BT_DBG("");
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
+ if (err) {
+ BT_ERR("Unable to decrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
+
+ net_idx = sys_get_be16(&pdu[16]);
+ flags = pdu[18];
+ iv_index = sys_get_be32(&pdu[19]);
+ addr = sys_get_be16(&pdu[23]);
+
+ BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
+ net_idx, iv_index, addr);
+
+ bt_mesh_prov_buf_init(msg, PROV_COMPLETE);
+ if (bt_mesh_prov_send(msg, NULL)) {
+ BT_ERR("Failed to send Provisioning Complete");
+ return;
+ }
+
+ /* Ignore any further PDUs on this link */
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ /* Store info, since bt_mesh_provision() will end up clearing it */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ identity_enable = is_pb_gatt();
+ } else {
+ identity_enable = false;
+ }
+
+ err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+ if (err) {
+ BT_ERR("Failed to provision (err %d)", err);
+ return;
+ }
+
+ /* After PB-GATT provisioning we should start advertising
+ * using Node Identity.
+ */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
+ bt_mesh_proxy_identity_enable();
+ }
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) {
+ send_input_complete();
+ } else {
+ atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE);
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ bt_mesh_prov_link.expect = PROV_INVITE;
+}
+
+static const struct bt_mesh_prov_role role_device = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_INVITE] = prov_invite,
+ [PROV_START] = prov_start,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_DATA] = prov_data,
+ },
+};
+
+int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
+{
+ BT_DBG("bt_mesh_prov_enable");
+
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ pb_adv.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ pb_gatt.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ BT_DBG("bt_mesh_prov_link.role = &role_device");
+ bt_mesh_prov_link.role = &role_device;
+
+ return 0;
+}
+
+int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
+{
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ bt_mesh_beacon_disable();
+ bt_mesh_scan_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ bt_mesh_proxy_prov_disable(true);
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
new file mode 100644
index 00000000..371c1f6c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
@@ -0,0 +1,746 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "testing.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static struct {
+ struct bt_mesh_cdb_node *node;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t attention_duration;
+ uint8_t uuid[16];
+} prov_device;
+
+static void send_pub_key(void);
+static void prov_dh_key_gen(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+#if BLE_MESH_CDB
+ if (prov_device.node != NULL) {
+ bt_mesh_cdb_node_del(prov_device.node, false);
+ }
+#endif
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ BT_DBG("%u", status);
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_link.bearer->link_close(status);
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_link_close(PROV_BEARER_LINK_STATUS_FAIL);
+}
+
+static void send_invite(void)
+{
+ struct os_mbuf *inv = PROV_BUF(2);
+
+ BT_DBG("");
+
+ bt_mesh_prov_buf_init(inv, PROV_INVITE);
+ net_buf_simple_add_u8(inv, prov_device.attention_duration);
+
+ bt_mesh_prov_link.conf_inputs[0] = prov_device.attention_duration;
+
+ if (bt_mesh_prov_send(inv, NULL)) {
+ BT_ERR("Failed to send invite");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CAPABILITIES;
+}
+
+static void start_sent(int err, void *cb_data)
+{
+ if (!bt_pub_key_get()) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
+ BT_WARN("Waiting for local public key");
+ } else {
+ send_pub_key();
+ }
+}
+
+static void send_start(void)
+{
+ BT_DBG("");
+ uint8_t method, action;
+ struct os_mbuf *start = PROV_BUF(6);
+
+ const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3];
+
+ bt_mesh_prov_buf_init(start, PROV_START);
+ net_buf_simple_add_u8(start, PROV_ALG_P256);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) &&
+ *data == PUB_KEY_OOB) {
+ net_buf_simple_add_u8(start, PUB_KEY_OOB);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY);
+ } else {
+ net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
+ }
+
+ if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
+ method = AUTH_METHOD_OUTPUT;
+ if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
+ action = OUTPUT_OOB_STRING;
+ } else {
+ action = OUTPUT_OOB_NUMBER;
+ }
+
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
+ method = AUTH_METHOD_INPUT;
+ if (bt_mesh_prov_link.oob_action == OUTPUT_OOB_STRING) {
+ action = INPUT_OOB_STRING;
+ } else {
+ action = INPUT_OOB_NUMBER;
+ }
+ } else {
+ method = bt_mesh_prov_link.oob_method;
+ action = 0x00;
+ }
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_method);
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_action);
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_size);
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[12], &start->om_data[1], 5);
+
+ if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) {
+ BT_ERR("Invalid authentication method: 0x%02x; "
+ "action: 0x%02x; size: 0x%02x", method,
+ action, bt_mesh_prov_link.oob_size);
+ return;
+ }
+
+ if (bt_mesh_prov_send(start, start_sent)) {
+ BT_ERR("Failed to send Provisioning Start");
+ return;
+ }
+}
+
+static bool prov_check_method(struct bt_mesh_dev_capabilities *caps)
+{
+ if (bt_mesh_prov_link.oob_method == AUTH_METHOD_STATIC) {
+ if (!caps->static_oob) {
+ BT_WARN("Device not support OOB static authentication provisioning");
+ return false;
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->input_size) {
+ BT_WARN("The required input length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->input_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) {
+ BT_WARN("The required input action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->input_actions);
+ return false;
+ }
+
+ if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
+ if (!bt_mesh_prov->output_string) {
+ BT_WARN("Not support output string");
+ return false;
+ }
+ } else {
+ if (!bt_mesh_prov->output_number) {
+ BT_WARN("Not support output number");
+ return false;
+ }
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->output_size) {
+ BT_WARN("The required output length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->output_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) {
+ BT_WARN("The required output action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->output_actions);
+ return false;
+ }
+
+ if (!bt_mesh_prov->input) {
+ BT_WARN("Not support input");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void prov_capabilities(const uint8_t *data)
+{
+ struct bt_mesh_dev_capabilities caps;
+
+ caps.elem_count = data[0];
+ BT_DBG("Elements: %u", caps.elem_count);
+
+ caps.algorithms = sys_get_be16(&data[1]);
+ BT_DBG("Algorithms: %u", caps.algorithms);
+
+ caps.pub_key_type = data[3];
+ caps.static_oob = data[4];
+ caps.output_size = data[5];
+ BT_DBG("Public Key Type: 0x%02x", caps.pub_key_type);
+ BT_DBG("Static OOB Type: 0x%02x", caps.static_oob);
+ BT_DBG("Output OOB Size: %u", caps.output_size);
+
+ caps.output_actions = (bt_mesh_output_action_t)data[6];
+ caps.input_size = data[8];
+ caps.input_actions = (bt_mesh_input_action_t)data[9];
+ BT_DBG("Output OOB Action: 0x%04x", caps.output_actions);
+ BT_DBG("Input OOB Size: %u", caps.input_size);
+ BT_DBG("Input OOB Action: 0x%04x", caps.input_actions);
+
+ if (data[0] == 0) {
+ BT_ERR("Invalid number of elements");
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+#if BLE_MESH_CDB
+ prov_device.node =
+ bt_mesh_cdb_node_alloc(prov_device.uuid,
+ prov_device.addr, data[0],
+ prov_device.net_idx);
+ if (prov_device.node == NULL) {
+ BT_ERR("Failed allocating node 0x%04x", prov_device.addr);
+ prov_fail(PROV_ERR_RESOURCES);
+ return;
+ }
+#endif
+ memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11);
+
+ if (bt_mesh_prov->capabilities) {
+ bt_mesh_prov->capabilities(&caps);
+ }
+
+ if (!prov_check_method(&caps)) {
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ send_start();
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
+ BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
+ BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.conf_salt, bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
+ bt_mesh_prov_link.rand, bt_mesh_prov_link.auth,
+ net_buf_simple_add(cfm, 16))) {
+ BT_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY) &&
+ atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ prov_dh_key_gen();
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
+
+ /* Swap X and Y halves independently to big-endian */
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
+
+ /* PublicKeyProvisioner */
+ memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ return;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
+
+ BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM);
+ return;
+ }
+
+ send_confirm();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[81];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * X and Y halves are swapped independently. The bt_dh_key_gen()
+ * will also take care of validating the remote public key.
+ */
+ sys_memcpy_swap(remote_pk_le, remote_pk, 32);
+ sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
+ }
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+ BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+ atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY);
+
+ /* PublicKeyDevice */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64);
+ bt_mesh_prov_link.bearer->clear_tx();
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ send_pub_key();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void prov_input_complete(const uint8_t *data)
+{
+ BT_DBG("");
+
+ notify_input_complete();
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void send_prov_data(void)
+{
+ struct os_mbuf *pdu = PROV_BUF(34);
+#if BLE_MESH_CDB
+ struct bt_mesh_cdb_subnet *sub;
+#endif
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ int err;
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, prov_device.node->dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(prov_device.node->dev_key, 16));
+#if BLE_MESH_CDB
+ sub = bt_mesh_cdb_subnet_get(prov_device.node->net_idx);
+ if (sub == NULL) {
+ BT_ERR("No subnet with net_idx %u",
+ prov_device.node->net_idx);
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+#endif
+ bt_mesh_prov_buf_init(pdu, PROV_DATA);
+#if BLE_MESH_CDB
+ net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net_key, 16);
+ net_buf_simple_add_be16(pdu, prov_device.node->net_idx);
+ net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub));
+ net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index);
+#endif
+ net_buf_simple_add_be16(pdu, prov_device.node->addr);
+ net_buf_simple_add(pdu, 8); /* For MIC */
+
+ BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
+ prov_device.node->net_idx, bt_mesh.iv_index,
+ prov_device.node->addr);
+
+ err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
+ &pdu->om_data[1]);
+ if (err) {
+ BT_ERR("Unable to encrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ if (bt_mesh_prov_send(pdu, NULL)) {
+ BT_ERR("Failed to send Provisioning Data");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_COMPLETE;
+}
+
+static void prov_complete(const uint8_t *data)
+{
+ struct bt_mesh_cdb_node *node = prov_device.node;
+
+ BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
+ bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
+ node->addr);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+
+ prov_device.node = NULL;
+ prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ if (bt_mesh_prov->node_added) {
+ bt_mesh_prov->node_added(node->net_idx, node->uuid, node->addr,
+ node->num_elem);
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
+ data, bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.rand, data, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_prov_data();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ send_random();
+}
+
+static void prov_failed(const uint8_t *data)
+{
+ BT_WARN("Error: 0x%02x", data[0]);
+ reset_state();
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ send_invite();
+}
+
+static const struct bt_mesh_prov_role role_provisioner = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_CAPABILITIES] = prov_capabilities,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_INPUT_COMPLETE] = prov_input_complete,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_COMPLETE] = prov_complete,
+ [PROV_FAILED] = prov_failed,
+ },
+};
+
+static void prov_set_method(uint8_t method, uint8_t action, uint8_t size)
+{
+ bt_mesh_prov_link.oob_method = method;
+ bt_mesh_prov_link.oob_action = action;
+ bt_mesh_prov_link.oob_size = size;
+}
+
+int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_INPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_OUTPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size)
+{
+ if (!size || !static_val || size > 16) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_STATIC, 0, 0);
+
+ memcpy(bt_mesh_prov_link.auth + 16 - size, static_val, size);
+ if (size < 16) {
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
+ }
+ return 0;
+}
+
+int bt_mesh_auth_method_set_none(void)
+{
+ prov_set_method(AUTH_METHOD_NO_OOB, 0, 0);
+ return 0;
+}
+
+int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64])
+{
+ if (public_key == NULL) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ return -EALREADY;
+ }
+
+ /* Swap X and Y halves independently to big-endian */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 32);
+ memcpy(&bt_mesh_prov_link.conf_inputs[81 + 32], &public_key[32], 32);
+
+ return 0;
+}
+
+#if defined(CONFIG_BT_MESH_PB_ADV)
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ int err;
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER);
+ memcpy(prov_device.uuid, uuid, 16);
+ prov_device.addr = addr;
+ prov_device.net_idx = net_idx;
+ prov_device.attention_duration = attention_duration;
+ bt_mesh_prov_link.bearer = &pb_adv;
+ bt_mesh_prov_link.role = &role_provisioner;
+
+ err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT,
+ bt_mesh_prov_bearer_cb_get(), NULL);
+ if (err) {
+ atomic_clear_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
+ }
+
+ return err;
+}
+#endif
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
new file mode 100644
index 00000000..ccda47ef
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
@@ -0,0 +1,10 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration);
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
index 134a36dd..6d631b72 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
@@ -19,6 +19,7 @@
#include "mesh_priv.h"
#include "adv.h"
#include "net.h"
+#include "rpl.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"
@@ -28,6 +29,9 @@
#define PDU_TYPE(data) (data[0] & BIT_MASK(6))
#define PDU_SAR(data) (data[0] >> 6)
+#define BT_UUID_16_ENCODE(w16) \
+ (((w16) >> 0) & 0xFF), \
+ (((w16) >> 8) & 0xFF)
/* Mesh Profile 1.0 Section 6.6:
* "The timeout for the SAR transfer is 20 seconds. When the timeout
* expires, the Proxy Server shall disconnect."
@@ -110,14 +114,14 @@ static bool prov_fast_adv;
static struct bt_mesh_proxy_client {
uint16_t conn_handle;
- u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
+ uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
enum __packed {
NONE,
WHITELIST,
BLACKLIST,
PROV,
} filter_type;
- u8_t msg_type;
+ uint8_t msg_type;
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
struct ble_npl_callout send_beacons;
#endif
@@ -127,6 +131,9 @@ static struct bt_mesh_proxy_client {
[0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 },
};
+static sys_slist_t idle_waiters;
+static atomic_t pending_notifications;
+
/* Track which service is enabled */
static enum {
MESH_GATT_NONE,
@@ -195,15 +202,15 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle)
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
/* Next subnet in queue to be advertised */
-static int next_idx;
+static struct bt_mesh_subnet *beacon_sub;
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg);
static int filter_set(struct bt_mesh_proxy_client *client,
struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
if (buf->om_len < 1) {
BT_WARN("Too short Filter Set message");
@@ -230,7 +237,7 @@ static int filter_set(struct bt_mesh_proxy_client *client,
return 0;
}
-static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -254,7 +261,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
}
}
-static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -281,7 +288,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client,
.ctx = &rx->ctx,
.src = bt_mesh_primary_addr(),
};
- u16_t filter_size;
+ uint16_t filter_size;
int i, err;
/* Configuration messages always have dst unassigned */
@@ -323,7 +330,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
struct bt_mesh_net_rx rx;
- u8_t opcode;
+ uint8_t opcode;
int err;
err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG,
@@ -333,8 +340,16 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
goto done;
}
+ rx.local_match = 1U;
+
+ if (bt_mesh_rpl_check(&rx, NULL)) {
+ BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
+ rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
+ goto done;
+ }
+
/* Remove network headers */
- net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
+ net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN);
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
@@ -351,7 +366,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_ADD:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_add(client, addr);
@@ -360,7 +375,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_REMOVE:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_remove(client, addr);
@@ -389,21 +404,20 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub)
return rc;
}
+static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data)
+{
+ struct bt_mesh_proxy_client *client = cb_data;
+
+ return beacon_send(client->conn_handle, sub);
+}
+
static void proxy_send_beacons(struct ble_npl_event *work)
{
struct bt_mesh_proxy_client *client;
- int i;
-
client = ble_npl_event_get_arg(work);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- beacon_send(client->conn_handle, sub);
- }
- }
+ (void)bt_mesh_subnet_find(send_beacon_cb, client);
}
static void proxy_sar_timeout(struct ble_npl_event *work)
@@ -429,12 +443,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
if (!sub) {
/* NULL means we send on all subnets */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
- }
- }
-
+ bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send);
return;
}
@@ -445,13 +454,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
}
}
-void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+static void node_id_start(struct bt_mesh_subnet *sub)
{
sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
sub->node_id_start = k_uptime_get_32();
+}
+void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+{
+ node_id_start(sub);
/* Prioritize the recently enabled subnet */
- next_idx = sub - bt_mesh.sub;
+ beacon_sub = sub;
}
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
@@ -462,30 +475,13 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
int bt_mesh_proxy_identity_enable(void)
{
- int i, count = 0;
-
BT_DBG("");
if (!bt_mesh_is_provisioned()) {
return -EAGAIN;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
- continue;
- }
-
- bt_mesh_proxy_identity_start(sub);
- count++;
- }
-
- if (count) {
+ if (bt_mesh_subnet_foreach(node_id_start)) {
bt_mesh_adv_update();
}
@@ -528,9 +524,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg)
{
- struct bt_mesh_proxy_client *client;
- const u8_t *data = ctxt->om->om_data;
- u16_t len = ctxt->om->om_len;
+ struct bt_mesh_proxy_client *client = find_client(conn_handle);
+ const uint8_t *data = ctxt->om->om_data;
+ uint16_t len = ctxt->om->om_len;
client = find_client(conn_handle);
@@ -652,7 +648,9 @@ static void proxy_connected(uint16_t conn_handle)
static void proxy_disconnected(uint16_t conn_handle, int reason)
{
int i;
- bool disconnected = false;
+
+ BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason);
+ conn_count--;
for (i = 0; i < ARRAY_SIZE(clients); i++) {
struct bt_mesh_proxy_client *client = &clients[i];
@@ -665,16 +663,11 @@ static void proxy_disconnected(uint16_t conn_handle, int reason)
k_delayed_work_cancel(&client->sar_timer);
client->conn_handle = BLE_HS_CONN_HANDLE_NONE;
- conn_count--;
- disconnected = true;
break;
}
}
- if (disconnected) {
- BT_INFO("conn_handle %d reason %d", conn_handle, reason);
- bt_mesh_adv_update();
- }
+ bt_mesh_adv_update();
}
struct os_mbuf *bt_mesh_proxy_get_buf(void)
@@ -887,7 +880,7 @@ int bt_mesh_proxy_gatt_disable(void)
return 0;
}
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
+void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr)
{
struct bt_mesh_proxy_client *client = NULL;
int i;
@@ -911,7 +904,7 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
}
static bool client_filter_match(struct bt_mesh_proxy_client *client,
- u16_t addr)
+ uint16_t addr)
{
int i;
@@ -942,7 +935,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
return false;
}
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
+bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst)
{
bool relayed = false;
int i;
@@ -978,9 +971,25 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */
-static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
+static void notify_complete(void)
+{
+ sys_snode_t *n;
+
+ if (atomic_dec(&pending_notifications) > 1) {
+ return;
+ }
+
+ BT_DBG("");
+
+ while ((n = sys_slist_get(&idle_waiters))) {
+ CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb();
+ }
+}
+
+static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len)
{
struct os_mbuf *om;
+ int err = 0;
BT_DBG("%u bytes: %s", len, bt_hex(data, len));
@@ -988,7 +997,8 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROXY) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ notify_complete();
}
#endif
@@ -996,17 +1006,22 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROV) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ notify_complete();
}
#endif
- return 0;
+ if (!err) {
+ atomic_inc(&pending_notifications);
+ }
+
+ return err;
}
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
- u16_t mtu;
+ uint16_t mtu;
BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len,
bt_hex(msg->om_data, msg->om_len));
@@ -1020,7 +1035,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
while (msg->om_len) {
if (msg->om_len + 1 < mtu) {
@@ -1031,13 +1046,13 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
}
return 0;
}
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
+int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
struct bt_mesh_proxy_client *client = find_client(conn_handle);
@@ -1056,11 +1071,14 @@ int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
}
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static u8_t prov_svc_data[20] = { 0x27, 0x18, };
+static uint8_t prov_svc_data[20] = {
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL),
+};
static const struct bt_data prov_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x27, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
};
#endif /* PB_GATT */
@@ -1075,23 +1093,27 @@ static const struct bt_data prov_ad[] = {
#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT)
-static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
+static uint8_t proxy_svc_data[NODE_ID_LEN] = {
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
+};
static const struct bt_data node_id_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
};
static const struct bt_data net_id_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
};
static int node_id_adv(struct bt_mesh_subnet *sub)
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
BT_DBG("");
@@ -1107,7 +1129,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub)
memcpy(tmp + 6, proxy_svc_data + 11, 8);
sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
- err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
+ err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp,
+ tmp);
if (err) {
return err;
}
@@ -1135,9 +1158,9 @@ static int net_id_adv(struct bt_mesh_subnet *sub)
proxy_svc_data[2] = ID_TYPE_NET;
BT_DBG("Advertising with NetId %s",
- bt_hex(sub->keys[sub->kr_flag].net_id, 8));
+ bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8));
- memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
+ memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8);
err = bt_le_adv_start(&slow_adv_param, net_id_ad,
ARRAY_SIZE(net_id_ad), NULL, 0);
@@ -1158,60 +1181,75 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub)
}
return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
- bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED);
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
}
static struct bt_mesh_subnet *next_sub(void)
{
- int i;
+ struct bt_mesh_subnet *sub = NULL;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub;
-
- sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
- if (advertise_subnet(sub)) {
- next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
- return sub;
+ if (!beacon_sub) {
+ beacon_sub = bt_mesh_subnet_next(NULL);
+ if (!beacon_sub) {
+ /* No valid subnets */
+ return NULL;
}
}
+ sub = beacon_sub;
+ do {
+ if (advertise_subnet(sub)) {
+ beacon_sub = sub;
+ return sub;
+ }
+
+ sub = bt_mesh_subnet_next(sub);
+ } while (sub != beacon_sub);
+
+ /* No subnets to advertise on */
+
return NULL;
}
-static int sub_count(void)
+static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data)
{
- int i, count = 0;
+ int *count = cb_data;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (advertise_subnet(sub)) {
- count++;
- }
+ if (advertise_subnet(sub)) {
+ (*count)++;
}
+ return 0;
+}
+
+static int sub_count(void)
+{
+ int count = 0;
+
+ (void)bt_mesh_subnet_find(sub_count_cb, &count);
return count;
}
-static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
+static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
{
- s32_t remaining = K_FOREVER;
+ int32_t remaining = K_FOREVER;
int subnet_count;
BT_DBG("");
if (conn_count == CONFIG_BT_MAX_CONN) {
- BT_DBG("Connectable advertising deferred (max connections)");
- return remaining;
+ BT_DBG("Connectable advertising deferred (max connections %d)", conn_count);
+ return -ENOMEM;
}
+ sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub);
if (!sub) {
BT_WARN("No subnets to advertise on");
- return remaining;
+ return -ENOENT;
}
if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
- u32_t active = k_uptime_get_32() - sub->node_id_start;
+ uint32_t active = k_uptime_get_32() - sub->node_id_start;
if (active < NODE_ID_TIMEOUT) {
remaining = NODE_ID_TIMEOUT - active;
@@ -1231,7 +1269,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
subnet_count = sub_count();
BT_DBG("sub_count %u", subnet_count);
if (subnet_count > 1) {
- s32_t max_timeout;
+ int32_t max_timeout;
/* We use NODE_ID_TIMEOUT as a starting point since it may
* be less than 60 seconds. Divide this period into at least
@@ -1249,6 +1287,8 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
BT_DBG("Advertising %d ms for net_idx 0x%04x",
(int) remaining, sub->net_idx);
+ beacon_sub = bt_mesh_subnet_next(beacon_sub);
+
return remaining;
}
#endif /* GATT_PROXY */
@@ -1299,7 +1339,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
}
#endif /* PB_GATT */
-s32_t bt_mesh_proxy_adv_start(void)
+int32_t bt_mesh_proxy_adv_start(void)
{
BT_DBG("");
@@ -1361,6 +1401,19 @@ void bt_mesh_proxy_adv_stop(void)
}
}
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt == BT_MESH_KEY_DELETED) {
+ if (sub == beacon_sub) {
+ beacon_sub = NULL;
+ }
+ } else {
+ bt_mesh_proxy_beacon_send(sub);
+ }
+}
+#endif
+
static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
@@ -1477,6 +1530,12 @@ int bt_mesh_proxy_init(void)
{
int i;
+#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
+ if (!bt_mesh_subnet_cb_list[4]) {
+ bt_mesh_subnet_cb_list[4] = subnet_evt;
+ }
+#endif
+
for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) {
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
k_work_init(&clients[i].send_beacons, proxy_send_beacons);
@@ -1496,4 +1555,14 @@ int bt_mesh_proxy_init(void)
return 0;
}
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb)
+{
+ if (!atomic_get(&pending_notifications)) {
+ cb->cb();
+ return;
+ }
+
+ sys_slist_append(&idle_waiters, &cb->n);
+}
+
#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
index 64338a0a..ebade45a 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
@@ -15,8 +15,14 @@
#define BT_MESH_PROXY_PROV 0x03
#include "mesh/mesh.h"
+#include "mesh/slist.h"
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg);
+struct bt_mesh_proxy_idle_cb {
+ sys_snode_t n;
+ void (*cb)(void);
+};
+
+int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg);
int bt_mesh_proxy_prov_enable(void);
int bt_mesh_proxy_prov_disable(bool disconnect);
@@ -29,16 +35,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
struct os_mbuf *bt_mesh_proxy_get_buf(void);
-s32_t bt_mesh_proxy_adv_start(void);
+int32_t bt_mesh_proxy_adv_start(void);
void bt_mesh_proxy_adv_stop(void);
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst);
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr);
+bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst);
+void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr);
int bt_mesh_proxy_init(void);
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb);
int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
new file mode 100644
index 00000000..93c2e1a8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
@@ -0,0 +1,162 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_RPL_LOG
+
+#include "log/log.h"
+
+#include "mesh_priv.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+
+static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)];
+
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+ struct bt_mesh_net_rx *rx)
+{
+ rpl->src = rx->ctx.addr;
+ rpl->seq = rx->seq;
+ rpl->old_iv = rx->old_iv;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+}
+
+/* Check the Replay Protection List for a replay attempt. If non-NULL match
+ * parameter is given the RPL slot is returned but it is not immediately
+ * updated (needed for segmented messages), whereas if a NULL match is given
+ * the RPL is immediately updated (used for unsegmented messages).
+ */
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+ struct bt_mesh_rpl **match)
+{
+ int i;
+
+ /* Don't bother checking messages from ourselves */
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ return false;
+ }
+
+ /* The RPL is used only for the local node */
+ if (!rx->local_match) {
+ return false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ /* Empty slot */
+ if (!rpl->src) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ }
+
+ /* Existing slot for given address */
+ if (rpl->src == rx->ctx.addr) {
+ if (rx->old_iv && !rpl->old_iv) {
+ return true;
+ }
+
+ if ((!rx->old_iv && rpl->old_iv) ||
+ rpl->seq < rx->seq) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ BT_ERR("RPL is full!");
+ return true;
+}
+
+void bt_mesh_rpl_clear(void)
+{
+ BT_DBG("");
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_rpl();
+ } else {
+ (void)memset(replay_list, 0, sizeof(replay_list));
+ }
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (replay_list[i].src == src) {
+ return &replay_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (!replay_list[i].src) {
+ replay_list[i].src = src;
+ return &replay_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ func(&replay_list[i], user_data);
+ }
+}
+
+void bt_mesh_rpl_reset(void)
+{
+ int i;
+
+ /* Discard "old old" IV Index entries from RPL and flag
+ * any other ones (which are valid) as old.
+ */
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ if (rpl->src) {
+ if (rpl->old_iv) {
+ (void)memset(rpl, 0, sizeof(*rpl));
+ } else {
+ rpl->old_iv = true;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h
new file mode 100644
index 00000000..0592712f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h
@@ -0,0 +1,30 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_mesh_rpl {
+ uint16_t src;
+ bool old_iv;
+#if defined(CONFIG_BT_SETTINGS)
+ bool store;
+#endif
+ uint32_t seq;
+};
+
+typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
+ void *user_data);
+
+void bt_mesh_rpl_reset(void);
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+ struct bt_mesh_rpl **match);
+void bt_mesh_rpl_clear(void);
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src);
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src);
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data);
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+ struct bt_mesh_net_rx *rx);
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
index 88d9b302..537bd785 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
@@ -9,16 +9,23 @@
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
+#include "mesh_priv.h"
#include "mesh/mesh.h"
#include "mesh/glue.h"
+#include "subnet.h"
+#include "app_keys.h"
#include "net.h"
+#include "rpl.h"
#include "crypto.h"
#include "transport.h"
+#include "heartbeat.h"
#include "access.h"
#include "foundation.h"
#include "proxy.h"
#include "settings.h"
-#include "nodes.h"
+#include "lpn.h"
+#include "cfg.h"
+
#include "config/config.h"
@@ -27,116 +34,155 @@
* bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
* gets deleted its struct becomes invalid and may be reused for other keys.
*/
-static struct key_update {
- u16_t key_idx:12, /* AppKey or NetKey Index */
+struct key_update {
+ uint16_t key_idx:12, /* AppKey or NetKey Index */
valid:1, /* 1 if this entry is valid, 0 if not */
app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */
clear:1; /* 1 if key needs clearing, 0 if storing */
-} key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT];
+};
+
+static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT +
+ CONFIG_BT_MESH_SUBNET_COUNT];
static struct k_delayed_work pending_store;
/* Mesh network storage information */
struct net_val {
- u16_t primary_addr;
- u8_t dev_key[16];
+ uint16_t primary_addr;
+ uint8_t dev_key[16];
} __packed;
/* Sequence number storage */
struct seq_val {
- u8_t val[3];
+ uint8_t val[3];
} __packed;
/* Heartbeat Publication storage */
struct hb_pub_val {
- u16_t dst;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx:12,
+ uint16_t dst;
+ uint8_t period;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx:12,
indefinite:1;
};
/* Miscelaneous configuration server model states */
struct cfg_val {
- u8_t net_transmit;
- u8_t relay;
- u8_t relay_retransmit;
- u8_t beacon;
- u8_t gatt_proxy;
- u8_t frnd;
- u8_t default_ttl;
+ uint8_t net_transmit;
+ uint8_t relay;
+ uint8_t relay_retransmit;
+ uint8_t beacon;
+ uint8_t gatt_proxy;
+ uint8_t frnd;
+ uint8_t default_ttl;
};
/* IV Index & IV Update storage */
struct iv_val {
- u32_t iv_index;
- u8_t iv_update:1,
+ uint32_t iv_index;
+ uint8_t iv_update:1,
iv_duration:7;
} __packed;
/* Replay Protection List storage */
struct rpl_val {
- u32_t seq:24,
+ uint32_t seq:24,
old_iv:1;
};
/* NetKey storage information */
struct net_key_val {
- u8_t kr_flag:1,
+ uint8_t kr_flag:1,
kr_phase:7;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
/* AppKey storage information */
struct app_key_val {
- u16_t net_idx;
+ uint16_t net_idx;
bool updated;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
struct mod_pub_val {
- u16_t addr;
- u16_t key;
- u8_t ttl;
- u8_t retransmit;
- u8_t period;
- u8_t period_div:4,
+ uint16_t addr;
+ uint16_t key;
+ uint8_t ttl;
+ uint8_t retransmit;
+ uint8_t period;
+ uint8_t period_div:4,
cred:1;
};
/* Virtual Address information */
struct va_val {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
+ uint16_t ref;
+ uint16_t addr;
+ uint8_t uuid[16];
+} __packed;
+
+struct cdb_net_val {
+ uint32_t iv_index;
+ bool iv_update;
} __packed;
/* Node storage information */
struct node_val {
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
+ uint16_t net_idx;
+ uint8_t num_elem;
+ uint8_t flags;
+#define F_NODE_CONFIGURED 0x01
+ uint8_t uuid[16];
+ uint8_t dev_key[16];
} __packed;
struct node_update {
- u16_t addr;
+ uint16_t addr;
bool clear;
};
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT];
+#if MYNEWT_VAL(BLE_MESH_CDB)
+static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)];
+static struct key_update cdb_key_updates[
+ MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) +
+ MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)];
#else
-static struct node_update node_updates[0];
+static struct node_update cdb_node_updates[0];
+static struct key_update cdb_key_updates[0];
#endif
-/* We need this so we don't overwrite app-hardcoded values in case FCB
- * contains a history of changes but then has a NULL at the end.
- */
-static struct {
- bool valid;
- struct cfg_val cfg;
-} stored_cfg;
+int settings_name_next(char *name, char **next)
+{
+ int rc = 0;
+
+ if (next) {
+ *next = NULL;
+ }
+
+ if (!name) {
+ return 0;
+ }
+
+ /* name might come from flash directly, in flash the name would end
+ * with '=' or '\0' depending how storage is done. Flash reading is
+ * limited to what can be read
+ */
+ while ((*name != '\0') && (*name != '=') &&
+ (*name != '/')) {
+ rc++;
+ name++;
+ }
+
+ if (*name == '/') {
+ if (next) {
+ *next = name + 1;
+ }
+ return rc;
+ }
+
+ return rc;
+}
static int net_set(int argc, char **argv, char *val)
{
@@ -231,8 +277,7 @@ static int seq_set(int argc, char **argv, char *val)
return -EINVAL;
}
- bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) |
- ((u32_t)seq.val[2] << 16));
+ bt_mesh.seq = sys_get_le24(seq.val);
if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) {
/* Make sure we have a large enough sequence number. We
@@ -249,39 +294,12 @@ static int seq_set(int argc, char **argv, char *val)
return 0;
}
-static struct bt_mesh_rpl *rpl_find(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (bt_mesh.rpl[i].src == src) {
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
-static struct bt_mesh_rpl *rpl_alloc(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (!bt_mesh.rpl[i].src) {
- bt_mesh.rpl[i].src = src;
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
static int rpl_set(int argc, char **argv, char *val)
{
struct bt_mesh_rpl *entry;
struct rpl_val rpl;
int len, err;
- u16_t src;
+ uint16_t src;
if (argc < 1) {
BT_ERR("Invalid argc (%d)", argc);
@@ -291,7 +309,7 @@ static int rpl_set(int argc, char **argv, char *val)
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
src = strtol(argv[0], NULL, 16);
- entry = rpl_find(src);
+ entry = bt_mesh_rpl_find(src);
if (!val) {
if (entry) {
@@ -304,7 +322,7 @@ static int rpl_set(int argc, char **argv, char *val)
}
if (!entry) {
- entry = rpl_alloc(src);
+ entry = bt_mesh_rpl_alloc(src);
if (!entry) {
BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
return -ENOMEM;
@@ -334,26 +352,13 @@ static int rpl_set(int argc, char **argv, char *val)
static int net_key_set(int argc, char **argv, char *val)
{
- struct bt_mesh_subnet *sub;
struct net_key_val key;
- int len, i, err;
- u16_t net_idx;
+ int len, err;
+ uint16_t net_idx;
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
net_idx = strtol(argv[0], NULL, 16);
- sub = bt_mesh_subnet_get(net_idx);
-
- if (!val) {
- if (!sub) {
- BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
- return -ENOENT;
- }
-
- BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
- bt_mesh_subnet_del(sub, false);
- return 0;
- }
len = sizeof(key);
err = settings_bytes_from_str(val, &key, &len);
@@ -367,93 +372,41 @@ static int net_key_set(int argc, char **argv, char *val)
return -EINVAL;
}
- if (sub) {
- BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
-
- sub->kr_flag = key.kr_flag;
- sub->kr_phase = key.kr_phase;
- memcpy(sub->keys[0].net, &key.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- BT_ERR("No space to allocate a new subnet");
- return -ENOMEM;
- }
-
- sub->net_idx = net_idx;
- sub->kr_flag = key.kr_flag;
- sub->kr_phase = key.kr_phase;
- memcpy(sub->keys[0].net, &key.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
- return 0;
+ return bt_mesh_subnet_set(
+ net_idx, key.kr_phase, key.val[0],
+ (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL);
}
static int app_key_set(int argc, char **argv, char *val)
{
- struct bt_mesh_app_key *app;
struct app_key_val key;
- u16_t app_idx;
- int len, err;
+ uint16_t app_idx;
+ int len_rd, err;
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
app_idx = strtol(argv[0], NULL, 16);
+ len_rd = strtol(argv[1], NULL, 16);
- if (!val) {
- BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
-
- app = bt_mesh_app_key_find(app_idx);
- if (app) {
- bt_mesh_app_key_del(app, false);
- }
-
+ if (!len_rd) {
return 0;
}
- len = sizeof(key);
- err = settings_bytes_from_str(val, &key, &len);
+ err = settings_bytes_from_str(val, &key, &len_rd);
if (err) {
BT_ERR("Failed to decode value %s (err %d)", val, err);
return err;
}
- if (len != sizeof(key)) {
- BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key));
- return -EINVAL;
+ err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0],
+ key.updated ? key.val[1] : NULL);
+ if (err) {
+ BT_ERR("Failed to set \'app-key\'");
+ return err;
}
- app = bt_mesh_app_key_find(app_idx);
- if (!app) {
- app = bt_mesh_app_key_alloc(app_idx);
- }
-
- if (!app) {
- BT_ERR("No space for a new app key");
- return -ENOMEM;
- }
-
- app->net_idx = key.net_idx;
- app->app_idx = app_idx;
- app->updated = key.updated;
- memcpy(app->keys[0].val, key.val[0], 16);
- memcpy(app->keys[1].val, key.val[1], 16);
-
- bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
- bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
-
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
return 0;
@@ -461,27 +414,12 @@ static int app_key_set(int argc, char **argv, char *val)
static int hb_pub_set(int argc, char **argv, char *val)
{
- struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val hb_val;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!pub) {
- return -ENOENT;
- }
-
- if (!val) {
- pub->dst = BT_MESH_ADDR_UNASSIGNED;
- pub->count = 0;
- pub->ttl = 0;
- pub->period = 0;
- pub->feat = 0;
-
- BT_DBG("Cleared heartbeat publication");
- return 0;
- }
-
len = sizeof(hb_val);
err = settings_bytes_from_str(val, &hb_val, &len);
if (err) {
@@ -495,18 +433,20 @@ static int hb_pub_set(int argc, char **argv, char *val)
return -EINVAL;
}
- pub->dst = hb_val.dst;
- pub->period = hb_val.period;
- pub->ttl = hb_val.ttl;
- pub->feat = hb_val.feat;
- pub->net_idx = hb_val.net_idx;
+ pub.dst = hb_val.dst;
+ pub.period = bt_mesh_hb_pwr2(hb_val.period);
+ pub.ttl = hb_val.ttl;
+ pub.feat = hb_val.feat;
+ pub.net_idx = hb_val.net_idx;
if (hb_val.indefinite) {
- pub->count = 0xffff;
+ pub.count = 0xffff;
} else {
- pub->count = 0;
+ pub.count = 0;
}
+ (void)bt_mesh_hb_pub_set(&pub);
+
BT_DBG("Restored heartbeat publication");
return 0;
@@ -514,35 +454,36 @@ static int hb_pub_set(int argc, char **argv, char *val)
static int cfg_set(int argc, char **argv, char *val)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+ struct cfg_val cfg;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!cfg) {
- return -ENOENT;
- }
-
if (!val) {
- stored_cfg.valid = false;
BT_DBG("Cleared configuration state");
return 0;
}
- len = sizeof(stored_cfg.cfg);
- err = settings_bytes_from_str(val, &stored_cfg.cfg, &len);
+ len = sizeof(cfg);
+ err = settings_bytes_from_str(val, &cfg, &len);
if (err) {
BT_ERR("Failed to decode value %s (err %d)", val, err);
return err;
}
- if (len != sizeof(stored_cfg.cfg)) {
+ if (len != sizeof(cfg)) {
BT_ERR("Unexpected value length (%d != %zu)", len,
- sizeof(stored_cfg.cfg));
+ sizeof(cfg));
return -EINVAL;
}
- stored_cfg.valid = true;
+ bt_mesh_net_transmit_set(cfg.net_transmit);
+ bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit);
+ bt_mesh_beacon_set(cfg.beacon);
+ bt_mesh_gatt_proxy_set(cfg.gatt_proxy);
+ bt_mesh_friend_set(cfg.frnd);
+ bt_mesh_default_ttl_set(cfg.default_ttl);
+
BT_DBG("Restored configuration state");
return 0;
@@ -646,11 +587,25 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val)
return 0;
}
+static int mod_data_set(struct bt_mesh_model *mod,
+ char *name, char *len_rd)
+{
+ char *next;
+
+ settings_name_next(name, &next);
+
+ if (mod->cb && mod->cb->settings_set) {
+ return mod->cb->settings_set(mod, next, len_rd);
+ }
+
+ return 0;
+}
+
static int mod_set(bool vnd, int argc, char **argv, char *val)
{
struct bt_mesh_model *mod;
- u8_t elem_idx, mod_idx;
- u16_t mod_key;
+ uint8_t elem_idx, mod_idx;
+ uint16_t mod_key;
if (argc < 2) {
BT_ERR("Too small argc (%d)", argc);
@@ -684,11 +639,7 @@ static int mod_set(bool vnd, int argc, char **argv, char *val)
}
if (!strcmp(argv[1], "data")) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
-
- if (mod->cb && mod->cb->settings_set) {
- return mod->cb->settings_set(mod, val);
- }
+ return mod_data_set(mod, argv[1], val);
}
BT_WARN("Unknown module key %s", argv[1]);
@@ -709,8 +660,8 @@ static int vnd_mod_set(int argc, char **argv, char *val)
static int va_set(int argc, char **argv, char *val)
{
struct va_val va;
- struct label *lab;
- u16_t index;
+ struct bt_mesh_va *lab;
+ uint16_t index;
int len, err;
if (argc < 1) {
@@ -741,7 +692,7 @@ static int va_set(int argc, char **argv, char *val)
return 0;
}
- lab = get_label(index);
+ lab = bt_mesh_va_get(index);
if (lab == NULL) {
BT_WARN("Out of labels buffers");
return -ENOBUFS;
@@ -758,12 +709,35 @@ static int va_set(int argc, char **argv, char *val)
}
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static int node_set(int argc, char **argv, char *str)
+#if MYNEWT_VAL(BLE_MESH_CDB)
+static int cdb_net_set(int argc, char *val)
{
- struct bt_mesh_node *node;
+ struct cdb_net_val net;
+ int len, err;
+
+ len = sizeof(net);
+ err = settings_bytes_from_str(val, &net, &len);
+ if (err) {
+ BT_ERR("Failed to set \'cdb_net\'");
+ return err;
+ }
+
+ bt_mesh_cdb.iv_index = net.iv_index;
+
+ if (net.iv_update) {
+ atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
+ }
+
+ atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+ return 0;
+}
+
+static int cdb_node_set(int argc, char *str)
+{
+ struct bt_mesh_cdb_node *node;
struct node_val val;
- u16_t addr;
+ uint16_t addr;
int len, err;
if (argc < 1) {
@@ -771,15 +745,16 @@ static int node_set(int argc, char **argv, char *str)
return -ENOENT;
}
- addr = strtol(argv[0], NULL, 16);
+ addr = strtol(str, NULL, 16);
+ len = sizeof(str);
- if (str == NULL) {
+ if (argc < 1) {
BT_DBG("val (null)");
BT_DBG("Deleting node 0x%04x", addr);
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (node) {
- bt_mesh_node_del(node, false);
+ bt_mesh_cdb_node_del(node, false);
}
return 0;
@@ -796,9 +771,10 @@ static int node_set(int argc, char **argv, char *str)
return -EINVAL;
}
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (!node) {
- node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx);
+ node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
+ val.net_idx);
}
if (!node) {
@@ -806,12 +782,163 @@ static int node_set(int argc, char **argv, char *str)
return -ENOMEM;
}
- memcpy(node->dev_key, &val.dev_key, 16);
+ if (val.flags & F_NODE_CONFIGURED) {
+ atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
+ }
+
+ memcpy(node->uuid, val.uuid, 16);
+ memcpy(node->dev_key, val.dev_key, 16);
BT_DBG("Node 0x%04x recovered from storage", addr);
return 0;
}
+
+static int cdb_subnet_set(int argc, char *name)
+{
+ struct bt_mesh_cdb_subnet *sub;
+ struct net_key_val key;
+ uint16_t net_idx;
+ int len, len_rd, err;
+
+ if (!name) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ len_rd = sizeof(sub);
+ net_idx = strtol(name, NULL, 16);
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+
+ if (len_rd == 0) {
+ BT_DBG("val (null)");
+ if (!sub) {
+ BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
+ return -ENOENT;
+ }
+
+ BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
+ bt_mesh_cdb_subnet_del(sub, false);
+ return 0;
+ }
+
+ len = sizeof(key);
+ err = settings_bytes_from_str(name, &key, &len);
+ if (err) {
+ BT_ERR("Failed to set \'net-key\'");
+ return err;
+ }
+
+ if (sub) {
+ BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
+
+ sub->kr_flag = key.kr_flag;
+ sub->kr_phase = key.kr_phase;
+ memcpy(sub->keys[0].net_key, &key.val[0], 16);
+ memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+ return 0;
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(net_idx);
+ if (!sub) {
+ BT_ERR("No space to allocate a new subnet");
+ return -ENOMEM;
+ }
+
+ sub->kr_flag = key.kr_flag;
+ sub->kr_phase = key.kr_phase;
+ memcpy(sub->keys[0].net_key, &key.val[0], 16);
+ memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+ BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
+
+ return 0;
+}
+
+static int cdb_app_key_set(int argc, char *name)
+{
+ struct bt_mesh_cdb_app_key *app;
+ struct app_key_val key;
+ uint16_t app_idx;
+ int len_rd, err;
+
+ app_idx = strtol(name, NULL, 16);
+ len_rd = sizeof(key);
+
+ if (len_rd == 0) {
+ BT_DBG("val (null)");
+ BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
+
+ app = bt_mesh_cdb_app_key_get(app_idx);
+ if (app) {
+ bt_mesh_cdb_app_key_del(app, false);
+ }
+
+ return 0;
+ }
+
+ err = settings_bytes_from_str(name, &key, &len_rd);
+ if (err) {
+ BT_ERR("Failed to set \'app-key\'");
+ return err;
+ }
+
+ app = bt_mesh_cdb_app_key_get(app_idx);
+ if (!app) {
+ app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
+ }
+
+ if (!app) {
+ BT_ERR("No space for a new app key");
+ return -ENOMEM;
+ }
+
+ memcpy(app->keys[0].app_key, key.val[0], 16);
+ memcpy(app->keys[1].app_key, key.val[1], 16);
+
+ BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
+
+ return 0;
+}
+
+static int cdb_set(int argc, char **argv, char *name)
+{
+ int len;
+ char *next;
+
+ if (argc < 1) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ if (!strcmp(name, "Net")) {
+ return cdb_net_set(1, name);
+ }
+
+
+ len = settings_name_next(name, &next);
+
+ if (!next) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ if (!strncmp(name, "Node", len)) {
+ return cdb_node_set(1, next);
+ }
+
+ if (!strncmp(name, "Subnet", len)) {
+ return cdb_subnet_set(1, next);
+ }
+
+ if (!strncmp(name, "AppKey", len)) {
+ return cdb_app_key_set(1, next);
+ }
+
+ BT_WARN("Unknown module key %s", name);
+ return -ENOENT;
+}
#endif
const struct mesh_setting {
@@ -831,8 +958,8 @@ const struct mesh_setting {
#if CONFIG_BT_MESH_LABEL_COUNT > 0
{ "Va", va_set },
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- { "Node", node_set },
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ { "cdb", cdb_set },
#endif
};
@@ -861,43 +988,12 @@ static int mesh_set(int argc, char **argv, char *val)
return -ENOENT;
}
-static int subnet_init(struct bt_mesh_subnet *sub)
-{
- int err;
-
- err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- return -EIO;
- }
-
- if (sub->kr_phase != BT_MESH_KR_NORMAL) {
- err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- memset(&sub->keys[0], 0, sizeof(sub->keys[0]));
- return -EIO;
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- return 0;
-}
-
static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
if (mod->pub && mod->pub->update &&
mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
- s32_t ms = bt_mesh_model_pub_period_get(mod);
+ int32_t ms = bt_mesh_model_pub_period_get(mod);
if (ms) {
BT_DBG("Starting publish timer (period %u ms)",
(unsigned) ms);
@@ -905,20 +1001,20 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
}
- if (mod->cb && mod->cb->settings_commit) {
- mod->cb->settings_commit(mod);
+ if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+ return;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) {
+ if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_lpn_group_add(mod->groups[i]);
+ }
}
}
static int mesh_commit(void)
{
- struct bt_mesh_hb_pub *hb_pub;
- struct bt_mesh_cfg_srv *cfg;
- int i;
-
- BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
-
- if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) {
+ if (!bt_mesh_subnet_next(NULL)) {
/* Nothing to do since we're not yet provisioned */
return 0;
}
@@ -927,47 +1023,15 @@ static int mesh_commit(void)
bt_mesh_proxy_prov_disable(true);
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- int err;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- err = subnet_init(sub);
- if (err) {
- BT_ERR("Failed to init subnet 0x%03x", sub->net_idx);
- }
- }
-
if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
}
bt_mesh_model_foreach(commit_mod, NULL);
- hb_pub = bt_mesh_hb_pub_get();
- if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
- hb_pub->count && hb_pub->period) {
- BT_DBG("Starting heartbeat publication");
- k_work_submit(&hb_pub->timer.work);
- }
-
- cfg = bt_mesh_cfg_get();
- if (cfg && stored_cfg.valid) {
- cfg->net_transmit = stored_cfg.cfg.net_transmit;
- cfg->relay = stored_cfg.cfg.relay;
- cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
- cfg->beacon = stored_cfg.cfg.beacon;
- cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
- cfg->frnd = stored_cfg.cfg.frnd;
- cfg->default_ttl = stored_cfg.cfg.default_ttl;
- }
-
atomic_set_bit(bt_mesh.flags, BT_MESH_VALID);
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
@@ -981,12 +1045,11 @@ static int mesh_commit(void)
#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \
BIT(BT_MESH_HB_PUB_PENDING) | \
BIT(BT_MESH_CFG_PENDING) | \
- BIT(BT_MESH_MOD_PENDING) | \
- BIT(BT_MESH_NODES_PENDING))
+ BIT(BT_MESH_MOD_PENDING))
static void schedule_store(int flag)
{
- s32_t timeout, remaining;
+ int32_t timeout, remaining;
atomic_set_bit(bt_mesh.flags, flag);
@@ -1112,9 +1175,7 @@ static void store_pending_seq(void)
char *str;
int err;
- seq.val[0] = bt_mesh.seq;
- seq.val[1] = bt_mesh.seq >> 8;
- seq.val[2] = bt_mesh.seq >> 16;
+ sys_put_le24(bt_mesh.seq, seq.val);
str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf));
if (!str) {
@@ -1172,69 +1233,54 @@ static void store_rpl(struct bt_mesh_rpl *entry)
}
}
-static void clear_rpl(void)
+static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i, err;
+ int err;
+ char path[18];
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
- char path[18];
-
- if (!rpl->src) {
- continue;
- }
-
- snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src);
- err = settings_save_one(path, NULL);
- if (err) {
- BT_ERR("Failed to clear RPL");
- } else {
- BT_DBG("Cleared RPL");
- }
-
- memset(rpl, 0, sizeof(*rpl));
+ if (!rpl->src) {
+ return;
}
+
+ snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear RPL");
+ } else {
+ BT_DBG("Cleared RPL");
+ }
+
+ (void)memset(rpl, 0, sizeof(*rpl));
}
-static void store_pending_rpl(void)
+static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i;
-
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->store) {
- rpl->store = false;
- store_rpl(rpl);
- }
+ if (rpl->store) {
+ rpl->store = false;
+ store_rpl(rpl);
}
}
static void store_pending_hb_pub(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))];
- struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val val;
char *str;
int err;
- if (!pub) {
- return;
- }
-
- if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_hb_pub_get(&pub);
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
str = NULL;
} else {
- val.indefinite = (pub->count == 0xffff);
- val.dst = pub->dst;
- val.period = pub->period;
- val.ttl = pub->ttl;
- val.feat = pub->feat;
- val.net_idx = pub->net_idx;
+ val.indefinite = (pub.count == 0xffff);
+ val.dst = pub.dst;
+ val.period = bt_mesh_hb_log(pub.period);
+ val.ttl = pub.ttl;
+ val.feat = pub.feat;
+ val.net_idx = pub.net_idx;
str = settings_str_from_bytes(&val, sizeof(val),
buf, sizeof(buf));
@@ -1257,22 +1303,17 @@ static void store_pending_hb_pub(void)
static void store_pending_cfg(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))];
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct cfg_val val;
char *str;
int err;
- if (!cfg) {
- return;
- }
-
- val.net_transmit = cfg->net_transmit;
- val.relay = cfg->relay;
- val.relay_retransmit = cfg->relay_retransmit;
- val.beacon = cfg->beacon;
- val.gatt_proxy = cfg->gatt_proxy;
- val.frnd = cfg->frnd;
- val.default_ttl = cfg->default_ttl;
+ val.net_transmit = bt_mesh_net_transmit_get();
+ val.relay = bt_mesh_relay_get();
+ val.relay_retransmit = bt_mesh_relay_retransmit_get();
+ val.beacon = bt_mesh_beacon_enabled();
+ val.gatt_proxy = bt_mesh_gatt_proxy_get();
+ val.frnd = bt_mesh_friend_get();
+ val.default_ttl = bt_mesh_default_ttl_get();
str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
if (!str) {
@@ -1301,7 +1342,7 @@ static void clear_cfg(void)
}
}
-static void clear_app_key(u16_t app_idx)
+static void clear_app_key(uint16_t app_idx)
{
char path[20];
int err;
@@ -1317,7 +1358,7 @@ static void clear_app_key(u16_t app_idx)
}
}
-static void clear_net_key(u16_t net_idx)
+static void clear_net_key(uint16_t net_idx)
{
char path[20];
int err;
@@ -1333,31 +1374,36 @@ static void clear_net_key(u16_t net_idx)
}
}
-static void store_net_key(struct bt_mesh_subnet *sub)
+static void store_subnet(uint16_t net_idx)
{
- char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
+ const struct bt_mesh_subnet *sub;
struct net_key_val key;
+ char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
char path[20];
char *str;
int err;
- BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
- bt_hex(sub->keys[0].net, 16));
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ BT_WARN("NetKeyIndex 0x%03x not found", net_idx);
+ return;
+ }
+
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+ snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", net_idx);
memcpy(&key.val[0], sub->keys[0].net, 16);
memcpy(&key.val[1], sub->keys[1].net, 16);
- key.kr_flag = sub->kr_flag;
+ key.kr_flag = 0U; /* Deprecated */
key.kr_phase = sub->kr_phase;
str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
if (!str) {
- BT_ERR("Unable to encode NetKey as value");
+ BT_ERR("Unable to encode AppKey as value");
return;
}
- snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx);
-
- BT_DBG("Saving NetKey %s as value %s", path, str);
err = settings_save_one(path, str);
if (err) {
BT_ERR("Failed to store NetKey");
@@ -1366,16 +1412,26 @@ static void store_net_key(struct bt_mesh_subnet *sub)
}
}
-static void store_app_key(struct bt_mesh_app_key *app)
+static void store_app(uint16_t app_idx)
{
+ const struct bt_mesh_app_key *app;
char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
struct app_key_val key;
char path[20];
char *str;
int err;
- key.net_idx = app->net_idx;
- key.updated = app->updated;
+ snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
+
+ app = bt_mesh_app_key_get(app_idx);
+ if (!app) {
+ BT_WARN("ApKeyIndex 0x%03x not found", app_idx);
+ return;
+ }
+
+ key.net_idx = app->net_idx,
+ key.updated = app->updated,
+
memcpy(key.val[0], app->keys[0].val, 16);
memcpy(key.val[1], app->keys[1].val, 16);
@@ -1414,47 +1470,71 @@ static void store_pending_keys(void)
clear_net_key(update->key_idx);
}
} else {
- if (update->app_key) {
- struct bt_mesh_app_key *key;
-
- key = bt_mesh_app_key_find(update->key_idx);
- if (key) {
- store_app_key(key);
- } else {
- BT_WARN("AppKeyIndex 0x%03x not found",
- update->key_idx);
- }
-
- } else {
- struct bt_mesh_subnet *sub;
-
- sub = bt_mesh_subnet_get(update->key_idx);
- if (sub) {
- store_net_key(sub);
- } else {
- BT_WARN("NetKeyIndex 0x%03x not found",
- update->key_idx);
- }
- }
+ store_subnet(update->key_idx);
}
update->valid = 0;
}
}
-static void store_node(struct bt_mesh_node *node)
+static void clear_cdb(void)
+{
+ int err;
+
+ err = settings_save_one("bt/mesh/cdb/Net", NULL);
+ if (err) {
+ BT_ERR("Failed to clear Network");
+ } else {
+ BT_DBG("Cleared Network");
+ }
+}
+
+static void store_pending_cdb(void)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct cdb_net_val))];
+ struct cdb_net_val net;
+ int err;
+ char *str;
+
+ BT_DBG("");
+
+ net.iv_index = bt_mesh_cdb.iv_index;
+ net.iv_update = atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_IVU_IN_PROGRESS);
+
+ str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf));
+ if (!str) {
+ BT_ERR("Unable to encode Network as value");
+ return;
+ }
+ err = settings_save_one("bt/mesh/cdb/Net", str);
+ if (err) {
+ BT_ERR("Failed to store Network value");
+ } else {
+ BT_DBG("Stored Network value");
+ }
+}
+
+static void store_cdb_node(const struct bt_mesh_cdb_node *node)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))];
struct node_val val;
- char path[20];
+ char path[30];
char *str;
int err;
val.net_idx = node->net_idx;
val.num_elem = node->num_elem;
+ val.flags = 0;
+
+ if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
+ val.flags |= F_NODE_CONFIGURED;
+ }
+
+ memcpy(val.uuid, node->uuid, 16);
memcpy(val.dev_key, node->dev_key, 16);
- snprintk(path, sizeof(path), "bt_mesh/Node/%x", node->addr);
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
if (!str) {
@@ -1471,14 +1551,14 @@ static void store_node(struct bt_mesh_node *node)
}
}
-static void clear_node(u16_t addr)
+static void clear_cdb_node(uint16_t addr)
{
- char path[20];
+ char path[30];
int err;
BT_DBG("Node 0x%04x", addr);
- snprintk(path, sizeof(path), "bt_mesh/Node/%x", addr);
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
err = settings_save_one(path, NULL);
if (err) {
BT_ERR("Failed to clear Node 0x%04x", addr);
@@ -1487,25 +1567,27 @@ static void clear_node(u16_t addr)
}
}
-static void store_pending_nodes(void)
+static void store_pending_cdb_nodes(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(node_updates); ++i) {
- struct node_update *update = &node_updates[i];
+ for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
+ struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
- if (update->clear) {
- clear_node(update->addr);
- } else {
- struct bt_mesh_node *node;
+ BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
- node = bt_mesh_node_find(update->addr);
+ if (update->clear) {
+ clear_cdb_node(update->addr);
+ } else {
+ struct bt_mesh_cdb_node *node;
+
+ node = bt_mesh_cdb_node_get(update->addr);
if (node) {
- store_node(node);
+ store_cdb_node(node);
} else {
BT_WARN("Node 0x%04x not found", update->addr);
}
@@ -1515,8 +1597,139 @@ static void store_pending_nodes(void)
}
}
-static struct node_update *node_update_find(u16_t addr,
- struct node_update **free_slot)
+static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
+ struct net_key_val key;
+ char path[30];
+ int err;
+ char *str;
+
+ BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
+ bt_hex(sub->keys[0].net_key, 16));
+
+ memcpy(&key.val[0], sub->keys[0].net_key, 16);
+ memcpy(&key.val[1], sub->keys[1].net_key, 16);
+ key.kr_flag = sub->kr_flag;
+ key.kr_phase = sub->kr_phase;
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
+
+
+ str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
+ if (!str) {
+ BT_ERR("Unable to encode Subnet as value");
+ return;
+ }
+ err = settings_save_one(path, str);
+ if (err) {
+ BT_ERR("Failed to store Subnet value");
+ } else {
+ BT_DBG("Stored Subnet value");
+ }
+}
+
+static void clear_cdb_subnet(uint16_t net_idx)
+{
+ char path[30];
+ int err;
+
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
+ } else {
+ BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
+ }
+}
+
+static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
+ struct app_key_val key;
+ char path[30];
+ int err;
+ char *str;
+
+ key.net_idx = app->net_idx;
+ key.updated = false;
+ memcpy(key.val[0], app->keys[0].app_key, 16);
+ memcpy(key.val[1], app->keys[1].app_key, 16);
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
+
+ str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
+ err = settings_save_one(path, str);
+ if (err) {
+ BT_ERR("Failed to store AppKey");
+ } else {
+ BT_DBG("Stored AppKey");
+ }
+}
+
+static void clear_cdb_app_key(uint16_t app_idx)
+{
+ char path[30];
+ int err;
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
+ } else {
+ BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
+ }
+}
+
+static void store_pending_cdb_keys(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+ struct key_update *update = &cdb_key_updates[i];
+
+ if (!update->valid) {
+ continue;
+ }
+
+ if (update->clear) {
+ if (update->app_key) {
+ clear_cdb_app_key(update->key_idx);
+ } else {
+ clear_cdb_subnet(update->key_idx);
+ }
+ } else {
+ if (update->app_key) {
+ struct bt_mesh_cdb_app_key *key;
+
+ key = bt_mesh_cdb_app_key_get(update->key_idx);
+ if (key) {
+ store_cdb_app_key(key);
+ } else {
+ BT_WARN("AppKeyIndex 0x%03x not found",
+ update->key_idx);
+ }
+ } else {
+ struct bt_mesh_cdb_subnet *sub;
+
+ sub = bt_mesh_cdb_subnet_get(update->key_idx);
+ if (sub) {
+ store_cdb_subnet(sub);
+ } else {
+ BT_WARN("NetKeyIndex 0x%03x not found",
+ update->key_idx);
+ }
+ }
+ }
+
+ update->valid = 0U;
+ }
+}
+
+static struct node_update *cdb_node_update_find(uint16_t addr,
+ struct node_update **free_slot)
{
struct node_update *match;
int i;
@@ -1524,8 +1737,8 @@ static struct node_update *node_update_find(u16_t addr,
match = NULL;
*free_slot = NULL;
- for (i = 0; i < ARRAY_SIZE(node_updates); i++) {
- struct node_update *update = &node_updates[i];
+ for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
+ struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
*free_slot = update;
@@ -1543,7 +1756,7 @@ static struct node_update *node_update_find(u16_t addr,
static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
const char *key, char *path, size_t path_len)
{
- u16_t mod_key = (((u16_t)mod->elem_idx << 8) | mod->mod_idx);
+ uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx);
if (vnd) {
snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key);
@@ -1554,7 +1767,7 @@ static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
{
- u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+ uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(keys))];
char path[20];
int i, count, err;
@@ -1590,7 +1803,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
{
- u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+ uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(groups))];
char path[20];
int i, count, err;
@@ -1690,19 +1903,20 @@ static void store_pending_mod(struct bt_mesh_model *mod,
static void store_pending_va(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))];
- struct label *lab;
+ struct bt_mesh_va *lab;
struct va_val va;
char path[18];
char *val;
- u16_t i;
+ uint16_t i;
int err = 0;
- for (i = 0; (lab = get_label(i)) != NULL; i++) {
- if (!atomic_test_and_clear_bit(lab->flags,
- BT_MESH_VA_CHANGED)) {
+ for (i = 0; (lab = bt_mesh_va_get(i)) != NULL; i++) {
+ if (!lab->changed) {
continue;
}
+ lab->changed = 0U;
+
snprintk(path, sizeof(path), "bt_mesh/Va/%x", i);
if (IS_VA_DEL(lab)) {
@@ -1738,9 +1952,9 @@ static void store_pending(struct ble_npl_event *work)
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
- store_pending_rpl();
+ bt_mesh_rpl_foreach(store_pending_rpl, NULL);
} else {
- clear_rpl();
+ bt_mesh_rpl_foreach(clear_rpl, NULL);
}
}
@@ -1788,9 +2002,26 @@ static void store_pending(struct ble_npl_event *work)
store_pending_va();
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) {
- store_pending_nodes();
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_SUBNET_PENDING)) {
+ if (atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ store_pending_cdb();
+ } else {
+ clear_cdb();
+ }
+ }
+
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_NODES_PENDING)) {
+ store_pending_cdb_nodes();
+ }
+
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_KEYS_PENDING)) {
+ store_pending_cdb_keys();
+ }
}
}
@@ -1800,7 +2031,7 @@ void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
schedule_store(BT_MESH_RPL_PENDING);
}
-static struct key_update *key_update_find(bool app_key, u16_t key_idx,
+static struct key_update *key_update_find(bool app_key, uint16_t key_idx,
struct key_update **free_slot)
{
struct key_update *match;
@@ -1829,13 +2060,13 @@ static struct key_update *key_update_find(bool app_key, u16_t key_idx,
return match;
}
-void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_store_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1843,25 +2074,25 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- store_net_key(sub);
+ store_subnet(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ free_slot->key_idx = net_idx;
free_slot->app_key = 0;
free_slot->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
}
-void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
+void bt_mesh_store_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1869,12 +2100,12 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- store_app_key(key);
+ store_app(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 0;
@@ -1898,13 +2129,13 @@ void bt_mesh_clear_net(void)
schedule_store(BT_MESH_CFG_PENDING);
}
-void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_clear_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1912,25 +2143,25 @@ void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- clear_net_key(sub->net_idx);
+ clear_net_key(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ free_slot->key_idx = net_idx;
free_slot->app_key = 0;
free_slot->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
}
-void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
+void bt_mesh_clear_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1938,12 +2169,12 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- clear_app_key(key->app_idx);
+ clear_app_key(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 1;
@@ -1979,64 +2210,215 @@ void bt_mesh_store_label(void)
schedule_store(BT_MESH_VA_PENDING);
}
-void bt_mesh_store_node(struct bt_mesh_node *node)
+static void schedule_cdb_store(int flag)
{
- struct node_update *update, *free_slot;
-
- BT_DBG("Node 0x%04x", node->addr);
-
- update = node_update_find(node->addr, &free_slot);
- if (update) {
- update->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
- return;
- }
-
- if (!free_slot) {
- store_node(node);
- return;
- }
-
- free_slot->addr = node->addr;
-
- schedule_store(BT_MESH_NODES_PENDING);
+ atomic_set_bit(bt_mesh_cdb.flags, flag);
+ k_delayed_work_submit(&pending_store, K_NO_WAIT);
}
-void bt_mesh_clear_node(struct bt_mesh_node *node)
+void bt_mesh_store_cdb(void)
+{
+ schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
+}
+
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
- update = node_update_find(node->addr, &free_slot);
+ update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
- update->clear = true;
- schedule_store(BT_MESH_NODES_PENDING);
+ update->clear = false;
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
- clear_node(node->addr);
+ store_cdb_node(node);
return;
}
free_slot->addr = node->addr;
+ free_slot->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+}
+
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node)
+{
+ struct node_update *update, *free_slot;
+
+ BT_DBG("Node 0x%04x", node->addr);
+
+ update = cdb_node_update_find(node->addr, &free_slot);
+ if (update) {
+ update->clear = true;
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ clear_cdb_node(node->addr);
+ return;
+ }
+
+ free_slot->addr = node->addr;
+ free_slot->clear = true;
+
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+}
+
+/* TODO: Could be shared with key_update_find? */
+static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx,
+ struct key_update **free_slot)
+{
+ struct key_update *match;
+ int i;
+
+ match = NULL;
+ *free_slot = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+ struct key_update *update = &cdb_key_updates[i];
+
+ if (!update->valid) {
+ *free_slot = update;
+ continue;
+ }
+
+ if (update->app_key != app_key) {
+ continue;
+ }
+
+ if (update->key_idx == key_idx) {
+ match = update;
+ }
+ }
+
+ return match;
+}
+
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+ update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+ if (update) {
+ update->clear = 0U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ store_cdb_subnet(sub);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = sub->net_idx;
+ free_slot->app_key = 0U;
+ free_slot->clear = 0U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+ update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+ if (update) {
+ update->clear = 1U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ clear_cdb_subnet(sub->net_idx);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = sub->net_idx;
+ free_slot->app_key = 0U;
+ free_slot->clear = 1U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+ update = cdb_key_update_find(true, key->app_idx, &free_slot);
+ if (update) {
+ update->clear = 0U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ store_cdb_app_key(key);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = key->app_idx;
+ free_slot->app_key = 1U;
+ free_slot->clear = 0U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+ update = cdb_key_update_find(true, key->app_idx, &free_slot);
+ if (update) {
+ update->clear = 1U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ clear_cdb_app_key(key->app_idx);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = key->app_idx;
+ free_slot->app_key = 1U;
+ free_slot->clear = 1U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
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)
{
- char path[20];
+ char path[30];
char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))];
char *val;
int err;
encode_mod_path(mod, vnd, "data", path, sizeof(path));
+ if (name) {
+ strcat(path, "/");
+ strncat(path, name, 8);
+ }
if (data_len) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
val = settings_str_from_bytes(data, data_len,
buf, sizeof(buf));
if (!val) {
@@ -2044,12 +2426,8 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
return -EINVAL;
}
err = settings_save_one(path, val);
- } else if (mod->flags & BT_MESH_MOD_DATA_PRESENT) {
- mod->flags &= ~BT_MESH_MOD_DATA_PRESENT;
- err = settings_save_one(path, NULL);
} else {
- /* Nothing to delete */
- err = 0;
+ err = settings_save_one(path, NULL);
}
if (err) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
index c630814e..9060a14a 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
@@ -8,20 +8,25 @@ void bt_mesh_store_net(void);
void bt_mesh_store_iv(bool only_duration);
void bt_mesh_store_seq(void);
void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl);
-void bt_mesh_store_subnet(struct bt_mesh_subnet *sub);
-void bt_mesh_store_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_store_subnet(uint16_t net_idx);
+void bt_mesh_store_app_key(uint16_t app_idx);
void bt_mesh_store_hb_pub(void);
void bt_mesh_store_cfg(void);
void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
void bt_mesh_store_label(void);
-void bt_mesh_store_node(struct bt_mesh_node *node);
+void bt_mesh_store_cdb(void);
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node);
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app);
void bt_mesh_clear_net(void);
-void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
-void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_clear_subnet(uint16_t net_idx);
+void bt_mesh_clear_app_key(uint16_t app_idx);
void bt_mesh_clear_rpl(void);
-void bt_mesh_clear_node(struct bt_mesh_node *node);
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node);
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app);
void bt_mesh_settings_init(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
index 91fbd978..d597ed6d 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
@@ -25,6 +25,7 @@
/* Private includes for raw Network & Transport layer access */
#include "net.h"
+#include "rpl.h"
#include "access.h"
#include "mesh_priv.h"
#include "lpn.h"
@@ -55,50 +56,29 @@ static struct os_eventq mesh_shell_queue;
#define VND_MODEL_ID_1 0x1234
/* Default net, app & dev key values, unless otherwise specified */
-static const u8_t default_key[16] = {
+static const uint8_t default_key[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};
static struct {
- u16_t local;
- u16_t dst;
- u16_t net_idx;
- u16_t app_idx;
+ uint16_t local;
+ uint16_t dst;
+ uint16_t net_idx;
+ uint16_t app_idx;
} net = {
.local = BT_MESH_ADDR_UNASSIGNED,
.dst = BT_MESH_ADDR_UNASSIGNED,
};
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_DISABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if MYNEWT_VAL(BLE_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_DISABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
-
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
#define CUR_FAULTS_MAX 4
-static u8_t cur_faults[CUR_FAULTS_MAX];
-static u8_t reg_faults[CUR_FAULTS_MAX * 2];
+static uint8_t cur_faults[CUR_FAULTS_MAX];
+static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
-static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
+static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
{
- u8_t i, limit = *count;
+ uint8_t i, limit = *count;
for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
if (faults[i]) {
@@ -108,8 +88,8 @@ static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
}
}
-static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
{
printk("Sending current faults\n");
@@ -121,8 +101,8 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
return 0;
}
-static int fault_get_reg(struct bt_mesh_model *model, u16_t cid,
- u8_t *test_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
{
if (cid != CID_VENDOR) {
printk("Faults requested for unknown Company ID 0x%04x\n", cid);
@@ -189,7 +169,7 @@ static struct bt_mesh_cfg_cli cfg_cli = {
#endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
#if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
-void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
+void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
{
size_t i;
@@ -207,8 +187,8 @@ void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
}
}
-static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+static void health_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)
{
printk("Health Current Status from 0x%04x\n", addr);
@@ -242,22 +222,22 @@ static struct bt_mesh_light_lightness_srv light_lightness_srv = {
.set = light_model_light_lightness_set,
};
-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_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
+ int (*set)(struct bt_mesh_model *model, uint8_t state))
{
gen_onoff_srv.get = get;
gen_onoff_srv.set = set;
}
-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_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
gen_level_srv.get = get;
gen_level_srv.set = set;
}
-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_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
light_lightness_srv.get = get;
light_lightness_srv.set = set;
@@ -265,7 +245,7 @@ void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model,
#endif
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
@@ -297,7 +277,7 @@ static const struct bt_mesh_comp comp = {
.elem_count = ARRAY_SIZE(elements),
};
-static u8_t hex2val(char c)
+static uint8_t hex2val(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
@@ -310,7 +290,54 @@ static u8_t hex2val(char c)
}
}
-static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
+int char2hex(char c, uint8_t *x)
+{
+ if (c >= '0' && c <= '9') {
+ *x = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ *x = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ *x = c - 'A' + 10;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int hex2char(uint8_t x, char *c)
+{
+ if (x <= 9) {
+ *c = x + '0';
+ } else if (x <= 15) {
+ *c = x - 10 + 'a';
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
+{
+ if ((hexlen + 1) < buflen * 2) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < buflen; i++) {
+ if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
+ return 0;
+ }
+ if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
+ return 0;
+ }
+ }
+
+ hex[2 * buflen] = '\0';
+ return 2 * buflen;
+}
+
+static size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len)
{
size_t len = 0;
@@ -328,7 +355,7 @@ static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
return len;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
net_idx, addr);
@@ -337,7 +364,8 @@ static void prov_complete(u16_t net_idx, u16_t addr)
net.dst = addr;
}
-static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
+static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem)
{
printk("Node provisioned, net_idx 0x%04x address "
"0x%04x elements %d", net_idx, addr, num_elem);
@@ -369,7 +397,7 @@ static int output_string(const char *str)
}
static bt_mesh_input_action_t input_act;
-static u8_t input_size;
+static uint8_t input_size;
static int cmd_input_num(int argc, char *argv[])
{
@@ -437,7 +465,7 @@ struct shell_cmd_help cmd_input_str_help = {
NULL, "", NULL
};
-static int input(bt_mesh_input_action_t act, u8_t size)
+static int input(bt_mesh_input_action_t act, uint8_t size)
{
switch (act) {
case BT_MESH_ENTER_NUMBER:
@@ -481,9 +509,9 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
printk("Provisioning link closed on %s\n", bearer2str(bearer));
}
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
-static u8_t static_val[16];
+static uint8_t static_val[16];
static struct bt_mesh_prov prov = {
.uuid = dev_uuid,
@@ -534,7 +562,7 @@ struct shell_cmd_help cmd_static_oob_help = {
static int cmd_uuid(int argc, char *argv[])
{
- u8_t uuid[16];
+ uint8_t uuid[16];
size_t len;
if (argc < 2) {
@@ -560,12 +588,38 @@ struct shell_cmd_help cmd_uuid_help = {
static int cmd_reset(int argc, char *argv[])
{
- bt_mesh_reset();
- printk("Local node reset complete\n");
+ uint16_t addr;
+ if (argc < 2) {
+ return -EINVAL;
+ }
+
+ addr = strtoul(argv[1], NULL, 0);
+
+ if (addr == net.local) {
+ bt_mesh_reset();
+ printk("Local node reset complete");
+ } else {
+ int err;
+ bool reset = false;
+
+ err = bt_mesh_cfg_node_reset(net.net_idx, net.dst, &reset);
+ if (err) {
+ printk("Unable to send "
+ "Remote Node Reset (err %d)", err);
+ return 0;
+ }
+
+ printk("Remote node reset complete");
+ }
+
return 0;
}
-static u8_t str2u8(const char *str)
+struct shell_cmd_help cmd_reset_help = {
+ NULL, "", NULL
+};
+
+static uint8_t str2u8(const char *str)
{
if (isdigit(str[0])) {
return strtoul(str, NULL, 0);
@@ -631,7 +685,7 @@ static int cmd_poll(int argc, char *argv[])
return 0;
}
-static void lpn_cb(u16_t friend_addr, bool established)
+static void lpn_cb(uint16_t friend_addr, bool established)
{
if (established) {
printk("Friendship (as LPN) established to Friend 0x%04x\n",
@@ -784,8 +838,6 @@ static int cmd_net_send(int argc, char *argv[])
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = net.local,
- .xmit = bt_mesh_net_transmit_get(),
- .sub = bt_mesh_subnet_get(net.net_idx),
};
size_t len;
int err = 0;
@@ -795,12 +847,6 @@ static int cmd_net_send(int argc, char *argv[])
goto done;
}
- if (!tx.sub) {
- printk("No matching subnet for NetKey Index 0x%04x\n",
- net.net_idx);
- goto done;
- }
-
net_buf_simple_init(msg, 0);
len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4);
net_buf_simple_add(msg, len);
@@ -828,7 +874,7 @@ static int cmd_rpl_clear(int argc, char *argv[])
#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
static int cmd_lpn_subscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -849,7 +895,7 @@ struct shell_cmd_help cmd_lpn_subscribe_help = {
static int cmd_lpn_unsubscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -912,7 +958,7 @@ struct shell_cmd_help cmd_iv_update_test_help = {
int cmd_timeout(int argc, char *argv[])
{
- s32_t timeout;
+ int32_t timeout;
if (argc < 2) {
timeout = bt_mesh_cfg_cli_timeout_get();
@@ -952,7 +998,7 @@ struct shell_cmd_help cmd_timeout_help = {
static int cmd_get_comp(int argc, char *argv[])
{
struct os_mbuf *comp = NET_BUF_SIMPLE(32);
- u8_t status, page = 0x00;
+ uint8_t status, page = 0x00;
int err = 0;
if (argc > 1) {
@@ -980,8 +1026,8 @@ static int cmd_get_comp(int argc, char *argv[])
printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp));
while (comp->om_len > 4) {
- u8_t sig, vnd;
- u16_t loc;
+ uint8_t sig, vnd;
+ uint16_t loc;
int i;
loc = net_buf_simple_pull_le16(comp);
@@ -1002,7 +1048,7 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < sig; i++) {
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\t0x%04x\n", mod_id);
}
@@ -1014,8 +1060,8 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < vnd; i++) {
- u16_t cid = net_buf_simple_pull_le16(comp);
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t cid = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id);
}
@@ -1032,13 +1078,13 @@ struct shell_cmd_help cmd_get_comp_help = {
static int cmd_beacon(int argc, char *argv[])
{
- u8_t status;
+ uint8_t status;
int err;
if (argc < 2) {
err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
&status);
@@ -1054,19 +1100,49 @@ static int cmd_beacon(int argc, char *argv[])
return 0;
}
+static void print_unprovisioned_beacon(uint8_t uuid[16],
+ bt_mesh_prov_oob_info_t oob_info,
+ uint32_t *uri_hash)
+{
+ char uuid_hex_str[32 + 1];
+
+ bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+
+ printk("UUID %s, OOB Info 0x%04x, URI Hash 0x%lx",
+ uuid_hex_str, oob_info,
+ (uri_hash == NULL ? 0 : *uri_hash));
+}
+
+static int cmd_beacon_listen(int argc, char *argv[])
+{
+ uint8_t val = str2u8(argv[1]);
+
+ if (val) {
+ prov.unprovisioned_beacon = print_unprovisioned_beacon;
+ } else {
+ prov.unprovisioned_beacon = NULL;
+ }
+
+ return 0;
+}
+
struct shell_cmd_help cmd_beacon_help = {
NULL, "[val: off, on]", NULL
};
+struct shell_cmd_help cmd_beacon_listen_help = {
+ NULL, "[val: off, on]", NULL
+};
+
static int cmd_ttl(int argc, char *argv[])
{
- u8_t ttl;
+ uint8_t ttl;
int err;
if (argc < 2) {
err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
} else {
- u8_t val = strtoul(argv[1], NULL, 0);
+ uint8_t val = strtoul(argv[1], NULL, 0);
err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
}
@@ -1087,13 +1163,13 @@ struct shell_cmd_help cmd_ttl_help = {
static int cmd_friend(int argc, char *argv[])
{
- u8_t frnd;
+ uint8_t frnd;
int err;
if (argc < 2) {
err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
}
@@ -1114,13 +1190,13 @@ struct shell_cmd_help cmd_friend_help = {
static int cmd_gatt_proxy(int argc, char *argv[])
{
- u8_t proxy;
+ uint8_t proxy;
int err;
if (argc < 2) {
err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
&proxy);
@@ -1140,17 +1216,60 @@ struct shell_cmd_help cmd_gatt_proxy_help = {
NULL, "[val: off, on]", NULL
};
+static int cmd_net_transmit(int argc, char *argv[])
+{
+ uint8_t transmit;
+ int err;
+
+ if (argc < 2) {
+ err = bt_mesh_cfg_net_transmit_get(net.net_idx,
+ net.dst, &transmit);
+ } else {
+ if (argc != 3) {
+ printk("Wrong number of input arguments"
+ "(2 arguments are required)");
+ return -EINVAL;
+ }
+
+ uint8_t count, interval, new_transmit;
+
+ count = strtoul(argv[1], NULL, 0);
+ interval = strtoul(argv[2], NULL, 0);
+
+ new_transmit = BT_MESH_TRANSMIT(count, interval);
+
+ err = bt_mesh_cfg_net_transmit_set(net.net_idx, net.dst,
+ new_transmit, &transmit);
+ }
+
+ if (err) {
+ printk("Unable to send network transmit"
+ " Get/Set (err %d)", err);
+ return 0;
+ }
+
+ printk("Transmit 0x%02x (count %u interval %ums)",
+ transmit, BT_MESH_TRANSMIT_COUNT(transmit),
+ BT_MESH_TRANSMIT_INT(transmit));
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_transmit_help = {
+ NULL, "[ ]", NULL
+};
+
static int cmd_relay(int argc, char *argv[])
{
- u8_t relay, transmit;
+ uint8_t relay, transmit;
int err;
if (argc < 2) {
err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
&transmit);
} else {
- u8_t val = str2u8(argv[1]);
- u8_t count, interval, new_transmit;
+ uint8_t val = str2u8(argv[1]);
+ uint8_t count, interval, new_transmit;
if (val) {
if (argc > 2) {
@@ -1192,9 +1311,10 @@ struct shell_cmd_help cmd_relay_help = {
static int cmd_net_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx;
- u8_t status;
+ bool has_key_val = (argc > 2);
+ uint8_t key_val[16];
+ uint16_t key_net_idx;
+ uint8_t status;
int err;
if (argc < 2) {
@@ -1203,7 +1323,7 @@ static int cmd_net_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
- if (argc > 2) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1212,6 +1332,29 @@ static int cmd_net_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_subnet *subnet;
+
+ subnet = bt_mesh_cdb_subnet_get(key_net_idx);
+ if (subnet) {
+ if (has_key_val) {
+ printk("Subnet 0x%03x already has a value", key_net_idx);
+ return 0;
+ }
+
+ memcpy(key_val, subnet->keys[0].net_key, 16);
+ } else {
+ subnet = bt_mesh_cdb_subnet_alloc(key_net_idx);
+ if (!subnet) {
+ printk("No space for subnet in cdb");
+ return 0;
+ }
+
+ memcpy(subnet->keys[0].net_key, key_val, 16);
+ bt_mesh_cdb_subnet_store(subnet);
+ }
+ }
+
err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
key_val, &status);
if (err) {
@@ -1232,11 +1375,67 @@ struct shell_cmd_help cmd_net_key_add_help = {
NULL, " [val]", NULL
};
+static int cmd_net_key_get(int argc, char *argv[])
+{
+ uint16_t keys[16];
+ size_t cnt;
+ int err, i;
+
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_net_key_get(net.net_idx, net.dst, keys, &cnt);
+ if (err) {
+ printk("Unable to send NetKeyGet (err %d)", err);
+ return 0;
+ }
+
+ printk("NetKeys known by 0x%04x:", net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_get_help = {
+ NULL, NULL, NULL
+};
+
+static int cmd_net_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx;
+ uint8_t status;
+ int err;
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+
+ err = bt_mesh_cfg_net_key_del(net.net_idx, net.dst, key_net_idx,
+ &status);
+ if (err) {
+ printk("Unable to send NetKeyDel (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("NetKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("NetKey 0x%03x deleted", key_net_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_del_help = {
+ NULL, "", NULL
+};
+
static int cmd_app_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint8_t key_val[16];
+ uint16_t key_net_idx, key_app_idx;
+ bool has_key_val = (argc > 3);
+ uint8_t status;
int err;
if (argc < 3) {
@@ -1246,7 +1445,7 @@ static int cmd_app_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
key_app_idx = strtoul(argv[2], NULL, 0);
- if (argc > 3) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1255,6 +1454,30 @@ static int cmd_app_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_app_key *app_key;
+
+ app_key = bt_mesh_cdb_app_key_get(key_app_idx);
+ if (app_key) {
+ if (has_key_val) {
+ printk("App key 0x%03x already has a value", key_app_idx);
+ return 0;
+ }
+
+ memcpy(key_val, app_key->keys[0].app_key, 16);
+ } else {
+ app_key = bt_mesh_cdb_app_key_alloc(key_net_idx,
+ key_app_idx);
+ if (!app_key) {
+ printk("No space for app key in cdb");
+ return 0;
+ }
+
+ memcpy(app_key->keys[0].app_key, key_val, 16);
+ bt_mesh_cdb_app_key_store(app_key);
+ }
+ }
+
err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
key_app_idx, key_val, &status);
if (err) {
@@ -1276,10 +1499,83 @@ struct shell_cmd_help cmd_app_key_add_help = {
NULL, " [val]", NULL
};
+static int cmd_app_key_get(int argc, char *argv[])
+{
+ uint16_t net_idx;
+ uint16_t keys[16];
+ size_t cnt;
+ uint8_t status;
+ int err, i;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_app_key_get(net.net_idx, net.dst, net_idx, &status,
+ keys, &cnt);
+ if (err) {
+ printk("Unable to send AppKeyGet (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyGet failed with status 0x%02x",
+ status);
+ return 0;
+ }
+
+ printk(
+ "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx,
+ net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_get_help = {
+ NULL, "", NULL
+};
+
+static int cmd_app_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
+ int err;
+
+ if (argc < 3) {
+ return -EINVAL;
+ }
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+ key_app_idx = strtoul(argv[2], NULL, 0);
+
+ err = bt_mesh_cfg_app_key_del(net.net_idx, net.dst, key_net_idx,
+ key_app_idx, &status);
+ if (err) {
+ printk("Unable to send App Key del(err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey deleted, NetKeyIndex 0x%04x "
+ "AppKeyIndex 0x%04x", key_net_idx, key_app_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_del_help = {
+ NULL, " ", NULL
+};
+
static int cmd_mod_app_bind(int argc, char *argv[])
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1318,10 +1614,107 @@ struct shell_cmd_help cmd_mod_app_bind_help = {
NULL, " [Company ID]", NULL
};
+static int cmd_mod_app_unbind(int argc, char *argv[])
+{
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
+ int err;
+
+ if (argc < 4) {
+ return -EINVAL;
+ }
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_app_idx = strtoul(argv[2], NULL, 0);
+ mod_id = strtoul(argv[3], NULL, 0);
+
+ if (argc > 4) {
+ cid = strtoul(argv[4], NULL, 0);
+ err = bt_mesh_cfg_mod_app_unbind_vnd(net.net_idx, net.dst,
+ elem_addr, mod_app_idx,
+ mod_id, cid, &status);
+ } else {
+ err = bt_mesh_cfg_mod_app_unbind(net.net_idx, net.dst,
+ elem_addr, mod_app_idx, mod_id, &status);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Unbind (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Unbind failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey successfully unbound");
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_unbind_help = {
+ NULL, " [Company ID]", NULL
+};
+
+static int cmd_mod_app_get(int argc,
+ char *argv[])
+{
+ uint16_t elem_addr, mod_id, cid;
+ uint16_t apps[16];
+ uint8_t status;
+ size_t cnt;
+ int err, i;
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_id = strtoul(argv[2], NULL, 0);
+ cnt = ARRAY_SIZE(apps);
+
+ if (argc > 3) {
+ cid = strtoul(argv[3], NULL, 0);
+ err = bt_mesh_cfg_mod_app_get_vnd(net.net_idx, net.dst,
+ elem_addr, mod_id, cid,
+ &status, apps, &cnt);
+ } else {
+ err = bt_mesh_cfg_mod_app_get(net.net_idx, net.dst, elem_addr,
+ mod_id, &status, apps, &cnt);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Get (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Get failed with status 0x%02x",
+ status);
+ } else {
+ printk(
+ "Apps bound to Element 0x%04x, Model 0x%04x %s:",
+ elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+ if (!cnt) {
+ printk("\tNone.");
+ }
+
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%04x", apps[i]);
+ }
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_get_help = {
+ NULL, " [Company ID]", NULL
+};
+
static int cmd_mod_sub_add(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1363,8 +1756,8 @@ struct shell_cmd_help cmd_mod_sub_add_help = {
static int cmd_mod_sub_del(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1407,9 +1800,9 @@ struct shell_cmd_help cmd_mod_sub_del_help = {
static int cmd_mod_sub_add_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1457,9 +1850,9 @@ struct shell_cmd_help cmd_mod_sub_add_va_help = {
static int cmd_mod_sub_del_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1506,10 +1899,64 @@ struct shell_cmd_help cmd_mod_sub_del_va_help = {
NULL, "