You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2021/11/02 11:54:59 UTC

[mynewt-nimble] 04/09: nimble/ll: Refactor conn init param handling

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit df6ac21d2f3a5d845dd490dbdd148628d030e2e1
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Tue Oct 19 17:55:49 2021 +0200

    nimble/ll: Refactor conn init param handling
    
    This fixes handling of parameters used for conn init.
    
    Firstly, we only need conn init params when intiating new connection so
    we can have single, global instance of that params - no need to store
    them in conns. This saves 72 bytes of RAM per connsm.
    
    Secondly, we do not need to store all parameters from HCI command since
    some of them are only used to initialize scanner and those can be used
    immediately. We only need to store connection parameters for ext conn
    create.
    
    This also allows to share more code between legacy and ext conn create
    code paths.
---
 nimble/controller/include/controller/ble_ll_conn.h |  27 --
 nimble/controller/include/controller/ble_ll_scan.h |  13 +-
 nimble/controller/include/controller/ble_phy.h     |   5 +
 nimble/controller/src/ble_ll.c                     |   2 +-
 nimble/controller/src/ble_ll_conn.c                | 147 +++----
 nimble/controller/src/ble_ll_conn_hci.c            | 464 ++++++++++-----------
 nimble/controller/src/ble_ll_conn_priv.h           |  52 ++-
 nimble/controller/src/ble_ll_hci.c                 |   4 +-
 nimble/controller/src/ble_ll_resolv.c              |   2 +-
 nimble/controller/src/ble_ll_scan.c                |  81 ++--
 10 files changed, 353 insertions(+), 444 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index 7be3a43..0de54af 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -188,29 +188,6 @@ struct hci_conn_update
     uint16_t max_ce_len;
 };
 
-struct hci_ext_conn_params
-{
-    uint16_t scan_itvl;
-    uint16_t scan_window;
-    uint32_t conn_itvl;
-    uint16_t conn_itvl_ticks;
-    uint8_t conn_itvl_usecs;
-    uint16_t conn_latency;
-    uint16_t supervision_timeout;
-    uint16_t min_ce_len;
-    uint16_t max_ce_len;
-};
-
-struct hci_ext_create_conn
-{
-    uint8_t filter_policy;
-    uint8_t own_addr_type;
-    uint8_t peer_addr_type;
-    uint8_t peer_addr[BLE_DEV_ADDR_LEN];
-    uint8_t init_phy_mask;
-    struct hci_ext_conn_params params[3];
-};
-
 /* Connection state machine */
 struct ble_ll_conn_sm
 {
@@ -379,10 +356,6 @@ struct ble_ll_conn_sm
     /* XXX: for now, just store them all */
     struct ble_ll_conn_params conn_cp;
 
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    struct hci_ext_create_conn initial_params;
-#endif
-
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
     uint8_t  sync_transfer_mode;
     uint16_t sync_transfer_skip;
diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index eae0c39..04ca481 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -197,10 +197,11 @@ int ble_ll_scan_can_chg_whitelist(void);
 int ble_ll_scan_enabled(void);
 
 /* Initialize the scanner when we start initiating */
-struct hci_create_conn;
+struct ble_ll_conn_create_scan;
+struct ble_ll_conn_create_params;
 int
-ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
-                            struct ble_ll_conn_sm *connsm);
+ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext,
+                            struct ble_ll_conn_create_scan *cc_scan);
 
 /* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */
 struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void);
@@ -227,12 +228,6 @@ void ble_ll_scan_wfr_timer_exp(void);
 void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-/* Initialize the extended scanner when we start initiating */
-struct hci_ext_create_conn;
-int
-ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
-                                struct ble_ll_conn_sm *connsm);
-
 /* Called to parse extended advertising*/
 void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
 #endif
diff --git a/nimble/controller/include/controller/ble_phy.h b/nimble/controller/include/controller/ble_phy.h
index cd8350d..47f3afd 100644
--- a/nimble/controller/include/controller/ble_phy.h
+++ b/nimble/controller/include/controller/ble_phy.h
@@ -202,6 +202,11 @@ void ble_phy_resolv_list_disable(void);
 #define BLE_PHY_MASK_2M             (BLE_HCI_LE_PHY_2M_PREF_MASK)
 #define BLE_PHY_MASK_CODED          (BLE_HCI_LE_PHY_CODED_PREF_MASK)
 
+/* PHY indices (for a zero-based array) */
+#define BLE_PHY_IDX_1M              (0)
+#define BLE_PHY_IDX_2M              (1)
+#define BLE_PHY_IDX_CODED           (2)
+
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
 uint32_t ble_phy_mode_pdu_start_off(int phy);
 void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode);
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index 2702b7c..014f7e2 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -577,7 +577,7 @@ ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext)
      * Test specification extends this also to initiating.
      */
 
-    if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() ||
+    if (g_ble_ll_conn_create_sm.connsm || ble_ll_scan_enabled() ||
                                 (!hci_adv_ext && ble_ll_adv_enabled())) {
         return BLE_ERR_CMD_DISALLOWED;
     }
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 76dd18e..eb61414 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -143,8 +143,7 @@ struct ble_ll_conn_global_params g_ble_ll_conn_params;
 struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params;
 #endif
 
-/* Pointer to connection state machine we are trying to create */
-struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
+struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm;
 
 /* Pointer to current connection */
 struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm;
@@ -421,25 +420,23 @@ ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm)
 }
 #endif
 
-static void
-ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm)
+void
+ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks,
+                          uint8_t *itvl_usecs)
 {
     uint32_t ticks;
     uint32_t usecs;
 
-    /*
-     * Precalculate the number of ticks and remaining microseconds for
-     * the connection interval
-     */
-    usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+    usecs = itvl * BLE_LL_CONN_ITVL_USECS;
     ticks = os_cputime_usecs_to_ticks(usecs);
-    connsm->conn_itvl_usecs = (uint8_t)(usecs -
-                                        os_cputime_ticks_to_usecs(ticks));
-    if (connsm->conn_itvl_usecs == 31) {
-        connsm->conn_itvl_usecs = 0;
+    usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+    if (usecs == 31) {
+        usecs = 0;
         ++ticks;
     }
-    connsm->conn_itvl_ticks = ticks;
+
+    *itvl_ticks = ticks;
+    *itvl_usecs = usecs;
 }
 
 /**
@@ -1578,37 +1575,23 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
  */
 void
 ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
-                        struct hci_create_conn *hcc)
+                        struct ble_ll_conn_create_scan *cc_scan,
+                        struct ble_ll_conn_create_params *cc_params)
 {
 
     ble_ll_conn_master_common_init(connsm);
 
-    /* Set slave latency and supervision timeout */
-    connsm->slave_latency = hcc->conn_latency;
-    connsm->supervision_tmo = hcc->supervision_timeout;
-
-    /* Set own address type and peer address if needed */
-    connsm->own_addr_type = hcc->own_addr_type;
-    if (hcc->filter_policy == 0) {
-        memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
-        connsm->peer_addr_type = hcc->peer_addr_type;
-    }
-
-    /* XXX: for now, just make connection interval equal to max */
-    connsm->conn_itvl = hcc->conn_itvl_max;
-
-    /* Check the min/max CE lengths are less than connection interval */
-    if (hcc->min_ce_len > (connsm->conn_itvl * 2)) {
-        connsm->min_ce_len = connsm->conn_itvl * 2;
-    } else {
-        connsm->min_ce_len = hcc->min_ce_len;
-    }
+    connsm->own_addr_type = cc_scan->own_addr_type;
+    memcpy(&connsm->peer_addr, &cc_scan->peer_addr, BLE_DEV_ADDR_LEN);
+    connsm->peer_addr_type = cc_scan->peer_addr_type;
 
-    if (hcc->max_ce_len > (connsm->conn_itvl * 2)) {
-        connsm->max_ce_len = connsm->conn_itvl * 2;
-    } else {
-        connsm->max_ce_len = hcc->max_ce_len;
-    }
+    connsm->conn_itvl = cc_params->conn_itvl;
+    connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks;
+    connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs;
+    connsm->slave_latency = cc_params->conn_latency;
+    connsm->supervision_tmo = cc_params->supervision_timeout;
+    connsm->min_ce_len = cc_params->min_ce_len;
+    connsm->max_ce_len = cc_params->max_ce_len;
 }
 
 static void
@@ -1684,54 +1667,20 @@ ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy)
 #endif
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-
-void
-ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm,
-                        struct hci_ext_create_conn *hcc)
-{
-
-    ble_ll_conn_master_common_init(connsm);
-
-    /* Set own address type and peer address if needed */
-    connsm->own_addr_type = hcc->own_addr_type;
-    if (hcc->filter_policy == 0) {
-        memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
-        connsm->peer_addr_type = hcc->peer_addr_type;
-    }
-
-    connsm->initial_params = *hcc;
-}
-
-void
-ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm,
-                           struct hci_ext_conn_params *hcc_params, int phy)
+static void
+ble_ll_conn_create_set_params(struct ble_ll_conn_sm *connsm, uint8_t phy)
 {
-    connsm->slave_latency = hcc_params->conn_latency;
-    connsm->supervision_tmo = hcc_params->supervision_timeout;
+    struct ble_ll_conn_create_params *cc_params;
 
-    connsm->conn_itvl = hcc_params->conn_itvl;
-    connsm->conn_itvl_ticks = hcc_params->conn_itvl_ticks;
-    connsm->conn_itvl_usecs = hcc_params->conn_itvl_usecs;
+    cc_params = &g_ble_ll_conn_create_sm.params[phy - 1];
 
-    /* Check the min/max CE lengths are less than connection interval */
-    if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) {
-        connsm->min_ce_len = connsm->conn_itvl * 2;
-    } else {
-        connsm->min_ce_len = hcc_params->min_ce_len;
-    }
+    connsm->slave_latency = cc_params->conn_latency;
+    connsm->supervision_tmo = cc_params->supervision_timeout;
 
-    if (hcc_params->max_ce_len > (connsm->conn_itvl * 2)) {
-        connsm->max_ce_len = connsm->conn_itvl * 2;
-    } else {
-        connsm->max_ce_len = hcc_params->max_ce_len;
-    }
-
-#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
-    ble_ll_conn_init_phy(connsm, phy);
-#endif
+    connsm->conn_itvl = cc_params->conn_itvl;
+    connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks;
+    connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs;
 }
-
-
 #endif
 
 static void
@@ -1862,8 +1811,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
                     connsm);
 #endif
 
-    ble_ll_conn_calc_itvl_ticks(connsm);
-
     /* Add to list of active connections */
     SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
 }
@@ -2170,7 +2117,10 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
             connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
         connsm->tx_win_off = upd->winoffset;
         connsm->conn_itvl = upd->interval;
-        ble_ll_conn_calc_itvl_ticks(connsm);
+
+        ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks,
+                                  &connsm->conn_itvl_usecs);
+
         if (upd->winoffset != 0) {
             usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS;
             ticks = os_cputime_usecs_to_ticks(usecs);
@@ -2651,7 +2601,7 @@ ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm,
         }
     } else {
         /* Get pointer to our device address */
-        connsm = g_ble_ll_conn_create_sm;
+        connsm = g_ble_ll_conn_create_sm.connsm;
         if ((connsm->own_addr_type & 1) == 0) {
             addr = g_dev_addr;
         } else {
@@ -2764,12 +2714,11 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
     struct ble_mbuf_hdr *rxhdr;
     int8_t rpa_index;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    struct hci_ext_conn_params *ecp;
     uint8_t phy;
 #endif
     int rc;
 
-    connsm = g_ble_ll_conn_create_sm;
+    connsm = g_ble_ll_conn_create_sm.connsm;
     rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
@@ -2779,8 +2728,7 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
 #else
         phy = BLE_PHY_1M;
 #endif
-        ecp = &connsm->initial_params.params[phy - 1];
-        ble_ll_conn_ext_set_params(connsm, ecp, phy);
+        ble_ll_conn_create_set_params(connsm, phy);
     }
 #endif
 
@@ -2806,6 +2754,12 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu,
         return -1;
     }
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && BLE_LL_BT5_PHY_SUPPORTED
+    if (ext) {
+        ble_ll_conn_init_phy(connsm, phy);
+    }
+#endif
+
     return 0;
 }
 
@@ -2814,7 +2768,7 @@ ble_ll_conn_send_connect_req_cancel(void)
 {
     struct ble_ll_conn_sm *connsm;
 
-    connsm = g_ble_ll_conn_create_sm;
+    connsm = g_ble_ll_conn_create_sm.connsm;
 
     ble_ll_sched_rmv_elem(&connsm->conn_sch);
 }
@@ -2825,8 +2779,8 @@ ble_ll_conn_master_start(uint8_t phy, uint8_t csa,
 {
     struct ble_ll_conn_sm *connsm;
 
-    connsm = g_ble_ll_conn_create_sm;
-    g_ble_ll_conn_create_sm = NULL;
+    connsm = g_ble_ll_conn_create_sm.connsm;
+    g_ble_ll_conn_create_sm.connsm = NULL;
 
     connsm->peer_addr_type = addrd->adv_addr_type;
     memcpy(connsm->peer_addr, addrd->adv_addr, 6);
@@ -3688,6 +3642,9 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr,
         goto err_slave_start;
     }
 
+    ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks,
+                              &connsm->conn_itvl_usecs);
+
     /* Start the connection state machine */
     connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
     ble_ll_conn_sm_new(connsm);
@@ -3751,7 +3708,7 @@ ble_ll_conn_module_reset(void)
     }
 
     /* Reset connection we are attempting to create */
-    g_ble_ll_conn_create_sm = NULL;
+    g_ble_ll_conn_create_sm.connsm = NULL;
 
     /* Now go through and end all the connections */
     while (1) {
diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c
index e53918f..decc485 100644
--- a/nimble/controller/src/ble_ll_conn_hci.c
+++ b/nimble/controller/src/ble_ll_conn_hci.c
@@ -43,19 +43,22 @@ static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt;
 extern uint8_t *g_ble_ll_conn_comp_ev;
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
+static const uint8_t ble_ll_conn_create_valid_phy_mask = (
+        BLE_HCI_LE_PHY_1M_PREF_MASK |
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
-                                | BLE_HCI_LE_PHY_2M_PREF_MASK
+        BLE_HCI_LE_PHY_2M_PREF_MASK |
 #endif
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-                                | BLE_HCI_LE_PHY_CODED_PREF_MASK
+        BLE_HCI_LE_PHY_CODED_PREF_MASK |
 #endif
-                              );
-static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
+        0);
+
+static const uint8_t ble_ll_conn_create_required_phy_mask = (
+        BLE_HCI_LE_PHY_1M_PREF_MASK |
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-                            | BLE_HCI_LE_PHY_CODED_PREF_MASK
+        BLE_HCI_LE_PHY_CODED_PREF_MASK |
 #endif
-                            );
+        0);
 #endif
 
 /**
@@ -401,18 +404,74 @@ ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason)
     }
 }
 
+int
+ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p)
+{
+    if (p->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if ((p->filter_policy == 0) &&
+        (p->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (p->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    if (p->init_phy_mask & ~ble_ll_conn_create_valid_phy_mask) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (!(p->init_phy_mask & ble_ll_conn_create_required_phy_mask)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+#endif
+
+    return 0;
+}
+
 static int
-ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window)
+ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params)
 {
-    /* Check interval and window */
-    if ((itvl < BLE_HCI_SCAN_ITVL_MIN) ||
-        (itvl > BLE_HCI_SCAN_ITVL_MAX) ||
-        (window < BLE_HCI_SCAN_WINDOW_MIN) ||
-        (window > BLE_HCI_SCAN_WINDOW_MAX) ||
-        (itvl < window)) {
+    uint32_t supervision_tmo_us;
+    uint32_t conn_itvl_us;
+
+    if ((cc_params->conn_itvl < BLE_HCI_CONN_ITVL_MIN) ||
+        (cc_params->conn_itvl > BLE_HCI_CONN_ITVL_MAX) ||
+        (cc_params->conn_latency > BLE_HCI_CONN_LATENCY_MAX) ||
+        (cc_params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
+        (cc_params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    /* Supervision timeout must be longer than (1 + latency) * interval * 2 */
+    supervision_tmo_us = cc_params->supervision_timeout *
+                         BLE_HCI_CONN_SPVN_TMO_UNITS * 1000;
+    conn_itvl_us = cc_params->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+
+    if (supervision_tmo_us <= (1 + cc_params->conn_latency) * conn_itvl_us * 2) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (cc_params->min_ce_len > cc_params->max_ce_len) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+    /* Adjust min/max ce length to be less than interval */
+    if (cc_params->min_ce_len > cc_params->conn_itvl) {
+        cc_params->min_ce_len = cc_params->conn_itvl;
+    }
+    if (cc_params->max_ce_len > cc_params->conn_itvl) {
+        cc_params->max_ce_len = cc_params->conn_itvl;
+    }
+
+    /* Precalculate conn interval */
+    ble_ll_conn_itvl_to_ticks(cc_params->conn_itvl, &cc_params->conn_itvl_ticks,
+                              &cc_params->conn_itvl_usecs);
+
     return 0;
 }
 
@@ -426,11 +485,14 @@ ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window)
  * @return int
  */
 int
-ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
+ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
 {
     const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf;
+    struct ble_ll_conn_create_scan cc_scan;
+    struct ble_ll_conn_create_params cc_params;
     struct ble_ll_conn_sm *connsm;
-    struct hci_create_conn hcc = { 0 };
+    uint16_t conn_itvl_min;
+    uint16_t conn_itvl_max;
     int rc;
 
     if (len < sizeof(*cmd)) {
@@ -438,7 +500,7 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
     }
 
     /* If we are already creating a connection we should leave */
-    if (g_ble_ll_conn_create_sm) {
+    if (g_ble_ll_conn_create_sm.connsm) {
         return BLE_ERR_CMD_DISALLOWED;
     }
 
@@ -447,57 +509,48 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CMD_DISALLOWED;
     }
 
-    /* Retrieve command data */
-    hcc.scan_itvl = le16toh(cmd->scan_itvl);
-    hcc.scan_window = le16toh(cmd->scan_window);
-
-    rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window);
-    if (rc) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
-    }
-
-    /* Check filter policy */
-    hcc.filter_policy = cmd->filter_policy;
-    if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
+    cc_scan.own_addr_type = cmd->own_addr_type;
+    cc_scan.filter_policy = cmd->filter_policy;
+    if (cc_scan.filter_policy == 0) {
+        cc_scan.peer_addr_type = cmd->peer_addr_type;
+        memcpy(&cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
+    } else {
+        cc_scan.peer_addr_type = 0;
+        memset(&cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN);
     }
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    cc_scan.init_phy_mask = BLE_HCI_LE_PHY_1M_PREF_MASK;
+#endif
 
-    /* Get peer address type and address only if no whitelist used */
-    if (hcc.filter_policy == 0) {
-        hcc.peer_addr_type = cmd->peer_addr_type;
-        if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
+    cc_scan.scan_params[PHY_UNCODED].itvl = le16toh(cmd->scan_itvl);
+    cc_scan.scan_params[PHY_UNCODED].window = le16toh(cmd->scan_window);
 
-        memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
+    rc = ble_ll_conn_hci_create_check_scan(&cc_scan);
+    if (rc) {
+        return rc;
     }
 
-    /* Get own address type (used in connection request) */
-    hcc.own_addr_type = cmd->own_addr_type;
-    if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+    conn_itvl_min = le16toh(cmd->min_conn_itvl);
+    conn_itvl_max = le16toh(cmd->max_conn_itvl);
+
+    /* Check min/max interval here since generic check does not have min/max
+     * parameters to check.
+     */
+    if (conn_itvl_min > conn_itvl_max) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
-    /* Check connection interval, latency and supervision timeoout */
-    hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl);
-    hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl);
-    hcc.conn_latency = le16toh(cmd->conn_latency);
-    hcc.supervision_timeout = le16toh(cmd->tmo);
-    rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min,
-                                         hcc.conn_itvl_max,
-                                         hcc.conn_latency,
-                                         hcc.supervision_timeout);
+    cc_params.conn_itvl = conn_itvl_max;
+    cc_params.conn_latency = le16toh(cmd->conn_latency);
+    cc_params.supervision_timeout = le16toh(cmd->tmo);
+    cc_params.min_ce_len = le16toh(cmd->min_ce);
+    cc_params.max_ce_len = le16toh(cmd->max_ce);
+
+    rc = ble_ll_conn_hci_create_check_params(&cc_params);
     if (rc) {
         return rc;
     }
 
-    /* Min/max connection event lengths */
-    hcc.min_ce_len = le16toh(cmd->min_ce);
-    hcc.max_ce_len = le16toh(cmd->max_ce);
-    if (hcc.min_ce_len > hcc.max_ce_len) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
-    }
-
     /* Make sure we can allocate an event to send the connection complete */
     if (ble_ll_init_alloc_conn_comp_ev()) {
         return BLE_ERR_MEM_CAPACITY;
@@ -510,18 +563,14 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
     }
 
     /* Initialize state machine in master role and start state machine */
-    ble_ll_conn_master_init(connsm, &hcc);
+    ble_ll_conn_master_init(connsm, &cc_scan, &cc_params);
     ble_ll_conn_sm_new(connsm);
-    /* CSA will be selected when advertising is received */
 
     /* Start scanning */
-    rc = ble_ll_scan_initiator_start(&hcc, connsm);
+    rc = ble_ll_scan_initiator_start(connsm, 0, &cc_scan);
     if (rc) {
         SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
         STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
-    } else {
-        /* Set the connection state machine we are trying to create. */
-        g_ble_ll_conn_create_sm = connsm;
     }
 
     return rc;
@@ -529,68 +578,117 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len)
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 static void
-ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc,
-                                    const struct hci_ext_conn_params *fallback)
+ble_ll_conn_hci_ext_create_set_fb_params(uint8_t init_phy_mask,
+                                         struct ble_ll_conn_create_params *cc_params_fb)
 {
-    BLE_LL_ASSERT(fallback);
-
-    if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) {
-        hcc->params[0] = *fallback;
+    if ((init_phy_mask & BLE_PHY_MASK_1M) == 0) {
+        g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_1M] = *cc_params_fb;
     }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
-    if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) {
-        hcc->params[1] = *fallback;
+    if ((init_phy_mask & BLE_PHY_MASK_2M) == 0) {
+        g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_2M] = *cc_params_fb;
     }
 #endif
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-    if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) {
-        hcc->params[2] = *fallback;
+    if ((init_phy_mask & BLE_PHY_MASK_CODED) == 0) {
+        g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_CODED] = *cc_params_fb;
     }
 #endif
 }
 
-static void
-ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint16_t *itvl_ticks,
-                          uint8_t *itvl_usecs)
+static int
+ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params,
+                                        uint8_t phy,
+                                        struct ble_ll_conn_create_scan *cc_scan,
+                                        struct ble_ll_conn_create_params *cc_params)
 {
-    uint32_t ticks;
-    uint32_t usecs;
+    uint16_t conn_itvl_min;
+    uint16_t conn_itvl_max;
+    uint16_t scan_itvl;
+    uint16_t scan_window;
+    int rc;
+
+    conn_itvl_min = le16toh(params->conn_min_itvl);
+    conn_itvl_max = le16toh(params->conn_max_itvl);
+
+    /* Check min/max interval here since generic check does not have min/max
+     * parameters to check.
+     */
+    if (conn_itvl_min > conn_itvl_max) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    cc_params->conn_itvl = conn_itvl_max;
+    cc_params->conn_latency = le16toh(params->conn_latency);
+    cc_params->supervision_timeout = le16toh(params->supervision_timeout);
+    cc_params->min_ce_len = le16toh(params->min_ce);
+    cc_params->max_ce_len = le16toh(params->max_ce);
+
+    rc = ble_ll_conn_hci_create_check_params(cc_params);
+    if (rc) {
+        return rc;
+    }
+
+    if (phy != BLE_PHY_2M) {
+        scan_itvl = le16toh(params->scan_itvl);
+        scan_window = le16toh(params->scan_window);
 
-    usecs = itvl * BLE_LL_CONN_ITVL_USECS;
-    ticks = os_cputime_usecs_to_ticks(usecs);
-    usecs = usecs - os_cputime_ticks_to_usecs(ticks);
-    if (usecs == 31) {
-        usecs = 0;
-        ++ticks;
+        if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
+            (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
+            (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
+            (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
+            (scan_itvl < scan_window)) {
+                return BLE_ERR_INV_HCI_CMD_PARMS;
+        }
+
+        if (phy == BLE_PHY_1M) {
+            cc_scan->scan_params[PHY_UNCODED].itvl = scan_itvl;
+            cc_scan->scan_params[PHY_UNCODED].window = scan_window;
+        } else {
+            cc_scan->scan_params[PHY_CODED].itvl = scan_itvl;
+            cc_scan->scan_params[PHY_CODED].window = scan_window;
+        }
     }
 
-    *itvl_ticks = ticks;
-    *itvl_usecs = usecs;
+    return 0;
 }
 
 int
-ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
+ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len)
 {
-    const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf;
+    static const struct init_phy {
+        uint8_t idx;
+        uint8_t mask;
+        uint8_t phy;
+    } init_phys[] = {
+            {BLE_PHY_IDX_1M, BLE_PHY_MASK_1M, BLE_PHY_1M},
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+            {BLE_PHY_IDX_2M, BLE_PHY_MASK_2M, BLE_PHY_2M},
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+            {BLE_PHY_IDX_CODED, BLE_PHY_MASK_CODED, BLE_PHY_CODED},
+#endif
+    };
+
+    const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *)cmdbuf;
     const struct conn_params *params = cmd->conn_params;
-    const struct hci_ext_conn_params *fallback_params = NULL;
-    struct hci_ext_create_conn hcc = { 0 };
+    struct ble_ll_conn_create_scan cc_scan;
+    struct ble_ll_conn_create_params *cc_params;
+    struct ble_ll_conn_create_params *cc_params_fb;
     struct ble_ll_conn_sm *connsm;
-    uint16_t conn_itvl_min;
-    uint16_t conn_itvl_max;
+    const struct init_phy *init_phy;
     int rc;
 
     /* validate length */
-    if (len < sizeof(*cmd)) {
+    if (len < sizeof(*cmd) +
+              __builtin_popcount(cmd->init_phy_mask) * sizeof(*params)) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
-    len -= sizeof(*cmd);
-
     /* If we are already creating a connection we should leave */
-    if (g_ble_ll_conn_create_sm) {
+    if (g_ble_ll_conn_create_sm.connsm) {
         return BLE_ERR_CMD_DISALLOWED;
     }
 
@@ -599,161 +697,47 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CMD_DISALLOWED;
     }
 
-    hcc.filter_policy = cmd->filter_policy;
-    if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
-    }
-
-    hcc.own_addr_type = cmd->own_addr_type;
-    if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
-    }
-
-    /* Validate peer address type only if no whitelist used */
-    if (hcc.filter_policy == 0) {
-        hcc.peer_addr_type = cmd->peer_addr_type;
-
-        if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-
-        memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
-    }
-
-    hcc.init_phy_mask = cmd->init_phy_mask;
-    if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) {
-        return BLE_ERR_INV_HCI_CMD_PARMS;
+    cc_scan.own_addr_type = cmd->own_addr_type;
+    cc_scan.filter_policy = cmd->filter_policy;
+    if (cc_scan.filter_policy == 0) {
+        cc_scan.peer_addr_type = cmd->peer_addr_type;
+        memcpy(cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN);
+    } else {
+        cc_scan.peer_addr_type = 0;
+        memset(cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN);
     }
+    cc_scan.init_phy_mask = cmd->init_phy_mask;
 
-    if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) {
-        /* At least one of those need to be set */
-        return BLE_ERR_INV_HCI_CMD_PARMS;
+    rc = ble_ll_conn_hci_create_check_scan(&cc_scan);
+    if (rc) {
+        return rc;
     }
 
-    if (hcc.init_phy_mask & BLE_PHY_MASK_1M) {
-        if (len < sizeof(*params)) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-        len -= sizeof(*params);
+    cc_params_fb = NULL;
 
-        hcc.params[0].scan_itvl = le16toh(params->scan_itvl);
-        hcc.params[0].scan_window = le16toh(params->scan_window);
+    for (int i = 0; i < ARRAY_SIZE(init_phys); i++) {
+        init_phy = &init_phys[i];
 
-        rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl,
-                                             hcc.params[0].scan_window);
-        if (rc) {
-            return rc;
+        if ((cc_scan.init_phy_mask & init_phy->mask) == 0) {
+            continue;
         }
 
-        conn_itvl_min = le16toh(params->conn_min_itvl);
-        conn_itvl_max = le16toh(params->conn_max_itvl);
-        hcc.params[0].conn_latency = le16toh(params->conn_latency);
-        hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout);
+        cc_params = &g_ble_ll_conn_create_sm.params[init_phy->idx];
 
-        rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
-                                             hcc.params[0].conn_latency,
-                                             hcc.params[0].supervision_timeout);
+        rc = ble_ll_conn_hci_ext_create_parse_params(params, init_phy->phy,
+                                                     &cc_scan, cc_params);
         if (rc) {
             return rc;
         }
 
-        /* Min/max connection event lengths */
-        hcc.params[0].min_ce_len = le16toh(params->min_ce);
-        hcc.params[0].max_ce_len = le16toh(params->max_ce);
-        if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
+        if (!cc_params_fb) {
+            cc_params_fb = cc_params;
         }
-
-        hcc.params[0].conn_itvl = conn_itvl_max;
-        ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[0].conn_itvl_ticks,
-                                  &hcc.params[0].conn_itvl_usecs);
-
-        fallback_params = &hcc.params[0];
         params++;
     }
 
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
-    if (hcc.init_phy_mask & BLE_PHY_MASK_2M) {
-        if (len < sizeof(*params)) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-        len -= sizeof(*params);
-
-        conn_itvl_min = le16toh(params->conn_min_itvl);
-        conn_itvl_max = le16toh(params->conn_max_itvl);
-        hcc.params[1].conn_latency = le16toh(params->conn_latency);
-        hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout);
-
-        rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
-                                             hcc.params[1].conn_latency,
-                                             hcc.params[1].supervision_timeout);
-        if (rc) {
-            return rc;
-        }
-
-        /* Min/max connection event lengths */
-        hcc.params[1].min_ce_len = le16toh(params->min_ce);
-        hcc.params[1].max_ce_len = le16toh(params->max_ce);
-        if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-
-        hcc.params[1].conn_itvl = conn_itvl_max;
-        ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[1].conn_itvl_ticks,
-                                  &hcc.params[1].conn_itvl_usecs);
-
-        if (!fallback_params) {
-            fallback_params = &hcc.params[1];
-        }
-        params++;
-    }
-#endif
-
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-    if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) {
-        if (len < sizeof(*params)) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-        len -= sizeof(*params);
-
-        hcc.params[2].scan_itvl = le16toh(params->scan_itvl);
-        hcc.params[2].scan_window = le16toh(params->scan_window);
-
-        rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl,
-                                             hcc.params[2].scan_window);
-        if (rc) {
-            return rc;
-        }
-
-        conn_itvl_min = le16toh(params->conn_min_itvl);
-        conn_itvl_max = le16toh(params->conn_max_itvl);
-        hcc.params[2].conn_latency = le16toh(params->conn_latency);
-        hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout);
-
-        rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max,
-                                             hcc.params[2].conn_latency,
-                                             hcc.params[2].supervision_timeout);
-        if (rc) {
-            return rc;
-        }
-
-        /* Min/max connection event lengths */
-        hcc.params[2].min_ce_len = le16toh(params->min_ce);
-        hcc.params[2].max_ce_len = le16toh(params->max_ce);
-        if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) {
-            return BLE_ERR_INV_HCI_CMD_PARMS;
-        }
-
-        hcc.params[2].conn_itvl = conn_itvl_max;
-        ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[2].conn_itvl_ticks,
-                                  &hcc.params[2].conn_itvl_usecs);
-
-        if (!fallback_params) {
-            fallback_params = &hcc.params[2];
-        }
-        params++;
-    }
-#endif
+    ble_ll_conn_hci_ext_create_set_fb_params(cc_scan.init_phy_mask,
+                                             cc_params_fb);
 
     /* Make sure we can allocate an event to send the connection complete */
     if (ble_ll_init_alloc_conn_comp_ev()) {
@@ -766,20 +750,16 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CONN_LIMIT;
     }
 
-    ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params);
-
     /* Initialize state machine in master role and start state machine */
-    ble_ll_conn_ext_master_init(connsm, &hcc);
+    ble_ll_conn_master_init(connsm, &cc_scan,
+                            &g_ble_ll_conn_create_sm.params[0]);
     ble_ll_conn_sm_new(connsm);
 
     /* Start scanning */
-    rc = ble_ll_scan_ext_initiator_start(&hcc, connsm);
+    rc = ble_ll_scan_initiator_start(connsm, 1, &cc_scan);
     if (rc) {
         SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
         STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
-    } else {
-        /* Set the connection state machine we are trying to create. */
-        g_ble_ll_conn_create_sm = connsm;
     }
 
     return rc;
@@ -1125,10 +1105,10 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
      * return disallowed as well
      */
     OS_ENTER_CRITICAL(sr);
-    connsm = g_ble_ll_conn_create_sm;
+    connsm = g_ble_ll_conn_create_sm.connsm;
     if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) {
         /* stop scanning and end the connection event */
-        g_ble_ll_conn_create_sm = NULL;
+        g_ble_ll_conn_create_sm.connsm = NULL;
         ble_ll_scan_sm_stop(1);
         ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
 
diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h
index 099ce77..d1a4a3e 100644
--- a/nimble/controller/src/ble_ll_conn_priv.h
+++ b/nimble/controller/src/ble_ll_conn_priv.h
@@ -93,8 +93,38 @@ STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm);
 extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list;
 extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list;
 
-/* Pointer to connection state machine we are trying to create */
-extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
+struct ble_ll_conn_create_scan {
+    uint8_t filter_policy;
+    uint8_t own_addr_type;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[BLE_DEV_ADDR_LEN];
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    uint8_t init_phy_mask;
+#endif
+    struct {
+        uint16_t itvl;
+        uint16_t window;
+    } scan_params[2];
+};
+
+struct ble_ll_conn_create_params {
+    uint32_t conn_itvl;
+    uint32_t conn_itvl_ticks;
+    uint8_t conn_itvl_usecs;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+    uint16_t min_ce_len;
+    uint16_t max_ce_len;
+};
+
+struct ble_ll_conn_create_sm {
+    struct ble_ll_conn_sm *connsm;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    struct ble_ll_conn_create_params params[3];
+#endif
+};
+
+extern struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm;
 
 /* Generic interface */
 struct ble_ll_len_req;
@@ -123,15 +153,8 @@ void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
                              uint8_t hdr_byte, uint16_t length);
 struct ble_ll_conn_sm *ble_ll_conn_sm_get(void);
 void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
-                             struct hci_create_conn *hcc);
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm,
-                                 struct hci_ext_create_conn *hcc);
-
-void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm,
-                                struct hci_ext_conn_params *hcc_params,
-                                int phy);
-#endif
+                             struct ble_ll_conn_create_scan *cc_scan,
+                             struct ble_ll_conn_create_params *cc_params);
 
 struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle);
 void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm);
@@ -158,7 +181,7 @@ void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
 void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
 int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
 int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
-int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len);
 int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
 int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len);
 int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len,
@@ -205,6 +228,9 @@ bool ble_ll_conn_cth_flow_enable(bool enabled);
 void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
 #endif
 
+void ble_ll_conn_itvl_to_ticks(uint32_t itvl,
+                               uint32_t *itvl_ticks, uint8_t *itvl_usecs);
+
 int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
 int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
 
@@ -213,7 +239,7 @@ int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len,
 int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len);
 int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm);
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen);
+int ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len);
 #endif
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c
index 7cd3621..547b661 100644
--- a/nimble/controller/src/ble_ll_hci.c
+++ b/nimble/controller/src/ble_ll_hci.c
@@ -910,7 +910,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
         rc = ble_ll_hci_scan_set_enable(cmdbuf, len);
         break;
     case BLE_HCI_OCF_LE_CREATE_CONN:
-        rc = ble_ll_conn_create(cmdbuf, len);
+        rc = ble_ll_conn_hci_create(cmdbuf, len);
         break;
     case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
         if (len == 0) {
@@ -1113,7 +1113,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
         rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len);
         break;
     case BLE_HCI_OCF_LE_EXT_CREATE_CONN:
-        rc = ble_ll_ext_conn_create(cmdbuf, len);
+        rc = ble_ll_conn_hci_ext_create(cmdbuf, len);
         break;
 #endif
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
diff --git a/nimble/controller/src/ble_ll_resolv.c b/nimble/controller/src/ble_ll_resolv.c
index 02af930..f85e26a 100644
--- a/nimble/controller/src/ble_ll_resolv.c
+++ b/nimble/controller/src/ble_ll_resolv.c
@@ -57,7 +57,7 @@ ble_ll_is_controller_busy(void)
 #endif
 
     return ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
-           g_ble_ll_conn_create_sm;
+           g_ble_ll_conn_create_sm.connsm;
 }
 /**
  * Called to determine if a change is allowed to the resolving list at this
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 0d9d36f..7363831 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -2411,65 +2411,37 @@ ble_ll_scan_can_chg_whitelist(void)
 }
 
 int
-ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
-                            struct ble_ll_conn_sm *connsm)
-{
-    struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_phy *scanp;
-    int rc;
-
-    scansm = &g_ble_ll_scan_sm;
-    scansm->own_addr_type = hcc->own_addr_type;
-    scansm->scan_filt_policy = hcc->filter_policy;
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    scansm->ext_scanning = 0;
-#endif
-    scansm->connsm = connsm;
-
-    scansm->scanp = &scansm->scan_phys[PHY_UNCODED];
-    scansm->scanp_next = NULL;
-
-    scanp = scansm->scanp;
-    scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
-    scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
-    scanp->scan_type = BLE_SCAN_TYPE_INITIATE;
-    scanp->configured = 1;
-
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-    scanp = &scansm->scan_phys[PHY_CODED];
-    scanp->configured = 0;
-#endif
-
-    rc = ble_ll_scan_sm_start(scansm);
-
-    return rc;
-}
-
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-int
-ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
-                                struct ble_ll_conn_sm *connsm)
+ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext,
+                            struct ble_ll_conn_create_scan *cc_scan)
 {
     struct ble_ll_scan_sm *scansm;
     struct ble_ll_scan_phy *scanp_uncoded;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
     struct ble_ll_scan_phy *scanp_coded;
-    struct hci_ext_conn_params *params;
+#endif
+    uint8_t init_phy_mask;
     int rc;
 
     scansm = &g_ble_ll_scan_sm;
-    scansm->own_addr_type = hcc->own_addr_type;
-    scansm->scan_filt_policy = hcc->filter_policy;
+    scansm->own_addr_type = cc_scan->own_addr_type;
+    scansm->scan_filt_policy = cc_scan->filter_policy;
     scansm->scanp = NULL;
     scansm->scanp_next = NULL;
-    scansm->ext_scanning = 1;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    scansm->ext_scanning = ext;
+    init_phy_mask = cc_scan->init_phy_mask;
+#else
+    init_phy_mask = BLE_PHY_MASK_1M;
+#endif
     scansm->connsm = connsm;
 
-    params = &hcc->params[0];
     scanp_uncoded = &scansm->scan_phys[PHY_UNCODED];
-    if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
+    if (init_phy_mask & BLE_PHY_MASK_1M) {
         scanp_uncoded->configured = 1;
-        scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
-        scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
+        scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(
+                                cc_scan->scan_params[PHY_UNCODED].itvl);
+        scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(
+                                cc_scan->scan_params[PHY_UNCODED].window);
         scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
         scansm->scanp = scanp_uncoded;
     } else {
@@ -2477,12 +2449,13 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
     }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
-    params = &hcc->params[2];
     scanp_coded = &scansm->scan_phys[PHY_CODED];
-    if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
+    if (init_phy_mask & BLE_PHY_MASK_CODED) {
         scanp_coded->configured = 1;
-        scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
-        scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
+        scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(
+                                cc_scan->scan_params[PHY_CODED].itvl);
+        scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(
+                                cc_scan->scan_params[PHY_CODED].window);
         scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE;
         if (scansm->scanp) {
             scansm->scanp_next = scanp_coded;
@@ -2492,9 +2465,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
     } else {
         scanp_coded->configured = 0;
     }
-#else
-    scanp_coded = NULL;
-#endif
 
     /* if any of PHYs is configured for continuous scan we alter interval to
      * fit other PHY
@@ -2509,12 +2479,15 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
             scanp_uncoded->timing.interval += scanp_coded->timing.window;
         }
     }
+#endif
 
     rc = ble_ll_scan_sm_start(scansm);
+    if (rc == 0) {
+        g_ble_ll_conn_create_sm.connsm = connsm;
+    }
 
     return rc;
 }
-#endif
 
 /**
  * Checks to see if the scanner is enabled.