You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2017/11/23 09:30:25 UTC

[GitHub] sjanc closed pull request #671: Extended Advertising API

sjanc closed pull request #671: Extended Advertising API
URL: https://github.com/apache/mynewt-core/pull/671
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/apps/bletiny/src/cmd.c b/apps/bletiny/src/cmd.c
index 4ff2f9294..ed1c45e1c 100644
--- a/apps/bletiny/src/cmd.c
+++ b/apps/bletiny/src/cmd.c
@@ -412,16 +412,6 @@ bletiny_help_disabled(void)
 }
 #endif
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-static struct kv_pair cmd_ext_adv_phy_opts[] = {
-    { "none",        0x00 },
-    { "1M",          0x01 },
-    { "2M",          0x02 },
-    { "coded",       0x03 },
-    { NULL }
-};
-#endif
-
 static void
 bletiny_adv_help(void)
 {
@@ -446,11 +436,6 @@ bletiny_adv_help(void)
     help_cmd_long_bounds_dflt("itvl_max", 0, UINT16_MAX, 0);
     help_cmd_long_bounds_dflt("hd", 0, 1, 0);
     help_cmd_long_bounds_dflt("dur", 1, INT32_MAX, BLE_HS_FOREVER);
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    help_cmd_long_bounds_dflt("tx_power", -127, 127, 127);
-    help_cmd_kv_dflt("primary_phy", cmd_ext_adv_phy_opts, 0);
-    help_cmd_kv_dflt("secondary_phy", cmd_ext_adv_phy_opts, 0);
-#endif
 }
 
 static int
@@ -462,10 +447,6 @@ cmd_adv(int argc, char **argv)
     ble_addr_t *peer_addr_param = &peer_addr;
     uint8_t own_addr_type;
     int rc;
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    int8_t tx_power;
-    uint8_t primary_phy, secondary_phy;
-#endif
 
     if (argc > 1 && strcmp(argv[1], "help") == 0) {
         bletiny_adv_help();
@@ -572,43 +553,6 @@ cmd_adv(int argc, char **argv)
         return rc;
     }
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    tx_power = parse_arg_long_bounds_default("tx_power", -127, 127, 127, &rc);
-    if (rc != 0) {
-        console_printf("invalid 'tx_power' parameter\n");
-        help_cmd_long_bounds_dflt("tx_power", -127, 127, 127);
-        return rc;
-    }
-
-    primary_phy = parse_arg_kv_default("primary_phy", cmd_ext_adv_phy_opts,
-                                       0, &rc);
-    if (rc != 0) {
-        console_printf("invalid 'primary_phy' parameter\n");
-        help_cmd_kv_dflt("primary_phy", cmd_ext_adv_phy_opts, 0);
-        return rc;
-    }
-
-    secondary_phy = parse_arg_kv_default("secondary_phy", cmd_ext_adv_phy_opts,
-                                         primary_phy, &rc);
-    if (rc != 0) {
-        console_printf("invalid 'secondary_phy' parameter\n");
-        help_cmd_kv_dflt("secondary_phy", cmd_ext_adv_phy_opts, 0);
-        return rc;
-    }
-
-    rc = ble_gap_adv_set_tx_power(tx_power);
-    if (rc != 0) {
-        console_printf("setting advertise TX power fail: %d\n", rc);
-        return rc;
-    }
-
-    rc = ble_gap_adv_set_phys(primary_phy, secondary_phy);
-    if (rc != 0) {
-        console_printf("setting advertise PHYs fail: %d\n", rc);
-        return rc;
-    }
-#endif
-
     rc = bletiny_adv_start(own_addr_type, peer_addr_param, duration_ms,
                            &params);
     if (rc != 0) {
diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h
index c636d15cc..ddbd5da53 100644
--- a/apps/btshell/src/btshell.h
+++ b/apps/btshell/src/btshell.h
@@ -114,6 +114,11 @@ int btshell_write_long(uint16_t conn_handle, uint16_t attr_handle,
                        uint16_t offset, struct os_mbuf *om);
 int btshell_write_reliable(uint16_t conn_handle,
                            struct ble_gatt_attr *attrs, int num_attrs);
+#if MYNEWT_VAL(BLE_EXT_ADV)
+int btshell_ext_adv_configure(uint8_t instance,
+                              const struct ble_gap_ext_adv_params *params,
+                              int8_t *selected_tx_power);
+#endif
 int btshell_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                       int32_t duration_ms,
                       const struct ble_gap_adv_params *params);
@@ -138,7 +143,6 @@ int btshell_ext_scan(uint8_t own_addr_type, uint16_t duration, uint16_t period,
                      const struct ble_gap_ext_disc_params *uncoded_params,
                      const struct ble_gap_ext_disc_params *coded_params);
 int btshell_scan_cancel(void);
-int btshell_set_adv_data(struct ble_hs_adv_fields *adv_fields);
 int btshell_update_conn(uint16_t conn_handle,
                          struct ble_gap_upd_params *params);
 void btshell_notify(uint16_t attr_handle);
diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c
index 60820fb18..de752251f 100644
--- a/apps/btshell/src/cmd.c
+++ b/apps/btshell/src/cmd.c
@@ -46,6 +46,16 @@
 
 #define BTSHELL_MODULE "btshell"
 
+#if MYNEWT_VAL(BLE_EXT_ADV)
+
+#define EXT_ADV_POOL_SIZE (MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) + \
+                            sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr))
+
+/* 1 mbuf is enough for configuring adv data */
+static os_membuf_t ext_adv_mem[OS_MEMPOOL_SIZE(1, EXT_ADV_POOL_SIZE)];
+static struct os_mempool ext_adv_pool;
+static struct os_mbuf_pool ext_adv_mbuf_pool;
+#endif
 
 int
 cmd_parse_conn_start_end(uint16_t *out_conn, uint16_t *out_start,
@@ -98,21 +108,6 @@ static const struct kv_pair cmd_addr_type[] = {
 /*****************************************************************************
  * $advertise                                                                *
  *****************************************************************************/
-
-static const struct kv_pair cmd_adv_conn_modes[] = {
-    { "non", BLE_GAP_CONN_MODE_NON },
-    { "und", BLE_GAP_CONN_MODE_UND },
-    { "dir", BLE_GAP_CONN_MODE_DIR },
-    { NULL }
-};
-
-static const struct kv_pair cmd_adv_disc_modes[] = {
-    { "non", BLE_GAP_DISC_MODE_NON },
-    { "ltd", BLE_GAP_DISC_MODE_LTD },
-    { "gen", BLE_GAP_DISC_MODE_GEN },
-    { NULL }
-};
-
 static const struct kv_pair cmd_adv_filt_types[] = {
     { "none", BLE_HCI_ADV_FILT_NONE },
     { "scan", BLE_HCI_ADV_FILT_SCAN },
@@ -123,14 +118,424 @@ static const struct kv_pair cmd_adv_filt_types[] = {
 
 #if MYNEWT_VAL(BLE_EXT_ADV)
 static struct kv_pair cmd_ext_adv_phy_opts[] = {
-    { "none",        0x00 },
     { "1M",          0x01 },
     { "2M",          0x02 },
     { "coded",       0x03 },
     { NULL }
 };
+
+static bool adv_instances[BLE_ADV_INSTANCES];
+
+static int
+cmd_advertise_configure(int argc, char **argv)
+{
+    struct ble_gap_ext_adv_params params;
+    int8_t selected_tx_power;
+    uint8_t instance;
+    int rc;
+
+    rc = parse_arg_all(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (adv_instances[instance]) {
+        console_printf("instance already configured\n");
+        return rc;
+    }
+
+    memset(&params, 0, sizeof(params));
+
+    params.connectable = parse_arg_bool_dflt("connectable", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'connectable' parameter\n");
+        return rc;
+    }
+
+    params.scannable = parse_arg_bool_dflt("scannable", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'scannable' parameter\n");
+        return rc;
+    }
+
+    params.high_duty_directed = parse_arg_bool_dflt("high_duty", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'high_duty' parameter\n");
+        return rc;
+    }
+
+    params.anonymous = parse_arg_bool_dflt("anonymous", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'anonymous' parameter\n");
+        return rc;
+    }
+
+    params.legacy_pdu = parse_arg_bool_dflt("legacy", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'legacy' parameter\n");
+        return rc;
+    }
+
+    params.include_tx_power = parse_arg_bool_dflt("include_tx_power", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'include_tx_power' parameter\n");
+        return rc;
+    }
+
+    params.scan_req_notif = parse_arg_bool_dflt("scan_req_notif", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'scan_req_notif' parameter\n");
+        return rc;
+    }
+
+    rc = parse_arg_mac("peer_addr", params.peer.val);
+    if (rc == 0) {
+        params.directed = 1;
+
+        params.peer.type = parse_arg_kv_dflt("peer_addr_type",
+                                             cmd_peer_addr_types,
+                                             BLE_ADDR_PUBLIC, &rc);
+        if (rc != 0) {
+            console_printf("invalid 'peer_addr_type' parameter\n");
+            return rc;
+        }
+    }
+    else if (rc == ENOENT) {
+       /* skip, no peer address provided */
+    } else {
+        console_printf("invalid 'peer_addr' parameter\n");
+        return rc;
+    }
+
+    params.own_addr_type = parse_arg_kv_dflt("own_addr_type",
+                                             cmd_own_addr_types,
+                                             BLE_OWN_ADDR_PUBLIC, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'own_addr_type' parameter\n");
+        return rc;
+    }
+
+    params.channel_map = parse_arg_uint8_dflt("channel_map", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'channel_map' parameter\n");
+        return rc;
+    }
+
+    params.filter_policy = parse_arg_kv_dflt("filter", cmd_adv_filt_types,
+                                             BLE_HCI_ADV_FILT_NONE, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'filter' parameter\n");
+        return rc;
+    }
+
+    params.itvl_min = parse_arg_uint32_dflt("interval_min", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'interval_min' parameter\n");
+        return rc;
+    }
+
+    params.itvl_max = parse_arg_uint32_dflt("interval_max", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'interval_max' parameter\n");
+        return rc;
+    }
+
+    params.tx_power = parse_arg_long_bounds_dflt("tx_power",
+                                             -127, 127, 127, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'tx_power' parameter\n");
+        return rc;
+    }
+
+    params.primary_phy = parse_arg_kv_dflt("primary_phy", cmd_ext_adv_phy_opts,
+                                           1, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'primary_phy' parameter\n");
+        return rc;
+    }
+
+    params.secondary_phy = parse_arg_kv_dflt("secondary_phy",
+                                         cmd_ext_adv_phy_opts,
+                                         params.primary_phy, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'secondary_phy' parameter\n");
+        return rc;
+   }
+
+    params.sid = parse_arg_uint8_dflt("sid", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'sid' parameter\n");
+        return rc;
+    }
+
+    params.high_duty_directed = parse_arg_uint8_dflt("high_duty", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'high_duty' parameter\n");
+        return rc;
+    }
+
+    rc = btshell_ext_adv_configure(instance, &params, &selected_tx_power);
+    if (rc) {
+        console_printf("failed to configure advertising instance\n");
+        return rc;
+    }
+
+    console_printf("Instance %u configured (selected tx power: %d)\n",
+                   instance, selected_tx_power);
+
+    adv_instances[instance] = true;
+
+    return 0;
+}
+
+static int
+cmd_advertise_set_addr(int argc, char **argv)
+{
+    ble_addr_t addr;
+    uint8_t instance;
+    int rc;
+
+    rc = parse_arg_all(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (!adv_instances[instance]) {
+        console_printf("instance not configured\n");
+        return rc;
+    }
+
+    rc = parse_arg_mac("addr", addr.val);
+    if (rc != 0) {
+        console_printf("invalid 'addr' parameter\n");
+                    return rc;
+    }
+
+    addr.type = BLE_ADDR_RANDOM;
+
+    rc = ble_gap_ext_adv_set_addr(instance, &addr);
+    if (rc) {
+        console_printf("failed to start advertising instance\n");
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+cmd_advertise_start(int argc, char **argv)
+{
+    int max_events;
+    uint8_t instance;
+    int duration;
+    int rc;
+
+    rc = parse_arg_all(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (!adv_instances[instance]) {
+        console_printf("instance not configured\n");
+        return rc;
+    }
+
+    duration = parse_arg_uint16_dflt("duration", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'duration' parameter\n");
+        return rc;
+    }
+
+    max_events = parse_arg_uint8_dflt("max_events", 0, &rc);
+    if (rc != 0) {
+        console_printf("invalid 'max_events' parameter\n");
+        return rc;
+    }
+
+    rc = ble_gap_ext_adv_start(instance, duration, max_events);
+    if (rc) {
+        console_printf("failed to start advertising instance\n");
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+cmd_advertise_stop(int argc, char **argv)
+{
+    uint8_t instance;
+    int rc;
+
+    rc = parse_arg_all(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (!adv_instances[instance]) {
+        console_printf("instance not configured\n");
+        return rc;
+    }
+
+    rc = ble_gap_ext_adv_stop(instance);
+    if (rc) {
+        console_printf("failed to stop advertising instance\n");
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+cmd_advertise_remove(int argc, char **argv)
+{
+    uint8_t instance;
+    int rc;
+
+    rc = parse_arg_all(argc - 1, argv + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (!adv_instances[instance]) {
+        console_printf("instance not configured\n");
+        return rc;
+    }
+
+    rc = ble_gap_ext_adv_remove(instance);
+    if (rc) {
+        console_printf("failed to remove advertising instance\n");
+        return rc;
+    }
+
+    adv_instances[instance] = false;
+
+    return 0;
+}
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+static const struct shell_param advertise_configure_params[] = {
+    {"instance", "default: 0"},
+    {"connectable", "connectable advertising, usage: =[0-1], default: 0"},
+    {"scannable", "scannable advertising, usage: =[0-1], default: 0"},
+    {"peer_addr_type", "usage: =[public|random|public_id|random_id], default: public"},
+    {"peer_addr", "usage: =[XX:XX:XX:XX:XX:XX]"},
+    {"own_addr_type", "usage: =[public|random|rpa_pub|rpa_rnd], default: public"},
+    {"channel_map", "usage: =[0x00-0xff], default: 0"},
+    {"filter", "usage: =[none|scan|conn|both], default: none"},
+    {"interval_min", "usage: =[0-UINT32_MAX], default: 0"},
+    {"interval_max", "usage: =[0-UINT32_MAX], default: 0"},
+    {"tx_power", "usage: =[-127-127], default: 127"},
+    {"primary_phy", "usage: =[1M|2M|coded], default: 1M"},
+    {"secondary_phy", "usage: =[1M|2M|coded], default: primary_phy"},
+    {"sid", "usage: =[0-UINT8_MAX], default: 0"},
+    {"high_duty", "usage: =[0-1], default: 0"},
+    {"anonymous", "enable anonymous advertising, usage: =[0-1], default: 0"},
+    {"legacy", "use legacy PDUs, usage: =[0-1], default: 0"},
+    {"include_tx_power", "include TX power in PDU, usage: =[0-1], default: 0"},
+    {"scan_req_notif", "enable Scan Request notification usage: =[0-1], default: 0"},
+    {NULL, NULL}
+};
+
+static const struct shell_cmd_help advertise_configure_help = {
+    .summary = "configure new advertising instance",
+    .usage = NULL,
+    .params = advertise_configure_params,
+};
+
+static const struct shell_param advertise_set_addr_params[] = {
+    {"instance", "default: 0"},
+    {"addr", "usage: =[XX:XX:XX:XX:XX:XX]"},
+    {NULL, NULL}
+};
+
+static const struct shell_cmd_help advertise_set_addr_help = {
+    .summary = "set advertising instance random address",
+    .usage = NULL,
+    .params = advertise_set_addr_params,
+};
+
+static const struct shell_param advertise_start_params[] = {
+    {"instance", "default: 0"},
+    {"duration", "advertising duration in 10ms units, default: 0 (forever)"},
+    {"max_events", "max number of advertising events, default: 0 (no limit)"},
+    {NULL, NULL}
+};
+
+static const struct shell_cmd_help advertise_start_help = {
+    .summary = "start advertising instance",
+    .usage = NULL,
+    .params = advertise_start_params,
+};
+
+static const struct shell_param advertise_stop_params[] = {
+    {"instance", "default: 0"},
+    {NULL, NULL}
+};
+
+static const struct shell_cmd_help advertise_stop_help = {
+    .summary = "stop advertising instance",
+    .usage = NULL,
+    .params = advertise_stop_params,
+};
+
+static const struct shell_param advertise_remove_params[] = {
+    {"instance", "default: 0"},
+    {NULL, NULL}
+};
+
+static const struct shell_cmd_help advertise_remove_help = {
+    .summary = "remove advertising instance",
+    .usage = NULL,
+    .params = advertise_remove_params,
+};
 #endif
 
+#else
+static const struct kv_pair cmd_adv_conn_modes[] = {
+    { "non", BLE_GAP_CONN_MODE_NON },
+    { "und", BLE_GAP_CONN_MODE_UND },
+    { "dir", BLE_GAP_CONN_MODE_DIR },
+    { NULL }
+};
+
+static const struct kv_pair cmd_adv_disc_modes[] = {
+    { "non", BLE_GAP_DISC_MODE_NON },
+    { "ltd", BLE_GAP_DISC_MODE_LTD },
+    { "gen", BLE_GAP_DISC_MODE_GEN },
+    { NULL }
+};
+
 static int
 cmd_advertise(int argc, char **argv)
 {
@@ -140,10 +545,6 @@ cmd_advertise(int argc, char **argv)
     ble_addr_t *peer_addr_param = &peer_addr;
     uint8_t own_addr_type;
     int rc;
-    #if MYNEWT_VAL(BLE_EXT_ADV)
-        int8_t tx_power;
-        uint8_t primary_phy, secondary_phy;
-    #endif
 
     rc = parse_arg_all(argc - 1, argv + 1);
     if (rc != 0) {
@@ -234,42 +635,6 @@ cmd_advertise(int argc, char **argv)
         return rc;
     }
 
-    #if MYNEWT_VAL(BLE_EXT_ADV)
-        tx_power = parse_arg_long_bounds_dflt("tx_power",
-                                                 -127, 127, 127, &rc);
-        if (rc != 0) {
-            console_printf("invalid 'tx_power' parameter\n");
-            return rc;
-        }
-
-        primary_phy = parse_arg_kv_dflt("primary_phy", cmd_ext_adv_phy_opts,
-                                           0, &rc);
-        if (rc != 0) {
-            console_printf("invalid 'primary_phy' parameter\n");
-            return rc;
-        }
-
-        secondary_phy = parse_arg_kv_dflt("secondary_phy",
-                                             cmd_ext_adv_phy_opts,
-                                             primary_phy, &rc);
-        if (rc != 0) {
-            console_printf("invalid 'secondary_phy' parameter\n");
-            return rc;
-       }
-
-        rc = ble_gap_adv_set_tx_power(tx_power);
-        if (rc != 0) {
-            console_printf("setting advertise TX power fail: %d\n", rc);
-           return rc;
-        }
-
-        rc = ble_gap_adv_set_phys(primary_phy, secondary_phy);
-        if (rc != 0) {
-            console_printf("setting advertise PHYs fail: %d\n", rc);
-            return rc;
-        }
-    #endif
-
     rc = btshell_adv_start(own_addr_type, peer_addr_param, duration_ms,
                            &params);
     if (rc != 0) {
@@ -294,11 +659,6 @@ static const struct shell_param advertise_params[] = {
     {"interval_max", "usage: =[0-UINT16_MAX], default: 0"},
     {"high_duty", "usage: =[0-1], default: 0"},
     {"duration", "usage: =[1-INT32_MAX], default: INT32_MAX"},
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    {"tx_power", "usage: =[-127-127], default: 127"},
-    {"primary_phy", "usage: =[none|1M|2M|coded], default: none"},
-    {"secondary_phy", "usage: =[none|1M|2M|coded], default: primary_phy"},
-#endif
     {NULL, NULL}
 };
 
@@ -308,6 +668,7 @@ static const struct shell_cmd_help advertise_help = {
     .params = advertise_params,
 };
 #endif
+#endif
 
 /*****************************************************************************
  * $connect                                                                  *
@@ -1009,7 +1370,7 @@ static const struct shell_cmd_help set_help = {
 #define CMD_ADV_DATA_MFG_DATA_MAX_LEN           BLE_HS_ADV_MAX_FIELD_SZ
 
 static int
-cmd_set_adv_data(int argc, char **argv)
+cmd_set_adv_data_or_scan_rsp(int argc, char **argv, bool scan_rsp)
 {
     static bssnz_t ble_uuid16_t uuids16[CMD_ADV_DATA_MAX_UUIDS16];
     static bssnz_t ble_uuid32_t uuids32[CMD_ADV_DATA_MAX_UUIDS32];
@@ -1043,6 +1404,10 @@ cmd_set_adv_data(int argc, char **argv)
     int mfg_data_len;
     int tmp;
     int rc;
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    uint8_t instance;
+    struct os_mbuf *adv_data;
+#endif
 
     memset(&adv_fields, 0, sizeof adv_fields);
 
@@ -1051,6 +1416,19 @@ cmd_set_adv_data(int argc, char **argv)
         return rc;
     }
 
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    instance = parse_arg_uint8_dflt("instance", 0, &rc);
+    if (rc != 0 || instance >= BLE_ADV_INSTANCES) {
+        console_printf("invalid instance\n");
+        return rc;
+    }
+
+    if (!adv_instances[instance]) {
+        console_printf("instance not configured\n");
+        return rc;
+    }
+#endif
+
     tmp = parse_arg_uint8("flags", &rc);
     if (rc == 0) {
         adv_fields.flags = tmp;
@@ -1262,7 +1640,7 @@ cmd_set_adv_data(int argc, char **argv)
                                  &eddystone_url_body_len,
                                  &eddystone_url_suffix);
         if (rc != 0) {
-            return rc;
+            goto done;
         }
 
         rc = ble_eddystone_set_adv_data_url(&adv_fields, eddystone_url_scheme,
@@ -1270,8 +1648,34 @@ cmd_set_adv_data(int argc, char **argv)
                                             eddystone_url_body_len,
                                             eddystone_url_suffix);
     } else {
-        rc = btshell_set_adv_data(&adv_fields);
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        adv_data = os_mbuf_get_pkthdr(&ext_adv_mbuf_pool, 0);
+        if (!adv_data) {
+            rc = ENOMEM;
+            goto done;
+        }
+
+        rc = ble_hs_adv_set_fields_mbuf(&adv_fields, adv_data);
+        if (rc) {
+            goto done;
+        }
+
+        if (scan_rsp) {
+            rc = ble_gap_ext_adv_rsp_set_data(instance, adv_data);
+        } else {
+            rc = ble_gap_ext_adv_set_data(instance, adv_data);
+        }
+
+        os_mbuf_free_chain(adv_data);
+#else
+        if (scan_rsp) {
+            rc = ble_gap_adv_rsp_set_fields(&adv_fields);
+        } else {
+            rc = ble_gap_adv_set_fields(&adv_fields);
+        }
+#endif
     }
+done:
     if (rc != 0) {
         console_printf("error setting advertisement data; rc=%d\n", rc);
         return rc;
@@ -1280,6 +1684,18 @@ cmd_set_adv_data(int argc, char **argv)
     return 0;
 }
 
+static int
+cmd_set_adv_data(int argc, char **argv)
+{
+    return cmd_set_adv_data_or_scan_rsp(argc, argv, false);
+}
+
+static int
+cmd_set_scan_rsp(int argc, char **argv)
+{
+    return cmd_set_adv_data_or_scan_rsp(argc, argv, true);
+}
+
 #if MYNEWT_VAL(SHELL_CMD_HELP)
 static const struct shell_param set_adv_data_params[] = {
     {"flags", "usage: =[0-UINT8_MAX]"},
@@ -1309,6 +1725,12 @@ static const struct shell_cmd_help set_adv_data_help = {
     .usage = NULL,
     .params = set_adv_data_params,
 };
+
+static const struct shell_cmd_help set_scan_rsp_help = {
+    .summary = "set scan response",
+    .usage = NULL,
+    .params = set_adv_data_params,
+};
 #endif
 
 /*****************************************************************************
@@ -2816,6 +3238,57 @@ static const struct shell_cmd_help l2cap_send_help = {
 #endif
 
 static const struct shell_cmd btshell_commands[] = {
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    {
+        .sc_cmd = "advertise-configure",
+        .sc_cmd_func = cmd_advertise_configure,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &advertise_configure_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-set-addr",
+        .sc_cmd_func = cmd_advertise_set_addr,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &advertise_set_addr_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-set-adv-data",
+        .sc_cmd_func = cmd_set_adv_data,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &set_adv_data_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-set-scan-rsp",
+        .sc_cmd_func = cmd_set_scan_rsp,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &set_scan_rsp_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-start",
+        .sc_cmd_func = cmd_advertise_start,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &advertise_start_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-stop",
+        .sc_cmd_func = cmd_advertise_stop,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &advertise_stop_help,
+#endif
+    },
+    {
+        .sc_cmd = "advertise-remove",
+        .sc_cmd_func = cmd_advertise_remove,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &advertise_remove_help,
+#endif
+    },
+#else
     {
         .sc_cmd = "advertise",
         .sc_cmd_func = cmd_advertise,
@@ -2823,6 +3296,7 @@ static const struct shell_cmd btshell_commands[] = {
         .help = &advertise_help,
 #endif
     },
+#endif
     {
         .sc_cmd = "connect",
         .sc_cmd_func = cmd_connect,
@@ -2851,6 +3325,7 @@ static const struct shell_cmd btshell_commands[] = {
         .help = &set_help,
 #endif
     },
+#if !MYNEWT_VAL(BLE_EXT_ADV)
     {
         .sc_cmd = "set-adv-data",
         .sc_cmd_func = cmd_set_adv_data,
@@ -2858,6 +3333,14 @@ static const struct shell_cmd btshell_commands[] = {
         .help = &set_adv_data_help,
 #endif
     },
+    {
+        .sc_cmd = "set-scan-rsp",
+        .sc_cmd_func = cmd_set_scan_rsp,
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+        .help = &set_scan_rsp_help,
+#endif
+    },
+#endif
     {
         .sc_cmd = "set-priv-mode",
         .sc_cmd_func = cmd_set_priv_mode,
@@ -3135,6 +3618,17 @@ static const struct shell_cmd btshell_commands[] = {
 void
 cmd_init(void)
 {
+    int rc;
+
     shell_register(BTSHELL_MODULE, btshell_commands);
     shell_register_default_module(BTSHELL_MODULE);
+
+    rc = os_mempool_init(&ext_adv_pool, 1,
+            EXT_ADV_POOL_SIZE,
+                         ext_adv_mem, "ext_adv_mem");
+    assert(rc == 0);
+
+    rc = os_mbuf_pool_init(&ext_adv_mbuf_pool, &ext_adv_pool,
+            EXT_ADV_POOL_SIZE,
+                           1);
 }
diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c
index d6a4df865..e6511e782 100755
--- a/apps/btshell/src/main.c
+++ b/apps/btshell/src/main.c
@@ -1054,8 +1054,14 @@ btshell_gap_event(struct ble_gap_event *event, void *arg)
         return 0;
 
     case BLE_GAP_EVENT_ADV_COMPLETE:
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        console_printf("advertise complete; reason=%d, instance=%u, handle=%d\n",
+                       event->adv_complete.reason, event->adv_complete.instance,
+                       event->adv_complete.conn_handle);
+#else
         console_printf("advertise complete; reason=%d\n",
                        event->adv_complete.reason);
+#endif
         return 0;
 
     case BLE_GAP_EVENT_ENC_CHANGE:
@@ -1408,6 +1414,17 @@ btshell_write_reliable(uint16_t conn_handle,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_EXT_ADV)
+int
+btshell_ext_adv_configure(uint8_t instance,
+                          const struct ble_gap_ext_adv_params *params,
+                          int8_t *selected_tx_power)
+{
+    return ble_gap_ext_adv_configure(instance, params, selected_tx_power,
+                                     btshell_gap_event, NULL);
+}
+#endif
+
 int
 btshell_adv_stop(void)
 {
@@ -1543,15 +1560,6 @@ btshell_scan_cancel(void)
     return rc;
 }
 
-int
-btshell_set_adv_data(struct ble_hs_adv_fields *adv_fields)
-{
-    int rc;
-
-    rc = ble_gap_adv_set_fields(adv_fields);
-    return rc;
-}
-
 int
 btshell_update_conn(uint16_t conn_handle, struct ble_gap_upd_params *params)
 {
diff --git a/net/nimble/host/include/host/ble_gap.h b/net/nimble/host/include/host/ble_gap.h
index 148357ff6..4dbf3c5f5 100644
--- a/net/nimble/host/include/host/ble_gap.h
+++ b/net/nimble/host/include/host/ble_gap.h
@@ -372,11 +372,19 @@ struct ble_gap_event {
             /**
              * The reason the advertise procedure stopped.  Typical reason
              * codes are:
-             *     o 0: Duration expired.
+             *     o 0: Terminated due to connection.
+             *     o BLE_HS_ETIMEOUT: Duration expired.
              *     o BLE_HS_EPREEMPTED: Host aborted procedure to configure a
              *       peer's identity.
              */
             int reason;
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+            /** Advertising instance */
+            uint8_t instance;
+            /** The handle of the relevant connection - valid if reason=0 */
+            uint16_t conn_handle;
+#endif
         } adv_complete;
 
         /**
@@ -676,8 +684,38 @@ int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields);
 int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);
 
 #if MYNEWT_VAL(BLE_EXT_ADV)
-int ble_gap_adv_set_tx_power(int8_t tx_power);
-int ble_gap_adv_set_phys(uint8_t primary_phy, uint8_t secondary_phy);
+struct ble_gap_ext_adv_params {
+    unsigned int connectable:1;
+    unsigned int scannable:1;
+    unsigned int directed:1;
+    unsigned int high_duty_directed:1;
+    unsigned int legacy_pdu:1;
+    unsigned int anonymous:1;
+    unsigned int include_tx_power:1;
+    unsigned int scan_req_notif:1;
+
+    uint32_t itvl_min;
+    uint32_t itvl_max;
+    uint8_t channel_map;
+    uint8_t own_addr_type;
+    ble_addr_t peer;
+    uint8_t filter_policy;
+    uint8_t primary_phy;
+    uint8_t secondary_phy;
+    int8_t tx_power;
+    uint8_t sid;
+};
+
+int ble_gap_ext_adv_configure(uint8_t instance,
+                              const struct ble_gap_ext_adv_params *params,
+                              int8_t *selected_tx_power,
+                              ble_gap_event_fn *cb, void *cb_arg);
+int ble_gap_ext_adv_set_addr(uint8_t instance, const ble_addr_t *addr);
+int ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events);
+int ble_gap_ext_adv_stop(uint8_t instance);
+int ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data);
+int ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data);
+int ble_gap_ext_adv_remove(uint8_t instance);
 #endif
 
 int ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
diff --git a/net/nimble/host/include/host/ble_hs_adv.h b/net/nimble/host/include/host/ble_hs_adv.h
index c0b46d27e..b0d85c02a 100644
--- a/net/nimble/host/include/host/ble_hs_adv.h
+++ b/net/nimble/host/include/host/ble_hs_adv.h
@@ -158,6 +158,9 @@ struct ble_hs_adv_fields {
 
 #define BLE_HS_ADV_SVC_DATA_UUID128_MIN_LEN     16
 
+int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
+                               struct os_mbuf *om);
+
 int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
                           uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
 
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index ed8fb0c13..20db13317 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -146,11 +146,20 @@ struct ble_gap_slave_state {
     uint8_t op;
 
     unsigned int our_addr_type:2;
-    unsigned int exp_set:1;
     unsigned int preempted:1;  /** Set to 1 if advertising was preempted. */
     unsigned int connectable:1;
 
+    unsigned int configured:1; /** If instance is configured */
+    unsigned int scannable:1;
+    unsigned int directed:1;
+    unsigned int legacy_pdu:1;
+    unsigned int rnd_addr_set:1;
+
+/* timer is used only with legacy advertising */
+#if !MYNEWT_VAL(BLE_EXT_ADV)
+    unsigned int exp_set:1;
     os_time_t exp_os_ticks;
+#endif
 
     ble_gap_event_fn *cb;
     void *cb_arg;
@@ -185,19 +194,13 @@ ble_gap_update_entry_remove(uint16_t conn_handle);
 static void
 ble_gap_update_l2cap_cb(uint16_t conn_handle, int status, void *arg);
 
-static int ble_gap_adv_enable_tx(int enable, bool directed);
+static int ble_gap_adv_enable_tx(int enable);
 static int ble_gap_conn_cancel_tx(void);
 
 #if NIMBLE_BLE_SCAN
 static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
 #endif
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-static uint8_t ext_adv_pri_phy = 0;
-static uint8_t ext_adv_sec_phy = 0;
-static int8_t ext_adv_tx_pwr = 127;
-#endif
-
 STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
 STATS_NAME_START(ble_gap_stats)
     STATS_NAME(ble_gap_stats, wl_set)
@@ -323,6 +326,7 @@ ble_gap_log_wl(const ble_addr_t *addr, uint8_t white_list_count)
     }
 }
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
 static void
 ble_gap_log_adv(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                 const struct ble_gap_adv_params *adv_params)
@@ -341,6 +345,7 @@ ble_gap_log_adv(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                adv_params->itvl_min,
                adv_params->itvl_max);
 }
+#endif
 
 /*****************************************************************************
  * $snapshot                                                                 *
@@ -617,10 +622,21 @@ ble_gap_call_conn_event_cb(struct ble_gap_event *event, uint16_t conn_handle)
 static bool
 ble_gap_is_preempted(void)
 {
+    int i;
+
     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
 
-    return ble_gap_slave[0].preempted ||
-           ble_gap_master.preempted_op != BLE_GAP_OP_NULL;
+    if (ble_gap_master.preempted_op != BLE_GAP_OP_NULL) {
+        return true;
+    }
+
+    for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+        if (ble_gap_slave[i].preempted) {
+            return true;
+        }
+    }
+
+    return false;
 }
 
 static void
@@ -637,9 +653,11 @@ static void
 ble_gap_slave_reset_state(uint8_t instance)
 {
     ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
-    ble_gap_slave[instance].exp_set = 0;
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
+    ble_gap_slave[instance].exp_set = 0;
     ble_hs_timer_resched();
+#endif
 }
 
 static bool
@@ -682,7 +700,7 @@ ble_gap_slave_extract_cb(uint8_t instance,
 }
 
 static void
-ble_gap_adv_finished(uint8_t instance)
+ble_gap_adv_finished(uint8_t instance, int reason, uint16_t conn_handle)
 {
     struct ble_gap_event event;
     ble_gap_event_fn *cb;
@@ -692,7 +710,11 @@ ble_gap_adv_finished(uint8_t instance)
     if (cb != NULL) {
         memset(&event, 0, sizeof event);
         event.type = BLE_GAP_EVENT_ADV_COMPLETE;
-        event.adv_complete.reason = 0;
+        event.adv_complete.reason = reason;
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        event.adv_complete.instance = instance;
+        event.adv_complete.conn_handle = conn_handle;
+#endif
         cb(&event, cb_arg);
     }
 }
@@ -840,6 +862,7 @@ ble_gap_master_ticks_until_exp(void)
     return 0;
 }
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
 static uint32_t
 ble_gap_slave_ticks_until_exp(void)
 {
@@ -859,6 +882,7 @@ ble_gap_slave_ticks_until_exp(void)
     /* Timer just expired. */
     return 0;
 }
+#endif
 
 /**
  * Finds the update procedure that expires soonest.
@@ -915,6 +939,7 @@ ble_gap_master_set_timer(uint32_t ticks_from_now)
     ble_hs_timer_resched();
 }
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
 static void
 ble_gap_slave_set_timer(uint32_t ticks_from_now)
 {
@@ -923,6 +948,7 @@ ble_gap_slave_set_timer(uint32_t ticks_from_now)
 
     ble_hs_timer_resched();
 }
+#endif
 
 /**
  * Called when an error is encountered while the master-connection-fsm is
@@ -1169,7 +1195,9 @@ ble_gap_accept_slave_conn(uint8_t instance)
 {
     int rc;
 
-    if (!ble_gap_adv_active_instance(instance)) {
+    if (instance >= BLE_ADV_INSTANCES) {
+       rc = BLE_HS_ENOENT;
+    } else if (!ble_gap_adv_active_instance(instance)) {
         rc = BLE_HS_ENOENT;
     } else {
         if (ble_gap_slave[instance].connectable) {
@@ -1237,6 +1265,25 @@ ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc)
 
     ble_gap_disc_report(desc);
 }
+
+void
+ble_gap_rx_adv_set_terminated(struct hci_le_adv_set_terminated *evt)
+{
+    uint16_t conn_handle;
+    int reason;
+
+    /* Currently spec allows only 0x3c and 0x43 when advertising was stopped
+     * due to timeout or events limit, mp this for timeout error for now */
+    if (evt->status) {
+        reason = BLE_HS_ETIMEOUT;
+        conn_handle = 0;
+    } else {
+        reason = 0;
+        conn_handle = evt->conn_handle;
+    }
+
+    ble_gap_adv_finished(evt->adv_handle, reason, conn_handle);
+}
 #endif
 
 static int
@@ -1262,9 +1309,10 @@ ble_gap_rd_rem_sup_feat_tx(uint16_t handle)
 
 /**
  * Processes an incoming connection-complete HCI event.
+ * instance parameter is valid only for slave connection.
  */
 int
-ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
+ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance)
 {
 #if !NIMBLE_BLE_CONNECT
     return BLE_HS_ENOTSUP;
@@ -1314,9 +1362,12 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
             break;
 
         case BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE:
+/* with ext advertising this is send from set terminated event */
+#if !MYNEWT_VAL(BLE_EXT_ADV)
             if (ble_gap_adv_active()) {
-                ble_gap_adv_finished(0);
+                ble_gap_adv_finished(0, 0, 0);
             }
+#endif
             break;
 
         default:
@@ -1337,7 +1388,7 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
         break;
 
     case BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE:
-        rc = ble_gap_accept_slave_conn(0);
+        rc = ble_gap_accept_slave_conn(instance);
         if (rc != 0) {
             return rc;
         }
@@ -1363,10 +1414,10 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
         conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type;
         ble_gap_master_reset_state();
     } else {
-        conn->bhc_cb = ble_gap_slave[0].cb;
-        conn->bhc_cb_arg = ble_gap_slave[0].cb_arg;
-        conn->bhc_our_addr_type = ble_gap_slave[0].our_addr_type;
-        ble_gap_slave_reset_state(0);
+        conn->bhc_cb = ble_gap_slave[instance].cb;
+        conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg;
+        conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type;
+        ble_gap_slave_reset_state(instance);
     }
 
     conn->bhc_peer_addr.type = evt->peer_addr_type;
@@ -1508,6 +1559,7 @@ ble_gap_master_timer(void)
     return BLE_HS_FOREVER;
 }
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
 static int32_t
 ble_gap_slave_timer(void)
 {
@@ -1523,7 +1575,7 @@ ble_gap_slave_timer(void)
     /*** Timer expired; process event. */
 
     /* Stop advertising. */
-    rc = ble_gap_adv_enable_tx(0, false);
+    rc = ble_gap_adv_enable_tx(0);
     if (rc != 0) {
         /* Failed to stop advertising; try again in 100 ms. */
         return 100;
@@ -1533,10 +1585,11 @@ ble_gap_slave_timer(void)
     ble_gap_slave_reset_state(0);
 
     /* Indicate to application that advertising has stopped. */
-    ble_gap_adv_finished(0);
+    ble_gap_adv_finished(0, BLE_HS_ETIMEOUT, 0);
 
     return BLE_HS_FOREVER;
 }
+#endif
 
 static int32_t
 ble_gap_update_timer(void)
@@ -1614,13 +1667,18 @@ ble_gap_timer(void)
 {
     int32_t update_ticks;
     int32_t master_ticks;
-    int32_t slave_ticks;
+    int32_t min_ticks;
 
     master_ticks = ble_gap_master_timer();
-    slave_ticks = ble_gap_slave_timer();
     update_ticks = ble_gap_update_timer();
 
-    return min(min(master_ticks, slave_ticks), update_ticks);
+    min_ticks = min(master_ticks, update_ticks);
+
+#if !MYNEWT_VAL(BLE_EXT_ADV)
+    min_ticks = min(min_ticks, ble_gap_slave_timer());
+#endif
+
+    return min_ticks;
 }
 
 /*****************************************************************************
@@ -1751,34 +1809,14 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count)
  *****************************************************************************/
 
 static int
-ble_gap_adv_enable_tx(int enable, bool directed)
+ble_gap_adv_enable_tx(int enable)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    uint8_t buf[6];
-    struct hci_ext_adv_set set = {0, 0, 0};
-#else
     uint8_t buf[BLE_HCI_SET_ADV_ENABLE_LEN];
-#endif
     uint16_t opcode;
     int rc;
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE);
-
-    if (enable && directed) {
-        set.duration = 128;
-    }
-
-    rc = ble_hs_hci_cmd_build_le_ext_adv_enable(!!enable, 1, &set, buf,
-                                                sizeof(buf));
-    if (rc != 0) {
-        return rc;
-    }
-
-#else
     opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE);
     ble_hs_hci_cmd_build_le_set_adv_enable(!!enable, buf, sizeof buf);
-#endif
 
     rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
     if (rc != 0) {
@@ -1809,7 +1847,7 @@ ble_gap_adv_stop_no_lock(void)
 
     BLE_HS_LOG(INFO, "GAP procedure initiated: stop advertising.\n");
 
-    rc = ble_gap_adv_enable_tx(0, false);
+    rc = ble_gap_adv_enable_tx(0);
     if (rc != 0) {
         goto done;
     }
@@ -1839,7 +1877,7 @@ ble_gap_adv_stop_no_lock(void)
 int
 ble_gap_adv_stop(void)
 {
-#if !NIMBLE_BLE_ADVERTISE
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
     return BLE_HS_ENOTSUP;
 #endif
 
@@ -1855,7 +1893,7 @@ ble_gap_adv_stop(void)
 /*****************************************************************************
  * $advertise                                                                *
  *****************************************************************************/
-
+#if !MYNEWT_VAL(BLE_EXT_ADV)
 static int
 ble_gap_adv_type(const struct ble_gap_adv_params *adv_params)
 {
@@ -1883,66 +1921,6 @@ ble_gap_adv_type(const struct ble_gap_adv_params *adv_params)
     }
 }
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-static uint16_t
-ble_gap_adv_type_to_props(int adv_type)
-{
-    uint16_t props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY;
-
-    switch(adv_type) {
-    case BLE_HCI_ADV_TYPE_ADV_IND:
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
-        break;
-    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED;
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED;
-        break;
-    case BLE_HCI_ADV_TYPE_ADV_SCAN_IND:
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
-        break;
-    case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND:
-        break;
-    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
-        props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED;
-        break;
-    default:
-        BLE_HS_DBG_ASSERT(0);
-        break;
-    }
-
-    return props;
-}
-
-static uint16_t
-ble_gap_ext_adv_prop(const struct ble_gap_adv_params *adv_params)
-{
-    uint16_t prop = 0;
-
-    switch (adv_params->conn_mode) {
-    case BLE_GAP_CONN_MODE_NON:
-        if (adv_params->disc_mode == BLE_GAP_DISC_MODE_NON) {
-            prop |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
-        }
-        break;
-    case BLE_GAP_CONN_MODE_UND:
-        prop |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
-        break;
-    case BLE_GAP_CONN_MODE_DIR:
-        prop |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
-        prop |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED;
-        break;
-    default:
-        BLE_HS_DBG_ASSERT(0);
-        break;
-    }
-
-    return prop;
-}
-#endif
-
 static void
 ble_gap_adv_dflt_itvls(uint8_t conn_mode,
                        uint16_t *out_itvl_min, uint16_t *out_itvl_max)
@@ -1974,80 +1952,6 @@ ble_gap_adv_params_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr,
                       const struct ble_gap_adv_params *adv_params)
 
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    struct hci_ext_adv_params hci_adv_params;
-    const ble_addr_t *peer_any = BLE_ADDR_ANY;
-    uint8_t buf[BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN];
-    uint16_t min_int = 0, max_int = 0;
-    uint16_t props;
-    int rc;
-
-    if (peer_addr == NULL) {
-        peer_addr = peer_any;
-    }
-
-    hci_adv_params.own_addr_type = own_addr_type;
-    hci_adv_params.peer_addr_type = peer_addr->type;
-    memcpy(hci_adv_params.peer_addr, peer_addr->val,
-           sizeof hci_adv_params.peer_addr);
-
-    /* Fill optional fields if application did not specify them. */
-    if (adv_params->itvl_min == 0 && adv_params->itvl_max == 0) {
-        ble_gap_adv_dflt_itvls(adv_params->conn_mode, &min_int, &max_int);
-
-        /* TODO for now limited to legacy values*/
-        hci_adv_params.min_interval = min_int;
-        hci_adv_params.max_interval = max_int;
-
-    } else {
-        hci_adv_params.min_interval = adv_params->itvl_min;
-        hci_adv_params.max_interval = adv_params->itvl_max;
-    }
-    if (adv_params->channel_map == 0) {
-        hci_adv_params.chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP;
-    } else {
-        hci_adv_params.chan_map = adv_params->channel_map;
-    }
-
-    /* Zero is the default value for filter policy and high duty cycle */
-    hci_adv_params.filter_policy = adv_params->filter_policy;
-    hci_adv_params.tx_power = ext_adv_tx_pwr;
-
-    /* if phy was not set this means legacy advertising PDUs */
-    if (ext_adv_pri_phy == 0) {
-        props = ble_gap_adv_type_to_props(ble_gap_adv_type(adv_params));
-
-        hci_adv_params.properties = props;
-        hci_adv_params.primary_phy = BLE_HCI_LE_PHY_1M;
-        hci_adv_params.secondary_phy = BLE_HCI_LE_PHY_1M;
-    } else {
-        /* allowed only for legacy PDUs */
-        if (adv_params->high_duty_cycle) {
-            return BLE_HS_EINVAL;
-        }
-
-        hci_adv_params.properties = ble_gap_ext_adv_prop(adv_params);
-        hci_adv_params.primary_phy = ext_adv_pri_phy;
-        hci_adv_params.secondary_phy = ext_adv_sec_phy;
-    }
-
-    hci_adv_params.max_skip = 0;
-    hci_adv_params.sid = 0;
-    hci_adv_params.scan_req_notif = 0;
-
-    rc = ble_hs_hci_cmd_build_le_ext_adv_params(0, &hci_adv_params,
-                                                buf, sizeof(buf));
-    if (rc != 0) {
-        return BLE_HS_EINVAL;
-    }
-
-    rc = ble_hs_hci_cmd_tx_empty_ack(
-        BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM),
-        buf, sizeof(buf));
-    if (rc != 0) {
-        return rc;
-    }
-#else
     const ble_addr_t *peer_any = BLE_ADDR_ANY;
     struct hci_adv_params hci_adv_params;
     uint8_t buf[BLE_HCI_SET_ADV_PARAM_LEN];
@@ -2093,7 +1997,6 @@ ble_gap_adv_params_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr,
     if (rc != 0) {
         return rc;
     }
-#endif
 
     return 0;
 }
@@ -2167,6 +2070,7 @@ ble_gap_adv_validate(uint8_t own_addr_type, const ble_addr_t *peer_addr,
 
     return 0;
 }
+#endif
 
 /**
  * Initiates advertising.
@@ -2204,10 +2108,9 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                   const struct ble_gap_adv_params *adv_params,
                   ble_gap_event_fn *cb, void *cb_arg)
 {
-#if !NIMBLE_BLE_ADVERTISE
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
     return BLE_HS_ENOTSUP;
-#endif
-
+#else
     uint32_t duration_ticks;
     int rc;
 
@@ -2260,7 +2163,7 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
 
     ble_gap_slave[0].op = BLE_GAP_OP_S_ADV;
 
-    rc = ble_gap_adv_enable_tx(1, direct_addr != NULL);
+    rc = ble_gap_adv_enable_tx(1);
     if (rc != 0) {
         ble_gap_slave_reset_state(0);
         goto done;
@@ -2279,6 +2182,7 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
         STATS_INC(ble_gap_stats, adv_start_fail);
     }
     return rc;
+#endif
 }
 
 /**
@@ -2294,11 +2198,11 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
 int
 ble_gap_adv_set_data(const uint8_t *data, int data_len)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    static uint8_t buf[4 + MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
-#else
-    uint8_t buf[BLE_HCI_SET_ADV_DATA_LEN];
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
+    return BLE_HS_ENOTSUP;
 #endif
+
+    uint8_t buf[BLE_HCI_SET_ADV_DATA_LEN];
     uint16_t opcode;
     int rc;
 
@@ -2306,16 +2210,9 @@ ble_gap_adv_set_data(const uint8_t *data, int data_len)
 
     ble_hs_lock();
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_DATA);
-    rc = ble_hs_hci_cmd_build_le_ext_adv_data(0,
-                                    BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE,
-                                    0, data, data_len, buf, sizeof(buf));
-#else
     opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA);
     rc = ble_hs_hci_cmd_build_le_set_adv_data(data, data_len, buf,
                                               sizeof(buf));
-#endif
     if (rc != 0) {
         goto done;
     }
@@ -2345,26 +2242,19 @@ ble_gap_adv_set_data(const uint8_t *data, int data_len)
 int
 ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    static uint8_t buf[4 + MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
-#else
-    uint8_t buf[BLE_HCI_SET_SCAN_RSP_DATA_LEN];
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
+    return BLE_HS_ENOTSUP;
 #endif
+
+    uint8_t buf[BLE_HCI_SET_SCAN_RSP_DATA_LEN];
     uint16_t opcode;
     int rc;
 
     ble_hs_lock();
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA);
-    rc = ble_hs_hci_cmd_build_le_ext_adv_scan_rsp(0,
-                                BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE,
-                                0, data, data_len, buf, sizeof(buf));
-#else
     opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA);
     rc = ble_hs_hci_cmd_build_le_set_scan_rsp_data(data, data_len,
                                                    buf, sizeof(buf));
-#endif
     if (rc != 0) {
         rc = BLE_HS_HCI_ERR(rc);
         goto done;
@@ -2397,11 +2287,11 @@ ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len)
 int
 ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    uint8_t buf[MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
-#else
-    uint8_t buf[BLE_HS_ADV_MAX_SZ];
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
+    return BLE_HS_ENOTSUP;
 #endif
+
+    uint8_t buf[BLE_HS_ADV_MAX_SZ];
     uint8_t buf_sz;
     int rc;
 
@@ -2431,11 +2321,11 @@ ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields)
 int
 ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    uint8_t buf[MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
-#else
-    uint8_t buf[BLE_HS_ADV_MAX_SZ];
+#if !NIMBLE_BLE_ADVERTISE || MYNEWT_VAL(BLE_EXT_ADV)
+    return BLE_HS_ENOTSUP;
 #endif
+
+    uint8_t buf[BLE_HS_ADV_MAX_SZ];
     uint8_t buf_sz;
     int rc;
 
@@ -2465,88 +2355,651 @@ ble_gap_adv_active(void)
 }
 
 #if MYNEWT_VAL(BLE_EXT_ADV)
-int
-ble_gap_adv_set_tx_power(int8_t tx_power)
+static int
+ble_gap_ext_adv_params_tx(uint8_t instance,
+                          const struct ble_gap_ext_adv_params *params,
+                          int8_t *selected_tx_power)
+
 {
-    ble_hs_lock();
+    struct hci_ext_adv_params hci_adv_params;
+    uint8_t buf[BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN];
+    uint8_t rsp;
+    int rc;
 
-    if (ble_gap_adv_active()) {
-        ble_hs_unlock();
-        return BLE_HS_EBUSY;
+    memset(&hci_adv_params, 0, sizeof(hci_adv_params));
+
+    if (params->connectable) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
+    }
+    if (params->scannable) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
+    }
+    if (params->directed) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED;
+        hci_adv_params.peer_addr_type = params->peer.type;
+        memcpy(hci_adv_params.peer_addr, params->peer.val, 6);
+    }
+    if (params->high_duty_directed) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED;
+    }
+    if (params->legacy_pdu) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY;
+    }
+    if (params->anonymous) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV;
+    }
+    if (params->include_tx_power) {
+        hci_adv_params.properties |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR;
     }
 
-    ext_adv_tx_pwr = tx_power;
+    /* Fill optional fields if application did not specify them. */
+    if (params->itvl_min == 0 && params->itvl_max == 0) {
+        /* TODO for now limited to legacy values*/
+        hci_adv_params.min_interval = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+        hci_adv_params.max_interval = BLE_GAP_ADV_FAST_INTERVAL2_MAX;
 
-    ble_hs_unlock();
+    } else {
+        hci_adv_params.min_interval = params->itvl_min;
+        hci_adv_params.max_interval = params->itvl_max;
+    }
 
-    return 0;
-}
+    if (params->channel_map == 0) {
+        hci_adv_params.chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP;
+    } else {
+        hci_adv_params.chan_map = params->channel_map;
+    }
 
-int
-ble_gap_adv_set_phys(uint8_t primary_phy, uint8_t secondary_phy)
-{
-    if (primary_phy) {
-        /* primary cannot be 2M */
-        if (primary_phy != BLE_HCI_LE_PHY_1M &&
-            primary_phy != BLE_HCI_LE_PHY_CODED) {
-            return BLE_HS_EINVAL;
-        }
+    /* Zero is the default value for filter policy and high duty cycle */
+    hci_adv_params.filter_policy = params->filter_policy;
+    hci_adv_params.tx_power = params->tx_power;
 
-        /* if primary is not legacy then secondary must not be legacy as
-         * well
-         */
-        if (!secondary_phy || secondary_phy > BLE_HCI_LE_PHY_CODED) {
-            return BLE_HS_EINVAL;
-        }
+    if (params->legacy_pdu) {
+        hci_adv_params.primary_phy = BLE_HCI_LE_PHY_1M;
+        hci_adv_params.secondary_phy = BLE_HCI_LE_PHY_1M;
     } else {
-        /* if primary is legacy then secondary must be legacy as well */
-        if (secondary_phy) {
-            return BLE_HS_EINVAL;
-        }
+        hci_adv_params.primary_phy = params->primary_phy;
+        hci_adv_params.secondary_phy = params->secondary_phy;
     }
 
-    ble_hs_lock();
+    hci_adv_params.own_addr_type = params->own_addr_type;
+    hci_adv_params.max_skip = 0;
+    hci_adv_params.sid = params->sid;
+    hci_adv_params.scan_req_notif = params->scan_req_notif;
 
-    if (ble_gap_adv_active()) {
-        ble_hs_unlock();
-        return BLE_HS_EBUSY;
+    rc = ble_hs_hci_cmd_build_le_ext_adv_params(instance, &hci_adv_params,
+                                                buf, sizeof(buf));
+    if (rc != 0) {
+        return rc;
     }
 
-    ext_adv_pri_phy = primary_phy;
-    ext_adv_sec_phy = secondary_phy;
+    rc = ble_hs_hci_cmd_tx(
+            BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM),
+            buf, sizeof(buf), &rsp, 1, NULL);
 
-    ble_hs_unlock();
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (selected_tx_power) {
+        *selected_tx_power = rsp;
+    }
 
     return 0;
 }
-#endif
 
-/*****************************************************************************
- * $discovery procedures                                                     *
- *****************************************************************************/
-
-#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
 static int
-ble_gap_ext_disc_tx_params(uint8_t own_addr_type, uint8_t filter_policy,
-                       const struct ble_hs_hci_ext_scan_param *uncoded_params,
-                       const struct ble_hs_hci_ext_scan_param *coded_params)
+ble_gap_ext_adv_params_validate(const struct ble_gap_ext_adv_params *params)
 {
-    uint8_t buf[BLE_HCI_LE_EXT_SCAN_BASE_LEN +
-                2 * BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN];
-    uint8_t phy_mask = 0;
-    struct ble_hs_hci_ext_scan_param param[2] = {{0}};
-    struct ble_hs_hci_ext_scan_param *p = param;
-    int phy_count = 0;
-    uint8_t len;
-    int rc;
+    if (!params) {
+        return BLE_HS_EINVAL;
+    }
 
-    if (uncoded_params) {
-        phy_mask |= BLE_HCI_LE_PHY_1M_PREF_MASK;
-        memcpy(&param[phy_count], uncoded_params, sizeof(*uncoded_params));
-        phy_count++;
+    if (params->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+        return BLE_HS_EINVAL;
     }
 
-    if (coded_params) {
+    /* Don't allow connectable advertising if we won't be able to allocate
+     * a new connection.
+     */
+    if (params->connectable && !ble_hs_conn_can_alloc()) {
+        return BLE_HS_ENOMEM;
+    }
+
+    if (params->legacy_pdu) {
+        /* not allowed for legacy PDUs */
+        if (params->anonymous || params->include_tx_power) {
+            return BLE_HS_EINVAL;
+        }
+    }
+
+    if (params->directed) {
+        if (params->scannable) {
+            return BLE_HS_EINVAL;
+        }
+    }
+
+    if (!params->legacy_pdu) {
+        /* not allowed for extended advertising PDUs */
+        if (params->connectable && params->scannable) {
+            return BLE_HS_EINVAL;
+        }
+
+        /* HD directed advertising allowed only for legacy PDUs */
+        if (params->high_duty_directed) {
+            return BLE_HS_EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+int
+ble_gap_ext_adv_configure(uint8_t instance,
+                          const struct ble_gap_ext_adv_params *params,
+                          int8_t *selected_tx_power,
+                          ble_gap_event_fn *cb, void *cb_arg)
+{
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return EINVAL;
+    }
+
+    rc = ble_gap_ext_adv_params_validate(params);
+    if (rc) {
+        return rc;
+    }
+
+    ble_hs_lock();
+
+    /* TODO should we allow to reconfigure existing instance? */
+    if (ble_gap_slave[instance].configured) {
+        ble_hs_unlock();
+        return ENOMEM;
+    }
+
+    rc = ble_gap_ext_adv_params_tx(instance, params, selected_tx_power);
+    if (rc) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    ble_gap_slave[instance].configured = 1;
+    ble_gap_slave[instance].cb = cb;
+    ble_gap_slave[instance].cb_arg = cb_arg;
+    ble_gap_slave[instance].our_addr_type = params->own_addr_type;
+
+    ble_gap_slave[instance].connectable = params->connectable;
+    ble_gap_slave[instance].scannable = params->scannable;
+    ble_gap_slave[instance].directed = params->directed;
+    ble_gap_slave[instance].legacy_pdu = params->legacy_pdu;
+
+    ble_hs_unlock();
+    return 0;
+}
+
+static int
+ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr)
+{
+    uint8_t buf[BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN];
+    int rc;
+
+    rc = ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(instance, addr, buf,
+                                                         sizeof(buf));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                     BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR),
+                                     buf, sizeof(buf));
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_gap_slave[instance].rnd_addr_set = 1;
+
+    return 0;
+}
+
+int
+ble_gap_ext_adv_set_addr(uint8_t instance, const ble_addr_t *addr)
+{
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES || addr->type != BLE_ADDR_RANDOM) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    rc = ble_gap_ext_adv_set_addr_no_lock(instance, addr->val);
+    ble_hs_unlock();
+
+    return rc;
+}
+
+int
+ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
+{
+    const uint8_t *rnd_addr;
+    uint8_t buf[6];
+    struct hci_ext_adv_set set;
+    uint16_t opcode;
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    if (!ble_gap_slave[instance].configured) {
+        ble_hs_unlock();
+        return BLE_HS_EINVAL;
+    }
+
+    if (ble_gap_slave[instance].op != BLE_GAP_OP_NULL) {
+        ble_hs_unlock();
+        return  BLE_HS_EALREADY;
+    }
+
+    if (ble_gap_slave[instance].directed && duration > 1280) {
+        ble_hs_unlock();
+        return BLE_HS_EINVAL;
+    }
+
+    /* verify own address type if random address for instance wasn't explicitly
+     * set
+     */
+    switch (ble_gap_slave[instance].our_addr_type) {
+    case BLE_OWN_ADDR_RANDOM:
+    case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
+        if (ble_gap_slave[instance].rnd_addr_set) {
+            break;
+        }
+        /* fall through */
+    case BLE_OWN_ADDR_PUBLIC:
+    case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
+    default:
+        rc = ble_hs_id_use_addr(ble_gap_slave[instance].our_addr_type);
+        if (rc) {
+            ble_hs_unlock();
+            return BLE_HS_EINVAL;
+        }
+        break;
+    }
+
+    /* fallback to ID static random address if using random address and instance
+     * wasn't configured with own address
+     */
+    if (!ble_gap_slave[instance].rnd_addr_set) {
+        switch (ble_gap_slave[instance].our_addr_type) {
+        case BLE_OWN_ADDR_RANDOM:
+        case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
+            rc = ble_hs_id_addr(BLE_ADDR_RANDOM, &rnd_addr, NULL);
+            if (rc != 0) {
+                ble_hs_unlock();
+                return rc;
+            }
+
+            rc = ble_gap_ext_adv_set_addr_no_lock(instance, rnd_addr);
+            if (rc != 0) {
+                ble_hs_unlock();
+                return rc;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE);
+
+    set.handle = instance;
+    set.duration = duration;
+    set.events = max_events;
+
+    rc = ble_hs_hci_cmd_build_le_ext_adv_enable(1, 1, &set, buf, sizeof(buf));
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    ble_gap_slave[instance].op = BLE_GAP_OP_S_ADV;
+
+    ble_hs_unlock();
+    return 0;
+}
+
+static int
+ble_gap_ext_adv_stop_no_lock(uint8_t instance)
+{
+    uint8_t buf[6];
+    struct hci_ext_adv_set set;
+    uint16_t opcode;
+    int rc;
+
+    if (!ble_gap_slave[instance].configured) {
+        return BLE_HS_EINVAL;
+    }
+
+    if (ble_gap_slave[instance].op != BLE_GAP_OP_S_ADV) {
+        return BLE_HS_EALREADY;
+    }
+
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE);
+
+    set.handle = instance;
+    set.duration = 0;
+    set.events = 0;
+
+    rc = ble_hs_hci_cmd_build_le_ext_adv_enable(0, 1, &set, buf, sizeof(buf));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
+
+    return 0;
+}
+
+int
+ble_gap_ext_adv_stop(uint8_t instance)
+{
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    rc = ble_gap_ext_adv_stop_no_lock(instance);
+    ble_hs_unlock();
+
+    return rc;
+}
+
+
+static int
+ble_gap_ext_adv_set_data_validate(uint8_t instance, struct os_mbuf *data)
+{
+    uint16_t len = OS_MBUF_PKTLEN(data);
+
+    if (!ble_gap_slave[instance].configured) {
+        return BLE_HS_EINVAL;
+    }
+
+    /* not allowed with directed advertising */
+    if (ble_gap_slave[instance].directed) {
+        return BLE_HS_EINVAL;
+    }
+
+    /* always allowed with legacy PDU but limited to legacy length */
+    if (ble_gap_slave[instance].legacy_pdu) {
+        if (len > BLE_HS_ADV_MAX_SZ) {
+            return BLE_HS_EINVAL;
+        }
+
+        return 0;
+    }
+
+    /* if already advertising, data must fit in single HCI command */
+    if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
+        if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) {
+            return EINVAL;
+        }
+    }
+
+    /* not allowed with scannable advertising */
+    if (ble_gap_slave[instance].scannable) {
+        return BLE_HS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf *data)
+{
+    /* in that case we always fit all data in single HCI command */
+#if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_EXT_ADV_DATA_LEN
+    static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \
+                       MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
+    uint16_t len = OS_MBUF_PKTLEN(data);
+    int rc;
+
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
+
+    rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
+                                    BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE,
+                                    0, data, len, buf, sizeof(buf));
+    if (rc) {
+        return rc;
+    }
+
+    return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
+                                       BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len);
+#else
+    static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \
+                       BLE_HCI_MAX_EXT_ADV_DATA_LEN];
+    uint16_t len = OS_MBUF_PKTLEN(data);
+    uint16_t off = 0;
+    uint8_t op;
+    int rc;
+
+    opcode =  BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
+
+    /* complete data */
+    if (len <= BLE_HCI_MAX_EXT_ADV_DATA_LEN) {
+        rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
+                                    BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE,
+                                    0, data, len, buf,sizeof(buf));
+        if (rc) {
+            return rc;
+        }
+
+        return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
+                                        BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len);
+    }
+
+    /* first fragment  */
+    op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST;
+
+    do {
+        rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, op, 0, data,
+                                                  BLE_HCI_MAX_EXT_ADV_DATA_LEN,
+                                                  buf, sizeof(buf));
+        if (rc) {
+            return rc;
+        }
+        rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
+        if (rc) {
+            return rc;
+        }
+
+        len -= BLE_HCI_MAX_EXT_ADV_DATA_LEN;
+        off += BLE_HCI_MAX_EXT_ADV_DATA_LEN;
+        op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT;
+    } while (len > BLE_HCI_MAX_EXT_ADV_DATA_LEN);
+
+    /* last fragment */
+    rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance,
+                                        BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST,
+                                        0, data, len, buf, sizeof(buf));
+    if (rc) {
+        return rc;
+    }
+
+    return ble_hs_hci_cmd_tx_empty_ack(opcode, buf,
+                                       BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len);
+#endif
+}
+
+int
+ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data)
+{
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    rc = ble_gap_ext_adv_set_data_validate(instance, data);
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_ADV_DATA, data);
+
+    ble_hs_unlock();
+
+    return rc;
+}
+
+static int
+ble_gap_ext_adv_rsp_set_validate(uint8_t instance,  struct os_mbuf *data)
+{
+    uint16_t len = OS_MBUF_PKTLEN(data);
+
+    if (!ble_gap_slave[instance].configured) {
+        return BLE_HS_EINVAL;
+    }
+
+    /* not allowed with directed advertising */
+    if (ble_gap_slave[instance].directed) {
+        return BLE_HS_EINVAL;
+    }
+
+    /* only allowed with scannable advertising */
+    if (!ble_gap_slave[instance].scannable) {
+        return BLE_HS_EINVAL;
+    }
+
+    /* with legacy PDU limited to legacy length */
+    if (ble_gap_slave[instance].legacy_pdu) {
+        if (len > BLE_HS_ADV_MAX_SZ) {
+            return BLE_HS_EINVAL;
+        }
+
+        return 0;
+    }
+
+    /* if already advertising, data must fit in single HCI command */
+    if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
+        if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) {
+            return EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+int
+ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data)
+{
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    rc = ble_gap_ext_adv_rsp_set_validate(instance, data);
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA,
+                             data);
+
+    ble_hs_unlock();
+
+    return rc;
+}
+
+int
+ble_gap_ext_adv_remove(uint8_t instance)
+{
+    uint8_t buf[BLE_HCI_LE_REMOVE_ADV_SET_LEN];
+    uint16_t opcode;
+    int rc;
+
+    if (instance >= BLE_ADV_INSTANCES) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    if (!ble_gap_slave[instance].configured) {
+        ble_hs_unlock();
+        return BLE_HS_EALREADY;
+    }
+
+    if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
+        ble_hs_unlock();
+        return BLE_HS_EBUSY;
+    }
+
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REMOVE_ADV_SET);
+
+    rc = ble_hs_hci_cmd_build_le_ext_adv_remove(instance, buf, sizeof(buf));
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
+    if (rc != 0) {
+        ble_hs_unlock();
+        return rc;
+    }
+
+    memset(&ble_gap_slave[instance], 0, sizeof(struct ble_gap_slave_state));
+    ble_hs_unlock();
+
+    return 0;
+}
+
+#endif
+
+/*****************************************************************************
+ * $discovery procedures                                                     *
+ *****************************************************************************/
+
+#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
+static int
+ble_gap_ext_disc_tx_params(uint8_t own_addr_type, uint8_t filter_policy,
+                       const struct ble_hs_hci_ext_scan_param *uncoded_params,
+                       const struct ble_hs_hci_ext_scan_param *coded_params)
+{
+    uint8_t buf[BLE_HCI_LE_EXT_SCAN_BASE_LEN +
+                2 * BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN];
+    uint8_t phy_mask = 0;
+    struct ble_hs_hci_ext_scan_param param[2] = {{0}};
+    struct ble_hs_hci_ext_scan_param *p = param;
+    int phy_count = 0;
+    uint8_t len;
+    int rc;
+
+    if (uncoded_params) {
+        phy_mask |= BLE_HCI_LE_PHY_1M_PREF_MASK;
+        memcpy(&param[phy_count], uncoded_params, sizeof(*uncoded_params));
+        phy_count++;
+    }
+
+    if (coded_params) {
         phy_mask |= BLE_HCI_LE_PHY_CODED_PREF_MASK;
         memcpy(&param[phy_count], coded_params, sizeof(*coded_params));
         phy_count++;
@@ -4323,19 +4776,30 @@ void
 ble_gap_preempt(void)
 {
     int rc;
+    int i;
 
     (void)rc;
+    (void) i;
 
     ble_hs_lock();
 
     BLE_HS_DBG_ASSERT(!ble_gap_is_preempted());
 
 #if NIMBLE_BLE_ADVERTISE
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+        rc = ble_gap_ext_adv_stop_no_lock(i);
+        if (rc == 0) {
+            ble_gap_slave[i].preempted = 1;
+        }
+    }
+#else
     rc = ble_gap_adv_stop_no_lock();
     if (rc == 0) {
         ble_gap_slave[0].preempted = 1;
     }
 #endif
+#endif
 
 #if NIMBLE_BLE_CONNECT
     rc = ble_gap_conn_cancel_no_lock();
@@ -4359,27 +4823,36 @@ ble_gap_preempt(void)
  * initiaited.  This function should only be called after a call to
  * `ble_gap_preempt()`.
  */
+
+static struct os_mutex preempt_done_mutex;
+
 void
 ble_gap_preempt_done(void)
 {
     struct ble_gap_event event;
     ble_gap_event_fn *master_cb;
-    ble_gap_event_fn *slave_cb;
     void *master_arg;
-    void *slave_arg;
     int disc_preempted;
-    int adv_preempted;
+    int i;
+    static struct {
+        ble_gap_event_fn *cb;
+        void *arg;
+    } slaves[BLE_ADV_INSTANCES];
 
-    adv_preempted = 0;
     disc_preempted = 0;
 
+    /* protects slaves from accessing by multiple threads */
+    os_mutex_pend(&preempt_done_mutex, 0xFFFFFFFF);
+    memset(slaves, 0, sizeof(slaves));
+
     ble_hs_lock();
 
-    if (ble_gap_slave[0].preempted) {
-        ble_gap_slave[0].preempted = 0;
-        adv_preempted = 1;
-        slave_cb = ble_gap_slave[0].cb;
-        slave_arg = ble_gap_slave[0].cb_arg;
+    for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+        if (ble_gap_slave[i].preempted) {
+            ble_gap_slave[i].preempted = 0;
+            slaves[i].cb = ble_gap_slave[i].cb;
+            slaves[i].arg = ble_gap_slave[i].cb_arg;
+        }
     }
 
     if (ble_gap_master.preempted_op == BLE_GAP_OP_M_DISC) {
@@ -4391,11 +4864,19 @@ ble_gap_preempt_done(void)
 
     ble_hs_unlock();
 
-    if (adv_preempted) {
-        event.type = BLE_GAP_EVENT_ADV_COMPLETE;
-        event.adv_complete.reason = BLE_HS_EPREEMPTED;
-        ble_gap_call_event_cb(&event, slave_cb, slave_arg);
+    event.type = BLE_GAP_EVENT_ADV_COMPLETE;
+    event.adv_complete.reason = BLE_HS_EPREEMPTED;
+
+    for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+        if (slaves[i].cb) {
+#if MYNEWT_VAL(BLE_EXT_ADV)
+            event.adv_complete.instance = i;
+            event.adv_complete.conn_handle = i;
+#endif
+            ble_gap_call_event_cb(&event, slaves[i].cb, slaves[i].arg);
+        }
     }
+    os_mutex_release(&preempt_done_mutex);
 
     if (disc_preempted) {
         event.type = BLE_GAP_EVENT_DISC_COMPLETE;
@@ -4418,6 +4899,8 @@ ble_gap_init(void)
     memset(&ble_gap_master, 0, sizeof ble_gap_master);
     memset(ble_gap_slave, 0, sizeof ble_gap_slave);
 
+    os_mutex_init(&preempt_done_mutex);
+
     SLIST_INIT(&ble_gap_update_entries);
 
     rc = mem_malloc_mempool(&ble_gap_update_entry_pool,
diff --git a/net/nimble/host/src/ble_gap_priv.h b/net/nimble/host/src/ble_gap_priv.h
index f90c1a01d..1da9aa7aa 100644
--- a/net/nimble/host/src/ble_gap_priv.h
+++ b/net/nimble/host/src/ble_gap_priv.h
@@ -77,10 +77,11 @@ extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
 
 #if MYNEWT_VAL(BLE_EXT_ADV)
 void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc);
+void ble_gap_rx_adv_set_terminated(struct hci_le_adv_set_terminated *evt);
 #endif
 void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
 void ble_gap_rx_rd_rem_sup_feat_complete(struct hci_le_rd_rem_supp_feat_complete *evt);
-int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt);
+int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt, uint8_t instance);
 void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
 void ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt);
 void ble_gap_rx_param_req(struct hci_le_conn_param_req *evt);
diff --git a/net/nimble/host/src/ble_hs_adv.c b/net/nimble/host/src/ble_hs_adv.c
index 026603bbb..7f1517c7c 100644
--- a/net/nimble/host/src/ble_hs_adv.c
+++ b/net/nimble/host/src/ble_hs_adv.c
@@ -34,8 +34,21 @@ static ble_uuid128_t ble_hs_adv_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16];
 
 static int
 ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len,
-                   uint8_t *dst, uint8_t *dst_len)
+                   uint8_t *dst, uint8_t *dst_len, struct os_mbuf *om)
 {
+    int rc;
+
+    if (om ) {
+        data_len++;
+        rc = os_mbuf_append(om, &data_len, sizeof(data_len));
+        if (rc) {
+            return rc;
+        }
+
+        return os_mbuf_append(om, &type, sizeof(type));
+    }
+
+
     if (*dst_len + 2 + data_len > max_len) {
         return BLE_HS_EMSGSIZE;
     }
@@ -48,46 +61,67 @@ ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len,
     return 0;
 }
 
-int
-ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data,
-                    uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
+static int
+ble_hs_adv_set_flat_mbuf(uint8_t type, int data_len, const void *data,
+                    uint8_t *dst, uint8_t *dst_len, uint8_t max_len,
+                    struct os_mbuf *om)
 {
-#if !NIMBLE_BLE_ADVERTISE
-    return BLE_HS_ENOTSUP;
-#endif
-
     int rc;
 
     BLE_HS_DBG_ASSERT(data_len > 0);
 
-    rc = ble_hs_adv_set_hdr(type, data_len, max_len, dst, dst_len);
+    rc = ble_hs_adv_set_hdr(type, data_len, max_len, dst, dst_len, om);
     if (rc != 0) {
         return rc;
     }
 
+    if (om) {
+        return os_mbuf_append(om, data, data_len);
+    }
+
     memcpy(dst + *dst_len, data, data_len);
     *dst_len += data_len;
 
     return 0;
 }
 
+int
+ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data,
+                    uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
+{
+#if !NIMBLE_BLE_ADVERTISE
+    return BLE_HS_ENOTSUP;
+#endif
+
+    return ble_hs_adv_set_flat_mbuf(type, data_len, data, dst, dst_len, max_len,
+                                    NULL);
+}
+
 static int
 ble_hs_adv_set_array_uuid16(uint8_t type, uint8_t num_elems,
                             const ble_uuid16_t *elems, uint8_t *dst,
-                            uint8_t *dst_len, uint8_t max_len)
+                            uint8_t *dst_len, uint8_t max_len,
+                            struct os_mbuf *om)
 {
     int rc;
     int i;
 
     rc = ble_hs_adv_set_hdr(type, num_elems * 2, max_len, dst,
-                            dst_len);
+                            dst_len, om);
     if (rc != 0) {
         return rc;
     }
 
     for (i = 0; i < num_elems; i++) {
-        ble_uuid_flat(&elems[i].u, dst + *dst_len);
-        *dst_len += 2;
+        if (om) {
+            rc = ble_uuid_to_mbuf(&elems[i].u, om);
+            if (rc) {
+                return rc;
+            }
+        } else {
+            ble_uuid_flat(&elems[i].u, dst + *dst_len);
+            *dst_len += 2;
+        }
     }
 
     return 0;
@@ -96,13 +130,15 @@ ble_hs_adv_set_array_uuid16(uint8_t type, uint8_t num_elems,
 static int
 ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems,
                             const ble_uuid32_t *elems, uint8_t *dst,
-                            uint8_t *dst_len, uint8_t max_len)
+                            uint8_t *dst_len, uint8_t max_len,
+                            struct os_mbuf *om)
 {
+    uint32_t uuid_le;
     int rc;
     int i;
 
     rc = ble_hs_adv_set_hdr(type, num_elems * 4, max_len, dst,
-                            dst_len);
+                            dst_len, om);
     if (rc != 0) {
         return rc;
     }
@@ -112,8 +148,16 @@ ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems,
          * 128-bit as ATT requires. In AD, 32-bit UUID shall be written as an
          * actual 32-bit value.
          */
-        put_le32(dst + *dst_len, elems[i].value);
-        *dst_len += 4;
+        if (om) {
+            uuid_le = htole32(elems[i].value);
+            rc = os_mbuf_append(om, &uuid_le, sizeof(uuid_le));
+            if (rc) {
+                return rc;
+            }
+        } else {
+            put_le32(dst + *dst_len, elems[i].value);
+            *dst_len += 4;
+        }
     }
 
     return 0;
@@ -122,20 +166,28 @@ ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems,
 static int
 ble_hs_adv_set_array_uuid128(uint8_t type, uint8_t num_elems,
                              const ble_uuid128_t *elems, uint8_t *dst,
-                             uint8_t *dst_len, uint8_t max_len)
+                             uint8_t *dst_len, uint8_t max_len,
+                             struct os_mbuf *om)
 {
     int rc;
     int i;
 
     rc = ble_hs_adv_set_hdr(type, num_elems * 16, max_len, dst,
-                            dst_len);
+                            dst_len, om);
     if (rc != 0) {
         return rc;
     }
 
     for (i = 0; i < num_elems; i++) {
-        ble_uuid_flat(&elems[i].u, dst + *dst_len);
-        *dst_len += 16;
+        if (om) {
+            rc = ble_uuid_to_mbuf(&elems[i].u, om);
+            if (rc) {
+                return rc;
+            }
+        } else {
+            ble_uuid_flat(&elems[i].u, dst + *dst_len);
+            *dst_len += 16;
+        }
     }
 
     return 0;
@@ -143,33 +195,39 @@ ble_hs_adv_set_array_uuid128(uint8_t type, uint8_t num_elems,
 
 static int
 ble_hs_adv_set_array16(uint8_t type, uint8_t num_elems, const uint16_t *elems,
-                       uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
+                       uint8_t *dst, uint8_t *dst_len, uint8_t max_len,
+                       struct os_mbuf *om)
 {
+    uint16_t tmp;
     int rc;
     int i;
 
     rc = ble_hs_adv_set_hdr(type, num_elems * sizeof *elems, max_len, dst,
-                            dst_len);
+                            dst_len, om);
     if (rc != 0) {
         return rc;
     }
 
     for (i = 0; i < num_elems; i++) {
-        put_le16(dst + *dst_len, elems[i]);
-        *dst_len += sizeof elems[i];
+        if (om) {
+            tmp = htole16(elems[i]);
+            rc = os_mbuf_append(om, &tmp, sizeof(tmp));
+            if (rc) {
+                return rc;
+            }
+        } else {
+            put_le16(dst + *dst_len, elems[i]);
+            *dst_len += sizeof elems[i];
+        }
     }
 
     return 0;
 }
 
-/**
- * Converts a high-level set of fields to a byte buffer.
- *
- * @return                      0 on success; nonzero on failure.
- */
-int
-ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
-                      uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
+static int
+adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
+                      uint8_t *dst, uint8_t *dst_len, uint8_t max_len,
+                      struct os_mbuf *om)
 {
 #if !NIMBLE_BLE_ADVERTISE
     return BLE_HS_ENOTSUP;
@@ -179,7 +237,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
     int8_t tx_pwr_lvl;
     int rc;
 
-    *dst_len = 0;
+    if (dst_len) {
+        *dst_len = 0;
+    }
 
     /*** 0x01 - Flags. */
     /* The application has two options concerning the flags field:
@@ -190,8 +250,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
      * of specifying option 1 vs. 2 is sound.
      */
     if (adv_fields->flags != 0) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &adv_fields->flags,
-                                 dst, dst_len, max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_FLAGS, 1,
+                                      &adv_fields->flags, dst, dst_len,
+                                      max_len, om);
 
         if (rc != 0) {
             return rc;
@@ -208,7 +269,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
         rc = ble_hs_adv_set_array_uuid16(type, adv_fields->num_uuids16,
                                          adv_fields->uuids16, dst, dst_len,
-                                         max_len);
+                                         max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -224,7 +285,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
         rc = ble_hs_adv_set_array_uuid32(type, adv_fields->num_uuids32,
                                          adv_fields->uuids32, dst, dst_len,
-                                         max_len);
+                                         max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -240,7 +301,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
         rc = ble_hs_adv_set_array_uuid128(type, adv_fields->num_uuids128,
                                           adv_fields->uuids128, dst, dst_len,
-                                          max_len);
+                                          max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -254,8 +315,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
             type = BLE_HS_ADV_TYPE_INCOMP_NAME;
         }
 
-        rc = ble_hs_adv_set_flat(type, adv_fields->name_len, adv_fields->name,
-                                 dst, dst_len, max_len);
+        rc = ble_hs_adv_set_flat_mbuf(type, adv_fields->name_len,
+                                      adv_fields->name, dst, dst_len, max_len,
+                                      om);
         if (rc != 0) {
             return rc;
         }
@@ -275,8 +337,8 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
             tx_pwr_lvl = adv_fields->tx_pwr_lvl;
         }
 
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1, &tx_pwr_lvl,
-                                 dst, dst_len, max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1,
+                                      &tx_pwr_lvl, dst, dst_len, max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -284,10 +346,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x12 - Slave connection interval range. */
     if (adv_fields->slave_itvl_range != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE,
-                                 BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN,
-                                 adv_fields->slave_itvl_range, dst, dst_len,
-                                 max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE,
+                                      BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN,
+                                      adv_fields->slave_itvl_range, dst,
+                                      dst_len, max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -295,10 +357,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x16 - Service data - 16-bit UUID. */
     if (adv_fields->svc_data_uuid16 != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID16,
-                                 adv_fields->svc_data_uuid16_len,
-                                 adv_fields->svc_data_uuid16, dst, dst_len,
-                                 max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID16,
+                                      adv_fields->svc_data_uuid16_len,
+                                      adv_fields->svc_data_uuid16, dst, dst_len,
+                                      max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -308,11 +370,11 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
     if (adv_fields->public_tgt_addr != NULL &&
         adv_fields->num_public_tgt_addrs != 0) {
 
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR,
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR,
                                  BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN *
                                      adv_fields->num_public_tgt_addrs,
                                  adv_fields->public_tgt_addr, dst, dst_len,
-                                 max_len);
+                                 max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -320,10 +382,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x19 - Appearance. */
     if (adv_fields->appearance_is_present) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_APPEARANCE,
-                                 BLE_HS_ADV_APPEARANCE_LEN,
-                                 &adv_fields->appearance, dst, dst_len,
-                                 max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_APPEARANCE,
+                                      BLE_HS_ADV_APPEARANCE_LEN,
+                                      &adv_fields->appearance, dst, dst_len,
+                                      max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -333,7 +395,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
     if (adv_fields->adv_itvl_is_present) {
         rc = ble_hs_adv_set_array16(BLE_HS_ADV_TYPE_ADV_ITVL, 1,
                                     &adv_fields->adv_itvl, dst, dst_len,
-                                    max_len);
+                                    max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -341,10 +403,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x20 - Service data - 32-bit UUID. */
     if (adv_fields->svc_data_uuid32 != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID32,
-                                 adv_fields->svc_data_uuid32_len,
-                                 adv_fields->svc_data_uuid32, dst, dst_len,
-                                 max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID32,
+                                     adv_fields->svc_data_uuid32_len,
+                                     adv_fields->svc_data_uuid32, dst, dst_len,
+                                     max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -352,10 +414,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x21 - Service data - 128-bit UUID. */
     if (adv_fields->svc_data_uuid128 != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID128,
-                                 adv_fields->svc_data_uuid128_len,
-                                 adv_fields->svc_data_uuid128, dst, dst_len,
-                                 max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID128,
+                                      adv_fields->svc_data_uuid128_len,
+                                      adv_fields->svc_data_uuid128, dst,
+                                      dst_len, max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -363,8 +425,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0x24 - URI. */
     if (adv_fields->uri != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_URI, adv_fields->uri_len,
-                                 adv_fields->uri, dst, dst_len, max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_URI, adv_fields->uri_len,
+                                      adv_fields->uri, dst, dst_len, max_len,
+                                      om);
         if (rc != 0) {
             return rc;
         }
@@ -372,9 +435,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
 
     /*** 0xff - Manufacturer specific data. */
     if (adv_fields->mfg_data != NULL) {
-        rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_MFG_DATA,
-                                 adv_fields->mfg_data_len,
-                                 adv_fields->mfg_data, dst, dst_len, max_len);
+        rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_MFG_DATA,
+                                      adv_fields->mfg_data_len,
+                                      adv_fields->mfg_data,
+                                      dst, dst_len, max_len, om);
         if (rc != 0) {
             return rc;
         }
@@ -383,6 +447,32 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
     return 0;
 }
 
+/**
+ * Converts a high-level set of fields to a byte buffer.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int
+ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
+                      uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
+{
+#if !NIMBLE_BLE_ADVERTISE
+    return BLE_HS_ENOTSUP;
+#endif
+
+    return adv_set_fields(adv_fields, dst, dst_len, max_len, NULL);
+}
+
+int
+ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
+                           struct os_mbuf *om)
+{
+#if !NIMBLE_BLE_ADVERTISE
+    return BLE_HS_ENOTSUP;
+#endif
+    return adv_set_fields(adv_fields, NULL, NULL, 0, om);
+}
+
 static int
 ble_hs_adv_parse_uuids16(struct ble_hs_adv_fields *adv_fields,
                          const uint8_t *data, uint8_t data_len)
diff --git a/net/nimble/host/src/ble_hs_hci_cmd.c b/net/nimble/host/src/ble_hs_hci_cmd.c
index f43e7a911..9cd732659 100644
--- a/net/nimble/host/src/ble_hs_hci_cmd.c
+++ b/net/nimble/host/src/ble_hs_hci_cmd.c
@@ -1471,8 +1471,8 @@ ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,
 
 int
 ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
-                                     uint8_t frag_pref,
-                                     const uint8_t *data, uint8_t data_len,
+                                     uint8_t frag_pref, struct os_mbuf *data,
+                                     uint8_t data_len,
                                      uint8_t *cmd, int cmd_len)
 {
     BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len);
@@ -1481,24 +1481,7 @@ ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
     cmd[1] = operation;
     cmd[2] = frag_pref;
     cmd[3] = data_len;
-    memcpy(cmd + 4, data, data_len);
-
-    return 0;
-}
-
-int
-ble_hs_hci_cmd_build_le_ext_adv_scan_rsp(uint8_t handle, uint8_t operation,
-                                         uint8_t frag_pref,
-                                         const uint8_t *data, uint8_t data_len,
-                                         uint8_t *cmd, int cmd_len)
-{
-    BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len);
-
-    cmd[0] = handle;
-    cmd[1] = operation;
-    cmd[2] = frag_pref;
-    cmd[3] = data_len;
-    memcpy(cmd + 4, data, data_len);
+    os_mbuf_copydata(data, 0, data_len, cmd + 4);
 
     return 0;
 }
@@ -1560,6 +1543,16 @@ ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
 
     return 0;
 }
+int
+ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
+                                       uint8_t *cmd, int cmd_len)
+{
+    BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_REMOVE_ADV_SET_LEN);
+
+    cmd[0] = handle;
+
+    return 0;
+}
 #endif
 
 static int
diff --git a/net/nimble/host/src/ble_hs_hci_evt.c b/net/nimble/host/src/ble_hs_hci_evt.c
index c5c8b8d62..4f7881271 100644
--- a/net/nimble/host/src/ble_hs_hci_evt.c
+++ b/net/nimble/host/src/ble_hs_hci_evt.c
@@ -50,6 +50,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
 static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete;
 static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt;
 static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_rem_used_feat_complete;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_set_terminated;
 
 /* Statistics */
 struct host_hci_stats
@@ -101,6 +102,8 @@ static const struct ble_hs_hci_evt_le_dispatch_entry
     { BLE_HCI_LE_SUBEV_EXT_ADV_RPT, ble_hs_hci_evt_le_ext_adv_rpt },
     { BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT,
             ble_hs_hci_evt_le_rd_rem_used_feat_complete },
+    { BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED,
+            ble_hs_hci_evt_le_adv_set_terminated },
 };
 
 #define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
@@ -300,12 +303,15 @@ ble_hs_hci_evt_le_meta(uint8_t event_code, uint8_t *data, int len)
     return 0;
 }
 
+#if MYNEWT_VAL(BLE_EXT_ADV)
+static struct hci_le_conn_complete pend_conn_complete;
+#endif
+
 static int
 ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
 {
     struct hci_le_conn_complete evt;
     int extended_offset = 0;
-    int rc;
 
     if (len < BLE_HCI_LE_CONN_COMPLETE_LEN) {
         return BLE_HS_ECONTROLLER;
@@ -348,12 +354,14 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
         }
     }
 
-    rc = ble_gap_rx_conn_complete(&evt);
-    if (rc != 0) {
-        return rc;
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    if (evt.role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) {
+    /* store this until we get set terminated event with adv handle */
+        memcpy(&pend_conn_complete, &evt, sizeof(evt));
+        return 0;
     }
-
-    return 0;
+#endif
+    return ble_gap_rx_conn_complete(&evt, 0xff);
 }
 
 static int
@@ -594,6 +602,32 @@ ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, uint8_t *data, int len)
     return 0;
 }
 
+static int
+ble_hs_hci_evt_le_adv_set_terminated(uint8_t subevent, uint8_t *data, int len)
+{
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    struct hci_le_adv_set_terminated evt;
+
+    if (len < BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED_LEN) {
+        return BLE_HS_ECONTROLLER;
+    }
+
+    evt.subevent_code = data[0];
+    evt.status = data[1];
+    evt.adv_handle = data[2];
+    evt.conn_handle = get_le16(data + 3);
+    evt.completed_events = data[5];
+
+    if (evt.status == 0) {
+        /* ignore return code as we need to terminate advertising set anyway */
+        ble_gap_rx_conn_complete(&pend_conn_complete, evt.adv_handle);
+    }
+    ble_gap_rx_adv_set_terminated(&evt);
+#endif
+
+    return 0;
+}
+
 static int
 ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
 {
diff --git a/net/nimble/host/src/ble_hs_hci_priv.h b/net/nimble/host/src/ble_hs_hci_priv.h
index 85b98b90a..45f95ac54 100644
--- a/net/nimble/host/src/ble_hs_hci_priv.h
+++ b/net/nimble/host/src/ble_hs_hci_priv.h
@@ -212,20 +212,12 @@ ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,
                                                 const uint8_t *addr,
                                                 uint8_t *cmd, int cmd_len);
 
-
-
 int
 ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
-                                     uint8_t frag_pref,
-                                     const uint8_t *data, uint8_t data_len,
+                                     uint8_t frag_pref, struct os_mbuf *data,
+                                     uint8_t data_len,
                                      uint8_t *cmd, int cmd_len);
 
-int
-ble_hs_hci_cmd_build_le_ext_adv_scan_rsp(uint8_t handle, uint8_t operation,
-                                         uint8_t frag_pref,
-                                         const uint8_t *data, uint8_t data_len,
-                                         uint8_t *cmd, int cmd_len);
-
 int
 ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable, uint8_t sets_num,
                                        const struct hci_ext_adv_set *sets,
@@ -235,6 +227,10 @@ int
 ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
                                        const struct hci_ext_adv_params *params,
                                        uint8_t *cmd, int cmd_len);
+
+int
+ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
+                                       uint8_t *cmd, int cmd_len);
 #endif
 
 int ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan, uint8_t phy,
diff --git a/net/nimble/host/src/ble_hs_hci_util.c b/net/nimble/host/src/ble_hs_hci_util.c
index ca6c2409a..f210ee7ba 100644
--- a/net/nimble/host/src/ble_hs_hci_util.c
+++ b/net/nimble/host/src/ble_hs_hci_util.c
@@ -126,12 +126,7 @@ ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
 int
 ble_hs_hci_util_set_random_addr(const uint8_t *addr)
 {
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    /* this buffer is larger and can handle both commands */
-    uint8_t buf[BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN];
-#else
     uint8_t buf[BLE_HCI_SET_RAND_ADDR_LEN];
-#endif
     int rc;
 
     /* set the address in the controller */
@@ -148,25 +143,6 @@ ble_hs_hci_util_set_random_addr(const uint8_t *addr)
         return rc;
     }
 
-#if MYNEWT_VAL(BLE_EXT_ADV)
-    /* TODO
-     * Since we currently support only 1 instance we can set random address
-     * here. For now advertising handle is hardcoded.
-     */
-    rc = ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(0, addr, buf,
-                                                         sizeof(buf));
-    if (rc != 0) {
-        return rc;
-    }
-
-    rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
-                                           BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR),
-                                     buf, sizeof(buf));
-    if (rc != 0) {
-        return rc;
-    }
-#endif
-
     return 0;
 }
 
diff --git a/net/nimble/host/test/src/ble_gap_test.c b/net/nimble/host/test/src/ble_gap_test.c
index 1e510a78d..00cb34571 100644
--- a/net/nimble/host/test/src/ble_gap_test.c
+++ b/net/nimble/host/test/src/ble_gap_test.c
@@ -860,7 +860,7 @@ TEST_CASE(ble_gap_test_case_conn_gen_good)
     evt.connection_handle = 2;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
     memcpy(evt.peer_addr, peer_addr.val, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
@@ -1008,7 +1008,7 @@ TEST_CASE(ble_gap_test_case_conn_gen_fail_evt)
     evt.status = BLE_ERR_CONN_ACCEPT_TMO;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
 
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT_FATAL(rc == 0);
 
     /* Ensure failed connect was reported to application. */
@@ -1055,7 +1055,7 @@ ble_gap_test_util_conn_cancel(uint8_t hci_status)
     memset(&evt, 0, sizeof evt);
     evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
     evt.status = BLE_ERR_UNK_CONN_ID;
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
 
@@ -1134,7 +1134,7 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
     evt.connection_handle = 2;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
     memcpy(evt.peer_addr, peer_addr, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
@@ -1492,7 +1492,7 @@ ble_gap_test_util_adv(uint8_t own_addr_type,
             evt.connection_handle = 2;
             evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
             memcpy(evt.peer_addr, peer_addr->val, 6);
-            rc = ble_gap_rx_conn_complete(&evt);
+            rc = ble_gap_rx_conn_complete(&evt, 0);
             TEST_ASSERT(rc == 0);
 
             if (connect_status == 0 ||
@@ -2773,7 +2773,7 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
     memset(&evt, 0, sizeof evt);
     evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
     evt.status = BLE_ERR_UNK_CONN_ID;
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT_FATAL(rc == 0);
 
     /* Ensure the GAP event was triggered. */
diff --git a/net/nimble/host/test/src/ble_hs_conn_test.c b/net/nimble/host/test/src/ble_hs_conn_test.c
index 44f0c958c..4c5d46887 100644
--- a/net/nimble/host/test/src/ble_hs_conn_test.c
+++ b/net/nimble/host/test/src/ble_hs_conn_test.c
@@ -70,7 +70,7 @@ TEST_CASE(ble_hs_conn_test_direct_connect_success)
     evt.connection_handle = 2;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
     memcpy(evt.peer_addr, addr.val, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
 
@@ -127,7 +127,7 @@ TEST_CASE(ble_hs_conn_test_direct_connectable_success)
     evt.connection_handle = 2;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
     memcpy(evt.peer_addr, addr.val, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
     TEST_ASSERT(!ble_gap_adv_active());
@@ -192,7 +192,7 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
     evt.connection_handle = 2;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
     memcpy(evt.peer_addr, addr.val, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
     TEST_ASSERT(!ble_gap_adv_active());
diff --git a/net/nimble/host/test/src/ble_hs_test_util.c b/net/nimble/host/test/src/ble_hs_test_util.c
index b6972d160..ba9dd5ee3 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.c
+++ b/net/nimble/host/test/src/ble_hs_test_util.c
@@ -242,7 +242,7 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
     memcpy(evt.local_rpa, our_rpa, 6);
     memcpy(evt.peer_rpa, peer_rpa, 6);
 
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
 
     evt2.subevent_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
diff --git a/net/nimble/host/test/src/ble_hs_test_util_hci.c b/net/nimble/host/test/src/ble_hs_test_util_hci.c
index 32548c666..6be161f1b 100644
--- a/net/nimble/host/test/src/ble_hs_test_util_hci.c
+++ b/net/nimble/host/test/src/ble_hs_test_util_hci.c
@@ -539,7 +539,7 @@ ble_hs_test_util_hci_rx_conn_cancel_evt(void)
     evt.status = BLE_ERR_UNK_CONN_ID;
     evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
 
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT_FATAL(rc == 0);
 }
 
diff --git a/net/nimble/host/test/src/ble_os_test.c b/net/nimble/host/test/src/ble_os_test.c
index cd39556c6..e8968b51d 100644
--- a/net/nimble/host/test/src/ble_os_test.c
+++ b/net/nimble/host/test/src/ble_os_test.c
@@ -154,7 +154,7 @@ ble_gap_direct_connect_test_task_handler(void *arg)
     evt.status = BLE_ERR_SUCCESS;
     evt.connection_handle = 2;
     memcpy(evt.peer_addr, addr.val, 6);
-    rc = ble_gap_rx_conn_complete(&evt);
+    rc = ble_gap_rx_conn_complete(&evt, 0);
     TEST_ASSERT(rc == 0);
 
     /* The connection should now be created. */
@@ -316,7 +316,7 @@ ble_gap_terminate_test_task_handler(void *arg)
     conn_evt.status = BLE_ERR_SUCCESS;
     conn_evt.connection_handle = 1;
     memcpy(conn_evt.peer_addr, addr1.val, 6);
-    rc = ble_gap_rx_conn_complete(&conn_evt);
+    rc = ble_gap_rx_conn_complete(&conn_evt, 0);
     TEST_ASSERT(rc == 0);
 
     ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
@@ -330,7 +330,7 @@ ble_gap_terminate_test_task_handler(void *arg)
     conn_evt.status = BLE_ERR_SUCCESS;
     conn_evt.connection_handle = 2;
     memcpy(conn_evt.peer_addr, addr2.val, 6);
-    rc = ble_gap_rx_conn_complete(&conn_evt);
+    rc = ble_gap_rx_conn_complete(&conn_evt, 0);
     TEST_ASSERT(rc == 0);
 
     TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(1));
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 31b0c6cc8..e14137d14 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -491,6 +491,9 @@ extern "C" {
 #define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN  (0x0010)
 
 /* --- LE set extended advertising data (OCF 0x0037) */
+#define BLE_HCI_MAX_EXT_ADV_DATA_LEN                (251)
+#define BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN            (4)
+
 #define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN             BLE_HCI_VARIABLE_LEN
 #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT        (0)
 #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST      (1)
@@ -499,6 +502,9 @@ extern "C" {
 #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED  (4)
 
 /* --- LE set extended scan response data (OCF 0x0038) */
+#define BLE_HCI_MAX_EXT_SCAN_RSP_DATA_LEN           (251)
+#define BLE_HCI_SET_EXT_SCAN_RSP_DATA_HDR_LEN       (4)
+
 #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN        BLE_HCI_VARIABLE_LEN
 #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT        (0)
 #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST      (1)
@@ -1046,6 +1052,16 @@ struct hci_le_phy_upd_complete
     uint8_t rx_phy;
 };
 
+/* LE Advertising Set Terminated subevent*/
+struct hci_le_adv_set_terminated
+{
+    uint8_t subevent_code;
+    uint8_t status;
+    uint8_t adv_handle;
+    uint16_t conn_handle;
+    uint8_t completed_events;
+};
+
 #define BLE_HCI_DATA_HDR_SZ                 4
 #define BLE_HCI_DATA_HANDLE(handle_pb_bc)   (((handle_pb_bc) & 0x0fff) >> 0)
 #define BLE_HCI_DATA_PB(handle_pb_bc)       (((handle_pb_bc) & 0x3000) >> 12)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services