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 <nrf_log.h>
 #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 <hal/nrf_rtc.h>
+#include <nrf_log.h>
 #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 <hal/nrf_rtc.h>
+#include <nrf_log.h>
 
 using namespace Pinetime::Controllers;
 
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 @@
+<!--
+#
+# 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.
+#
+-->
+
+# 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(&notify_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 <krzysztof.kopyscinski@codecoup.pl>"
+
+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 "<name> 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 <dev@mynewt.apache.org>"
+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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
+int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
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 <stdint.h>
+#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 <stdlib.h>
 #include <stdint.h>
 #include <assert.h>
 #include <string.h>
@@ -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 @@
+<!--
+#
+# 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.
+#
+-->
+
+## 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 <dev@mynewt.apache.org>"
+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 <assert.h>
+#include <stdint.h>
+#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 <stdint.h>
+
+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 <assert.h>
+#include <stdint.h>
+#include <assert.h>
+#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 <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#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 <stdint.h>
 #include <assert.h>
 #include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
 #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 <dev@mynewt.apache.org>"
+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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include <syscfg/syscfg.h>
+#include <os/os.h>
+#include <nimble/ble.h>
+#include <nimble/nimble_opt.h>
+#include <controller/ble_hw.h>
+
+#include <ble/xcvr.h>
+#include <mcu/cmsis_nvic.h>
+#include <os/os_trace_api.h>
+
+/* 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <syscfg/syscfg.h>
+#include <os/os.h>
+#include <nimble/ble.h>
+#include <nimble/nimble_opt.h>
+#include <nimble/nimble_npl.h>
+#include <controller/ble_phy.h>
+
+#include <ble/xcvr.h>
+#include <controller/ble_phy_trace.h>
+#include <controller/ble_ll.h>
+#include <mcu/nrf5340_net_clock.h>
+#include <mcu/cmsis_nvic.h>
+
+/*
+ * 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 <stdint.h>
+#include <syscfg/syscfg.h>
+#include <os/os_trace_api.h>
+
+#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 <stdbool.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+/**
+ * @brief Bluetooth Mesh Runtime Configuration API
+ * @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Bluetooth Mesh Feature states */
+enum bt_mesh_feat_state {
+	/** Feature is supported, but disabled. */
+	BT_MESH_FEATURE_DISABLED,
+	/** Feature is supported and enabled. */
+	BT_MESH_FEATURE_ENABLED,
+	/** Feature is not supported, and cannot be enabled. */
+	BT_MESH_FEATURE_NOT_SUPPORTED,
+};
+
+/* Legacy feature defines */
+#define BT_MESH_RELAY_DISABLED              BT_MESH_FEATURE_DISABLED
+#define BT_MESH_RELAY_ENABLED               BT_MESH_FEATURE_ENABLED
+#define BT_MESH_RELAY_NOT_SUPPORTED         BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_BEACON_DISABLED             BT_MESH_FEATURE_DISABLED
+#define BT_MESH_BEACON_ENABLED              BT_MESH_FEATURE_ENABLED
+
+#define BT_MESH_GATT_PROXY_DISABLED         BT_MESH_FEATURE_DISABLED
+#define BT_MESH_GATT_PROXY_ENABLED          BT_MESH_FEATURE_ENABLED
+#define BT_MESH_GATT_PROXY_NOT_SUPPORTED    BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_FRIEND_DISABLED             BT_MESH_FEATURE_DISABLED
+#define BT_MESH_FRIEND_ENABLED              BT_MESH_FEATURE_ENABLED
+#define BT_MESH_FRIEND_NOT_SUPPORTED        BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_NODE_IDENTITY_STOPPED       BT_MESH_FEATURE_DISABLED
+#define BT_MESH_NODE_IDENTITY_RUNNING       BT_MESH_FEATURE_ENABLED
+#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+/** @brief Enable or disable sending of the Secure Network Beacon.
+ *
+ *  @param beacon New Secure Network Beacon state.
+ */
+void bt_mesh_beacon_set(bool beacon);
+
+/** @brief Get the current Secure Network Beacon state.
+ *
+ *  @returns Whether the Secure Network Beacon feature is enabled.
+ */
+bool bt_mesh_beacon_enabled(void);
+
+/** @brief Set the default TTL value.
+ *
+ *  The default TTL value is used when no explicit TTL value is set. Models will
+ *  use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
+ *  @ref BT_MESH_TTL_DEFAULT.
+ *
+ *  @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
+ *                     to @ref BT_MESH_TTL_MAX.
+ *
+ *  @retval 0       Successfully set the default TTL value.
+ *  @retval -EINVAL Invalid TTL value.
+ */
+int bt_mesh_default_ttl_set(uint8_t default_ttl);
+
+/** @brief Get the current default TTL value.
+ *
+ *  @return The current default TTL value.
+ */
+uint8_t bt_mesh_default_ttl_get(void);
+
+/** @brief Set the Network Transmit parameters.
+ *
+ *  The Network Transmit parameters determine the parameters local messages are
+ *  transmitted with.
+ *
+ *  @see BT_MESH_TRANSMIT
+ *
+ *  @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
+ *              encoding.
+ */
+void bt_mesh_net_transmit_set(uint8_t xmit);
+
+/** @brief Get the current Network Transmit parameters.
+ *
+ *  The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ *  used to decode the Network Transmit parameters.
+ *
+ *  @return The current Network Transmit parameters.
+ */
+uint8_t bt_mesh_net_transmit_get(void);
+
+/** @brief Configure the Relay feature.
+ *
+ *  Enable or disable the Relay feature, and configure the parameters to
+ *  transmit relayed messages with.
+ *
+ *  Support for the Relay feature must be enabled through the
+ *  @c CONFIG_BT_MESH_RELAY configuration option.
+ *
+ *  @see BT_MESH_TRANSMIT
+ *
+ *  @param relay New Relay feature state. Must be one of
+ *               @ref BT_MESH_FEATURE_ENABLED and
+ *               @ref BT_MESH_FEATURE_DISABLED.
+ *  @param xmit  New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
+ *               encoding.
+ *
+ *  @retval 0         Successfully changed the Relay configuration.
+ *  @retval -ENOTSUP  The Relay feature is not supported.
+ *  @retval -EINVAL   Invalid parameter.
+ *  @retval -EALREADY Already using the given parameters.
+ */
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
+
+/** @brief Get the current Relay feature state.
+ *
+ *  @returns The Relay feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_relay_get(void);
+
+/** @brief Get the current Relay Retransmit parameters.
+ *
+ *  The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ *  used to decode the Relay Retransmit parameters.
+ *
+ *  @return The current Relay Retransmit parameters, or 0 if relay is not
+ *          supported.
+ */
+uint8_t bt_mesh_relay_retransmit_get(void);
+
+/** @brief Enable or disable the GATT Proxy feature.
+ *
+ *  Support for the GATT Proxy feature must be enabled through the
+ *  @c CONFIG_BT_MESH_GATT_PROXY configuration option.
+ *
+ *  @note The GATT Proxy feature only controls a Proxy node's ability to relay
+ *        messages to the mesh network. A node that supports GATT Proxy will
+ *        still advertise Connectable Proxy beacons, even if the feature is
+ *        disabled. The Proxy feature can only be fully disabled through compile
+ *        time configuration.
+ *
+ *  @param gatt_proxy New GATT Proxy state. Must be one of
+ *                    @ref BT_MESH_FEATURE_ENABLED and
+ *                    @ref BT_MESH_FEATURE_DISABLED.
+ *
+ *  @retval 0         Successfully changed the GATT Proxy feature state.
+ *  @retval -ENOTSUP  The GATT Proxy feature is not supported.
+ *  @retval -EINVAL   Invalid parameter.
+ *  @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
+
+/** @brief Get the current GATT Proxy state.
+ *
+ *  @returns The GATT Proxy feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
+
+/** @brief Enable or disable the Friend feature.
+ *
+ *  Any active friendships will be terminated immediately if the Friend feature
+ *  is disabled.
+ *
+ *  Support for the Friend feature must be enabled through the
+ *  @c CONFIG_BT_MESH_FRIEND configuration option.
+ *
+ *  @param friendship New Friend feature state. Must be one of
+ *                    @ref BT_MESH_FEATURE_ENABLED and
+ *                    @ref BT_MESH_FEATURE_DISABLED.
+ *
+ *  @retval 0        Successfully changed the Friend feature state.
+ *  @retval -ENOTSUP The Friend feature is not supported.
+ *  @retval -EINVAL  Invalid parameter.
+ *  @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
+
+/** @brief Get the current Friend state.
+ *
+ *  @returns The Friend feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_friend_get(void);
+
+/**
+ * @brief Bluetooth Mesh Subnet Configuration
+ * @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
+ * @{
+ */
+
+/** @brief Add a Subnet.
+ *
+ *  Adds a subnet with the given network index and network key to the list of
+ *  known Subnets. All messages sent on the given Subnet will be processed by
+ *  this node, and the node may send and receive Network Beacons on the given
+ *  Subnet.
+ *
+ *  @param net_idx Network index.
+ *  @param key     Root network key of the Subnet. All other keys are derived
+ *                 from this.
+ *
+ *  @retval STATUS_SUCCESS The Subnet was successfully added.
+ *  @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
+ *  @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
+ */
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Update the given Subnet.
+ *
+ *  Starts the Key Refresh procedure for this Subnet by adding a second set of
+ *  encryption keys. The Subnet will continue sending with the old key (but
+ *  receiving messages using both) until the Subnet enters Key Refresh phase 2.
+ *
+ *  This allows a network configurator to replace old network and application
+ *  keys for the entire network, effectively removing access for all nodes that
+ *  aren't given the new keys.
+ *
+ *  @param net_idx Network index.
+ *  @param key     New root network key of the Subnet.
+ *
+ *  @retval STATUS_SUCCESS The Subnet was updated with a second key.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
+ *                                    current key.
+ *  @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
+ */
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Delete a Subnet.
+ *
+ *  Removes the Subnet with the given network index from the node. The node will
+ *  stop sending Network Beacons with the given Subnet, and can no longer
+ *  process messages on this Subnet.
+ *
+ *  All Applications bound to this Subnet are also deleted.
+ *
+ *  @param net_idx Network index.
+ *
+ *  @retval STATUS_SUCCESS The Subnet was deleted.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_del(uint16_t net_idx);
+
+/** @brief Check whether a Subnet is known.
+ *
+ *  @param net_idx Network index
+ *
+ *  @return true if a Subnet with the given index exists, false otherwise.
+ */
+bool bt_mesh_subnet_exists(uint16_t net_idx);
+
+/** @brief Set the Subnet's Key Refresh phase.
+ *
+ *  The Key Refresh procedure is started by updating the Subnet keys through
+ *  @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
+ *  Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
+ *  activated through this function to start transmitting with the new network
+ *  key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
+ *  removes the old keys from the node, and returns the Subnet back to normal
+ *  single-key operation with the new key set.
+ *
+ *  @param net_idx Network index.
+ *  @param phase   Pointer to the new Key Refresh phase. Will return the actual
+ *                 Key Refresh phase after updating.
+ *
+ *  @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
+ *                         changed.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
+ */
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Get the Subnet's Key Refresh phase.
+ *
+ *  @param net_idx Network index.
+ *  @param phase   Pointer to the Key Refresh variable to fill.
+ *
+ *  @retval STATUS_SUCCESS Successfully populated the @c phase variable.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Set the Node Identity state of the Subnet.
+ *
+ *  The Node Identity state of a Subnet determines whether the Subnet advertises
+ *  connectable Node Identity beacons for Proxy Clients to connect to.
+ *  Once started, the Node Identity beacon runs for 60 seconds, or until it is
+ *  stopped.
+ *
+ *  This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
+ *  but only acts on a single Subnet.
+ *
+ *  GATT Proxy support must be enabled through
+ *  @option{CONFIG_BT_MESH_GATT_PROXY}.
+ *
+ *  @param net_idx Network index.
+ *  @param node_id New Node Identity state, must be either @ref
+ *                 BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
+ *
+ *  @retval STATUS_SUCCESS Successfully set the Node Identity state of the
+ *                         Subnet.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
+ *  @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
+ */
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+				   enum bt_mesh_feat_state node_id);
+
+/** @brief Get the Node Identity state of the Subnet.
+ *
+ *  @param net_idx Network index.
+ *  @param node_id Node Identity variable to fill.
+ *
+ *  @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+				   enum bt_mesh_feat_state *node_id);
+
+/** @brief Get a list of all known Subnet indexes.
+ *
+ *  Builds a list of all known Subnet indexes in the @c net_idxs array.
+ *  If the @c net_idxs array is smaller than the list of known Subnets, this
+ *  function fills all available entries and returns @c -ENOMEM. In this
+ *  case, the next @c max entries of the list can be read out by calling
+ *  @code
+ *  bt_mesh_subnets_get(list, max, max);
+ *  @endcode
+ *
+ *  Note that any changes to the Subnet list between calls to this function
+ *  could change the order and number of entries in the list.
+ *
+ *  @param net_idxs Array to fill.
+ *  @param max      Max number of indexes to return.
+ *  @param skip     Number of indexes to skip. Enables batched processing of the
+ *                  list.
+ *
+ *  @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
+ *          if the number of known Subnets exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Bluetooth Mesh Application Configuration
+ * @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
+ * @{
+ */
+
+/** @brief Add an Application key.
+ *
+ *  Adds the Application with the given index to the list of known applications.
+ *  Allows the node to send and receive model messages encrypted with this
+ *  Application key.
+ *
+ *  Every Application is bound to a specific Subnet. The node must know the
+ *  Subnet the Application is bound to before it can add the Application.
+ *
+ *  @param app_idx Application index.
+ *  @param net_idx Network index the Application is bound to.
+ *  @param key     Application key value.
+ *
+ *  @retval STATUS_SUCCESS The Application was successfully added.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_INSUFF_RESOURCES There's no room for storing this
+ *                                  Application.
+ *  @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
+ *                                 Subnet.
+ *  @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
+ *                                    different key value.
+ *  @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
+ */
+uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
+			    const uint8_t key[16]);
+
+/** @brief Update an Application key.
+ *
+ *  Update an Application with a second Application key, as part of the
+ *  Key Refresh procedure of the bound Subnet. The node will continue
+ *  transmitting with the old application key (but receiving on both) until the
+ *  Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
+ *  3, the old application key will be deleted.
+ *
+ *  @note The Application key can only be updated if the bound Subnet is in Key
+ *        Refresh phase 1.
+ *
+ *  @param app_idx Application index.
+ *  @param net_idx Network index the Application is bound to, or
+ *                 @ref BT_MESH_KEY_ANY to skip the binding check.
+ *  @param key     New key value.
+ *
+ *  @retval STATUS_SUCCESS The Application key was successfully updated.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ *  @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
+ *                               reason.
+ *  @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
+ *                                    different key value.
+ */
+uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
+			       const uint8_t key[16]);
+
+/** @brief Delete an Application key.
+ *
+ *  All models bound to this application will remove this binding.
+ *  All models publishing with this application will stop publishing.
+ *
+ *  @param app_idx Application index.
+ *  @param net_idx Network index.
+ *
+ *  @retval STATUS_SUCCESS The Application key was successfully deleted.
+ *  @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ *  @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ */
+uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
+
+/** @brief Check if an Application key is known.
+ *
+ *  @param app_idx Application index.
+ *
+ *  @return true if the Application is known, false otherwise.
+ */
+bool bt_mesh_app_key_exists(uint16_t app_idx);
+
+/** @brief Get a list of all known Application key indexes.
+ *
+ *  Builds a list of all Application indexes for the given network index in the
+ *  @c app_idxs array. If the @c app_idxs array cannot fit all bound
+ *  Applications, this function fills all available entries and returns @c
+ *  -ENOMEM. In this case, the next @c max entries of the list can be read out
+ *  by calling
+ *  @code
+ *  bt_mesh_app_keys_get(net_idx, list, max, max);
+ *  @endcode
+ *
+ *  Note that any changes to the Application key list between calls to this
+ *  function could change the order and number of entries in the list.
+ *
+ *  @param net_idx  Network Index to get the Applications of, or @ref
+ *                  BT_MESH_KEY_ANY to get all Applications.
+ *  @param app_idxs Array to fill.
+ *  @param max      Max number of indexes to return.
+ *  @param skip     Number of indexes to skip. Enables batched processing of the
+ *                  list.
+ *
+ *  @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
+ *          if the number of known Applications exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
+			     off_t skip);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* _BT_MESH_CFG_H_ */
\ 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 <string.h>
+#include <stdlib.h>
+#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, &params);
 	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, &param->keys[i], &param->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, &param->keys[i], &param->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(&param, 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(&param, 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(&param, 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(&param, 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(&param, 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(&param, 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 <stdbool.h>
+#include <stdint.h>
+
 #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 <stdint.h>
+#include <string.h>
+#include "mesh/mesh.h"
+#include <os/os_mbuf.h>
+#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 <errno.h>
 
 #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, "<string>", 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, "<addr>", 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, "[<count: 0-7> <interval: 10-320>]", 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, "<NetKeyIndex> [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, "<NetKeyIndex>", 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, "<NetKeyIndex> <AppKeyIndex> [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, "<NetKeyIndex>", 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, "<NetKeyIndex> <AppKeyIndex>", 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, "<addr> <AppIndex> <Model ID> [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, "<addr> <AppIndex> <Model ID> [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, "<elem addr> <Model ID> [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, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
 };
 
-static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
+static int cmd_mod_sub_get(int argc,
+			      char *argv[])
+{
+	uint16_t elem_addr, mod_id, cid;
+	uint16_t subs[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(subs);
+
+	if (argc > 3) {
+		cid = strtoul(argv[3], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_get_vnd(net.net_idx, net.dst,
+						  elem_addr, mod_id, cid,
+						  &status, subs, &cnt);
+	} else {
+		err = bt_mesh_cfg_mod_sub_get(net.net_idx, net.dst, elem_addr,
+					      mod_id, &status, subs, &cnt);
+	}
+
+	if (err) {
+		printk("Unable to send Model Subscription Get "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		printk("Model Subscription Get failed with "
+			    "status 0x%02x", status);
+	} else {
+		printk(
+			"Model Subscriptions for 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", subs[i]);
+		}
+	}
+
+	return 0;
+}
+
+struct shell_cmd_help cmd_mod_sub_get_help = {
+	NULL, "<elem addr> <Model ID> [Company ID]", NULL
+};
+
+static int mod_pub_get(uint16_t addr, uint16_t mod_id, uint16_t cid)
 {
 	struct bt_mesh_cfg_mod_pub pub;
-	u8_t status;
+	uint8_t status;
 	int err;
 
 	if (cid == CID_NVAL) {
@@ -1546,11 +1993,11 @@ static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
 	return 0;
 }
 
-static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
+static int mod_pub_set(uint16_t addr, uint16_t mod_id, uint16_t cid, char *argv[])
 {
 	struct bt_mesh_cfg_mod_pub pub;
-	u8_t status, count;
-	u16_t interval;
+	uint8_t status, count;
+	uint16_t interval;
 	int err;
 
 	pub.addr = strtoul(argv[0], NULL, 0);
@@ -1598,7 +2045,7 @@ static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
 
 static int cmd_mod_pub(int argc, char *argv[])
 {
-	u16_t addr, mod_id, cid;
+	uint16_t addr, mod_id, cid;
 
 	if (argc < 3) {
 		return -EINVAL;
@@ -1650,7 +2097,7 @@ static void hb_sub_print(struct bt_mesh_cfg_hb_sub *sub)
 static int hb_sub_get(int argc, char *argv[])
 {
 	struct bt_mesh_cfg_hb_sub sub;
-	u8_t status;
+	uint8_t status;
 	int err;
 
 	err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
@@ -1672,7 +2119,7 @@ static int hb_sub_get(int argc, char *argv[])
 static int hb_sub_set(int argc, char *argv[])
 {
 	struct bt_mesh_cfg_hb_sub sub;
-	u8_t status;
+	uint8_t status;
 	int err;
 
 	sub.src = strtoul(argv[1], NULL, 0);
@@ -1715,7 +2162,7 @@ struct shell_cmd_help cmd_hb_sub_help = {
 static int hb_pub_get(int argc, char *argv[])
 {
 	struct bt_mesh_cfg_hb_pub pub;
-	u8_t status;
+	uint8_t status;
 	int err;
 
 	err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
@@ -1742,7 +2189,7 @@ static int hb_pub_get(int argc, char *argv[])
 static int hb_pub_set(int argc, char *argv[])
 {
 	struct bt_mesh_cfg_hb_pub pub;
-	u8_t status;
+	uint8_t status;
 	int err;
 
 	pub.dst = strtoul(argv[1], NULL, 0);
@@ -1787,7 +2234,7 @@ struct shell_cmd_help cmd_hb_pub_help = {
 
 #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
 
-#if MYNEWT_VAL(BLE_MESH_PROV)
+#if MYNEWT_VAL(BLE_MESH_PROV_DEVICE)
 static int cmd_pb(bt_mesh_prov_bearer_t bearer, int argc, char *argv[])
 {
 	int err;
@@ -1833,10 +2280,10 @@ static int cmd_pb_adv(int argc, char *argv[])
 #if MYNEWT_VAL(BLE_MESH_PROVISIONER)
 static int cmd_provision_adv(int argc, char *argv[])
 {
-	u8_t uuid[16];
-	u8_t attention_duration;
-	u16_t net_idx;
-	u16_t addr;
+	uint8_t uuid[16];
+	uint8_t attention_duration;
+	uint16_t net_idx;
+	uint16_t addr;
 	size_t len;
 	int err;
 
@@ -1871,8 +2318,9 @@ static int cmd_pb_gatt(int argc, char *argv[])
 
 static int cmd_provision(int argc, char *argv[])
 {
-	u16_t net_idx, addr;
-	u32_t iv_index;
+	const uint8_t *net_key = default_key;
+	uint16_t net_idx, addr;
+	uint32_t iv_index;
 	int err;
 
 	if (argc < 3) {
@@ -1888,7 +2336,19 @@ static int cmd_provision(int argc, char *argv[])
 		iv_index = 0;
 	}
 
-	err = bt_mesh_provision(default_key, net_idx, 0, iv_index, addr,
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		const struct bt_mesh_cdb_subnet *sub;
+
+		sub = bt_mesh_cdb_subnet_get(net_idx);
+		if (!sub) {
+			printk("No cdb entry for subnet 0x%03x", net_idx);
+			return 0;
+		}
+
+		net_key = sub->keys[sub->kr_flag].net_key;
+	}
+
+	err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr,
 				default_key);
 	if (err) {
 		printk("Provisioning failed (err %d)\n", err);
@@ -1905,10 +2365,10 @@ struct shell_cmd_help cmd_provision_help = {
 
 static int cmd_fault_get(int argc, char *argv[])
 {
-	u8_t faults[32];
+	uint8_t faults[32];
 	size_t fault_count;
-	u8_t test_id;
-	u16_t cid;
+	uint8_t test_id;
+	uint16_t cid;
 	int err;
 
 	if (argc < 2) {
@@ -1918,8 +2378,8 @@ static int cmd_fault_get(int argc, char *argv[])
 	cid = strtoul(argv[1], NULL, 0);
 	fault_count = sizeof(faults);
 
-	err = bt_mesh_health_fault_get(net.net_idx, net.dst, net.app_idx, cid,
-				       &test_id, faults, &fault_count);
+	err = bt_mesh_health_fault_get(net.dst, net.app_idx, cid, &test_id,
+								   faults, &fault_count);
 	if (err) {
 		printk("Failed to send Health Fault Get (err %d)\n", err);
 	} else {
@@ -1935,10 +2395,10 @@ struct shell_cmd_help cmd_fault_get_help = {
 
 static int cmd_fault_clear(int argc, char *argv[])
 {
-	u8_t faults[32];
+	uint8_t faults[32];
 	size_t fault_count;
-	u8_t test_id;
-	u16_t cid;
+	uint8_t test_id;
+	uint16_t cid;
 	int err;
 
 	if (argc < 2) {
@@ -1948,8 +2408,8 @@ static int cmd_fault_clear(int argc, char *argv[])
 	cid = strtoul(argv[1], NULL, 0);
 	fault_count = sizeof(faults);
 
-	err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
-					 cid, &test_id, faults, &fault_count);
+	err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+									 &test_id, faults, &fault_count);
 	if (err) {
 		printk("Failed to send Health Fault Clear (err %d)\n", err);
 	} else {
@@ -1965,7 +2425,7 @@ struct shell_cmd_help cmd_fault_clear_help = {
 
 static int cmd_fault_clear_unack(int argc, char *argv[])
 {
-	u16_t cid;
+	uint16_t cid;
 	int err;
 
 	if (argc < 2) {
@@ -1974,8 +2434,8 @@ static int cmd_fault_clear_unack(int argc, char *argv[])
 
 	cid = strtoul(argv[1], NULL, 0);
 
-	err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
-					 cid, NULL, NULL, NULL);
+	err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+									 NULL, NULL, NULL);
 	if (err) {
 		printk("Health Fault Clear Unacknowledged failed (err %d)\n",
 		       err);
@@ -1990,10 +2450,10 @@ struct shell_cmd_help cmd_fault_clear_unack_help = {
 
 static int cmd_fault_test(int argc, char *argv[])
 {
-	u8_t faults[32];
+	uint8_t faults[32];
 	size_t fault_count;
-	u8_t test_id;
-	u16_t cid;
+	uint8_t test_id;
+	uint16_t cid;
 	int err;
 
 	if (argc < 3) {
@@ -2004,8 +2464,8 @@ static int cmd_fault_test(int argc, char *argv[])
 	test_id = strtoul(argv[2], NULL, 0);
 	fault_count = sizeof(faults);
 
-	err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
-					cid, test_id, faults, &fault_count);
+	err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+									test_id, faults, &fault_count);
 	if (err) {
 		printk("Failed to send Health Fault Test (err %d)\n", err);
 	} else {
@@ -2021,8 +2481,8 @@ struct shell_cmd_help cmd_fault_test_help = {
 
 static int cmd_fault_test_unack(int argc, char *argv[])
 {
-	u16_t cid;
-	u8_t test_id;
+	uint16_t cid;
+	uint8_t test_id;
 	int err;
 
 	if (argc < 3) {
@@ -2032,8 +2492,8 @@ static int cmd_fault_test_unack(int argc, char *argv[])
 	cid = strtoul(argv[1], NULL, 0);
 	test_id = strtoul(argv[2], NULL, 0);
 
-	err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
-					cid, test_id, NULL, NULL);
+	err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+									test_id, NULL, NULL);
 	if (err) {
 		printk("Health Fault Test Unacknowledged failed (err %d)\n",
 		       err);
@@ -2048,11 +2508,10 @@ struct shell_cmd_help cmd_fault_test_unack_help = {
 
 static int cmd_period_get(int argc, char *argv[])
 {
-	u8_t divisor;
+	uint8_t divisor;
 	int err;
 
-	err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx,
-					&divisor);
+	err = bt_mesh_health_period_get(net.dst, net.app_idx, &divisor);
 	if (err) {
 		printk("Failed to send Health Period Get (err %d)\n", err);
 	} else {
@@ -2064,7 +2523,7 @@ static int cmd_period_get(int argc, char *argv[])
 
 static int cmd_period_set(int argc, char *argv[])
 {
-	u8_t divisor, updated_divisor;
+	uint8_t divisor, updated_divisor;
 	int err;
 
 	if (argc < 2) {
@@ -2073,8 +2532,8 @@ static int cmd_period_set(int argc, char *argv[])
 
 	divisor = strtoul(argv[1], NULL, 0);
 
-	err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
-					divisor, &updated_divisor);
+	err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor,
+									&updated_divisor);
 	if (err) {
 		printk("Failed to send Health Period Set (err %d)\n", err);
 	} else {
@@ -2090,7 +2549,7 @@ struct shell_cmd_help cmd_period_set_help = {
 
 static int cmd_period_set_unack(int argc, char *argv[])
 {
-	u8_t divisor;
+	uint8_t divisor;
 	int err;
 
 	if (argc < 2) {
@@ -2099,8 +2558,7 @@ static int cmd_period_set_unack(int argc, char *argv[])
 
 	divisor = strtoul(argv[1], NULL, 0);
 
-	err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
-					divisor, NULL);
+	err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor, NULL);
 	if (err) {
 		printk("Failed to send Health Period Set (err %d)\n", err);
 	}
@@ -2114,11 +2572,11 @@ struct shell_cmd_help cmd_period_set_unack_help = {
 
 static int cmd_attention_get(int argc, char *argv[])
 {
-	u8_t attention;
+	uint8_t attention;
 	int err;
 
-	err = bt_mesh_health_attention_get(net.net_idx, net.dst, net.app_idx,
-					   &attention);
+	err = bt_mesh_health_attention_get(net.dst, net.app_idx,
+									   &attention);
 	if (err) {
 		printk("Failed to send Health Attention Get (err %d)\n", err);
 	} else {
@@ -2130,7 +2588,7 @@ static int cmd_attention_get(int argc, char *argv[])
 
 static int cmd_attention_set(int argc, char *argv[])
 {
-	u8_t attention, updated_attention;
+	uint8_t attention, updated_attention;
 	int err;
 
 	if (argc < 2) {
@@ -2139,8 +2597,8 @@ static int cmd_attention_set(int argc, char *argv[])
 
 	attention = strtoul(argv[1], NULL, 0);
 
-	err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
-					   attention, &updated_attention);
+	err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+				 					   &updated_attention);
 	if (err) {
 		printk("Failed to send Health Attention Set (err %d)\n", err);
 	} else {
@@ -2156,7 +2614,7 @@ struct shell_cmd_help cmd_attention_set_help = {
 
 static int cmd_attention_set_unack(int argc, char *argv[])
 {
-	u8_t attention;
+	uint8_t attention;
 	int err;
 
 	if (argc < 2) {
@@ -2165,8 +2623,8 @@ static int cmd_attention_set_unack(int argc, char *argv[])
 
 	attention = strtoul(argv[1], NULL, 0);
 
-	err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
-					   attention, NULL);
+	err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+									   NULL);
 	if (err) {
 		printk("Failed to send Health Attention Set (err %d)\n", err);
 	}
@@ -2182,8 +2640,8 @@ struct shell_cmd_help cmd_attention_set_unack_help = {
 
 static int cmd_add_fault(int argc, char *argv[])
 {
-	u8_t fault_id;
-	u8_t i;
+	uint8_t fault_id;
+	uint8_t i;
 
 	if (argc < 2) {
 		return -EINVAL;
@@ -2229,8 +2687,8 @@ struct shell_cmd_help cmd_add_fault_help = {
 
 static int cmd_del_fault(int argc, char *argv[])
 {
-	u8_t fault_id;
-	u8_t i;
+	uint8_t fault_id;
+	uint8_t i;
 
 	if (argc < 2) {
 		memset(cur_faults, 0, sizeof(cur_faults));
@@ -2261,10 +2719,337 @@ struct shell_cmd_help cmd_del_fault_help = {
 	NULL, "[Fault ID]", NULL
 };
 
+#if BLE_MESH_CDB
+struct shell_cmd_help cmd_cdb_create_help = {
+	NULL, "[NetKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_clear_help = {
+	NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_show_help = {
+	NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_node_add_help = {
+	NULL, "<UUID> <addr> <num-elem> "
+		  "<NetKeyIdx> [DevKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_node_del_help = {
+	NULL, "<addr>", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_add_help = {
+	NULL, "<NeyKeyIdx> [<NetKey>]", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_del_help = {
+	NULL, "<NetKeyIdx>", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_add_help = {
+	NULL, "<NetKeyIdx> <AppKeyIdx> [<AppKey>]", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_del_help = {
+	NULL, "<AppKeyIdx>", NULL
+};
+
+static int cmd_cdb_create(int argc, char *argv[])
+{
+	uint8_t net_key[16];
+	size_t len;
+	int err;
+
+	if (argc < 2) {
+		bt_rand(net_key, 16);
+	} else {
+		len = hex2bin(argv[1], net_key, sizeof(net_key));
+		memset(net_key + len, 0, sizeof(net_key) - len);
+	}
+
+	err = bt_mesh_cdb_create(net_key);
+	if (err < 0) {
+		printk("Failed to create CDB (err %d)", err);
+	}
+
+	return 0;
+}
+
+static int cmd_cdb_clear(int argc, char *argv[])
+{
+	bt_mesh_cdb_clear();
+
+	printk("Cleared CDB");
+
+	return 0;
+}
+
+static void cdb_print_nodes(void)
+{
+	char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
+	struct bt_mesh_cdb_node *node;
+	int i, total = 0;
+	bool configured;
+
+	printk("Address  Elements  Flags  %-32s  DevKey", "UUID");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+		node = &bt_mesh_cdb.nodes[i];
+		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		configured = atomic_test_bit(node->flags,
+					     BT_MESH_CDB_NODE_CONFIGURED);
+
+		total++;
+		bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+		bin2hex(node->dev_key, 16, key_hex_str, sizeof(key_hex_str));
+		printk("0x%04x   %-8d  %-5s  %s  %s", node->addr,
+			    node->num_elem, configured ? "C" : "-",
+			    uuid_hex_str, key_hex_str);
+	}
+
+	printk("> Total nodes: %d", total);
+}
+
+static void cdb_print_subnets(void)
+{
+	struct bt_mesh_cdb_subnet *subnet;
+	char key_hex_str[32 + 1];
+	int i, total = 0;
+
+	printk("NetIdx  NetKey");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+		subnet = &bt_mesh_cdb.subnets[i];
+		if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		total++;
+		bin2hex(subnet->keys[0].net_key, 16, key_hex_str,
+			sizeof(key_hex_str));
+		printk("0x%03x   %s", subnet->net_idx,
+			    key_hex_str);
+	}
+
+	printk("> Total subnets: %d", total);
+}
+
+static void cdb_print_app_keys(void)
+{
+	struct bt_mesh_cdb_app_key *app_key;
+	char key_hex_str[32 + 1];
+	int i, total = 0;
+
+	printk("NetIdx  AppIdx  AppKey");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+		app_key = &bt_mesh_cdb.app_keys[i];
+		if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		total++;
+		bin2hex(app_key->keys[0].app_key, 16, key_hex_str,
+			sizeof(key_hex_str));
+		printk("0x%03x   0x%03x   %s",
+			    app_key->net_idx, app_key->app_idx, key_hex_str);
+	}
+
+	printk("> Total app-keys: %d", total);
+}
+
+static int cmd_cdb_show(int argc, char *argv[])
+{
+	if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
+		printk("No valid networks");
+		return 0;
+	}
+
+	printk("Mesh Network Information");
+	printk("========================");
+
+	cdb_print_nodes();
+	printk("---");
+	cdb_print_subnets();
+	printk("---");
+	cdb_print_app_keys();
+
+	return 0;
+}
+
+static int cmd_cdb_node_add(int argc, char *argv[])
+{
+	struct bt_mesh_cdb_node *node;
+	uint8_t uuid[16], dev_key[16];
+	uint16_t addr, net_idx;
+	uint8_t num_elem;
+	size_t len;
+
+	len = hex2bin(argv[1], uuid, sizeof(uuid));
+	memset(uuid + len, 0, sizeof(uuid) - len);
+
+	addr = strtoul(argv[2], NULL, 0);
+	num_elem = strtoul(argv[3], NULL, 0);
+	net_idx = strtoul(argv[4], NULL, 0);
+
+	if (argc < 6) {
+		bt_rand(dev_key, 16);
+	} else {
+		len = hex2bin(argv[5], dev_key, sizeof(dev_key));
+		memset(dev_key + len, 0, sizeof(dev_key) - len);
+	}
+
+	node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
+	if (node == NULL) {
+		printk("Failed to allocate node");
+		return 0;
+	}
+
+	memcpy(node->dev_key, dev_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_node(node);
+	}
+
+	printk("Added node 0x%04x", addr);
+
+	return 0;
+}
+
+static int cmd_cdb_node_del(int argc, char *argv[])
+{
+	struct bt_mesh_cdb_node *node;
+	uint16_t addr;
+
+	addr = strtoul(argv[1], NULL, 0);
+
+	node = bt_mesh_cdb_node_get(addr);
+	if (node == NULL) {
+		printk("No node with address 0x%04x", addr);
+		return 0;
+	}
+
+	bt_mesh_cdb_node_del(node, true);
+
+	printk("Deleted node 0x%04x", addr);
+
+	return 0;
+}
+
+static int cmd_cdb_subnet_add(int argc,
+			     char *argv[])
+{
+	struct bt_mesh_cdb_subnet *sub;
+	uint8_t net_key[16];
+	uint16_t net_idx;
+	size_t len;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+
+	if (argc < 3) {
+		bt_rand(net_key, 16);
+	} else {
+		len = hex2bin(argv[2], net_key, sizeof(net_key));
+		memset(net_key + len, 0, sizeof(net_key) - len);
+	}
+
+	sub = bt_mesh_cdb_subnet_alloc(net_idx);
+	if (sub == NULL) {
+		printk("Could not add subnet");
+		return 0;
+	}
+
+	memcpy(sub->keys[0].net_key, net_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_subnet(sub);
+	}
+
+	printk("Added Subnet 0x%03x", net_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_subnet_del(int argc,
+			     char *argv[])
+{
+	struct bt_mesh_cdb_subnet *sub;
+	uint16_t net_idx;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+
+	sub = bt_mesh_cdb_subnet_get(net_idx);
+	if (sub == NULL) {
+		printk("No subnet with NetIdx 0x%03x", net_idx);
+		return 0;
+	}
+
+	bt_mesh_cdb_subnet_del(sub, true);
+
+	printk("Deleted subnet 0x%03x", net_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_app_key_add(int argc,
+			      char *argv[])
+{
+	struct bt_mesh_cdb_app_key *key;
+	uint16_t net_idx, app_idx;
+	uint8_t app_key[16];
+	size_t len;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+	app_idx = strtoul(argv[2], NULL, 0);
+
+	if (argc < 4) {
+		bt_rand(app_key, 16);
+	} else {
+		len = hex2bin(argv[3], app_key, sizeof(app_key));
+		memset(app_key + len, 0, sizeof(app_key) - len);
+	}
+
+	key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
+	if (key == NULL) {
+		printk("Could not add AppKey");
+		return 0;
+	}
+
+	memcpy(key->keys[0].app_key, app_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_app_key(key);
+	}
+
+	printk("Added AppKey 0x%03x", app_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_app_key_del(int argc,
+			      char *argv[])
+{
+	struct bt_mesh_cdb_app_key *key;
+	uint16_t app_idx;
+
+	app_idx = strtoul(argv[1], NULL, 0);
+
+	key = bt_mesh_cdb_app_key_get(app_idx);
+	if (key == NULL) {
+		printk("No AppKey 0x%03x", app_idx);
+		return 0;
+	}
+
+	bt_mesh_cdb_app_key_del(key, true);
+
+	printk("Deleted AppKey 0x%03x", app_idx);
+
+	return 0;
+}
+#endif
+
 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
 static int cmd_gen_onoff_get(int argc, char *argv[])
 {
-	u8_t state;
+	uint8_t state;
 	int err;
 
 	err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
@@ -2280,8 +3065,8 @@ static int cmd_gen_onoff_get(int argc, char *argv[])
 
 static int cmd_gen_onoff_set(int argc, char *argv[])
 {
-	u8_t state;
-	u8_t val;
+	uint8_t state;
+	uint8_t val;
 	int err;
 
 	if (argc < 2) {
@@ -2307,7 +3092,7 @@ struct shell_cmd_help cmd_gen_onoff_set_help = {
 
 static int cmd_gen_onoff_set_unack(int argc, char *argv[])
 {
-	u8_t val;
+	uint8_t val;
 	int err;
 
 	if (argc < 2) {
@@ -2331,7 +3116,7 @@ struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
 
 static int cmd_gen_level_get(int argc, char *argv[])
 {
-	s16_t state;
+	int16_t state;
 	int err;
 
 	err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
@@ -2347,15 +3132,15 @@ static int cmd_gen_level_get(int argc, char *argv[])
 
 static int cmd_gen_level_set(int argc, char *argv[])
 {
-	s16_t state;
-	s16_t val;
+	int16_t state;
+	int16_t val;
 	int err;
 
 	if (argc < 2) {
 		return -EINVAL;
 	}
 
-	val = (s16_t)strtoul(argv[1], NULL, 0);
+	val = (int16_t)strtoul(argv[1], NULL, 0);
 
 	err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
 				    val, &state);
@@ -2374,14 +3159,14 @@ struct shell_cmd_help cmd_gen_level_set_help = {
 
 static int cmd_gen_level_set_unack(int argc, char *argv[])
 {
-	s16_t val;
+	int16_t val;
 	int err;
 
 	if (argc < 2) {
 		return -EINVAL;
 	}
 
-	val = (s16_t)strtoul(argv[1], NULL, 0);
+	val = (int16_t)strtoul(argv[1], NULL, 0);
 
 	err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
 				    val, NULL);
@@ -2479,7 +3264,7 @@ static const struct shell_cmd mesh_commands[] = {
     {
         .sc_cmd = "reset",
         .sc_cmd_func = cmd_reset,
-        .help = NULL,
+        .help = &cmd_reset_help,
     },
     {
         .sc_cmd = "uuid",
@@ -2605,6 +3390,11 @@ static const struct shell_cmd mesh_commands[] = {
         .sc_cmd_func = cmd_beacon,
         .help = &cmd_beacon_help,
     },
+    {
+        .sc_cmd = "beacon-listen",
+        .sc_cmd_func = cmd_beacon_listen,
+        .help = &cmd_beacon_listen_help,
+    },
     {
         .sc_cmd = "ttl",
         .sc_cmd_func = cmd_ttl,
@@ -2630,16 +3420,51 @@ static const struct shell_cmd mesh_commands[] = {
         .sc_cmd_func = cmd_net_key_add,
         .help = &cmd_net_key_add_help,
     },
+    {
+        .sc_cmd = "net-key-get",
+        .sc_cmd_func = cmd_net_key_get,
+        .help = &cmd_net_key_get_help,
+    },
+    {
+        .sc_cmd = "net-key-del",
+        .sc_cmd_func = cmd_net_key_del,
+        .help = &cmd_net_key_del_help,
+    },
     {
         .sc_cmd = "app-key-add",
         .sc_cmd_func = cmd_app_key_add,
         .help = &cmd_app_key_add_help,
     },
+    {
+        .sc_cmd = "app-key-del",
+        .sc_cmd_func = cmd_app_key_del,
+        .help = &cmd_app_key_del_help,
+    },
+    {
+        .sc_cmd = "app-key-get",
+        .sc_cmd_func = cmd_app_key_get,
+        .help = &cmd_app_key_get_help,
+    },
+    {
+        .sc_cmd = "net-transmit-param",
+        .sc_cmd_func = cmd_net_transmit,
+        .help = &cmd_net_transmit_help,
+    },
     {
         .sc_cmd = "mod-app-bind",
         .sc_cmd_func = cmd_mod_app_bind,
         .help = &cmd_mod_app_bind_help,
     },
+    {
+        .sc_cmd = "mod-app-get",
+        .sc_cmd_func = cmd_mod_app_get,
+        .help = &cmd_mod_app_get_help,
+    },
+    {
+        .sc_cmd = "mod-app-unbind",
+        .sc_cmd_func = cmd_mod_app_unbind,
+        .help = &cmd_mod_app_unbind_help,
+    },
     {
         .sc_cmd = "mod-pub",
         .sc_cmd_func = cmd_mod_pub,
@@ -2660,6 +3485,11 @@ static const struct shell_cmd mesh_commands[] = {
         .sc_cmd_func = cmd_mod_sub_add_va,
         .help = &cmd_mod_sub_add_va_help,
     },
+    {
+        .sc_cmd = "mod-sub-get",
+        .sc_cmd_func = cmd_mod_sub_get,
+        .help = &cmd_mod_sub_get_help,
+    },
     {
         .sc_cmd = "mod-sub-del-va",
         .sc_cmd_func = cmd_mod_sub_del_va,
@@ -2748,6 +3578,46 @@ static const struct shell_cmd mesh_commands[] = {
         .help = &cmd_del_fault_help,
     },
 
+#if MYNEWT_VAL(BLE_MESH_CDB)
+	{
+        .sc_cmd = "cdb-create",
+        .sc_cmd_func = cmd_cdb_create,
+        .help = &cmd_cdb_create_help,
+    },{
+        .sc_cmd = "cdb-clear",
+        .sc_cmd_func = cmd_cdb_clear,
+        .help = &cmd_cdb_clear_help,
+    },{
+        .sc_cmd = "cdb-show",
+        .sc_cmd_func = cmd_cdb_show,
+        .help = &cmd_cdb_show_help,
+    },{
+        .sc_cmd = "cdb-node-add",
+        .sc_cmd_func = cmd_cdb_node_add,
+        .help = &cmd_cdb_node_add_help,
+    },{
+        .sc_cmd = "cdb-node-del",
+        .sc_cmd_func = cmd_cdb_node_del,
+        .help = &cmd_cdb_node_del_help,
+    },{
+        .sc_cmd = "cdb-subnet-add",
+        .sc_cmd_func = cmd_cdb_subnet_add,
+        .help = &cmd_cdb_subnet_add_help,
+    },{
+        .sc_cmd = "cdb-subnet-del",
+        .sc_cmd_func = cmd_cdb_subnet_del,
+        .help = &cmd_cdb_subnet_del_help,
+    },{
+        .sc_cmd = "cdb-app-key-add",
+        .sc_cmd_func = cmd_cdb_app_key_add,
+        .help = &cmd_cdb_app_key_add_help,
+    },{
+        .sc_cmd = "cdb-app-key-add",
+        .sc_cmd_func = cmd_cdb_app_key_del,
+        .help = &cmd_cdb_app_key_del_help,
+    },
+#endif
+
 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
     /* Generic Client Model Operations */
     {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c
new file mode 100644
index 00000000..d6fcfbee
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c
@@ -0,0 +1,666 @@
+/*
+ * 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_NET_KEYS_LOG
+
+#include "log/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "mesh_priv.h"
+#include "lpn.h"
+#include "friend.h"
+#include "proxy.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "beacon.h"
+#include "rpl.h"
+#include "settings.h"
+#include "prov.h"
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+									      enum bt_mesh_key_evt evt);
+#else
+void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+									      enum bt_mesh_key_evt evt);
+#endif
+
+static struct bt_mesh_subnet subnets[CONFIG_BT_MESH_SUBNET_COUNT] = {
+	[0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+		.net_idx = BT_MESH_KEY_UNUSED,
+	},
+};
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+	int i;
+	for (i = 0; i < (sizeof(bt_mesh_subnet_cb_list)/sizeof(void *)); i++) {
+		BT_DBG("%d", i);
+		if (bt_mesh_subnet_cb_list[i]) {
+			bt_mesh_subnet_cb_list[i] (sub, evt);
+		}
+	}
+}
+
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
+{
+	uint8_t flags = 0x00;
+
+	if (sub && (sub->kr_phase == BT_MESH_KR_PHASE_2)) {
+		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;
+}
+
+static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase)
+{
+	BT_DBG("Phase 0x%02x -> 0x%02x", sub->kr_phase, new_phase);
+
+	switch (new_phase) {
+	/* Added second set of keys */
+	case BT_MESH_KR_PHASE_1:
+		sub->kr_phase = new_phase;
+		subnet_evt(sub, BT_MESH_KEY_UPDATED);
+		break;
+	/* Now using new keys for TX */
+	case BT_MESH_KR_PHASE_2:
+		sub->kr_phase = new_phase;
+		subnet_evt(sub, BT_MESH_KEY_SWAPPED);
+		break;
+	/* Revoking keys */
+	case BT_MESH_KR_PHASE_3:
+		if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+			return;
+		}
+		/* __fallthrough; */
+	case BT_MESH_KR_NORMAL:
+		sub->kr_phase = BT_MESH_KR_NORMAL;
+		memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
+		sub->keys[1].valid = 0U;
+		subnet_evt(sub, BT_MESH_KEY_REVOKED);
+		break;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing Updated NetKey persistently");
+		bt_mesh_store_subnet(sub->net_idx);
+	}
+}
+
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key)
+{
+	if (!new_key) {
+		return;
+	}
+
+	if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
+		/* Bluetooth Mesh Profile Specification Section 3.10.4.1:
+		 * Can skip phase 2 if we get KR=0 on new key.
+		 */
+		key_refresh(sub, (kr_flag ? BT_MESH_KR_PHASE_2 :
+					    BT_MESH_KR_PHASE_3));
+	} else if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !kr_flag) {
+		key_refresh(sub, BT_MESH_KR_PHASE_3);
+	}
+}
+
+static struct bt_mesh_subnet *subnet_alloc(uint16_t net_idx)
+{
+	struct bt_mesh_subnet *sub = NULL;
+
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+		/* Check for already existing subnet */
+		if (subnets[i].net_idx == net_idx) {
+			return &subnets[i];
+		}
+
+		if (!sub && subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+			sub = &subnets[i];
+		}
+	}
+
+	return sub;
+}
+
+static void subnet_del(struct bt_mesh_subnet *sub)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_clear_subnet(sub->net_idx);
+	}
+
+	bt_mesh_net_loopback_clear(sub->net_idx);
+
+	subnet_evt(sub, BT_MESH_KEY_DELETED);
+	(void)memset(sub, 0, sizeof(*sub));
+	sub->net_idx = BT_MESH_KEY_UNUSED;
+}
+
+static int msg_cred_create(struct bt_mesh_net_cred *cred, const uint8_t *p,
+			   size_t p_len, const uint8_t key[16])
+{
+	return bt_mesh_k2(key, p, p_len, &cred->nid, cred->enc, cred->privacy);
+}
+
+static int net_keys_create(struct bt_mesh_subnet_keys *keys,
+			   const uint8_t key[16])
+{
+	uint8_t p = 0;
+	int err;
+
+	err = msg_cred_create(&keys->msg, &p, 1, key);
+	if (err) {
+		BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+		return err;
+	}
+
+	memcpy(keys->net, key, 16);
+
+	BT_DBG("NID 0x%02x EncKey %s", keys->msg.nid,
+	       bt_hex(keys->msg.enc, 16));
+	BT_DBG("PrivacyKey %s", bt_hex(keys->msg.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 defined(CONFIG_BT_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));
+
+	keys->valid = 1U;
+
+	return 0;
+}
+
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16])
+{
+	struct bt_mesh_subnet *sub = NULL;
+	int err;
+
+	BT_DBG("0x%03x", net_idx);
+
+	sub = subnet_alloc(net_idx);
+	if (!sub) {
+		return STATUS_INSUFF_RESOURCES;
+	}
+
+	if (sub->net_idx == net_idx) {
+		if (memcmp(key, sub->keys[0].net, 16)) {
+			return STATUS_IDX_ALREADY_STORED;
+		}
+
+		return STATUS_SUCCESS;
+	}
+
+	err = net_keys_create(&sub->keys[0], key);
+	if (err) {
+		return STATUS_UNSPECIFIED;
+	}
+
+	sub->net_idx = net_idx;
+	sub->kr_phase = BT_MESH_KR_NORMAL;
+
+	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;
+	}
+
+	subnet_evt(sub, BT_MESH_KEY_ADDED);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing NetKey persistently");
+		bt_mesh_store_subnet(sub->net_idx);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+bool bt_mesh_subnet_exists(uint16_t net_idx)
+{
+	return !!bt_mesh_subnet_get(net_idx);
+}
+
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16])
+{
+	struct bt_mesh_subnet *sub;
+	int err;
+
+	BT_DBG("0x%03x", net_idx);
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		return STATUS_INVALID_NETKEY;
+	}
+
+	/* 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(key, sub->keys[0].net, 16)) {
+			return STATUS_IDX_ALREADY_STORED;
+		}
+		break;
+	case BT_MESH_KR_PHASE_1:
+		if (!memcmp(key, sub->keys[1].net, 16)) {
+			return STATUS_SUCCESS;
+		}
+		/* __fallthrough; */
+	case BT_MESH_KR_PHASE_2:
+	case BT_MESH_KR_PHASE_3:
+		return STATUS_CANNOT_UPDATE;
+	}
+
+	err = net_keys_create(&sub->keys[1], key);
+	if (err) {
+		return STATUS_CANNOT_UPDATE;
+	}
+
+	key_refresh(sub, BT_MESH_KR_PHASE_1);
+
+	return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_del(uint16_t net_idx)
+{
+	struct bt_mesh_subnet *sub;
+
+	BT_DBG("0x%03x", net_idx);
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		/* This could be a retry of a previous attempt that had its
+		 * response lost, so pretend that it was a success.
+		 */
+		return STATUS_INVALID_NETKEY;
+	}
+
+	subnet_del(sub);
+
+	return STATUS_SUCCESS;
+}
+
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred, uint16_t lpn_addr,
+			       uint16_t frnd_addr, uint16_t lpn_counter,
+			       uint16_t frnd_counter, const uint8_t key[16])
+{
+	uint8_t p[9];
+
+	p[0] = 0x01;
+	sys_put_be16(lpn_addr, p + 1);
+	sys_put_be16(frnd_addr, p + 3);
+	sys_put_be16(lpn_counter, p + 5);
+	sys_put_be16(frnd_counter, p + 7);
+
+	return msg_cred_create(cred, p, sizeof(p), key);
+}
+
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase)
+{
+	/* Table in Bluetooth Mesh Profile Specification Section 4.2.14: */
+	const uint8_t valid_transitions[] = {
+		BIT(BT_MESH_KR_PHASE_3), /* Normal phase: KR is started by key update */
+		BIT(BT_MESH_KR_PHASE_2) | BIT(BT_MESH_KR_PHASE_3), /* Phase 1 */
+		BIT(BT_MESH_KR_PHASE_3), /* Phase 2 */
+		/* Subnet is never in Phase 3 */
+	};
+	struct bt_mesh_subnet *sub;
+
+	BT_DBG("0x%03x", net_idx);
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		*phase = 0x00;
+		return STATUS_INVALID_NETKEY;
+	}
+
+	if (*phase == sub->kr_phase) {
+		return STATUS_SUCCESS;
+	}
+
+	if (sub->kr_phase < ARRAY_SIZE(valid_transitions) &&
+	    valid_transitions[sub->kr_phase] & BIT(*phase)) {
+		key_refresh(sub, *phase);
+
+		*phase = sub->kr_phase;
+
+		return STATUS_SUCCESS;
+	}
+
+	BT_WARN("Invalid KR transition: 0x%02x -> 0x%02x", sub->kr_phase,
+		*phase);
+
+	*phase = sub->kr_phase;
+
+	return STATUS_CANNOT_UPDATE;
+}
+
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase)
+{
+	struct bt_mesh_subnet *sub;
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		*phase = BT_MESH_KR_NORMAL;
+		return STATUS_INVALID_NETKEY;
+	}
+
+	*phase = sub->kr_phase;
+
+	return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+				   enum bt_mesh_feat_state node_id)
+{
+	struct bt_mesh_subnet *sub;
+
+	if (node_id == BT_MESH_FEATURE_NOT_SUPPORTED) {
+		return STATUS_CANNOT_SET;
+	}
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		return STATUS_INVALID_NETKEY;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		return STATUS_FEAT_NOT_SUPP;
+	}
+
+	if (node_id) {
+		bt_mesh_proxy_identity_start(sub);
+	} else {
+		bt_mesh_proxy_identity_stop(sub);
+	}
+
+	bt_mesh_adv_update();
+
+	return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+				   enum bt_mesh_feat_state *node_id)
+{
+	struct bt_mesh_subnet *sub;
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		*node_id = 0x00;
+		return STATUS_INVALID_NETKEY;
+	}
+
+	*node_id = sub->node_id;
+
+	return STATUS_SUCCESS;
+}
+
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip)
+{
+	size_t count = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+		struct bt_mesh_subnet *sub = &subnets[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (skip) {
+			skip--;
+			continue;
+		}
+
+		if (count >= max) {
+			return -ENOMEM;
+		}
+
+		net_idxs[count++] = sub->net_idx;
+	}
+
+	return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
+{
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+		struct bt_mesh_subnet *sub = &subnets[i];
+
+		if (sub->net_idx == net_idx) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+		       const uint8_t old_key[16], const uint8_t new_key[16])
+{
+	const uint8_t *keys[] = { old_key, new_key };
+	struct bt_mesh_subnet *sub;
+
+	sub = subnet_alloc(net_idx);
+	if (!sub) {
+		return -ENOMEM;
+	}
+
+	if (sub->net_idx == net_idx) {
+		return -EALREADY;
+	}
+
+	for (int i = 0; i < ARRAY_SIZE(keys); i++) {
+		if (!keys[i]) {
+			continue;
+		}
+
+		if (net_keys_create(&sub->keys[i], keys[i])) {
+			return -EIO;
+		}
+	}
+
+	sub->net_idx = net_idx;
+	sub->kr_phase = kr_phase;
+
+	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_beacon_update(sub);
+
+	return 0;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+						     void *cb_data),
+					   void *cb_data)
+{
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+		if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (!cb || cb(&subnets[i], cb_data)) {
+			return &subnets[i];
+		}
+	}
+
+	return NULL;
+}
+
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub))
+{
+	size_t count = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+		if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		cb(&subnets[i]);
+		count++;
+	}
+
+	return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub)
+{
+	if (sub) {
+		sub++;
+	} else {
+		sub = &subnets[0];
+	}
+
+	for (int i = 0; i < ARRAY_SIZE(subnets); i++, sub++) {
+		/* Roll over once we reach the end */
+		if (sub == &subnets[ARRAY_SIZE(subnets)]) {
+			sub = &subnets[0];
+		}
+
+		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_net_keys_reset(void)
+{
+	int i;
+
+	/* 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(subnets); i++) {
+		struct bt_mesh_subnet *sub = &subnets[i];
+
+		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+			subnet_del(sub);
+		}
+	}
+}
+
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+			   struct os_mbuf *out,
+			   bool (*cb)(struct bt_mesh_net_rx *rx,
+				      struct os_mbuf *in,
+				      struct os_mbuf *out,
+				      const struct bt_mesh_net_cred *cred))
+{
+	int i, j;
+
+	BT_DBG("");
+
+#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
+	if (bt_mesh_lpn_waiting_update()) {
+		rx->sub = bt_mesh.lpn.sub;
+
+		for (j = 0; j < ARRAY_SIZE(bt_mesh.lpn.cred); j++) {
+			if (!rx->sub->keys[j].valid) {
+				continue;
+			}
+
+			if (cb(rx, in, out, &bt_mesh.lpn.cred[j])) {
+				rx->new_key = (j > 0);
+				rx->friend_cred = 1U;
+				rx->ctx.net_idx = rx->sub->net_idx;
+				return true;
+			}
+		}
+
+		/* LPN Should only receive on the friendship credentials when in
+		 * a friendship.
+		 */
+		return false;
+	}
+#endif
+
+#if MYNEWT_VAL(BLE_MESH_FRIEND)
+	/** Each friendship has unique friendship credentials */
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (!frnd->subnet) {
+			continue;
+		}
+
+		rx->sub = frnd->subnet;
+
+		for (j = 0; j < ARRAY_SIZE(frnd->cred); j++) {
+			if (!rx->sub->keys[j].valid) {
+				continue;
+			}
+
+			if (cb(rx, in, out, &frnd->cred[j])) {
+				rx->new_key = (j > 0);
+				rx->friend_cred = 1U;
+				rx->ctx.net_idx = rx->sub->net_idx;
+				return true;
+			}
+		}
+	}
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(subnets); i++) {
+		rx->sub = &subnets[i];
+		if (rx->sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		for (j = 0; j < ARRAY_SIZE(rx->sub->keys); j++) {
+			if (!rx->sub->keys[j].valid) {
+				continue;
+			}
+
+			if (cb(rx, in, out, &rx->sub->keys[j].msg)) {
+				rx->new_key = (j > 0);
+				rx->friend_cred = 0U;
+				rx->ctx.net_idx = rx->sub->net_idx;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h
new file mode 100644
index 00000000..154b5d4e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BLUETOOTH_MESH_SUBNET_H_
+#define _BLUETOOTH_MESH_SUBNET_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include "mesh/glue.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
+
+/** Which of the two subnet.keys should be used for sending. */
+#define SUBNET_KEY_TX_IDX(sub) ((sub)->kr_phase == BT_MESH_KR_PHASE_2)
+
+struct bt_mesh_net_rx;
+enum bt_mesh_key_evt;
+
+/** Network message encryption credentials */
+struct bt_mesh_net_cred {
+	uint8_t nid;         /* NID */
+	uint8_t enc[16];     /* EncKey */
+	uint8_t privacy[16]; /* PrivacyKey */
+};
+
+/** Subnet instance. */
+struct bt_mesh_subnet {
+	uint32_t beacon_sent;        /* Timestamp of last sent beacon */
+	uint8_t  beacons_last;       /* Number of beacons during last
+				      * observation window
+				      */
+	uint8_t  beacons_cur;        /* Number of beaconds observed during
+				      * currently ongoing window.
+				      */
+
+	uint8_t  beacon_cache[21];   /* Cached last authenticated beacon */
+
+	uint16_t net_idx;            /* NetKeyIndex */
+
+	uint8_t  kr_phase;           /* Key Refresh Phase */
+
+	uint8_t  node_id;            /* Node Identity State */
+	uint32_t node_id_start;      /* Node Identity started timestamp */
+
+	uint8_t  auth[8];            /* Beacon Authentication Value */
+
+	struct bt_mesh_subnet_keys {
+		bool valid;
+		uint8_t net[16];       /* NetKey */
+		struct bt_mesh_net_cred msg;
+		uint8_t net_id[8];     /* Network ID */
+	#if defined(CONFIG_BT_MESH_GATT_PROXY)
+		uint8_t identity[16];  /* IdentityKey */
+	#endif
+		uint8_t beacon[16];    /* BeaconKey */
+	} keys[2];
+};
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+extern void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+									      enum bt_mesh_key_evt evt);
+#else
+extern void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+									      enum bt_mesh_key_evt evt);
+#endif
+
+/** Subnet callback structure. Instantiate with @ref BT_MESH_SUBNET_CB */
+struct bt_mesh_subnet_cb {
+	void (*evt_handler)(struct bt_mesh_subnet *subnet,
+			    enum bt_mesh_key_evt evt);
+};
+
+/** @brief Reset all Network keys. */
+void bt_mesh_net_keys_reset(void);
+
+/** @brief Call cb on every valid Subnet until it returns a non-zero value.
+ *
+ *  @param cb Callback to call, or NULL to return first valid subnet.
+ *  @param cb_data Callback data to pass to callback.
+ *
+ *  @return Subnet that returned non-zero value.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+						     void *cb_data),
+					   void *cb_data);
+
+/** @brief Iterate through all valid Subnets.
+ *
+ *  @param cb Callback to call on every Subnet.
+ *
+ *  @returns The number of valid subnets.
+ */
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub));
+
+/** @brief Get the next valid Subnet.
+ *
+ *  If there's only one valid Subnet, this will be returned on every call.
+ *
+ *  @param sub Previous Subnet, or NULL to get the first valid.
+ *
+ *  @returns Gets the next valid Subnet after @c sub, or NULL if there are no
+ *           valid Subnets.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub);
+
+/** @brief Get a pointer to the Subnet with the given index.
+ *
+ *  @param net_idx Network index to look for.
+ *
+ *  @returns Subnet with index @c net_idx, or NULL if no such Subnet is known.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx);
+
+/** @brief Initialize a new Subnet.
+ *
+ *  @param net_idx Network index of the Subnet.
+ *  @param kr_phase Key refresh phase the Subnet should be in.
+ *  @param key The current network key for the Subnet.
+ *  @param new_key New network key, if available.
+ *
+ *  @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+		       const uint8_t key[16], const uint8_t new_key[16]);
+
+/** @brief Create Friendship credentials.
+ *
+ *  @param cred Credential object to create.
+ *  @param lpn_addr Address of the LPN node in the friendship.
+ *  @param frnd_addr Address of the Friend node in the friendship.
+ *  @param lpn_counter The LPN's counter parameter.
+ *  @param frnd_counter The Friend node's counter parameter.
+ *  @param key Network key to create the Friendship credentials for.
+ *
+ *  @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred,
+			       uint16_t lpn_addr, uint16_t frnd_addr,
+			       uint16_t lpn_counter, uint16_t frnd_counter,
+			       const uint8_t key[16]);
+
+/** @brief Iterate through all valid network credentials to decrypt a message.
+ *
+ *  @param rx Network RX parameters, passed to the callback.
+ *  @param in Input message buffer, passed to the callback.
+ *  @param out Output message buffer, passed to the callback.
+ *  @param cb Callback to call for each known network credential. Iteration
+ *            stops when this callback returns @c true.
+ *
+ *  @returns Whether any of the credentials got a @c true return from the
+ *           callback.
+ */
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+			   struct os_mbuf *out,
+			   bool (*cb)(struct bt_mesh_net_rx *rx,
+				      struct os_mbuf *in,
+				      struct os_mbuf *out,
+				      const struct bt_mesh_net_cred *cred));
+
+/** @brief Get the network flags of the given Subnet.
+ *
+ *  @param sub Subnet to get the network flags of.
+ *
+ *  @returns A bitmap of @ref BT_MESH_NET_FLAG_KR and @ref BT_MESH_NET_FLAG_IVU.
+ */
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
+
+/** @brief Process a Key Refresh event from a beacon.
+ *
+ *  @param sub Subnet the Key Refresh was received on.
+ *  @param kr_flag Key Refresh flag.
+ *  @param new_key Whether the Key Refresh event was received on the new key
+ *                 set.
+ */
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key);
+
+/** @brief Check whether the Subnet has the refreshed keys.
+ *
+ *  @param sub Subnet.
+ *
+ *  @returns Whether the Subnet's second key is valid.
+ */
+static inline bool
+bt_mesh_subnet_has_new_key(const struct bt_mesh_subnet *sub)
+{
+	return sub->kr_phase != BT_MESH_KR_NORMAL;
+}
+
+#endif /* _BLUETOOTH_MESH_SUBNET_H_ */
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
index d0a05376..bde8ff3b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
@@ -13,6 +13,8 @@
 #include "mesh/access.h"
 
 #include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
 #include "testing.h"
 #include "access.h"
 #include "foundation.h"
@@ -31,7 +33,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb)
 	sys_slist_find_and_remove(&cb_slist, &cb->node);
 }
 
-void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
 			   const void *payload, size_t payload_len)
 {
 	struct bt_test_cb *cb;
@@ -44,8 +46,8 @@ void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
 	}
 }
 
-void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
-			      u16_t key_idx)
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+			      uint16_t key_idx)
 {
 	struct bt_test_cb *cb;
 
@@ -56,8 +58,8 @@ void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
 	}
 }
 
-void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
-				u16_t key_idx)
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+				uint16_t key_idx)
 {
 	struct bt_test_cb *cb;
 
@@ -68,7 +70,7 @@ void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
 	}
 }
 
-void bt_test_mesh_prov_invalid_bearer(u8_t opcode)
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode)
 {
 	struct bt_test_cb *cb;
 
@@ -90,14 +92,14 @@ void bt_test_mesh_trans_incomp_timer_exp(void)
 	}
 }
 
-int bt_test_mesh_lpn_group_add(u16_t group)
+int bt_test_mesh_lpn_group_add(uint16_t group)
 {
 	bt_mesh_lpn_group_add(group);
 
 	return 0;
 }
 
-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)
 {
 	bt_mesh_lpn_group_del(groups, groups_count);
 
@@ -114,38 +116,38 @@ int bt_test_mesh_rpl_clear(void)
 void bt_test_print_credentials(void)
 {
 	int i;
-	u8_t nid;
-	const u8_t *enc;
-	const u8_t *priv;
-	struct bt_mesh_subnet *sub;
-	struct bt_mesh_app_key *app_key;
+	struct bt_mesh_cdb_subnet *sub;
+	struct bt_mesh_cdb_app_key *app_key;
+	struct bt_mesh_subnet *subnet;
 
 	console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index);
 	console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16));
 
-	for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i)
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i)
 	{
-		if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) {
+		app_key = &bt_mesh_cdb.app_keys[i];
+		if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
 			continue;
 		}
 
-		sub = &bt_mesh.sub[i];
+		sub = bt_mesh_cdb_subnet_get(i);
 
 		console_printf("Subnet: %d\n", i);
 		console_printf("\tNetKeyIdx: %04x\n",
 			       sub->net_idx);
 		console_printf("\tNetKey: %s\n",
-			       bt_hex(sub->keys[sub->kr_flag].net, 16));
+			       bt_hex(sub->keys[sub->kr_flag].net_key, 16));
 	}
 
-	for (i = 0; i < MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT); ++i)
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i)
 	{
-		if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) {
+		app_key = &bt_mesh_cdb.app_keys[i];
+		if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
 			continue;
 		}
 
-		sub = &bt_mesh.sub[i];
-		app_key = &bt_mesh.app_keys[i];
+		sub = bt_mesh_cdb_subnet_get(i);
+		app_key = &bt_mesh_cdb.app_keys[i];
 
 		console_printf("AppKey: %d\n", i);
 		console_printf("\tNetKeyIdx: %04x\n",
@@ -153,28 +155,27 @@ void bt_test_print_credentials(void)
 		console_printf("\tAppKeyIdx: %04x\n",
 			       app_key->app_idx);
 		console_printf("\tAppKey: %s\n",
-			       bt_hex(app_key->keys[sub->kr_flag].val, 16));
+			       bt_hex(app_key->keys[sub->kr_flag].app_key, 16));
 	}
 
-	for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i)
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i)
 	{
-		if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
+		sub = bt_mesh_cdb_subnet_get(i);
+		app_key = &bt_mesh_cdb.app_keys[i];
+		if (sub[i].net_idx == BT_MESH_KEY_UNUSED) {
 			continue;
 		}
 
-		if (friend_cred_get(&bt_mesh.sub[i], BT_MESH_ADDR_UNASSIGNED,
-				&nid, &enc, &priv)) {
-			return;
-		}
+		subnet = bt_mesh_subnet_get(app_key->net_idx);
 
 		console_printf("Friend cred: %d\n", i);
 		console_printf("\tNetKeyIdx: %04x\n",
-			       bt_mesh.sub[i].net_idx);
-		console_printf("\tNID: %02x\n", nid);
+			           sub[i].net_idx);
+		console_printf("\tNID: %02x\n", subnet->keys->msg.nid);
 		console_printf("\tEncKey: %s\n",
-			       bt_hex(enc, 16));
+			       bt_hex(subnet->keys->msg.enc, 16));
 		console_printf("\tPrivKey: %s\n",
-			       bt_hex(priv, 16));
+			       bt_hex(subnet->keys->msg.privacy, 16));
 	}
 }
 
@@ -187,7 +188,7 @@ int bt_test_shell_init(void)
 #endif
 }
 
-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)
 {
 	struct bt_mesh_model *found_model;
 
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
index 166a9eea..68f7fd72 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
@@ -12,12 +12,12 @@
 #include "mesh/glue.h"
 #include "mesh/access.h"
 
-void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
-			      u16_t key_idx);
-void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
-				u16_t key_idx);
-void bt_test_mesh_prov_invalid_bearer(u8_t opcode);
-void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+			      uint16_t key_idx);
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+				uint16_t key_idx);
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode);
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
 			   const void *payload, size_t payload_len);
 void bt_test_mesh_trans_incomp_timer_exp(void);
 void bt_test_print_credentials(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
index caf1b4f1..00ccb088 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
@@ -13,42 +13,38 @@
 #include <string.h>
 
 #include "mesh/mesh.h"
+#include "mesh/glue.h"
 #include "mesh_priv.h"
 
 #include "crypto.h"
 #include "adv.h"
 #include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
 #include "lpn.h"
 #include "friend.h"
 #include "access.h"
 #include "foundation.h"
 #include "settings.h"
+#include "heartbeat.h"
 #include "transport.h"
 #include "testing.h"
-#include "nodes.h"
 
-/* The transport layer needs at least three buffers for itself to avoid
- * deadlocks. Ensure that there are a sufficient number of advertising
- * buffers available compared to the maximum supported outgoing segment
- * count.
- */
-BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
-
-#define AID_MASK                    ((u8_t)(BIT_MASK(6)))
+#define AID_MASK                    ((uint8_t)(BIT_MASK(6)))
 
 #define SEG(data)                   ((data)[0] >> 7)
 #define AKF(data)                   (((data)[0] >> 6) & 0x01)
 #define AID(data)                   ((data)[0] & AID_MASK)
 #define ASZMIC(data)                (((data)[1] >> 7) & 1)
 
-#define APP_MIC_LEN(aszmic)         ((aszmic) ? 8 : 4)
+#define APP_MIC_LEN(aszmic) ((aszmic) ? BT_MESH_MIC_LONG : BT_MESH_MIC_SHORT)
 
 #define UNSEG_HDR(akf, aid)         ((akf << 6) | (aid & AID_MASK))
 #define SEG_HDR(akf, aid)           (UNSEG_HDR(akf, aid) | 0x80)
 
-#define BLOCK_COMPLETE(seg_n)       (u32_t)(((u64_t)1 << (seg_n + 1)) - 1)
+#define BLOCK_COMPLETE(seg_n)       (uint32_t)(((uint64_t)1 << (seg_n + 1)) - 1)
 
-#define SEQ_AUTH(iv_index, seq)     (((u64_t)iv_index) << 24 | (u64_t)seq)
+#define SEQ_AUTH(iv_index, seq)     (((uint64_t)iv_index) << 24 | (uint64_t)seq)
 
 /* Number of retransmit attempts (after the initial transmit) per segment */
 #define SEG_RETRANSMIT_ATTEMPTS     (MYNEWT_VAL(BLE_MESH_SEG_RETRANSMIT_ATTEMPTS))
@@ -57,59 +53,84 @@ BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
  * We use 400 since 300 is a common send duration for standard HCI, and we
  * need to have a timeout that's bigger than that.
  */
-#define SEG_RETRANSMIT_TIMEOUT(tx) (K_MSEC(400) + 50 * (tx)->ttl)
+#define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) \
+	(MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST) + 50 * (tx)->ttl)
+/* When sending to a group, the messages are not acknowledged, and there's no
+ * reason to delay the repetitions significantly. Delaying by more than 0 ms
+ * to avoid flooding the network.
+ */
+#define SEG_RETRANSMIT_TIMEOUT_GROUP \
+	MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP)
 
+#define SEG_RETRANSMIT_TIMEOUT(tx)                                             \
+	(BT_MESH_ADDR_IS_UNICAST(tx->dst) ?                                    \
+		 SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) :                          \
+		 SEG_RETRANSMIT_TIMEOUT_GROUP)
 /* How long to wait for available buffers before giving up */
 #define BUF_TIMEOUT                 K_NO_WAIT
 
 static struct seg_tx {
-	struct bt_mesh_subnet   *sub;
-	struct os_mbuf          *seg[CONFIG_BT_MESH_TX_SEG_MAX];
-	u64_t                    seq_auth;
-	u16_t                    dst;
-	u8_t                     seg_n:5,       /* Last segment index */
-				 new_key:1;     /* New/old key */
-	u8_t                     nack_count;    /* Number of unacked segs */
-	u8_t                     ttl;
+	struct bt_mesh_subnet *sub;
+	void                  *seg[CONFIG_BT_MESH_TX_SEG_MAX];
+	uint64_t              seq_auth;
+	uint16_t              src;
+	uint16_t              dst;
+	uint16_t              len;
+	uint8_t               hdr;
+	uint8_t               xmit;
+	uint8_t               seg_n;         /* Last segment index */
+	uint8_t               seg_o;         /* Segment being sent */
+	uint8_t               nack_count;    /* Number of unacked segs */
+	uint8_t               attempts;      /* Remaining tx attempts */
+	uint8_t               ttl;           /* Transmitted TTL value */
+	uint8_t               seg_pending;   /* Number of segments pending */
+	uint8_t               blocked:1,     /* Blocked by ongoing tx */
+					      ctl:1,         /* Control packet */
+			      		  aszmic:1,      /* MIC size */
+			      		  started:1,     /* Start cb called */
+			      		  sending:1,     /* Sending is in progress */
+			      		  friend_cred:1; /* Using Friend credentials */
 	const struct bt_mesh_send_cb *cb;
-	void                    *cb_data;
-	struct k_delayed_work    retransmit; /* Retransmit timer */
+	void                  *cb_data;
+	struct k_delayed_work retransmit; /* Retransmit timer */
 } seg_tx[MYNEWT_VAL(BLE_MESH_TX_SEG_MSG_COUNT)];
 
 static struct seg_rx {
 	struct bt_mesh_subnet   *sub;
-	u64_t                    seq_auth;
-	u8_t                     seg_n:5,
-				 ctl:1,
-				 in_use:1,
-				 obo:1;
-	u8_t                     hdr;
-	u8_t                     ttl;
-	u16_t                    src;
-	u16_t                    dst;
-	u32_t                    block;
-	u32_t                    last;
+	void                    *seg[CONFIG_BT_MESH_RX_SEG_MAX];
+	uint64_t                    seq_auth;
+	uint16_t                    src;
+	uint16_t                    dst;
+	uint16_t                    len;
+	uint8_t                     hdr;
+	uint8_t                     seg_n:5,
+							 ctl:1,
+							 in_use:1,
+							 obo:1;
+	uint8_t                     ttl;
+	uint32_t                    block;
+	uint32_t                    last;
 	struct k_delayed_work    ack;
-	struct os_mbuf    *buf;
-} seg_rx[MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)] = {
-	[0 ... (MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT) - 1)] = { 0 },
+} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
+
+char _k_mem_slab_buffer_[(BT_MESH_APP_SEG_SDU_MAX*CONFIG_BT_MESH_SEG_BUFS)];
+
+struct k_mem_slab segs = {
+	.num_blocks = CONFIG_BT_MESH_SEG_BUFS,
+	.block_size = BT_MESH_APP_SEG_SDU_MAX,
+	.buffer = _k_mem_slab_buffer_,
+	.free_list = NULL,
+	.num_used = 0
 };
 
-static u16_t hb_sub_dst = BT_MESH_ADDR_UNASSIGNED;
-
-void bt_mesh_set_hb_sub_dst(u16_t addr)
-{
-	hb_sub_dst = addr;
-}
+static struct bt_mesh_va virtual_addrs[CONFIG_BT_MESH_LABEL_COUNT];
 
 static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu,
-		      const struct bt_mesh_send_cb *cb, void *cb_data)
+		      const struct bt_mesh_send_cb *cb, void *cb_data,
+		      const uint8_t *ctl_op)
 {
 	struct os_mbuf *buf;
 
-	BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
-	       tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->om_len);
-
 	buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
 	if (!buf) {
 		BT_ERR("Out of network buffers");
@@ -118,7 +139,9 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu,
 
 	net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
 
-	if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
+	if (ctl_op) {
+		net_buf_add_u8(buf, TRANS_CTL_HDR(*ctl_op, 0));
+	} else if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
 		net_buf_add_u8(buf, UNSEG_HDR(0, 0));
 	} else {
 		net_buf_add_u8(buf, UNSEG_HDR(1, tx->aid));
@@ -156,6 +179,15 @@ send:
 	return bt_mesh_net_send(tx, buf, cb, cb_data);
 }
 
+static inline uint8_t seg_len(bool ctl)
+{
+	if (ctl) {
+		return BT_MESH_CTL_SEG_SDU_MAX;
+	} else {
+		return BT_MESH_APP_SEG_SDU_MAX;
+	}
+}
+
 bool bt_mesh_tx_in_progress(void)
 {
 	int i;
@@ -169,6 +201,41 @@ bool bt_mesh_tx_in_progress(void)
 	return false;
 }
 
+static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
+{
+	k_mem_slab_free(&segs, (void **)&tx->seg[seg_idx]);
+	tx->seg[seg_idx] = NULL;
+	tx->nack_count--;
+}
+
+static bool seg_tx_blocks(struct seg_tx *tx, uint16_t src, uint16_t dst)
+{
+	return (tx->src == src) && (tx->dst == dst);
+}
+
+static void seg_tx_unblock_check(struct seg_tx *tx)
+{
+	struct seg_tx *blocked = NULL;
+	int i;
+
+	/* Unblock the first blocked tx with the same params. */
+	for (i = 0; i < ARRAY_SIZE(seg_tx); ++i) {
+		if (&seg_tx[i] != tx &&
+		    seg_tx[i].blocked &&
+		    seg_tx_blocks(tx, seg_tx[i].src, seg_tx[i].dst) &&
+		    (!blocked || seg_tx[i].seq_auth < blocked->seq_auth)) {
+			blocked = &seg_tx[i];
+		}
+	}
+
+	if (blocked) {
+		BT_DBG("Unblocked 0x%04x",
+		       (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK));
+		blocked->blocked = false;
+		k_delayed_work_submit(&blocked->retransmit, 0);
+	}
+}
+
 static void seg_tx_reset(struct seg_tx *tx)
 {
 	int i;
@@ -179,22 +246,19 @@ static void seg_tx_reset(struct seg_tx *tx)
 	tx->cb_data = NULL;
 	tx->seq_auth = 0;
 	tx->sub = NULL;
+	tx->src = BT_MESH_ADDR_UNASSIGNED;
 	tx->dst = BT_MESH_ADDR_UNASSIGNED;
+	tx->blocked = false;
 
-	if (!tx->nack_count) {
-		return;
-	}
-
-	for (i = 0; i <= tx->seg_n; i++) {
+	for (i = 0; i <= tx->seg_n && tx->nack_count; i++) {
 		if (!tx->seg[i]) {
 			continue;
 		}
 
-		net_buf_unref(tx->seg[i]);
-		tx->seg[i] = NULL;
+		seg_tx_done(tx, i);
 	}
 
-	tx->nack_count = 0U;
+	tx->nack_count = 0;
 
 	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) {
 		BT_DBG("Proceding with pending IV Update");
@@ -202,41 +266,60 @@ static void seg_tx_reset(struct seg_tx *tx)
 		/* bt_mesh_net_iv_update() will re-enable the flag if this
 		 * wasn't the only transfer.
 		 */
-		if (bt_mesh_net_iv_update(bt_mesh.iv_index, false)) {
-			bt_mesh_net_sec_update(NULL);
-		}
+		bt_mesh_net_iv_update(bt_mesh.iv_index, false);
 	}
 }
 
 static inline void seg_tx_complete(struct seg_tx *tx, int err)
 {
-	if (tx->cb && tx->cb->end) {
-		tx->cb->end(err, tx->cb_data);
-	}
+	const struct bt_mesh_send_cb *cb = tx->cb;
+	void *cb_data = tx->cb_data;
+
+	seg_tx_unblock_check(tx);
 
 	seg_tx_reset(tx);
-}
 
-static void seg_first_send_start(u16_t duration, int err, void *user_data)
-{
-	struct seg_tx *tx = user_data;
-
-	if (tx->cb && tx->cb->start) {
-		tx->cb->start(duration, err, tx->cb_data);
+	if (cb && cb->end) {
+		cb->end(err, cb_data);
 	}
 }
 
-static void seg_send_start(u16_t duration, int err, void *user_data)
+static void schedule_retransmit(struct seg_tx *tx)
+{
+	if (!tx->nack_count) {
+		return;
+	}
+
+	if (--tx->seg_pending || tx->sending) {
+		return;
+	}
+
+	BT_DBG("");
+
+	/* If we haven't gone through all the segments for this attempt yet,
+	 * (likely because of a buffer allocation failure or because we
+	 * called this from inside bt_mesh_net_send), we should continue the
+	 * retransmit immediately, as we just freed up a tx buffer.
+	 */
+	k_delayed_work_submit(&tx->retransmit,
+			      tx->seg_o ? 0 : K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
+}
+
+static void seg_send_start(uint16_t duration, int err, void *user_data)
 {
 	struct seg_tx *tx = user_data;
 
+	if (!tx->started && tx->cb && tx->cb->start) {
+		tx->cb->start(duration, err, tx->cb_data);
+		tx->started = 1U;
+	}
+
 	/* If there's an error in transmitting the 'sent' callback will never
 	 * be called. Make sure that we kick the retransmit timer also in this
 	 * case since otherwise we risk the transmission of becoming stale.
 	 */
 	if (err) {
-		k_delayed_work_submit(&tx->retransmit,
-				      SEG_RETRANSMIT_TIMEOUT(tx));
+		schedule_retransmit(tx);
 	}
 }
 
@@ -244,52 +327,107 @@ static void seg_sent(int err, void *user_data)
 {
 	struct seg_tx *tx = user_data;
 
-	k_delayed_work_submit(&tx->retransmit,
-			      SEG_RETRANSMIT_TIMEOUT(tx));
+	schedule_retransmit(tx);
 }
 
-static const struct bt_mesh_send_cb first_sent_cb = {
-	.start = seg_first_send_start,
-	.end = seg_sent,
-};
-
 static const struct bt_mesh_send_cb seg_sent_cb = {
 	.start = seg_send_start,
 	.end = seg_sent,
 };
 
+static void seg_tx_buf_build(struct seg_tx *tx, uint8_t seg_o,
+			     struct os_mbuf *buf)
+{
+	uint16_t seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
+	uint8_t len = MIN(seg_len(tx->ctl), tx->len - (seg_len(tx->ctl) * seg_o));
+
+	net_buf_simple_add_u8(buf, tx->hdr);
+	net_buf_simple_add_u8(buf, (tx->aszmic << 7) | seq_zero >> 6);
+	net_buf_simple_add_u8(buf, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
+	net_buf_simple_add_u8(buf, ((seg_o & 0x07) << 5) | tx->seg_n);
+	net_buf_simple_add_mem(buf, tx->seg[seg_o], len);
+}
+
 static void seg_tx_send_unacked(struct seg_tx *tx)
 {
-	int i, err;
+	if (!tx->nack_count) {
+		return;
+	}
 
-	for (i = 0; i <= tx->seg_n; i++) {
-		struct os_mbuf *seg = tx->seg[i];
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = tx->sub->net_idx,
+		/* App idx only used by network to detect control messages: */
+		.app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0),
+		.addr = tx->dst,
+		.send_rel = true,
+		.send_ttl = tx->ttl,
+	};
+	struct bt_mesh_net_tx net_tx = {
+		.sub = tx->sub,
+		.ctx = &ctx,
+		.src = tx->src,
+		.xmit = tx->xmit,
+		.friend_cred = tx->friend_cred,
+		.aid = tx->hdr & AID_MASK,
+	};
 
-		if (!seg) {
-			continue;
-		}
-
-		if (BT_MESH_ADV(seg)->busy) {
-			BT_DBG("Skipping segment that's still advertising");
-			continue;
-		}
-
-		if (!(BT_MESH_ADV(seg)->seg.attempts--)) {
+	if (!tx->attempts) {
+		if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
 			BT_ERR("Ran out of retransmit attempts");
 			seg_tx_complete(tx, -ETIMEDOUT);
-			return;
+		} else {
+			/* Segmented sending to groups doesn't have acks, so
+			 * running out of attempts is the expected behavior.
+			 */
+			seg_tx_complete(tx, 0);
 		}
 
-		BT_DBG("resending %u/%u", i, tx->seg_n);
+		return;
+	}
 
-		err = bt_mesh_net_resend(tx->sub, seg, tx->new_key,
-					 &seg_sent_cb, tx);
+	BT_DBG("SeqZero: 0x%04x Attempts: %u",
+	       (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts);
+
+	tx->sending = 1U;
+
+	for (; tx->seg_o <= tx->seg_n; tx->seg_o++) {
+		struct os_mbuf *seg;
+		int err;
+
+		if (!tx->seg[tx->seg_o]) {
+			continue;
+		}
+
+		seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit,
+					 BUF_TIMEOUT);
+		if (!seg) {
+			BT_DBG("Allocating segment failed");
+			goto end;
+		}
+
+		net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
+		seg_tx_buf_build(tx, tx->seg_o, seg);
+
+		tx->seg_pending++;
+
+		BT_DBG("Sending %u/%u", tx->seg_o, tx->seg_n);
+
+		err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx);
 		if (err) {
-			BT_ERR("Sending segment failed");
-			seg_tx_complete(tx, -EIO);
-			return;
+			BT_DBG("Sending segment failed");
+			tx->seg_pending--;
+			goto end;
 		}
 	}
+	tx->seg_o = 0U;
+	tx->attempts--;
+end:
+	if (!tx->seg_pending) {
+		k_delayed_work_submit(&tx->retransmit,
+					  SEG_RETRANSMIT_TIMEOUT(tx));
+	}
+
+	tx->sending = 0U;
 }
 
 static void seg_retransmit(struct ble_npl_event *work)
@@ -299,31 +437,24 @@ static void seg_retransmit(struct ble_npl_event *work)
 }
 
 static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
-		    const struct bt_mesh_send_cb *cb, void *cb_data)
+		    const struct bt_mesh_send_cb *cb, void *cb_data,
+		    uint8_t *ctl_op)
 {
-	u8_t seg_hdr, seg_o;
-	u16_t seq_zero;
+	bool blocked = false;
 	struct seg_tx *tx;
+	uint8_t seg_o;
 	int i;
 
 	BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
 	       net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx,
 	       net_tx->aszmic, sdu->om_len);
 
-	if (sdu->om_len < 1) {
-		BT_ERR("Zero-length SDU not allowed");
-		return -EINVAL;
-	}
-
-	if (sdu->om_len > BT_MESH_TX_SDU_MAX) {
-		BT_ERR("Not enough segment buffers for length %u", sdu->om_len);
-		return -EMSGSIZE;
-	}
-
 	for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) {
-		if (!seg_tx[i].nack_count) {
+		if (seg_tx[i].nack_count) {
+			blocked |= seg_tx_blocks(&seg_tx[i], net_tx->src,
+						 net_tx->ctx->addr);
+		} else if (!tx) {
 			tx = &seg_tx[i];
-			break;
 		}
 	}
 
@@ -332,31 +463,37 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
 		return -EBUSY;
 	}
 
-	if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
-		seg_hdr = SEG_HDR(0, 0);
+	if (ctl_op) {
+		tx->hdr = TRANS_CTL_HDR(*ctl_op, 1);
+	} else if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
+		tx->hdr = SEG_HDR(0, 0);
 	} else {
-		seg_hdr = SEG_HDR(1, net_tx->aid);
+		tx->hdr = SEG_HDR(1, net_tx->aid);
 	}
 
-	seg_o = 0;
+	tx->src = net_tx->src;
 	tx->dst = net_tx->ctx->addr;
-	tx->seg_n = (sdu->om_len - 1) / 12;
+	tx->seg_n = (sdu->om_len - 1) / seg_len(!!ctl_op);
+	tx->seg_o = 0;
+	tx->len = sdu->om_len;
 	tx->nack_count = tx->seg_n + 1;
 	tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
 	tx->sub = net_tx->sub;
-	tx->new_key = net_tx->sub->kr_flag;
 	tx->cb = cb;
 	tx->cb_data = cb_data;
+	tx->attempts = SEG_RETRANSMIT_ATTEMPTS;
+	tx->seg_pending = 0;
+	tx->xmit = net_tx->xmit;
+	tx->aszmic = net_tx->aszmic;
+	tx->friend_cred = net_tx->friend_cred;
+	tx->blocked = blocked;
+	tx->started = 0;
+	tx->ctl = !!ctl_op;
 
-	if (net_tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
-		tx->ttl = bt_mesh_default_ttl_get();
-	} else {
-		tx->ttl = net_tx->ctx->send_ttl;
-	}
+	tx->ttl = net_tx->ctx->send_ttl;
 
-	seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
-
-	BT_DBG("SeqZero 0x%04x", seq_zero);
+	BT_DBG("SeqZero 0x%04x (segs: %u)",
+	       (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->nack_count);
 
 	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
 	    !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src,
@@ -370,66 +507,48 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
 	}
 
 	for (seg_o = 0; sdu->om_len; seg_o++) {
-		struct os_mbuf *seg;
-		u16_t len;
+		void *buf;
+		uint16_t len;
 		int err;
 
-		seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, net_tx->xmit,
-					 BUF_TIMEOUT);
-		if (!seg) {
+		err = k_mem_slab_alloc(&segs, &buf);
+		if (err) {
 			BT_ERR("Out of segment buffers");
 			seg_tx_reset(tx);
 			return -ENOBUFS;
 		}
 
-		BT_MESH_ADV(seg)->seg.attempts = SEG_RETRANSMIT_ATTEMPTS;
+		len = MIN(sdu->om_len, seg_len(!!ctl_op));
+		memcpy(buf, net_buf_simple_pull_mem(sdu, len), len);
+		BT_DBG("seg %u: %s", seg_o, bt_hex(buf, len));
 
-		net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
-
-		net_buf_add_u8(seg, seg_hdr);
-		net_buf_add_u8(seg, (net_tx->aszmic << 7) | seq_zero >> 6);
-		net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) |
-				     (seg_o >> 3)));
-		net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
-
-		len = min(sdu->om_len, 12);
-		net_buf_add_mem(seg, sdu->om_data, len);
-		net_buf_simple_pull(sdu, len);
+		tx->seg[seg_o] = buf;
 
 		if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
 			enum bt_mesh_friend_pdu_type type;
 
+			struct os_mbuf *seg = NET_BUF_SIMPLE(16);
+			seg_tx_buf_build(tx, seg_o, seg);
+
 			if (seg_o == tx->seg_n) {
 				type = BT_MESH_FRIEND_PDU_COMPLETE;
 			} else {
 				type = BT_MESH_FRIEND_PDU_PARTIAL;
 			}
 
-			if (bt_mesh_friend_enqueue_tx(net_tx, type,
-						      &tx->seq_auth,
-						      tx->seg_n + 1,
-						      seg) &&
+			if (bt_mesh_friend_enqueue_tx(
+				    net_tx, type, ctl_op ? NULL : &tx->seq_auth,
+				    tx->seg_n + 1, seg) &&
 			    BT_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
 				/* PDUs for a specific Friend should only go
 				 * out through the Friend Queue.
 				 */
-				net_buf_unref(seg);
-				continue;
+				k_mem_slab_free(&segs, &buf);
+				tx->seg[seg_o] = NULL;
 			}
+			os_mbuf_free_chain(seg);
 		}
 
-		tx->seg[seg_o] = net_buf_ref(seg);
-
-		BT_DBG("Sending %u/%u", seg_o, tx->seg_n);
-
-		err = bt_mesh_net_send(net_tx, seg,
-				       seg_o ? &seg_sent_cb : &first_sent_cb,
-				       tx);
-		if (err) {
-			BT_ERR("Sending segment failed");
-			seg_tx_reset(tx);
-			return err;
-		}
 	}
 
 	/* This can happen if segments only went into the Friend Queue */
@@ -441,8 +560,21 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
 		 * with the Friend Queue.
 		 */
 		send_cb_finalize(cb, cb_data);
+		return 0;
 	}
 
+	if (blocked) {
+		/* Move the sequence number, so we don't end up creating
+		 * another segmented transmission with the same SeqZero while
+		 * this one is blocked.
+		 */
+		bt_mesh_next_seq();
+		BT_DBG("Blocked.");
+		return 0;
+	}
+
+	seg_tx_send_unacked(tx);
+
 	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
 	    bt_mesh_lpn_established()) {
 		bt_mesh_lpn_poll();
@@ -451,50 +583,75 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
 	return 0;
 }
 
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx)
+static int trans_encrypt(const struct bt_mesh_net_tx *tx, const uint8_t *key,
+			 struct os_mbuf *msg)
 {
-	int i;
+	struct bt_mesh_app_crypto_ctx crypto = {
+		.dev_key = BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
+		.aszmic = tx->aszmic,
+		.src = tx->src,
+		.dst = tx->ctx->addr,
+		.seq_num = bt_mesh.seq,
+		.iv_index = BT_MESH_NET_IVI_TX,
+	};
 
-	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 key;
-		}
+	if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+		crypto.ad = bt_mesh_va_label_get(tx->ctx->addr);
 	}
 
-	return NULL;
+	return bt_mesh_app_encrypt(key, &crypto, msg);
 }
 
 int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
 		       const struct bt_mesh_send_cb *cb, void *cb_data)
 {
-	const u8_t *key;
-	u8_t *ad;
-	u8_t aid;
+	const uint8_t *key;
+	uint8_t aid;
 	int err;
 
+	if (msg->om_len < 1) {
+		BT_ERR("Zero-length SDU not allowed");
+		return -EINVAL;
+	}
+
+	if (msg->om_len > BT_MESH_TX_SDU_MAX) {
+		BT_ERR("Not enough segment buffers for length %u", msg->om_len);
+		return -EMSGSIZE;
+	}
+
 	if (net_buf_simple_tailroom(msg) < 4) {
 		BT_ERR("Insufficient tailroom for Transport MIC");
 		return -EINVAL;
 	}
 
-	if (msg->om_len > 11) {
-		tx->ctx->send_rel = 1;
+	if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+		tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+	} else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+		BT_ERR("TTL too large (max 127)");
+		return -EINVAL;
+	}
+
+	if (msg->om_len > BT_MESH_SDU_UNSEG_MAX) {
 		tx->ctx->send_rel = true;
 	}
 
+	if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+	    (!BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) &&
+	     BT_MESH_IS_DEV_KEY(tx->ctx->app_idx))) {
+		BT_ERR("Invalid destination address");
+		return -EINVAL;
+	}
+
 	BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx,
 	       tx->ctx->app_idx, tx->ctx->addr);
 	BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
 
-	err = bt_mesh_app_key_get(tx->sub, tx->ctx->app_idx,
-				  tx->ctx->addr, &key, &aid);
+	err = bt_mesh_keys_resolve(tx->ctx, &tx->sub, &key, &aid);
 	if (err) {
 		return err;
 	}
 
+	tx->xmit = bt_mesh_net_transmit_get();
 	tx->aid = aid;
 
 	if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
@@ -503,115 +660,80 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
 		tx->aszmic = 1;
 	}
 
-	if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
-		ad = bt_mesh_label_uuid_get(tx->ctx->addr);
-	} else {
-		ad = NULL;
-	}
-
-	err = bt_mesh_app_encrypt(key, BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
-				  tx->aszmic, msg, ad, tx->src, tx->ctx->addr,
-				  bt_mesh.seq, BT_MESH_NET_IVI_TX);
+	err = trans_encrypt(tx, key, msg);
 	if (err) {
 		return err;
 	}
 
 	if (tx->ctx->send_rel) {
-		err = send_seg(tx, msg, cb, cb_data);
+		err = send_seg(tx, msg, cb, cb_data, NULL);
 	} else {
-		err = send_unseg(tx, msg, cb, cb_data);
+		err = send_unseg(tx, msg, cb, cb_data, NULL);
 	}
 
 	return err;
 }
 
-static void update_rpl(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).
- */
-static bool is_replay(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
+static void seg_rx_assemble(struct seg_rx *rx, struct os_mbuf *buf,
+			    uint8_t aszmic)
 {
 	int i;
 
-	/* Don't bother checking messages from ourselves */
-	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
-		return false;
+	net_buf_simple_reset(buf);
+
+	for (i = 0; i <= rx->seg_n; i++) {
+		net_buf_simple_add_mem(buf, rx->seg[i],
+				       MIN(seg_len(rx->ctl),
+					   rx->len - (i * seg_len(rx->ctl))));
 	}
 
-	/* The RPL is used only for the local node */
-	if (!rx->local_match) {
-		return false;
+	/* Adjust the length to not contain the MIC at the end */
+	if (!rx->ctl) {
+		buf->om_len -= APP_MIC_LEN(aszmic);
 	}
-
-	for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
-		struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
-		/* Empty slot */
-		if (!rpl->src) {
-			if (match) {
-				*match = rpl;
-			} else {
-				update_rpl(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 {
-					update_rpl(rpl, rx);
-				}
-
-				return false;
-			} else {
-				return true;
-			}
-		}
-	}
-
-	BT_ERR("RPL is full!");
-	return true;
 }
 
-static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
-		    u8_t aszmic, struct os_mbuf *buf)
+struct decrypt_ctx {
+	struct bt_mesh_app_crypto_ctx crypto;
+	struct os_mbuf *buf;
+	struct os_mbuf *sdu;
+	struct seg_rx *seg;
+};
+
+static int sdu_try_decrypt(struct bt_mesh_net_rx *rx, const uint8_t key[16],
+			   void *cb_data)
 {
-	struct os_mbuf *sdu =
-		NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX) - 4);
-	u8_t *ad;
-	u16_t i;
-	int err = 0;
+	const struct decrypt_ctx *ctx = cb_data;
 
-	BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr));
-	BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
-	if (buf->om_len < 1 + APP_MIC_LEN(aszmic)) {
-		BT_ERR("Too short SDU + MIC");
-		err = -EINVAL;
-		goto done;
+	if (ctx->seg) {
+		seg_rx_assemble(ctx->seg, ctx->buf, ctx->crypto.aszmic);
 	}
 
+	net_buf_simple_reset(ctx->sdu);
+
+	return bt_mesh_app_decrypt(key, &ctx->crypto, ctx->buf, ctx->sdu);
+}
+
+static int sdu_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, uint8_t aszmic,
+		    struct os_mbuf *buf, struct os_mbuf *sdu,
+		    struct seg_rx *seg)
+{
+	struct decrypt_ctx ctx = {
+		.crypto = {
+			.dev_key = !AKF(&hdr),
+			.aszmic = aszmic,
+			.src = rx->ctx.addr,
+			.dst = rx->ctx.recv_dst,
+			.seq_num = seg ? (seg->seq_auth & 0xffffff) : rx->seq,
+			.iv_index = BT_MESH_NET_IVI_RX(rx),
+		},
+		.buf = buf,
+		.sdu = sdu,
+		.seg = seg,
+	};
+
+	BT_DBG("AKF %u AID 0x%02x", !ctx.crypto.dev_key, AID(&hdr));
+
 	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
 		BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
 		       rx->ctx.recv_dst);
@@ -619,109 +741,26 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
 	}
 
 	if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
-		ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
-	} else {
-		ad = NULL;
+		ctx.crypto.ad = bt_mesh_va_label_get(rx->ctx.recv_dst);
 	}
 
-	/* Adjust the length to not contain the MIC at the end */
-	buf->om_len -= APP_MIC_LEN(aszmic);
-
-	if (!AKF(&hdr)) {
-		net_buf_simple_init(sdu, 0);
-		err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, buf,
-					  sdu, ad, rx->ctx.addr,
-					  rx->ctx.recv_dst, seq,
-					  BT_MESH_NET_IVI_RX(rx));
-		if (err) {
-			BT_WARN("Unable to decrypt with local DevKey");
-		} else {
-			rx->ctx.app_idx = BT_MESH_KEY_DEV_LOCAL;
-			bt_mesh_model_recv(rx, sdu);
-			goto done;
-		}
-
-		if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
-			struct bt_mesh_node *node;
-
-			/*
-			 * There is no way of knowing if we should use our
-			 * local DevKey or the remote DevKey to decrypt the
-			 * message so we must try both.
-			 */
-
-			node = bt_mesh_node_find(rx->ctx.addr);
-			if (node == NULL) {
-				BT_ERR("No node found for addr 0x%04x",
-				       rx->ctx.addr);
-				return -EINVAL;
-			}
-
-			net_buf_simple_init(sdu, 0);
-			err = bt_mesh_app_decrypt(node->dev_key, true, aszmic,
-						  buf, sdu, ad, rx->ctx.addr,
-						  rx->ctx.recv_dst, seq,
-						  BT_MESH_NET_IVI_RX(rx));
-			if (err) {
-				BT_ERR("Unable to decrypt with node DevKey");
-				return -EINVAL;
-			}
-
-			rx->ctx.app_idx = BT_MESH_KEY_DEV_REMOTE;
-			bt_mesh_model_recv(rx, sdu);
-			return 0;
-		}
-
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
-		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-		struct bt_mesh_app_keys *keys;
-
-		/* Check that this AppKey matches received net_idx */
-		if (key->net_idx != rx->sub->net_idx) {
-			continue;
-		}
-
-		if (rx->new_key && key->updated) {
-			keys = &key->keys[1];
-		} else {
-			keys = &key->keys[0];
-		}
-
-		/* Check that the AppKey ID matches */
-		if (AID(&hdr) != keys->id) {
-			continue;
-		}
-
-		net_buf_simple_init(sdu, 0);
-		err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf,
-					  sdu, ad, rx->ctx.addr,
-					  rx->ctx.recv_dst, seq,
-					  BT_MESH_NET_IVI_RX(rx));
-		if (err) {
-			BT_WARN("Unable to decrypt with AppKey 0x%03x",
-				key->app_idx);
-			continue;
-
-		}
-
-		rx->ctx.app_idx = key->app_idx;
-
-		bt_mesh_model_recv(rx, sdu);
+	rx->ctx.app_idx = bt_mesh_app_key_find(ctx.crypto.dev_key, AID(&hdr),
+					       rx, sdu_try_decrypt, &ctx);
+	if (rx->ctx.app_idx == BT_MESH_KEY_UNUSED) {
+		BT_DBG("No matching AppKey");
 		goto done;
 	}
 
-	BT_WARN("No matching AppKey");
+	BT_DBG("Decrypted (AppIdx: 0x%03x)", rx->ctx.app_idx);
+
+	bt_mesh_model_recv(rx, sdu);
 
-	err = -EINVAL;
 done:
     os_mbuf_free_chain(sdu);
-    return err;
+    return 0;
 }
 
-static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
+static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t addr)
 {
 	struct seg_tx *tx;
 	int i;
@@ -751,14 +790,14 @@ static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
 	return NULL;
 }
 
-static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
-		     struct os_mbuf *buf, u64_t *seq_auth)
+static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
+		     struct os_mbuf *buf, uint64_t *seq_auth)
 {
 	struct seg_tx *tx;
 	unsigned int bit;
-	u32_t ack;
-	u16_t seq_zero;
-	u8_t obo;
+	uint32_t ack;
+	uint16_t seq_zero;
+	uint8_t obo;
 
 	if (buf->om_len < 6) {
 		BT_ERR("Too short ack message");
@@ -787,6 +826,11 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
 		return -EINVAL;
 	}
 
+	if (!BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+		BT_ERR("Received ack for group seg");
+		return -EINVAL;
+	}
+
 	*seq_auth = tx->seq_auth;
 
 	if (!ack) {
@@ -805,9 +849,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
 	while ((bit = find_lsb_set(ack))) {
 		if (tx->seg[bit - 1]) {
 			BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
-			net_buf_unref(tx->seg[bit - 1]);
-			tx->seg[bit - 1] = NULL;
-			tx->nack_count--;
+			seg_tx_done(tx, bit - 1);
 		}
 
 		ack &= ~BIT(bit - 1);
@@ -823,40 +865,10 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
 	return 0;
 }
 
-static int trans_heartbeat(struct bt_mesh_net_rx *rx,
-			   struct os_mbuf *buf)
+static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr,
+		    struct os_mbuf *buf, uint64_t *seq_auth)
 {
-	u8_t init_ttl, hops;
-	u16_t feat;
-
-	if (buf->om_len < 3) {
-		BT_ERR("Too short heartbeat message");
-		return -EINVAL;
-	}
-
-	if (rx->ctx.recv_dst != hb_sub_dst) {
-		BT_WARN("Ignoring heartbeat to non-subscribed destination");
-		return 0;
-	}
-
-	init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
-	feat = net_buf_simple_pull_be16(buf);
-
-	hops = (init_ttl - rx->ctx.recv_ttl + 1);
-
-	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 == 1) ? "" : "s", feat);
-
-	bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
-
-	return 0;
-}
-
-static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
-		    struct os_mbuf *buf, u64_t *seq_auth)
-{
-	u8_t ctl_op = TRANS_CTL_OP(&hdr);
+	uint8_t ctl_op = TRANS_CTL_OP(&hdr);
 
 	BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->om_len);
 
@@ -864,7 +876,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
 	case TRANS_CTL_OP_ACK:
 		return trans_ack(rx, hdr, buf, seq_auth);
 	case TRANS_CTL_OP_HEARTBEAT:
-		return trans_heartbeat(rx, buf);
+		return bt_mesh_hb_recv(rx, buf);
 	}
 
 	/* Only acks and heartbeats may need processing without local_match */
@@ -919,9 +931,10 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
 }
 
 static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
-		       u64_t *seq_auth)
+		       uint64_t *seq_auth)
 {
-	u8_t hdr;
+	struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_SDU_UNSEG_MAX);
+	uint8_t hdr;
 
 	BT_DBG("AFK %u AID 0x%02x", AKF(buf->om_data), AID(buf->om_data));
 
@@ -930,7 +943,7 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
 		return -EINVAL;
 	}
 
-	if (is_replay(rx, NULL)) {
+	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, (unsigned) rx->seq);
 		return -EINVAL;
@@ -940,20 +953,23 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
 
 	if (rx->ctl) {
 		return ctl_recv(rx, hdr, buf, seq_auth);
-	} else {
-		/* SDUs must match a local element or an LPN of this Friend. */
-		if (!rx->local_match && !rx->friend_match) {
-			return 0;
-		}
-
-		return sdu_recv(rx, rx->seq, hdr, 0, buf);
 	}
+
+	if (buf->om_len < 1 + APP_MIC_LEN(0)) {
+		BT_ERR("Too short SDU + MIC");
+		return -EINVAL;
+	}
+
+	/* Adjust the length to not contain the MIC at the end */
+	buf->om_len -= APP_MIC_LEN(0);
+
+	return sdu_recv(rx, hdr, 0, buf, sdu, NULL);
 }
 
-static inline s32_t ack_timeout(struct seg_rx *rx)
+static inline int32_t ack_timeout(struct seg_rx *rx)
 {
-	s32_t to;
-	u8_t ttl;
+	int32_t to;
+	uint8_t ttl;
 
 	if (rx->ttl == BT_MESH_TTL_DEFAULT) {
 		ttl = bt_mesh_default_ttl_get();
@@ -975,45 +991,46 @@ static inline s32_t ack_timeout(struct seg_rx *rx)
 	return max(to, K_MSEC(400));
 }
 
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
-		     size_t data_len, u64_t *seq_auth,
-		     const struct bt_mesh_send_cb *cb, void *cb_data)
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+		     size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data)
 {
-	struct os_mbuf *buf;
+	struct os_mbuf *buf = NET_BUF_SIMPLE(data_len);
+
+	net_buf_simple_init_with_data(buf, data, data_len);
+
+	if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+		tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+	} else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+		BT_ERR("TTL too large (max 127)");
+		return -EINVAL;
+	}
+
+	if (data_len > BT_MESH_SDU_UNSEG_MAX) {
+		tx->ctx->send_rel = true;
+	}
+
+	tx->ctx->app_idx = BT_MESH_KEY_UNUSED;
+
+	if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+	    BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+		BT_ERR("Invalid destination address");
+		return -EINVAL;
+	}
 
 	BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src,
 	       tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
 	BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
 
-	buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
-	if (!buf) {
-		BT_ERR("Out of transport buffers");
-		return -ENOBUFS;
+	if (tx->ctx->send_rel) {
+		return send_seg(tx, buf, cb, cb_data, &ctl_op);
+	} else {
+		return send_unseg(tx, buf, cb, cb_data, &ctl_op);
 	}
-
-	net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
-
-	net_buf_add_u8(buf, TRANS_CTL_HDR(ctl_op, 0));
-
-	net_buf_add_mem(buf, data, data_len);
-
-	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
-		if (bt_mesh_friend_enqueue_tx(tx, BT_MESH_FRIEND_PDU_SINGLE,
-					      seq_auth, 1, buf) &&
-		    BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
-			/* PDUs for a specific Friend should only go
-			 * out through the Friend Queue.
-			 */
-			net_buf_unref(buf);
-			return 0;
-		}
-	}
-
-	return bt_mesh_net_send(tx, buf, cb, cb_data);
+	os_mbuf_free_chain(buf);
 }
 
-static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
-		    u8_t ttl, u64_t *seq_auth, u32_t block, u8_t obo)
+static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst,
+		    uint8_t ttl, uint64_t *seq_auth, uint32_t block, uint8_t obo)
 {
 	struct bt_mesh_msg_ctx ctx = {
 		.net_idx = sub->net_idx,
@@ -1027,8 +1044,8 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
 		.src = obo ? bt_mesh_primary_addr() : src,
 		.xmit = bt_mesh_net_transmit_get(),
 	};
-	u16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
-	u8_t buf[6];
+	uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
+	uint8_t buf[6];
 
 	BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero,
 	       (unsigned) block, obo);
@@ -1042,7 +1059,7 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
 	 * or virtual address.
 	 */
 	if (!BT_MESH_ADDR_IS_UNICAST(src)) {
-		BT_WARN("Not sending ack for non-unicast address");
+		BT_DBG("Not sending ack for non-unicast address");
 		return 0;
 	}
 
@@ -1050,11 +1067,13 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
 	sys_put_be32(block, &buf[2]);
 
 	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_ACK, buf, sizeof(buf),
-				NULL, NULL, NULL);
+				NULL, NULL);
 }
 
 static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
 {
+	int i;
+
 	BT_DBG("rx %p", rx);
 
 	k_delayed_work_cancel(&rx->ack);
@@ -1066,6 +1085,15 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
 						&rx->seq_auth);
 	}
 
+	for (i = 0; i <= rx->seg_n; i++) {
+		if (!rx->seg[i]) {
+			continue;
+		}
+
+		k_mem_slab_free(&segs, &rx->seg[i]);
+		rx->seg[i] = NULL;
+	}
+
 	rx->in_use = 0;
 
 	/* We don't always reset these values since we need to be able to
@@ -1083,6 +1111,7 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
 static void seg_ack(struct ble_npl_event *work)
 {
 	struct seg_rx *rx = ble_npl_event_get_arg(work);
+	int32_t timeout;
 
 	BT_DBG("rx %p", rx);
 
@@ -1100,25 +1129,17 @@ static void seg_ack(struct ble_npl_event *work)
 	send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
 		 rx->block, rx->obo);
 
-	k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+	timeout = ack_timeout(rx);
+	k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
 }
 
-static inline u8_t seg_len(bool ctl)
+static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
 {
-	if (ctl) {
-		return 8;
-	} else {
-		return 12;
-	}
-}
-
-static inline bool sdu_len_is_ok(bool ctl, u8_t seg_n)
-{
-	return ((seg_n * seg_len(ctl) + 1) <= MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
+	return (seg_n < CONFIG_BT_MESH_RX_SEG_MAX);
 }
 
 static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
-				  const u64_t *seq_auth)
+				  const uint64_t *seq_auth)
 {
 	int i;
 
@@ -1155,7 +1176,7 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
 }
 
 static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
-			    const u8_t *hdr, u8_t seg_n)
+			    const uint8_t *hdr, uint8_t seg_n)
 {
 	if (rx->hdr != *hdr || rx->seg_n != seg_n) {
 		BT_ERR("Invalid segment for ongoing session");
@@ -1176,11 +1197,19 @@ static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
 }
 
 static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
-				   const u8_t *hdr, const u64_t *seq_auth,
-				   u8_t seg_n)
+				   const uint8_t *hdr, const uint64_t *seq_auth,
+				   uint8_t seg_n)
 {
 	int i;
 
+	/* No race condition on this check, as this function only executes in
+	 * the collaborative Bluetooth rx thread:
+	 */
+	if (k_mem_slab_num_free_get(&segs) < 1) {
+		BT_WARN("Not enough segments for incoming message");
+		return NULL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
 		struct seg_rx *rx = &seg_rx[i];
 
@@ -1189,7 +1218,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
 		}
 
 		rx->in_use = 1;
-		net_buf_simple_init(rx->buf, 0);
 		rx->sub = net_rx->sub;
 		rx->ctl = net_rx->ctl;
 		rx->seq_auth = *seq_auth;
@@ -1210,15 +1238,15 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
 }
 
 static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
-		     enum bt_mesh_friend_pdu_type *pdu_type, u64_t *seq_auth,
-		     u8_t *seg_count)
+		     enum bt_mesh_friend_pdu_type *pdu_type, uint64_t *seq_auth,
+		     uint8_t *seg_count)
 {
 	struct bt_mesh_rpl *rpl = NULL;
 	struct seg_rx *rx;
-	u8_t *hdr = buf->om_data;
-	u16_t seq_zero;
-	u8_t seg_n;
-	u8_t seg_o;
+	uint8_t *hdr = buf->om_data;
+	uint16_t seq_zero;
+	uint8_t seg_n;
+	uint8_t seg_o;
 	int err;
 
 	if (buf->om_len < 5) {
@@ -1226,7 +1254,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
 		return -EINVAL;
 	}
 
-	if (is_replay(net_rx, &rpl)) {
+	if (bt_mesh_rpl_check(net_rx, &rpl)) {
 		BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
 			net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
 		return -EINVAL;
@@ -1290,14 +1318,14 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
 		}
 
 		if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
-			BT_WARN("Got segment for already complete SDU");
+			BT_DBG("Got segment for already complete SDU");
 
 			send_ack(net_rx->sub, net_rx->ctx.recv_dst,
 				 net_rx->ctx.addr, net_rx->ctx.send_ttl,
 				 seq_auth, rx->block, rx->obo);
 
 			if (rpl) {
-				update_rpl(rpl, net_rx);
+				bt_mesh_rpl_update(rpl, net_rx);
 			}
 
 			return -EALREADY;
@@ -1351,7 +1379,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
 
 found_rx:
 	if (BIT(seg_o) & rx->block) {
-		BT_WARN("Received already received fragment");
+		BT_DBG("Received already received fragment");
 		return -EALREADY;
 	}
 
@@ -1361,11 +1389,11 @@ found_rx:
 	 */
 	if (seg_o == seg_n) {
 		/* Set the expected final buffer length */
-		rx->buf->om_len = seg_n * seg_len(rx->ctl) + buf->om_len;
+		rx->len = seg_n * seg_len(rx->ctl) + buf->om_len;
 		BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
-		       buf->om_len, rx->buf->om_len);
+		       buf->om_len, rx->len);
 
-		if (rx->buf->om_len > MYNEWT_VAL(BLE_MESH_RX_SDU_MAX)) {
+		if (rx->len > BT_MESH_RX_SDU_MAX) {
 			BT_ERR("Too large SDU len");
 			send_ack(net_rx->sub, net_rx->ctx.recv_dst,
 				 net_rx->ctx.addr, net_rx->ctx.send_ttl,
@@ -1385,11 +1413,20 @@ found_rx:
 
 	if (!k_delayed_work_remaining_get(&rx->ack) &&
 	    !bt_mesh_lpn_established()) {
-		k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+		int32_t timeout = ack_timeout(rx);
+
+		k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
 	}
 
-	/* Location in buffer can be calculated based on seg_o & rx->ctl */
-	memcpy(rx->buf->om_data + (seg_o * seg_len(rx->ctl)), buf->om_data, buf->om_len);
+	/* Allocated segment here */
+	err = k_mem_slab_alloc(&segs, &rx->seg[seg_o]);
+	if (err) {
+		BT_WARN("Unable allocate buffer for Seg %u", seg_o);
+		return -ENOBUFS;
+	}
+
+	os_mbuf_copydata(buf, 0, buf->om_len, rx->seg[seg_o]);
+	BT_DBG("copied %s", bt_hex(rx->seg[seg_o], rx->len));
 
 	BT_DBG("Received %u/%u", seg_o, seg_n);
 
@@ -1404,7 +1441,7 @@ found_rx:
 	BT_DBG("Complete SDU");
 
 	if (rpl) {
-		update_rpl(rpl, net_rx);
+		bt_mesh_rpl_update(rpl, net_rx);
 	}
 
 	*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
@@ -1414,23 +1451,40 @@ found_rx:
 		 net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
 
 	if (net_rx->ctl) {
-		err = ctl_recv(net_rx, *hdr, rx->buf, seq_auth);
+		struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_RX_CTL_MAX);
+		seg_rx_assemble(rx, sdu, 0U);
+		err = ctl_recv(net_rx, *hdr, sdu, seq_auth);
+	} else if (rx->len < 1 + APP_MIC_LEN(ASZMIC(hdr))) {
+		BT_ERR("Too short SDU + MIC");
+		err = -EINVAL;
 	} else {
-		err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), *hdr,
-			       ASZMIC(hdr), rx->buf);
+		struct os_mbuf *seg_buf = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX);
+		struct os_mbuf *sdu;
+
+		/* Decrypting in place to avoid creating two assembly buffers.
+		 * We'll reassemble the buffer from the segments before each
+		 * decryption attempt.
+		 */
+		net_buf_simple_init(seg_buf, 0);
+
+	    sdu = NET_BUF_SIMPLE(rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+		net_buf_simple_init_with_data(
+			sdu, seg_buf->om_data, rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+
+		err = sdu_recv(net_rx, *hdr, ASZMIC(hdr), seg_buf, sdu, rx);
+		os_mbuf_free_chain(seg_buf);
 	}
 
 	seg_rx_reset(rx, false);
-
 	return err;
 }
 
 int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx)
 {
-	u64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
+	uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
 	enum bt_mesh_friend_pdu_type pdu_type = BT_MESH_FRIEND_PDU_SINGLE;
 	struct net_buf_simple_state state;
-	u8_t seg_count = 0;
+	uint8_t seg_count = 0;
 	int err;
 
 	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
@@ -1525,28 +1579,43 @@ void bt_mesh_rx_reset(void)
 	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
 		seg_rx_reset(&seg_rx[i], true);
 	}
-
-	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
-		bt_mesh_clear_rpl();
-	} else {
-		memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
-	}
 }
 
-void bt_mesh_tx_reset(void)
+void bt_mesh_trans_reset(void)
 {
 	int i;
 
+	bt_mesh_rx_reset();
+
 	BT_DBG("");
 
 	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
 		seg_tx_reset(&seg_tx[i]);
 	}
+
+	for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+		if (virtual_addrs[i].ref) {
+			virtual_addrs[i].ref = 0U;
+			virtual_addrs[i].changed = 1U;
+		}
+	}
+
+	bt_mesh_rpl_clear();
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_label();
+	}
 }
 
 void bt_mesh_trans_init(void)
 {
-	int i;
+	int i, rc;
+
+	/* We need to initialize memslab free list here */
+	rc = create_free_list(&segs);
+	if (rc) {
+		BT_ERR("Failed to create free memslab list")
+	}
 
 	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
 		k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit);
@@ -1557,112 +1626,124 @@ void bt_mesh_trans_init(void)
 	 *  For now we increase MSYS_1_BLOCK_COUNT
 	 */
 	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
-	    seg_rx[i].buf = NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
 		k_delayed_work_init(&seg_rx[i].ack, seg_ack);
 		k_delayed_work_add_arg(&seg_rx[i].ack, &seg_rx[i]);
 	}
 }
 
-void bt_mesh_rpl_clear(void)
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index)
 {
-	BT_DBG("");
-	memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+	if (index >= ARRAY_SIZE(virtual_addrs)) {
+		return NULL;
+	}
+
+	return &virtual_addrs[index];
 }
 
-void bt_mesh_heartbeat_send(void)
+static inline void va_store(struct bt_mesh_va *store)
 {
-	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
-	u16_t feat = 0U;
-	struct __packed {
-		u8_t  init_ttl;
-		u16_t feat;
-	} hb;
-	struct bt_mesh_msg_ctx ctx = {
-		.net_idx = cfg->hb_pub.net_idx,
-		.app_idx = BT_MESH_KEY_UNUSED,
-		.addr = cfg->hb_pub.dst,
-		.send_ttl = cfg->hb_pub.ttl,
-	};
-	struct bt_mesh_net_tx tx = {
-		.sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
-		.ctx = &ctx,
-		.src = bt_mesh_model_elem(cfg->model)->addr,
-		.xmit = bt_mesh_net_transmit_get(),
-	};
-
-	/* Do nothing if heartbeat publication is not enabled */
-	if (cfg->hb_pub.dst == BT_MESH_ADDR_UNASSIGNED) {
-		return;
+	store->changed = 1U;
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_label();
 	}
-
-	hb.init_ttl = cfg->hb_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", cfg->hb_pub.ttl, feat);
-
-	bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
-			 NULL, NULL, NULL);
 }
 
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
-			u16_t addr, const u8_t **key, u8_t *aid)
+uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr)
 {
-	struct bt_mesh_app_key *app_key;
+	struct bt_mesh_va *va = NULL;
+	int err;
 
-	if (app_idx == BT_MESH_KEY_DEV_LOCAL ||
-	    (app_idx == BT_MESH_KEY_DEV_REMOTE &&
-	     bt_mesh_elem_find(addr) != NULL)) {
-		*aid = 0;
-		*key = bt_mesh.dev_key;
-		return 0;
-	} else if (app_idx == BT_MESH_KEY_DEV_REMOTE) {
-		if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
-			return -EINVAL;
+	for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+		if (!virtual_addrs[i].ref) {
+			if (!va) {
+				va = &virtual_addrs[i];
+			}
+
+			continue;
 		}
 
-		struct bt_mesh_node *node = bt_mesh_node_find(addr);
-		if (!node) {
-			return -EINVAL;
+		if (!memcmp(uuid, virtual_addrs[i].uuid,
+			    ARRAY_SIZE(virtual_addrs[i].uuid))) {
+			*addr = virtual_addrs[i].addr;
+			virtual_addrs[i].ref++;
+			va_store(&virtual_addrs[i]);
+			return STATUS_SUCCESS;
 		}
-
-		*key = node->dev_key;
-		*aid = 0;
-		return 0;
 	}
 
-	if (!subnet) {
-		return -EINVAL;
+	if (!va) {
+		return STATUS_INSUFF_RESOURCES;
 	}
 
-	app_key = bt_mesh_app_key_find(app_idx);
-	if (!app_key) {
-		return -ENOENT;
+	memcpy(va->uuid, uuid, ARRAY_SIZE(va->uuid));
+	err = bt_mesh_virtual_addr(uuid, &va->addr);
+	if (err) {
+		va->addr = BT_MESH_ADDR_UNASSIGNED;
+		return STATUS_UNSPECIFIED;
 	}
 
-	if (subnet->kr_phase == BT_MESH_KR_PHASE_2 && app_key->updated) {
-		*key = app_key->keys[1].val;
-		*aid = app_key->keys[1].id;
-	} else {
-		*key = app_key->keys[0].val;
-		*aid = app_key->keys[0].id;
-	}
+	va->ref = 1;
+	va_store(va);
 
-	return 0;
+	*addr = va->addr;
+
+	return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr)
+{
+	struct bt_mesh_va *va = NULL;
+
+	for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+		if (virtual_addrs[i].ref &&
+		    !memcmp(uuid, virtual_addrs[i].uuid,
+			    ARRAY_SIZE(virtual_addrs[i].uuid))) {
+			va = &virtual_addrs[i];
+			break;
+		}
+	}
+
+	if (!va) {
+		return STATUS_CANNOT_REMOVE;
+	}
+
+	va->ref--;
+	if (addr) {
+		*addr = va->addr;
+	}
+
+	va_store(va);
+	return STATUS_SUCCESS;
+}
+
+struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16])
+{
+	for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+		if (virtual_addrs[i].ref &&
+		    !memcmp(uuid, virtual_addrs[i].uuid,
+			    ARRAY_SIZE(virtual_addrs[i].uuid))) {
+			return &virtual_addrs[i];
+		}
+	}
+
+	return NULL;
+}
+
+uint8_t *bt_mesh_va_label_get(uint16_t addr)
+{
+	int i;
+
+	BT_DBG("addr 0x%04x", addr);
+
+	for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+		if (virtual_addrs[i].ref && virtual_addrs[i].addr == addr) {
+			BT_DBG("Found Label UUID for 0x%04x: %s", addr,
+			       bt_hex(virtual_addrs[i].uuid, 16));
+			return virtual_addrs[i].uuid;
+		}
+	}
+
+	BT_WARN("No matching Label UUID for 0x%04x", addr);
+
+	return NULL;
 }
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
index eff768e9..23be7139 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
@@ -11,10 +11,12 @@
 
 #define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff
 
-#define BT_MESH_TX_SDU_MAX             (CONFIG_BT_MESH_TX_SEG_MAX * 12)
+#define BT_MESH_SDU_UNSEG_MAX          11
+#define BT_MESH_CTL_SEG_SDU_MAX        8
+#define BT_MESH_RX_CTL_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_CTL_SEG_SDU_MAX)
 
-#define TRANS_SEQ_ZERO_MASK            ((u16_t)BIT_MASK(13))
-#define TRANS_CTL_OP_MASK              ((u8_t)BIT_MASK(7))
+#define TRANS_SEQ_ZERO_MASK            ((uint16_t)BIT_MASK(13))
+#define TRANS_CTL_OP_MASK              ((uint8_t)BIT_MASK(7))
 #define TRANS_CTL_OP(data)             ((data)[0] & TRANS_CTL_OP_MASK)
 #define TRANS_CTL_HDR(op, seg)         ((op & TRANS_CTL_OP_MASK) | (seg << 7))
 
@@ -31,64 +33,65 @@
 #define TRANS_CTL_OP_HEARTBEAT         0x0a
 
 struct bt_mesh_ctl_friend_poll {
-	u8_t  fsn;
+	uint8_t  fsn;
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_update {
-	u8_t  flags;
-	u32_t iv_index;
-	u8_t  md;
+	uint8_t  flags;
+	uint32_t iv_index;
+	uint8_t  md;
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_req {
-	u8_t  criteria;
-	u8_t  recv_delay;
-	u8_t  poll_to[3];
-	u16_t prev_addr;
-	u8_t  num_elem;
-	u16_t lpn_counter;
+	uint8_t  criteria;
+	uint8_t  recv_delay;
+	uint8_t  poll_to[3];
+	uint16_t prev_addr;
+	uint8_t  num_elem;
+	uint16_t lpn_counter;
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_offer {
-	u8_t  recv_win;
-	u8_t  queue_size;
-	u8_t  sub_list_size;
-	s8_t  rssi;
-	u16_t frnd_counter;
+	uint8_t  recv_win;
+	uint8_t  queue_size;
+	uint8_t  sub_list_size;
+	int8_t  rssi;
+	uint16_t frnd_counter;
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_clear {
-	u16_t lpn_addr;
-	u16_t lpn_counter;
+	uint16_t lpn_addr;
+	uint16_t lpn_counter;
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_clear_confirm {
-	u16_t lpn_addr;
-	u16_t lpn_counter;
+	uint16_t lpn_addr;
+	uint16_t lpn_counter;
 }__attribute__((__packed__));
 
 #define BT_MESH_FRIEND_SUB_MIN_LEN (1 + 2)
 struct bt_mesh_ctl_friend_sub {
-	u8_t  xact;
-	u16_t addr_list[5];
+	uint8_t  xact;
+	uint16_t addr_list[5];
 }__attribute__((__packed__));
 
 struct bt_mesh_ctl_friend_sub_confirm {
-	u8_t  xact;
+	uint8_t  xact;
 }__attribute__((__packed__));
 
-void bt_mesh_set_hb_sub_dst(u16_t addr);
-
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
+struct bt_mesh_va {
+	uint16_t ref:15,
+		 changed:1;
+	uint16_t addr;
+	uint8_t  uuid[16];
+};
 
 bool bt_mesh_tx_in_progress(void);
 
 void bt_mesh_rx_reset(void);
-void bt_mesh_tx_reset(void);
 
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
-		     size_t data_len, u64_t *seq_auth,
-		     const struct bt_mesh_send_cb *cb, void *cb_data);
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+		     size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data);
 
 int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
 		       const struct bt_mesh_send_cb *cb, void *cb_data);
@@ -97,9 +100,14 @@ int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx);
 
 void bt_mesh_trans_init(void);
 
-void bt_mesh_rpl_clear(void);
+void bt_mesh_trans_reset(void);
 
-void bt_mesh_heartbeat_send(void);
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index);
 
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
-			u16_t addr, const u8_t **key, u8_t *aid);
+struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16]);
+
+uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr);
+
+uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr);
+
+uint8_t *bt_mesh_va_label_get(uint16_t addr);
\ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
index 98632232..cf0c7f75 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
@@ -29,17 +29,57 @@ syscfg.defs:
            the advertising bearer.
         value: 1
 
+    BLE_MESH_UNPROV_BEACON_INT:
+        description: >
+           This option specifies the interval (in seconds) at which the
+           device sends unprovisioned beacon.
+        value: 5
+
+    BLE_MESH_PB_ADV_RETRANS_TIMEOUT:
+        description: >
+           Timeout value of retransmit provisioning PDUs.
+        value: 500
+
+    BLE_MESH_PROV_DEVICE:
+        description: >
+           Enable this option to allow the device to be provisioned into a mesh network.
+        value: 1
+        restrictions: BLE_MESH_PROV
+
     BLE_MESH_PROVISIONER:
         description: >
             Enable this option to have support for provisioning remote devices.
-        value: 0
+        value: 1
         restrictions:
-            - (BLE_MESH_PROV)
+            - BLE_MESH_PROV
+            - BLE_MESH_PB_ADV
 
-    BLE_MESH_NODE_COUNT:
+    BLE_MESH_CDB:
+        description: >
+            Mesh Configuration Database [EXPERIMENTAL]
+        value: 0
+
+    BLE_MESH_CDB_NODE_COUNT:
         description: >
             This option specifies how many nodes each network can at most
-            save in the provisioning database. Range 1-4096
+            save in the configuration database.
+        value: 1
+
+    BLE_MESH_CDB_SUBNET_COUNT:
+        description: >
+            This option specifies how many subnets that can at most be
+            saved in the configuration database.
+        value: 1
+
+    BLE_MESH_CDB_APP_KEY_COUNT:
+        description: >
+            This option specifies how many application keys that can at most
+            be saved in the configuration database.
+        value: 1
+
+    BLE_MESH_DEBUG_CDB:
+        description:
+            Use this option to enable configuration database debug logs.
         value: 1
 
     BLE_MESH_PROXY:
@@ -61,6 +101,19 @@ syscfg.defs:
             and a Mesh network.
         value: 1
 
+    BLE_MESH_GATT_PROXY_ENABLED:
+        description: >
+            Controls whether the GATT Proxy feature is enabled by default.
+            Can be changed through runtime configuration.
+        value: 1
+        restrictions: BLE_MESH_GATT_PROXY
+
+    BLE_MESH_DEFAULT_TTL:
+        description: >
+            Controls the default TTL value for outgoing messages. Can be changed
+            through runtime configuration.
+        value: 7
+
     BLE_MESH_NODE_ID_TIMEOUT:
         description: >
             This option determines for how long the local node advertises
@@ -136,6 +189,13 @@ syscfg.defs:
             supported outgoing segment count (BT_MESH_TX_SEG_MAX).
         value: 6
 
+    BLE_MESH_ADV_STACK_SIZE:
+        description: >
+            Mesh advertiser thread stack size.
+            NOTE: This is an advanced setting and should not be changed unless
+            absolutely necessary
+        value: 768
+
     BLE_MESH_IVU_DIVIDER:
         description: >
             When the IV Update state enters Normal operation or IV Update
@@ -164,7 +224,7 @@ syscfg.defs:
         description: >
             Maximum number of simultaneous outgoing multi-segment and/or
             reliable messages.
-        value: 4
+        value: 1
 
     BLE_MESH_RX_SEG_MSG_COUNT:
         description: >
@@ -172,15 +232,39 @@ syscfg.defs:
             reliable messages.
         value: 2
 
-    BLE_MESH_RX_SDU_MAX:
+    BLE_MESH_SEG_BUFS:
         description: >
-            Maximum incoming Upper Transport Access PDU length. This
-            determines also how many segments incoming segmented messages
-            can have. Each segment can contain 12 bytes, so this value should
-            be set to a multiple of 12 to avoid wasted memory. The minimum
-            requirement is 2 segments (24 bytes) whereas the maximum supported
-            by the Mesh specification is 32 segments (384 bytes).
-        value: 72
+            The incoming and outgoing segmented messages allocate their
+            segments from the same pool. Each segment is a 12 byte block,
+            and may only be used by one message at the time.
+
+            Outgoing messages will allocate their segments at the start of the
+            transmission, and release them one by one as soon as they have been
+            acknowledged by the receiver. Incoming messages allocate all their
+            segments at the start of the transaction, and won't release them until
+            the message is fully received.
+        value:
+            64
+
+    BLE_MESH_RX_SEG_MAX:
+        description: >
+            Maximum number of segments supported for incoming messages.
+            This value should typically be fine-tuned based on what
+            models the local node supports, i.e. what's the largest
+            message payload that the node needs to be able to receive.
+            This value affects memory and call stack consumption, which
+            is why the default is lower than the maximum that the
+            specification would allow (32 segments).
+
+            The maximum incoming SDU size is 12 times this number (out of
+            which 4 or 8 bytes is used for the Transport Layer MIC). For
+            example, 5 segments means the maximum SDU size is 60 bytes,
+            which leaves 56 bytes for application layer data using a
+            4-byte MIC and 52 bytes using an 8-byte MIC.
+        value:
+            3
+
+
 
     BLE_MESH_TX_SEG_MAX:
         description: >
@@ -188,22 +272,39 @@ syscfg.defs:
             This value should typically be fine-tuned based on what
             models the local node supports, i.e. what's the largest
             message payload that the node needs to be able to send.
-            This value affects memory and call stack consumption, which
-            is why the default is lower than the maximum that the
-            specification would allow (32 segments).
+            This value affects memory consumption, which is why the
+            default is lower than the maximum that the specification
+            would allow (32 segments).
 
             The maximum outgoing SDU size is 12 times this number (out of
             which 4 or 8 bytes is used for the Transport Layer MIC). For
             example, 5 segments means the maximum SDU size is 60 bytes,
             which leaves 56 bytes for application layer data using a
             4-byte MIC and 52 bytes using an 8-byte MIC.
-
-            Be sure to specify a sufficient number of advertising buffers
-            when setting this option to a higher value. There must be at
-            least three more advertising buffers (BT_MESH_ADV_BUF_COUNT)
-            as there are outgoing segments.
         value: 3
 
+    BLE_MESH_LOOPBACK_BUFS:
+        description: >
+            The number of buffers allocated for the network loopback mechanism.
+            Loopback is used when the device sends messages to itself.
+        value: 3
+
+    BLE_MESH_TX_SEG_RETRANS_COUNT:
+        description: >
+            Maximum number of transport message segment retransmit attempts
+            for outgoing segment message.
+        value: 4
+
+    BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST:
+        description: >
+             Maximum time of retransmit segment message to unicast address.
+        value: 400
+
+    BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP:
+        description: >
+              Maximum time of retransmit segment message to group address.
+        value: 50
+
     BLE_MESH_SEG_RETRANSMIT_ATTEMPTS:
         description: >
             Number of retransmit attempts (after the initial transmit) per segment
@@ -211,9 +312,57 @@ syscfg.defs:
         retrictions: 'BLE_MESH_SEG_RETRANSMIT_ATTEMPTS > 1'
 
     BLE_MESH_RELAY:
+        description: >
+            Controls the initial number of retransmissions of original messages,
+            in addition to the first transmission. Can be changed through runtime
+            configuration.
+        value: 2
+
+    BLE_MESH_NETWORK_TRANSMIT_COUNT:
+        description: >
+            Controls the initial number of retransmissions of original messages,
+            in addition to the first transmission. Can be changed through runtime
+            configuration.
+        value: 2
+
+    BLE_MESH_NETWORK_TRANSMIT_INTERVAL:
+        description: >
+            Controls the initial interval between retransmissions of original
+            messages, in milliseconds. Can be changed through runtime
+            configuration.
+        value: 20
+
+    BT_MESH_RELAY:
         description: >
             Support for acting as a Mesh Relay Node.
-        value: 0
+        value: 1
+
+    BLE_MESH_RELAY_ENABLED:
+        description: >
+            Controls whether the Mesh Relay feature is enabled by default. Can be
+            changed through runtime configuration.
+        value: 1
+
+    BLE_MESH_RELAY_RETRANSMIT_COUNT:
+        description: >
+            Controls the initial number of retransmissions of relayed messages, in
+            addition to the first transmission. Can be changed through runtime
+            configuration.
+
+        value: 2
+
+    BLE_MESH_RELAY_RETRANSMIT_INTERVAL:
+        description: >
+            Controls the initial interval between retransmissions of relayed
+            messages, in milliseconds. Can be changed through runtime
+            configuration.
+        value: 20
+
+    BLE_MESH_BEACON_ENABLED:
+        description: >
+            Controls whether the Secure network beacon feature is enabled by
+            default. Can be changed through runtime configuration.
+        value: 1
 
     BLE_MESH_LOW_POWER:
         description: >
@@ -287,6 +436,16 @@ syscfg.defs:
             a value of 300 means 30 seconds.
         value: 300
 
+    BLE_MESH_LPN_POLL_TIMEOUT:
+        description: >
+            PollTimeout timer is used to measure time between two
+            consecutive requests sent by the Low Power node. If no
+            requests are received by the Friend node before the
+            PollTimeout timer expires, then the friendship is considered
+            terminated. The value is in units of 100 milliseconds, so e.g.
+            a value of 300 means 30 seconds.
+        value: 300
+
     BLE_MESH_LPN_INIT_POLL_TIMEOUT:
         description: >
             The initial value of the PollTimeout timer when Friendship
@@ -308,11 +467,23 @@ syscfg.defs:
             Maximum number of groups that the LPN can subscribe to.
         value: 10
 
+    BLE_MESH_LPN_SUB_ALL_NODES_ADDR:
+        description: >
+            Automatically subscribe all nodes address when friendship
+            established.
+        value: 1
+
     BLE_MESH_FRIEND:
         description: >
             Enable this option to be able to act as a Friend Node.
         value: 0
 
+    BLE_MESH_FRIEND_ENABLED:
+        description: >
+            Controls whether the Friend feature is enabled by default. Can be
+            changed through runtime configuration.
+        value: 1
+
     BLE_MESH_FRIEND_RECV_WIN:
         description: >
             Receive Window in milliseconds supported by the Friend node.
@@ -336,6 +507,7 @@ syscfg.defs:
             with simultaneously.
         value: 2
 
+
     BLE_MESH_FRIEND_SEG_RX:
         description: >
             Number of incomplete segment lists that we track for each LPN
@@ -344,6 +516,7 @@ syscfg.defs:
             messages from when the messages are going into the Friend queue.
         value: 1
 
+
     BLE_MESH_CFG_CLI:
         description: >
             Enable support for the configuration client model.
@@ -592,6 +765,51 @@ syscfg.defs:
             Minimum level for the BLE Mesh Transport Layer log.
         value: 1
 
+    BLE_MESH_RPL_LOG_MOD:
+        description: >
+            Numeric module ID to use for BLE Mesh Replay protection list messages.
+        value: 22
+    BLE_MESH_RPL_LOG_LVL:
+        description: >
+            Minimum level for the BLE Mesh Replay protection list log.
+        value: 1
+
+    BLE_MESH_NET_KEYS_LOG_MOD:
+        description: >
+            Numeric module ID to use for BLE Mesh Replay protection list messages.
+        value: 23
+    BLE_MESH_NET_KEYS_LOG_LVL:
+        description: >
+            Minimum level for the BLE Mesh Replay protection list log.
+        value: 1
+
+    BLE_MESH_PROV_DEVICE_LOG_MOD:
+        description: >
+            Numeric module ID to use for BLE Mesh Replay protection list messages.
+        value: 24
+    BLE_MESH_PROV_DEVICE_LOG_LVL:
+        description: >
+            Minimum level for the BLE Mesh Replay protection list log.
+        value: 1
+
+    BLE_MESH_PROVISIONER_LOG_MOD:
+        description: >
+            Numeric module ID to use for BLE Mesh Replay protection list messages.
+        value: 25
+    BLE_MESH_PROVISIONER_LOG_LVL:
+        description: >
+            Minimum level for the BLE Mesh Replay protection list log.
+        value: 1
+
+    BLE_MESH_HEARTBEAT_LOG_MOD:
+        description: >
+            Numeric module ID to use for BLE Mesh Replay protection list messages.
+        value: 26
+    BLE_MESH_HEARTBEAT_LOG_LVL:
+        description: >
+            Minimum level for the BLE Mesh Replay protection list log.
+        value: 1
+
 syscfg.logs:
     BLE_MESH_LOG:
         module: MYNEWT_VAL(BLE_MESH_LOG_MOD)
@@ -641,10 +859,30 @@ syscfg.logs:
         module: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_MOD)
         level: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_LVL)
 
+    BLE_MESH_RPL_LOG:
+        module: MYNEWT_VAL(BLE_MESH_RPL_LOG_MOD)
+        level: MYNEWT_VAL(BLE_MESH_RPL_LOG_LVL)
+
     BLE_MESH_TRANS_LOG:
         module: MYNEWT_VAL(BLE_MESH_TRANS_LOG_MOD)
         level: MYNEWT_VAL(BLE_MESH_TRANS_LOG_LVL)
 
+    BLE_MESH_NET_KEYS_LOG:
+        module: MYNEWT_VAL(BLE_MESH_NET_KEYS_LOG_MOD)
+        level: MYNEWT_VAL(BLE_MESH_NET_KEYS_LOG_LVL)
+
+    BLE_MESH_PROV_DEVICE_LOG:
+        module: MYNEWT_VAL(BLE_MESH_PROV_DEVICE_LOG_MOD)
+        level: MYNEWT_VAL(BLE_MESH_PROV_DEVICE_LOG_LVL)
+
+    BLE_MESH_PROVISIONER_LOG:
+        module: MYNEWT_VAL(BLE_MESH_PROVISIONER_LOG_MOD)
+        level: MYNEWT_VAL(BLE_MESH_PROVISIONER_LOG_LVL)
+
+    BLE_MESH_HEARTBEAT_LOG:
+        module: MYNEWT_VAL(BLE_MESH_HEARTBEAT_LOG_MOD)
+        level: MYNEWT_VAL(BLE_MESH_HEARTBEAT_LOG_LVL)
+
 syscfg.vals.BLE_MESH_SHELL:
     BLE_MESH_CFG_CLI: 1
     BLE_MESH_HEALTH_CLI: 1
diff --git a/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
index 2706b5d3..24b9a26c 100644
--- a/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
+++ b/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
@@ -28,4 +28,6 @@
 
 int ble_svc_bas_battery_level_set(uint8_t level);
 
+void ble_svc_bas_init(void);
+
 #endif
diff --git a/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
index d7b60df4..707a3bd0 100644
--- a/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
+++ b/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
@@ -34,6 +34,7 @@ extern "C" {
 
 #define BLE_SVC_GAP_APPEARANCE_GEN_UNKNOWN                         0
 #define BLE_SVC_GAP_APPEARANCE_GEN_COMPUTER                        128
+#define BLE_SVC_GAP_APPEARANCE_GEN_HID                             960
 #define BLE_SVC_GAP_APPEARANCE_CYC_SPEED_AND_CADENCE_SENSOR        1157
 
 typedef void (ble_svc_gap_chr_changed_fn) (uint16_t uuid);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
index a123c857..81b070f9 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
@@ -66,11 +66,10 @@ ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom)
 
     ble_hs_lock();
 
-    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
-                                    &chan);
-    if (chan == NULL) {
+    rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
+                                         &chan);
+    if (rc != 0) {
         os_mbuf_free_chain(txom);
-        rc = BLE_HS_ENOTCONN;
     } else {
         ble_att_truncate_to_mtu(chan, txom);
         rc = ble_l2cap_tx(conn, chan, txom);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c b/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
index 46a71681..be61e4b8 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
@@ -1360,7 +1360,7 @@ done:
         *att_err = 0;
 
         /* Fill the response base. */
-        rsp->batp_length = htole16(sizeof(*data) + prev_attr_len);
+        rsp->batp_length = sizeof(*data) + prev_attr_len;
     }
 
     *out_txom = txom;
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c b/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
index 7d80d134..eccb3e98 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
@@ -76,7 +76,7 @@ ble_eddystone_set_adv_data_gen(struct ble_hs_adv_fields *adv_fields,
     if (adv_fields->num_uuids16 > BLE_EDDYSTONE_MAX_UUIDS16) {
         return BLE_HS_EINVAL;
     }
-    if (svc_data_len > BLE_EDDYSTONE_MAX_SVC_DATA_LEN) {
+    if (svc_data_len > (BLE_EDDYSTONE_MAX_SVC_DATA_LEN - BLE_EDDYSTONE_SVC_DATA_BASE_SZ)) {
         return BLE_HS_EINVAL;
     }
     if (adv_fields->num_uuids16 > 0 && !adv_fields->uuids16_is_complete) {
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
index e32482e6..bbedc319 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
@@ -310,14 +310,12 @@ ble_gap_log_conn(uint8_t own_addr_type, const ble_addr_t *peer_addr,
         BLE_HS_LOG_ADDR(INFO, peer_addr->val);
     }
 
-    /* // NRF LOG support max 6 params in log
     BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d "
                      "latency=%d supervision_timeout=%d min_ce_len=%d "
                      "max_ce_len=%d own_addr_type=%d",
                params->scan_itvl, params->scan_window, params->itvl_min,
                params->itvl_max, params->latency, params->supervision_timeout,
                params->min_ce_len, params->max_ce_len, own_addr_type);
-     */
 }
 #endif
 
@@ -341,10 +339,10 @@ ble_gap_log_update(uint16_t conn_handle,
 {
     BLE_HS_LOG(INFO, "connection parameter update; "
                      "conn_handle=%d itvl_min=%d itvl_max=%d latency=%d "
-                     "supervision_timeout=%d min_ce_len=%d max_ce_len=???",
+                     "supervision_timeout=%d min_ce_len=%d max_ce_len=%d",
                conn_handle, params->itvl_min, params->itvl_max,
                params->latency, params->supervision_timeout,
-               params->min_ce_len);
+               params->min_ce_len, params->max_ce_len);
 }
 #endif
 
@@ -747,7 +745,7 @@ ble_gap_has_client(struct ble_gap_master_state *out_state)
         return 0;
     }
 
-    return out_state->cb;
+    return out_state->cb != NULL;
 }
 
 static void
@@ -932,7 +930,7 @@ ble_gap_master_ticks_until_exp(void)
     return 0;
 }
 
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
 static uint32_t
 ble_gap_slave_ticks_until_exp(void)
 {
@@ -1000,7 +998,7 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
 
 }
 
-#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
+#if NIMBLE_BLE_SCAN
 static void
 ble_gap_master_set_timer(uint32_t ticks_from_now)
 {
@@ -1022,7 +1020,7 @@ ble_gap_slave_set_timer(uint32_t ticks_from_now)
 }
 #endif
 
-#if NIMBLE_BLE_CONNECT
+#if (NIMBLE_BLE_CONNECT || NIMBLE_BLE_SCAN)
 /**
  * Called when an error is encountered while the master-connection-fsm is
  * active.
@@ -1036,12 +1034,22 @@ ble_gap_master_failed(int status)
         ble_gap_master_connect_failure(status);
         break;
 
+#if NIMBLE_BLE_SCAN
+    case BLE_GAP_OP_M_DISC:
+        STATS_INC(ble_gap_stats, initiate_fail);
+        ble_gap_disc_complete();
+        ble_gap_master_reset_state();
+        break;
+#endif
+
     default:
         BLE_HS_DBG_ASSERT(0);
         break;
     }
 }
+#endif
 
+#if NIMBLE_BLE_CONNECT
 static void
 ble_gap_update_failed(uint16_t conn_handle, int status)
 {
@@ -1239,6 +1247,46 @@ ble_gap_adv_active_instance(uint8_t instance)
     return ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV;
 }
 
+/**
+ * Clears advertisement and discovery state.  This function is necessary
+ * when the controller loses its active state (e.g. on stack reset).
+ */
+void
+ble_gap_reset_state(int reason)
+{
+    uint16_t conn_handle;
+
+    while (1) {
+        conn_handle = ble_hs_atomic_first_conn_handle();
+        if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
+            break;
+        }
+
+        ble_gap_conn_broken(conn_handle, reason);
+    }
+
+#if NIMBLE_BLE_ADVERTISE
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    uint8_t i;
+    for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+        if (ble_gap_adv_active_instance(i)) {
+            /* Indicate to application that advertising has stopped. */
+            ble_gap_adv_finished(i, reason, 0, 0);
+        }
+    }
+#else
+    if (ble_gap_adv_active_instance(0)) {
+        /* Indicate to application that advertising has stopped. */
+        ble_gap_adv_finished(0, reason, 0, 0);
+    }
+#endif
+#endif
+
+#if (NIMBLE_BLE_SCAN || NIMBLE_BLE_CONNECT)
+    ble_gap_master_failed(reason);
+#endif
+}
+
 #if NIMBLE_BLE_CONNECT
 static int
 ble_gap_accept_master_conn(void)
@@ -1893,7 +1941,7 @@ ble_gap_master_timer(void)
     return BLE_HS_FOREVER;
 }
 
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
 static int32_t
 ble_gap_slave_timer(void)
 {
@@ -1945,7 +1993,6 @@ ble_gap_update_timer(void)
         ble_hs_unlock();
 
         if (entry != NULL) {
-            ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
             ble_gap_update_entry_free(entry);
         }
     } while (entry != NULL);
@@ -1993,7 +2040,7 @@ ble_gap_timer(void)
 
     min_ticks = min(master_ticks, update_ticks);
 
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
     min_ticks = min(min_ticks, ble_gap_slave_timer());
 #endif
 
@@ -5547,7 +5594,7 @@ ble_gap_unpair_oldest_peer(void)
     }
 
     if (num_peers == 0) {
-        return 0;
+        return BLE_HS_ENOENT;
     }
 
     rc = ble_gap_unpair(&oldest_peer_id_addr);
@@ -5558,6 +5605,36 @@ ble_gap_unpair_oldest_peer(void)
     return 0;
 }
 
+int
+ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
+{
+    ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+    int num_peers;
+    int rc, i;
+
+    rc = ble_store_util_bonded_peers(
+            &peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (num_peers == 0) {
+        return BLE_HS_ENOENT;
+    }
+
+    for (i = 0; i < num_peers; i++) {
+        if (ble_addr_cmp(peer_addr, &peer_id_addrs[i]) != 0) {
+            break;
+        }
+    }
+
+    if (i >= num_peers) {
+        return BLE_HS_ENOMEM;
+    }
+
+    return ble_gap_unpair(&peer_id_addrs[i]);
+}
+
 void
 ble_gap_passkey_event(uint16_t conn_handle,
                       struct ble_gap_passkey_params *passkey_params)
@@ -5577,7 +5654,8 @@ ble_gap_passkey_event(uint16_t conn_handle,
 }
 
 void
-ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
+ble_gap_enc_event(uint16_t conn_handle, int status,
+                  int security_restored, int bonded)
 {
 #if NIMBLE_BLE_SM
     struct ble_gap_event event;
@@ -5590,12 +5668,24 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
     ble_gap_event_listener_call(&event);
     ble_gap_call_conn_event_cb(&event, conn_handle);
 
-    if (status == 0) {
-        if (security_restored) {
-            ble_gatts_bonding_restored(conn_handle);
-        } else {
-            ble_gatts_bonding_established(conn_handle);
-        }
+    if (status != 0) {
+        return;
+    }
+
+    /* If encryption succeded and encryption has been restored for bonded device,
+     * notify gatt server so it has chance to send notification/indication if needed.
+     */
+    if (security_restored) {
+        ble_gatts_bonding_restored(conn_handle);
+        return;
+    }
+
+    /* If this is fresh pairing and bonding has been established,
+     * notify gatt server about that so previous subscriptions (before bonding)
+     * can be stored.
+     */
+    if (bonded) {
+        ble_gatts_bonding_established(conn_handle);
     }
 #endif
 }
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
index ce443198..499823bc 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
@@ -116,7 +116,7 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
                                 struct ble_gap_upd_params *params);
 void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev);
 void ble_gap_enc_event(uint16_t conn_handle, int status,
-                       int security_restored);
+                       int security_restored, int bonded);
 void ble_gap_passkey_event(uint16_t conn_handle,
                            struct ble_gap_passkey_params *passkey_params);
 void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
@@ -136,6 +136,7 @@ void ble_gap_preempt(void);
 void ble_gap_preempt_done(void);
 
 int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason);
+void ble_gap_reset_state(int reason);
 void ble_gap_conn_broken(uint16_t conn_handle, int reason);
 int32_t ble_gap_timer(void);
 
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
index 23ac1d14..731e8155 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
@@ -361,7 +361,6 @@ ble_hs_sync(void)
 static int
 ble_hs_reset(void)
 {
-    uint16_t conn_handle;
     int rc;
 
     STATS_INC(ble_hs_stats, reset);
@@ -376,14 +375,8 @@ ble_hs_reset(void)
 
     ble_hs_clear_rx_queue();
 
-    while (1) {
-        conn_handle = ble_hs_atomic_first_conn_handle();
-        if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
-            break;
-        }
-
-        ble_gap_conn_broken(conn_handle, ble_hs_reset_reason);
-    }
+    /* Clear adverising and scanning states. */
+    ble_gap_reset_state(ble_hs_reset_reason);
 
     /* Clear configured addresses. */
     ble_hs_id_reset();
@@ -680,7 +673,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
     /* If flow control is enabled, mark this packet with its corresponding
      * connection handle.
      */
-    ble_hs_flow_fill_acl_usrhdr(om);
+    ble_hs_flow_track_data_mbuf(om);
 
     rc = ble_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
     if (rc != 0) {
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
index f7edb624..ea89460c 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
@@ -327,6 +327,7 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
 #endif
 
     struct ble_hs_conn *conn;
+    struct ble_hs_conn_addrs addrs;
 
     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
 
@@ -343,6 +344,14 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
             if (ble_addr_cmp(&conn->bhc_peer_addr, addr) == 0) {
                 return conn;
             }
+            if (conn->bhc_peer_addr.type < BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT) {
+                continue;
+            }
+            /*If type 0x02 or 0x03 is used, let's double check if address is good */
+            ble_hs_conn_addrs(conn, &addrs);
+            if (ble_addr_cmp(&addrs.peer_id_addr, addr) == 0) {
+                return conn;
+            }
         }
     }
 
@@ -472,29 +481,52 @@ ble_hs_conn_timer(void)
     int32_t time_diff;
     uint16_t conn_handle;
 
-    conn_handle = BLE_HS_CONN_HANDLE_NONE;
-    next_exp_in = BLE_HS_FOREVER;
-    now = ble_npl_time_get();
+    for (;;) {
+        conn_handle = BLE_HS_CONN_HANDLE_NONE;
+        next_exp_in = BLE_HS_FOREVER;
+        now = ble_npl_time_get();
 
-    ble_hs_lock();
+        ble_hs_lock();
 
-    /* This loop performs one of two tasks:
-     * 1. Determine if any connections need to be terminated due to timeout.
-     *    If so, break out of the loop and terminate the connection.  This
-     *    function will need to be executed again.
-     * 2. Otherwise, determine when the next timeout will occur.
-     */
-    SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
-        if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
+        /* This loop performs one of two tasks:
+         * 1. Determine if any connections need to be terminated due to timeout.
+         *    If so, break out of the loop and terminate the connection.  This
+         *    function will need to be executed again.
+         * 2. Otherwise, determine when the next timeout will occur.
+         */
+        SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
+            if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
 
 #if MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) != 0
-            /* Check each connection's rx fragment timer.  If too much time
-             * passes after a partial packet is received, the connection is
-             * terminated.
-             */
-            if (conn->bhc_rx_chan != NULL) {
-                time_diff = conn->bhc_rx_timeout - now;
+                /* Check each connection's rx fragment timer.  If too much time
+                 * passes after a partial packet is received, the connection is
+                 * terminated.
+                 */
+                if (conn->bhc_rx_chan != NULL) {
+                    time_diff = conn->bhc_rx_timeout - now;
 
+                    if (time_diff <= 0) {
+                        /* ACL reassembly has timed out.  Remember the connection
+                         * handle so it can be terminated after the mutex is
+                         * unlocked.
+                         */
+                        conn_handle = conn->bhc_handle;
+                        break;
+                    }
+
+                    /* Determine if this connection is the soonest to time out. */
+                    if (time_diff < next_exp_in) {
+                        next_exp_in = time_diff;
+                    }
+                }
+#endif
+
+#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
+                /* Check each connection's rx queued write timer.  If too much
+                 * time passes after a prep write is received, the queue is
+                 * cleared.
+                 */
+                time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
                 if (time_diff <= 0) {
                     /* ACL reassembly has timed out.  Remember the connection
                      * handle so it can be terminated after the mutex is
@@ -508,45 +540,22 @@ ble_hs_conn_timer(void)
                 if (time_diff < next_exp_in) {
                     next_exp_in = time_diff;
                 }
-            }
 #endif
-
-#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
-            /* Check each connection's rx queued write timer.  If too much
-             * time passes after a prep write is received, the queue is
-             * cleared.
-             */
-            time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
-            if (time_diff <= 0) {
-                /* ACL reassembly has timed out.  Remember the connection
-                 * handle so it can be terminated after the mutex is
-                 * unlocked.
-                 */
-                conn_handle = conn->bhc_handle;
-                break;
             }
-
-            /* Determine if this connection is the soonest to time out. */
-            if (time_diff < next_exp_in) {
-                next_exp_in = time_diff;
-            }
-#endif
         }
+
+        ble_hs_unlock();
+
+        /* If a connection has timed out, terminate it.  We need to repeatedly
+         * call this function again to determine when the next timeout is.
+         */
+        if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
+            ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+            continue;
+        }
+
+        return next_exp_in;
     }
-
-    ble_hs_unlock();
-
-    /* If a connection has timed out, terminate it.  We need to recursively
-     * call this function again to determine when the next timeout is.  This
-     * is a tail-recursive call, so it should be optimized to execute in the
-     * same stack frame.
-     */
-    if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
-        ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
-        return ble_hs_conn_timer();
-    }
-
-    return next_exp_in;
 }
 
 int
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
index d224e6ee..2520c854 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
@@ -40,6 +40,23 @@ static ble_npl_event_fn ble_hs_flow_event_cb;
 
 static struct ble_npl_event ble_hs_flow_ev;
 
+/* Connection handle associated with each mbuf in ACL pool */
+static uint16_t ble_hs_flow_mbuf_conn_handle[ MYNEWT_VAL(BLE_ACL_BUF_COUNT) ];
+
+static inline int
+ble_hs_flow_mbuf_index(const struct os_mbuf *om)
+{
+    const struct os_mempool *mp = om->om_omp->omp_pool;
+    uintptr_t addr = (uintptr_t)om;
+    int idx;
+
+    idx = (addr - mp->mp_membuf_addr) / mp->mp_block_size;
+
+    BLE_HS_DBG_ASSERT(mp->mp_membuf_addr + idx * mp->mp_block_size == addr);
+
+    return idx;
+}
+
 static int
 ble_hs_flow_tx_num_comp_pkts(void)
 {
@@ -143,18 +160,13 @@ ble_hs_flow_acl_free(struct os_mempool_ext *mpe, void *data, void *arg)
     struct ble_hs_conn *conn;
     const struct os_mbuf *om;
     uint16_t conn_handle;
+    int idx;
     int rc;
 
     om = data;
 
-    /* An ACL data packet must be a single mbuf, and it must contain the
-     * corresponding connection handle in its user header.
-     */
-    assert(OS_MBUF_IS_PKTHDR(om));
-    assert(OS_MBUF_USRHDR_LEN(om) >= sizeof conn_handle);
-
-    /* Copy the connection handle out of the mbuf. */
-    memcpy(&conn_handle, OS_MBUF_USRHDR(om), sizeof conn_handle);
+    idx = ble_hs_flow_mbuf_index(om);
+    conn_handle = ble_hs_flow_mbuf_conn_handle[idx];
 
     /* Free the mbuf back to its pool. */
     rc = os_memblock_put_from_cb(&mpe->mpe_mp, data);
@@ -190,23 +202,19 @@ ble_hs_flow_connection_broken(uint16_t conn_handle)
 }
 
 /**
- * Fills the user header of an incoming data packet.  On function return, the
- * header contains the connection handle associated with the sender.
+ * Associates incoming data packet with a connection handle of the sender.
  *
  * If flow control is disabled, this function is a no-op.
  */
 void
-ble_hs_flow_fill_acl_usrhdr(struct os_mbuf *om)
+ble_hs_flow_track_data_mbuf(struct os_mbuf *om)
 {
 #if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
     const struct hci_data_hdr *hdr;
-    uint16_t *conn_handle;
-
-    BLE_HS_DBG_ASSERT(OS_MBUF_USRHDR_LEN(om) >= sizeof *conn_handle);
-    conn_handle = OS_MBUF_USRHDR(om);
+    int idx = ble_hs_flow_mbuf_index(om);
 
     hdr = (void *)om->om_data;
-    *conn_handle = BLE_HCI_DATA_HANDLE(hdr->hdh_handle_pb_bc);
+    ble_hs_flow_mbuf_conn_handle[idx] = BLE_HCI_DATA_HANDLE(hdr->hdh_handle_pb_bc);
 #endif
 }
 
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
index b1aa8c2f..753eaf8f 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
@@ -26,7 +26,7 @@ extern "C" {
 #endif
 
 void ble_hs_flow_connection_broken(uint16_t conn_handle);
-void ble_hs_flow_fill_acl_usrhdr(struct os_mbuf *om);
+void ble_hs_flow_track_data_mbuf(struct os_mbuf *om);
 int ble_hs_flow_startup(void);
 
 #ifdef __cplusplus
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
index a334a747..ac472a9e 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
@@ -447,8 +447,8 @@ ble_hs_hci_acl_hdr_prepend(struct os_mbuf *om, uint16_t handle,
     struct hci_data_hdr hci_hdr;
     struct os_mbuf *om2;
 
-    hci_hdr.hdh_handle_pb_bc =
-        ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0);
+    put_le16(&hci_hdr.hdh_handle_pb_bc,
+             ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0));
     put_le16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
 
     om2 = os_mbuf_prepend(om, sizeof hci_hdr);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
index 6c6da467..dfb46b74 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
@@ -56,7 +56,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
     return rc;
 }
 
-void
+int
 ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
                                 struct ble_hs_conn **out_conn,
                                 struct ble_l2cap_chan **out_chan)
@@ -66,7 +66,9 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
     int rc;
 
     rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
-    BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+    if (rc != 0) {
+        return rc;
+    }
 
     if (out_conn != NULL) {
         *out_conn = conn;
@@ -74,6 +76,8 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
     if (out_chan != NULL) {
         *out_chan = chan;
     }
+
+    return 0;
 }
 
 uint8_t
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
index 2cad6ef1..538d07a9 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
@@ -114,9 +114,9 @@ int ble_hs_hci_evt_acl_process(struct os_mbuf *om);
 int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
                                struct ble_hs_conn **out_conn,
                                struct ble_l2cap_chan **out_chan);
-void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
-                                     struct ble_hs_conn **out_conn,
-                                     struct ble_l2cap_chan **out_chan);
+int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
+                                    struct ble_hs_conn **out_conn,
+                                    struct ble_l2cap_chan **out_chan);
 uint8_t ble_hs_misc_own_addr_type_to_id(uint8_t addr_type);
 uint8_t ble_hs_misc_peer_addr_type_to_id(uint8_t addr_type);
 int ble_hs_misc_restore_irks(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
index 41a83156..8dc367ed 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
@@ -73,7 +73,7 @@ ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu,
 
     srv = ble_l2cap_coc_srv_alloc();
     if (!srv) {
-            return BLE_HS_ENOMEM;
+        return BLE_HS_ENOMEM;
     }
 
     srv->psm = psm;
@@ -392,6 +392,8 @@ ble_l2cap_event_coc_unstalled(struct ble_l2cap_chan *chan, int status)
     chan->cb(&event, chan->cb_arg);
 }
 
+/* WARNING: this function is called from different task contexts. We expect the
+ * host to be locked (ble_hs_lock()) before entering this function! */
 static int
 ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
 {
@@ -406,6 +408,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
     /* If there is no data to send, just return success */
     tx = &chan->coc_tx;
     if (!tx->sdu) {
+        ble_hs_unlock();
         return 0;
     }
 
@@ -440,6 +443,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
             BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", OS_MBUF_PKTLEN(tx->sdu));
             rc = os_mbuf_append(txom, &l, sizeof(uint16_t));
             if (rc) {
+                rc = BLE_HS_ENOMEM;
                 BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
                 goto failed;
             }
@@ -452,55 +456,63 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
         rc = os_mbuf_appendfrom(txom, tx->sdu, tx->data_offset,
                                 len - sdu_size_offset);
         if (rc) {
+            rc = BLE_HS_ENOMEM;
             BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
-           goto failed;
+            goto failed;
         }
 
-        ble_hs_lock();
         conn = ble_hs_conn_find_assert(chan->conn_handle);
         rc = ble_l2cap_tx(conn, chan, txom);
-        ble_hs_unlock();
 
         if (rc) {
-          /* txom is consumed by l2cap */
-          txom = NULL;
-          goto failed;
+            /* txom is consumed by l2cap */
+            txom = NULL;
+            goto failed;
         } else {
-            tx->credits --;
+            tx->credits--;
             tx->data_offset += len - sdu_size_offset;
         }
 
         BLE_HS_LOG(DEBUG, "Sent %d bytes, credits=%d, to send %d bytes \n",
-                  len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset );
+                  len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset);
 
         if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdu)) {
-                BLE_HS_LOG(DEBUG, "Complete package sent\n");
-                os_mbuf_free_chain(tx->sdu);
-                tx->sdu = 0;
-                tx->data_offset = 0;
-                if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
-                    ble_l2cap_event_coc_unstalled(chan, 0);
-                    tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
-                }
-                break;
+            BLE_HS_LOG(DEBUG, "Complete package sent\n");
+            os_mbuf_free_chain(tx->sdu);
+            tx->sdu = NULL;
+            tx->data_offset = 0;
+            break;
         }
     }
 
     if (tx->sdu) {
         /* Not complete SDU sent, wait for credits */
         tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
+        ble_hs_unlock();
         return BLE_HS_ESTALLED;
     }
 
+    if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
+        tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+        ble_hs_unlock();
+        ble_l2cap_event_coc_unstalled(chan, 0);
+    } else {
+        ble_hs_unlock();
+    }
+
     return 0;
 
 failed:
     os_mbuf_free_chain(tx->sdu);
     tx->sdu = NULL;
+
     os_mbuf_free_chain(txom);
     if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
-        ble_l2cap_event_coc_unstalled(chan, rc);
         tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+        ble_hs_unlock();
+        ble_l2cap_event_coc_unstalled(chan, rc);
+    } else {
+        ble_hs_unlock();
     }
 
     return rc;
@@ -535,7 +547,8 @@ ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
     }
 
     chan->coc_tx.credits += credits;
-    ble_hs_unlock();
+
+    /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
     ble_l2cap_coc_continue_tx(chan);
 }
 
@@ -584,18 +597,22 @@ ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx)
 {
     struct ble_l2cap_coc_endpoint *tx;
 
-    tx = &chan->coc_tx;
 
-    if (tx->sdu) {
-        return BLE_HS_EBUSY;
-    }
+    tx = &chan->coc_tx;
 
     if (OS_MBUF_PKTLEN(sdu_tx) > tx->mtu) {
         return BLE_HS_EBADDATA;
     }
 
+    ble_hs_lock();
+    if (tx->sdu) {
+        ble_hs_unlock();
+        return BLE_HS_EBUSY;
+    }
     tx->sdu = sdu_tx;
 
+
+    /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
     return ble_l2cap_coc_continue_tx(chan);
 }
 
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
index bb4d8a5a..ad81c64a 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
@@ -508,8 +508,13 @@ ble_l2cap_sig_update(uint16_t conn_handle,
     STATS_INC(ble_l2cap_stats, update_init);
 
     ble_hs_lock();
-    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
-                                    &conn, &chan);
+    rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+                                         &conn, &chan);
+    if (rc != 0) {
+        ble_hs_unlock();
+        goto done;
+    }
+
     master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
     ble_hs_unlock();
 
@@ -656,8 +661,8 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
             continue;
         }
 
-        if ((status == 0) && (chan->dcid != 0)) {
-            ble_l2cap_event_coc_connected(chan, status);
+        if (chan->dcid != 0) {
+            ble_l2cap_event_coc_connected(chan, 0);
             /* Let's forget about connected channel now.
              * Not connected will be freed later on.
              */
@@ -859,6 +864,7 @@ ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
 
     rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
     ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+    ble_l2cap_sig_proc_free(proc);
 
     return 0;
 }
@@ -1061,7 +1067,15 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
 
     if (rsp->result) {
         rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
-        goto done;
+        /* Below results means that some of the channels has not been created
+         * and we have to look closer into the response.
+         * Any other results means that all the connections has been refused.
+         */
+        if ((rsp->result != BLE_L2CAP_COC_ERR_NO_RESOURCES) &&
+            (rsp->result != BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID) &&
+            (rsp->result != BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED)) {
+            goto done;
+        }
     }
 
     ble_hs_lock();
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
index 366dde62..510420f0 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -28,9 +28,11 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
     int rc;
 
     ble_hs_lock();
-    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
-                                    &conn, &chan);
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+                                         &conn, &chan);
+    if (rc == 0) {
+        rc = ble_l2cap_tx(conn, chan, txom);
+    }
     ble_hs_unlock();
 
     return rc;
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c b/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
index 6057e7e2..55524f2d 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
@@ -29,7 +29,6 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <inttypes.h>
-#include <libs/mynewt-nimble/porting/nimble/include/os/os_cputime.h>
 #include "os/os.h"
 #include "log/log.h"
 #if MYNEWT_VAL(BLE_MONITOR_UART)
@@ -162,7 +161,7 @@ update_drop_counters(struct ble_monitor_hdr *failed_hdr)
 
     if (*cnt < UINT8_MAX) {
         (*cnt)++;
-        ble_npl_callout_reset(&rtt_drops.tmo, OS_TICKS_PER_SEC);
+        ble_npl_callout_reset(&rtt_drops.tmo, portMAX_DELAY);
     }
 }
 
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
index cfd80fcb..91afb75c 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
@@ -938,7 +938,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
 
         if (res->enc_cb) {
             BLE_HS_DBG_ASSERT(proc == NULL || rm);
-            ble_gap_enc_event(conn_handle, res->app_status, res->restore);
+            ble_gap_enc_event(conn_handle, res->app_status, res->restore, res->bonded);
         }
 
         if (res->app_status == 0 &&
@@ -1190,6 +1190,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
 
     ble_hs_unlock();
 
+    res.bonded = bonded;
     ble_sm_process_result(conn_handle, &res);
 }
 
@@ -2425,7 +2426,7 @@ ble_sm_timer(void)
      * procedures without reconnect.
      */
     while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
-        ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0);
+        ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0, 0);
 
         STAILQ_REMOVE_HEAD(&exp_list, next);
         ble_sm_proc_free(proc);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
index 50fd77ec..148995c8 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
@@ -68,8 +68,6 @@ ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext,
 
     swap_buf(tmp, plaintext, 16);
 
-
-
     if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
         return BLE_HS_EUNKNOWN;
     }
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
index 5eef798d..01651f1d 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
@@ -52,12 +52,17 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
 {
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
+    int rc;
 
     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
 
     STATS_INC(ble_l2cap_stats, sm_tx);
 
-    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
-                                    &conn, &chan);
-    return ble_l2cap_tx(conn, chan, txom);
+    rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
+                                         &conn, &chan);
+    if (rc == 0) {
+        rc = ble_l2cap_tx(conn, chan, txom);
+    }
+
+    return rc;
 }
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
index 6d5601bf..27e75aa1 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
@@ -279,10 +279,10 @@ struct ble_sm_result {
     uint8_t sm_err;
     struct ble_gap_passkey_params passkey_params;
     void *state_arg;
-    unsigned execute:1;
-    unsigned enc_cb:1;
-    unsigned persist_keys:1;
-    unsigned restore:1;
+    unsigned execute : 1;
+    unsigned enc_cb : 1;
+    unsigned bonded : 1;
+    unsigned restore : 1;
 };
 
 #if MYNEWT_VAL(BLE_HS_DEBUG)
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c b/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
index 444cc55d..7de48272 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
@@ -233,13 +233,15 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
     switch (event->event_code) {
     case BLE_STORE_EVENT_OVERFLOW:
         switch (event->overflow.obj_type) {
-            case BLE_STORE_OBJ_TYPE_OUR_SEC:
-            case BLE_STORE_OBJ_TYPE_PEER_SEC:
-            case BLE_STORE_OBJ_TYPE_CCCD:
-                return ble_gap_unpair_oldest_peer();
+        case BLE_STORE_OBJ_TYPE_OUR_SEC:
+        case BLE_STORE_OBJ_TYPE_PEER_SEC:
+            return ble_gap_unpair_oldest_peer();
+        case BLE_STORE_OBJ_TYPE_CCCD:
+            /* Try unpairing oldest peer except current peer */
+            return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr);
 
-            default:
-                return BLE_HS_EUNKNOWN;
+        default:
+            return BLE_HS_EUNKNOWN;
         }
 
     case BLE_STORE_EVENT_FULL:
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
index ce60d1fb..cc1d59af 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
@@ -23,7 +23,6 @@
 #include "sysinit/sysinit.h"
 #include "syscfg/syscfg.h"
 #include "host/ble_hs.h"
-#include "config/config.h"
 #include "base64/base64.h"
 #include "store/config/ble_store_config.h"
 #include "ble_store_config_priv.h"
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
index 842fb5f3..19372f17 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
@@ -17,6 +17,11 @@
  * under the License.
  */
 
+/* This package has been deprecated and you should
+ * use the store/config package. For a RAM-only BLE store,
+ * use store/config and set BLE_STORE_CONFIG_PERSIST to 0.
+ */
+
 #ifndef H_BLE_STORE_RAM_
 #define H_BLE_STORE_RAM_
 
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
index ab5cdb9f..b912ea47 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
@@ -23,6 +23,11 @@
  * contents are lost when the application terminates.
  */
 
+/* This package has been deprecated and you should
+ * use the store/config package. For a RAM-only BLE store,
+ * use store/config and set BLE_STORE_CONFIG_PERSIST to 0.
+ */
+
 #include <inttypes.h>
 #include <string.h>
 
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
index 442211dd..91c55fd8 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
@@ -20,4 +20,13 @@ syscfg.defs:
         description: >
             Sysinit stage for the RAM BLE store.
         value: 500
+    BLE_STORE_RAM_DEPRECATED_FLAG:
+        description: >
+            Package store/ram is deprecated and store/config shall be used with BLE_STORE_CONFIG_PERSIST set to 0
+        value: 0
+        deprecated: 1
+
+
+syscfg.vals:
+    BLE_STORE_RAM_DEPRECATED_FLAG: 1
 
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
index 3962bacc..7496e316 100644
--- a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
@@ -2049,70 +2049,6 @@ ble_gap_test_util_update_l2cap(struct ble_gap_upd_params *params,
                        peer_addr, 6) == 0);
 }
 
-static void
-ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
-                                      int master)
-{
-    struct ble_hs_conn *conn;
-    int rc;
-
-    uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
-
-    ble_gap_test_util_init();
-
-    ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
-                                 NULL);
-
-    if (!master) {
-        ble_hs_lock();
-        conn = ble_hs_conn_find(2);
-        TEST_ASSERT_FATAL(conn != NULL);
-        conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
-        ble_hs_unlock();
-    }
-
-    /* Erase callback info reported during connection establishment; we only
-     * care about updates.
-     */
-    ble_gap_test_util_reset_cb_info();
-
-    TEST_ASSERT(!ble_gap_master_in_progress());
-
-    rc = ble_hs_test_util_conn_update(2, params, 0);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(!ble_gap_master_in_progress());
-
-    /* Verify tx of connection update command. */
-    ble_gap_test_util_verify_tx_update_conn(params);
-
-    /* Ensure no update event reported. */
-    TEST_ASSERT(ble_gap_test_event.type == 0xff);
-
-    /* Advance 39 seconds; ensure no timeout reported. */
-    os_time_advance(39 * OS_TICKS_PER_SEC);
-    ble_gap_timer();
-    TEST_ASSERT(ble_gap_test_event.type == 0xff);
-
-    /* Advance 40th second; ensure timeout reported. */
-    os_time_advance(1 * OS_TICKS_PER_SEC);
-
-    /* Timeout will result in a terminate HCI command being sent; schedule ack
-     * from controller.
-     */
-    ble_hs_test_util_hci_ack_set_disconnect(0);
-
-    ble_gap_timer();
-
-    /* Verify terminate was sent. */
-    ble_gap_test_util_verify_tx_disconnect();
-
-    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
-    TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
-    TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
-    TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
-                       peer_addr, 6) == 0);
-}
-
 static void
 ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
                                    uint8_t hci_status, uint8_t event_status,
@@ -2982,9 +2918,6 @@ TEST_CASE_SELF(ble_gap_test_case_update_timeout)
         .max_ce_len = 456,
     };
 
-    /* No L2CAP. */
-    ble_gap_test_util_update_no_l2cap_tmo(&params, 1);
-
     /* L2CAP - Local unsupported; L2CAP timeout. */
     ble_gap_test_util_update_l2cap_tmo(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
 
diff --git a/src/libs/mynewt-nimble/nimble/include/nimble/ble.h b/src/libs/mynewt-nimble/nimble/include/nimble/ble.h
index 3fc2902e..248e8ae8 100644
--- a/src/libs/mynewt-nimble/nimble/include/nimble/ble.h
+++ b/src/libs/mynewt-nimble/nimble/include/nimble/ble.h
@@ -81,7 +81,14 @@ struct ble_mbuf_hdr_rxinfo
 #endif
 };
 
-/* Flag definitions for rxinfo  */
+/*
+ * Flag definitions for rxinfo
+ *
+ * Note: it's ok to have symbols with the same values as long as they cannot be
+ *       set for the same PDU (e.g. one use by scanner, other one used by
+ *       connection)
+ */
+#define BLE_MBUF_HDR_F_CONN_CREDIT      (0x8000)
 #define BLE_MBUF_HDR_F_IGNORED          (0x8000)
 #define BLE_MBUF_HDR_F_SCAN_REQ_TXD     (0x4000)
 #define BLE_MBUF_HDR_F_INITA_RESOLVED   (0x2000)
diff --git a/src/libs/mynewt-nimble/nimble/include/nimble/hci_common.h b/src/libs/mynewt-nimble/nimble/include/nimble/hci_common.h
index c79abb31..3df8dd66 100644
--- a/src/libs/mynewt-nimble/nimble/include/nimble/hci_common.h
+++ b/src/libs/mynewt-nimble/nimble/include/nimble/hci_common.h
@@ -108,7 +108,7 @@ struct ble_hci_cb_ctlr_to_host_fc_cp {
 #define BLE_HCI_OCF_CB_HOST_BUF_SIZE        (0x0033)
 struct ble_hci_cb_host_buf_size_cp {
     uint16_t acl_data_len;
-    uint16_t sco_data_len;
+    uint8_t  sco_data_len;
     uint16_t acl_num;
     uint16_t sco_num;
 } __attribute__((packed));
@@ -201,6 +201,14 @@ struct ble_hci_le_rd_buf_size_rp {
     uint8_t  data_packets;
 } __attribute__((packed));
 
+#define BLE_HCI_OCF_LE_RD_BUF_SIZE_V2                    (0x0060)
+struct ble_hci_le_rd_buf_size_v2_rp {
+    uint16_t data_len;
+    uint8_t  data_packets;
+    uint16_t iso_data_len;
+    uint8_t  iso_data_packets;
+} __attribute__((packed));
+
 #define BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT             (0x0003)
 struct ble_hci_le_rd_loc_supp_feat_rp {
     uint64_t features;
@@ -825,6 +833,228 @@ struct ble_hci_le_set_default_periodic_sync_transfer_params_cp {
 #define BLE_HCI_OCF_LE_GENERATE_DHKEY_V2                 (0x005E)
 #define BLE_HCI_OCF_LE_MODIFY_SCA                        (0x005F)
 
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_READ_ISO_TX_SYNC                  (0x0061)
+struct ble_hci_le_read_iso_tx_sync_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_read_iso_tx_sync_rp {
+    uint16_t conn_handle;
+    uint16_t packet_seq_num;
+    uint32_t timestamp;
+    uint8_t timeoffset[3];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SET_CIG_CIS_MAX_NUM                   (0x1F)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM                     (0x0062)
+struct ble_hci_le_cis_params {
+    uint8_t cis_id;
+    uint16_t max_sdu_mtos;
+    uint16_t max_sdu_stom;
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t rnt_mtos;
+    uint8_t rnt_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_cp {
+    uint8_t cig_id;
+    uint8_t sdu_interval_mtos[3];
+    uint8_t sdu_interval_stom[3];
+    uint8_t sca;
+    uint8_t packing;
+    uint8_t framing;
+    uint16_t max_latency_mtos;
+    uint16_t max_latency_stom;
+    uint8_t cis_cnt;
+    struct ble_hci_le_cis_params cis_params[0];
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_rp {
+    uint8_t cig_id;
+    uint8_t cis_cnt;
+    uint16_t cis_handle[0];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST                (0x0063)
+struct ble_hci_le_cis_params_test {
+    uint8_t cis_id;
+    uint8_t nse;
+    uint16_t max_sdu_mtos;
+    uint16_t max_sdu_stom;
+    uint16_t max_pdu_mtos;
+    uint16_t max_pdu_stom;
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t bn_mtos;
+    uint8_t bn_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_test_cp {
+    uint8_t cig_id;
+    uint8_t sdu_interval_mtos[3];
+    uint8_t sdu_interval_stom[3];
+    uint8_t ft_mtos;
+    uint8_t ft_stom;
+    uint16_t iso_interval;
+    uint8_t sca;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t cis_cnt;
+    struct ble_hci_le_cis_params_test cis_params[0];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_LE_CREATE_CIS_MAX_CIS_NUM                (0x1F)
+#define BLE_HCI_OCF_LE_CREATE_CIS                        (0x0064)
+struct ble_hci_le_create_cis_params {
+    uint16_t cis_handle;
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_create_cis_cp {
+    uint8_t cis_cnt;
+    struct ble_hci_le_create_cis_params params[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REMOVE_CIG                        (0x0065)
+struct ble_hci_le_remove_cig_cp {
+    uint8_t cig_id;
+} __attribute__((packed));
+
+struct ble_hci_le_remove_cig_rp {
+    uint8_t cig_id;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ACCEPT_CIS_REQ                    (0x0066)
+struct ble_hci_le_accept_cis_request_cp {
+    uint16_t cis_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REJECT_CIS_REQ                    (0x0067)
+struct ble_hci_le_reject_cis_request_cp {
+    uint16_t cis_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+struct ble_hci_le_reject_cis_request_rp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CREATE_BIG                        (0x0068)
+struct ble_hci_le_create_big_cp {
+    uint8_t big_handle;
+    uint8_t adv_handle;
+    uint8_t bis_cnt;
+    uint8_t sdu_interval[3];
+    uint16_t max_sdu;
+    uint16_t max_transport_latency;
+    uint8_t rnt;
+    uint8_t phy;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_CREATE_BIG_TEST                   (0x0069)
+struct ble_hci_le_create_big_test_cp {
+    uint8_t big_handle;
+    uint8_t adv_handle;
+    uint8_t bis_cnt;
+    uint8_t sdu_interval[3];
+    uint16_t iso_interval;
+    uint8_t nse;
+    uint16_t max_sdu;
+    uint16_t max_pdu;
+    uint8_t phy;
+    uint8_t packing;
+    uint8_t framing;
+    uint8_t bn;
+    uint8_t irc;
+    uint8_t pto;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_TERMINATE_BIG                     (0x006a)
+struct ble_hci_le_terminate_big_cp {
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_BIG_CREATE_SYNC_LEN_MIN               (25)
+#define BLE_HCI_OCF_LE_BIG_CREATE_SYNC                   (0x006b)
+struct ble_hci_le_big_create_sync_cp {
+    uint8_t big_handle;
+    uint16_t sync_handle;
+    uint8_t big_cnt;
+    uint8_t encryption;
+    uint8_t broadcast_code[16];
+    uint8_t mse;
+    uint16_t timeout;
+    uint8_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC                (0x006c)
+struct ble_hci_le_terminate_big_sync_cp {
+    uint8_t big_handle;
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_REQ_PEER_SCA                      (0x006d)
+struct ble_hci_le_request_peer_sca_cp {
+    uint16_t conn_handle;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH               (0x006e)
+struct ble_hci_le_iso_setup_data_path_cp {
+    uint16_t iso_handle;
+    uint8_t direction;
+    uint8_t id;
+    uint8_t codec_id[5];
+    uint8_t controller_delay[3];
+    uint8_t codec_conf_len;
+    uint8_t codec_conf[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_REMOVE_INPUT_DATA_PATH_BIT            (0x01)
+#define BLE_HCI_LE_REMOVE_OUTPUT_DATA_PATH_BIT           (0x02)
+#define BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH              (0x006f)
+struct ble_hci_le_iso_remove_data_path_cp {
+    uint16_t iso_handle;
+    uint8_t direction;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST                 (0x0070)
+struct ble_hci_le_iso_transmit_test_cp {
+    uint16_t iso_handle;
+    uint8_t payload_type;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_RECEIVE_TEST                  (0x0071)
+struct ble_hci_le_iso_receive_test_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS            (0x0072)
+struct ble_hci_le_iso_read_test_counters_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_TEST_END                      (0x0073)
+struct ble_hci_le_iso_test_end_cp {
+    uint16_t iso_handle;
+} __attribute__((packed));
+#endif
+#endif
+
 #define BLE_HCI_OCF_LE_SET_HOST_FEAT                     (0x0074)
 struct ble_hci_le_set_host_feat_cp {
     uint8_t bit_num;
@@ -1212,7 +1442,7 @@ struct ble_hci_ev_auth_pyld_tmo {
 struct ble_hci_ev_vendor_debug {
     uint8_t id;
     uint8_t data[0];
-}__attribute__((packed));
+} __attribute__((packed));
 
 /* LE sub-event codes */
 #define BLE_HCI_LE_SUBEV_CONN_COMPLETE          (0x01)
@@ -1444,6 +1674,110 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_transfer {
     uint8_t  aca;
 } __attribute__((packed));
 
+#define BLE_HCI_LE_SUBEV_CIS_ESTAB              (0x19)
+struct ble_hci_ev_le_subev_cis_established {
+    uint8_t subev_code;
+    uint8_t status;
+    uint16_t cis_handle;
+    uint8_t cig_sync_delay[3];
+    uint8_t cis_sync_delay[3];
+    uint8_t trans_latency_mtos[3];
+    uint8_t trans_latency_stom[3];
+    uint8_t phy_mtos;
+    uint8_t phy_stom;
+    uint8_t nse;
+    uint8_t bn_mtos;
+    uint8_t bn_stom;
+    uint8_t ft_mtos;
+    uint8_t ft_stom;
+    uint16_t max_pdu_mtos;
+    uint16_t max_pdu_stom;
+    uint16_t iso_interval;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CIS_REQUEST            (0x1A)
+struct ble_hci_ev_le_subev_cis_request {
+    uint8_t subev_code;
+    uint16_t conn_handle;
+    uint16_t cis_handle;
+    uint8_t cig_id;
+    uint8_t cis_id;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_COMP               (0x1B)
+struct ble_hci_ev_le_subev_big_complete {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t big_handle;
+    uint8_t big_sync_delay[3];
+    uint8_t transport_latency[3];
+    uint8_t phy;
+    uint8_t nse;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint16_t iso_interval;
+    uint8_t bis_cnt;
+    uint16_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_TERMINATE_COMP     (0x1C)
+struct ble_hci_ev_le_subev_big_terminate_complete {
+    uint8_t subev_code;
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_ESTAB         (0x1D)
+struct ble_hci_ev_le_subev_big_sync_established {
+    uint8_t subev_code;
+    uint8_t status;
+    uint8_t big_handle;
+    uint8_t transport_latency[3];
+    uint8_t nse;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint16_t iso_interval;
+    uint8_t bis_cnt;
+    uint16_t bis_handles[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_LOST          (0x1E)
+struct ble_hci_ev_le_subev_big_sync_lost {
+    uint8_t subev_code;
+    uint8_t big_handle;
+    uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP      (0x1F)
+struct ble_hci_ev_le_subev_peer_sca_complete {
+    uint8_t subev_code;
+    uint8_t status;
+    uint16_t conn_handle;
+    uint8_t sca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT         (0x22)
+struct ble_hci_ev_le_subev_biginfo_adv_report {
+    uint8_t subev_code;
+    uint16_t sync_handle;
+    uint8_t bis_cnt;
+    uint8_t nse;
+    uint16_t iso_interval;
+    uint8_t bn;
+    uint8_t pto;
+    uint8_t irc;
+    uint16_t max_pdu;
+    uint8_t sdu_interval[3];
+    uint16_t max_sdu;
+    uint8_t phy;
+    uint8_t framing;
+    uint8_t encryption;
+} __attribute__((packed));
+
 /* Data buffer overflow event */
 #define BLE_HCI_EVENT_ACL_BUF_OVERFLOW      (0x01)
 
diff --git a/src/libs/mynewt-nimble/nimble/syscfg.yml b/src/libs/mynewt-nimble/nimble/syscfg.yml
index 537fd9ba..35a6ef81 100644
--- a/src/libs/mynewt-nimble/nimble/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/syscfg.yml
@@ -77,6 +77,19 @@ syscfg.defs:
             integer for easy comparison.
         range: 50, 51, 52
         value: 50
+    BLE_ISO:
+        description: >
+            This enables LE Isochronous Channels as per Bluetooth v5.2
+        value: 0
+        restrictions:
+            - '(BLE_VERSION >= 52) if 1'
+
+    BLE_ISO_TEST:
+        description: >
+            Enables BLE ISO Testing commands
+        value: 0
+        restrictions:
+            - 'BLE_ISO if 1'
 
 # Allow periodic sync transfer only if 5.1 or higher
 syscfg.restrictions:
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore
new file mode 100644
index 00000000..bba9f995
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore
@@ -0,0 +1,2 @@
+/src/libble_stack_da1469x.a
+
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml
new file mode 100644
index 00000000..9b9ee83e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml
@@ -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.
+#
+
+pkg.name: nimble/transport/dialog_cmac/cmac_driver/diag
+pkg.description: Default diag configuration for CMAC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - dialog
+    - da1469x
+    - cmac
+pkg.apis: dialog_cmac_diag
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c
new file mode 100644
index 00000000..4f754706
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c
@@ -0,0 +1,68 @@
+/*
+ * 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"
+#include "mcu/mcu.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+void
+cmac_diag_setup_host(void)
+{
+    /* Setup pins for diagnostic signals */
+    mcu_gpio_set_pin_function(42, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG0); /* DIAG_0 @ P1.10 */
+    mcu_gpio_set_pin_function(43, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG1); /* DIAG_1 @ P1.11 */
+    mcu_gpio_set_pin_function(44, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG2); /* DIAG_2 @ P1.12 */
+    mcu_gpio_set_pin_function(24, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_3 @ P0.24 */
+    mcu_gpio_set_pin_function(21, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_4 @ P0.21 */
+    mcu_gpio_set_pin_function(20, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_5 @ P0.20 */
+    mcu_gpio_set_pin_function(19, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_6 @ P0.19 */
+    mcu_gpio_set_pin_function(18, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_7 @ P0.18 */
+    mcu_gpio_set_pin_function(31, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_8 @ P0.31 */
+    mcu_gpio_set_pin_function(30, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_9 @ P0.30 */
+    mcu_gpio_set_pin_function(29, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_10 @ P0.29 */
+    mcu_gpio_set_pin_function(28, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_11 @ P0.28 */
+    mcu_gpio_set_pin_function(27, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_12 @ P0.27 */
+    mcu_gpio_set_pin_function(26, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_13 @ P0.26 */
+    mcu_gpio_set_pin_function(38, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_14 @ P1.06 */
+    mcu_gpio_set_pin_function(41, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_15 @ P1.09 */
+}
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+void
+cmac_diag_setup_cmac(void)
+{
+    MCU_DIAG_MAP( 0, 4, DSER);
+    MCU_DIAG_MAP( 1, 6, CMAC_ON_ERROR);
+    MCU_DIAG_MAP( 2, 2, PHY_TX_EN);
+    MCU_DIAG_MAP( 3, 2, PHY_RX_EN);
+    MCU_DIAG_MAP( 4, 2, PHY_TXRX_DATA_COMB);
+    MCU_DIAG_MAP( 5, 2, PHY_TXRX_DATA_EN_COMB);
+    MCU_DIAG_MAP( 6, 5, EV1US_FRAME_START);
+    MCU_DIAG_MAP( 7, 5, EV_BS_START);
+    MCU_DIAG_MAP( 8, 5, EV1C_BS_STOP);
+    MCU_DIAG_MAP( 9, 5, EV1US_PHY_TO_IDLE);
+    MCU_DIAG_MAP(10, 9, CALLBACK_IRQ);
+    MCU_DIAG_MAP(11, 9, FIELD_IRQ);
+    MCU_DIAG_MAP(12, 9, FRAME_IRQ);
+    MCU_DIAG_MAP(13, 3, SLP_TIMER_ACTIVE);
+    MCU_DIAG_MAP(14, 4, SLEEPING);
+    MCU_DIAG_MAP(15, 8, LL_TIMER1_00);
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h
new file mode 100644
index 00000000..dc6ee903
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h
@@ -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.
+ */
+
+#ifndef __MCU_CMAC_DIAG_H_
+#define __MCU_CMAC_DIAG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cmac_diag_setup_host(void);
+void cmac_diag_setup_cmac(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CMAC_DIAG_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h
new file mode 100644
index 00000000..50d86755
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h
@@ -0,0 +1,35 @@
+/*
+ * 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 __DA1469X_CMAC_V2_H_
+#define __DA1469X_CMAC_V2_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cmac_host_init(void);
+void cmac_host_signal2cmac(void);
+void cmac_host_rf_calibrate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DA1469X_CMAC_V2_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h
new file mode 100644
index 00000000..90b5827d
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h
@@ -0,0 +1,193 @@
+/*
+ * 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 __MCU_CMAC_SHARED_H_
+#define __MCU_CMAC_SHARED_H_
+
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CMAC_SHARED_MAGIC_CMAC              (0x4C6C) /* "lL" */
+#define CMAC_SHARED_MAGIC_SYS               (0x5368) /* "hS" */
+
+#define CMAC_SHARED_F_SYS_LPCLK_AVAILABLE   (0x0001)
+
+/*
+ * Simple circular buffer for storing random numbers generated by M33
+ *  Empty: cmr_in = cmr_out = 0;
+ *  Full: cmr_in + 1 = cmr_out
+ *
+ *  cmr_in: used by the M33 to add random numbers to the circular buffer.
+ *  cmr_out: used by CMAC to retrieve random numbers
+ *
+ *  NOTE: cmr_in and cmr_out are indices.
+ */
+#define CMAC_RAND_BUF_ELEMS                 (16)
+
+struct cmac_rand {
+    int cmr_active;
+    int cmr_in;
+    int cmr_out;
+    uint32_t cmr_buf[CMAC_RAND_BUF_ELEMS];
+};
+
+struct cmac_mbox {
+    uint16_t rd_off;
+    uint16_t wr_off;
+};
+
+struct cmac_dcdc {
+    uint8_t enabled;
+    uint32_t v18;
+    uint32_t v18p;
+    uint32_t vdd;
+    uint32_t v14;
+    uint32_t ctrl1;
+};
+
+struct cmac_trim {
+    uint8_t rfcu_len;
+    uint8_t rfcu_mode1_len;
+    uint8_t rfcu_mode2_len;
+    uint8_t synth_len;
+    uint32_t rfcu[ MYNEWT_VAL(CMAC_TRIM_SIZE_RFCU) ];
+    uint32_t rfcu_mode1[2];
+    uint32_t rfcu_mode2[2];
+    uint32_t synth[ MYNEWT_VAL(CMAC_TRIM_SIZE_SYNTH) ];
+};
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+struct cmac_debug {
+    int8_t last_rx_rssi;
+    int8_t tx_power_override;
+
+    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;
+};
+#endif
+
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+struct cmac_coredump {
+    uint32_t lr;
+    uint32_t pc;
+    uint32_t assert;
+    const char *assert_file;
+    uint32_t assert_line;
+
+    uint32_t CM_STAT_REG;
+    uint32_t CM_LL_TIMER1_36_10_REG;
+    uint32_t CM_LL_TIMER1_9_0_REG;
+    uint32_t CM_ERROR_REG;
+    uint32_t CM_EXC_STAT_REG;
+};
+#endif
+
+#define CMAC_PENDING_OP_LP_CLK      0x0001
+#define CMAC_PENDING_OP_RF_CAL      0x0002
+
+struct cmac_shared_data {
+    uint16_t magic_cmac;
+    uint16_t magic_sys;
+    uint16_t pending_ops;
+    uint16_t lp_clock_freq;    /* LP clock frequency */
+    uint32_t xtal32m_settle_us;/* XTAL32M settling time */
+    struct cmac_mbox mbox_s2c; /* SYS2CMAC mailbox */
+    struct cmac_mbox mbox_c2s; /* CMAC2SYS mailbox */
+    struct cmac_dcdc dcdc;     /* DCDC settings */
+    struct cmac_trim trim;     /* Trim data */
+    struct cmac_rand rand;     /* Random numbers */
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+    struct cmac_debug debug;   /* Extra debug data */
+#endif
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+    struct cmac_coredump coredump;
+#endif
+
+    uint8_t mbox_s2c_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_S2C) ];
+    uint8_t mbox_c2s_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_C2S) ];
+};
+
+#if MYNEWT_VAL(BLE_HOST)
+extern volatile struct cmac_shared_data *g_cmac_shared_data;
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+extern volatile struct cmac_shared_data g_cmac_shared_data;
+#endif
+
+/* cmac_mbox */
+typedef int (cmac_mbox_read_cb)(const void *data, uint16_t len);
+typedef void (cmac_mbox_write_notif_cb)(void);
+void cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb);
+void cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb);
+int cmac_mbox_read(void);
+int cmac_mbox_write(const void *data, uint16_t len);
+
+/* cmac_rand */
+typedef void (*cmac_rand_isr_cb_t)(uint8_t rnum);
+void cmac_rand_start(void);
+void cmac_rand_stop(void);
+void cmac_rand_read(void);
+void cmac_rand_write(void);
+void cmac_rand_chk_fill(void);
+int cmac_rand_get_next(void);
+int cmac_rand_is_active(void);
+int cmac_rand_is_full(void);
+void cmac_rand_fill(uint32_t *buf, int num_words);
+void cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb);
+
+void cmac_shared_init(void);
+void cmac_shared_sync(void);
+
+#if MYNEWT_VAL(BLE_HOST)
+#define CMAC_SHARED_LOCK_VAL    0x40000000
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+#define CMAC_SHARED_LOCK_VAL    0xc0000000
+#endif
+
+static inline void
+cmac_shared_lock(void)
+{
+    volatile uint32_t *bsr_set = (void *)0x50050074;
+    volatile uint32_t *bsr_stat = (void *)0x5005007c;
+
+    while ((*bsr_stat & 0xc0000000) != CMAC_SHARED_LOCK_VAL) {
+        *bsr_set = CMAC_SHARED_LOCK_VAL;
+    }
+}
+
+static inline void
+cmac_shared_unlock(void)
+{
+    volatile uint32_t *bsr_reset = (void *)0x50050078;
+
+    *bsr_reset = CMAC_SHARED_LOCK_VAL;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CMAC_SHARED_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml
new file mode 100644
index 00000000..5b4a2129
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/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: nimble/transport/dialog_cmac/cmac_driver
+pkg.description: Driver for Dialog CMAC IPC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - dialog
+    - da1469x
+    - cmac
+
+pkg.req_apis.CMAC_DEBUG_DIAG_ENABLE:
+    - dialog_cmac_diag
+
+pkg.ign_files.BLE_CONTROLLER:
+    - cmac_host.c
+
+pkg.post_link_cmds.BLE_CONTROLLER:
+    scripts/create_cmac_bin.sh: 100
+
+pkg.pre_link_cmds.BLE_HOST:
+    scripts/build_libcmac.sh: 100
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh
new file mode 100755
index 00000000..bbc822aa
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# 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.
+
+NEWT=${MYNEWT_NEWT_PATH}
+OBJCOPY=${MYNEWT_OBJCOPY_PATH}
+AR=${MYNEWT_AR_PATH}
+LIBCMAC_A=${MYNEWT_USER_SRC_DIR}/libcmac.a
+
+export WORK_DIR=${MYNEWT_USER_WORK_DIR}
+export BASENAME_ROM=cmac.rom
+export BASENAME_RAM=cmac.ram
+
+if [ ${MYNEWT_VAL_CMAC_IMAGE_SINGLE} -eq 0 ]; then
+    # Create empty binary for ROM image (1 byte required for objcopy)
+    truncate -s 1 ${WORK_DIR}/${BASENAME_ROM}.bin
+    # Create fixed size RAM image
+    truncate -s ${MYNEWT_VAL_CMAC_IMAGE_RAM_SIZE} ${WORK_DIR}/${BASENAME_RAM}.bin
+else
+    ${NEWT} build ${MYNEWT_VAL_CMAC_IMAGE_TARGET_NAME}
+fi
+
+cd ${WORK_DIR}
+
+# Convert both binaries to objects and create archive to link
+${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
+    --rename-section .data=.libcmac.rom ${BASENAME_ROM}.bin ${BASENAME_ROM}.o
+${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
+    --rename-section .data=.libcmac.ram ${BASENAME_RAM}.bin ${BASENAME_RAM}.o
+${AR} -rcs ${LIBCMAC_A} ${BASENAME_ROM}.o ${BASENAME_RAM}.o
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh
new file mode 100755
index 00000000..954d0860
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# 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.
+
+OBJCOPY=${MYNEWT_OBJCOPY_PATH}
+ELF=${MYNEWT_APP_BIN_DIR}/blehci.elf
+
+cd ${WORK_DIR}
+
+# Strip .ram section from ROM image
+${OBJCOPY} -R .ram -O binary ${ELF} ${BASENAME_ROM}.bin
+# RAM image is the same as binary created by newt
+cp ${ELF}.bin ${BASENAME_RAM}.bin
+
+# Create a copy of ROM image to flash to partition, if required
+cp ${BASENAME_ROM}.bin ${ELF}.rom.bin
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c
new file mode 100644
index 00000000..df81c582
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c
@@ -0,0 +1,326 @@
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "sysflash/sysflash.h"
+#include "os/os.h"
+#include "mcu/mcu.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/da1469x_hal.h"
+#include "mcu/da1469x_lpclk.h"
+#include "mcu/da1469x_clock.h"
+#include "mcu/da1469x_trimv.h"
+#include "mcu/da1469x_pdc.h"
+#include "cmac_driver/cmac_host.h"
+#include "cmac_driver/cmac_shared.h"
+#include "cmac_driver/cmac_diag.h"
+#include "trng/trng.h"
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+#include "console/console.h"
+#endif
+
+/* CMAC data */
+extern char _binary_cmac_rom_bin_start[];
+extern char _binary_cmac_rom_bin_end;
+extern char _binary_cmac_ram_bin_start[];
+extern char _binary_cmac_ram_bin_end;
+
+struct cmac_image_info {
+    uint32_t magic;
+    uint32_t size_rom;
+    uint32_t size_ram;
+    uint32_t offset_data;
+    uint32_t offset_shared;
+};
+
+/* PDC entry for waking up CMAC */
+static int8_t g_cmac_host_pdc_sys2cmac;
+/* PDC entry for waking up M33 */
+static int8_t g_cmac_host_pdc_cmac2sys;
+
+static void cmac_host_rand_fill(struct os_event *ev);
+static struct os_event g_cmac_host_rand_ev = {
+    .ev_cb = cmac_host_rand_fill
+};
+
+static void cmac_host_rand_chk_fill(void);
+
+static void
+cmac2sys_isr(void)
+{
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+    volatile struct cmac_coredump *cd = &g_cmac_shared_data->coredump;
+    const char *assert_file;
+#endif
+
+    os_trace_isr_enter();
+
+    /* Clear CMAC2SYS interrupt */
+    *(volatile uint32_t *)0x40002000 = 2;
+
+    cmac_mbox_read();
+
+    if (*(volatile uint32_t *)0x40002000 & 0x1c00) {
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+        console_blocking_mode();
+        console_printf("CMAC error (0x%08lx)\n", *(volatile uint32_t *)0x40002000);
+        console_printf("  lr:0x%08lx  pc:0x%08lx\n", cd->lr, cd->pc);
+        if (cd->assert) {
+            console_printf("  assert:0x%08lx\n", cd->assert);
+            if (cd->assert_file) {
+                /* Need to translate pointer from M0 code segment to M33 data */
+                assert_file = cd->assert_file + MCU_MEM_SYSRAM_START_ADDRESS +
+                              MEMCTRL->CMI_CODE_BASE_REG;
+                console_printf("         %s:%d\n",
+                               assert_file, (unsigned)cd->assert_line);
+            }
+        }
+        console_printf("  0x%08lx CM_ERROR_REG\n", cd->CM_ERROR_REG);
+        console_printf("  0x%08lx CM_EXC_STAT_REG\n", cd->CM_EXC_STAT_REG);
+        console_printf("  0x%08lx CM_LL_TIMER1_36_10_REG\n", cd->CM_LL_TIMER1_36_10_REG);
+        console_printf("  0x%08lx CM_LL_TIMER1_9_0_REG\n", cd->CM_LL_TIMER1_9_0_REG);
+
+        /* Spin if debugger is connected to CMAC to avoid resetting it */
+        if (cd->CM_STAT_REG & 0x20) {
+            for (;;);
+        }
+#endif
+        /* XXX CMAC is in error state, need to recover */
+        assert(0);
+        return;
+    }
+
+    cmac_host_rand_chk_fill();
+
+    os_trace_isr_exit();
+}
+
+static void
+cmac_host_rand_fill(struct os_event *ev)
+{
+    size_t num_bytes;
+    struct trng_dev *trng;
+    uint32_t *rnum;
+    uint32_t rnums[CMAC_RAND_BUF_ELEMS];
+
+    /* Check if full */
+    if (!cmac_rand_is_active() || cmac_rand_is_full()) {
+        return;
+    }
+
+    assert(ev->ev_arg != NULL);
+
+    /* Fill buffer with random numbers even though we may not use all of them */
+    trng = ev->ev_arg;
+    rnum = &rnums[0];
+    num_bytes = trng_read(trng, rnum, CMAC_RAND_BUF_ELEMS * sizeof(uint32_t));
+
+    cmac_rand_fill(rnum, num_bytes / 4);
+    cmac_host_signal2cmac();
+}
+
+static void
+cmac_host_rand_chk_fill(void)
+{
+    if (cmac_rand_is_active() && !cmac_rand_is_full()) {
+        os_eventq_put(os_eventq_dflt_get(), &g_cmac_host_rand_ev);
+    }
+}
+
+void
+cmac_host_signal2cmac(void)
+{
+    da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
+}
+
+static void
+cmac_host_lpclk_cb(uint32_t freq)
+{
+    /* No need to wakeup CMAC if LP clock frequency did not change */
+    if (g_cmac_shared_data->lp_clock_freq == freq) {
+        return;
+    }
+
+    cmac_shared_lock();
+    g_cmac_shared_data->lp_clock_freq = freq;
+    g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_LP_CLK;
+    cmac_shared_unlock();
+
+    cmac_host_signal2cmac();
+}
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
+static void
+cmac_host_print_trim(const char *name, const uint32_t *tv, unsigned len)
+{
+    console_printf("[CMAC] Trim values for '%s'\n", name);
+
+    while (len) {
+        console_printf("       0x%08x = 0x%08x\n", (unsigned)tv[0], (unsigned)tv[1]);
+        len -= 2;
+        tv += 2;
+    }
+}
+#endif
+
+void
+cmac_host_rf_calibrate(void)
+{
+    cmac_shared_lock();
+    g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_RF_CAL;
+    cmac_shared_unlock();
+
+    cmac_host_signal2cmac();
+}
+
+void
+cmac_host_init(void)
+{
+    struct trng_dev *trng;
+    struct cmac_image_info ii;
+    uint32_t cmac_rom_size;
+    uint32_t cmac_ram_size;
+#if !MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+    const struct flash_area *fa;
+    int rc;
+#endif
+    struct cmac_trim *trim;
+
+    /* Get trng os device */
+    trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL);
+    assert(trng);
+    g_cmac_host_rand_ev.ev_arg = trng;
+
+#if MYNEWT_VAL(CMAC_DEBUG_DIAG_ENABLE)
+    cmac_diag_setup_host();
+#endif
+
+#if MYNEWT_VAL(CMAC_DEBUG_SWD_ENABLE)
+    /* Enable CMAC debugger */
+    CRG_TOP->SYS_CTRL_REG |= 0x40; /* CRG_TOP_SYS_CTRL_REG_CMAC_DEBUGGER_ENABLE_Msk */
+#endif
+
+    /*
+     * Add PDC entry to wake up CMAC from M33
+     *
+     * XXX if MCU_DEBUG_GPIO_DEEP_SLEEP is enabled on CMAC, this should also
+     *     enable PD_COM so CMAC can access GPIOs after wake up
+     */
+    g_cmac_host_pdc_sys2cmac = da1469x_pdc_add(MCU_PDC_TRIGGER_MAC_TIMER,
+                                               MCU_PDC_MASTER_CMAC,
+                                               MCU_PDC_EN_XTAL);
+    da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
+    da1469x_pdc_ack(g_cmac_host_pdc_sys2cmac);
+
+    /* Add PDC entry to wake up M33 from CMAC, if does not exist yet */
+    g_cmac_host_pdc_cmac2sys = da1469x_pdc_find(MCU_PDC_TRIGGER_COMBO,
+                                              MCU_PDC_MASTER_M33, 0);
+    if (g_cmac_host_pdc_cmac2sys < 0) {
+        g_cmac_host_pdc_cmac2sys = da1469x_pdc_add(MCU_PDC_TRIGGER_COMBO,
+                                                 MCU_PDC_MASTER_M33,
+                                                 MCU_PDC_EN_XTAL);
+        da1469x_pdc_set(g_cmac_host_pdc_cmac2sys);
+        da1469x_pdc_ack(g_cmac_host_pdc_cmac2sys);
+    }
+
+    /* Setup CMAC2SYS interrupt */
+    NVIC_SetVector(CMAC2SYS_IRQn, (uint32_t)cmac2sys_isr);
+    NVIC_SetPriority(CMAC2SYS_IRQn, MYNEWT_VAL(CMAC_CMAC2SYS_IRQ_PRIORITY));
+    NVIC_DisableIRQ(CMAC2SYS_IRQn);
+
+    /* Enable Radio LDO */
+    CRG_TOP->POWER_CTRL_REG |= CRG_TOP_POWER_CTRL_REG_LDO_RADIO_ENABLE_Msk;
+
+    /* Enable CMAC, but keep it in reset */
+    CRG_TOP->CLK_RADIO_REG = (1 << CRG_TOP_CLK_RADIO_REG_RFCU_ENABLE_Pos) |
+                             (1 << CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Pos) |
+                             (0 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_SEL_Pos) |
+                             (1 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_ENABLE_Pos) |
+                             (0 << CRG_TOP_CLK_RADIO_REG_CMAC_DIV_Pos);
+
+    /* Calculate size of ROM and RAM area */
+    cmac_rom_size = &_binary_cmac_rom_bin_end - &_binary_cmac_rom_bin_start[0];
+    cmac_ram_size = &_binary_cmac_ram_bin_end - &_binary_cmac_ram_bin_start[0];
+
+    /* Load image header and check if image can be loaded */
+#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+    memcpy(&ii, &_binary_cmac_rom_bin_start[128], sizeof(ii));
+#else
+    rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa);
+    assert(rc == 0);
+    rc = flash_area_read(fa, 128, &ii, sizeof(ii));
+    assert(rc == 0);
+#endif
+
+    assert(ii.magic == 0xC3ACC3AC);
+    assert(ii.size_rom == cmac_rom_size);
+    assert(ii.size_ram <= cmac_ram_size);
+
+    /* Copy CMAC image to RAM */
+#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+    memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
+    memcpy(&_binary_cmac_ram_bin_start, &_binary_cmac_rom_bin_start, ii.size_rom);
+#else
+    memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
+    rc = flash_area_read(fa, 0, &_binary_cmac_ram_bin_start, ii.size_rom);
+    assert(rc == 0);
+#endif
+
+    /* Setup CMAC memory addresses */
+    MEMCTRL->CMI_CODE_BASE_REG = (uint32_t)&_binary_cmac_ram_bin_start;
+    MEMCTRL->CMI_DATA_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_data;
+    MEMCTRL->CMI_SHARED_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_shared;
+    MEMCTRL->CMI_END_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.size_ram - 1;
+
+    /* Initialize shared memory */
+    cmac_shared_init();
+
+    trim = (struct cmac_trim *)&g_cmac_shared_data->trim;
+    trim->rfcu_len = da1469x_trimv_group_read(6, trim->rfcu, ARRAY_SIZE(trim->rfcu));
+    trim->rfcu_mode1_len = da1469x_trimv_group_read(8, trim->rfcu_mode1, ARRAY_SIZE(trim->rfcu_mode1));
+    trim->rfcu_mode2_len = da1469x_trimv_group_read(10, trim->rfcu_mode2, ARRAY_SIZE(trim->rfcu_mode2));
+    trim->synth_len = da1469x_trimv_group_read(7, trim->synth, ARRAY_SIZE(trim->synth));
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
+    cmac_host_print_trim("rfcu", trim->rfcu, trim->rfcu_len);
+    cmac_host_print_trim("rfcu_mode1", trim->rfcu_mode1, trim->rfcu_mode1_len);
+    cmac_host_print_trim("rfcu_mode2", trim->rfcu_mode2, trim->rfcu_mode2_len);
+    cmac_host_print_trim("synth", trim->synth, trim->synth_len);
+#endif
+
+    /* Release CMAC from reset and sync */
+    CRG_TOP->CLK_RADIO_REG &= ~CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk;
+    cmac_shared_sync();
+
+    da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb);
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) && MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+    /* Trim values are calculated on RF init, so are valid after synced with CMAC */
+    console_printf("[CMAC] Calculated trim_val1: 1=0x%08x 2=0x%08x\n",
+                   (unsigned)g_cmac_shared_data->debug.trim_val1_tx_1,
+                   (unsigned)g_cmac_shared_data->debug.trim_val1_tx_2);
+    console_printf("[CMAC] Calculated trim_val2: tx=0x%08x rx=0x%08x\n",
+                   (unsigned)g_cmac_shared_data->debug.trim_val2_tx,
+                   (unsigned)g_cmac_shared_data->debug.trim_val2_rx);
+#endif
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c
new file mode 100644
index 00000000..9594dbe9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c
@@ -0,0 +1,162 @@
+/*
+ * 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 <assert.h>
+#include <cmac_driver/cmac_shared.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/mcu.h"
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#ifndef min
+#define min(_a, _b)     ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+static cmac_mbox_read_cb *g_cmac_mbox_read_cb;
+static cmac_mbox_write_notif_cb *g_cmac_mbox_write_notif_cb;
+
+void
+cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb)
+{
+    g_cmac_mbox_read_cb = cb;
+}
+
+void
+cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb)
+{
+    g_cmac_mbox_write_notif_cb = cb;
+}
+
+int
+cmac_mbox_read(void)
+{
+#if MYNEWT_VAL(BLE_HOST)
+    volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s;
+    uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_c2s_buf;
+    const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
+#else
+    volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_s2c;
+    uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_s2c_buf;
+    const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
+#endif
+    uint16_t rd_off;
+    uint16_t wr_off;
+    uint16_t chunk;
+    int len = 0;
+
+    if (!g_cmac_mbox_read_cb) {
+        return 0;
+    }
+
+    do {
+        rd_off = mbox->rd_off;
+        wr_off = mbox->wr_off;
+
+        if (rd_off <= wr_off) {
+            chunk = wr_off - rd_off;
+        } else {
+            chunk = mbox_size - rd_off;
+        }
+
+        while (chunk) {
+            len = g_cmac_mbox_read_cb(&mbox_buf[rd_off], chunk);
+            if (len < 0) {
+                break;
+            }
+
+            rd_off += len;
+            chunk -= len;
+        }
+
+        mbox->rd_off = rd_off == mbox_size ? 0 : rd_off;
+    } while ((mbox->rd_off != mbox->wr_off) && (len >= 0));
+
+    return 0;
+}
+
+int
+cmac_mbox_write(const void *data, uint16_t len)
+{
+#if MYNEWT_VAL(BLE_HOST)
+    volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_s2c;
+    uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_s2c_buf;
+    const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
+#else
+    volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_c2s;
+    uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_c2s_buf;
+    const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
+#endif
+    uint16_t rd_off;
+    uint16_t wr_off;
+    uint16_t max_wr;
+    uint16_t chunk;
+
+    while (len) {
+        rd_off = mbox->rd_off;
+        wr_off = mbox->wr_off;
+
+        /*
+         * Calculate maximum length to write, i.e. up to end of buffer or stop
+         * before rd_off to be able to detect full queue.
+         */
+        if (rd_off > wr_off) {
+            /*
+             * |0|1|2|3|4|5|6|7|
+             * | | | |W| | |R| |
+             *        `---^
+             */
+            max_wr = rd_off - wr_off - 1;
+        } else if (rd_off == 0) {
+            /*
+             * |0|1|2|3|4|5|6|7|
+             * |R| | |W| | | | |
+             *        `-------^
+             */
+            max_wr = mbox_size - wr_off - 1;
+        } else {
+            /*
+             * |0|1|2|3|4|5|6|7|
+             * | |R| |W| | | | |
+             *        `---------^
+             */
+            max_wr = mbox_size - wr_off;
+        }
+
+        chunk = min(len, max_wr);
+
+        if (chunk == 0) {
+            continue;
+        }
+
+        memcpy(&mbox_buf[wr_off], data, chunk);
+
+        wr_off += chunk;
+        mbox->wr_off = wr_off == mbox_size ? 0 : wr_off;
+
+        g_cmac_mbox_write_notif_cb();
+
+        len -= chunk;
+        data = (uint8_t *)data + chunk;
+    }
+
+    return 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c
new file mode 100644
index 00000000..67a315f9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c
@@ -0,0 +1,145 @@
+/*
+ * 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 <assert.h>
+#include <cmac_driver/cmac_shared.h>
+#include <string.h>
+#include <stdbool.h>
+#include "syscfg/syscfg.h"
+#include "mcu/mcu.h"
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+int
+cmac_rand_is_active(void)
+{
+    return g_cmac_shared_data->rand.cmr_active;
+}
+
+int
+cmac_rand_is_full(void)
+{
+    int next;
+    bool rc;
+
+    next = cmac_rand_get_next();
+    if (next == g_cmac_shared_data->rand.cmr_out) {
+        rc = 1;
+    } else {
+        rc = 0;
+    }
+    return rc;
+}
+
+int
+cmac_rand_get_next(void)
+{
+    int next;
+
+    /* If active and not full, put event on queue to get random numbers */
+    next = g_cmac_shared_data->rand.cmr_in + 1;
+    if (next == CMAC_RAND_BUF_ELEMS) {
+        next = 0;
+    }
+    return next;
+}
+
+void
+cmac_rand_fill(uint32_t *buf, int num_words)
+{
+    int next;
+
+    /* XXX: if words is 0, is it possible we could get into a state
+       where we are waiting for random numbers but M33 does not know it
+       has to fill any? */
+
+    /* NOTE: we already know the buffer is not full first time through */
+    next = g_cmac_shared_data->rand.cmr_in;
+    while (num_words) {
+        g_cmac_shared_data->rand.cmr_buf[next] = buf[0];
+        next = cmac_rand_get_next();
+        g_cmac_shared_data->rand.cmr_in = next;
+        next = cmac_rand_get_next();
+        if (next == g_cmac_shared_data->rand.cmr_out) {
+            break;
+        }
+        --num_words;
+        ++buf;
+    }
+}
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+static cmac_rand_isr_cb_t g_cmac_rand_isr_cb;
+
+void
+cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb)
+{
+    g_cmac_rand_isr_cb = cb;
+}
+
+void
+cmac_rand_start(void)
+{
+    g_cmac_shared_data.rand.cmr_active = 1;
+}
+
+void
+cmac_rand_stop(void)
+{
+    g_cmac_shared_data.rand.cmr_active = 0;
+}
+
+/**
+ * cmac rnum read
+ *
+ * Called during the system to cmac isr to take random numbers
+ * from shared memory into the BLE stack.
+ */
+void
+cmac_rand_read(void)
+{
+    uint8_t bytes_left;
+    uint32_t rnum;
+
+    /* Just leave if no callback. */
+    if (g_cmac_rand_isr_cb == NULL) {
+        return;
+    }
+
+    bytes_left = 0;
+    while (g_cmac_shared_data.rand.cmr_active) {
+        if (bytes_left) {
+            --bytes_left;
+            rnum >>= 8;
+        } else if (g_cmac_shared_data.rand.cmr_out != g_cmac_shared_data.rand.cmr_in) {
+            bytes_left = 3;
+            rnum = g_cmac_shared_data.rand.cmr_buf[g_cmac_shared_data.rand.cmr_out];
+            ++g_cmac_shared_data.rand.cmr_out;
+            if (g_cmac_shared_data.rand.cmr_out == CMAC_RAND_BUF_ELEMS) {
+                g_cmac_shared_data.rand.cmr_out = 0;
+            }
+        } else {
+            break;
+        }
+        (*g_cmac_rand_isr_cb)((uint8_t)rnum);
+    }
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c
new file mode 100644
index 00000000..24640ca4
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c
@@ -0,0 +1,98 @@
+/*
+ * 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_CONTROLLER) && !MYNEWT_VAL(MCU_DEBUG_DSER_CMAC_SHARED)
+#define MCU_DIAG_SER_DISABLE
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include "mcu/mcu.h"
+#include <cmac_driver/cmac_shared.h>
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#ifndef min
+#define min(_a, _b)     ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+volatile struct cmac_shared_data *g_cmac_shared_data;
+#include "mcu/da1469x_clock.h"
+#define MCU_DIAG_SER(_x)
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+volatile struct cmac_shared_data g_cmac_shared_data     __attribute__((section(".shdata")));
+#endif
+
+void
+cmac_shared_init(void)
+{
+#if MYNEWT_VAL(BLE_HOST)
+    g_cmac_shared_data = (void *)(MCU_MEM_SYSRAM_START_ADDRESS +
+                                  MEMCTRL->CMI_SHARED_BASE_REG);
+
+    memset((void *)g_cmac_shared_data, 0, sizeof(*g_cmac_shared_data));
+
+    g_cmac_shared_data->xtal32m_settle_us = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US);
+
+    g_cmac_shared_data->dcdc.enabled = DCDC->DCDC_CTRL1_REG & DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk;
+    if (g_cmac_shared_data->dcdc.enabled) {
+        g_cmac_shared_data->dcdc.v18 = DCDC->DCDC_V18_REG;
+        g_cmac_shared_data->dcdc.v18p = DCDC->DCDC_V18P_REG;
+        g_cmac_shared_data->dcdc.vdd = DCDC->DCDC_VDD_REG;
+        g_cmac_shared_data->dcdc.v14 = DCDC->DCDC_V14_REG;
+        g_cmac_shared_data->dcdc.ctrl1 = DCDC->DCDC_CTRL1_REG;
+    }
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+    g_cmac_shared_data->debug.tx_power_override = INT8_MAX;
+#endif
+#endif
+}
+
+
+void
+cmac_shared_sync(void)
+{
+    /*
+     * We need to guarantee proper order of initialization here, i.e. SYS has
+     * to wait until CMAC finished initialization as otherwise host may start
+     * sending HCI packets which will timeout as there is no one to read them.
+     */
+#if MYNEWT_VAL(BLE_HOST)
+    assert(g_cmac_shared_data->magic_sys == 0);
+
+    while (g_cmac_shared_data->magic_cmac != CMAC_SHARED_MAGIC_CMAC);
+    g_cmac_shared_data->magic_sys = CMAC_SHARED_MAGIC_SYS;
+
+    NVIC_EnableIRQ(CMAC2SYS_IRQn);
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    assert(g_cmac_shared_data.magic_cmac == 0);
+
+    g_cmac_shared_data.magic_cmac = CMAC_SHARED_MAGIC_CMAC;
+    while (g_cmac_shared_data.magic_sys != CMAC_SHARED_MAGIC_SYS);
+
+    NVIC_SetPriority(SYS2CMAC_IRQn, 3);
+    NVIC_EnableIRQ(SYS2CMAC_IRQn);
+#endif
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml
new file mode 100644
index 00000000..a382c424
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml
@@ -0,0 +1,104 @@
+# 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:
+    CMAC_MBOX_SIZE_S2C:
+        description: >
+            Size of mailbox for SYS to CMAC data. The size
+            value should be power of 2 to allow for better
+            code optimization.
+        value: 128
+    CMAC_MBOX_SIZE_C2S:
+        description: >
+            Size of mailbox for CMAC to SYS data. The size
+            value should be power of 2 to allow for better
+            code optimization.
+        value: 128
+
+    CMAC_TRIM_SIZE_RFCU:
+        description: >
+            Size of trim values for RFCU. This is maximum
+            number of trim values that can be read from
+            OTP and applied, all excessive values will be
+            discarded.
+        value: 10
+    CMAC_TRIM_SIZE_SYNTH:
+        description: >
+            Size of trim values for RFCU. This is maximum
+            number of trim values that can be read from
+            OTP and applied, all excessive values will be
+            discarded.
+        value: 10
+
+    CMAC_DEBUG_SWD_ENABLE:
+        description: >
+            Enable CMAC SWD interface.
+        value: 0
+    CMAC_DEBUG_DIAG_ENABLE:
+        description: >
+            Enable CMAC diagnostic lines.
+        value: 0
+    CMAC_DEBUG_DATA_ENABLE:
+        description: >
+            Enable extra debugging data in shared segment.
+        value: 0
+    CMAC_DEBUG_COREDUMP_ENABLE:
+        description: >
+            Enable dumping CMAC registers to shared segment
+            on fault.
+        value: 1
+    CMAC_DEBUG_HOST_PRINT_ENABLE:
+        description: >
+            Enable some debug printouts to console from host side.
+            This will dump some settings during startup, useful to
+            check what is loaded to CMAC via shared data.
+        value: 0
+
+    CMAC_IMAGE_SINGLE:
+        description: >
+            When enable, CMAC binary is linked with application image
+            creating a single image build. See CMAC_IMAGE_TARGET_NAME.
+            When disabled, CMAC binary is built and flashed separately
+            to flash partition. See CMAC_IMAGE_PARTITION.
+        value: 1
+    CMAC_IMAGE_TARGET_NAME:
+        description: >
+            Target name to build for CMAC binary for single image build.
+        value: "@apache-mynewt-nimble/targets/dialog_cmac"
+    CMAC_IMAGE_PARTITION:
+        description: >
+            Flash partition to load CMAC binary from if single image build
+            is disabled.
+        value: FLASH_AREA_IMAGE_1
+    CMAC_IMAGE_RAM_SIZE:
+        description: >
+            Size of RAM area in bytes reserved for CMAC if single image
+            build is disabled. Unit suffix (K, M) is allowed.
+            Note: for single image build this setting is not applicable
+            since proper RAM area size is automatically calculated from
+            CMAC binary.
+        value: 128K
+
+    CMAC_CMAC2SYS_IRQ_PRIORITY:
+        description: >
+            The priority of the CMAC2SYS IRQ. Default is 0, or highest
+            priority.
+        value: 0
+
+syscfg.restrictions.BLE_HOST:
+    - TRNG
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml
new file mode 100644
index 00000000..ef8fc1ee
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml
@@ -0,0 +1,36 @@
+#
+# 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/transport/dialog_cmac
+pkg.description: HCI H4 transport for Dialog CMAC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.deps:
+    - nimble
+    - nimble/transport/dialog_cmac/cmac_driver
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    ble_hci_cmac_init: 100
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c
new file mode 100644
index 00000000..665b6216
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c
@@ -0,0 +1,194 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+
+#include "syscfg/syscfg.h"
+#include "os/mynewt.h"
+#include "nimble/ble.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+#include "ble_hci_cmac_priv.h"
+
+/*
+ * If controller-to-host flow control is enabled we need to hold an extra command
+ * buffer for HCI_Host_Number_Of_Completed_Packets which can be sent at any time.
+ */
+#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) || MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+#define HCI_CMD_COUNT   2
+#else
+#define HCI_CMD_COUNT   1
+#endif
+
+#define POOL_ACL_BLOCK_SIZE     OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) +     \
+                                         BLE_MBUF_MEMBLOCK_OVERHEAD +       \
+                                         BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+static uint8_t ble_hci_pool_cmd_mempool_buf[
+    OS_MEMPOOL_BYTES(HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ)];
+static struct os_mempool ble_hci_pool_cmd_mempool;
+
+static uint8_t ble_hci_pool_evt_hi_mempool_buf[
+    OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                     MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool ble_hci_pool_evt_hi_mempool;
+
+static uint8_t ble_hci_pool_evt_lo_mempool_buf[
+    OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                     MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool ble_hci_pool_evt_lo_mempool;
+
+static uint8_t ble_hci_pool_acl_mempool_buf[
+    OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                     POOL_ACL_BLOCK_SIZE)];
+static struct os_mempool_ext ble_hci_pool_acl_mempool;
+static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
+
+__attribute__((weak)) void ble_hci_trans_notify_free(void);
+
+static os_mempool_put_fn *g_ble_hci_pool_acl_mempool_put_cb;
+static void *g_ble_hci_pool_acl_mempool_put_arg;
+
+int
+ble_hci_trans_reset(void)
+{
+    return 0;
+}
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+    uint8_t *buf;
+
+    switch (type) {
+    case BLE_HCI_TRANS_BUF_CMD:
+        buf = os_memblock_get(&ble_hci_pool_cmd_mempool);
+        break;
+    case BLE_HCI_TRANS_BUF_EVT_HI:
+        buf = os_memblock_get(&ble_hci_pool_evt_hi_mempool);
+        if (buf) {
+            break;
+        }
+    /* no break */
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_pool_evt_lo_mempool);
+        break;
+    default:
+        assert(0);
+        buf = NULL;
+    }
+
+    return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+    int rc;
+
+    if (os_memblock_from(&ble_hci_pool_cmd_mempool, buf)) {
+        rc = os_memblock_put(&ble_hci_pool_cmd_mempool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_pool_evt_hi_mempool, buf)) {
+        rc = os_memblock_put(&ble_hci_pool_evt_hi_mempool, buf);
+        assert(rc == 0);
+    } else {
+        assert(os_memblock_from(&ble_hci_pool_evt_lo_mempool, buf));
+        rc = os_memblock_put(&ble_hci_pool_evt_lo_mempool, buf);
+        assert(rc == 0);
+    }
+
+    ble_hci_trans_notify_free();
+}
+
+struct os_mbuf *
+ble_hci_cmac_alloc_acl_mbuf(void)
+{
+    return os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
+                              sizeof(struct ble_mbuf_hdr));
+}
+
+static os_error_t
+ble_hci_cmac_free_acl_cb(struct os_mempool_ext *mpe, void *data, void *arg)
+{
+    int rc;
+
+    if (g_ble_hci_pool_acl_mempool_put_cb) {
+        rc = g_ble_hci_pool_acl_mempool_put_cb(mpe, data,
+                                               g_ble_hci_pool_acl_mempool_put_arg);
+    } else {
+        rc = os_memblock_put_from_cb(&mpe->mpe_mp, data);
+    }
+
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hci_trans_notify_free();
+
+    return 0;
+}
+
+
+int
+ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
+{
+    g_ble_hci_pool_acl_mempool_put_cb = cb;
+    g_ble_hci_pool_acl_mempool_put_arg = arg;
+
+    return 0;
+}
+
+void
+ble_hci_cmac_init(void)
+{
+    int rc;
+
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = os_mempool_init(&ble_hci_pool_cmd_mempool,
+                         HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ,
+                         ble_hci_pool_cmd_mempool_buf, "ble_hci_cmd");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_pool_evt_hi_mempool,
+                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_pool_evt_hi_mempool_buf, "ble_hci_evt_hi");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_pool_evt_lo_mempool,
+                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_pool_evt_lo_mempool_buf, "ble_hci_evt_lo");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_ext_init(&ble_hci_pool_acl_mempool,
+                             MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE,
+                             ble_hci_pool_acl_mempool_buf, "ble_hci_acl");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mbuf_pool_init(&ble_hci_pool_acl_mbuf_pool,
+                           &ble_hci_pool_acl_mempool.mpe_mp, POOL_ACL_BLOCK_SIZE,
+                           MYNEWT_VAL(BLE_ACL_BUF_COUNT));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    ble_hci_pool_acl_mempool.mpe_put_cb = ble_hci_cmac_free_acl_cb;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c
new file mode 100644
index 00000000..1164fe71
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c
@@ -0,0 +1,153 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+
+#include "cmac_driver/cmac_shared.h"
+#include "cmac_driver/cmac_host.h"
+#include "nimble/ble_hci_trans.h"
+#include "os/os_mbuf.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+struct ble_hci_cmac_hs_api {
+    ble_hci_trans_rx_cmd_fn *evt_cb;
+    void *evt_arg;
+    ble_hci_trans_rx_acl_fn *acl_cb;
+    void *acl_arg;
+};
+
+static struct ble_hci_cmac_hs_api g_ble_hci_cmac_hs_api;
+static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_hs_rx_state;
+static bool g_ble_hci_cmac_hs_read_err;
+
+static int
+ble_hci_cmac_hs_frame_cb(uint8_t pkt_type, void *data)
+{
+    int rc;
+
+    switch (pkt_type) {
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        rc = g_ble_hci_cmac_hs_api.acl_cb(data, g_ble_hci_cmac_hs_api.acl_arg);
+        break;
+    case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+        rc = g_ble_hci_cmac_hs_api.evt_cb(data, g_ble_hci_cmac_hs_api.evt_arg);
+        break;
+    default:
+        assert(0);
+        break;
+    }
+
+    return rc;
+}
+
+static int
+ble_hci_cmac_hs_mbox_read_cb(const void *data, uint16_t len)
+{
+    int rlen;
+    os_sr_t sr;
+
+    rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_hs_rx_state, data, len,
+                               ble_hci_cmac_hs_frame_cb);
+    if (rlen < 0) {
+        /*
+         * There was oom error, we need to wait for buffer to be freed and
+         * trigger another read.
+         */
+        OS_ENTER_CRITICAL(sr);
+        g_ble_hci_cmac_hs_read_err = true;
+        OS_EXIT_CRITICAL(sr);
+    }
+
+    return rlen;
+}
+
+static void
+ble_hci_cmac_hs_mbox_write_notif_cb(void)
+{
+    cmac_host_signal2cmac();
+}
+
+int
+ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
+{
+    uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_CMD;
+
+    cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+    cmac_mbox_write(cmd, cmd[2] + 3);
+
+    ble_hci_trans_buf_free(cmd);
+
+    return 0;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+    uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
+    struct os_mbuf *om_next;
+
+    cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+
+    while (om) {
+        om_next = SLIST_NEXT(om, om_next);
+
+        cmac_mbox_write(om->om_data, om->om_len);
+
+        os_mbuf_free(om);
+        om = om_next;
+    }
+
+    return 0;
+}
+
+void
+ble_hci_trans_notify_free(void)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    if (g_ble_hci_cmac_hs_read_err) {
+        g_ble_hci_cmac_hs_read_err = false;
+        /* Just trigger an interrupt, it will trigger read */
+        NVIC_SetPendingIRQ(CMAC2SYS_IRQn);
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, void *evt_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+    g_ble_hci_cmac_hs_api.evt_cb = evt_cb;
+    g_ble_hci_cmac_hs_api.evt_arg = evt_arg;
+    g_ble_hci_cmac_hs_api.acl_cb = acl_cb;
+    g_ble_hci_cmac_hs_api.acl_arg = acl_arg;
+
+    /* We can now handle data from CMAC, initialize it */
+    cmac_mbox_set_read_cb(ble_hci_cmac_hs_mbox_read_cb);
+    cmac_mbox_set_write_notif_cb(ble_hci_cmac_hs_mbox_write_notif_cb);
+    cmac_host_init();
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c
new file mode 100644
index 00000000..3531529c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c
@@ -0,0 +1,141 @@
+/*
+ * 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_CONTROLLER)
+
+#if !MYNEWT_VAL(MCU_DEBUG_DSER_BLE_HCI_CMAC_LL)
+#define MCU_DIAG_SER_DISABLE
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include "mcu/mcu.h"
+#include "cmac_driver/cmac_shared.h"
+#include "nimble/ble_hci_trans.h"
+#include "os/os_mbuf.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+struct ble_hci_cmac_ll_api {
+    ble_hci_trans_rx_cmd_fn *cmd_cb;
+    void *cmd_arg;
+    ble_hci_trans_rx_acl_fn *acl_cb;
+    void *acl_arg;
+};
+
+static struct ble_hci_cmac_ll_api g_ble_hci_cmac_ll_api;
+static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_ll_rx_state;
+
+static int
+ble_hci_cmac_ll_frame_cb(uint8_t pkt_type, void *data)
+{
+    int rc;
+
+    MCU_DIAG_SER('F');
+
+    switch (pkt_type) {
+    case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+        rc = g_ble_hci_cmac_ll_api.cmd_cb(data, g_ble_hci_cmac_ll_api.cmd_arg);
+        break;
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        rc = g_ble_hci_cmac_ll_api.acl_cb(data, g_ble_hci_cmac_ll_api.acl_arg);
+        break;
+    default:
+        assert(0);
+        break;
+    }
+
+    return rc;
+}
+
+static int
+ble_hci_cmac_ll_mbox_read_cb(const void *data, uint16_t len)
+{
+    int rlen;
+
+    MCU_DIAG_SER('R');
+    rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_ll_rx_state, data, len,
+                               ble_hci_cmac_ll_frame_cb);
+
+    /* There should be no oom on LL side due to flow control used */
+    assert(rlen >= 0);
+
+    return rlen;
+}
+
+static void
+ble_hci_cmac_ll_mbox_write_notif_cb(void)
+{
+    MCU_DIAG_SER('W');
+    CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *evt)
+{
+    uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_EVT;
+
+    cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+    cmac_mbox_write(evt, evt[1] + 2);
+
+    ble_hci_trans_buf_free(evt);
+
+    return 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+    uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
+    struct os_mbuf *om_next;
+
+    cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+
+    while (om) {
+        om_next = SLIST_NEXT(om, om_next);
+
+        cmac_mbox_write(om->om_data, om->om_len);
+
+        os_mbuf_free(om);
+        om = om_next;
+    }
+
+    return 0;
+}
+
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+    g_ble_hci_cmac_ll_api.cmd_cb = cmd_cb;
+    g_ble_hci_cmac_ll_api.cmd_arg = cmd_arg;
+    g_ble_hci_cmac_ll_api.acl_cb = acl_cb;
+    g_ble_hci_cmac_ll_api.acl_arg = acl_arg;
+
+    /* Setup callbacks for mailboxes */
+    cmac_mbox_set_read_cb(ble_hci_cmac_ll_mbox_read_cb);
+    cmac_mbox_set_write_notif_cb(ble_hci_cmac_ll_mbox_write_notif_cb);
+
+    /* Synchronize with SYS */
+    cmac_shared_sync();
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h
new file mode 100644
index 00000000..451053c3
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_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_HCI_CMAC_PRIV_H_
+#define _BLE_HCI_CMAC_PRIV_H_
+
+#include "os/os_mbuf.h"
+
+struct os_mbuf *ble_hci_cmac_alloc_acl_mbuf(void);
+
+void ble_hci_trans_notify_free(void);
+
+#endif /* _BLE_HCI_CMAC_PRIV_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c
new file mode 100644
index 00000000..74da3912
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c
@@ -0,0 +1,332 @@
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os_mbuf.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+#define RXS_STATE_W4_PKT_TYPE       0
+#define RXS_STATE_W4_HEADER         1
+#define RXS_STATE_W4_PAYLOAD        2
+#define RXS_STATE_COMPLETED         3
+
+struct input_buffer {
+    const uint8_t *buf;
+    uint16_t len;
+};
+
+static int
+ble_hci_trans_h4_ib_adjust(struct input_buffer *ib, uint16_t len)
+{
+    assert(ib->len >= len);
+
+    ib->buf += len;
+    ib->len -= len;
+
+    return len;
+}
+
+static void
+ble_hci_trans_h4_rxs_start(struct ble_hci_trans_h4_rx_state *rxs, uint8_t pkt_type)
+{
+    rxs->pkt_type = pkt_type;
+    rxs->len = 0;
+    rxs->expected_len = 0;
+
+    switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+        rxs->min_len = 3;
+        break;
+#endif
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        rxs->min_len = 4;
+        break;
+#if MYNEWT_VAL(BLE_HOST)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+        rxs->min_len = 2;
+        break;
+#endif
+    default:
+        /* XXX sync loss */
+        assert(0);
+        break;
+    }
+}
+
+static int
+ble_hci_trans_h4_pull_min_len(struct ble_hci_trans_h4_rx_state *rxs,
+                              struct input_buffer *ib)
+{
+    uint16_t len;
+
+    len = min(ib->len, rxs->min_len - rxs->len);
+    memcpy(&rxs->hdr[rxs->len], ib->buf, len);
+
+    rxs->len += len;
+    ble_hci_trans_h4_ib_adjust(ib, len);
+
+    return rxs->len != rxs->min_len;
+}
+
+static int
+ble_hci_trans_h4_rx_state_w4_header(struct ble_hci_trans_h4_rx_state *rxs,
+                                    struct input_buffer *ib)
+{
+#if MYNEWT_VAL(BLE_HOST)
+    int pool;
+#endif
+    int rc;
+
+    rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
+    if (rc) {
+        /* need more data */
+        return 1;
+    }
+
+    switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+        rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+        if (!rxs->buf) {
+            return -1;
+        }
+
+        memcpy(rxs->buf, rxs->hdr, rxs->len);
+        rxs->expected_len = rxs->hdr[2] + 3;
+        break;
+#endif
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        rxs->om = ble_hci_cmac_alloc_acl_mbuf();
+        if (!rxs->om) {
+            return -1;
+        }
+
+        os_mbuf_append(rxs->om, rxs->hdr, rxs->len);
+        rxs->expected_len = get_le16(&rxs->hdr[2]) + 4;
+        break;
+#if MYNEWT_VAL(BLE_HOST)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+        pool = BLE_HCI_TRANS_BUF_EVT_HI;
+        if (rxs->hdr[0] == BLE_HCI_EVCODE_LE_META) {
+            /* For LE Meta event we need 3 bytes to parse header */
+            rxs->min_len = 3;
+            rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
+            if (rc) {
+                /* need more data */
+                return 1;
+            }
+
+            /* Advertising reports shall be allocated from low-prio pool */
+            if ((rxs->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
+                (rxs->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+                pool = BLE_HCI_TRANS_BUF_EVT_LO;
+            }
+        }
+
+        /*
+         * XXX Events originally allocated from hi-pool can use lo-pool as
+         *     fallback and cannot be dropped. Events allocated from lo-pool
+         *     can be dropped to avoid oom while scanning which means that
+         *     any advertising or extended advertising report can be silently
+         *     discarded by transport. While this is perfectly fine for legacy
+         *     advertising, for extended advertising it means we can drop start
+         *     or end of chain report and host won't be able to reassemble
+         *     chain properly... so just need to make sure pool on host side is
+         *     large enough to catch up with controller.
+         */
+        rxs->buf = ble_hci_trans_buf_alloc(pool);
+        if (!rxs->buf && pool == BLE_HCI_TRANS_BUF_EVT_HI) {
+            rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+            if (!rxs->buf) {
+                return -1;
+            }
+        }
+
+        if (rxs->buf) {
+            memcpy(rxs->buf, rxs->hdr, rxs->len);
+        }
+
+        rxs->expected_len = rxs->hdr[1] + 2;
+        break;
+#endif
+    default:
+        assert(0);
+        break;
+    }
+
+    return 0;
+}
+
+static int
+ble_hci_trans_h4_rx_state_w4_payload(struct ble_hci_trans_h4_rx_state *rxs,
+                                     struct input_buffer *ib)
+{
+    uint16_t mbuf_len;
+    uint16_t len;
+    int rc;
+
+    len = min(ib->len, rxs->expected_len - rxs->len);
+
+    switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+#endif
+        if (rxs->buf) {
+            memcpy(&rxs->buf[rxs->len], ib->buf, len);
+        }
+        break;
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        assert(rxs->om);
+
+        mbuf_len = OS_MBUF_PKTLEN(rxs->om);
+        rc = os_mbuf_append(rxs->om, ib->buf, len);
+        if (rc) {
+            /*
+             * Some data may already be appended so need to adjust rxs only by
+             * the size of appended data.
+             */
+            len = OS_MBUF_PKTLEN(rxs->om) - mbuf_len;
+            rxs->len += len;
+            ble_hci_trans_h4_ib_adjust(ib, len);
+
+            return -1;
+        }
+        break;
+    default:
+        assert(0);
+        break;
+    }
+
+    rxs->len += len;
+    ble_hci_trans_h4_ib_adjust(ib, len);
+
+    /* return 1 if need more data */
+    return rxs->len != rxs->expected_len;
+}
+
+static void
+ble_hci_trans_h4_rx_state_completed(struct ble_hci_trans_h4_rx_state *rxs,
+                                    ble_hci_trans_h4_frame_cb *frame_cb)
+{
+    int rc;
+
+    switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+    case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+#endif
+        if (rxs->buf) {
+            rc = frame_cb(rxs->pkt_type, rxs->buf);
+            if (rc != 0) {
+                ble_hci_trans_buf_free(rxs->buf);
+            }
+            rxs->buf = NULL;
+        }
+        break;
+    case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+        if (rxs->om) {
+            rc = frame_cb(rxs->pkt_type, rxs->om);
+            if (rc != 0) {
+                os_mbuf_free_chain(rxs->om);
+            }
+            rxs->om = NULL;
+        }
+        break;
+    default:
+        assert(0);
+        break;
+    }
+}
+
+int
+ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs, const uint8_t *buf,
+                    uint16_t len, ble_hci_trans_h4_frame_cb *frame_cb)
+{
+    struct input_buffer ib = {
+        .buf = buf,
+        .len = len,
+    };
+    int rc = 0;
+
+    while (ib.len && (rc >= 0)) {
+        rc = 0;
+        switch (rxs->state) {
+        case RXS_STATE_W4_PKT_TYPE:
+            ble_hci_trans_h4_rxs_start(rxs, ib.buf[0]);
+            ble_hci_trans_h4_ib_adjust(&ib, 1);
+            rxs->state = RXS_STATE_W4_HEADER;
+        /* no break */
+
+        case RXS_STATE_W4_HEADER:
+            rc = ble_hci_trans_h4_rx_state_w4_header(rxs, &ib);
+            if (rc) {
+                break;
+            }
+            rxs->state = RXS_STATE_W4_PAYLOAD;
+        /* no break */
+
+        case RXS_STATE_W4_PAYLOAD:
+            rc = ble_hci_trans_h4_rx_state_w4_payload(rxs, &ib);
+            if (rc) {
+                break;
+            }
+            rxs->state = RXS_STATE_COMPLETED;
+        /* no break */
+
+        case RXS_STATE_COMPLETED:
+            ble_hci_trans_h4_rx_state_completed(rxs, frame_cb);
+            rxs->state = RXS_STATE_W4_PKT_TYPE;
+            break;
+
+        default:
+            assert(0);
+            /* consume all remaining data */
+            ble_hci_trans_h4_ib_adjust(&ib, ib.len);
+            break;
+        }
+    }
+
+    /*
+     * Calculate consumed bytes
+     *
+     * Note: we should always consume some bytes unless there is an oom error.
+     * It's also possible that we have an oom error but already consumed some
+     * data, in such case just return success and error will be returned on next
+     * pass.
+     */
+    len = len - ib.len;
+    if (len == 0) {
+        assert(rc < 0);
+        return -1;
+    }
+
+    return len;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h
new file mode 100644
index 00000000..5b83f6b0
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h
@@ -0,0 +1,49 @@
+/*
+ * 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_HCI_TRANS_H4_H_
+#define _BLE_HCI_TRANS_H4_H_
+
+#include <stdint.h>
+
+#define BLE_HCI_TRANS_H4_PKT_TYPE_NONE      0x00
+#define BLE_HCI_TRANS_H4_PKT_TYPE_CMD       0x01
+#define BLE_HCI_TRANS_H4_PKT_TYPE_ACL       0x02
+#define BLE_HCI_TRANS_H4_PKT_TYPE_EVT       0x04
+
+struct ble_hci_trans_h4_rx_state {
+    uint8_t state;
+    uint8_t pkt_type;
+    uint8_t min_len;
+    uint16_t len;
+    uint16_t expected_len;
+    uint8_t hdr[4];
+    union {
+        uint8_t *buf;
+        struct os_mbuf *om;
+    };
+};
+
+typedef int (ble_hci_trans_h4_frame_cb)(uint8_t pkt_type, void *data);
+
+int ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs,
+                        const uint8_t *buf, uint16_t len,
+                        ble_hci_trans_h4_frame_cb *frame_cb);
+
+#endif /* _BLE_HCI_TRANS_H4_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml
new file mode 100644
index 00000000..c44773ef
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml
@@ -0,0 +1,43 @@
+# 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_HCI_EVT_HI_BUF_COUNT:
+        description: 'Number of high-priority event buffers.'
+        value:  2
+
+    BLE_HCI_EVT_LO_BUF_COUNT:
+        description: 'Number of low-priority event buffers.'
+        value:  8
+
+    BLE_HCI_EVT_BUF_SIZE:
+        description: 'Size of each event buffer, in bytes.'
+        value:  70
+
+    BLE_ACL_BUF_COUNT:
+        description: 'The number of ACL data buffers'
+        value: 4
+
+    BLE_ACL_BUF_SIZE:
+        description: >
+            This is the maximum size of the data portion of HCI ACL data
+            packets. It does not include the HCI data header (of 4 bytes).
+        value: 255
+
+syscfg.vals.'BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV':
+    BLE_HCI_EVT_BUF_SIZE: 257
diff --git a/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c b/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
index 61c0c9cb..61fe96b2 100644
--- a/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
+++ b/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
@@ -295,15 +295,7 @@ done:
 static struct os_mbuf *
 ble_hci_trans_acl_buf_alloc(void)
 {
-    uint8_t usrhdr_len;
-
-#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
-    usrhdr_len = BLE_MBUF_HS_HDR_LEN;
-#else
-    usrhdr_len = 0;
-#endif
-
-    return os_mbuf_get_pkthdr(&ble_hci_emspi_acl_mbuf_pool, usrhdr_len);
+    return os_mbuf_get_pkthdr(&ble_hci_emspi_acl_mbuf_pool, 0);
 }
 
 /**
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml
new file mode 100644
index 00000000..4db567c8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml
@@ -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.
+#
+
+pkg.name: nimble/transport/nrf5340
+pkg.description: HCI transport for nRF5340
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+    - nrf5340
+
+pkg.deps:
+    - "@apache-mynewt-nimble/nimble"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/hw/drivers/ipc_nrf5340"
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    nrf5340_ble_hci_init: 'MYNEWT_VAL(BLE_TRANS_NRF5340_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
new file mode 100644
index 00000000..3f113e11
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
@@ -0,0 +1,426 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+#include <os/mynewt.h>
+#include <nimble/ble.h>
+#include <nimble/ble_hci_trans.h>
+#include <nimble/hci_common.h>
+#include <ipc_nrf5340/ipc_nrf5340.h>
+
+#define HCI_PKT_NONE    0x00
+#define HCI_PKT_CMD     0x01
+#define HCI_PKT_ACL     0x02
+#define HCI_PKT_EVT     0x04
+
+#define POOL_ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) +     \
+                                     BLE_MBUF_MEMBLOCK_OVERHEAD +       \
+                                     BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+#define IPC_TX_CHANNEL 0
+#define IPC_RX_CHANNEL 1
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+#define IPC_TX_CHANNEL 1
+#define IPC_RX_CHANNEL 0
+#endif
+
+struct nrf5340_ble_hci_api {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    ble_hci_trans_rx_cmd_fn *cmd_cb;
+    void *cmd_arg;
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+    ble_hci_trans_rx_cmd_fn *evt_cb;
+    void *evt_arg;
+#endif
+    ble_hci_trans_rx_acl_fn *acl_cb;
+    void *acl_arg;
+};
+
+struct nrf5340_ble_hci_rx_data {
+    uint8_t type;
+    uint8_t hdr[4];
+    uint16_t len;
+    uint16_t expected_len;
+    union {
+        uint8_t *buf;
+        struct os_mbuf *om;
+    };
+};
+
+struct nrf5340_ble_hci_pool_cmd {
+    uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
+    bool allocated;
+};
+
+/* (Pseudo)pool for HCI commands */
+static struct nrf5340_ble_hci_pool_cmd nrf5340_ble_hci_pool_cmd;
+
+/* Pools for HCI events (high and low priority) */
+static uint8_t nrf5340_ble_hci_pool_evt_hi_buf[OS_MEMPOOL_BYTES(
+                                            MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                                            MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool nrf5340_ble_hci_pool_evt_hi;
+static uint8_t nrf5340_ble_hci_pool_evt_lo_buf[OS_MEMPOOL_BYTES(
+                                            MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                                            MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool nrf5340_ble_hci_pool_evt_lo;
+
+/* Pool for ACL data */
+static uint8_t nrf5340_ble_hci_pool_acl_buf[OS_MEMPOOL_BYTES(
+                                            MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                                            POOL_ACL_BLOCK_SIZE)];
+static struct os_mempool nrf5340_ble_hci_pool_acl;
+static struct os_mbuf_pool nrf5340_ble_hci_pool_acl_mbuf;
+
+/* Interface to host/ll */
+static struct nrf5340_ble_hci_api nrf5340_ble_hci_api;
+
+/* State of RX currently in progress (needs to reassemble frame) */
+static struct nrf5340_ble_hci_rx_data nrf5340_ble_hci_rx_data;
+
+int
+ble_hci_trans_reset(void)
+{
+    /* XXX Should we do something with RF and/or BLE core? */
+    return 0;
+}
+
+static int
+ble_hci_trans_acl_tx(struct os_mbuf *om)
+{
+    uint8_t ind = HCI_PKT_ACL;
+    struct os_mbuf *x;
+    int rc;
+
+    rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+    if (rc == 0) {
+        x = om;
+        while (x) {
+            rc = ipc_nrf5340_send(IPC_TX_CHANNEL, x->om_data, x->om_len);
+            if (rc < 0) {
+                break;
+            }
+            x = SLIST_NEXT(x, om_next);
+        }
+    }
+
+    os_mbuf_free_chain(om);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+    nrf5340_ble_hci_api.cmd_cb = cmd_cb;
+    nrf5340_ble_hci_api.cmd_arg = cmd_arg;
+    nrf5340_ble_hci_api.acl_cb = acl_cb;
+    nrf5340_ble_hci_api.acl_arg = acl_arg;
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+{
+    uint8_t ind = HCI_PKT_EVT;
+    int len = 2 + hci_ev[1];
+    int rc;
+
+    rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+    if (rc == 0) {
+        rc = ipc_nrf5340_send(IPC_TX_CHANNEL, hci_ev, len);
+    }
+
+    ble_hci_trans_buf_free(hci_ev);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+    return ble_hci_trans_acl_tx(om);
+}
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+void
+ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, void *evt_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+    nrf5340_ble_hci_api.evt_cb = evt_cb;
+    nrf5340_ble_hci_api.evt_arg = evt_arg;
+    nrf5340_ble_hci_api.acl_cb = acl_cb;
+    nrf5340_ble_hci_api.acl_arg = acl_arg;
+}
+
+int
+ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
+{
+    uint8_t ind = HCI_PKT_CMD;
+    int len = 3 + cmd[2];
+    int rc;
+
+    rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+    if (rc == 0) {
+        rc = ipc_nrf5340_send(IPC_TX_CHANNEL, cmd, len);
+    }
+
+    ble_hci_trans_buf_free(cmd);
+
+    return (rc < 0) ? BLE_ERR_MEM_CAPACITY :  0;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+    return ble_hci_trans_acl_tx(om);
+}
+#endif
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+    uint8_t *buf;
+
+    switch (type) {
+    case BLE_HCI_TRANS_BUF_CMD:
+        assert(!nrf5340_ble_hci_pool_cmd.allocated);
+        nrf5340_ble_hci_pool_cmd.allocated = 1;
+        buf = nrf5340_ble_hci_pool_cmd.cmd;
+        break;
+    case BLE_HCI_TRANS_BUF_EVT_HI:
+        buf = os_memblock_get(&nrf5340_ble_hci_pool_evt_hi);
+        if (buf) {
+            break;
+        }
+        /* no break */
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&nrf5340_ble_hci_pool_evt_lo);
+        break;
+    default:
+        assert(0);
+        buf = NULL;
+    }
+
+    return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+    int rc;
+
+    if (buf == nrf5340_ble_hci_pool_cmd.cmd) {
+        assert(nrf5340_ble_hci_pool_cmd.allocated);
+        nrf5340_ble_hci_pool_cmd.allocated = 0;
+    } else if (os_memblock_from(&nrf5340_ble_hci_pool_evt_hi, buf)) {
+        rc = os_memblock_put(&nrf5340_ble_hci_pool_evt_hi, buf);
+        assert(rc == 0);
+    } else {
+        assert(os_memblock_from(&nrf5340_ble_hci_pool_evt_lo, buf));
+        rc = os_memblock_put(&nrf5340_ble_hci_pool_evt_lo, buf);
+        assert(rc == 0);
+    }
+}
+
+static void
+nrf5340_ble_hci_trans_rx_process(int channel)
+{
+    struct nrf5340_ble_hci_rx_data *rxd = &nrf5340_ble_hci_rx_data;
+#if MYNEWT_VAL(BLE_HOST)
+    int pool = BLE_HCI_TRANS_BUF_EVT_HI;
+#endif
+    int rc;
+
+    switch (rxd->type) {
+    case HCI_PKT_NONE:
+        ipc_nrf5340_read(channel, &rxd->type, 1);
+        rxd->len = 0;
+        rxd->expected_len = 0;
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+        assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_CMD));
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+        assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_EVT));
+#endif
+        break;
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    case HCI_PKT_CMD:
+        /* commands are sent complete over IPC */
+        rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 3);
+        assert(rxd->len == 3);
+
+        rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+        memcpy(rxd->buf, rxd->hdr, rxd->len);
+
+        rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len], rxd->hdr[2]);
+        assert(rxd->len == 3 + rxd->hdr[2]);
+
+        rc = nrf5340_ble_hci_api.cmd_cb(rxd->buf, nrf5340_ble_hci_api.cmd_arg);
+        if (rc != 0) {
+            ble_hci_trans_buf_free(rxd->buf);
+        }
+
+        rxd->type = HCI_PKT_NONE;
+        break;
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+    case HCI_PKT_EVT:
+        /* events are sent complete over IPC */
+        rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 2);
+        assert(rxd->len == 2);
+
+        if (rxd->hdr[0] == BLE_HCI_EVCODE_LE_META) {
+            /* For LE Meta event we need 3 bytes to parse header */
+            rxd->len += ipc_nrf5340_read(channel, rxd->hdr + 2, 1);
+            assert(rxd->len == 3);
+
+            /* Advertising reports shall be allocated from low-prio pool */
+            if ((rxd->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
+                (rxd->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+                pool = BLE_HCI_TRANS_BUF_EVT_LO;
+            }
+        }
+
+        rxd->buf = ble_hci_trans_buf_alloc(pool);
+        if (!rxd->buf) {
+            /*
+             * Only care about valid buffer when shall be allocated from
+             * high-prio pool, otherwise NULL is fine and we'll just skip
+             * this event.
+             */
+            if (pool != BLE_HCI_TRANS_BUF_EVT_LO) {
+                rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+            }
+        }
+
+        rxd->expected_len = 2 + rxd->hdr[1];
+
+        if (rxd->buf) {
+            memcpy(rxd->buf, rxd->hdr, rxd->len);
+
+            rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len],
+                                         rxd->expected_len - rxd->len);
+            assert(rxd->expected_len == rxd->len);
+
+            rc = nrf5340_ble_hci_api.evt_cb(rxd->buf,
+                                            nrf5340_ble_hci_api.evt_arg);
+            if (rc != 0) {
+                ble_hci_trans_buf_free(rxd->buf);
+            }
+        } else {
+            rxd->len += ipc_nrf5340_consume(channel,
+                                            rxd->expected_len - rxd->len);
+            assert(rxd->expected_len == rxd->len);
+        }
+
+        rxd->type = HCI_PKT_NONE;
+        break;
+#endif
+    case HCI_PKT_ACL:
+        if (rxd->len < 4) {
+            rxd->len += ipc_nrf5340_read(channel, rxd->hdr, 4 - rxd->len);
+
+            if (rxd->len < 4) {
+                break;
+            }
+        }
+
+        /* Parse header and allocate proper buffer if not done yet */
+        if (rxd->expected_len == 0) {
+            rxd->om = os_mbuf_get_pkthdr(&nrf5340_ble_hci_pool_acl_mbuf,
+                                         sizeof(struct ble_mbuf_hdr));
+            if (!rxd->om) {
+                /* not much we can do here... */
+                assert(0);
+            }
+
+            os_mbuf_append(rxd->om, rxd->hdr, rxd->len);
+            rxd->expected_len = get_le16(&rxd->hdr[2]) + 4;
+        }
+
+        if (rxd->len != rxd->expected_len) {
+            rxd->len += ipc_nrf5340_read_om(channel, rxd->om,
+                                            rxd->expected_len - rxd->len);
+        }
+
+        if (rxd->len == rxd->expected_len) {
+            rc = nrf5340_ble_hci_api.acl_cb(rxd->om,
+                                            nrf5340_ble_hci_api.acl_arg);
+            if (rc != 0) {
+                os_mbuf_free_chain(rxd->om);
+            }
+            rxd->type = HCI_PKT_NONE;
+        }
+        break;
+    default:
+        assert(0);
+        break;
+    }
+}
+
+static void
+nrf5340_ble_hci_trans_rx(int channel, void *user_data)
+{
+    while (ipc_nrf5340_available(channel) > 0) {
+        nrf5340_ble_hci_trans_rx_process(channel);
+    }
+}
+
+void
+nrf5340_ble_hci_init(void)
+{
+    int rc;
+
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = os_mempool_init(&nrf5340_ble_hci_pool_acl, MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                         POOL_ACL_BLOCK_SIZE, nrf5340_ble_hci_pool_acl_buf,
+                         "nrf5340_ble_hci_pool_acl");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mbuf_pool_init(&nrf5340_ble_hci_pool_acl_mbuf,
+                           &nrf5340_ble_hci_pool_acl, POOL_ACL_BLOCK_SIZE,
+                           MYNEWT_VAL(BLE_ACL_BUF_COUNT));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&nrf5340_ble_hci_pool_evt_hi,
+                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         nrf5340_ble_hci_pool_evt_hi_buf,
+                         "nrf5340_ble_hci_pool_evt_hi");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&nrf5340_ble_hci_pool_evt_lo,
+                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         nrf5340_ble_hci_pool_evt_lo_buf,
+                         "nrf5340_ble_hci_pool_evt_lo");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    ipc_nrf5340_recv(IPC_RX_CHANNEL, nrf5340_ble_hci_trans_rx, NULL);
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml
new file mode 100644
index 00000000..1417bbc0
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml
@@ -0,0 +1,51 @@
+# 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_HCI_EVT_HI_BUF_COUNT:
+        description: 'Number of high-priority event buffers.'
+        value:  2
+
+    BLE_HCI_EVT_LO_BUF_COUNT:
+        description: 'Number of low-priority event buffers.'
+        value:  8
+
+    BLE_HCI_EVT_BUF_SIZE:
+        description: 'Size of each event buffer, in bytes.'
+        value:  70
+
+    BLE_ACL_BUF_COUNT:
+        description: 'The number of ACL data buffers'
+        value: 4
+
+    BLE_ACL_BUF_SIZE:
+        description: >
+            This is the maximum size of the data portion of HCI ACL data
+            packets. It does not include the HCI data header (of 4 bytes).
+        value: 255
+
+    BLE_TRANS_NRF5340_SYSINIT_STAGE:
+        description: >
+            Sysinit stage for the RAM BLE transport.
+        value: 100
+
+syscfg.vals.BLE_EXT_ADV:
+    BLE_HCI_EVT_BUF_SIZE: 257
+    
+syscfg.restrictions:
+    - '!(BLE_HOST && BLE_CONTROLLER)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/pkg.yml
index 2bc4ac29..8174286d 100644
--- a/src/libs/mynewt-nimble/nimble/transport/pkg.yml
+++ b/src/libs/mynewt-nimble/nimble/transport/pkg.yml
@@ -43,3 +43,12 @@ pkg.deps.'BLE_HCI_TRANSPORT == "uart"':
 
 pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"':
     - nimble/transport/da1469x
+
+pkg.deps.'BLE_HCI_TRANSPORT == "dialog_cmac"':
+    - nimble/transport/dialog_cmac
+
+pkg.deps.'BLE_HCI_TRANSPORT == "usb"':
+    - nimble/transport/usb
+
+pkg.deps.'BLE_HCI_TRANSPORT == "nrf5340"':
+    - nimble/transport/nrf5340
diff --git a/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c b/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
index 863d0fbb..44de8fed 100644
--- a/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
+++ b/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
@@ -53,19 +53,22 @@
 
 #if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
 #include <sys/errno.h>
-#define BTPROTO_HCI 1
-#define HCI_CHANNEL_RAW		0
-#define HCI_CHANNEL_USER	1
-#define HCIDEVUP	_IOW('H', 201, int)
-#define HCIDEVDOWN	_IOW('H', 202, int)
-#define HCIDEVRESET	_IOW('H', 203, int)
-#define HCIGETDEVLIST	_IOR('H', 210, int)
+#define BTPROTO_HCI       1
+#define HCI_CHANNEL_RAW	  0
+#define HCI_CHANNEL_USER  1
+#define HCIDEVUP          _IOW('H', 201, int)
+#define HCIDEVDOWN        _IOW('H', 202, int)
+#define HCIDEVRESET       _IOW('H', 203, int)
+#define HCIGETDEVLIST     _IOR('H', 210, int)
 
 struct sockaddr_hci {
-        sa_family_t    hci_family;
-        unsigned short hci_dev;
-        unsigned short hci_channel;
+    sa_family_t hci_family;
+    unsigned short hci_dev;
+    unsigned short hci_channel;
 };
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+#include <errno.h>
+#include <netpacket/bluetooth.h>
 #endif
 
 #include <fcntl.h>
@@ -205,6 +208,8 @@ static struct ble_hci_sock_state {
 static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_TCP_PORT);
 #elif MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
 static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_LINUX_DEV);
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int s_ble_hci_device = 0;
 #endif
 
 /**
@@ -227,6 +232,7 @@ ble_hci_trans_acl_buf_alloc(void)
     return m;
 }
 
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
 static int
 ble_hci_sock_acl_tx(struct os_mbuf *om)
 {
@@ -268,10 +274,66 @@ ble_hci_sock_acl_tx(struct os_mbuf *om)
     }
     return 0;
 }
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_acl_tx(struct os_mbuf *om)
+{
+    size_t len;
+    uint8_t *buf;
+    int i;
+    struct os_mbuf *m;
+    struct sockaddr_hci addr;
 
+    addr.hci_family = AF_BLUETOOTH;
+    addr.hci_channel = HCI_CHANNEL_RAW;
+    addr.hci_dev = 0;
+
+    memcpy(&addr, &addr, sizeof(struct sockaddr_hci));
+
+    len = 1;
+
+    for (m = om; m; m = SLIST_NEXT(m, om_next)) {
+        len += m->om_len;
+    }
+
+    buf = (uint8_t *)malloc(len);
+
+    buf[0] = BLE_HCI_UART_H4_ACL;
+
+    i = 1;
+    for (m = om; m; m = SLIST_NEXT(m, om_next)) {
+        memcpy(&buf[i], m->om_data, m->om_len);
+        i += m->om_len;
+    }
+
+    STATS_INC(hci_sock_stats, omsg);
+    STATS_INC(hci_sock_stats, oacl);
+    STATS_INCN(hci_sock_stats, obytes, OS_MBUF_PKTLEN(om) + 1);
+
+    i = sendto(ble_hci_sock_state.sock, buf, len, 0,
+               (struct sockaddr *)&addr, sizeof(struct sockaddr_hci));
+
+    free(buf);
+
+    os_mbuf_free_chain(om);
+    if (i != OS_MBUF_PKTLEN(om) + 1) {
+        if (i < 0) {
+            dprintf(1, "sendto() failed : %d\n", errno);
+        } else {
+            dprintf(1, "sendto() partial write: %d\n", i);
+        }
+        STATS_INC(hci_sock_stats, oerr);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+    return 0;
+}
+#endif
+
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
 static int
 ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
 {
+    uint8_t btaddr[6];
     struct msghdr msg;
     struct iovec iov[8];
     int len;
@@ -316,6 +378,57 @@ ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
 
     return 0;
 }
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
+{
+    uint8_t *buf;
+    size_t len;
+    struct sockaddr_hci addr;
+    int i;
+
+    addr.hci_family = AF_BLUETOOTH;
+    addr.hci_channel = HCI_CHANNEL_RAW;
+    addr.hci_dev = 0;
+
+    memcpy(&addr, &addr, sizeof(struct sockaddr_hci));
+
+    if (h4_type == BLE_HCI_UART_H4_CMD) {
+        len = sizeof(struct ble_hci_cmd) + hci_ev[2];
+        STATS_INC(hci_sock_stats, ocmd);
+    } else if (h4_type == BLE_HCI_UART_H4_EVT) {
+        len = sizeof(struct ble_hci_ev) + hci_ev[1];
+        STATS_INC(hci_sock_stats, oevt);
+    } else {
+        assert(0);
+    }
+
+    STATS_INC(hci_sock_stats, omsg);
+    STATS_INCN(hci_sock_stats, obytes, len + 1);
+
+    buf = (uint8_t *)malloc(len + 1);
+
+    buf[0] = h4_type;
+    memcpy(&buf[1], hci_ev, len);
+
+    i = sendto(ble_hci_sock_state.sock, buf, len + 1, 0,
+               (struct sockaddr *)&addr, sizeof(struct sockaddr_hci));
+
+    free(buf);
+    ble_hci_trans_buf_free(hci_ev);
+    if (i != len + 1) {
+        if (i < 0) {
+            dprintf(1, "sendto() failed : %d\n", errno);
+        } else {
+            dprintf(1, "sendto() partial write: %d\n", i);
+        }
+        STATS_INC(hci_sock_stats, oerr);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    return 0;
+}
+#endif
 
 static int
 ble_hci_sock_rx_msg(void)
@@ -427,6 +540,7 @@ ble_hci_sock_rx_msg(void)
             STATS_INC(hci_sock_stats, ierr);
             break;
         }
+
         memmove(bhss->rx_data, &bhss->rx_data[len], bhss->rx_off - len);
         bhss->rx_off -= len;
     }
@@ -540,7 +654,7 @@ ble_hci_sock_config(void)
 
     rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
     if (rc) {
-        dprintf(1, "bind() failed %d\n", errno);
+        dprintf(1, "bind() failed %d hci%d\n", errno, shci.hci_dev);
         goto err;
     }
 
@@ -565,7 +679,54 @@ err:
     }
     return BLE_ERR_HW_FAIL;
 }
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_config(void)
+{
+    struct sockaddr_hci shci;
+    int s;
+    int rc;
+    ble_npl_time_t timeout;
+
+    memset(&shci, 0, sizeof(shci));
+    shci.hci_family = AF_BLUETOOTH;
+    shci.hci_dev = 0;
+    shci.hci_channel = HCI_CHANNEL_RAW;
+
+    if (ble_hci_sock_state.sock >= 0) {
+        close(ble_hci_sock_state.sock);
+        ble_hci_sock_state.sock = -1;
+    }
+
+    s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+    if (s < 0) {
+        dprintf(1, "socket() failed %d\n", errno);
+        goto err;
+    }
+
+    rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
+    if (rc) {
+        dprintf(1, "bind() failed %d hci%d\n", errno, shci.hci_dev);
+        goto err;
+    }
+
+    ble_hci_sock_state.sock = s;
+
+    rc = ble_npl_time_ms_to_ticks(10, &timeout);
+    if (rc) {
+        goto err;
+    }
+    ble_npl_callout_reset(&ble_hci_sock_state.timer, timeout);
+
+    return 0;
+err:
+    if (s >= 0) {
+        close(s);
+    }
+    return BLE_ERR_HW_FAIL;
+}
 #endif
+
 /**
  * Sends an HCI event from the controller to the host.
  *
diff --git a/src/libs/mynewt-nimble/nimble/transport/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
index 137d6e94..5bec6adf 100644
--- a/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
@@ -26,13 +26,16 @@ syscfg.defs:
         value: builtin
         restrictions: $notnull
         choices:
-            - builtin   # Built-in NimBLE controller and RAM transport
-            - custom    # Custom transport, has to be included manually by user
-            - ram       # RAM transport
-            - uart      # UART HCI H4 transport
-            - socket    # Socket transport (for native builds)
-            - emspi     # SPI transport for EM Microelectionic controllers
-            - da1469x   # Dialog DA1469x integrated controller
+            - builtin           # Built-in NimBLE controller and RAM transport
+            - custom            # Custom transport, has to be included manually by user
+            - ram               # RAM transport
+            - uart              # UART HCI H4 transport
+            - socket            # Socket transport (for native builds)
+            - emspi             # SPI transport for EM Microelectionic controllers
+            - da1469x           # Dialog DA1469x integrated controller
+            - dialog_cmac       # Dialog CMAC via shared memory
+            - usb               # USB
+            - nrf5340           # nRF5340
 
 # Deprecated settings
     BLE_HCI_TRANSPORT_NIMBLE_BUILTIN:
diff --git a/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c b/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
index ac6af28e..cbb6dd42 100644
--- a/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
+++ b/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
@@ -195,8 +195,6 @@ ble_hci_trans_acl_buf_alloc(void)
 
 #if MYNEWT_VAL(BLE_CONTROLLER)
     usrhdr_len = sizeof(struct ble_mbuf_hdr);
-#elif MYNEWT_VAL(BLE_HS_FLOW_CTRL)
-    usrhdr_len = BLE_MBUF_HS_HDR_LEN;
 #else
     usrhdr_len = 0;
 #endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml
new file mode 100644
index 00000000..49317c97
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/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: nimble/transport/usb
+pkg.description: Provides HCI transport over USB interface
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+    - usb
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/util/mem"
+    - nimble
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    ble_hci_usb_init: 'MYNEWT_VAL(BLE_TRANS_USB_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c b/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c
new file mode 100644
index 00000000..55c91f22
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c
@@ -0,0 +1,410 @@
+/*
+ * 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 <assert.h>
+#include <stddef.h>
+#include "syscfg/syscfg.h"
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "mem/mem.h"
+
+#include "nimble/ble.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+
+#include <class/bth/bth_device.h>
+
+/*
+ * The MBUF payload size must accommodate the HCI data header size plus the
+ * maximum ACL data packet length. The ACL block size is the size of the
+ * mbufs we will allocate.
+ */
+#define ACL_BLOCK_SIZE  OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
+                                 + BLE_MBUF_MEMBLOCK_OVERHEAD \
+                                 + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+struct usb_ble_hci_pool_cmd {
+    uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
+    bool allocated;
+};
+
+/* (Pseudo)pool for HCI commands */
+static struct usb_ble_hci_pool_cmd usb_ble_hci_pool_cmd;
+
+static ble_hci_trans_rx_cmd_fn *ble_hci_usb_rx_cmd_ll_cb;
+static void *ble_hci_usb_rx_cmd_ll_arg;
+
+static ble_hci_trans_rx_acl_fn *ble_hci_usb_rx_acl_ll_cb;
+static void *ble_hci_usb_rx_acl_ll_arg;
+
+static struct os_mempool ble_hci_usb_evt_hi_pool;
+static os_membuf_t ble_hci_usb_evt_hi_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static struct os_mempool ble_hci_usb_evt_lo_pool;
+static os_membuf_t ble_hci_usb_evt_lo_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static uint8_t ble_hci_pool_acl_mempool_buf[
+    OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                     ACL_BLOCK_SIZE)];
+static struct os_mempool ble_hci_pool_acl_mempool;
+static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
+
+static struct os_mbuf *incoming_acl_data;
+
+static struct os_mbuf *
+ble_hci_trans_acl_buf_alloc(void)
+{
+    struct os_mbuf *m;
+
+    m = os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
+                           sizeof(struct ble_mbuf_hdr));
+    return m;
+}
+
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                     void *cmd_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb,
+                     void *acl_arg)
+{
+    ble_hci_usb_rx_cmd_ll_cb = cmd_cb;
+    ble_hci_usb_rx_cmd_ll_arg = cmd_arg;
+    ble_hci_usb_rx_acl_ll_cb = acl_cb;
+    ble_hci_usb_rx_acl_ll_arg = acl_arg;
+}
+
+#define BLE_HCI_USB_EVT_COUNT  \
+    (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
+
+/**
+ * A packet to be sent over the USB.  This can be a command, an event, or ACL
+ * data.
+ */
+struct ble_hci_pkt {
+    STAILQ_ENTRY(ble_hci_pkt) next;
+    void *data;
+};
+
+static struct os_mempool ble_hci_pkt_pool;
+static os_membuf_t ble_hci_pkt_buf[
+    OS_MEMPOOL_SIZE(BLE_HCI_USB_EVT_COUNT + 1 +
+                    MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                    sizeof(struct ble_hci_pkt))];
+
+struct tx_queue {
+    STAILQ_HEAD(, ble_hci_pkt) queue;
+};
+
+static struct tx_queue ble_hci_tx_acl_queue = {STAILQ_HEAD_INITIALIZER(ble_hci_tx_acl_queue.queue)};
+static struct tx_queue ble_hci_tx_evt_queue = { STAILQ_HEAD_INITIALIZER(ble_hci_tx_evt_queue.queue) };
+
+/*
+ * TinyUSB callbacks.
+ */
+void
+tud_bt_acl_data_sent_cb(uint16_t sent_bytes)
+{
+    struct os_mbuf *om;
+    struct ble_hci_pkt *curr_acl;
+    struct ble_hci_pkt *next_acl;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    curr_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+
+    assert(curr_acl != NULL);
+    om = curr_acl->data;
+    assert(om != NULL && om->om_len >= sent_bytes);
+    os_mbuf_adj(om, sent_bytes);
+
+    while (om != NULL && om->om_len == 0) {
+        curr_acl->data = SLIST_NEXT(om, om_next);
+        os_mbuf_free(om);
+        om = curr_acl->data;
+    }
+
+    if (om == NULL) {
+        OS_ENTER_CRITICAL(sr);
+        STAILQ_REMOVE_HEAD(&ble_hci_tx_acl_queue.queue, next);
+        next_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+        OS_EXIT_CRITICAL(sr);
+        os_memblock_put(&ble_hci_pkt_pool, curr_acl);
+        if (next_acl != NULL) {
+            om = next_acl->data;
+        }
+    }
+
+    if (om != NULL) {
+        tud_bt_acl_data_send(om->om_data, om->om_len);
+    }
+}
+
+void
+tud_bt_event_sent_cb(uint16_t sent_bytes)
+{
+    struct ble_hci_pkt *curr_evt;
+    struct ble_hci_pkt *next_evt;
+    uint8_t *hci_ev;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    curr_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+    assert(curr_evt != NULL);
+    hci_ev = curr_evt->data;
+
+    assert(hci_ev != NULL && hci_ev[1] + sizeof(struct ble_hci_ev) == sent_bytes);
+
+    ble_hci_trans_buf_free(hci_ev);
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_REMOVE_HEAD(&ble_hci_tx_evt_queue.queue, next);
+    next_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+    OS_EXIT_CRITICAL(sr);
+    os_memblock_put(&ble_hci_pkt_pool, curr_evt);
+
+    if (next_evt != NULL) {
+        hci_ev = next_evt->data;
+        tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+    }
+}
+
+void
+tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len)
+{
+    uint8_t *data;
+    uint32_t len;
+    struct os_mbuf *om = incoming_acl_data;
+    int rc;
+
+    if (om == NULL) {
+        om = ble_hci_trans_acl_buf_alloc();
+        assert(om != NULL);
+    }
+    assert(om->om_len + data_len <= MYNEWT_VAL(BLE_ACL_BUF_SIZE) + BLE_HCI_DATA_HDR_SZ);
+
+    os_mbuf_append(om, acl_data, data_len);
+    incoming_acl_data = om;
+    if (om->om_len > BLE_HCI_DATA_HDR_SZ) {
+        data = incoming_acl_data->om_data;
+        len = data[2] + (data[3] << 8) + BLE_HCI_DATA_HDR_SZ;
+        if (len >= incoming_acl_data->om_len) {
+            incoming_acl_data = NULL;
+            rc = ble_hci_usb_rx_acl_ll_cb(om, ble_hci_usb_rx_acl_ll_arg);
+            (void)rc;
+        }
+    }
+}
+
+void
+tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len)
+{
+    uint8_t *buf;
+    int rc = -1;
+
+    assert(ble_hci_usb_rx_cmd_ll_cb);
+    if (ble_hci_usb_rx_cmd_ll_cb) {
+        buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+        assert(buf != NULL);
+        memcpy(buf, hci_cmd, cmd_len);
+
+        rc = ble_hci_usb_rx_cmd_ll_cb(buf, ble_hci_usb_rx_cmd_ll_arg);
+    }
+
+    if (rc != 0) {
+        ble_hci_trans_buf_free(buf);
+    }
+}
+
+static int
+ble_hci_trans_ll_tx(struct tx_queue *queue, struct os_mbuf *om)
+{
+    struct ble_hci_pkt *pkt;
+    os_sr_t sr;
+    bool first;
+
+    /* If this packet is zero length, just free it */
+    if (OS_MBUF_PKTLEN(om) == 0) {
+        os_mbuf_free_chain(om);
+        return 0;
+    }
+
+    pkt = os_memblock_get(&ble_hci_pkt_pool);
+    if (pkt == NULL) {
+        os_mbuf_free_chain(om);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->data = om;
+    OS_ENTER_CRITICAL(sr);
+    first = STAILQ_EMPTY(&queue->queue);
+    STAILQ_INSERT_TAIL(&queue->queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+    if (first) {
+        tud_bt_acl_data_send(om->om_data, om->om_len);
+    }
+
+    return 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+    return ble_hci_trans_ll_tx(&ble_hci_tx_acl_queue, om);
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+{
+    struct ble_hci_pkt *pkt;
+    os_sr_t sr;
+    bool first;
+
+    assert(hci_ev != NULL);
+
+    pkt = os_memblock_get(&ble_hci_pkt_pool);
+    if (pkt == NULL) {
+        ble_hci_trans_buf_free(hci_ev);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->data = hci_ev;
+    OS_ENTER_CRITICAL(sr);
+    first = STAILQ_EMPTY(&ble_hci_tx_evt_queue.queue);
+    STAILQ_INSERT_TAIL(&ble_hci_tx_evt_queue.queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+    if (first) {
+        tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+    }
+
+    return 0;
+}
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+    uint8_t *buf;
+
+    switch (type) {
+    case BLE_HCI_TRANS_BUF_CMD:
+        assert(!usb_ble_hci_pool_cmd.allocated);
+        usb_ble_hci_pool_cmd.allocated = 1;
+        buf = usb_ble_hci_pool_cmd.cmd;
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_HI:
+        buf = os_memblock_get(&ble_hci_usb_evt_hi_pool);
+        if (buf == NULL) {
+            /* If no high-priority event buffers remain, try to grab a
+             * low-priority one.
+             */
+            buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+        }
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_usb_evt_lo_pool);
+        break;
+
+    default:
+        assert(0);
+        buf = NULL;
+    }
+
+    return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+    int rc;
+
+    /* XXX: this may look a bit odd, but the controller uses the command
+     * buffer to send back the command complete/status as an immediate
+     * response to the command. This was done to insure that the controller
+     * could always send back one of these events when a command was received.
+     * Thus, we check to see which pool the buffer came from so we can free
+     * it to the appropriate pool
+     */
+    if (os_memblock_from(&ble_hci_usb_evt_hi_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_usb_evt_hi_pool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_usb_evt_lo_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_usb_evt_lo_pool, buf);
+        assert(rc == 0);
+    } else {
+        assert(usb_ble_hci_pool_cmd.allocated);
+        usb_ble_hci_pool_cmd.allocated = 0;
+    }
+    (void)rc;
+}
+
+int
+ble_hci_trans_reset(void)
+{
+    return 0;
+}
+
+void
+ble_hci_usb_init(void)
+{
+    int rc;
+
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = mem_init_mbuf_pool(ble_hci_pool_acl_mempool_buf, &ble_hci_pool_acl_mempool, &ble_hci_pool_acl_mbuf_pool,
+                            MYNEWT_VAL(BLE_ACL_BUF_COUNT), ACL_BLOCK_SIZE, "ble_hci_acl");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_usb_evt_hi_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_usb_evt_hi_buf,
+                         "ble_hci_usb_evt_hi_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_usb_evt_lo_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_usb_evt_lo_buf,
+                         "ble_hci_usb_evt_lo_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    /*
+     * Create memory pool of packet list nodes. NOTE: the number of these
+     * buffers should be, at least, the total number of event buffers (hi
+     * and lo), the number of command buffers (currently 1) and the total
+     * number of buffers that the controller could possibly hand to the host.
+     */
+    rc = os_mempool_init(&ble_hci_pkt_pool,
+                         BLE_HCI_USB_EVT_COUNT + 1 +
+                         MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                         sizeof (struct ble_hci_pkt),
+                         ble_hci_pkt_buf,
+                         "ble_hci_usb_pkt_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml
new file mode 100644
index 00000000..ebc261a2
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml
@@ -0,0 +1,57 @@
+# 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_HCI_EVT_BUF_SIZE:
+        description: 'The size of the allocated event buffers'
+        value: 70
+    BLE_HCI_EVT_HI_BUF_COUNT:
+        description: 'The number of high priority event buffers'
+        value: 8
+    BLE_HCI_EVT_LO_BUF_COUNT:
+        description: 'The number of low priority event buffers'
+        value: 8
+    BLE_ACL_BUF_COUNT:
+        description: 'The number of ACL data buffers'
+        value: 12
+    BLE_ACL_BUF_SIZE:
+        description: >
+            This is the maximum size of the data portion of HCI ACL data
+            packets. It does not include the HCI data header (of 4 bytes).
+        value: 255
+
+    BLE_HCI_ACL_OUT_COUNT:
+        description: >
+            This count is used in creating a pool of elements used by the
+            code to enqueue various elements. In the case of the controller
+            only HCI, this number should be equal to the number of mbufs in
+            the msys pool. For host only, it is really dependent on the
+            number of ACL buffers that the controller tells the host it
+            has.
+        value: 12
+
+    BLE_TRANS_USB_SYSINIT_STAGE:
+        description: >
+            Sysinit stage for the USB BLE transport.
+        value: 500
+
+syscfg.vals.BLE_EXT_ADV:
+    BLE_HCI_EVT_BUF_SIZE: 257
+
+syscfg.restrictions:
+    - '!BLE_HOST'
diff --git a/src/libs/mynewt-nimble/porting/examples/linux/include/logcfg/logcfg.h b/src/libs/mynewt-nimble/porting/examples/linux/include/logcfg/logcfg.h
index e21a3ae5..837cdeac 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux/include/logcfg/logcfg.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux/include/logcfg/logcfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_LOGCFG_
diff --git a/src/libs/mynewt-nimble/porting/examples/linux/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/examples/linux/include/syscfg/syscfg.h
index 7e9bfcac..99939f2b 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux/include/syscfg/syscfg.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux/include/syscfg/syscfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSCFG_
@@ -15,8 +15,6 @@
 #define MYNEWT_VAL(_name)                       MYNEWT_VAL_ ## _name
 #define MYNEWT_VAL_CHOICE(_name, _val)          MYNEWT_VAL_ ## _name ## __ ## _val
 
-
-
 /*** @apache-mynewt-core/crypto/tinycrypt */
 #ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE
 #define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200)
@@ -297,7 +295,7 @@
 #define MYNEWT_VAL_LOG_FCB_SLOT1 (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux (defined by @apache-mynewt-core/sys/log/stub) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux (defined by @apache-mynewt-core/sys/log/stub) */
 #ifndef MYNEWT_VAL_LOG_LEVEL
 #define MYNEWT_VAL_LOG_LEVEL (0)
 #endif
@@ -368,6 +366,14 @@
 #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
 #define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
 #endif
@@ -945,12 +951,12 @@
 #define MYNEWT_VAL_BLE_SOCK_LINUX_DEV (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_STACK_SIZE
 #define MYNEWT_VAL_BLE_SOCK_STACK_SIZE (1028)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_TASK_PRIO
 #define MYNEWT_VAL_BLE_SOCK_TASK_PRIO (3)
 #endif
@@ -959,12 +965,12 @@
 #define MYNEWT_VAL_BLE_SOCK_TCP_PORT (14433)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE
 #define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_USE_TCP
 #define MYNEWT_VAL_BLE_SOCK_USE_TCP (0)
 #endif
diff --git a/src/libs/mynewt-nimble/porting/examples/linux/include/sysflash/sysflash.h b/src/libs/mynewt-nimble/porting/examples/linux/include/sysflash/sysflash.h
index 413cb267..ab1341b2 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux/include/sysflash/sysflash.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux/include/sysflash/sysflash.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSFLASH_
diff --git a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/ble.c b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/ble.c
index 22a9e71d..deaef5a4 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/ble.c
+++ b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/ble.c
@@ -40,26 +40,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_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 int
 fault_get_cur(struct bt_mesh_model *model,
               uint8_t *test_id,
@@ -323,7 +303,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),
@@ -381,7 +361,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/porting/examples/linux_blemesh/include/logcfg/logcfg.h b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h
index 7404dbb4..798418da 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_LOGCFG_
@@ -106,6 +106,34 @@
 #define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__)
 #define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__)
 
+#define BLE_MESH_RPL_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define BLE_MESH_RPL_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__)
+#define BLE_MESH_RPL_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__)
+#define BLE_MESH_RPL_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__)
+#define BLE_MESH_RPL_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__)
+#define BLE_MESH_RPL_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__)
+
+#define BLE_MESH_NET_KEYS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define BLE_MESH_NET_KEYS_LOG_INFO(...) MODLOG_INFO(23, __VA_ARGS__)
+#define BLE_MESH_NET_KEYS_LOG_WARN(...) MODLOG_WARN(23, __VA_ARGS__)
+#define BLE_MESH_NET_KEYS_LOG_ERROR(...) MODLOG_ERROR(23, __VA_ARGS__)
+#define BLE_MESH_NET_KEYS_LOG_CRITICAL(...) MODLOG_CRITICAL(23, __VA_ARGS__)
+#define BLE_MESH_NET_KEYS_LOG_DISABLED(...) MODLOG_DISABLED(23, __VA_ARGS__)
+
+#define BLE_MESH_PROV_DEVICE_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define BLE_MESH_PROV_DEVICE_LOG_INFO(...) MODLOG_INFO(24, __VA_ARGS__)
+#define BLE_MESH_PROV_DEVICE_LOG_WARN(...) MODLOG_WARN(24, __VA_ARGS__)
+#define BLE_MESH_PROV_DEVICE_LOG_ERROR(...) MODLOG_ERROR(24, __VA_ARGS__)
+#define BLE_MESH_PROV_DEVICE_LOG_CRITICAL(...) MODLOG_CRITICAL(24, __VA_ARGS__)
+#define BLE_MESH_PROV_DEVICE_LOG_DISABLED(...) MODLOG_DISABLED(24, __VA_ARGS__)
+
+#define BLE_MESH_HEARTBEAT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define BLE_MESH_HEARTBEAT_LOG_INFO(...) MODLOG_INFO(25, __VA_ARGS__)
+#define BLE_MESH_HEARTBEAT_LOG_WARN(...) MODLOG_WARN(25, __VA_ARGS__)
+#define BLE_MESH_HEARTBEAT_LOG_ERROR(...) MODLOG_ERROR(25, __VA_ARGS__)
+#define BLE_MESH_HEARTBEAT_LOG_CRITICAL(...) MODLOG_CRITICAL(25, __VA_ARGS__)
+#define BLE_MESH_HEARTBEAT_LOG_DISABLED(...) MODLOG_DISABLED(25, __VA_ARGS__)
+
 #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
 #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__)
 #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__)
diff --git a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h
index 24ad0c58..9aac1068 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSCFG_
@@ -15,8 +15,6 @@
 #define MYNEWT_VAL(_name)                       MYNEWT_VAL_ ## _name
 #define MYNEWT_VAL_CHOICE(_name, _val)          MYNEWT_VAL_ ## _name ## __ ## _val
 
-
-
 /*** @apache-mynewt-core/crypto/tinycrypt */
 #ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE
 #define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200)
@@ -56,7 +54,7 @@
 #define MYNEWT_VAL_FLOAT_USER (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-core/kernel/os) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-core/kernel/os) */
 #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
 #define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (80)
 #endif
@@ -298,7 +296,7 @@
 #define MYNEWT_VAL_LOG_FCB_SLOT1 (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-core/sys/log/stub) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-core/sys/log/stub) */
 #ifndef MYNEWT_VAL_LOG_LEVEL
 #define MYNEWT_VAL_LOG_LEVEL (0)
 #endif
@@ -369,6 +367,14 @@
 #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
 #define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
 #endif
@@ -650,7 +656,7 @@
 #define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host) */
 #ifndef MYNEWT_VAL_BLE_MESH
 #define MYNEWT_VAL_BLE_MESH (1)
 #endif
@@ -757,7 +763,7 @@
 #define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD (10)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT
 #define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20)
 #endif
@@ -774,7 +780,7 @@
 #define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT
 #define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (4)
 #endif
@@ -787,7 +793,7 @@
 #define MYNEWT_VAL_BLE_MESH_BEACON_LOG_MOD (12)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_CFG_CLI
 #define MYNEWT_VAL_BLE_MESH_CFG_CLI (1)
 #endif
@@ -812,7 +818,7 @@
 #define MYNEWT_VAL_BLE_MESH_DEV_UUID (((uint8_t[16]){0x11, 0x22, 0}))
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_FRIEND
 #define MYNEWT_VAL_BLE_MESH_FRIEND (1)
 #endif
@@ -845,7 +851,7 @@
 #define MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE (3)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY
 #define MYNEWT_VAL_BLE_MESH_GATT_PROXY (1)
 #endif
@@ -858,12 +864,12 @@
 #define MYNEWT_VAL_BLE_MESH_IVU_DIVIDER (4)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST
 #define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_LABEL_COUNT
 #define MYNEWT_VAL_BLE_MESH_LABEL_COUNT (2)
 #endif
@@ -876,7 +882,7 @@
 #define MYNEWT_VAL_BLE_MESH_LOG_MOD (9)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER
 #define MYNEWT_VAL_BLE_MESH_LOW_POWER (1)
 #endif
@@ -889,7 +895,7 @@
 #define MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_MOD (15)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_LPN_AUTO
 #define MYNEWT_VAL_BLE_MESH_LPN_AUTO (0)
 #endif
@@ -906,6 +912,10 @@
 #define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (10)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR
+#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (1)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT
 #define MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT (MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT)
 #endif
@@ -942,7 +952,7 @@
 #define MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT
 #define MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT (2)
 #endif
@@ -995,17 +1005,17 @@
 #define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (4)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_PB_ADV
 #define MYNEWT_VAL_BLE_MESH_PB_ADV (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_PB_GATT
 #define MYNEWT_VAL_BLE_MESH_PB_GATT (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_PROV
 #define MYNEWT_VAL_BLE_MESH_PROV (1)
 #endif
@@ -1014,6 +1024,22 @@
 #define MYNEWT_VAL_BLE_MESH_PROVISIONER (0)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_MESH_CDB
+#define MYNEWT_VAL_BLE_MESH_CDB (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT
+#define MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT
+#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT
+#define MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT (1)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL
 #define MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL (1)
 #endif
@@ -1039,7 +1065,7 @@
 #define MYNEWT_VAL_BLE_MESH_PROXY_LOG_MOD (19)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_RELAY
 #define MYNEWT_VAL_BLE_MESH_RELAY (1)
 #endif
@@ -1048,8 +1074,12 @@
 #define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5)
 #endif
 
-#ifndef MYNEWT_VAL_BLE_MESH_RX_SDU_MAX
-#define MYNEWT_VAL_BLE_MESH_RX_SDU_MAX (72)
+#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS
+#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (72)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX
+#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT
@@ -1064,7 +1094,7 @@
 #define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_SETTINGS
 #define MYNEWT_VAL_BLE_MESH_SETTINGS (0)
 #endif
@@ -1077,7 +1107,7 @@
 #define MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_MOD (20)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_SHELL
 #define MYNEWT_VAL_BLE_MESH_SHELL (0)
 #endif
@@ -1090,7 +1120,7 @@
 #define MYNEWT_VAL_BLE_MESH_STORE_TIMEOUT (2)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_SUBNET_COUNT
 #define MYNEWT_VAL_BLE_MESH_SUBNET_COUNT (2)
 #endif
@@ -1103,7 +1133,7 @@
 #define MYNEWT_VAL_BLE_MESH_SYSINIT_STAGE_SHELL (1000)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_TESTING
 #define MYNEWT_VAL_BLE_MESH_TESTING (1)
 #endif
@@ -1116,15 +1146,88 @@
 #define MYNEWT_VAL_BLE_MESH_TRANS_LOG_MOD (21)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
+#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL
+#define MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD
+#define MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD (22)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
 #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MAX
 #define MYNEWT_VAL_BLE_MESH_TX_SEG_MAX (6)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT
+#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (3)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT
+#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT
+#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT
 #define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT
+#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT (4)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST
+#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP
+#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (50)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS
+#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL
+#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT
+#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL
+#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT
+#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED
+#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED
+#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED
+#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED
+#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL
+#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20)
+#endif
+
 /*** @apache-mynewt-nimble/nimble/host/services/ans */
 #ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
 #define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
@@ -1325,12 +1428,12 @@
 #define MYNEWT_VAL_BLE_SOCK_LINUX_DEV (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_STACK_SIZE
 #define MYNEWT_VAL_BLE_SOCK_STACK_SIZE (1028)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_TASK_PRIO
 #define MYNEWT_VAL_BLE_SOCK_TASK_PRIO (3)
 #endif
@@ -1339,12 +1442,12 @@
 #define MYNEWT_VAL_BLE_SOCK_TCP_PORT (14433)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE
 #define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/transport/socket) */
 #ifndef MYNEWT_VAL_BLE_SOCK_USE_TCP
 #define MYNEWT_VAL_BLE_SOCK_USE_TCP (0)
 #endif
diff --git a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/sysflash/sysflash.h b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/sysflash/sysflash.h
index 413cb267..ab1341b2 100644
--- a/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/sysflash/sysflash.h
+++ b/src/libs/mynewt-nimble/porting/examples/linux_blemesh/include/sysflash/sysflash.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSFLASH_
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/Make.defs b/src/libs/mynewt-nimble/porting/examples/nuttx/Make.defs
new file mode 100644
index 00000000..f35d428e
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/Make.defs
@@ -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.
+#
+
+# Configure NimBLE variables
+NIMBLE_CFG_TINYCRYPT := 1
+
+# Skip files that don't build for this port
+NIMBLE_IGNORE := $(NIMBLE_ROOT)/porting/nimble/src/hal_timer.c \
+	$(NIMBLE_ROOT)/porting/nimble/src/os_cputime.c \
+	$(NIMBLE_ROOT)/porting/nimble/src/os_cputime_pwr2.c
+
+include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
+
+CSRCS := $(NIMBLE_SRC)
+
+# Source files for NPL OSAL
+CSRCS += \
+	$(wildcard $(NIMBLE_ROOT)/porting/npl/nuttx/src/*.c) \
+	$(wildcard $(NIMBLE_ROOT)/nimble/transport/socket/src/*.c) \
+	$(TINYCRYPT_SRC)
+
+# Source files for demo app
+CSRCS += $(NIMBLE_ROOT)/porting/examples/nuttx/ble.c
+
+MAINSRC = $(NIMBLE_ROOT)/porting/examples/nuttx/main.c
+
+# Add NPL and all NimBLE directories to include paths
+INC = \
+  $(wildcard $(NIMBLE_ROOT)/porting/examples/nuttx/include) \
+	$(NIMBLE_ROOT)/porting/npl/nuttx/include \
+	$(NIMBLE_ROOT)/nimble/transport/socket/include \
+	$(NIMBLE_INCLUDE) \
+	$(TINYCRYPT_INCLUDE)
+
+INCLUDES := $(addprefix -I, $(INC))
+
+CFLAGS +=                    \
+    $(NIMBLE_CFLAGS)        \
+    $(INCLUDES)             \
+    $(TINYCRYPT_CFLAGS)     \
+    -DNIMBLE_CFG_CONTROLLER=0 -DOS_CFG_ALIGN_4=4 -DOS_CFG_ALIGNMENT=4 \
+    -Ddefault_RNG_defined=0
+
+PROGNAME=nimble
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/ble.c b/src/libs/mynewt-nimble/porting/examples/nuttx/ble.c
new file mode 100644
index 00000000..da7bdecc
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/ble.c
@@ -0,0 +1,118 @@
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "nimble/nimble_port.h"
+#include "host/ble_hs.h"
+#include "host/util/util.h"
+#include "services/gap/ble_svc_gap.h"
+
+static const char gap_name[] = "nimble";
+
+static uint8_t own_addr_type;
+
+static void start_advertise(void);
+
+static void
+put_ad(uint8_t ad_type, uint8_t ad_len, const void *ad, uint8_t *buf,
+       uint8_t *len)
+{
+    buf[(*len)++] = ad_len + 1;
+    buf[(*len)++] = ad_type;
+
+    memcpy(&buf[*len], ad, ad_len);
+
+    *len += ad_len;
+}
+
+static void
+update_ad(void)
+{
+    uint8_t ad[BLE_HS_ADV_MAX_SZ];
+    uint8_t ad_len = 0;
+    uint8_t ad_flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
+
+    put_ad(BLE_HS_ADV_TYPE_FLAGS, 1, &ad_flags, ad, &ad_len);
+    put_ad(BLE_HS_ADV_TYPE_COMP_NAME, sizeof(gap_name), gap_name, ad, &ad_len);
+
+    ble_gap_adv_set_data(ad, ad_len);
+}
+
+static int
+gap_event_cb(struct ble_gap_event *event, void *arg)
+{
+    switch (event->type) {
+    case BLE_GAP_EVENT_CONNECT:
+        if (event->connect.status) {
+            start_advertise();
+        }
+        break;
+
+    case BLE_GAP_EVENT_DISCONNECT:
+        start_advertise();
+        break;
+    }
+
+    return 0;
+}
+
+static void
+start_advertise(void)
+{
+    struct ble_gap_adv_params advp;
+    int rc;
+
+    printf("advertise\n");
+
+    update_ad();
+
+    memset(&advp, 0, sizeof advp);
+    advp.conn_mode = BLE_GAP_CONN_MODE_UND;
+    advp.disc_mode = BLE_GAP_DISC_MODE_GEN;
+    rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
+                           &advp, gap_event_cb, NULL);
+    assert(rc == 0);
+}
+
+static void
+app_ble_sync_cb(void)
+{
+    int rc;
+
+    rc = ble_hs_util_ensure_addr(0);
+    assert(rc == 0);
+
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    assert(rc == 0);
+
+    start_advertise();
+}
+
+void
+nimble_host_task(void *param)
+{
+    ble_hs_cfg.sync_cb = app_ble_sync_cb;
+
+    ble_svc_gap_device_name_set(gap_name);
+
+    nimble_port_run();
+}
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/include/logcfg/logcfg.h b/src/libs/mynewt-nimble/porting/examples/nuttx/include/logcfg/logcfg.h
new file mode 100644
index 00000000..837cdeac
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/include/logcfg/logcfg.h
@@ -0,0 +1,32 @@
+/**
+ * This file was generated by Apache newt version: 1.9.0-dev
+ */
+
+#ifndef H_MYNEWT_LOGCFG_
+#define H_MYNEWT_LOGCFG_
+
+#include "modlog/modlog.h"
+#include "log_common/log_common.h"
+
+#define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__)
+#define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__)
+#define BLE_HS_LOG_ERROR(...) MODLOG_ERROR(4, __VA_ARGS__)
+#define BLE_HS_LOG_CRITICAL(...) MODLOG_CRITICAL(4, __VA_ARGS__)
+#define BLE_HS_LOG_DISABLED(...) MODLOG_DISABLED(4, __VA_ARGS__)
+
+#define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__)
+#define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__)
+#define DFLT_LOG_ERROR(...) MODLOG_ERROR(0, __VA_ARGS__)
+#define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__)
+#define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__)
+
+#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
+#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__)
+#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__)
+#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__)
+#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__)
+#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__)
+
+#endif
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/examples/nuttx/include/syscfg/syscfg.h
new file mode 100644
index 00000000..ff73312e
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/include/syscfg/syscfg.h
@@ -0,0 +1,1074 @@
+/**
+ * This file was generated by Apache newt version: 1.9.0-dev
+ */
+
+#ifndef H_MYNEWT_SYSCFG_
+#define H_MYNEWT_SYSCFG_
+
+/**
+ * This macro exists to ensure code includes this header when needed.  If code
+ * checks the existence of a setting directly via ifdef without including this
+ * header, the setting macro will silently evaluate to 0.  In contrast, an
+ * attempt to use these macros without including this header will result in a
+ * compiler error.
+ */
+#define MYNEWT_VAL(_name)                       MYNEWT_VAL_ ## _name
+#define MYNEWT_VAL_CHOICE(_name, _val)          MYNEWT_VAL_ ## _name ## __ ## _val
+
+
+/*** Repository @apache-mynewt-core info */
+#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE
+#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("4d75fc41bd7ead84638ebbfad4841d5effb296dd")
+#endif
+
+#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE
+#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.1")
+#endif
+
+/*** Repository @apache-mynewt-mcumgr info */
+#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR
+#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("8d087a7e0e5485394419d10051606c92d68d2111")
+#endif
+
+#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR
+#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR ("0.0.0")
+#endif
+
+/*** Repository @apache-mynewt-nimble info */
+#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE
+#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("37dceb35df57ff41a6c31f79290512df2fde7064")
+#endif
+
+#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE
+#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE ("0.0.0")
+#endif
+
+/*** Repository @mcuboot info */
+#ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT
+#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("03d96ad1f6dd77d47ffca72ade9377acb8559115-dirty")
+#endif
+
+#ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT
+#define MYNEWT_VAL_REPO_VERSION_MCUBOOT ("0.0.0")
+#endif
+
+/*** Repository @my_project info */
+#ifndef MYNEWT_VAL_REPO_HASH_MY_PROJECT
+#define MYNEWT_VAL_REPO_HASH_MY_PROJECT ("37dceb35df57ff41a6c31f79290512df2fde7064")
+#endif
+
+#ifndef MYNEWT_VAL_REPO_VERSION_MY_PROJECT
+#define MYNEWT_VAL_REPO_VERSION_MY_PROJECT ("0.0.0")
+#endif
+
+
+
+/*** @apache-mynewt-core/crypto/tinycrypt */
+#ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE
+#define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200)
+#endif
+
+#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME
+#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME ("trng")
+#endif
+
+#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG
+#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0)
+#endif
+
+/*** @apache-mynewt-core/hw/hal */
+#ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS
+#define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1)
+#endif
+
+#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ
+#define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16)
+#endif
+
+#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES
+#define MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES (0)
+#endif
+
+#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES
+#define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0)
+#endif
+
+#ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB
+#define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0)
+#endif
+
+/*** @apache-mynewt-core/kernel/os */
+#ifndef MYNEWT_VAL_FLOAT_USER
+#define MYNEWT_VAL_FLOAT_USER (0)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
+#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
+#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT
+#define MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT (0)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT
+#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE
+#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_2_SANITY_MIN_COUNT
+#define MYNEWT_VAL_MSYS_2_SANITY_MIN_COUNT (0)
+#endif
+
+#ifndef MYNEWT_VAL_MSYS_SANITY_TIMEOUT
+#define MYNEWT_VAL_MSYS_SANITY_TIMEOUT (60000)
+#endif
+
+#ifndef MYNEWT_VAL_OS_ASSERT_CB
+#define MYNEWT_VAL_OS_ASSERT_CB (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CLI
+#define MYNEWT_VAL_OS_CLI (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_COREDUMP
+#define MYNEWT_VAL_OS_COREDUMP (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CPUTIME_FREQ
+#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM
+#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE
+#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CRASH_LOG
+#define MYNEWT_VAL_OS_CRASH_LOG (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CRASH_RESTORE_REGS
+#define MYNEWT_VAL_OS_CRASH_RESTORE_REGS (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CRASH_STACKTRACE
+#define MYNEWT_VAL_OS_CRASH_STACKTRACE (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_CHECK
+#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_GUARD
+#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4)
+#endif
+
+#ifndef MYNEWT_VAL_OS_DEBUG_MODE
+#define MYNEWT_VAL_OS_DEBUG_MODE (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_EVENTQ_DEBUG
+#define MYNEWT_VAL_OS_EVENTQ_DEBUG (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_EVENTQ_MONITOR
+#define MYNEWT_VAL_OS_EVENTQ_MONITOR (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX
+#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000)
+#endif
+
+#ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN
+#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE
+#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MAIN_TASK_PRIO
+#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MAIN_TASK_SANITY_ITVL_MS
+#define MYNEWT_VAL_OS_MAIN_TASK_SANITY_ITVL_MS (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MEMPOOL_CHECK
+#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MEMPOOL_GUARD
+#define MYNEWT_VAL_OS_MEMPOOL_GUARD (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_MEMPOOL_POISON
+#define MYNEWT_VAL_OS_MEMPOOL_POISON (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SCHEDULING
+#define MYNEWT_VAL_OS_SCHEDULING (1)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSINIT_STAGE
+#define MYNEWT_VAL_OS_SYSINIT_STAGE (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW
+#define MYNEWT_VAL_OS_SYSVIEW (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_CALLOUT
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_CALLOUT (1)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_EVENTQ
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_EVENTQ (1)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MBUF
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MBUF (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MEMPOOL
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MEMPOOL (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MUTEX
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MUTEX (1)
+#endif
+
+#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_SEM
+#define MYNEWT_VAL_OS_SYSVIEW_TRACE_SEM (1)
+#endif
+
+#ifndef MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME
+#define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_TIME_DEBUG
+#define MYNEWT_VAL_OS_TIME_DEBUG (0)
+#endif
+
+#ifndef MYNEWT_VAL_OS_WATCHDOG_MONITOR
+#define MYNEWT_VAL_OS_WATCHDOG_MONITOR (0)
+#endif
+
+#ifndef MYNEWT_VAL_SANITY_INTERVAL
+#define MYNEWT_VAL_SANITY_INTERVAL (15000)
+#endif
+
+#ifndef MYNEWT_VAL_WATCHDOG_INTERVAL
+#define MYNEWT_VAL_WATCHDOG_INTERVAL (30000)
+#endif
+
+/*** @apache-mynewt-core/sys/console/stub */
+#ifndef MYNEWT_VAL_CONSOLE_UART_BAUD
+#define MYNEWT_VAL_CONSOLE_UART_BAUD (115200)
+#endif
+
+#ifndef MYNEWT_VAL_CONSOLE_UART_DEV
+#define MYNEWT_VAL_CONSOLE_UART_DEV ("uart0")
+#endif
+
+#ifndef MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL
+#define MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL (UART_FLOW_CTL_NONE)
+#endif
+
+/*** @apache-mynewt-core/sys/flash_map */
+#ifndef MYNEWT_VAL_FLASH_MAP_MAX_AREAS
+#define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10)
+#endif
+
+#ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE
+#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2)
+#endif
+
+/*** @apache-mynewt-core/sys/log/common */
+#ifndef MYNEWT_VAL_DFLT_LOG_LVL
+#define MYNEWT_VAL_DFLT_LOG_LVL (1)
+#endif
+
+#ifndef MYNEWT_VAL_DFLT_LOG_MOD
+#define MYNEWT_VAL_DFLT_LOG_MOD (0)
+#endif
+
+#ifndef MYNEWT_VAL_LOG_GLOBAL_IDX
+#define MYNEWT_VAL_LOG_GLOBAL_IDX (1)
+#endif
+
+/*** @apache-mynewt-core/sys/log/modlog */
+#ifndef MYNEWT_VAL_MODLOG_CONSOLE_DFLT
+#define MYNEWT_VAL_MODLOG_CONSOLE_DFLT (1)
+#endif
+
+#ifndef MYNEWT_VAL_MODLOG_LOG_MACROS
+#define MYNEWT_VAL_MODLOG_LOG_MACROS (0)
+#endif
+
+#ifndef MYNEWT_VAL_MODLOG_MAX_MAPPINGS
+#define MYNEWT_VAL_MODLOG_MAX_MAPPINGS (16)
+#endif
+
+#ifndef MYNEWT_VAL_MODLOG_MAX_PRINTF_LEN
+#define MYNEWT_VAL_MODLOG_MAX_PRINTF_LEN (128)
+#endif
+
+#ifndef MYNEWT_VAL_MODLOG_SYSINIT_STAGE
+#define MYNEWT_VAL_MODLOG_SYSINIT_STAGE (100)
+#endif
+
+/*** @apache-mynewt-core/sys/log/stub */
+#ifndef MYNEWT_VAL_LOG_CONSOLE
+#define MYNEWT_VAL_LOG_CONSOLE (1)
+#endif
+
+#ifndef MYNEWT_VAL_LOG_FCB
+#define MYNEWT_VAL_LOG_FCB (0)
+#endif
+
+#ifndef MYNEWT_VAL_LOG_FCB_SLOT1
+#define MYNEWT_VAL_LOG_FCB_SLOT1 (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-core/sys/log/stub) */
+#ifndef MYNEWT_VAL_LOG_LEVEL
+#define MYNEWT_VAL_LOG_LEVEL (2)
+#endif
+
+/*** @apache-mynewt-core/sys/mfg */
+#ifndef MYNEWT_VAL_MFG_LOG_LVL
+#define MYNEWT_VAL_MFG_LOG_LVL (15)
+#endif
+
+#ifndef MYNEWT_VAL_MFG_LOG_MODULE
+#define MYNEWT_VAL_MFG_LOG_MODULE (128)
+#endif
+
+#ifndef MYNEWT_VAL_MFG_MAX_MMRS
+#define MYNEWT_VAL_MFG_MAX_MMRS (2)
+#endif
+
+#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE
+#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100)
+#endif
+
+/*** @apache-mynewt-core/sys/sys */
+#ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED
+#define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1)
+#endif
+
+/*** @apache-mynewt-core/sys/sysdown */
+#ifndef MYNEWT_VAL_SYSDOWN_CONSTRAIN_DOWN
+#define MYNEWT_VAL_SYSDOWN_CONSTRAIN_DOWN (1)
+#endif
+
+#ifndef MYNEWT_VAL_SYSDOWN_PANIC_FILE_LINE
+#define MYNEWT_VAL_SYSDOWN_PANIC_FILE_LINE (0)
+#endif
+
+#ifndef MYNEWT_VAL_SYSDOWN_PANIC_MESSAGE
+#define MYNEWT_VAL_SYSDOWN_PANIC_MESSAGE (0)
+#endif
+
+#ifndef MYNEWT_VAL_SYSDOWN_TIMEOUT_MS
+#define MYNEWT_VAL_SYSDOWN_TIMEOUT_MS (10000)
+#endif
+
+/*** @apache-mynewt-core/sys/sysinit */
+#ifndef MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT
+#define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1)
+#endif
+
+#ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE
+#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0)
+#endif
+
+#ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE
+#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0)
+#endif
+
+/*** @apache-mynewt-core/util/rwlock */
+#ifndef MYNEWT_VAL_RWLOCK_DEBUG
+#define MYNEWT_VAL_RWLOCK_DEBUG (0)
+#endif
+
+/*** @apache-mynewt-nimble/nimble */
+#ifndef MYNEWT_VAL_BLE_EXT_ADV
+#define MYNEWT_VAL_BLE_EXT_ADV (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE
+#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
+#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS
+#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
+#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV
+#define MYNEWT_VAL_BLE_PERIODIC_ADV (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER
+#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER
+#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL
+#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER
+#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL
+#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_VERSION
+#define MYNEWT_VAL_BLE_VERSION (50)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_WHITELIST
+#define MYNEWT_VAL_BLE_WHITELIST (1)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host */
+#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
+#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO
+#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE
+#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_INDICATE
+#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES
+#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY
+#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE
+#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO
+#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ
+#define MYNEWT_VAL_BLE_ATT_SVR_READ (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE
+#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE
+#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP
+#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE
+#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID
+#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID
+#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS
+#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_INDICATE
+#define MYNEWT_VAL_BLE_GATT_INDICATE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS
+#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY
+#define MYNEWT_VAL_BLE_GATT_NOTIFY (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_READ
+#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_READ_LONG
+#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS
+#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT
+#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
+#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_RESUME_RATE
+#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_SIGNED_WRITE
+#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_WRITE
+#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_WRITE_LONG
+#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS
+#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP
+#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE
+#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HOST
+#define MYNEWT_VAL_BLE_HOST (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_AUTO_START
+#define MYNEWT_VAL_BLE_HS_AUTO_START (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_DEBUG
+#define MYNEWT_VAL_BLE_HS_DEBUG (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_LOG_LVL
+#define MYNEWT_VAL_BLE_HS_LOG_LVL (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_LOG_MOD
+#define MYNEWT_VAL_BLE_HS_LOG_MOD (4)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
+#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_REQUIRE_OS
+#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN
+#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT
+#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT (2000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM
+#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MPS
+#define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC
+#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS
+#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS
+#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT
+#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS
+#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH
+#define MYNEWT_VAL_BLE_MESH (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE
+#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_RTT
+#define MYNEWT_VAL_BLE_MONITOR_RTT (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("btmonitor")
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_UART
+#define MYNEWT_VAL_BLE_MONITOR_UART (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE
+#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE
+#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV
+#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0")
+#endif
+
+#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT
+#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_BONDING
+#define MYNEWT_VAL_BLE_SM_BONDING (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_IO_CAP
+#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS
+#define MYNEWT_VAL_BLE_SM_KEYPRESS (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/host) */
+#ifndef MYNEWT_VAL_BLE_SM_LEGACY
+#define MYNEWT_VAL_BLE_SM_LEGACY (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS
+#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_MITM
+#define MYNEWT_VAL_BLE_SM_MITM (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG
+#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST
+#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/host) */
+#ifndef MYNEWT_VAL_BLE_SM_SC
+#define MYNEWT_VAL_BLE_SM_SC (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS
+#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST
+#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
+#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS
+#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/ans */
+#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
+#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_ANS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_ANS_SYSINIT_STAGE (303)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT
+#define MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT (0)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/bas */
+#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE
+#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_BAS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_BAS_SYSINIT_STAGE (303)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/dis */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_DEFAULT_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_DEFAULT_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT ("Apache Mynewt NimBLE")
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_READ_PERM (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_DIS_SYSINIT_STAGE (303)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT
+#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT (NULL)
+#endif
+
+/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */
+#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM
+#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (-1)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/gap */
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE
+#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM
+#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION
+#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("nimble")
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SVC_GAP_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_GAP_SYSINIT_STAGE (301)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/gatt */
+#ifndef MYNEWT_VAL_BLE_SVC_GATT_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_GATT_SYSINIT_STAGE (302)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/ias */
+#ifndef MYNEWT_VAL_BLE_SVC_IAS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_IAS_SYSINIT_STAGE (303)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/ipss */
+#ifndef MYNEWT_VAL_BLE_SVC_IPSS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_IPSS_SYSINIT_STAGE (303)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/lls */
+#ifndef MYNEWT_VAL_BLE_SVC_LLS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_LLS_SYSINIT_STAGE (303)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/host/services/tps */
+#ifndef MYNEWT_VAL_BLE_SVC_TPS_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SVC_TPS_SYSINIT_STAGE (303)
+#endif
+
+/*** @apache-mynewt-nimble/nimble/transport/socket */
+#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
+#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (24)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
+#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT
+#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE
+#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
+#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
+#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SOCK_CLI_SYSINIT_STAGE
+#define MYNEWT_VAL_BLE_SOCK_CLI_SYSINIT_STAGE (500)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SOCK_LINUX_DEV
+#define MYNEWT_VAL_BLE_SOCK_LINUX_DEV (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+#ifndef MYNEWT_VAL_BLE_SOCK_STACK_SIZE
+#define MYNEWT_VAL_BLE_SOCK_STACK_SIZE (1028)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+#ifndef MYNEWT_VAL_BLE_SOCK_TASK_PRIO
+#define MYNEWT_VAL_BLE_SOCK_TASK_PRIO (3)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_SOCK_TCP_PORT
+#define MYNEWT_VAL_BLE_SOCK_TCP_PORT (14433)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+#ifndef MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE
+#define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+#ifndef MYNEWT_VAL_BLE_SOCK_USE_NUTTX
+#define MYNEWT_VAL_BLE_SOCK_USE_NUTTX (1)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */
+#ifndef MYNEWT_VAL_BLE_SOCK_USE_TCP
+#define MYNEWT_VAL_BLE_SOCK_USE_TCP (0)
+#endif
+
+/*** newt */
+#ifndef MYNEWT_VAL_APP_NAME
+#define MYNEWT_VAL_APP_NAME ("dummy_app")
+#endif
+
+#ifndef MYNEWT_VAL_APP_dummy_app
+#define MYNEWT_VAL_APP_dummy_app (1)
+#endif
+
+#ifndef MYNEWT_VAL_ARCH_NAME
+#define MYNEWT_VAL_ARCH_NAME ("dummy")
+#endif
+
+#ifndef MYNEWT_VAL_ARCH_dummy
+#define MYNEWT_VAL_ARCH_dummy (1)
+#endif
+
+#ifndef MYNEWT_VAL_BSP_NAME
+#define MYNEWT_VAL_BSP_NAME ("dummy_bsp")
+#endif
+
+#ifndef MYNEWT_VAL_BSP_dummy_bsp
+#define MYNEWT_VAL_BSP_dummy_bsp (1)
+#endif
+
+#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
+#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
+#endif
+
+#ifndef MYNEWT_VAL_NEWT_FEATURE_SYSDOWN
+#define MYNEWT_VAL_NEWT_FEATURE_SYSDOWN (1)
+#endif
+
+#ifndef MYNEWT_VAL_TARGET_NAME
+#define MYNEWT_VAL_TARGET_NAME ("nuttx")
+#endif
+
+#ifndef MYNEWT_VAL_TARGET_nuttx
+#define MYNEWT_VAL_TARGET_nuttx (1)
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/include/sysflash/sysflash.h b/src/libs/mynewt-nimble/porting/examples/nuttx/include/sysflash/sysflash.h
new file mode 100644
index 00000000..ab1341b2
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/include/sysflash/sysflash.h
@@ -0,0 +1,24 @@
+/**
+ * This file was generated by Apache newt version: 1.9.0-dev
+ */
+
+#ifndef H_MYNEWT_SYSFLASH_
+#define H_MYNEWT_SYSFLASH_
+
+#include "flash_map/flash_map.h"
+
+/**
+ * This flash map definition is used for two purposes:
+ * 1. To locate the meta area, which contains the true flash map definition.
+ * 2. As a fallback in case the meta area cannot be read from flash.
+ */
+extern const struct flash_area sysflash_map_dflt[6];
+
+#define FLASH_AREA_BOOTLOADER                    0
+#define FLASH_AREA_IMAGE_0                       1
+#define FLASH_AREA_IMAGE_1                       2
+#define FLASH_AREA_IMAGE_SCRATCH                 3
+#define FLASH_AREA_REBOOT_LOG                    16
+#define FLASH_AREA_NFFS                          17
+
+#endif
diff --git a/src/libs/mynewt-nimble/porting/examples/nuttx/main.c b/src/libs/mynewt-nimble/porting/examples/nuttx/main.c
new file mode 100644
index 00000000..acfc9fcd
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/examples/nuttx/main.c
@@ -0,0 +1,124 @@
+/*
+ * 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 <nuttx/config.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#include <pthread.h>
+#include "nimble/nimble_npl.h"
+#include "nimble/nimble_port.h"
+
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+#include "services/ans/ble_svc_ans.h"
+#include "services/ias/ble_svc_ias.h"
+#include "services/lls/ble_svc_lls.h"
+#include "services/tps/ble_svc_tps.h"
+
+static struct ble_npl_task s_task_host;
+static struct ble_npl_task s_task_hci;
+
+void nimble_host_task(void *param);
+void ble_hci_sock_ack_handler(void *param);
+void ble_hci_sock_init(void);
+void ble_hci_sock_set_device(int dev);
+void ble_store_ram_init(void);
+
+#define TASK_DEFAULT_PRIORITY       1
+#define TASK_DEFAULT_STACK          NULL
+#define TASK_DEFAULT_STACK_SIZE     400
+
+void *ble_hci_sock_task(void *param)
+{
+    printf("hci sock task\n");
+    ble_hci_sock_ack_handler(param);
+    return NULL;
+}
+
+void *ble_host_task(void *param)
+{
+    printf("host task\n");
+    nimble_host_task(param);
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    int ret = 0;
+
+    /* allow to specify custom hci */
+    if (argc > 1) {
+        ble_hci_sock_set_device(atoi(argv[1]));
+    }
+
+    printf("hci init\n");
+    ble_hci_sock_init();
+    printf("port init\n");
+    nimble_port_init();
+
+    /* This example provides GATT Alert service */
+    printf("gap init\n");
+    ble_svc_gap_init();
+    printf("gatt init\n");
+    ble_svc_gatt_init();
+    printf("ans init\n");
+    ble_svc_ans_init();
+    printf("ias init\n");
+    ble_svc_ias_init();
+    printf("lls init\n");
+    ble_svc_lls_init();
+    printf("tps init\n");
+    ble_svc_tps_init();
+
+    /* XXX Need to have template for store */
+    ble_store_ram_init();
+
+    printf("hci_sock task init\n");
+    ret = ble_npl_task_init(&s_task_hci, "hci_sock", ble_hci_sock_task,
+                      NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_TIME_FOREVER,
+                      TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE);
+
+    if (ret != 0)
+      {
+        fprintf(stderr, "error starting hci task: %i\n", ret);
+      }
+
+    /* Create task which handles default event queue for host stack. */
+    printf("ble_host task init\n");
+    ret = ble_npl_task_init(&s_task_host, "ble_host", ble_host_task,
+                      NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_TIME_FOREVER,
+                      TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE);
+
+
+    if (ret != 0)
+      {
+        fprintf(stderr, "error starting ble task: %i\n", ret);
+      }
+
+    while (true)
+      {
+        usleep(100);
+        //pause();
+      }
+    return 0;
+}
diff --git a/src/libs/mynewt-nimble/porting/nimble/Makefile.defs b/src/libs/mynewt-nimble/porting/nimble/Makefile.defs
index ffb531fb..5bab893f 100644
--- a/src/libs/mynewt-nimble/porting/nimble/Makefile.defs
+++ b/src/libs/mynewt-nimble/porting/nimble/Makefile.defs
@@ -30,6 +30,7 @@ NIMBLE_INCLUDE := \
 	$(NIMBLE_ROOT)/nimble/host/services/gap/include \
 	$(NIMBLE_ROOT)/nimble/host/services/gatt/include \
 	$(NIMBLE_ROOT)/nimble/host/services/ias/include \
+	$(NIMBLE_ROOT)/nimble/host/services/dis/include \
 	$(NIMBLE_ROOT)/nimble/host/services/lls/include \
 	$(NIMBLE_ROOT)/nimble/host/services/tps/include \
 	$(NIMBLE_ROOT)/nimble/host/store/ram/include \
@@ -46,6 +47,7 @@ NIMBLE_SRC := \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/bas/src/*.c)) \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/gap/src/*.c)) \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/gatt/src/*.c)) \
+	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/dis/src/*.c)) \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/ias/src/*.c)) \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/lls/src/*.c)) \
 	$(filter-out $(NIMBLE_IGNORE), $(wildcard $(NIMBLE_ROOT)/nimble/host/services/tps/src/*.c)) \
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/log/log.h b/src/libs/mynewt-nimble/porting/nimble/include/log/log.h
index 004667cc..b50c5b17 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/log/log.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/log/log.h
@@ -30,11 +30,13 @@ log_dummy(void *log, ...)
     (void)log;
 }
 
-#define LOG_DEBUG(_log, _mod, ...)      NRF_LOG_DEBUG(## __VA_ARGS__)
+#if MYNEWT
+#define LOG_DEBUG(_log, _mod, ...)      log_dummy(_log, ## __VA_ARGS__)
 #define LOG_INFO(_log, _mod, ...)       log_dummy(_log, ## __VA_ARGS__)
 #define LOG_WARN(_log, _mod, ...)       log_dummy(_log, ## __VA_ARGS__)
 #define LOG_ERROR(_log, _mod, ...)      log_dummy(_log, ## __VA_ARGS__)
 #define LOG_CRITICAL(_log, _mod, ...)   log_dummy(_log, ## __VA_ARGS__)
+#endif
 
 struct log {
 };
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/log_common/log_common.h b/src/libs/mynewt-nimble/porting/nimble/include/log_common/log_common.h
index 106d02d7..ed590b6b 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/log_common/log_common.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/log_common/log_common.h
@@ -20,20 +20,123 @@
 #ifndef H_LOG_COMMON_
 #define H_LOG_COMMON_
 
+#include <stdint.h>
 #include "log_common/ignore.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct log;
+
+#define LOG_VERSION_V3  3
+
+#define LOG_TYPE_STREAM  (0)
+#define LOG_TYPE_MEMORY  (1)
+#define LOG_TYPE_STORAGE (2)
+
 #define LOG_LEVEL_DEBUG    (0)
 #define LOG_LEVEL_INFO     (1)
 #define LOG_LEVEL_WARN     (2)
 #define LOG_LEVEL_ERROR    (3)
 #define LOG_LEVEL_CRITICAL (4)
-/* Up to 7 custom log levels. */
+/* Up to 10 custom log levels. */
 #define LOG_LEVEL_MAX      (15)
 
+#define LOG_LEVEL_STR(level) \
+    (LOG_LEVEL_DEBUG    == level ? "DEBUG"    :\
+    (LOG_LEVEL_INFO     == level ? "INFO"     :\
+    (LOG_LEVEL_WARN     == level ? "WARN"     :\
+    (LOG_LEVEL_ERROR    == level ? "ERROR"    :\
+    (LOG_LEVEL_CRITICAL == level ? "CRITICAL" :\
+     "UNKNOWN")))))
+
+/* XXX: These module IDs are defined for backwards compatibility.  Application
+ * code should use the syscfg settings directly.  These defines will be removed
+ * in a future release.
+ */
+#define LOG_MODULE_DEFAULT          0
+#define LOG_MODULE_OS               1
+#define LOG_MODULE_NEWTMGR          2
+#define LOG_MODULE_NIMBLE_CTLR      3
+#define LOG_MODULE_NIMBLE_HOST      4
+#define LOG_MODULE_NFFS             5
+#define LOG_MODULE_REBOOT           6
+#define LOG_MODULE_IOTIVITY         7
+#define LOG_MODULE_TEST             8
+
+#define LOG_MODULE_PERUSER          64
+#define LOG_MODULE_MAX              (255)
+
+#define LOG_ETYPE_STRING         (0)
+#define LOG_ETYPE_CBOR           (1)
+#define LOG_ETYPE_BINARY         (2)
+
+/* UTC Timestamp for Jan 2016 00:00:00 */
+#define UTC01_01_2016    1451606400
+
+#define LOG_NAME_MAX_LEN    (64)
+
+#ifndef MYNEWT_VAL_LOG_LEVEL
+#define LOG_SYSLEVEL    ((uint8_t)LOG_LEVEL_MAX)
+#else
+#define LOG_SYSLEVEL    ((uint8_t)MYNEWT_VAL_LOG_LEVEL)
+#endif
+
+/**
+ * @brief Determines if a log module will accept an entry with a given level.
+ *
+ * A log entry is only accepted if its level is less than or equal to both:
+ *    o Global log level setting (LOG_LEVEL), and
+ *    o The specified module log level
+ *
+ * @param mod_level             The module's minimum log level.
+ * @param entry_level           The level of the entry to be logged.
+ *
+ * @return                      true if the entry would be logged;
+ *                              false otherwise.
+ */
+#define LOG_MOD_LEVEL_IS_ACTIVE(mod_level, entry_level) \
+    (LOG_LEVEL <= (entry_level) && (mod_level) <= (entry_level))
+
+/* Newtmgr Log opcodes */
+#define LOGS_NMGR_OP_READ               (0)
+#define LOGS_NMGR_OP_CLEAR              (1)
+#define LOGS_NMGR_OP_APPEND             (2)
+#define LOGS_NMGR_OP_MODULE_LIST        (3)
+#define LOGS_NMGR_OP_LEVEL_LIST         (4)
+#define LOGS_NMGR_OP_LOGS_LIST          (5)
+#define LOGS_NMGR_OP_SET_WATERMARK      (6)
+#define LOGS_NMGR_OP_MODLEVEL           (8)
+
+#define LOG_PRINTF_MAX_ENTRY_LEN (128)
+
+/* Global log info */
+struct log_info {
+#if MYNEWT_VAL(LOG_GLOBAL_IDX)
+    uint32_t li_next_index;
+#endif
+    uint8_t li_version;
+};
+
+extern struct log_info g_log_info;
+
+/** @typedef log_append_cb
+ * @brief Callback that is executed each time the corresponding log is appended
+ * to.
+ *
+ * @param log                   The log that was just appended to.
+ * @param idx                   The index of newly appended log entry.
+ */
+typedef void log_append_cb(struct log *log, uint32_t idx);
+
+/** @typdef log_notify_rotate_cb
+ * @brief Callback that is executed each time we are about to rotate a log.
+ *
+ * @param log                   The log that is about to rotate
+ */
+typedef void log_notify_rotate_cb(const struct log *log);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/logcfg/logcfg.h b/src/libs/mynewt-nimble/porting/nimble/include/logcfg/logcfg.h
index 983f419f..837cdeac 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/logcfg/logcfg.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/logcfg/logcfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_LOGCFG_
@@ -7,24 +7,14 @@
 
 #include "modlog/modlog.h"
 #include "log_common/log_common.h"
-#include <libraries/log/nrf_log.h>
 
-#if 1
-#define BLE_HS_LOG_DEBUG(...) NRF_LOG_DEBUG(__VA_ARGS__)
-#define BLE_HS_LOG_INFO(...) NRF_LOG_INFO(__VA_ARGS__)
-#define BLE_HS_LOG_WARN(...) NRF_LOG_WARNING( __VA_ARGS__)
-#define BLE_HS_LOG_ERROR(...) NRF_LOG_ERROR(__VA_ARGS__)
-#define BLE_HS_LOG_CRITICAL(...) NRF_LOG_ERROR(__VA_ARGS__)
-#define BLE_HS_LOG_DISABLED(...) MODLOG_DISABLED(4, __VA_ARGS__)
-#endif
-#if 0
 #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
 #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__)
 #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__)
 #define BLE_HS_LOG_ERROR(...) MODLOG_ERROR(4, __VA_ARGS__)
 #define BLE_HS_LOG_CRITICAL(...) MODLOG_CRITICAL(4, __VA_ARGS__)
 #define BLE_HS_LOG_DISABLED(...) MODLOG_DISABLED(4, __VA_ARGS__)
-#endif
+
 #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
 #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__)
 #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__)
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/modlog/modlog.h b/src/libs/mynewt-nimble/porting/nimble/include/modlog/modlog.h
index 29b1e8f0..03904610 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/modlog/modlog.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/modlog/modlog.h
@@ -22,6 +22,7 @@
 
 #include <stdio.h>
 
+#include "log_common/log_common.h"
 #include "log/log.h"
 
 #define MODLOG_MODULE_DFLT 255
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h
index 6efa3f28..94b72cb6 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSCFG_
@@ -15,10 +15,6 @@
 #define MYNEWT_VAL(_name)                       MYNEWT_VAL_ ## _name
 #define MYNEWT_VAL_CHOICE(_name, _val)          MYNEWT_VAL_ ## _name ## __ ## _val
 
-#ifndef OS_TICKS_PER_SEC
-#define OS_TICKS_PER_SEC 1024
-#endif
-
 /*** @apache-mynewt-core/crypto/tinycrypt */
 #ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE
 #define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200)
@@ -369,6 +365,14 @@
 #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
 #define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
 #endif
@@ -1264,4 +1268,10 @@
 #define MYNEWT_VAL_TIMER_5 (1)
 #endif
 
+/* Value copied from BLE_LL_OUR_SCA */
+#ifndef MYNEWT_VAL_BLE_LL_SCA
+#define MYNEWT_VAL_BLE_LL_SCA (60)
+#endif
+
+
 #endif
diff --git a/src/libs/mynewt-nimble/porting/nimble/include/sysflash/sysflash.h b/src/libs/mynewt-nimble/porting/nimble/include/sysflash/sysflash.h
index 413cb267..ab1341b2 100644
--- a/src/libs/mynewt-nimble/porting/nimble/include/sysflash/sysflash.h
+++ b/src/libs/mynewt-nimble/porting/nimble/include/sysflash/sysflash.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSFLASH_
diff --git a/src/libs/mynewt-nimble/porting/nimble/src/nimble_port.c b/src/libs/mynewt-nimble/porting/nimble/src/nimble_port.c
index ff350a89..06b5f6df 100644
--- a/src/libs/mynewt-nimble/porting/nimble/src/nimble_port.c
+++ b/src/libs/mynewt-nimble/porting/nimble/src/nimble_port.c
@@ -24,34 +24,28 @@
 #include "nimble/nimble_port.h"
 #if NIMBLE_CFG_CONTROLLER
 #include "controller/ble_ll.h"
+#include "transport/ram/ble_hci_ram.h"
 #endif
 
 static struct ble_npl_eventq g_eventq_dflt;
 
+extern void os_msys_init(void);
+
 void
 nimble_port_init(void)
 {
-    void os_msys_init(void);
-    void ble_store_ram_init(void);
-#if NIMBLE_CFG_CONTROLLER
-    void ble_hci_ram_init(void);
-#endif
-
     /* Initialize default event queue */
     ble_npl_eventq_init(&g_eventq_dflt);
-
+    /* Initialize the global memory pool */
     os_msys_init();
-
+    /* Initialize the host */
     ble_hs_init();
 
-    /* XXX Need to have template for store */
-    ble_store_ram_init();
-
 #if NIMBLE_CFG_CONTROLLER
+    ble_hci_ram_init();
     hal_timer_init(5, NULL);
     os_cputime_init(32768);
     ble_ll_init();
-    ble_hci_ram_init();
 #endif
 }
 
diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h b/src/libs/mynewt-nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
index d8810f35..545be0f4 100644
--- a/src/libs/mynewt-nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
+++ b/src/libs/mynewt-nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
@@ -282,14 +282,12 @@ static inline uint32_t
 ble_npl_hw_enter_critical(void)
 {
     //vPortEnterCritical();
-
   return npl_freertos_hw_enter_critical();
 }
 
 static inline void
 ble_npl_hw_exit_critical(uint32_t ctx)
 {
-  //  vPortExitCritical();
   npl_freertos_hw_exit_critical(ctx);
 
 }
diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c
index 64196b36..8ee3475a 100644
--- a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c
+++ b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c
@@ -37,7 +37,7 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn)
      * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped
      * since it has compatible prototype.
      */
-    xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 100,
+    xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400,
                 NULL, configMAX_PRIORITIES - 1, &ll_task_h);
 #endif
 
@@ -46,6 +46,6 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn)
      * have separate task for NimBLE host, but since something needs to handle
      * default queue it is just easier to make separate task which does this.
      */
-    xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 200,
+    xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 400,
                 NULL, tskIDLE_PRIORITY + 1, &host_task_h);
 }
diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/src/npl_os_freertos.c b/src/libs/mynewt-nimble/porting/npl/freertos/src/npl_os_freertos.c
index eb3b4c99..87936bd8 100644
--- a/src/libs/mynewt-nimble/porting/npl/freertos/src/npl_os_freertos.c
+++ b/src/libs/mynewt-nimble/porting/npl/freertos/src/npl_os_freertos.c
@@ -268,16 +268,10 @@ void
 npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
                      ble_npl_event_fn *ev_cb, void *ev_arg)
 {
-  // I added this 'if' because nimble seems to never delete the timers. I assume it wants to recycle them.
-  // This condition ensure that a new timer is created only if 'co' points to an uninitialized structure.
-  // If the struct contains an existing timer, no new timer is created, which prevent a significant memory leak.
-  // TODO Ensure that this workaround is valid and does not generate bad side-effect.
-  if(co->handle == NULL) {
     memset(co, 0, sizeof(*co));
     co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb);
     co->evq = evq;
     ble_npl_event_init(&co->ev, ev_cb, ev_arg);
-  }
 }
 
 ble_npl_error_t
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/include/console/console.h b/src/libs/mynewt-nimble/porting/npl/nuttx/include/console/console.h
new file mode 100644
index 00000000..0f65d475
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/include/console/console.h
@@ -0,0 +1,36 @@
+/*
+ * 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 __CONSOLE_H__
+#define __CONSOLE_H__
+
+#include <nuttx/config.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define console_printf(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONSOLE_H__ */
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/include/modlog/modlog.h b/src/libs/mynewt-nimble/porting/npl/nuttx/include/modlog/modlog.h
new file mode 100644
index 00000000..5e51b501
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/include/modlog/modlog.h
@@ -0,0 +1,68 @@
+/*
+ * 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_MODLOG_
+#define H_MODLOG_
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "log_common/log_common.h"
+
+#define MODLOG_MODULE_DFLT 255
+
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG || defined __DOXYGEN__
+#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
+    printf((ml_msg_), ##__VA_ARGS__)
+#else
+#define MODLOG_DEBUG(ml_mod_, ...) IGNORE(__VA_ARGS__)
+#endif
+
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_INFO || defined __DOXYGEN__
+#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
+    printf((ml_msg_), ##__VA_ARGS__)
+#else
+#define MODLOG_INFO(ml_mod_, ...) IGNORE(__VA_ARGS__)
+#endif
+
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_WARN || defined __DOXYGEN__
+#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
+    printf((ml_msg_), ##__VA_ARGS__)
+#else
+#define MODLOG_WARN(ml_mod_, ...) IGNORE(__VA_ARGS__)
+#endif
+
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_ERROR || defined __DOXYGEN__
+#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
+    printf((ml_msg_), ##__VA_ARGS__)
+#else
+#define MODLOG_ERROR(ml_mod_, ...) IGNORE(__VA_ARGS__)
+#endif
+
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_CRITICAL || defined __DOXYGEN__
+#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
+    printf((ml_msg_), ##__VA_ARGS__)
+#else
+#define MODLOG_CRITICAL(ml_mod_, ...) IGNORE(__VA_ARGS__)
+#endif
+
+#define MODLOG(ml_lvl_, ml_mod_, ...) \
+    MODLOG_ ## ml_lvl_((ml_mod_), __VA_ARGS__)
+
+#endif
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/nimble_npl_os.h b/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/nimble_npl_os.h
new file mode 100644
index 00000000..0f765f5a
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/nimble_npl_os.h
@@ -0,0 +1,71 @@
+/*
+ * 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 _NIMBLE_NPL_OS_H_
+#define _NIMBLE_NPL_OS_H_
+
+#include <nuttx/config.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "os_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLE_NPL_OS_ALIGNMENT    4
+
+#define BLE_NPL_TIME_FOREVER    INT32_MAX
+
+#define SYSINIT_PANIC_MSG(msg) { fprintf(stderr, "%s\n", msg); abort(); }
+
+#define SYSINIT_PANIC_ASSERT_MSG(rc, msg) do \
+{                                            \
+    if (!(rc)) {                             \
+        SYSINIT_PANIC_MSG(msg);              \
+    }                                        \
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Define some variables since nimBLE is designed to be built ignoring
+ * undefined macros and we do not ignore warnings on NuttX.
+ *
+ * Note: MYNEWT will give undefined warning, but some parts of the code
+ * interpret !defined(MYNEWT) as MYNEWT=0, so we shouldn't define it to zero
+ * either.
+ *
+ * Note 2: default_RNG_defined could probably set to 1 but this requires
+ * testing
+ */
+
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY 0
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV 0
+#define MYNEWT_VAL_BLE_LL_DTM_EXTENSIONS 0
+#define MYNEWT_VAL_BLE_CONTROLLER 0
+#define default_RNG_defined 0
+#define BLETEST_THROUGHPUT_TEST 0
+#define MYNEWT_VAL_TRNG 0
+#define MYNEWT_VAL_SELFTEST 0
+
+#endif  /* _NPL_H_ */
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/os_types.h b/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/os_types.h
new file mode 100644
index 00000000..93d52891
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/include/nimble/os_types.h
@@ -0,0 +1,90 @@
+/*
+ * 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 _NPL_OS_TYPES_H
+#define _NPL_OS_TYPES_H
+
+#include <nuttx/config.h>
+#include <time.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <sched.h>
+#include <mqueue.h>
+
+/* The highest and lowest task priorities */
+#define OS_TASK_PRI_HIGHEST (sched_get_priority_max(SCHED_RR))
+#define OS_TASK_PRI_LOWEST  (sched_get_priority_min(SCHED_RR))
+
+typedef uint32_t ble_npl_time_t;
+typedef int32_t ble_npl_stime_t;
+
+//typedef int os_sr_t;
+typedef int ble_npl_stack_t;
+
+
+struct ble_npl_event {
+    uint8_t                 ev_queued;
+    ble_npl_event_fn       *ev_cb;
+    void                   *ev_arg;
+};
+
+struct ble_npl_eventq {
+    mqd_t                  mq;
+};
+
+struct ble_npl_callout {
+    struct ble_npl_event    c_ev;
+    struct ble_npl_eventq  *c_evq;
+    uint32_t                c_ticks;
+    timer_t                 c_timer;
+    bool                    c_active;
+};
+
+struct ble_npl_mutex {
+    pthread_mutex_t         lock;
+    pthread_mutexattr_t     attr;
+    struct timespec         wait;
+};
+
+struct ble_npl_sem {
+    sem_t                   lock;
+};
+
+struct ble_npl_task {
+    pthread_t               handle;
+    pthread_attr_t          attr;
+    struct sched_param      param;
+    const char*             name;
+};
+
+typedef void *(*ble_npl_task_func_t)(void *);
+
+int ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
+		 void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
+		 ble_npl_stack_t *stack_bottom, uint16_t stack_size);
+
+int ble_npl_task_remove(struct ble_npl_task *t);
+
+uint8_t ble_npl_task_count(void);
+
+void ble_npl_task_yield(void);
+
+#endif // _NPL_OS_TYPES_H
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_atomic.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_atomic.c
new file mode 100644
index 00000000..ceededb2
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_atomic.c
@@ -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.
+ */
+
+#include <nuttx/config.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include "nimble/nimble_npl.h"
+
+static pthread_mutex_t s_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+uint32_t
+ble_npl_hw_enter_critical(void)
+{
+    pthread_mutex_lock(&s_mutex);
+    return 0;
+}
+
+void
+ble_npl_hw_exit_critical(uint32_t ctx)
+{
+    pthread_mutex_unlock(&s_mutex);
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_callout.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_callout.c
new file mode 100644
index 00000000..affa1c2d
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_callout.c
@@ -0,0 +1,166 @@
+/*
+ * 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 <nuttx/config.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <time.h>
+#include <signal.h>
+
+#include "nimble/nimble_npl.h"
+
+static void
+ble_npl_callout_timer_cb(union sigval sv)
+{
+    struct ble_npl_callout *c = (struct ble_npl_callout *)sv.sival_ptr;
+    assert(c);
+
+    if (c->c_evq) {
+        ble_npl_eventq_put(c->c_evq, &c->c_ev);
+    } else {
+        c->c_ev.ev_cb(&c->c_ev);
+    }
+}
+
+void
+ble_npl_callout_init(struct ble_npl_callout *c,
+                     struct ble_npl_eventq *evq,
+                     ble_npl_event_fn *ev_cb,
+                     void *ev_arg)
+{
+    struct sigevent         event;
+
+    /* Initialize the callout. */
+    memset(c, 0, sizeof(*c));
+    c->c_ev.ev_cb = ev_cb;
+    c->c_ev.ev_arg = ev_arg;
+    c->c_evq = evq;
+    c->c_active = false;
+
+    event.sigev_notify = SIGEV_THREAD;
+    event.sigev_value.sival_ptr = c;     // put callout obj in signal args
+    event.sigev_notify_function = ble_npl_callout_timer_cb;
+    event.sigev_notify_attributes = NULL;
+
+    timer_create(CLOCK_REALTIME, &event, &c->c_timer);
+}
+
+bool
+ble_npl_callout_is_active(struct ble_npl_callout *c)
+{
+    /* TODO: seek native posix method to determine whether timer_t is active.
+       TODO: fix bug where one-shot timer is still active after fired. */
+
+    return c->c_active;
+}
+
+int
+ble_npl_callout_inited(struct ble_npl_callout *c)
+{
+    return (c->c_timer != NULL);
+}
+
+ble_npl_error_t
+ble_npl_callout_reset(struct ble_npl_callout *c,
+                      ble_npl_time_t ticks)
+{
+    struct itimerspec       its;
+
+    if (ticks < 0) {
+        return BLE_NPL_EINVAL;
+    }
+
+    if (ticks == 0) {
+        ticks = 1;
+    }
+
+    c->c_ticks = ble_npl_time_get() + ticks;
+
+    its.it_interval.tv_sec = 0;
+    its.it_interval.tv_nsec = 0;                     /* one shot */
+    its.it_value.tv_sec = (ticks / 1000);
+    its.it_value.tv_nsec = (ticks % 1000) * 1000000; /* expiration */
+    its.it_value.tv_nsec %= 1000000000;
+    c->c_active = true;
+    timer_settime(c->c_timer, 0, &its, NULL);
+
+    return BLE_NPL_OK;
+}
+
+int
+ble_npl_callout_queued(struct ble_npl_callout *c)
+{
+    struct itimerspec its;
+    timer_gettime(c->c_timer, &its);
+
+    return ((its.it_value.tv_sec > 0) ||
+            (its.it_value.tv_nsec > 0));
+}
+
+void
+ble_npl_callout_stop(struct ble_npl_callout *c)
+{
+    if (!ble_npl_callout_inited(c)) {
+        return;
+    }
+
+    struct itimerspec its;
+    its.it_interval.tv_sec = 0;
+    its.it_interval.tv_nsec = 0;
+    its.it_value.tv_sec = 0;
+    its.it_value.tv_nsec = 0;
+    timer_settime(c->c_timer, 0, &its, NULL);
+    c->c_active = false;
+}
+
+ble_npl_time_t
+ble_npl_callout_get_ticks(struct ble_npl_callout *co)
+{
+    return co->c_ticks;
+}
+
+void
+ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg)
+{
+    co->c_ev.ev_arg = arg;
+}
+
+uint32_t
+ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
+                                ble_npl_time_t now)
+{
+    ble_npl_time_t rt;
+    uint32_t exp;
+
+    struct itimerspec its;
+    timer_gettime(co->c_timer, &its);
+
+    exp = its.it_value.tv_sec * 1000;
+
+    if (exp > now) {
+        rt = exp - now;
+    } else {
+        rt = 0;
+    }
+
+    return rt;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_eventq.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_eventq.c
new file mode 100644
index 00000000..815b0969
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_eventq.c
@@ -0,0 +1,177 @@
+/*
+ * 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 <nuttx/config.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "nimble/nimble_npl.h"
+
+static struct ble_npl_eventq dflt_evq =
+{
+  .mq = (mqd_t)-1
+};
+
+int qnum = 0;
+
+struct ble_npl_eventq *
+ble_npl_eventq_dflt_get(void)
+{
+    return &dflt_evq;
+}
+
+void
+ble_npl_eventq_init(struct ble_npl_eventq *evq)
+{
+    char path[PATH_MAX];
+    struct mq_attr attr;
+    attr.mq_maxmsg = 16;
+    attr.mq_msgsize = sizeof(struct ble_npl_event*);
+    attr.mq_flags = 0;
+
+    qnum++;
+    sprintf(path, "/nimbleq%i", qnum);
+    evq->mq = mq_open(path, O_CREAT | O_RDWR, 0, &attr);
+    DEBUGASSERT((intptr_t)evq->mq >= 0);
+}
+
+bool
+ble_npl_eventq_is_empty(struct ble_npl_eventq *evq)
+{
+    struct mq_attr attr;
+    mq_getattr(evq->mq, &attr);
+
+    return (attr.mq_curmsgs == 0);
+}
+
+int
+ble_npl_eventq_inited(const struct ble_npl_eventq *evq)
+{
+    return (evq->mq != ((mqd_t)-1));
+}
+
+void
+ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+    if (ev->ev_queued)
+      {
+        return;
+      }
+
+    ev->ev_queued = 1;
+    mq_send(evq->mq, (const char*)&ev, sizeof(ev), 0);
+}
+
+struct ble_npl_event *
+ble_npl_eventq_get(struct ble_npl_eventq *evq,
+                   ble_npl_time_t tmo)
+{
+    struct ble_npl_event *ev = NULL;
+
+    if (tmo == BLE_NPL_TIME_FOREVER)
+      {
+        do
+          {
+            mq_receive(evq->mq, (char*)&ev, sizeof(ev), NULL);
+          } while (ev && ev->ev_queued == 0);
+      }
+    else
+      {
+        struct timespec now, t;
+
+        clock_gettime(CLOCK_REALTIME, &now);
+
+        t.tv_sec += tmo / USEC_PER_SEC;
+        t.tv_nsec = (tmo - t.tv_sec) * NSEC_PER_MSEC;
+        clock_timespec_add(&now, &t, &t);
+
+        do
+          {
+            mq_timedreceive(evq->mq, (char*)&ev, sizeof(ev), NULL, &t);
+          } while (ev && ev->ev_queued == 0);
+      }
+
+    if (ev) {
+        ev->ev_queued = 0;
+    }
+
+    return ev;
+}
+
+void
+ble_npl_eventq_run(struct ble_npl_eventq *evq)
+{
+    struct ble_npl_event *ev;
+
+    ev = ble_npl_eventq_get(evq, BLE_NPL_TIME_FOREVER);
+    ble_npl_event_run(ev);
+}
+
+
+// ========================================================================
+//                         Event Implementation
+// ========================================================================
+
+void
+ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+                   void *arg)
+{
+    memset(ev, 0, sizeof(*ev));
+    ev->ev_cb = fn;
+    ev->ev_arg = arg;
+}
+
+bool
+ble_npl_event_is_queued(struct ble_npl_event *ev)
+{
+    return ev->ev_queued;
+}
+
+void *
+ble_npl_event_get_arg(struct ble_npl_event *ev)
+{
+    return ev->ev_arg;
+}
+
+void
+ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
+{
+    ev->ev_arg = arg;
+}
+
+void
+ble_npl_event_run(struct ble_npl_event *ev)
+{
+    assert(ev->ev_cb != NULL);
+
+    ev->ev_cb(ev);
+}
+
+void
+ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+    /* we simply mark the event as unqueued. we will ignore these elements
+     * when receiving from the queue */
+
+    ev->ev_queued = 0;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_mutex.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_mutex.c
new file mode 100644
index 00000000..0c43f369
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_mutex.c
@@ -0,0 +1,82 @@
+/*
+ * 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 <nuttx/config.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "os/os.h"
+#include "nimble/nimble_npl.h"
+
+ble_npl_error_t
+ble_npl_mutex_init(struct ble_npl_mutex *mu)
+{
+    if (!mu) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    pthread_mutexattr_init(&mu->attr);
+    pthread_mutexattr_settype(&mu->attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&mu->lock, &mu->attr);
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+ble_npl_mutex_release(struct ble_npl_mutex *mu)
+{
+    if (!mu) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    if (pthread_mutex_unlock(&mu->lock)) {
+        return BLE_NPL_BAD_MUTEX;
+    }
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+ble_npl_mutex_pend(struct ble_npl_mutex *mu, uint32_t timeout)
+{
+    int err;
+
+    if (!mu) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    if (timeout == BLE_NPL_TIME_FOREVER) {
+        err = pthread_mutex_lock(&mu->lock);
+    } else {
+        err = clock_gettime(CLOCK_REALTIME, &mu->wait);
+        if (err) {
+            return BLE_NPL_ERROR;
+        }
+
+        mu->wait.tv_sec  += timeout / 1000;
+        mu->wait.tv_nsec += (timeout % 1000) * 1000000;
+
+        err = pthread_mutex_timedlock(&mu->lock, &mu->wait);
+        if (err == ETIMEDOUT) {
+            return BLE_NPL_TIMEOUT;
+        }
+    }
+
+    return (err) ? BLE_NPL_ERROR : BLE_NPL_OK;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_sem.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_sem.c
new file mode 100644
index 00000000..91a70964
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_sem.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <nuttx/config.h>
+#include <assert.h>
+#include <errno.h>
+#include <semaphore.h>
+
+#include "os/os.h"
+#include "nimble/nimble_npl.h"
+
+ble_npl_error_t
+ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
+{
+    if (!sem) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    sem_init(&sem->lock, 0, tokens);
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+ble_npl_sem_release(struct ble_npl_sem *sem)
+{
+    int err;
+
+    if (!sem) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    err = sem_post(&sem->lock);
+
+    return (err) ? BLE_NPL_ERROR : BLE_NPL_OK;
+}
+
+ble_npl_error_t
+ble_npl_sem_pend(struct ble_npl_sem *sem, uint32_t timeout)
+{
+    int err = 0;
+    struct timespec wait;
+
+    if (!sem) {
+        return BLE_NPL_INVALID_PARAM;
+    }
+
+    if (timeout == BLE_NPL_TIME_FOREVER) {
+        err = sem_wait(&sem->lock);
+    } else {
+        err = clock_gettime(CLOCK_REALTIME, &wait);
+        if (err) {
+            return BLE_NPL_ERROR;
+        }
+
+        wait.tv_sec  += timeout / 1000;
+        wait.tv_nsec += (timeout % 1000) * 1000000;
+
+        err = sem_timedwait(&sem->lock, &wait);
+        if (err && errno == ETIMEDOUT) {
+            return BLE_NPL_TIMEOUT;
+        }
+    }
+
+    return (err) ? BLE_NPL_ERROR : BLE_NPL_OK;
+}
+
+uint16_t
+ble_npl_sem_get_count(struct ble_npl_sem *sem)
+{
+    int count;
+
+    assert(sem);
+    assert(&sem->lock);
+    sem_getvalue(&sem->lock, &count);
+
+    /* NuttX can return negative value, return 0 in that case */
+
+    if (count < 0) {
+        count = 0;
+    }
+
+    return count;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_task.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_task.c
new file mode 100644
index 00000000..2e020236
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_task.c
@@ -0,0 +1,117 @@
+/*
+ * 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 <nuttx/config.h>
+#include "os/os.h"
+#include "nimble/nimble_npl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize a task.
+ *
+ * This function initializes the task structure pointed to by t,
+ * clearing and setting it's stack pointer, provides sane defaults
+ * and sets the task as ready to run, and inserts it into the operating
+ * system scheduler.
+ *
+ * @param t The task to initialize
+ * @param name The name of the task to initialize
+ * @param func The task function to call
+ * @param arg The argument to pass to this task function
+ * @param prio The priority at which to run this task
+ * @param sanity_itvl The time at which this task should check in with the
+ *                    sanity task.  OS_WAIT_FOREVER means never check in
+ *                    here.
+ * @param stack_bottom A pointer to the bottom of a task's stack
+ * @param stack_size The overall size of the task's stack.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
+        void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
+        ble_npl_stack_t *stack_bottom, uint16_t stack_size)
+{
+    int err;
+    if ((t == NULL) || (func == NULL)) {
+        return OS_INVALID_PARM;
+    }
+
+    err = pthread_attr_init(&t->attr);
+    if (err) return err;
+    err = pthread_attr_getschedparam (&t->attr, &t->param);
+    if (err) return err;
+    err = pthread_attr_setschedpolicy(&t->attr, SCHED_RR);
+    if (err) return err;
+    t->param.sched_priority = prio;
+    err = pthread_attr_setschedparam (&t->attr, &t->param);
+    if (err) return err;
+
+    t->name = name;
+    err = pthread_create(&t->handle, &t->attr, func, arg);
+
+    return err;
+}
+
+/*
+ * Removes specified task
+ * XXX
+ * NOTE: This interface is currently experimental and not ready for common use
+ */
+int
+ble_npl_task_remove(struct ble_npl_task *t)
+{
+    return pthread_cancel(t->handle);
+}
+
+/**
+ * Return the number of tasks initialized.
+ *
+ * @return number of tasks initialized
+ */
+uint8_t
+ble_npl_task_count(void)
+{
+    return 0;
+}
+
+void *
+ble_npl_get_current_task_id(void)
+{
+    return (void *)(uintptr_t)pthread_self();
+}
+
+bool
+ble_npl_os_started(void)
+{
+    return true;
+}
+
+void
+ble_npl_task_yield(void)
+{
+    pthread_yield();
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_time.c b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_time.c
new file mode 100644
index 00000000..99b4c912
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/os_time.c
@@ -0,0 +1,85 @@
+/*
+ * 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 <nuttx/config.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include "os/os.h"
+#include "nimble/nimble_npl.h"
+
+#include <unistd.h>
+#include <time.h>
+
+/**
+ * Return ticks [ms] since system start as uint32_t.
+ */
+ble_npl_time_t
+ble_npl_time_get(void)
+{
+    struct timespec now;
+    if (clock_gettime(CLOCK_MONOTONIC, &now)) {
+        return 0;
+    }
+    return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;
+}
+
+
+ble_npl_error_t
+ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
+{
+    *out_ticks = ms;
+
+    return BLE_NPL_OK;
+}
+
+
+ble_npl_error_t
+ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
+{
+    *out_ms = ticks;
+
+    return BLE_NPL_OK;
+}
+
+ble_npl_time_t
+ble_npl_time_ms_to_ticks32(uint32_t ms)
+{
+    return ms;
+}
+
+uint32_t
+ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
+{
+    return ticks;
+}
+
+void
+ble_npl_time_delay(ble_npl_time_t ticks)
+{
+    struct timespec sleep_time;
+    long ms = ble_npl_time_ticks_to_ms32(ticks);
+    uint32_t s = ms / 1000;
+
+    ms -= s * 1000;
+    sleep_time.tv_sec = s;
+    sleep_time.tv_nsec = ms * 1000000;
+
+    nanosleep(&sleep_time, NULL);
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/src/wqueue.h b/src/libs/mynewt-nimble/porting/npl/nuttx/src/wqueue.h
new file mode 100644
index 00000000..7821eacd
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/src/wqueue.h
@@ -0,0 +1,104 @@
+/*
+   wqueue.h
+   Worker thread queue based on the Standard C++ library list
+   template class.
+   ------------------------------------------
+   Copyright (c) 2013 Vic Hargrave
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+       http://www.apache.org/licenses/LICENSE-2.0
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+// https://vichargrave.github.io/articles/2013-01/multithreaded-work-queue-in-cpp
+// https://github.com/vichargrave/wqueue/blob/master/wqueue.h
+
+
+#ifndef __wqueue_h__
+#define __wqueue_h__
+
+#include <nuttx/config.h>
+#include <pthread.h>
+#include <queue.h>
+
+struct wqueue_s
+{
+    dq_queue_s           m_queue;
+    pthread_mutex_t      m_mutex;
+    pthread_mutexattr_t  m_mutex_attr;
+    pthread_cond_t       m_condv;
+};
+
+using namespace std;
+
+template <typename T> class wqueue
+{
+    dq_queue_s           m_queue;
+    pthread_mutex_t      m_mutex;
+    pthread_mutexattr_t  m_mutex_attr;
+    pthread_cond_t       m_condv;
+
+public:
+    wqueue()
+    {
+        dq_init(m_queue);
+        pthread_mutexattr_init(&m_mutex_attr);
+        pthread_mutexattr_settype(&m_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&m_mutex, &m_mutex_attr);
+        pthread_cond_init(&m_condv, NULL);
+    }
+
+    ~wqueue() {
+        pthread_mutex_destroy(&m_mutex);
+        pthread_cond_destroy(&m_condv);
+    }
+
+    void put(T item) {
+        dq_entry_t* entry = malloc(sizeof(T));
+
+        pthread_mutex_lock(&m_mutex);
+        dq_addlast(entry, &m_queue);
+        m_queue.push_back(item);
+        pthread_cond_signal(&m_condv);
+        pthread_mutex_unlock(&m_mutex);
+    }
+
+    T get(uint32_t tmo) {
+        pthread_mutex_lock(&m_mutex);
+        if (tmo) {
+            while (m_queue.size() == 0) {
+                pthread_cond_wait(&m_condv, &m_mutex);
+            }
+        }
+
+        T item = NULL;
+
+        if (m_queue.size() != 0) {
+            item = m_queue.front();
+            m_queue.pop_front();
+        }
+
+        pthread_mutex_unlock(&m_mutex);
+        return item;
+    }
+
+    void remove(T item) {
+        pthread_mutex_lock(&m_mutex);
+        m_queue.remove(item);
+        pthread_mutex_unlock(&m_mutex);
+    }
+
+    int size() {
+        pthread_mutex_lock(&m_mutex);
+        int size = m_queue.size();
+        pthread_mutex_unlock(&m_mutex);
+        return size;
+    }
+};
+
+#endif
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/Make.defs b/src/libs/mynewt-nimble/porting/npl/nuttx/test/Make.defs
new file mode 100644
index 00000000..a4bdce16
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/Make.defs
@@ -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.
+#
+
+CFLAGS += \
+    -I.    \
+    -I$(NIMBLE_ROOT)/nimble/include             \
+    -I$(NIMBLE_ROOT)/porting/npl/nuttx/include  \
+    -I$(NIMBLE_ROOT)/porting/npl/nuttx/src      \
+    -I$(NIMBLE_ROOT)/porting/nimble/include
+
+OSAL_PATH = $(NIMBLE_ROOT)/porting/npl/nuttx/src
+
+CSRCS = $(wildcard $(OSAL_PATH)/*.c) \
+        $(wildcard $(OSAL_PATH)/*.cc) \
+        $(NIMBLE_ROOT)/porting/nimble/src/os_mempool.c
+
+CXXOBJS += $($(wildcard *.cxx):$(CXXEXT)=$(SUFFIX)$(OBJEXT))
+
+CFLAGS += -DNIMBLE_CFG_CONTROLLER=0 -DOS_CFG_ALIGN_4=4 -DOS_CFG_ALIGNMENT=4
+
+DEPPATH += --dep-path $(NIMBLE_ROOT)/porting/npl/nuttx/test
+VPATH += :$(NIMBLE_ROOT)/porting/npl/nuttx/test
+VPATH += :$(NIMBLE_ROOT)/porting/nimble/src
+VPATH += :$(OSAL_PATH)
+
+PROGNAME = test_npl_task test_npl_eventq test_npl_callout test_npl_sem
+MAINSRC = $(wildcard $(NIMBLE_ROOT)/porting/npl/nuttx/test/*.c)
+
+clean::
+	(cd $(NIMBLE_ROOT)/porting/npl/nuttx/test && rm -f *.o)
+	(cd $(NIMBLE_ROOT)/porting/nimble/src && rm -f *.o)
+	(cd $(OSAL_PATH) && rm -f *.o)
+
+test_npl_task.exe: test_npl_task.o $(OBJS)
+	$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+test_npl_eventq.exe: test_npl_eventq.o $(OBJS)
+	$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+test_npl_callout.exe: test_npl_callout.o $(OBJS)
+	$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+test_npl_sem.exe: test_npl_sem.o $(OBJS)
+	$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_callout.c b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_callout.c
new file mode 100644
index 00000000..d04303f8
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_callout.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+/**
+  Unit tests for the ble_npl_callout api:
+
+  void ble_npl_callout_init(struct ble_npl_callout *cf, struct ble_npl_eventq *evq,
+                       ble_npl_event_fn *ev_cb, void *ev_arg);
+  int ble_npl_callout_reset(struct ble_npl_callout *, int32_t);
+  int ble_npl_callout_queued(struct ble_npl_callout *c);
+  void ble_npl_callout_stop(struct ble_npl_callout *c);
+*/
+
+#include "test_util.h"
+#include "nimble/nimble_npl.h"
+
+#define TEST_ARGS_VALUE  (55)
+#define TEST_INTERVAL    (100)
+
+static bool                   s_tests_running = true;
+static struct ble_npl_task    s_task;
+static struct ble_npl_callout s_callout;
+static int                    s_callout_args = TEST_ARGS_VALUE;
+
+static struct ble_npl_eventq  s_eventq;
+
+
+void on_callout(struct ble_npl_event *ev)
+{
+    VerifyOrQuit(ev->ev_arg == &s_callout_args,
+		 "callout: wrong args passed");
+
+    VerifyOrQuit(*(int*)ev->ev_arg == TEST_ARGS_VALUE,
+		 "callout: args corrupted");
+
+    s_tests_running = false;
+}
+
+/**
+ * ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq,
+ *                 ble_npl_event_fn *ev_cb, void *ev_arg)
+ */
+int test_init(void)
+{
+    ble_npl_callout_init(&s_callout,
+		    &s_eventq,
+		    on_callout,
+		    &s_callout_args);
+    return PASS;
+}
+
+int test_queued(void)
+{
+  //VerifyOrQuit(ble_npl_callout_queued(&s_callout),
+  //	 "callout: not queued when expected");
+    return PASS;
+}
+
+int test_reset(void)
+{
+    return ble_npl_callout_reset(&s_callout, TEST_INTERVAL);
+}
+
+int test_stop(void)
+{
+    return PASS;
+}
+
+
+/**
+ * ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq,
+ *                 ble_npl_event_fn *ev_cb, void *ev_arg)
+ */
+void *test_task_run(void *args)
+{
+    SuccessOrQuit(test_init(),   "callout_init failed");
+    SuccessOrQuit(test_queued(), "callout_queued failed");
+    SuccessOrQuit(test_reset(),  "callout_reset failed");
+
+    while (s_tests_running)
+    {
+        ble_npl_eventq_run(&s_eventq);
+    }
+
+    printf("All tests passed\n");
+    exit(PASS);
+
+    return NULL;
+}
+
+int main(void)
+{
+    ble_npl_eventq_init(&s_eventq);
+
+    SuccessOrQuit(ble_npl_task_init(&s_task, "s_task", test_task_run,
+			       NULL, 1, 0, NULL, 0),
+		  "task: error initializing");
+
+    while (1) {}
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_eventq.c b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_eventq.c
new file mode 100644
index 00000000..f0c362b9
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_eventq.c
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+/**
+  Unit tests for the ble_npl_eventq api:
+
+  void ble_npl_eventq_init(struct ble_npl_eventq *);
+  void ble_npl_eventq_put(struct ble_npl_eventq *, struct ble_npl_event *);
+  struct ble_npl_event *ble_npl_eventq_get_no_wait(struct ble_npl_eventq *evq);
+  struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *);
+  void ble_npl_eventq_run(struct ble_npl_eventq *evq);
+  struct ble_npl_event *ble_npl_eventq_poll(struct ble_npl_eventq **, int, ble_npl_time_t);
+  void ble_npl_eventq_remove(struct ble_npl_eventq *, struct ble_npl_event *);
+  struct ble_npl_eventq *ble_npl_eventq_dflt_get(void);
+*/
+
+#include <assert.h>
+#include <pthread.h>
+#include "test_util.h"
+#include "nimble/nimble_npl.h"
+
+#define TEST_ARGS_VALUE  (55)
+#define TEST_STACK_SIZE  (1024)
+
+static bool                   s_tests_running = true;
+static struct ble_npl_task    s_task_runner;
+static struct ble_npl_task    s_task_dispatcher;
+
+static struct ble_npl_eventq  s_eventq;
+static struct ble_npl_event   s_event;
+static int                    s_event_args = TEST_ARGS_VALUE;
+
+
+void on_event(struct ble_npl_event *ev)
+{
+    VerifyOrQuit(ev->ev_arg == &s_event_args,
+		 "callout: wrong args passed");
+
+    VerifyOrQuit(*(int*)ev->ev_arg == TEST_ARGS_VALUE,
+		 "callout: args corrupted");
+
+    s_tests_running = false;
+}
+
+int test_init(void)
+{
+    //VerifyOrQuit(!ble_npl_eventq_inited(&s_eventq), "eventq: empty q initialized");
+    ble_npl_eventq_init(&s_eventq);
+    //VerifyOrQuit(ble_npl_eventq_inited(&s_eventq), "eventq: not initialized");
+
+    return PASS;
+}
+
+int test_run(void)
+{
+    while (s_tests_running)
+    {
+        ble_npl_eventq_run(&s_eventq);
+    }
+
+    return PASS;
+}
+
+int test_put(void)
+{
+    s_event.ev_cb = on_event;
+    s_event.ev_arg = &s_event_args;
+    ble_npl_eventq_put(&s_eventq, &s_event);
+    return PASS;
+}
+
+int test_get_no_wait(void)
+{
+    //struct ble_npl_event *ev = ble_npl_eventq_get_no_wait(&s_eventq);
+    return FAIL;
+}
+
+int test_get(void)
+{
+    struct ble_npl_event *ev = ble_npl_eventq_get(&s_eventq,
+                                                  BLE_NPL_TIME_FOREVER);
+
+    VerifyOrQuit(ev == &s_event,
+		 "callout: wrong event passed");
+
+    return PASS;
+}
+
+
+void *task_test_runner(void *args)
+{
+    int count = 1000000000;
+
+    SuccessOrQuit(test_init(), "eventq_init failed");
+    SuccessOrQuit(test_put(),  "eventq_put failed");
+    SuccessOrQuit(test_get(),  "eventq_get failed");
+    SuccessOrQuit(test_put(),  "eventq_put failed");
+    SuccessOrQuit(test_run(),  "eventq_run failed");
+
+    printf("All tests passed\n");
+    exit(PASS);
+
+    return NULL;
+}
+
+int main(void)
+{
+    SuccessOrQuit(ble_npl_task_init(&s_task_runner,
+			      "task_test_runner",
+			      task_test_runner,
+			      NULL, 1, 0, NULL, 0),
+		          "task: error initializing");
+
+    while (1) {}
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_mempool.c b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_mempool.c
new file mode 100644
index 00000000..2dac0bb1
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_mempool.c
@@ -0,0 +1,111 @@
+/*
+ * 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 "test_util.h"
+#include "nimble/nimble_npl.h"
+
+#define    TEST_MEMPOOL_BLOCKS       4
+#define    TEST_MEMPOOL_BLOCK_SIZE   128
+
+static struct ble_npl_mempool s_mempool;
+
+static os_membuf_t s_mempool_mem[OS_MEMPOOL_SIZE(TEST_MEMPOOL_BLOCKS,
+						 TEST_MEMPOOL_BLOCK_SIZE)];
+
+static void *s_memblock[TEST_MEMPOOL_BLOCKS];
+
+/**
+ * Unit test for initializing a mempool.
+ *
+ * ble_npl_error_t ble_npl_mempool_init(struct ble_npl_mempool *mp, int blocks,
+ *                            int block_size, void *membuf, char *name);
+ *
+ */
+int test_init(void)
+{
+    int err;
+    err = ble_npl_mempool_init(NULL,
+			  TEST_MEMPOOL_BLOCKS,
+			  TEST_MEMPOOL_BLOCK_SIZE,
+			  NULL,
+			  "Null mempool");
+    VerifyOrQuit(err, "ble_npl_mempool_init accepted NULL parameters.");
+
+    err = ble_npl_mempool_init(&s_mempool,
+			  TEST_MEMPOOL_BLOCKS,
+			  TEST_MEMPOOL_BLOCK_SIZE,
+			  s_mempool_mem,
+			  "s_mempool");
+    return err;
+}
+
+/**
+ * Test integrity check of a mempool.
+ *
+ * bool ble_npl_mempool_is_sane(const struct ble_npl_mempool *mp);
+ */
+int test_is_sane(void)
+{
+    return (ble_npl_mempool_is_sane(&s_mempool)) ? PASS : FAIL;
+}
+
+/**
+ * Test getting a memory block from the pool, putting it back,
+ * and checking if it is still valid.
+ *
+ * void *ble_npl_memblock_get(struct ble_npl_mempool *mp);
+ *
+ * ble_npl_error_t ble_npl_memblock_put(struct ble_npl_mempool *mp, void *block_addr);
+ *
+ * int ble_npl_memblock_from(const struct ble_npl_mempool *mp, const void *block_addr);
+ */
+int test_stress(void)
+{
+    int loops = 3;
+    while(loops--)
+    {
+        for (int i = 0; i < 4; i++)
+	{
+	    s_memblock[i] = ble_npl_memblock_get(&s_mempool);
+	    VerifyOrQuit(ble_npl_memblock_from(&s_mempool, s_memblock[i]),
+			 "ble_npl_memblock_get return invalid block.");
+	}
+
+
+        for (int i = 0; i < 4; i++)
+	{
+ 	    SuccessOrQuit(ble_npl_memblock_put(&s_mempool, s_memblock[i]),
+			"ble_npl_memblock_put refused to take valid block.");
+	    //VerifyOrQuit(!ble_npl_memblock_from(&s_mempool, s_memblock[i]),
+	    //		 "Block still valid after ble_npl_memblock_put.");
+	}
+
+    }
+    return PASS;
+}
+
+int main(void)
+{
+    SuccessOrQuit(test_init(),    "Failed: ble_npl_mempool_init");
+    SuccessOrQuit(test_is_sane(), "Failed: ble_npl_mempool_is_sane");
+    SuccessOrQuit(test_stress(),  "Failed: ble_npl_mempool stree test");
+    SuccessOrQuit(test_is_sane(), "Failed: ble_npl_mempool_is_sane");
+    printf("All tests passed\n");
+    return PASS;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_sem.c b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_sem.c
new file mode 100644
index 00000000..b62f8e2a
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_sem.c
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+/**
+  Unit tests for the Semaphore api (ble_npl_sem):
+
+  ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
+  ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
+  ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, uint32_t timeout);
+  uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
+*/
+
+#include "test_util.h"
+#include "nimble/nimble_npl.h"
+//#include "os/os.h"
+
+#define TEST_ITERATIONS   10
+
+#define TASK1_PRIO        1
+#define TASK2_PRIO        1
+
+#define TASK1_STACK_SIZE  1028
+#define TASK2_STACK_SIZE  1028
+
+static struct ble_npl_task    task1;
+static struct ble_npl_task    task2;
+
+static ble_npl_stack_t task1_stack[TASK1_STACK_SIZE];
+static ble_npl_stack_t task2_stack[TASK2_STACK_SIZE];
+
+struct ble_npl_sem task1_sem;
+struct ble_npl_sem task2_sem;
+
+/* Task 1 handler function */
+void *
+task1_handler(void *arg)
+{
+    for (int i = 0; i < TEST_ITERATIONS; i++)
+    {
+	/* Release semaphore to task 2 */
+        SuccessOrQuit(ble_npl_sem_release(&task1_sem),
+		      "ble_npl_sem_release: error releasing task2_sem.");
+
+	/* Wait for semaphore from task 2 */
+        SuccessOrQuit(ble_npl_sem_pend(&task2_sem, BLE_NPL_TIME_FOREVER),
+		      "ble_npl_sem_pend: error waiting for task2_sem.");
+    }
+
+    printf("All tests passed\n");
+    exit(PASS);
+
+    return NULL;
+}
+
+/* Task 2 handler function */
+void *
+task2_handler(void *arg)
+{
+    while(1)
+    {
+        /* Wait for semaphore from task1 */
+        SuccessOrQuit(ble_npl_sem_pend(&task1_sem, BLE_NPL_TIME_FOREVER),
+		      "ble_npl_sem_pend: error waiting for task1_sem.");
+
+	    /* Release task2 semaphore */
+        SuccessOrQuit(ble_npl_sem_release(&task2_sem),
+		      "ble_npl_sem_release: error releasing task1_sem.");
+    }
+
+    return NULL;
+}
+
+
+/* Initialize task 1 exposed data objects */
+void
+task1_init(void)
+{
+    /* Initialize task1 semaphore */
+    SuccessOrQuit(ble_npl_sem_init(&task1_sem, 0),
+		  "ble_npl_sem_init: task1 returned error.");
+}
+
+/* Initialize task 2 exposed data objects */
+void
+task2_init(void)
+{
+    /* Initialize task1 semaphore */
+    SuccessOrQuit(ble_npl_sem_init(&task2_sem, 0),
+		  "ble_npl_sem_init: task2 returned error.");
+}
+
+/**
+ * init_app_tasks
+ *
+ * This function performs initializations that are required before tasks run.
+ *
+ * @return int 0 success; error otherwise.
+ */
+static int
+init_app_tasks(void)
+{
+    /*
+     * Call task specific initialization functions to initialize any shared objects
+     * before initializing the tasks with the OS.
+     */
+    task1_init();
+    task2_init();
+
+    /*
+     * Initialize tasks 1 and 2 with the OS.
+     */
+    ble_npl_task_init(&task1, "task1", task1_handler, NULL, TASK1_PRIO,
+                      BLE_NPL_TIME_FOREVER, task1_stack, TASK1_STACK_SIZE);
+
+    ble_npl_task_init(&task2, "task2", task2_handler, NULL, TASK2_PRIO,
+                      BLE_NPL_TIME_FOREVER, task2_stack, TASK2_STACK_SIZE);
+
+    return 0;
+}
+
+/**
+ * main
+ *
+ * The main function for the application. This function initializes the system and packages,
+ * calls the application specific task initialization function, then waits and dispatches
+ * events from the OS default event queue in an infinite loop.
+ */
+int
+main(int argc, char **arg)
+{
+    /* Initialize application specific tasks */
+    init_app_tasks();
+
+    while (1)
+    {
+        ble_npl_eventq_run(ble_npl_eventq_dflt_get());
+    }
+    /* main never returns */
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_task.c b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_task.c
new file mode 100644
index 00000000..66310cd7
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_npl_task.c
@@ -0,0 +1,98 @@
+/*
+ * 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 "test_util.h"
+#include "nimble/nimble_npl.h"
+
+#include <pthread.h>
+
+#define TASK0_ARG     55
+#define TASK1_ARG     66
+
+static struct ble_npl_task s_task[2];
+static int            s_task_arg[2] =
+{
+    TASK0_ARG, TASK1_ARG
+};
+
+
+void *task0_run(void *args)
+{
+    int i = 10000;
+    VerifyOrQuit(args == &s_task_arg[0], "Wrong args passed to task0");
+
+    while (i--)
+    {
+    }
+
+    return NULL;
+}
+
+void *task1_run(void *args)
+{
+    int i = 10000;
+    VerifyOrQuit(args == &s_task_arg[1], "Wrong args passed to task0");
+
+    while (i--)
+    {
+    }
+
+    printf("All tests passed\n");
+    exit(PASS);
+
+    return NULL;
+}
+
+/**
+ * Unit test for initializing a task.
+ *
+ * int ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
+ *                  void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
+ *                  ble_npl_stack_t *stack_bottom, uint16_t stack_size)
+ *
+ */
+int test_init(void)
+{
+    int err;
+    err = ble_npl_task_init(NULL,
+		       "Null task",
+		       NULL, NULL, 1, 0, NULL, 0);
+    VerifyOrQuit(err, "ble_npl_task_init accepted NULL parameters.");
+
+    err = ble_npl_task_init(&s_task[0],
+		       "s_task[0]",
+		       task0_run, &s_task_arg[0], 1, 0, NULL, 0);
+    SuccessOrQuit(err, "ble_npl_task_init failed.");
+
+    err = ble_npl_task_init(&s_task[1],
+		       "s_task[1]",
+		       task1_run, &s_task_arg[1], 1, 0, NULL, 0);
+
+    return err;
+}
+
+int main(void)
+{
+    int ret = PASS;
+    SuccessOrQuit(test_init(),    "Failed: ble_npl_task_init");
+
+    pthread_exit(&ret);
+
+    return ret;
+}
diff --git a/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_util.h b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_util.h
new file mode 100644
index 00000000..90985c3f
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/npl/nuttx/test/test_util.h
@@ -0,0 +1,56 @@
+/*
+ * 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 _TEST_UTIL_H_
+#define _TEST_UTIL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define PASS    (0)
+#define FAIL    (-1)
+
+#define SuccessOrQuit(ERR, MSG)						      \
+  do {                                                                        \
+    if ((ERR))                                                                \
+    {                                                                         \
+      fprintf(stderr, "\nFAILED %s:%d - %s\n", __FUNCTION__, __LINE__, MSG);  \
+      exit(-1);                                                               \
+    }                                                                         \
+  } while (false)
+
+#define VerifyOrQuit(TST, MSG)                                                \
+  do {                                                                        \
+    if (!(TST))                                                               \
+    {                                                                         \
+      fprintf(stderr, "\nFAILED %s:%d - %s\n", __FUNCTION__, __LINE__, MSG);  \
+      exit(-1);                                                               \
+    }                                                                         \
+  } while (false)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _TEST_UTIL_H_ */
diff --git a/src/libs/mynewt-nimble/porting/npl/riot/include/logcfg/logcfg.h b/src/libs/mynewt-nimble/porting/npl/riot/include/logcfg/logcfg.h
index e21a3ae5..837cdeac 100644
--- a/src/libs/mynewt-nimble/porting/npl/riot/include/logcfg/logcfg.h
+++ b/src/libs/mynewt-nimble/porting/npl/riot/include/logcfg/logcfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_LOGCFG_
diff --git a/src/libs/mynewt-nimble/porting/npl/riot/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/npl/riot/include/syscfg/syscfg.h
index e78ebe0a..816f410a 100644
--- a/src/libs/mynewt-nimble/porting/npl/riot/include/syscfg/syscfg.h
+++ b/src/libs/mynewt-nimble/porting/npl/riot/include/syscfg/syscfg.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSCFG_
@@ -15,8 +15,6 @@
 #define MYNEWT_VAL(_name)                       MYNEWT_VAL_ ## _name
 #define MYNEWT_VAL_CHOICE(_name, _val)          MYNEWT_VAL_ ## _name ## __ ## _val
 
-
-
 /*** @apache-mynewt-core/compiler/arm-none-eabi-m4 */
 #ifndef MYNEWT_VAL_HARDFLOAT
 #define MYNEWT_VAL_HARDFLOAT (0)
@@ -167,6 +165,10 @@
 #define MYNEWT_VAL_NFC_PINS_AS_GPIO (1)
 #endif
 
+#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC
+#define MYNEWT_VAL_OS_TICKS_PER_SEC (128)
+#endif
+
 #ifndef MYNEWT_VAL_PWM_0
 #define MYNEWT_VAL_PWM_0 (0)
 #endif
@@ -357,6 +359,10 @@
 
 #undef MYNEWT_VAL_SPI_3_MASTER_PIN_SCK
 
+#ifndef MYNEWT_VAL_TEMP
+#define MYNEWT_VAL_TEMP (0)
+#endif
+
 /* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */
 #ifndef MYNEWT_VAL_TIMER_0
 #define MYNEWT_VAL_TIMER_0 (0)
@@ -427,7 +433,7 @@
 
 #undef MYNEWT_VAL_UART_1_PIN_TX
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */
 #ifndef MYNEWT_VAL_XTAL_32768
 #define MYNEWT_VAL_XTAL_32768 (1)
 #endif
@@ -445,12 +451,12 @@
 #define MYNEWT_VAL_FLOAT_USER (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-core/kernel/os) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/kernel/os) */
 #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
 #define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (5)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-core/kernel/os) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/kernel/os) */
 #ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
 #define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (88)
 #endif
@@ -769,11 +775,19 @@
 #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
 #define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble) */
 #ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS
 #define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0)
 #endif
@@ -823,7 +837,7 @@
 #define MYNEWT_VAL_BLE_DEVICE (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE
 #define MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE (0)
 #endif
@@ -836,7 +850,11 @@
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL (0)
+#endif
+
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT (0)
 #endif
@@ -849,12 +867,12 @@
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (0)
 #endif
@@ -868,6 +886,16 @@
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV (0)
 #endif
 
+/* Value copied from BLE_ISO */
+#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO (0)
+#endif
+
+/* Value copied from BLE_ISO_TEST */
+#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO_TEST
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO_TEST (0)
+#endif
+
 /* Value copied from BLE_PERIODIC_ADV */
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV (0)
@@ -888,16 +916,20 @@
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (0)
 #endif
 
+#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_SCA_UPDATE
+#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_SCA_UPDATE (0)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG
 #define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (1)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES
 #define MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE)
 #endif
@@ -910,12 +942,20 @@
 #define MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS (4)
 #endif
 
-#ifndef MYNEWT_VAL_BLE_LL_DBG_HCI_CMD_PIN
-#define MYNEWT_VAL_BLE_LL_DBG_HCI_CMD_PIN (-1)
+#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_CMD
+#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_CMD (-1)
 #endif
 
-#ifndef MYNEWT_VAL_BLE_LL_DBG_HCI_EV_PIN
-#define MYNEWT_VAL_BLE_LL_DBG_HCI_EV_PIN (-1)
+#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_EV
+#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_EV (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB
+#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB (-1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_RUN
+#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_RUN (-1)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE
@@ -980,6 +1020,11 @@
 #define MYNEWT_VAL_BLE_LL_RNG_BUFSIZE (32)
 #endif
 
+/* Value copied from BLE_LL_OUR_SCA */
+#ifndef MYNEWT_VAL_BLE_LL_SCA
+#define MYNEWT_VAL_BLE_LL_SCA (60)
+#endif
+
 #ifndef MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY
 #define MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY (0)
 #endif
@@ -1000,12 +1045,12 @@
 #define MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES
 #define MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
 #ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES
 #define MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE)
 #endif
@@ -1372,7 +1417,7 @@
 #define MYNEWT_VAL_BLE_SM_KEYPRESS (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */
 #ifndef MYNEWT_VAL_BLE_SM_LEGACY
 #define MYNEWT_VAL_BLE_SM_LEGACY (0)
 #endif
@@ -1393,7 +1438,7 @@
 #define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */
 #ifndef MYNEWT_VAL_BLE_SM_SC
 #define MYNEWT_VAL_BLE_SM_SC (0)
 #endif
@@ -1465,9 +1510,9 @@
 #endif
 
 /*** @apache-mynewt-nimble/nimble/transport/ram */
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/transport/ram) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/transport/ram) */
 #ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
-#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (4)
+#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (24)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
@@ -1478,7 +1523,7 @@
 #define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70)
 #endif
 
-/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/transport/ram) */
+/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/transport/ram) */
 #ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
 #define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (2)
 #endif
diff --git a/src/libs/mynewt-nimble/porting/npl/riot/include/sysflash/sysflash.h b/src/libs/mynewt-nimble/porting/npl/riot/include/sysflash/sysflash.h
index 413cb267..ab1341b2 100644
--- a/src/libs/mynewt-nimble/porting/npl/riot/include/sysflash/sysflash.h
+++ b/src/libs/mynewt-nimble/porting/npl/riot/include/sysflash/sysflash.h
@@ -1,5 +1,5 @@
 /**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
  */
 
 #ifndef H_MYNEWT_SYSFLASH_
diff --git a/src/libs/mynewt-nimble/porting/targets/linux/pkg.yml b/src/libs/mynewt-nimble/porting/targets/linux/pkg.yml
index f1159d4a..c819a83c 100644
--- a/src/libs/mynewt-nimble/porting/targets/linux/pkg.yml
+++ b/src/libs/mynewt-nimble/porting/targets/linux/pkg.yml
@@ -16,7 +16,7 @@
 # under the License.
 #
 
-pkg.name: "targets/linux"
+pkg.name: "porting/targets/linux"
 pkg.type: "target"
 pkg.description: This target is used to generate syscfg.h file and other artifacts for linux example app.
 pkg.author:
diff --git a/src/libs/mynewt-nimble/porting/targets/linux_blemesh/pkg.yml b/src/libs/mynewt-nimble/porting/targets/linux_blemesh/pkg.yml
index c3149333..3cbe09a4 100644
--- a/src/libs/mynewt-nimble/porting/targets/linux_blemesh/pkg.yml
+++ b/src/libs/mynewt-nimble/porting/targets/linux_blemesh/pkg.yml
@@ -16,7 +16,7 @@
 # under the License.
 #
 
-pkg.name: "targets/linux_blemesh"
+pkg.name: "porting/targets/linux_blemesh"
 pkg.type: "target"
 pkg.description: This target is used to generate syscfg.h file and other artifacts for linux_blemesh example app.
 pkg.author:
diff --git a/src/libs/mynewt-nimble/porting/targets/nuttx/pkg.yml b/src/libs/mynewt-nimble/porting/targets/nuttx/pkg.yml
new file mode 100644
index 00000000..e105cd63
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/targets/nuttx/pkg.yml
@@ -0,0 +1,40 @@
+# 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: "porting/targets/nuttx"
+pkg.type: "target"
+pkg.description: This target is used to generate syscfg.h file and other artifacts for nuttx example app.
+pkg.author:
+pkg.homepage:
+
+pkg.deps:
+- "@apache-mynewt-core/kernel/os"
+- "@apache-mynewt-core/sys/console/stub"
+- "@apache-mynewt-core/sys/log/stub"
+- "@apache-mynewt-core/sys/stats/stub"
+- "@apache-mynewt-nimble/nimble/host"
+- "@apache-mynewt-nimble/nimble/transport/socket"
+- "@apache-mynewt-nimble/nimble/host/services/ans"
+- "@apache-mynewt-nimble/nimble/host/services/bas"
+- "@apache-mynewt-nimble/nimble/host/services/dis"
+- "@apache-mynewt-nimble/nimble/host/services/gap"
+- "@apache-mynewt-nimble/nimble/host/services/gatt"
+- "@apache-mynewt-nimble/nimble/host/services/ias"
+- "@apache-mynewt-nimble/nimble/host/services/ipss"
+- "@apache-mynewt-nimble/nimble/host/services/lls"
+- "@apache-mynewt-nimble/nimble/host/services/tps"
diff --git a/src/libs/mynewt-nimble/porting/targets/nuttx/syscfg.yml b/src/libs/mynewt-nimble/porting/targets/nuttx/syscfg.yml
new file mode 100644
index 00000000..fdfa7b59
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/targets/nuttx/syscfg.yml
@@ -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.
+#
+
+syscfg.vals:
+    BLE_SOCK_USE_TCP: 0
+    BLE_SOCK_USE_NUTTX: 1
+    BLE_SOCK_TASK_PRIO: 3
+    BLE_SOCK_STACK_SIZE: 1028
+    BLE_LL_CFG_FEAT_LL_PRIVACY: 0
+    LOG_LEVEL: 2
+    BLE_SM_LEGACY: 1
+    BLE_SM_SC: 1
+
diff --git a/src/libs/mynewt-nimble/porting/targets/nuttx/target.yml b/src/libs/mynewt-nimble/porting/targets/nuttx/target.yml
new file mode 100644
index 00000000..9ab4152c
--- /dev/null
+++ b/src/libs/mynewt-nimble/porting/targets/nuttx/target.yml
@@ -0,0 +1,20 @@
+# 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.
+#
+target.app: "porting/targets/dummy_app"
+target.bsp: "porting/targets/dummy_bsp"
+target.build_profile: "debug"
diff --git a/src/libs/mynewt-nimble/porting/targets/porting_default/pkg.yml b/src/libs/mynewt-nimble/porting/targets/porting_default/pkg.yml
index f7319c25..44a34ba0 100644
--- a/src/libs/mynewt-nimble/porting/targets/porting_default/pkg.yml
+++ b/src/libs/mynewt-nimble/porting/targets/porting_default/pkg.yml
@@ -16,7 +16,7 @@
 # under the License.
 #
 
-pkg.name: "targets/porting_default"
+pkg.name: "porting/targets/porting_default"
 pkg.type: "target"
 pkg.description: This target is used to generate syscfg.h file and other artifacts for default Nimble port includes.
 pkg.author:
diff --git a/src/libs/mynewt-nimble/porting/targets/riot/pkg.yml b/src/libs/mynewt-nimble/porting/targets/riot/pkg.yml
index b6610c30..7d1a3243 100644
--- a/src/libs/mynewt-nimble/porting/targets/riot/pkg.yml
+++ b/src/libs/mynewt-nimble/porting/targets/riot/pkg.yml
@@ -16,7 +16,7 @@
 # under the License.
 #
 
-pkg.name: "targets/riot"
+pkg.name: "porting/targets/riot"
 pkg.type: "target"
 pkg.description: This target is used to generate syscfg.h file and other artifacts for RIOT Nimble port.
 pkg.author:
diff --git a/src/libs/mynewt-nimble/porting/targets/riot/syscfg.yml b/src/libs/mynewt-nimble/porting/targets/riot/syscfg.yml
index 7bbb57fe..d6ee102b 100644
--- a/src/libs/mynewt-nimble/porting/targets/riot/syscfg.yml
+++ b/src/libs/mynewt-nimble/porting/targets/riot/syscfg.yml
@@ -17,7 +17,7 @@
 #
 
 syscfg.vals:
-    BLE_ACL_BUF_COUNT: 4
+    BLE_ACL_BUF_COUNT: 24
     BLE_HCI_EVT_HI_BUF_COUNT: 2
     BLE_HW_WHITELIST_ENABLE: 0
     BLE_LL_CFG_FEAT_DATA_LEN_EXT: 0
diff --git a/src/libs/mynewt-nimble/porting/update_generated_files.sh b/src/libs/mynewt-nimble/porting/update_generated_files.sh
index c01dddd2..6309ed2b 100755
--- a/src/libs/mynewt-nimble/porting/update_generated_files.sh
+++ b/src/libs/mynewt-nimble/porting/update_generated_files.sh
@@ -23,6 +23,7 @@ if [ ! -f "project.yml" ]; then
 fi
 
 declare -A targets=(
+    ["nuttx"]="repos/apache-mynewt-nimble/porting/examples/nuttx/"
     ["linux"]="repos/apache-mynewt-nimble/porting/examples/linux/"
     ["linux_blemesh"]="repos/apache-mynewt-nimble/porting/examples/linux_blemesh/"
     ["porting_default"]="repos/apache-mynewt-nimble/porting/nimble"
@@ -31,6 +32,11 @@ declare -A targets=(
 
 for target in "${!targets[@]}"; do
     echo "Updating target $target"
-    newt build "$target" > /dev/null 2>&1
-    cp "bin/@apache-mynewt-nimble/targets/${target}/generated/include" "${targets[$target]}" -r
+    newt build "@apache-mynewt-nimble/porting/targets/$target" > /dev/null 2>&1
+    cp "bin/@apache-mynewt-nimble/porting/targets/${target}/generated/include" "${targets[$target]}" -r
+    # Remove repo version and hash MYNEWT_VALS as it doesn't make much sense to commit them and they
+    # defeat the purpose of this script.
+    find "${targets[$target]}/include" -type f -name 'syscfg.h' -exec sed -i '/MYNEWT_VAL_REPO_*/,/#endif/d' {} \;
+    find "${targets[$target]}/include" -type f -name 'syscfg.h' -exec sed -i '/\/\*\*\* Repository/,/\*\//d' {} \;
+    find "${targets[$target]}/include" -type f -name 'syscfg.h' -exec sed -i '$!N;/^\n$/{$q;D;};P;D;' {} \;
 done
diff --git a/src/libs/mynewt-nimble/targets/dialog_cmac/pkg.yml b/src/libs/mynewt-nimble/targets/dialog_cmac/pkg.yml
new file mode 100644
index 00000000..31242b20
--- /dev/null
+++ b/src/libs/mynewt-nimble/targets/dialog_cmac/pkg.yml
@@ -0,0 +1,5 @@
+pkg.name: targets/dialog_cmac
+pkg.type: target
+pkg.description: Sample target for BLE controller on Dialog CMAC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
diff --git a/src/libs/mynewt-nimble/targets/dialog_cmac/syscfg.yml b/src/libs/mynewt-nimble/targets/dialog_cmac/syscfg.yml
new file mode 100644
index 00000000..2f4d3348
--- /dev/null
+++ b/src/libs/mynewt-nimble/targets/dialog_cmac/syscfg.yml
@@ -0,0 +1,16 @@
+syscfg.vals:
+    MCU_DEEP_SLEEP: 1
+    MCU_SLP_TIMER: 1
+    MCU_SLP_TIMER_32K_ONLY: 1
+
+    BLE_HCI_TRANSPORT: dialog_cmac
+
+    # LL recommended settings (decreasing timing values is not recommended)
+    BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL: 1
+    BLE_LL_CONN_INIT_MIN_WIN_OFFSET: 2
+    BLE_LL_RFMGMT_ENABLE_TIME: 20
+    BLE_LL_SCHED_AUX_MAFS_DELAY: 150
+    BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY: 150
+
+    # NOTE: set public address in target settings
+    # BLE_PUBLIC_DEV_ADDR: "(uint8_t[6]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff}"
diff --git a/src/libs/mynewt-nimble/targets/dialog_cmac/target.yml b/src/libs/mynewt-nimble/targets/dialog_cmac/target.yml
new file mode 100644
index 00000000..e3ca85cd
--- /dev/null
+++ b/src/libs/mynewt-nimble/targets/dialog_cmac/target.yml
@@ -0,0 +1,3 @@
+target.app: "@apache-mynewt-nimble/apps/blehci"
+target.bsp: "@apache-mynewt-core/hw/bsp/dialog_cmac"
+target.build_profile: speed
diff --git a/src/main.cpp b/src/main.cpp
index 3b993ee9..4f8ed6a8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -232,7 +232,7 @@ void nimble_port_ll_task_func(void *args) {
   ble_ll_task(args);
 }
 }
-
+int countT2 = 0;
 int main(void) {
   logger.Init();