You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ry...@apache.org on 2017/04/27 21:45:54 UTC

[1/6] incubator-mynewt-core git commit: nimble/controller: MYNEWT-726

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/bluetooth5 87329b514 -> 230462f8f


nimble/controller: MYNEWT-726

Modify how the controller deals with the terminate procedure. The
old method set a pending control procedure bit and it was not the
best way to deal with this since the terminate procedure can
occur while another control procedure is in process. The
new method uses a flag in the connection state machine flags
to denote that the terminate procedure was started. Started means
a control pdu was allocated and enqueued. The disconnect reason
being non-zero means that the connection is to be terminated.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/46d67b04
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/46d67b04
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/46d67b04

Branch: refs/heads/bluetooth5
Commit: 46d67b04b26d25391d057785765549e5f72d04d0
Parents: 87329b5
Author: William San Filippo <wi...@runtime.io>
Authored: Fri Apr 14 12:51:51 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 18:39:34 2017 +0200

----------------------------------------------------------------------
 net/nimble/controller/include/controller/ble_ll_conn.h | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/46d67b04/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index cf5f9b1..7817c65 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -273,6 +273,7 @@ struct ble_ll_conn_sm
 #define CONN_F_LE_PING_SUPP(csm)    ((csm)->csmflags.cfbit.le_ping_supp)
 #define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started)
 #define CONN_F_CSA2_SUPP(csm)       ((csm)->csmflags.cfbit.csa2_supp)
+#define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started)
 
 /* Role */
 #define CONN_IS_MASTER(csm)         (csm->conn_role == BLE_LL_CONN_ROLE_MASTER)


[6/6] incubator-mynewt-core git commit: MYNEWT-723: Some additional changes to get the basic 2Mbps PHY support.

Posted by ry...@apache.org.
MYNEWT-723: Some additional changes to get the basic 2Mbps PHY support.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/230462f8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/230462f8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/230462f8

Branch: refs/heads/bluetooth5
Commit: 230462f8f6d76cd37ed58f0524f709ea1e9fe796
Parents: bb2c04e
Author: William San Filippo <wi...@runtime.io>
Authored: Wed Apr 26 16:45:03 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 23:39:50 2017 +0200

----------------------------------------------------------------------
 hw/drivers/nimble/nrf52/src/ble_phy.c               |  3 ++-
 net/nimble/controller/include/controller/ble_ll.h   |  2 +-
 .../controller/include/controller/ble_ll_conn.h     | 13 ++++++++++---
 net/nimble/controller/src/ble_ll_conn.c             | 16 ++++++++--------
 net/nimble/controller/src/ble_ll_ctrl.c             | 14 ++++++++++++--
 net/nimble/controller/src/ble_ll_hci.c              |  8 ++++----
 net/nimble/controller/src/ble_ll_hci_ev.c           |  2 +-
 net/nimble/host/src/ble_hs_dbg.c                    |  5 +++++
 net/nimble/host/src/ble_hs_startup.c                |  3 ++-
 9 files changed, 45 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/hw/drivers/nimble/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index 0ab7cd6..00c0292 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -240,7 +240,8 @@ ble_phy_set_mode(int cur_phy, int txtorx_phy)
         NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0;    /* Default is 8 bits */
     } else if (cur_phy == BLE_PHY_2M) {
         NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit;
-        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 | RADIO_PCNF0_PLEN_16bit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 |
+            (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos);
     } else {
         /* XXX: TODO added coded PHY */
         assert(0);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index 373c3e5..a98d207 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -416,7 +416,7 @@ int ble_ll_rand_start(void);
  * XXX: temporary LL debug log. Will get removed once we transition to real
  * log
  */
-#undef BLE_LL_LOG
+#define BLE_LL_LOG
 #include "console/console.h"
 
 #define BLE_LL_LOG_ID_PHY_SETCHAN       (1)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index 8560316..99d9466 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -128,12 +128,19 @@ union ble_ll_conn_sm_flags {
 /**
  * Structure used for PHY data inside a connection.
  *
+ * NOTE: the new phy's are the phys we will change to when a phy update
+ * procedure is ongoing and the event counter hits the instant.
+ *
  * tx_phy_mode: chip specific phy mode for tx
- * rx_phy_mode: chip specific phy mode for tx
+ * rx_phy_mode: chip specific phy mode for rx
  * cur_tx_phy: value denoting current tx_phy (not a bitmask!)
  * cur_rx_phy: value denoting current rx phy (not a bitmask!)
- * pref_tx_phys: bitmask of preferred transmit PHYs
- * pref_rx_phys: bitmask of preferred receive PHYs
+ * new_tx_phy: value denoting new tx_phy (not a bitmask!)
+ * new_rx_phy: value denoting new rx phy (not a bitmask!)
+ * req_pref_tx_phy: tx phy sent in a phy request (may be different than host)
+ * req_pref_rx_phy: rx phy sent in a phy request (may be different than host)
+ * host_pref_tx_phys: bitmask of preferred transmit PHYs sent by host
+ * host_pref_rx_phys: bitmask of preferred receive PHYs sent by host
  * phy_options: preferred phy options for coded phy
  */
 struct ble_ll_conn_phy_data

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 3236869..9e662ea 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1025,7 +1025,7 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
         STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next);
         ble_hdr = BLE_MBUF_HDR_PTR(m);
 
-        /* WWW: need to check this with phy update procedure. There are
+        /* XXX: TODO: need to check this with phy update procedure. There are
            limitations if we have started update */
 
         /* Determine packet length we will transmit */
@@ -1085,7 +1085,7 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
         /* Get next event time */
         next_event_time = ble_ll_conn_get_next_sched_time(connsm);
 
-        /* WWW: need to check this with phy update procedure. There are
+        /* XXX: TODO: need to check this with phy update procedure. There are
            limitations if we have started update */
 
         /*
@@ -1507,7 +1507,7 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime,
             pkthdr = OS_MBUF_PKTHDR(txpdu);
         }
 
-        /* WWW: need to check this with phy update procedure. There are
+        /* XXX: TODO: need to check this with phy update procedure. There are
            limitations if we have started update */
         if (txpdu) {
             txhdr = BLE_MBUF_HDR_PTR(txpdu);
@@ -2062,6 +2062,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     if (CONN_F_PHY_UPDATE_SCHED(connsm) &&
         (connsm->event_cntr == connsm->phy_instant)) {
+
         /* Set cur phy to new phy */
         connsm->phy_data.cur_tx_phy = connsm->phy_data.new_tx_phy;
         connsm->phy_data.tx_phy_mode = connsm->phy_data.cur_tx_phy;
@@ -3287,8 +3288,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
                         os_mbuf_free_chain(txpdu);
                         connsm->cur_tx_pdu = NULL;
                     } else {
-                        /* WWW: need to check this with phy update procedure. There are
-                           limitations if we have started update */
+                        /*  XXX: TODO need to check with phy update procedure.
+                         *  There are limitations if we have started update */
                         rem_bytes = OS_MBUF_PKTLEN(txpdu) - txhdr->txinfo.offset;
                         if (rem_bytes > connsm->eff_max_tx_octets) {
                             txhdr->txinfo.pyld_len = connsm->eff_max_tx_octets;
@@ -3383,7 +3384,7 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
     ble_hdr->txinfo.pyld_len = length;
     ble_hdr->txinfo.hdr_byte = hdr_byte;
 
-    /* WWW: need to check this with phy update procedure. There are
+    /* XXX: TODO: need to check this with phy update procedure. There are
        limitations if we have started update */
     /*
      * We need to set the initial payload length if the total length of the
@@ -3675,8 +3676,7 @@ ble_ll_conn_module_reset(void)
     conn_params = &g_ble_ll_conn_params;
     max_phy_pyld = ble_phy_max_data_pdu_pyld();
 
-    /* WWW: change these on change of phy */
-
+    /* NOTE: this all assumes that the default phy is 1Mbps */
     maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld);
     conn_params->supp_max_rx_octets = maxbytes;
     conn_params->supp_max_rx_time =

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index 1029bf2..10ec1c0 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -648,8 +648,17 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
 static void
 ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
 {
-    ctrdata[0] = connsm->phy_data.host_pref_tx_phys;
-    ctrdata[1] = connsm->phy_data.host_pref_rx_phys;
+    /* If no preference we use current phy */
+    if (connsm->phy_data.host_pref_tx_phys == 0) {
+        ctrdata[0] = CONN_CUR_TX_PHY_MASK(connsm);
+    } else {
+        ctrdata[0] = connsm->phy_data.host_pref_tx_phys;
+    }
+    if (connsm->phy_data.host_pref_rx_phys == 0) {
+        ctrdata[1] = CONN_CUR_RX_PHY_MASK(connsm);
+    } else {
+        ctrdata[1] = connsm->phy_data.host_pref_rx_phys;
+    }
 }
 
 static uint8_t
@@ -727,6 +736,7 @@ ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
         if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
             ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0);
+            os_callout_stop(&connsm->ctrl_proc_rsp_timer);
             rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index a6e4c56..68cc17e 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -314,8 +314,8 @@ ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy)
     tx_phys = cmdbuf[1] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
     rx_phys = cmdbuf[2] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
 
-    if (((all_phys & BLE_HCI_LE_PHY_TX_PREF) && (tx_phys == 0)) ||
-        ((all_phys & BLE_HCI_LE_PHY_RX_PREF) && (rx_phys == 0))) {
+    if ((!(all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) && (tx_phys == 0)) ||
+        (!(all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) && (rx_phys == 0))) {
         rc = BLE_ERR_INV_HCI_CMD_PARMS;
     } else {
         /* If phy not supported, wipe its bit */
@@ -328,11 +328,11 @@ ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy)
         rx_phys &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
 #endif
         /* Set the default PHY preferences */
-        if ((all_phys & BLE_HCI_LE_PHY_TX_PREF) == 0) {
+        if (all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) {
             tx_phys = 0;
         }
         *txphy = tx_phys;
-        if ((all_phys & BLE_HCI_LE_PHY_RX_PREF) == 0) {
+        if (all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) {
             rx_phys = 0;
         }
         *rxphy = rx_phys;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/controller/src/ble_ll_hci_ev.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci_ev.c b/net/nimble/controller/src/ble_ll_hci_ev.c
index 2ee9908..bd7b8ad 100644
--- a/net/nimble/controller/src/ble_ll_hci_ev.c
+++ b/net/nimble/controller/src/ble_ll_hci_ev.c
@@ -311,7 +311,7 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
         evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
         if (evbuf) {
             evbuf[0] = BLE_HCI_EVCODE_LE_META;
-            evbuf[1] = BLE_HCI_LE_PHY_UPD_COMP_LEN;
+            evbuf[1] = BLE_HCI_LE_PHY_UPD_LEN;
             evbuf[2] = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE;
             evbuf[3] = status;
             put_le16(evbuf + 4, connsm->conn_handle);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/host/src/ble_hs_dbg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_dbg.c b/net/nimble/host/src/ble_hs_dbg.c
index 77c84f1..5599358 100644
--- a/net/nimble/host/src/ble_hs_dbg.c
+++ b/net/nimble/host/src/ble_hs_dbg.c
@@ -144,6 +144,11 @@ ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
                        get_le32(evdata + 2), get_le16(evdata + 10));
         break;
 
+    case BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE:
+            BLE_HS_LOG(DEBUG, "PHY update. handle=%u tx=%u rx=%u\n",
+                       get_le16(evdata + 1), evdata[3], evdata[4]);
+        break;
+
     default:
         BLE_HS_LOG(DEBUG, "\tUnknown LE event\n");
         break;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/230462f8/net/nimble/host/src/ble_hs_startup.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_startup.c b/net/nimble/host/src/ble_hs_startup.c
index f7d5956..fc350de 100644
--- a/net/nimble/host/src/ble_hs_startup.c
+++ b/net/nimble/host/src/ble_hs_startup.c
@@ -117,8 +117,9 @@ ble_hs_startup_le_set_evmask_tx(void)
      *     0x0000000000000020 LE Remote Connection Parameter Request Event
      *     0x0000000000000040 LE Data Length Change Event
      *     0x0000000000000200 LE Enhanced Connection Complete Event
+     *     0x0000000000000800 LE PHY Update Complete Event
      */
-    ble_hs_hci_cmd_build_le_set_event_mask(0x000000000000027f,
+    ble_hs_hci_cmd_build_le_set_event_mask(0x0000000000000A7f,
                                            buf, sizeof buf);
     rc = ble_hs_hci_cmd_tx_empty_ack(buf);
     if (rc != 0) {


[4/6] incubator-mynewt-core git commit: MYNEWT-723: L# 2Mbit and Long range support

Posted by ry...@apache.org.
MYNEWT-723: L# 2Mbit and Long range support

Some refactoring to combine code.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/3f997c2a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3f997c2a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3f997c2a

Branch: refs/heads/bluetooth5
Commit: 3f997c2aec0e8cc70dcb13691e0b218e665310bc
Parents: 4e34701
Author: William San Filippo <wi...@runtime.io>
Authored: Mon Apr 24 09:11:59 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 23:39:25 2017 +0200

----------------------------------------------------------------------
 net/nimble/controller/src/ble_ll_conn_hci.c |  4 +--
 net/nimble/controller/src/ble_ll_ctrl.c     | 33 +++++++++---------------
 2 files changed, 14 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3f997c2a/net/nimble/controller/src/ble_ll_conn_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_hci.c b/net/nimble/controller/src/ble_ll_conn_hci.c
index 4f7390c..6ce5c6b 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -1290,13 +1290,13 @@ ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf)
         CONN_F_HOST_PHY_UPDATE(connsm) = 1;
     } else {
         /*
-         * We could be doing a peer-initiated PHY update procedure. If this
-         * is the case the requested phy preferences will not both be 0. If
+         * We could be doing a peer-initiated PHY update procedure. If
          * we are not done with a peer-initiated procedure we just set the
          * pending bit but do not start the control procedure.
          */
         if (CONN_F_PEER_PHY_UPDATE(connsm)) {
             connsm->pending_ctrl_procs |= BLE_LL_CTRL_PROC_PHY_UPDATE;
+            CONN_F_HOST_PHY_UPDATE(connsm) = 1;
         } else {
             /* Check if we should start phy update procedure */
             if (!ble_ll_conn_chk_phy_upd_start(connsm)) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3f997c2a/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index ed9f336..99a2cd8 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -192,26 +192,24 @@ ble_ll_ctrl_chk_supp_time(uint16_t t)
 
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
 /**
- * Called when an unknown response or ext reject received while performing
- * a PHY update procedure
+ * Called to cancel a phy update procedure.
  *
  * @param connsm
  * @param ble_err
  */
 void
-ble_ll_ctrl_phy_update_rejected(strcut ble_ll_conn_sm *connsm, uint8_t ble_err)
+ble_ll_ctrl_phy_update_cancel(strcut ble_ll_conn_sm *connsm, uint8_t ble_err)
 {
     /* cancel any pending phy update procedures */
     CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
 
     /* Check if the host wants an event */
-    if (CONN_F_HOST_PHY_UPDATE(connsm) == 1) {
+    if (CONN_F_HOST_PHY_UPDATE(connsm)) {
         ble_ll_hci_ev_phy_update(connsm, ble_err);
         CONN_F_HOST_PHY_UPDATE(connsm) = 0;
     }
 
     /* Clear any bits for phy updates that might be in progress */
-    CONN_F_PEER_PHY_UPDATE(connsm) = 0;
     CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
 }
 #endif
@@ -419,7 +417,7 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
         break;
 #if (BLE_LL_BT5_PHY_SUPPORTED ==1)
     case BLE_LL_CTRL_PHY_REQ:
-        ble_ll_ctrl_phy_update_rejected(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
+        ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
         ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
         break;
 #endif
@@ -452,8 +450,6 @@ ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm)
 
     if (CONN_F_PEER_PHY_UPDATE(connsm)) {
         CONN_F_PEER_PHY_UPDATE(connsm) = 0;
-        /* Must check if we need to start procedure */
-        chk_proc_stop = 0;
     } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) {
         CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
     } else {
@@ -467,9 +463,11 @@ ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm)
 
     /* Must check if we need to start host procedure */
     if (chk_host_phy) {
-        if (CONN_F_HOST_PHY_UPDATE(connsm) == 1) {
+        if (CONN_F_HOST_PHY_UPDATE(connsm)) {
             if (ble_ll_conn_chk_phy_upd_start(connsm)) {
                 CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+            } else {
+                chk_proc_stop = 0;
             }
         }
     }
@@ -692,22 +690,15 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
                 connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
             }
 
-            /* If there is a PHY update procedure pending clear it */
-            CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+            /* If there is a PHY update procedure pending cancel it */
+            ble_ll_ctrl_phy_update_cancel(connsm, err);
 
-            /* Need to send event to host if the host phy update is pending */
-            if (CONN_F_HOST_PHY_UPDATE(connsm)) {
-                CONN_F_HOST_PHY_UPDATE(connsm) = 0;
-                ble_ll_hci_ev_phy_update(connsm, err);
-            }
-
-            /* Clear any flags we do not want around */
-            CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+            /* XXX: ? Should not be any phy update events */
             CONN_F_PHY_UPDATE_EVENT(connsm) = 0;
         }
 
         /* XXX: TODO: if we started another procedure with an instant
-           why are we doing this? Need to look into this */
+         * why are we doing this? Need to look into this.*/
 
         /* Respond to master's phy update procedure */
         CONN_F_PEER_PHY_UPDATE(connsm) = 1;
@@ -1454,7 +1445,7 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
 #endif
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     case BLE_LL_CTRL_PROC_PHY_UPDATE:
-        ble_ll_ctrl_phy_update_rejected(connsm, ble_error);
+        ble_ll_ctrl_phy_update_cancel(connsm, ble_error);
         ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
         break;
 #endif


[2/6] incubator-mynewt-core git commit: MYNEWT-723: Add control procedure code and HCI command/event code.

Posted by ry...@apache.org.
MYNEWT-723: Add control procedure code and HCI command/event code.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/4e347012
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/4e347012
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/4e347012

Branch: refs/heads/bluetooth5
Commit: 4e347012011204fd92bf1c3512debe93ae802b2f
Parents: 46d67b0
Author: William San Filippo <wi...@runtime.io>
Authored: Sun Apr 23 15:02:14 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 23:38:58 2017 +0200

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll.h      |  20 +-
 .../controller/include/controller/ble_ll_conn.h |  57 +-
 .../controller/include/controller/ble_ll_ctrl.h |  28 +-
 .../controller/include/controller/ble_ll_hci.h  |   2 +
 net/nimble/controller/src/ble_ll.c              |  12 +
 net/nimble/controller/src/ble_ll_conn.c         |  94 ++++
 net/nimble/controller/src/ble_ll_conn_hci.c     | 128 ++++-
 net/nimble/controller/src/ble_ll_conn_priv.h    |   4 +
 net/nimble/controller/src/ble_ll_ctrl.c         | 543 ++++++++++++++++++-
 net/nimble/controller/src/ble_ll_hci.c          |  83 +++
 net/nimble/controller/src/ble_ll_hci_ev.c       |  33 ++
 net/nimble/controller/syscfg.yml                |  10 +
 net/nimble/include/nimble/hci_common.h          |  10 +-
 13 files changed, 988 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index b2cff88..619d1a9 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -57,6 +57,12 @@ extern "C" {
 
 #endif
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+#define BLE_LL_BT5_PHY_SUPPORTED    (1)
+#else
+#define BLE_LL_BT5_PHY_SUPPORTED    (0)
+#endif
+
 /* Controller revision. */
 #define BLE_LL_SUB_VERS_NR      (0x0000)
 
@@ -90,18 +96,16 @@ struct ble_ll_obj
     /* Number of ACL data packets supported */
     uint8_t ll_num_acl_pkts;
 
-#ifdef BLE_XCVR_RFCLK
-    uint8_t ll_rfclk_state;
-    uint16_t ll_xtal_ticks;
-#else
-    uint8_t _pad;
-    uint16_t _pad16;
-#endif
-
     /* ACL data packet size */
     uint16_t ll_acl_pkt_size;
 
+    /* Preferred PHY's */
+    uint8_t ll_pref_tx_phys;
+    uint8_t ll_pref_rx_phys;
+
 #ifdef BLE_XCVR_RFCLK
+    uint8_t ll_rfclk_state;
+    uint16_t ll_xtal_ticks;
     uint32_t ll_rfclk_start_time;
     struct hal_timer ll_rfclk_timer;
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index 7817c65..d3d7639 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -116,10 +116,40 @@ union ble_ll_conn_sm_flags {
         uint32_t encrypt_chg_sent:1;
         uint32_t le_ping_supp:1;
         uint32_t csa2_supp:1;
+        uint32_t host_phy_update: 1;
+        uint32_t phy_update_sched: 1;
+        uint32_t ctrlr_phy_update: 1;
+        uint32_t phy_update_event: 1;
+        uint32_t peer_phy_update: 1;    /* XXX:combine with ctrlr udpate bit? */
     } cfbit;
     uint32_t conn_flags;
 } __attribute__((packed));
 
+/**
+ * Structure used for PHY data inside a connection.
+ *
+ * cur_tx_phy: value denoting current tx_phy (not a bitmask!)
+ * cur_rx_phy: value denoting current rx phy (not a bitmask)
+ * pref_tx_phys: bitmask of preferred transmit PHYs
+ * pref_rx_phys: bitmask of preferred receive PHYs
+ * phy_options: preferred phy options for coded phy
+ */
+struct ble_ll_conn_phy_data
+{
+    uint8_t cur_tx_phy: 2;
+    uint8_t cur_rx_phy: 2;
+    uint8_t new_tx_phy: 2;
+    uint8_t new_rx_phy: 2;
+    uint16_t host_pref_tx_phys: 3;
+    uint16_t host_pref_rx_phys: 3;
+    uint16_t req_pref_tx_phys: 3;
+    uint16_t req_pref_rx_phys: 3;
+    uint16_t phy_options: 2;
+}  __attribute__((packed));
+
+#define CONN_CUR_TX_PHY_MASK(csm)   (1 << ((csm)->phy_data.cur_tx_phy - 1))
+#define CONN_CUR_RX_PHY_MASK(csm)   (1 << ((csm)->phy_data.cur_rx_phy - 1))
+
 /* Connection state machine */
 struct ble_ll_conn_sm
 {
@@ -131,6 +161,12 @@ struct ble_ll_conn_sm
     uint8_t conn_state;
     uint8_t conn_role;          /* Can possibly be 1 bit */
 
+    /* RSSI */
+    int8_t conn_rssi;
+
+    /* For privacy */
+    int8_t rpa_index;
+
     /* Connection data length management */
     uint8_t max_tx_octets;
     uint8_t max_rx_octets;
@@ -145,6 +181,10 @@ struct ble_ll_conn_sm
     uint16_t eff_max_tx_time;
     uint16_t eff_max_rx_time;
 
+    /* XXX: TODO: could make this conditional */
+    struct ble_ll_conn_phy_data phy_data;
+    uint16_t phy_instant;
+
     /* Used to calculate data channel index for connection */
     uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
     uint8_t req_chanmap[BLE_LL_CONN_CHMAP_LEN];
@@ -155,9 +195,6 @@ struct ble_ll_conn_sm
     uint8_t last_unmapped_chan;
     uint8_t num_used_chans;
 
-    /* RSSI */
-    int8_t conn_rssi;
-
     /* Ack/Flow Control */
     uint8_t tx_seqnum;          /* note: can be 1 bit */
     uint8_t next_exp_seqnum;    /* note: can be 1 bit */
@@ -166,9 +203,6 @@ struct ble_ll_conn_sm
     uint8_t last_rxd_hdr_byte;  /* note: possibly can make 1 bit since we
                                    only use the MD bit now */
 
-    /* For privacy */
-    int8_t rpa_index;
-
     /* connection event mgmt */
     uint8_t reject_reason;
     uint8_t host_reply_opcode;
@@ -177,8 +211,8 @@ struct ble_ll_conn_sm
     uint8_t cur_ctrl_proc;
     uint8_t disconnect_reason;
     uint8_t rxd_disconnect_reason;
-    uint32_t common_features;
     uint8_t vers_nr;
+    uint32_t common_features;
     uint16_t pending_ctrl_procs;
     uint16_t event_cntr;
     uint16_t completed_pkts;
@@ -216,6 +250,10 @@ struct ble_ll_conn_sm
     uint8_t peer_addr_type;
     uint8_t peer_addr[BLE_DEV_ADDR_LEN];
 
+    /*
+     * XXX: TODO. Could save memory. Have single event at LL and put these
+     * on a singly linked list. Only would need list pointer here.
+     */
     /* Connection end event */
     struct os_event conn_ev_end;
 
@@ -274,6 +312,11 @@ struct ble_ll_conn_sm
 #define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started)
 #define CONN_F_CSA2_SUPP(csm)       ((csm)->csmflags.cfbit.csa2_supp)
 #define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started)
+#define CONN_F_HOST_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.host_phy_update)
+#define CONN_F_PHY_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.phy_update_sched)
+#define CONN_F_CTRLR_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.ctrlr_phy_update)
+#define CONN_F_PHY_UPDATE_EVENT(csm) ((csm)->csmflags.cfbit.phy_update_event)
+#define CONN_F_PEER_PHY_UPDATE(csm)  ((csm)->csmflags.cfbit.peer_phy_update)
 
 /* Role */
 #define CONN_IS_MASTER(csm)         (csm->conn_role == BLE_LL_CONN_ROLE_MASTER)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/include/controller/ble_ll_ctrl.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_ctrl.h b/net/nimble/controller/include/controller/ble_ll_ctrl.h
index 23da308..95f56c4 100644
--- a/net/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -38,7 +38,8 @@ extern "C" {
 #define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6)
 #define BLE_LL_CTRL_PROC_LE_PING        (7)
 #define BLE_LL_CTRL_PROC_DATA_LEN_UPD   (8)
-#define BLE_LL_CTRL_PROC_NUM            (9)
+#define BLE_LL_CTRL_PROC_PHY_UPDATE     (9)
+#define BLE_LL_CTRL_PROC_NUM            (10)
 #define BLE_LL_CTRL_PROC_IDLE           (255)
 
 /* Checks if a particular control procedure is running */
@@ -75,9 +76,13 @@ extern "C" {
 #define BLE_LL_CTRL_PING_RSP            (19)
 #define BLE_LL_CTRL_LENGTH_REQ          (20)
 #define BLE_LL_CTRL_LENGTH_RSP          (21)
+#define BLE_LL_CTRL_PHY_REQ             (22)
+#define BLE_LL_CTRL_PHY_RSP             (23)
+#define BLE_LL_CTRL_PHY_UPDATE_IND      (24)
+#define BLE_LL_CTRL_MIN_USED_CHAN_IND   (25)
 
 /* Maximum opcode value */
-#define BLE_LL_CTRL_OPCODES             (BLE_LL_CTRL_LENGTH_RSP + 1)
+#define BLE_LL_CTRL_OPCODES             (BLE_LL_CTRL_MIN_USED_CHAN_IND + 1)
 
 extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
 
@@ -131,6 +136,12 @@ struct ble_ll_enc_rsp
 
 #define BLE_LL_CTRL_ENC_RSP_LEN             (12)
 
+/* LL control start/pause enc request and response */
+#define BLE_LL_CTRL_START_ENC_REQ_LEN       (0)
+#define BLE_LL_CTRL_START_ENC_RSP_LEN       (0)
+#define BLE_LL_CTRL_PAUSE_ENC_REQ_LEN       (0)
+#define BLE_LL_CTRL_PAUSE_ENC_RSP_LEN       (0)
+
 /*
  * LL control unknown response
  *  -> 1 byte which contains the unknown or un-supported opcode.
@@ -190,7 +201,7 @@ struct ble_ll_conn_params
     uint16_t offset5;
 };
 
-#define BLE_LL_CTRL_CONN_PARAMS_LEN     (24)
+#define BLE_LL_CTRL_CONN_PARAMS_LEN     (23)
 
 /* LL control reject ind ext */
 struct ble_ll_reject_ind_ext
@@ -221,6 +232,14 @@ struct ble_ll_len_req
 
 #define BLE_LL_CTRL_LENGTH_REQ_LEN      (8)
 
+/* PHY request/response */
+#define BLE_LL_CTRL_PHY_REQ_LEN         (2)
+#define BLE_LL_CTRL_PHY_RSP_LEN         (2)
+#define BLE_LL_CTRL_PHY_UPD_IND_LEN     (4)
+
+/* Min used channels */
+#define BLE_LL_CTRL_MIN_USED_CHAN_LEN   (2)
+
 /* API */
 struct ble_ll_conn_sm;
 void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
@@ -251,8 +270,9 @@ int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm);
 int ble_ll_hci_ev_hw_err(uint8_t hw_err);
 void ble_ll_hci_ev_databuf_overflow(void);
 void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm);
-
+int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status);
 void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm);
+void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/include/controller/ble_ll_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_hci.h b/net/nimble/controller/include/controller/ble_ll_hci.h
index c2c4542..e54ec7e 100644
--- a/net/nimble/controller/include/controller/ble_ll_hci.h
+++ b/net/nimble/controller/include/controller/ble_ll_hci.h
@@ -54,6 +54,8 @@ int ble_ll_hci_event_send(uint8_t *evbuf);
 /* Sends a command complete with a no-op opcode to host */
 int ble_ll_hci_send_noop(void);
 
+/* Checks the preferref phy masks from set default phy and set phy commands */
+int ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 5fe03d0..eb1534b 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -1174,6 +1174,10 @@ ble_ll_reset(void)
     memset(&g_ble_ll_log, 0, sizeof(g_ble_ll_log));
 #endif
 
+    /* Reset any preferred PHYs */
+    g_ble_ll_data.ll_pref_tx_phys = 0;
+    g_ble_ll_data.ll_pref_rx_phys = 0;
+
     /* Reset connection module */
     ble_ll_conn_module_reset();
 
@@ -1344,6 +1348,14 @@ ble_ll_init(void)
     features |= BLE_LL_FEAT_CSA2;
 #endif
 
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) == 1)
+    features |= BLE_LL_FEAT_LE_2M_PHY;
+#endif
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
+    features |= BLE_LL_FEAT_LE_CODED_PHY;
+#endif
+
     /* Initialize random number generation */
     ble_ll_rand_init();
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index e981cd7..0efbba2 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -229,6 +229,42 @@ STATS_NAME_END(ble_ll_conn_stats)
 
 static void ble_ll_conn_event_end(struct os_event *ev);
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/**
+ * Checks to see if we should start a PHY update procedure
+ *
+ * If current phy is not one of the preferred we need to start control
+ * procedure.
+ *
+ * XXX: we could also decide to change the PHY if RSSI is really good
+ * and we are currently at 1Mbps or lower data rate and we could use
+ * a higher data rate.
+ *
+ * @param connsm
+ * @return 0: success; -1: no phy update procedure started
+ */
+int
+ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm)
+{
+    int rc;
+
+    /* If no host preferences or  */
+    if (((csm->phy_data.host_pref_tx_phys == 0) &&
+         (csm->phy_data.host_pref_rx_phys == 0)) ||
+        ((csm->phy_data.host_pref_tx_phys & CONN_CUR_TX_PHY_MASK(csm)) &&
+         (csm->phy_data.host_pref_rx_phys & CONN_CUR_RX_PHY_MASK(csm)))) {
+        rc = -1;
+    } else {
+        csm->phy_data.req_pref_tx_phys = csm->phy_data.host_pref_tx_phys;
+        csm->phy_data.req_pref_rx_phys = csm->phy_data.host_pref_rx_phys;
+        ble_ll_ctrl_proc_start(csm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+        rc = 0;
+    }
+
+    return rc;
+}
+#endif
+
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
 static void
 ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm)
@@ -905,6 +941,16 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm)
         ble_ll_hci_ev_conn_update(connsm, update_status);
         connsm->csmflags.cfbit.host_expects_upd_event = 0;
     }
+
+    /* Check if we need to send PHY update complete event */
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    if (CONN_F_PHY_UPDATE_EVENT(connsm)) {
+        if (!ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS)) {
+            /* Sent event. Clear flag */
+            CONN_F_PHY_UPDATE_EVENT(connsm) = 0;
+        }
+    }
+#endif
 }
 
 /**
@@ -1640,6 +1686,17 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
     connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI;
     connsm->rpa_index = -1;
 
+    /* XXX: TODO set these based on PHY that started connection */
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    connsm->phy_data.cur_tx_phy = BLE_HCI_LE_PHY_1M;
+    connsm->phy_data.cur_rx_phy = BLE_HCI_LE_PHY_1M;
+    connsm->phy_data.req_pref_tx_phys = 0;
+    connsm->phy_data.req_pref_rx_phys = 0;
+    connsm->phy_data.host_pref_tx_phys = g_ble_ll_data.ll_pref_tx_phys;
+    connsm->phy_data.host_pref_rx_phys = g_ble_ll_data.ll_pref_rx_phys;
+    connsm->phy_data.phy_options = 0;
+#endif
+
     /* Reset current control procedure */
     connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
     connsm->pending_ctrl_procs = 0;
@@ -1836,6 +1893,8 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
 /**
  * Called to move to the next connection event.
  *
+ * Context: Link Layer task.
+ *
  * @param connsm
  *
  * @return int
@@ -1861,11 +1920,18 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         ble_ll_ctrl_terminate_start(connsm);
     }
 
+    /*
+     * XXX TODO: I think this is technically incorrect. We can allow slave
+     * latency if we are doing one of these updates as long as we
+     * know that the master has received the ACK to the PDU that set
+     * the instant
+     */
     /* Set event counter to the next connection event that we will tx/rx in */
     itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
     latency = 1;
     if (connsm->csmflags.cfbit.allow_slave_latency      &&
         !connsm->csmflags.cfbit.conn_update_sched       &&
+        !CONN_F_PHY_UPDATE_SCHED(connsm)                &&
         !connsm->csmflags.cfbit.chanmap_update_scheduled) {
         if (connsm->csmflags.cfbit.pkt_rxd) {
             latency += connsm->slave_latency;
@@ -1974,6 +2040,21 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
            check to make sure we dont have to restart! */
     }
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    if (CONN_F_PHY_UPDATE_SCHED(connsm) &&
+        (connsm->event_cntr == connsm->phy_instant)) {
+        /* Set cur phy to new phy */
+        connsm->phy_data.cur_tx_phy = connsm->phy_data.new_tx_phy;
+        connsm->phy_data.cur_rx_phy = connsm->phy_data.new_rx_phy;
+
+        /* Clear flags and set flag to send event at next instant */
+        CONN_F_PHY_UPDATE_SCHED(connsm) = 0;
+        CONN_F_PHY_UPDATE_EVENT(connsm) = 1;
+
+        ble_ll_ctrl_phy_update_proc_complete(connsm);
+    }
+#endif
+
     /* Calculate data channel index of next connection event */
     connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, latency);
 
@@ -2125,6 +2206,19 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
 
     /* Send connection complete event to inform host of connection */
     if (rc) {
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+        /*
+         * If we have default phy preferences and they are different than
+         * the current PHY's in use, start update procedure.
+         */
+        /*
+         * XXX: should we attempt to start this without knowing if
+         * the other side can support it?
+         */
+        if (!ble_ll_conn_chk_phy_upd_start(connsm)) {
+            CONN_F_CTRLR_PHY_UPDATE(connsm) = 1;
+        }
+#endif
         /*
          * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
          * exceeds the minimum, data length procedure needs to occur

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_conn_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_hci.c b/net/nimble/controller/src/ble_ll_conn_hci.c
index 429fcb3..4f7390c 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -236,13 +236,6 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
 /**
  * Called to create and send the number of completed packets event to the
  * host.
- *
- * Because of the ridiculous spec, all the connection handles are contiguous
- * and then all the completed packets are contiguous. In order to avoid
- * multiple passes through the connection list or allocating a large stack
- * variable or malloc, I just use the event buffer and place the completed
- * packets after the last possible handle. I then copy the completed packets
- * to make it contiguous with the handles.
  */
 void
 ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm)
@@ -1021,7 +1014,8 @@ ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
 
         /*
          * XXX: For now; we will simply ignore what the host asks as we are
-         * allowed to do so by the spec.
+         * allowed to do so by the spec. If we implement this and something
+         * changes we need to send data length change event.
          */
     }
 
@@ -1204,3 +1198,121 @@ wr_auth_exit:
     return rc;
 }
 #endif
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/**
+ * Read current phy for connection (OGF=8, OCF==0x0030)
+ *
+ * @param cmdbuf
+ * @param rsplen
+ *
+ * @return int
+ */
+int
+ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
+{
+    int rc;
+    uint16_t handle;
+    struct ble_ll_conn_sm *connsm;
+
+    handle = get_le16(cmdbuf);
+    connsm = ble_ll_conn_find_active_conn(handle);
+    if (!connsm) {
+        rc = BLE_ERR_UNK_CONN_ID;
+    } else {
+        rsp[2] = connsm->phy_data.cur_tx_phy;
+        rsp[3] = connsm->phy_data.cur_rx_phy;
+        rc = BLE_ERR_SUCCESS;
+    }
+
+    put_le16(rsp, handle);
+    *rsplen = BLE_HCI_LE_RD_PHY_RSPLEN;
+    return rc;
+}
+
+/**
+ * Set PHY preferences for connection
+ *
+ * @param cmdbuf
+ *
+ * @return int
+ */
+int
+ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf)
+{
+    int rc;
+    uint8_t phy_options;
+    uint8_t tx_phys;
+    uint8_t rx_phys;
+    uint16_t handle;
+    struct ble_ll_conn_sm *connsm;
+
+    handle = get_le16(cmdbuf);
+    connsm = ble_ll_conn_find_active_conn(handle);
+    if (!connsm) {
+        return BLE_ERR_UNK_CONN_ID;
+    }
+
+    /*
+     * If host has requested a PHY update and we are not finished do
+     * not allow another one
+     */
+    if (CONN_F_HOST_PHY_UPDATE(connsm)) {
+        return BLE_ERR_CMD_DISALLOWED;
+    }
+
+    phy_options = cmdbuf[5];
+    if (phy_options > BLE_HCI_LE_PHY_CODED_S8_PREF) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+    connsm->phy_data.phy_options = phy_options;
+
+    /* Check valid parameters */
+    rc = ble_ll_hci_chk_phy_masks(cmdbuf + 2, &tx_phys, &rx_phys);
+    if (rc) {
+        goto phy_cmd_param_err;
+    }
+
+    connsm->phy_data.host_pref_tx_phys = tx_phys,
+    connsm->phy_data.host_pref_rx_phys = rx_phys;
+
+    /*
+     * The host preferences override the default phy preferences. Currently,
+     * the only reason the controller will initiate a procedure on its own
+     * is due to the fact that the host set default preferences. So if there
+     * is a pending control procedure and it has not yet started, we do not
+     * need to perform the default controller procedure.
+     */
+    if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE)) {
+        if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_PHY_UPDATE) {
+            CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+        }
+        CONN_F_HOST_PHY_UPDATE(connsm) = 1;
+    } else {
+        /*
+         * We could be doing a peer-initiated PHY update procedure. If this
+         * is the case the requested phy preferences will not both be 0. If
+         * we are not done with a peer-initiated procedure we just set the
+         * pending bit but do not start the control procedure.
+         */
+        if (CONN_F_PEER_PHY_UPDATE(connsm)) {
+            connsm->pending_ctrl_procs |= BLE_LL_CTRL_PROC_PHY_UPDATE;
+        } else {
+            /* Check if we should start phy update procedure */
+            if (!ble_ll_conn_chk_phy_upd_start(connsm)) {
+                CONN_F_HOST_PHY_UPDATE(connsm) = 1;
+            } else {
+                /*
+                 * Set flag to send a PHY update complete event. We set flag
+                 * even if we do not do an update procedure since we have to
+                 * inform the host even if we decide not to change anything.
+                 */
+                CONN_F_PHY_UPDATE_EVENT(connsm) = 1;
+            }
+        }
+    }
+
+phy_cmd_param_err:
+    return rc;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h b/net/nimble/controller/src/ble_ll_conn_priv.h
index 02cac60..13e03cf 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -162,6 +162,10 @@ void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
 int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
 int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
 
+int ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen);
+int ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf);
+int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index fe0831b..ed9f336 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -79,9 +79,88 @@
  */
 const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
 {
-    11, 7, 1, 22, 12, 0, 0, 1, 8, 8, 0, 0, 5, 1, 8, 23, 23, 2, 0, 0, 8, 8
+    BLE_LL_CTRL_CONN_UPD_REQ_LEN,
+    BLE_LL_CTRL_CHAN_MAP_LEN,
+    BLE_LL_CTRL_TERMINATE_IND_LEN,
+    BLE_LL_CTRL_ENC_REQ_LEN,
+    BLE_LL_CTRL_ENC_RSP_LEN,
+    BLE_LL_CTRL_START_ENC_REQ_LEN,
+    BLE_LL_CTRL_START_ENC_RSP_LEN,
+    BLE_LL_CTRL_UNK_RSP_LEN,
+    BLE_LL_CTRL_FEATURE_LEN,
+    BLE_LL_CTRL_FEATURE_LEN,
+    BLE_LL_CTRL_PAUSE_ENC_REQ_LEN,
+    BLE_LL_CTRL_PAUSE_ENC_RSP_LEN,
+    BLE_LL_CTRL_VERSION_IND_LEN,
+    BLE_LL_CTRL_REJ_IND_LEN,
+    BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN,
+    BLE_LL_CTRL_CONN_PARAMS_LEN,
+    BLE_LL_CTRL_CONN_PARAMS_LEN,
+    BLE_LL_CTRL_REJECT_IND_EXT_LEN,
+    BLE_LL_CTRL_PING_LEN,
+    BLE_LL_CTRL_PING_LEN,
+    BLE_LL_CTRL_LENGTH_REQ_LEN,
+    BLE_LL_CTRL_LENGTH_REQ_LEN,
+    BLE_LL_CTRL_PHY_REQ_LEN,
+    BLE_LL_CTRL_PHY_RSP_LEN,
+    BLE_LL_CTRL_PHY_UPD_IND_LEN,
+    BLE_LL_CTRL_MIN_USED_CHAN_LEN
 };
 
+/**
+ * Called to determine if a LL control procedure with an instant has
+ * been initiated.
+ *
+ * If the function returns a 0 it means no conflicting procedure has
+ * been initiated. Otherwise it returns the appropriate BLE error code to
+ * send.
+ *
+ * @param connsm Pointer to connection state machine.
+ * @param req_ctrl_proc The procedure that the peer is trying to initiate
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_ll_ctrl_proc_with_instant_initiated(struct ble_ll_conn_sm *connsm,
+                                        uint8_t req_ctrl_proc)
+{
+    uint8_t err;
+
+    switch (connsm->cur_ctrl_proc) {
+    case BLE_LL_CTRL_PROC_PHY_UPDATE:
+    case BLE_LL_CTRL_PROC_CONN_UPDATE:
+    case BLE_LL_CTRL_PROC_CONN_PARAM_REQ:
+    case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
+        if (req_ctrl_proc == connsm->cur_ctrl_proc) {
+            err = BLE_ERR_LMP_COLLISION;
+        } else if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_UPDATE) &&
+                   (req_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) {
+            err = BLE_ERR_LMP_COLLISION;
+        } else {
+            err = BLE_ERR_DIFF_TRANS_COLL;
+        }
+        break;
+    default:
+        err = 0;
+    }
+
+    return err;
+}
+
+/**
+ * Create a LL_REJECT_EXT_IND pdu.
+ *
+ * @param rej_opcode Opcode to be rejected.
+ * @param err: error response
+ * @param ctrdata: Pointer to where CtrData starts in pdu
+ */
+void
+ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata)
+{
+    ctrdata[0] = rej_opcode;
+    ctrdata[1] = err;
+}
+
 static int
 ble_ll_ctrl_chk_supp_bytes(uint16_t bytes)
 {
@@ -111,6 +190,32 @@ ble_ll_ctrl_chk_supp_time(uint16_t t)
     return rc;
 }
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/**
+ * Called when an unknown response or ext reject received while performing
+ * a PHY update procedure
+ *
+ * @param connsm
+ * @param ble_err
+ */
+void
+ble_ll_ctrl_phy_update_rejected(strcut ble_ll_conn_sm *connsm, uint8_t ble_err)
+{
+    /* cancel any pending phy update procedures */
+    CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+
+    /* Check if the host wants an event */
+    if (CONN_F_HOST_PHY_UPDATE(connsm) == 1) {
+        ble_ll_hci_ev_phy_update(connsm, ble_err);
+        CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+    }
+
+    /* Clear any bits for phy updates that might be in progress */
+    CONN_F_PEER_PHY_UPDATE(connsm) = 0;
+    CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+}
+#endif
+
 static int
 ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
 {
@@ -312,6 +417,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
 #endif
         ctrl_proc = BLE_LL_CTRL_PROC_LE_PING;
         break;
+#if (BLE_LL_BT5_PHY_SUPPORTED ==1)
+    case BLE_LL_CTRL_PHY_REQ:
+        ble_ll_ctrl_phy_update_rejected(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
+        ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
+        break;
+#endif
     default:
         ctrl_proc = BLE_LL_CTRL_PROC_NUM;
         break;
@@ -329,6 +440,394 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
     }
 }
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+void
+ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm)
+{
+    int chk_proc_stop;
+    int chk_host_phy;
+
+    chk_proc_stop = 1;
+    chk_host_phy = 1;
+
+    if (CONN_F_PEER_PHY_UPDATE(connsm)) {
+        CONN_F_PEER_PHY_UPDATE(connsm) = 0;
+        /* Must check if we need to start procedure */
+        chk_proc_stop = 0;
+    } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) {
+        CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+    } else {
+        /* Must be a host-initiated update */
+        CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+        chk_host_phy = 0;
+        if (CONN_F_PHY_UPDATE_EVENT(connsm) == 0) {
+            ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS);
+        }
+    }
+
+    /* Must check if we need to start host procedure */
+    if (chk_host_phy) {
+        if (CONN_F_HOST_PHY_UPDATE(connsm) == 1) {
+            if (ble_ll_conn_chk_phy_upd_start(connsm)) {
+                CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+            }
+        }
+    }
+
+    if (chk_proc_stop) {
+        ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+    }
+}
+
+/**
+ * Convert a phy mask to a numeric phy value.
+ *
+ * NOTE: only one bit should be set here and there should be at least one.
+ * If this function returns a 0 it is an error!
+ *
+ * @param phy_mask Bitmask of phy
+ *
+ * @return uint8_t The numeric value associated with the phy mask
+ *
+ * BLE_HCI_LE_PHY_1M                    (1)
+ * BLE_HCI_LE_PHY_2M                    (2)
+ * BLE_HCI_LE_PHY_CODED                 (3)
+ */
+static uint8_t
+ble_ll_ctrl_phy_mask_to_numeric(uint8_t phy_mask)
+{
+    uint8_t numeric;
+
+    /*
+     * NOTE: wipe out unsupported PHYs. There should not be an unsupported
+     * in this mask if the other side is working correctly.
+     */
+#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+    phy_mask &= ~BLE_HCI_LE_PHY_2M_PREF_MASK;
+#endif
+#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+    phy_mask &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
+#endif
+
+    if (phy_mask & BLE_HCI_LE_PHY_1M_PREF_MASK) {
+        numeric = BLE_HCI_LE_PHY_1M;
+        phy_mask &= ~BLE_HCI_LE_PHY_1M_PREF_MASK;
+    } else if (phy_mask & BLE_HCI_LE_PHY_2M_PREF_MASK) {
+        numeric = BLE_HCI_LE_PHY_2M;
+        phy_mask &= ~BLE_HCI_LE_PHY_2M_PREF_MASK;
+    } else if (phy_mask & BLE_HCI_LE_PHY_CODED_PREF_MASK) {
+        numeric = BLE_HCI_LE_PHY_CODED;
+        phy_mask &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
+    } else {
+        numeric = 0;
+    }
+
+    if (phy_mask != 0) {
+        numeric = 0;
+    }
+
+    return numeric;
+}
+
+/**
+ *
+ *  There is probably a better way for the controller to choose which PHY use.
+ *  There are no BER metrics and RSSI does not give you S/N so for now we will
+ *  choose this heirarchy:
+ *     -> if 2Mbps available, use it.
+ *     -> If 1Mbps available, use it.
+ *     -> otherwise use coded phy.
+ *
+ * @param prefs The mask of preferred phys
+ * @return uint8_t The phy to use (not a mask)
+ */
+static uint8_t
+ble_ll_ctrl_find_new_phy(uint8_t prefs)
+{
+    uint8_t new_phy;
+
+    new_phy = prefs;
+    if (new_phy) {
+        if (new_phy & BLE_HCI_LE_PHY_2M_PREF_MASK) {
+            new_phy = BLE_HCI_LE_PHY_2M;
+        } else if (new_phy & BLE_HCI_LE_PHY_1M_PREF_MASK) {
+            new_phy = BLE_HCI_LE_PHY_1M;
+        } else {
+            new_phy = BLE_HCI_LE_PHY_CODED;
+        }
+    }
+
+    return new_phy;
+}
+
+/**
+ * Create a LL_PHY_UPDATE_IND pdu
+ *
+ * @param connsm Pointer to connection state machine
+ * @param dptr Pointer to PHY_REQ or PHY_RSP data.
+ * @param ctrdata: Pointer to where CtrData of UPDATE_IND pdu starts
+ * @param slave_req flag denoting if slave requested this. 0: no 1:yes
+ */
+static void
+ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
+                                uint8_t *ctrdata, int slave_req)
+{
+    uint8_t m_to_s;
+    uint8_t s_to_m;
+    uint8_t tx_phys;
+    uint8_t rx_phys;
+    uint16_t instant;
+
+    /* Get preferences from PDU */
+    tx_phys = dptr[0];
+    rx_phys = dptr[1];
+
+    /* Get m_to_s and s_to_m masks */
+    if (slave_req) {
+        m_to_s = connsm->phy_data.host_pref_tx_phys & rx_phys;
+        s_to_m = connsm->phy_data.host_pref_rx_phys & tx_phys;
+    } else {
+        m_to_s = connsm->phy_data.req_pref_tx_phys & rx_phys;
+        s_to_m = connsm->phy_data.req_pref_rx_phys & tx_phys;
+    }
+
+    /* Find new phys. If not different than current, set to 0 */
+    m_to_s = ble_ll_ctrl_find_new_phy(m_to_s);
+    if (m_to_s == connsm->phy_data.cur_tx_phy) {
+        m_to_s = 0;
+    }
+
+    s_to_m = ble_ll_ctrl_find_new_phy(s_to_m);
+    if (s_to_m == connsm->phy_data.cur_rx_phy) {
+        s_to_m = 0;
+    }
+
+    /* At this point, m_to_s and s_to_m are not masks; they are numeric */
+
+    /*
+     * If not changing we still send update ind. Check if hosts expects
+     * the event and if so send it. Stop control procedure if it is the
+     * one running.
+     */
+    if ((m_to_s == 0) && (s_to_m == 0)) {
+        if (CONN_F_PEER_PHY_UPDATE(connsm)) {
+            CONN_F_PEER_PHY_UPDATE(connsm) = 0;
+        } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) {
+            CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+            ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+        } else {
+            ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS);
+            CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+            ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+        }
+        instant = 0;
+    } else {
+        /* Determine instant we will use. 6 more is minimum */
+        instant = connsm->event_cntr + connsm->slave_latency + 6 + 1;
+        connsm->phy_instant = instant;
+        CONN_F_PHY_UPDATE_SCHED(connsm) = 1;
+
+        /* Convert m_to_s and s_to_m to masks */
+        m_to_s = 1 << (m_to_s - 1);
+        s_to_m = 1 << (s_to_m - 1);
+
+        /* Set new phys to use when instant occurs */
+        connsm->phy_data.new_tx_phy = m_to_s;
+        connsm->phy_data.new_rx_phy = s_to_m;
+    }
+
+    ctrdata[0] = m_to_s;
+    ctrdata[1] = s_to_m;
+    put_le16(ctrdata + 2, instant);
+}
+
+/**
+ * Create a LL_PHY_REQ or LL_PHY_RSP pdu
+ *
+ * @param connsm Pointer to connection state machine
+ * @param ctrdata: Pointer to where CtrData starts in pdu
+ */
+static void
+ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
+{
+    ctrdata[0] = connsm->phy_data.host_pref_tx_phys;
+    ctrdata[1] = connsm->phy_data.host_pref_rx_phys;
+}
+
+static uint8_t
+ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
+                       uint8_t *rsp)
+{
+    uint8_t rsp_opcode;
+    uint8_t err;
+
+    /*
+     * XXX: TODO if we have an instant in progress we should end connection.
+     * At least it seems that is the case. Need to figure out more from
+     * the spec here.
+     */
+
+    /* Check if we have already initiated a procedure with an instant */
+    err = ble_ll_ctrl_proc_with_instant_initiated(connsm,
+                                                  BLE_LL_CTRL_PROC_PHY_UPDATE);
+
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+        if (err) {
+            ble_ll_ctrl_rej_ext_ind_make(BLE_LL_CTRL_PHY_REQ, err, rsp);
+            rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
+        } else {
+            /*
+             * NOTE: do not change order of these two lines as the call to
+             * make the LL_PHY_UPDATE_IND pdu might clear the flag.
+             */
+            CONN_F_PEER_PHY_UPDATE(connsm) = 1;
+            ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1);
+            rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
+        }
+    } else {
+        /* XXX: deal with other control procedures that we need to stop */
+        if (err) {
+            if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
+                os_callout_stop(&connsm->ctrl_proc_rsp_timer);
+                connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
+            }
+
+            /* If there is a PHY update procedure pending clear it */
+            CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+
+            /* Need to send event to host if the host phy update is pending */
+            if (CONN_F_HOST_PHY_UPDATE(connsm)) {
+                CONN_F_HOST_PHY_UPDATE(connsm) = 0;
+                ble_ll_hci_ev_phy_update(connsm, err);
+            }
+
+            /* Clear any flags we do not want around */
+            CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
+            CONN_F_PHY_UPDATE_EVENT(connsm) = 0;
+        }
+
+        /* XXX: TODO: if we started another procedure with an instant
+           why are we doing this? Need to look into this */
+
+        /* Respond to master's phy update procedure */
+        CONN_F_PEER_PHY_UPDATE(connsm) = 1;
+        ble_ll_ctrl_phy_req_rsp_make(connsm, rsp);
+        rsp_opcode = BLE_LL_CTRL_PHY_RSP;
+    }
+    return rsp_opcode;
+}
+
+/**
+ * Process a received LL_PHY_RSP pdu
+ *
+ * @param connsm
+ * @param dptr Pointer to LL_PHY_RSP ctrdata
+ * @param rsp Pointer to CtrData of PHY_UPDATE_IND.
+ *
+ * @return uint8_t
+ */
+static uint8_t
+ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
+                       uint8_t *rsp)
+{
+    uint8_t rsp_opcode;
+
+    rsp_opcode = BLE_ERR_MAX;
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+        if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
+            ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0);
+            rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
+        }
+
+        /*
+         * If not in the process of doing this control procedure something
+         * is wrong. End connection? Assert?
+         *
+         * XXX: TODO count some stat?
+         */
+    }
+
+    /* NOTE: slave should never receive one of these */
+
+    return rsp_opcode;
+}
+
+/**
+ * Called when a LL_PHY_UPDATE_IND pdu is received
+ *
+ * NOTE: slave is the only device that should receive this.
+ *
+ * @param connsm
+ * @param dptr
+ */
+void
+ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+    uint8_t new_tx_phy_mask;
+    uint8_t new_rx_phy_mask;
+    uint8_t new_tx_phy;
+    uint8_t new_rx_phy;
+    int no_change;
+    uint16_t instant;
+    uint16_t delta;
+
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+        /*
+         * Reception stops the procedure response timer but does not
+         * complete the procedure
+         */
+        if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
+            os_callout_stop(&connsm->ctrl_proc_rsp_timer);
+        }
+
+        /*
+         * XXX: Should we check to see if we are expecting to receive one
+         * of these, and if not, kill connection? Meaning we better be
+         * doing either a PEER, CTRLR, or HOST phy update.
+         */
+        /* get the new phy masks and see if we need to change */
+        new_tx_phy_mask = dptr[0];
+        new_rx_phy_mask = dptr[1];
+        instant = get_le16(dptr + 2);
+
+        no_change = 0;
+        if ((new_tx_phy_mask == 0) && (new_rx_phy_mask == 0)) {
+            /* No change in phy */
+            no_change = 1;
+        } else {
+            new_tx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_tx_phy_mask);
+            new_rx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_rx_phy_mask);
+
+            if ((new_tx_phy == 0) && (new_rx_phy == 0)) {
+                /* XXX: this is an error! What to do??? */
+                no_change = 1;
+            }
+
+            if ((new_tx_phy == connsm->phy_data.cur_tx_phy) &&
+                (new_rx_phy == connsm->phy_data.cur_tx_phy)) {
+                no_change = 1;
+            }
+        }
+
+        if (!no_change) {
+            /* If instant is in the past, we have to end the connection */
+            delta = (instant - connsm->event_cntr) & 0xFFFF;
+            if (delta >= 32767) {
+                ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED);
+            } else {
+                connsm->phy_data.new_tx_phy = new_tx_phy;
+                connsm->phy_data.new_rx_phy = new_rx_phy;
+                connsm->phy_instant = instant;
+                CONN_F_PHY_UPDATE_SCHED(connsm) = 1;
+            }
+            return;
+        }
+
+        ble_ll_ctrl_phy_update_proc_complete(connsm);
+    }
+}
+#endif
+
 /**
  * Create a link layer length request or length response PDU.
  *
@@ -461,7 +960,6 @@ ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu)
  * Called to create and send a LL_START_ENC_REQ or LL_START_ENC_RSP
  *
  * @param connsm
- * @param rej_opcode
  * @param err
  *
  * @return int
@@ -919,7 +1417,7 @@ ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp,
 
 /**
  * Called when we have received a LL_REJECT_IND or LL_REJECT_IND_EXT link
- * layer control Dat Channel pdu.
+ * layer control Data Channel pdu.
  *
  * @param connsm
  * @param dptr
@@ -954,6 +1452,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
         connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED;
         break;
 #endif
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    case BLE_LL_CTRL_PROC_PHY_UPDATE:
+        ble_ll_ctrl_phy_update_rejected(connsm, ble_error);
+        ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+        break;
+#endif
     default:
         break;
     }
@@ -964,13 +1468,11 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
  *
  * @param connsm
  * @param dptr
- * @param rspbuf
  *
  * @return int
  */
 static int
-ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
-                           uint8_t *rspbuf)
+ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
 {
     uint8_t rsp_opcode;
     uint16_t conn_events;
@@ -1320,6 +1822,12 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
             }
             break;
 #endif
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+        case BLE_LL_CTRL_PROC_PHY_UPDATE:
+            opcode = BLE_LL_CTRL_PHY_REQ;
+            ble_ll_ctrl_phy_req_rsp_make(connsm, dptr);
+            break;
+#endif
         default:
             assert(0);
             break;
@@ -1462,6 +1970,13 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
 {
     int i;
 
+    /* WWW: new rules! Cannot start certain control procedures if other
+     * ones are peer initiated. We need to wait. Deal with this.
+     *
+     * WWW: Do not forget code that when some of these things end we need
+     * to check to start other control procedures
+     */
+
     /*
      * If we are terminating, dont start any new procedures but start
      * terminate if needed
@@ -1602,6 +2117,9 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
     case BLE_LL_CTRL_PING_REQ:
         feature = BLE_LL_FEAT_LE_PING;
         break;
+    case BLE_LL_CTRL_PHY_REQ:
+        feature = BLE_LL_FEAT_LE_2M_PHY | BLE_LL_FEAT_LE_CODED_PHY;
+        break;
     default:
         feature = 0;
         break;
@@ -1632,7 +2150,7 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
     rsp_opcode = BLE_ERR_MAX;
     switch (opcode) {
     case BLE_LL_CTRL_CONN_UPDATE_REQ:
-        rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr, rspbuf);
+        rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr);
         break;
     case BLE_LL_CTRL_CHANNEL_MAP_REQ:
         ble_ll_ctrl_rx_chanmap_req(connsm, dptr);
@@ -1733,6 +2251,17 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
     case BLE_LL_CTRL_REJECT_IND_EXT:
         ble_ll_ctrl_rx_reject_ind(connsm, dptr, opcode);
         break;
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    case BLE_LL_CTRL_PHY_REQ:
+        rsp_opcode = ble_ll_ctrl_rx_phy_req(connsm, dptr, rspdata);
+        break;
+    case BLE_LL_CTRL_PHY_RSP:
+        rsp_opcode = ble_ll_ctrl_rx_phy_rsp(connsm, dptr, rspdata);
+        break;
+    case BLE_LL_CTRL_PHY_UPDATE_IND:
+        ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
+        break;
+#endif
     default:
         /* Nothing to do here */
         break;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index 692c0c9..a6e4c56 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -290,6 +290,75 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
     return BLE_ERR_SUCCESS;
 }
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/**
+ * Checks the preferred phy masks for validity and places the preferred masks
+ * in the input phy masks
+ *
+ * @param cmdbuf Pointer to command buffer where phy masks are located
+ * @param txphy Pointer to output tx phy mask
+ * @param rxphy Pointer to output rx phy mask
+ *
+ * @return int BLE_ERR_SUCCESS or BLE_ERR_INV_HCI_CMD_PARMS
+ */
+int
+ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy)
+{
+    int rc;
+    uint8_t all_phys;
+    uint8_t rx_phys;
+    uint8_t tx_phys;
+
+    /* Check for valid values */
+    all_phys = cmdbuf[0];
+    tx_phys = cmdbuf[1] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
+    rx_phys = cmdbuf[2] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
+
+    if (((all_phys & BLE_HCI_LE_PHY_TX_PREF) && (tx_phys == 0)) ||
+        ((all_phys & BLE_HCI_LE_PHY_RX_PREF) && (rx_phys == 0))) {
+        rc = BLE_ERR_INV_HCI_CMD_PARMS;
+    } else {
+        /* If phy not supported, wipe its bit */
+#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
+        tx_phys &= ~BLE_HCI_LE_PHY_2M_PREF_MASK;
+        rx_phys &= ~BLE_HCI_LE_PHY_2M_PREF_MASK;
+#endif
+#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+        tx_phys &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
+        rx_phys &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
+#endif
+        /* Set the default PHY preferences */
+        if ((all_phys & BLE_HCI_LE_PHY_TX_PREF) == 0) {
+            tx_phys = 0;
+        }
+        *txphy = tx_phys;
+        if ((all_phys & BLE_HCI_LE_PHY_RX_PREF) == 0) {
+            rx_phys = 0;
+        }
+        *rxphy = rx_phys;
+        rc = BLE_ERR_SUCCESS;
+    }
+    return rc;
+}
+
+/**
+ * Set PHY preferences for connection
+ *
+ * @param cmdbuf
+ *
+ * @return int
+ */
+static int
+ble_ll_hci_le_set_def_phy(uint8_t *cmdbuf)
+{
+    int rc;
+
+    rc = ble_ll_hci_chk_phy_masks(cmdbuf, &g_ble_ll_data.ll_pref_tx_phys,
+                                  &g_ble_ll_data.ll_pref_rx_phys);
+    return rc;
+}
+#endif
+
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
 /**
  * HCI write suggested default data length command.
@@ -322,6 +391,8 @@ ble_ll_hci_le_wr_sugg_data_len(uint8_t *cmdbuf)
         g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct;
         g_ble_ll_conn_params.sugg_tx_time = tx_time;
 
+        /* XXX TODO: This has to change! They do not have to be the same
+           at this point. Deal with this */
         if ((tx_time <= g_ble_ll_conn_params.supp_max_tx_time) &&
             (tx_oct <= g_ble_ll_conn_params.supp_max_tx_octets)) {
             g_ble_ll_conn_params.conn_init_max_tx_octets = tx_oct;
@@ -500,6 +571,7 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
     case BLE_HCI_OCF_LE_START_ENCRYPT:
     case BLE_HCI_OCF_LE_RD_P256_PUBKEY:
     case BLE_HCI_OCF_LE_GEN_DHKEY:
+    case BLE_HCI_OCF_LE_SET_PHY:
         rc = 1;
         break;
     default:
@@ -768,6 +840,17 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
     case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN:
         rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen);
         break;
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    case BLE_HCI_OCF_LE_RD_PHY:
+        rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, rspbuf, rsplen);
+        break;
+    case BLE_HCI_OCF_LE_SET_DEFAULT_PHY:
+        rc = ble_ll_hci_le_set_def_phy(cmdbuf);
+        break;
+    case BLE_HCI_OCF_LE_SET_PHY:
+        rc = ble_ll_conn_hci_le_set_phy(cmdbuf);
+        break;
+#endif
     default:
         rc = BLE_ERR_UNKNOWN_HCI_CMD;
         break;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/src/ble_ll_hci_ev.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci_ev.c b/net/nimble/controller/src/ble_ll_hci_ev.c
index 3319db3..2ee9908 100644
--- a/net/nimble/controller/src/ble_ll_hci_ev.c
+++ b/net/nimble/controller/src/ble_ll_hci_ev.c
@@ -292,3 +292,36 @@ ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm)
     }
 }
 #endif
+
+/**
+ * Send a PHY update complete event
+ *
+ * @param connsm Pointer to connection state machine
+ * @param status error status of event
+ */
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+int
+ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
+{
+    int rc;
+    uint8_t *evbuf;
+
+    rc = 0;
+    if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE)) {
+        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+        if (evbuf) {
+            evbuf[0] = BLE_HCI_EVCODE_LE_META;
+            evbuf[1] = BLE_HCI_LE_PHY_UPD_COMP_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE;
+            evbuf[3] = status;
+            put_le16(evbuf + 4, connsm->conn_handle);
+            evbuf[6] = connsm->phy_data.cur_tx_phy;
+            evbuf[7] = connsm->phy_data.cur_rx_phy;
+            ble_ll_hci_event_send(evbuf);
+        } else {
+            rc = BLE_ERR_MEM_CAPACITY;
+        }
+    }
+    return rc;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/controller/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/controller/syscfg.yml b/net/nimble/controller/syscfg.yml
index 0fe7a48..1b00a4e 100644
--- a/net/nimble/controller/syscfg.yml
+++ b/net/nimble/controller/syscfg.yml
@@ -210,6 +210,16 @@ syscfg.defs:
             Selection Algorithm #2.
         value: '0'
 
+    BLE_LL_CFG_FEAT_LE_2M_PHY:
+        description: >
+            This option is used to enable/disable support for the 2Mbps PHY.
+        value: '0'
+
+    BLE_LL_CFG_FEAT_LE_CODED_PHY:
+        description: >
+            This option is used to enable/disable support for the coded PHY.
+        value: '0'
+
     BLE_PUBLIC_DEV_ADDR:
         description: >
             Allows the target or app to override the public device address

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4e347012/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 8ae29dc..f929d85 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -161,7 +161,6 @@ extern "C" {
 #define BLE_HCI_OCF_LE_SET_PRIVACY_MODE             (0x004E)
 
 /* Command Specific Definitions */
-
 #define BLE_HCI_VARIABLE_LEN                (0xFF)
 
 /* --- Disconnect command (OGF 0x01, OCF 0x0006) --- */
@@ -418,12 +417,19 @@ extern "C" {
 #define BLE_HCI_RD_MAX_DATALEN_RSPLEN       (8)
 
 /* --- LE read maximum default PHY (OCF 0x0030) */
-#define BLE_HCI_LE_RD_PHY_LEN                       (2)
+#define BLE_HCI_LE_RD_PHY_LEN               (2)
+#define BLE_HCI_LE_RD_PHY_RSPLEN            (4)
+#define BLE_HCI_LE_PHY_1M                   (1)
+#define BLE_HCI_LE_PHY_2M                   (2)
+#define BLE_HCI_LE_PHY_CODED                (3)
 
 /* --- LE set default PHY (OCF 0x0031) */
 #define BLE_HCI_LE_SET_DEFAULT_PHY_LEN              (3)
 #define BLE_HCI_LE_PHY_NO_TX_PREF_MASK              (0x01)
 #define BLE_HCI_LE_PHY_NO_RX_PREF_MASK              (0x02)
+#define BLE_HCI_LE_PHY_PREF_MASK_ALL                \
+    (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK |  \
+     BLE_HCI_LE_PHY_CODED_PREF_MASK)
 
 #define BLE_HCI_LE_PHY_1M_PREF_MASK                 (0x01)
 #define BLE_HCI_LE_PHY_2M_PREF_MASK                 (0x02)


[3/6] incubator-mynewt-core git commit: MYNEWT-723: Add PHY support to change modulations for 2M phy.

Posted by ry...@apache.org.
MYNEWT-723: Add PHY support to change modulations for 2M phy.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/57414417
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/57414417
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/57414417

Branch: refs/heads/bluetooth5
Commit: 5741441768360699cf778022dea522f5e9992d01
Parents: 3f997c2
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Apr 25 17:17:22 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 23:39:25 2017 +0200

----------------------------------------------------------------------
 apps/bletest/src/main.c                         |   2 +-
 hw/drivers/nimble/nrf51/src/ble_phy.c           |  26 ++--
 hw/drivers/nimble/nrf52/src/ble_phy.c           | 133 ++++++++++++++++---
 .../controller/include/controller/ble_ll.h      |  35 +----
 .../controller/include/controller/ble_ll_conn.h |  24 ++--
 .../include/controller/ble_ll_sched.h           |   3 -
 .../controller/include/controller/ble_phy.h     |  28 ++++
 net/nimble/controller/src/ble_ll_adv.c          |   7 +-
 net/nimble/controller/src/ble_ll_conn.c         |  92 +++++++++----
 net/nimble/controller/src/ble_ll_conn_priv.h    |   3 -
 net/nimble/controller/src/ble_ll_ctrl.c         |  32 ++---
 net/nimble/controller/src/ble_ll_scan.c         |   6 +
 net/nimble/controller/src/ble_ll_sched.c        |  12 +-
 13 files changed, 278 insertions(+), 125 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index e2519eb..d1eb1d5 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -178,7 +178,7 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
 #define BLETEST_CFG_RAND_PKT_SIZE       (1)
 #define BLETEST_CFG_SUGG_DEF_TXOCTETS   (251)
 #define BLETEST_CFG_SUGG_DEF_TXTIME     \
-    BLE_TX_DUR_USECS_M(BLETEST_CFG_SUGG_DEF_TXOCTETS + 4)
+    ble_phy_pdu_dur(BLETEST_CFG_SUGG_DEF_TXOCTETS + 4, BLE_PHY_1M)
 
 /* Test configurations. One of these should be set to 1 */
 #if !defined(BLETEST_CONCURRENT_CONN_TEST) && !defined(BLETEST_THROUGHPUT_TEST)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/hw/drivers/nimble/nrf51/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/src/ble_phy.c b/hw/drivers/nimble/nrf51/src/ble_phy.c
index c9e2b74..4affa2c 100644
--- a/hw/drivers/nimble/nrf51/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf51/src/ble_phy.c
@@ -55,7 +55,6 @@ extern uint32_t g_nrf_irk_list[];
 /* Maximum length of frames */
 #define NRF_MAXLEN              (255)
 #define NRF_BALEN               (3)     /* For base address of 3 bytes */
-#define NRF_RX_START_OFFSET     (5)
 
 /* Maximum tx power */
 #define NRF_TX_PWR_MAX_DBM      (4)
@@ -385,16 +384,14 @@ ble_phy_wfr_enable(int txrx, uint32_t wfr_usecs)
          * Timeout occurs an IFS time plus time it takes to receive address
          * from the transmit end. We add additional time to make sure the
          * address event comes before the compare. Note that transmit end
-         * is captured in CC[2]
-         *
-         * XXX: this assumes 1Mbps as 40 usecs is header rx time for 1Mbps
+         * is captured in CC[2]. I just made up the 16 usecs I add here.
          */
-        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + 40 + 16;
+        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS +
+            ble_phy_pdu_start_off(BLE_PHY_1M) + 16;
     } else {
-        /* CC[0] is set to when RXEN occurs. NOTE: the extra 16 usecs is
-           jitter */
+        /* CC[0] is set to when RXEN occurs. */
         end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs +
-            40 + 16;
+            ble_phy_pdu_start_off(BLE_PHY_1M) + BLE_LL_JITTER_USECS;
     }
 
     /* wfr_secs is the time from rxen until timeout */
@@ -568,8 +565,10 @@ ble_phy_tx_end_isr(void)
 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
         ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0);
 #else
-        wfr_time = BLE_LL_WFR_USECS - BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
-        wfr_time += BLE_TX_DUR_USECS_M(txlen);
+        wfr_time = (BLE_LL_IFS + ble_phy_pdu_start_off(BLE_PHY_1M) +
+                    (2 * BLE_LL_JITTER_USECS)) -
+                    ble_phy_pdu_start_off(BLE_PHY_1M);
+        wfr_time += ble_phy_pdu_dur(txlen, BLE_PHY_1M);
         wfr_time = os_cputime_usecs_to_ticks(wfr_time);
         ble_ll_wfr_enable(txstart + wfr_time);
 #endif
@@ -699,12 +698,11 @@ ble_phy_rx_start_isr(void)
 
 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
     /*
-     * Calculate receive start time. We assume that the header time is
-     * 40 usecs (only 1 mbps supported right now).
+     * Calculate receive start time.
      *
      * XXX: possibly use other routine with remainder!
      */
-    usecs = NRF_TIMER0->CC[1] - 40;
+    usecs = NRF_TIMER0->CC[1] - ble_phy_pdu_start_off(BLE_PHY_1M);
     ticks = os_cputime_usecs_to_ticks(usecs);
     ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
     if (ble_hdr->rem_usecs == 31) {
@@ -714,7 +712,7 @@ ble_phy_rx_start_isr(void)
     ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
 #else
     ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
-        os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
+        os_cputime_usecs_to_ticks(ble_phy_pdu_start_off(BLE_PHY_1M));
 #endif
 
     /* Wait to get 1st byte of frame */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/hw/drivers/nimble/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index e6b470e..0ab7cd6 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -28,7 +28,7 @@
 #include "nimble/nimble_opt.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_ll.h"
-#include "nrf52_bitfields.h"
+#include "nrf.h"
 
 /* XXX: 4) Make sure RF is higher priority interrupt than schedule */
 
@@ -55,12 +55,14 @@ extern uint32_t g_nrf_irk_list[];
 /* Maximum length of frames */
 #define NRF_MAXLEN              (255)
 #define NRF_BALEN               (3)     /* For base address of 3 bytes */
-#define NRF_RX_START_OFFSET     (5)
 
 /* Maximum tx power */
 #define NRF_TX_PWR_MAX_DBM      (4)
 #define NRF_TX_PWR_MIN_DBM      (-40)
 
+/* The number of different modulations */
+#define BLE_PHY_NUM_MODULATIONS (4)
+
 /* BLE PHY data structure */
 struct ble_phy_obj
 {
@@ -73,8 +75,12 @@ struct ble_phy_obj
     uint8_t phy_encrypted;
     uint8_t phy_privacy;
     uint8_t phy_tx_pyld_len;
+    uint8_t phy_txtorx_phy;
+    uint8_t phy_cur_phy;
+    uint8_t phy_pkt_start_off[BLE_PHY_NUM_MODULATIONS];
     uint32_t phy_aar_scratch;
     uint32_t phy_access_address;
+    uint32_t phy_pcnf0;
     struct ble_mbuf_hdr rxhdr;
     void *txend_arg;
     ble_phy_tx_end_func txend_cb;
@@ -182,6 +188,68 @@ struct nrf_ccm_data
 struct nrf_ccm_data g_nrf_ccm_data;
 #endif
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+/**
+ * Calculate the length of BLE PDU
+ *
+ * Returns the number of usecs it will take to transmit a PDU of payload
+ * length 'len' bytes. Each byte takes 8 usecs. This routine includes the LL
+ * overhead: preamble (1), access addr (4) and crc (3) and the PDU header (2)
+ * for a total of 10 bytes.
+ *
+ * @param pyld_len PDU payload length (does not include include header).
+ * @param phy PHY modulation being used.
+ *
+ * @return uint32_t The number of usecs it will take to transmit a PDU of
+ *                  length 'len' bytes.
+ */
+uint32_t
+ble_phy_pdu_dur(uint8_t pyld_len, int phy)
+{
+    uint32_t usecs;
+
+    if (phy == BLE_PHY_1M) {
+        /* 8 usecs per byte */
+        usecs = (pyld_len + BLE_LL_PREAMBLE_LEN + BLE_LL_ACC_ADDR_LEN
+                 + BLE_LL_CRC_LEN + BLE_LL_PDU_HDR_LEN) << 3;
+    } else if (phy == BLE_PHY_2M) {
+        /* 4 usecs per byte */
+        usecs = (pyld_len + (2 * BLE_LL_PREAMBLE_LEN) + BLE_LL_ACC_ADDR_LEN
+                 + BLE_LL_CRC_LEN + BLE_LL_PDU_HDR_LEN) << 2;
+    } else {
+        /* XXX: TODO implement */
+        assert(0);
+    }
+    return usecs;
+}
+
+
+/* Packet start offset (in usecs). This is the preamble plus access address. */
+uint32_t
+ble_phy_pdu_start_off(int phy)
+{
+    return g_ble_phy_data.phy_pkt_start_off[phy];
+}
+
+void
+ble_phy_set_mode(int cur_phy, int txtorx_phy)
+{
+
+    if (cur_phy == BLE_PHY_1M) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0;    /* Default is 8 bits */
+    } else if (cur_phy == BLE_PHY_2M) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 | RADIO_PCNF0_PLEN_16bit;
+    } else {
+        /* XXX: TODO added coded PHY */
+        assert(0);
+    }
+    g_ble_phy_data.phy_cur_phy = (uint8_t)cur_phy;
+    g_ble_phy_data.phy_txtorx_phy = (uint8_t)txtorx_phy;
+}
+#endif
+
 /**
  * Copies the data from the phy receive buffer into a mbuf chain.
  *
@@ -381,21 +449,25 @@ ble_phy_wfr_enable(int txrx, uint32_t wfr_usecs)
 {
     uint32_t end_time;
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    int phy;
+
+    phy = g_ble_phy_data.phy_cur_phy;
+#endif
     if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
         /*
          * Timeout occurs an IFS time plus time it takes to receive address
          * from the transmit end. We add additional time to make sure the
          * address event comes before the compare. Note that transmit end
          * is captured in CC[2]
-         *
-         * XXX: this assumes 1Mbps as 40 usecs is header rx time for 1Mbps
          */
-        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + 40 + 16;
+        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS +
+            ble_phy_pdu_start_off(phy) + BLE_LL_JITTER_USECS;
     } else {
         /* CC[0] is set to when RXEN occurs. NOTE: the extra 16 usecs is
            jitter */
         end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs +
-            40 + 16;
+            ble_phy_pdu_start_off(phy) + BLE_LL_JITTER_USECS;
     }
 
     /* wfr_secs is the time from rxen until timeout */
@@ -486,15 +558,16 @@ ble_phy_rx_xcvr_setup(void)
 static void
 ble_phy_tx_end_isr(void)
 {
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    int phy;
+#endif
     uint8_t was_encrypted;
     uint8_t transition;
     uint8_t txlen;
     uint32_t wfr_time;
 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
     uint32_t txstart;
-#endif
 
-#if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
     /*
      * Read captured tx start time. This is not the actual transmit start
      * time but it is the time at which the address event occurred
@@ -545,6 +618,15 @@ ble_phy_tx_end_isr(void)
 
     transition = g_ble_phy_data.phy_transition;
     if (transition == BLE_PHY_TRANSITION_TX_RX) {
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+        /* See if a new phy has been specified for tx to rx transition */
+        phy = g_ble_phy_data.phy_txtorx_phy;
+        if (phy != g_ble_phy_data.phy_cur_phy) {
+            ble_phy_set_mode(phy, phy);
+        }
+#endif
+
         /* Packet pointer needs to be reset. */
         ble_phy_rx_xcvr_setup();
 
@@ -559,8 +641,13 @@ ble_phy_tx_end_isr(void)
 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
         ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0);
 #else
-        wfr_time = BLE_LL_WFR_USECS - BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
-        wfr_time += BLE_TX_DUR_USECS_M(txlen);
+        /*
+         * NOTE: technically we only need to add the jitter once but we
+         * add twice the jitter just to be sure.
+         */
+        wfr_time = BLE_LL_IFS + (2 * BLE_LL_JITTER_USECS) +
+            ble_phy_pdu_start_off(phy) - ble_phy_pdu_start_off(phy);
+        wfr_time += ble_phy_pdu_dur(txlen, phy);
         wfr_time = os_cputime_usecs_to_ticks(wfr_time);
         ble_ll_wfr_enable(txstart + wfr_time);
 #endif
@@ -686,12 +773,11 @@ ble_phy_rx_start_isr(void)
 
 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
     /*
-     * Calculate receive start time. We assume that the header time is
-     * 40 usecs (only 1 mbps supported right now).
+     * Calculate receive start time.
      *
      * XXX: possibly use other routine with remainder!
      */
-    usecs = NRF_TIMER0->CC[1] - 40;
+    usecs = NRF_TIMER0->CC[1] - ble_phy_pdu_start_off(g_ble_phy_data.phy_cur_phy);
     ticks = os_cputime_usecs_to_ticks(usecs);
     ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
     if (ble_hdr->rem_usecs == 31) {
@@ -701,7 +787,7 @@ ble_phy_rx_start_isr(void)
     ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
 #else
     ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
-        os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
+        os_cputime_usecs_to_ticks(ble_phy_pdu_start_off(g_ble_phy_data.phy_cur_phy));
 #endif
 
     /* XXX: I wonder if we always have the 1st byte. If we need to wait for
@@ -812,6 +898,15 @@ ble_phy_init(void)
 {
     int rc;
 
+    /* XXX: TODO add coded phy */
+    /* Set packet start offsets for various phys */
+    g_ble_phy_data.phy_pkt_start_off[BLE_PHY_1M] = 40;  /* 40 usecs */
+    g_ble_phy_data.phy_pkt_start_off[BLE_PHY_2M] = 24;  /* 24 usecs */
+
+    /* Default phy to use is 1M */
+    g_ble_phy_data.phy_cur_phy = BLE_PHY_1M;
+    g_ble_phy_data.phy_txtorx_phy = BLE_PHY_1M;
+
 #if !defined(BLE_XCVR_RFCLK)
     uint32_t os_tmo;
 
@@ -841,10 +936,11 @@ ble_phy_init(void)
 
     /* Set configuration registers */
     NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
-    NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos)    |
-                       RADIO_PCNF0_S1INCL_Msk                       |
-                       (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos)        |
-                       (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos);
+    g_ble_phy_data.phy_pcnf0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos)    |
+                               RADIO_PCNF0_S1INCL_Msk                       |
+                               (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos)        |
+                               (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos);
+    NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0;
 
     /* XXX: should maxlen be 251 for encryption? */
     NRF_RADIO->PCNF1 = NRF_MAXLEN |
@@ -1061,6 +1157,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
     }
     return rc;
 }
+
 /**
  * Called to set the start time of a reception
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index 619d1a9..373c3e5 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -66,16 +66,8 @@ extern "C" {
 /* Controller revision. */
 #define BLE_LL_SUB_VERS_NR      (0x0000)
 
-/*
- * The amount of time that we will wait to hear the start of a receive
- * packet after we have transmitted a packet. This time is at least
- * an IFS time plus the time to receive the preamble and access address (which
- * is 40 usecs). We add an additional 32 usecs just to be safe.
- *
- * XXX: move this definition and figure out how we determine the worst-case
- * jitter (spec. should have this).
- */
-#define BLE_LL_WFR_USECS    (BLE_LL_IFS + 40 + 32)
+/* Timing jitter as per spec is +/16 usecs */
+#define BLE_LL_JITTER_USECS         (16)
 
 /* Packet queue header definition */
 STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
@@ -219,7 +211,7 @@ struct ble_dev_addr
 /*
  * LL packet format
  *
- *  -> Preamble         (1 byte)
+ *  -> Preamble         (1/2 bytes)
  *  -> Access Address   (4 bytes)
  *  -> PDU              (2 to 257 octets)
  *  -> CRC              (3 bytes)
@@ -227,31 +219,10 @@ struct ble_dev_addr
 #define BLE_LL_PREAMBLE_LEN     (1)
 #define BLE_LL_ACC_ADDR_LEN     (4)
 #define BLE_LL_CRC_LEN          (3)
-#define BLE_LL_OVERHEAD_LEN     \
-    (BLE_LL_CRC_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_PREAMBLE_LEN)
 #define BLE_LL_PDU_HDR_LEN      (2)
 #define BLE_LL_MIN_PDU_LEN      (BLE_LL_PDU_HDR_LEN)
 #define BLE_LL_MAX_PDU_LEN      (257)
 #define BLE_LL_CRCINIT_ADV      (0x555555)
-#define BLE_LL_PDU_OVERHEAD     (BLE_LL_OVERHEAD_LEN + BLE_LL_PDU_HDR_LEN)
-
-/**
- * ll pdu tx time get
- *
- * Returns the number of usecs it will take to transmit a PDU of payload
- * length 'len' bytes. Each byte takes 8 usecs. This routine includes the LL
- * overhead: preamble (1), access addr (4) and crc (3) and the PDU header (2)
- * for a total of 10 bytes.
- *
- * @param len The length of the PDU payload (does not include include header).
- *
- * @return uint16_t The number of usecs it will take to transmit a PDU of
- *                  length 'len' bytes.
- */
-#define BLE_TX_DUR_USECS_M(len)     (((len) + BLE_LL_PDU_OVERHEAD) << 3)
-
-/* Calculates the time it takes to transmit 'len' bytes */
-#define BLE_TX_LEN_USECS_M(len)     ((len) << 3)
 
 /* Access address for advertising channels */
 #define BLE_ACCESS_ADDR_ADV             (0x8E89BED6)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index d3d7639..8560316 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -128,23 +128,27 @@ union ble_ll_conn_sm_flags {
 /**
  * Structure used for PHY data inside a connection.
  *
+ * tx_phy_mode: chip specific phy mode for tx
+ * rx_phy_mode: chip specific phy mode for tx
  * cur_tx_phy: value denoting current tx_phy (not a bitmask!)
- * cur_rx_phy: value denoting current rx phy (not a bitmask)
+ * cur_rx_phy: value denoting current rx phy (not a bitmask!)
  * pref_tx_phys: bitmask of preferred transmit PHYs
  * pref_rx_phys: bitmask of preferred receive PHYs
  * phy_options: preferred phy options for coded phy
  */
 struct ble_ll_conn_phy_data
 {
-    uint8_t cur_tx_phy: 2;
-    uint8_t cur_rx_phy: 2;
-    uint8_t new_tx_phy: 2;
-    uint8_t new_rx_phy: 2;
-    uint16_t host_pref_tx_phys: 3;
-    uint16_t host_pref_rx_phys: 3;
-    uint16_t req_pref_tx_phys: 3;
-    uint16_t req_pref_rx_phys: 3;
-    uint16_t phy_options: 2;
+    uint32_t tx_phy_mode: 2;
+    uint32_t rx_phy_mode: 2;
+    uint32_t cur_tx_phy: 2;
+    uint32_t cur_rx_phy: 2;
+    uint32_t new_tx_phy: 2;
+    uint32_t new_rx_phy: 2;
+    uint32_t host_pref_tx_phys: 3;
+    uint32_t host_pref_rx_phys: 3;
+    uint32_t req_pref_tx_phys: 3;
+    uint32_t req_pref_rx_phys: 3;
+    uint32_t phy_options: 2;
 }  __attribute__((packed));
 
 #define CONN_CUR_TX_PHY_MASK(csm)   (1 << ((csm)->phy_data.cur_tx_phy - 1))

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/include/controller/ble_ll_sched.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_sched.h b/net/nimble/controller/include/controller/ble_ll_sched.h
index d2321b7..c407397 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -47,9 +47,6 @@ extern "C" {
 #define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS   (502)
 #define BLE_LL_SCHED_MAX_ADV_PDU_USECS      (376)
 
-/* BLE Jitter (+/- 16 useecs) */
-#define BLE_LL_JITTER_USECS                 (16)
-
 /*
  * This is the offset from the start of the scheduled item until the actual
  * tx/rx should occur, in ticks.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/include/controller/ble_phy.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h
index e62b216..d4d0b40 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -179,6 +179,34 @@ void ble_phy_resolv_list_enable(void);
 /* Disable phy resolving list */
 void ble_phy_resolv_list_disable(void);
 
+/*
+ * These definitions are used for the 'phy' parameters in the API listed below.
+ * These are numbered in a specific order to save code. The HCI definitions for
+ * the PHY modes for 1Mbps and 2Mbps are the same here. For the coded phy
+ * they need to be translated from the HCI number to either 0 or 3. This
+ * was done in order to save code when translating between the HCI phy value
+ * and the phy API.
+ */
+#define BLE_PHY_CODED_125KBPS   (0)
+#define BLE_PHY_1M              (1)
+#define BLE_PHY_2M              (2)
+#define BLE_PHY_CODED_500KBPS   (3)
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
+uint32_t ble_phy_pdu_dur(uint8_t len, int phy);
+uint32_t ble_phy_pdu_start_off(int phy);
+void ble_phy_set_mode(int cur_phy, int txtorx_phy);
+#else
+#define ble_phy_pdu_dur(len, phy)   \
+    (((len) + BLE_LL_PDU_HDR_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_PREAMBLE_LEN \
+      + BLE_LL_CRC_LEN) << 3)
+
+#define ble_phy_pdu_start_off(phy)      (40)
+
+#endif
+
+
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index 2c57573..c55c435 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -484,6 +484,10 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
 
     ble_ll_adv_pdu_make(advsm, adv_pdu);
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    ble_phy_set_mode(BLE_PHY_1M, BLE_PHY_1M);
+#endif
+
     /* Transmit advertisement */
     rc = ble_phy_tx(adv_pdu, end_trans);
     os_mbuf_free_chain(adv_pdu);
@@ -523,7 +527,7 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm)
     sch->sched_type = BLE_LL_SCHED_TYPE_ADV;
 
     /* Set end time to maximum time this schedule item may take */
-    max_usecs = BLE_TX_DUR_USECS_M(advsm->adv_pdu_len);
+    max_usecs = ble_phy_pdu_dur(advsm->adv_pdu_len, BLE_PHY_1M);
     switch (advsm->adv_type) {
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
@@ -1216,6 +1220,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
     if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
         scan_rsp = ble_ll_adv_scan_rsp_pdu_make(advsm);
         if (scan_rsp) {
+            /* XXX TODO: assume we do not need to change phy mode */
             ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
             rc = ble_phy_tx(scan_rsp, BLE_PHY_TRANSITION_NONE);
             if (!rc) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 0efbba2..3236869 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -117,17 +117,6 @@ extern void bletest_completed_pkt(uint16_t handle);
  *  1) The current connection event has not ended but a schedule item starts
  */
 
-/*
- * The amount of time that we will wait to hear the start of a receive
- * packet after we have transmitted a packet. This time is at least
- * an IFS time plus the time to receive the preamble and access address. We
- * add an additional 32 usecs just to be safe.
- *
- * XXX: move this definition and figure out how we determine the worst-case
- * jitter (spec. should have this).
- */
-#define BLE_LL_WFR_USECS                    (BLE_LL_IFS + 40 + 32)
-
 /* This is a dummy structure we use for the empty PDU */
 struct ble_ll_empty_pdu
 {
@@ -1036,6 +1025,9 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
         STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next);
         ble_hdr = BLE_MBUF_HDR_PTR(m);
 
+        /* WWW: need to check this with phy update procedure. There are
+           limitations if we have started update */
+
         /* Determine packet length we will transmit */
         cur_txlen = connsm->eff_max_tx_octets;
         pktlen = pkthdr->omp_len;
@@ -1093,6 +1085,9 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
         /* Get next event time */
         next_event_time = ble_ll_conn_get_next_sched_time(connsm);
 
+        /* WWW: need to check this with phy update procedure. There are
+           limitations if we have started update */
+
         /*
          * Dont bother to set the MD bit if we cannot do the following:
          *  -> wait IFS, send the current frame.
@@ -1122,8 +1117,8 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
          * received a frame and we are replying to it.
          */
         ticks = (BLE_LL_IFS * 3) + connsm->eff_max_rx_time +
-                BLE_TX_DUR_USECS_M(next_txlen) +
-                BLE_TX_DUR_USECS_M(cur_txlen);
+                ble_phy_pdu_dur(next_txlen, connsm->phy_data.tx_phy_mode) +
+                ble_phy_pdu_dur(cur_txlen, connsm->phy_data.tx_phy_mode);
 
         if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
             ticks += (BLE_LL_IFS + connsm->eff_max_rx_time);
@@ -1271,6 +1266,10 @@ conn_tx_pdu:
     }
 #endif
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    ble_phy_set_mode(connsm->phy_data.tx_phy_mode,connsm->phy_data.rx_phy_mode);
+#endif
+
     /* Set transmit end callback */
     ble_phy_set_txend_cb(txend_func, connsm);
     rc = ble_phy_tx(m, end_transition);
@@ -1387,6 +1386,11 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
                 ble_phy_encrypt_disable();
             }
 #endif
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    ble_phy_set_mode(connsm->phy_data.rx_phy_mode,connsm->phy_data.rx_phy_mode);
+#endif
+
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
         /* XXX: what is this really for the slave? */
         start = sch->start_time + g_ble_ll_sched_offset_ticks;
@@ -1433,8 +1437,13 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
                 (2 * connsm->slave_cur_window_widening);
             ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, usecs);
 #else
-            usecs = connsm->slave_cur_tx_win_usecs + BLE_LL_WFR_USECS +
-                connsm->slave_cur_window_widening;
+            /*
+             * NOTE: technically we do not need twice the jitter but I want
+             * to be sure we do not bail out early.
+             */
+            usecs = connsm->slave_cur_tx_win_usecs + BLE_LL_IFS +
+                ble_phy_pdu_start_off(connsm->rx_phy_mode) +
+                (BLE_LL_JITTER_USECS * 2) + connsm->slave_cur_window_widening;
             wfr_time = connsm->anchor_point + os_cputime_usecs_to_ticks(usecs);
             ble_ll_wfr_enable(wfr_time);
 #endif
@@ -1498,16 +1507,18 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime,
             pkthdr = OS_MBUF_PKTHDR(txpdu);
         }
 
+        /* WWW: need to check this with phy update procedure. There are
+           limitations if we have started update */
         if (txpdu) {
             txhdr = BLE_MBUF_HDR_PTR(txpdu);
             rem_bytes = pkthdr->omp_len - txhdr->txinfo.offset;
             if (rem_bytes > connsm->eff_max_tx_octets) {
                 rem_bytes = connsm->eff_max_tx_octets;
             }
-            usecs = BLE_TX_DUR_USECS_M(rem_bytes);
+            usecs = ble_phy_pdu_dur(rem_bytes, connsm->phy_data.tx_phy_mode);
         } else {
             /* We will send empty pdu (just a LL header) */
-            usecs = BLE_TX_DUR_USECS_M(0);
+            usecs = ble_phy_pdu_dur(0, connsm->phy_data.tx_phy_mode);
         }
         usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time;
 
@@ -1690,6 +1701,8 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     connsm->phy_data.cur_tx_phy = BLE_HCI_LE_PHY_1M;
     connsm->phy_data.cur_rx_phy = BLE_HCI_LE_PHY_1M;
+    connsm->phy_data.tx_phy_mode = BLE_PHY_1M;
+    connsm->phy_data.rx_phy_mode = BLE_PHY_1M;
     connsm->phy_data.req_pref_tx_phys = 0;
     connsm->phy_data.req_pref_rx_phys = 0;
     connsm->phy_data.host_pref_tx_phys = g_ble_ll_data.ll_pref_tx_phys;
@@ -1921,6 +1934,12 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     }
 
     /*
+     * XXX: TODO Probably want to add checks to see if we need to start
+     * a control procedure here as an instant may have prevented us from
+     * starting one.
+     */
+
+    /*
      * XXX TODO: I think this is technically incorrect. We can allow slave
      * latency if we are doing one of these updates as long as we
      * know that the master has received the ACK to the PDU that set
@@ -2045,7 +2064,13 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         (connsm->event_cntr == connsm->phy_instant)) {
         /* Set cur phy to new phy */
         connsm->phy_data.cur_tx_phy = connsm->phy_data.new_tx_phy;
+        connsm->phy_data.tx_phy_mode = connsm->phy_data.cur_tx_phy;
         connsm->phy_data.cur_rx_phy = connsm->phy_data.new_rx_phy;
+        connsm->phy_data.rx_phy_mode = connsm->phy_data.cur_rx_phy;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+        /* XXX: TODO convert to coded phy mode if new phy is coded */
+#endif
 
         /* Clear flags and set flag to send event at next instant */
         CONN_F_PHY_UPDATE_SCHED(connsm) = 0;
@@ -2129,6 +2154,8 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
     uint32_t endtime;
     uint32_t usecs;
 
+    /* XXX: TODO this assumes we received in 1M phy */
+
     /* Set state to created */
     connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
 
@@ -2162,7 +2189,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
 
         usecs = rxhdr->rem_usecs + 1250 +
             (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) +
-            BLE_TX_DUR_USECS_M(BLE_CONNECT_REQ_LEN);
+            ble_phy_pdu_dur(BLE_CONNECT_REQ_LEN, BLE_PHY_1M);
 
         /* Anchor point is cputime. */
         endtime = os_cputime_usecs_to_ticks(usecs);
@@ -2182,7 +2209,8 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
 #else
         connsm->last_anchor_point = rxhdr->beg_cputime;
         endtime = rxhdr->beg_cputime +
-            os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(BLE_CONNECT_REQ_LEN));
+            os_cputime_usecs_to_ticks(ble_phy_pdu_dur(BLE_CONNECT_REQ_LEN,
+                                                      BLE_PHY_1M));
         connsm->slave_cur_tx_win_usecs =
             connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
         usecs = 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
@@ -2535,6 +2563,7 @@ ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva, uint16_t txoffset,
     int rc;
     struct os_mbuf *m;
 
+    /* XXX: TODO: assume we are already on correct phy */
     m = ble_ll_scan_get_pdu();
     ble_ll_conn_req_pdu_update(m, adva, addr_type, txoffset, rpa_index);
     ble_phy_set_txend_cb(ble_ll_conn_req_txend, NULL);
@@ -3111,13 +3140,20 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
         goto conn_exit;
     }
 
-    /* Calculate the end time of the received PDU */
+    /*
+     * Calculate the end time of the received PDU. NOTE: this looks strange
+     * but for the 32768 crystal we add the time it takes to send the packet
+     * to the 'additional usecs' field to save some calculations.
+     */
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
     endtime = rxhdr->beg_cputime;
-    add_usecs = rxhdr->rem_usecs + BLE_TX_DUR_USECS_M(rx_pyld_len);
+    add_usecs = rxhdr->rem_usecs +
+        ble_phy_pdu_dur(rx_pyld_len, connsm->phy_data.rx_phy_mode);
 #else
     endtime = rxhdr->beg_cputime +
-        os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(rx_pyld_len));
+        os_cputime_usecs_to_ticks(ble_phy_pdu_dur(rx_pyld_len,
+                                                  connsm->phy_data.rx_phy_mode));
+
     add_usecs = 0;
 #endif
 
@@ -3251,6 +3287,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
                         os_mbuf_free_chain(txpdu);
                         connsm->cur_tx_pdu = NULL;
                     } else {
+                        /* WWW: need to check this with phy update procedure. There are
+                           limitations if we have started update */
                         rem_bytes = OS_MBUF_PKTLEN(txpdu) - txhdr->txinfo.offset;
                         if (rem_bytes > connsm->eff_max_tx_octets) {
                             txhdr->txinfo.pyld_len = connsm->eff_max_tx_octets;
@@ -3345,6 +3383,8 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
     ble_hdr->txinfo.pyld_len = length;
     ble_hdr->txinfo.hdr_byte = hdr_byte;
 
+    /* WWW: need to check this with phy update procedure. There are
+       limitations if we have started update */
     /*
      * We need to set the initial payload length if the total length of the
      * PDU exceeds the maximum allowed for the connection for any single tx.
@@ -3635,20 +3675,22 @@ ble_ll_conn_module_reset(void)
     conn_params = &g_ble_ll_conn_params;
     max_phy_pyld = ble_phy_max_data_pdu_pyld();
 
+    /* WWW: change these on change of phy */
+
     maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld);
     conn_params->supp_max_rx_octets = maxbytes;
     conn_params->supp_max_rx_time =
-        BLE_TX_DUR_USECS_M(maxbytes + BLE_LL_DATA_MIC_LEN);
+        ble_phy_pdu_dur(maxbytes + BLE_LL_DATA_MIC_LEN, BLE_PHY_1M);
 
     maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_TX_BYTES), max_phy_pyld);
     conn_params->supp_max_tx_octets = maxbytes;
     conn_params->supp_max_tx_time =
-        BLE_TX_DUR_USECS_M(maxbytes + BLE_LL_DATA_MIC_LEN);
+        ble_phy_pdu_dur(maxbytes + BLE_LL_DATA_MIC_LEN, BLE_PHY_1M);
 
     maxbytes = min(MYNEWT_VAL(BLE_LL_CONN_INIT_MAX_TX_BYTES), max_phy_pyld);
     conn_params->conn_init_max_tx_octets = maxbytes;
     conn_params->conn_init_max_tx_time =
-        BLE_TX_DUR_USECS_M(maxbytes + BLE_LL_DATA_MIC_LEN);
+        ble_phy_pdu_dur(maxbytes + BLE_LL_DATA_MIC_LEN, BLE_PHY_1M);
 
     conn_params->sugg_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
     conn_params->sugg_tx_time = BLE_LL_CONN_SUPP_TIME_MIN;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h b/net/nimble/controller/src/ble_ll_conn_priv.h
index 13e03cf..ce18ddc 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -47,9 +47,6 @@ extern "C" {
 #define BLE_LL_CONN_TX_WIN_MIN              (1)         /* in tx win units */
 #define BLE_LL_CONN_SLAVE_LATENCY_MAX       (499)
 
-/* Connection request duration (in usecs) */
-#define BLE_LL_CONN_REQ_DURATION            (352)       /* 1 Mbps only */
-
 /* Connection handle range */
 #define BLE_LL_CONN_MAX_CONN_HANDLE         (0x0EFF)
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index 99a2cd8..1029bf2 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -198,7 +198,7 @@ ble_ll_ctrl_chk_supp_time(uint16_t t)
  * @param ble_err
  */
 void
-ble_ll_ctrl_phy_update_cancel(strcut ble_ll_conn_sm *connsm, uint8_t ble_err)
+ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
 {
     /* cancel any pending phy update procedures */
     CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
@@ -754,11 +754,11 @@ ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
 void
 ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
 {
-    uint8_t new_tx_phy_mask;
-    uint8_t new_rx_phy_mask;
+    int no_change;
+    uint8_t new_m_to_s_mask;
+    uint8_t new_s_to_m_mask;
     uint8_t new_tx_phy;
     uint8_t new_rx_phy;
-    int no_change;
     uint16_t instant;
     uint16_t delta;
 
@@ -777,17 +777,22 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
          * doing either a PEER, CTRLR, or HOST phy update.
          */
         /* get the new phy masks and see if we need to change */
-        new_tx_phy_mask = dptr[0];
-        new_rx_phy_mask = dptr[1];
+        new_m_to_s_mask = dptr[0];
+        new_s_to_m_mask = dptr[1];
         instant = get_le16(dptr + 2);
 
-        no_change = 0;
-        if ((new_tx_phy_mask == 0) && (new_rx_phy_mask == 0)) {
+        if ((new_m_to_s_mask == 0) && (new_s_to_m_mask == 0)) {
             /* No change in phy */
             no_change = 1;
         } else {
-            new_tx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_tx_phy_mask);
-            new_rx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_rx_phy_mask);
+            no_change = 0;
+            /*
+             * NOTE: from the slaves perspective, the m to s phy is the one
+             * that the slave will receive on; s to m is the one it will
+             * transmit on
+             */
+            new_rx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_m_to_s_mask);
+            new_tx_phy = ble_ll_ctrl_phy_mask_to_numeric(new_s_to_m_mask);
 
             if ((new_tx_phy == 0) && (new_rx_phy == 0)) {
                 /* XXX: this is an error! What to do??? */
@@ -795,7 +800,7 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
             }
 
             if ((new_tx_phy == connsm->phy_data.cur_tx_phy) &&
-                (new_rx_phy == connsm->phy_data.cur_tx_phy)) {
+                (new_rx_phy == connsm->phy_data.cur_rx_phy)) {
                 no_change = 1;
             }
         }
@@ -1961,11 +1966,8 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
 {
     int i;
 
-    /* WWW: new rules! Cannot start certain control procedures if other
+    /* XXX: TODO new rules! Cannot start certain control procedures if other
      * ones are peer initiated. We need to wait. Deal with this.
-     *
-     * WWW: Do not forget code that when some of these things end we need
-     * to check to start other control procedures
      */
 
     /*

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c
index 7f0c40b..569823e 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -595,6 +595,10 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, uint8_t chan)
     }
 #endif
 
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    ble_phy_set_mode(BLE_PHY_1M, BLE_PHY_1M);
+#endif
+
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
         /* XXX: probably need to make sure hfxo is running too */
         /* XXX: can make this better; want to just start asap. */
@@ -1141,6 +1145,8 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
         if (scansm->backoff_count == 0) {
             /* Setup to transmit the scan request */
             adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
+
+            /* XXX: TODO assume we are on correct phy */
             ble_ll_scan_req_pdu_make(scansm, adv_addr, addr_type);
             rc = ble_phy_tx(scansm->scan_req_pdu, BLE_PHY_TRANSITION_TX_RX);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/57414417/net/nimble/controller/src/ble_ll_sched.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_sched.c b/net/nimble/controller/src/ble_ll_sched.c
index 7637ac9..5c292ae 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -306,6 +306,11 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
     struct ble_ll_sched_item *entry;
     struct ble_ll_sched_item *sch;
 
+    /*
+     * XXX: TODO this code assumes the advertisement and connect request were
+     * sent at 1Mbps.
+     */
+
     /* Get schedule element from connection */
     rc = -1;
     sch = &connsm->conn_sch;
@@ -360,7 +365,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
     itvl_t = connsm->conn_itvl_ticks;
 #else
     adv_rxend = ble_hdr->beg_cputime +
-        os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(pyld_len));
+        os_cputime_usecs_to_ticks(ble_phy_pdu_dur(pyld_len, BLE_PHY_1M));
     /*
      * The earliest start time is 1.25 msecs from the end of the connect
      * request transmission. Note that adv_rxend is the end of the received
@@ -370,8 +375,9 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
      */
     dur = os_cputime_usecs_to_ticks(req_slots * BLE_LL_SCHED_USECS_PER_SLOT);
     earliest_start = adv_rxend +
-        os_cputime_usecs_to_ticks(BLE_LL_IFS + BLE_LL_CONN_REQ_DURATION +
-                                  BLE_LL_CONN_INITIAL_OFFSET);
+        os_cputime_usecs_to_ticks(BLE_LL_IFS +
+            ble_phy_pdu_dur(BLE_CONNECT_REQ_LEN, BLE_PHY_1M) +
+            BLE_LL_CONN_INITIAL_OFFSET);
     earliest_end = earliest_start + dur;
     itvl_t = os_cputime_usecs_to_ticks(connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS);
 #endif



[5/6] incubator-mynewt-core git commit: MYNEWT-723: Add control procedure code and HCI command/event code.

Posted by ry...@apache.org.
MYNEWT-723: Add control procedure code and HCI command/event code.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/bb2c04ed
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/bb2c04ed
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/bb2c04ed

Branch: refs/heads/bluetooth5
Commit: bb2c04ed88cbfe8eb15fa1d68a7d8b8b2b1b69a6
Parents: 5741441
Author: William San Filippo <wi...@runtime.io>
Authored: Sun Apr 23 15:02:14 2017 -0700
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Apr 27 23:39:36 2017 +0200

----------------------------------------------------------------------
 net/nimble/controller/src/ble_ll_conn_hci.c | 3 ++-
 net/nimble/include/nimble/hci_common.h      | 8 ++++----
 2 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/bb2c04ed/net/nimble/controller/src/ble_ll_conn_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_hci.c b/net/nimble/controller/src/ble_ll_conn_hci.c
index 6ce5c6b..f15dc2d 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -1290,7 +1290,8 @@ ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf)
         CONN_F_HOST_PHY_UPDATE(connsm) = 1;
     } else {
         /*
-         * We could be doing a peer-initiated PHY update procedure. If
+         * We could be doing a peer-initiated PHY update procedure. If this
+         * is the case the requested phy preferences will not both be 0. If
          * we are not done with a peer-initiated procedure we just set the
          * pending bit but do not start the control procedure.
          */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/bb2c04ed/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index f929d85..86bc862 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -427,14 +427,14 @@ extern "C" {
 #define BLE_HCI_LE_SET_DEFAULT_PHY_LEN              (3)
 #define BLE_HCI_LE_PHY_NO_TX_PREF_MASK              (0x01)
 #define BLE_HCI_LE_PHY_NO_RX_PREF_MASK              (0x02)
-#define BLE_HCI_LE_PHY_PREF_MASK_ALL                \
-    (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK |  \
-     BLE_HCI_LE_PHY_CODED_PREF_MASK)
-
 #define BLE_HCI_LE_PHY_1M_PREF_MASK                 (0x01)
 #define BLE_HCI_LE_PHY_2M_PREF_MASK                 (0x02)
 #define BLE_HCI_LE_PHY_CODED_PREF_MASK              (0x04)
 
+#define BLE_HCI_LE_PHY_PREF_MASK_ALL                \
+    (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK |  \
+     BLE_HCI_LE_PHY_CODED_PREF_MASK)
+
 /* --- LE set PHY (OCF 0x0032) */
 #define BLE_HCI_LE_SET_PHY_LEN                      (7)
 #define BLE_HCI_LE_PHY_CODED_ANY                    (0x0000)