You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2016/06/15 15:29:07 UTC

incubator-mynewt-core git commit: Add LE ping and Authenticated Payload Timeout event

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/upf54 a1de643d4 -> 9fc076cc3


Add LE ping and Authenticated Payload Timeout event


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/9fc076cc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/9fc076cc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/9fc076cc

Branch: refs/heads/upf54
Commit: 9fc076cc3269acbba6ed2b36bc3471fe93b196be
Parents: a1de643
Author: William San Filippo <wi...@runtime.io>
Authored: Wed Jun 15 08:28:44 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Wed Jun 15 08:29:00 2016 -0700

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll_conn.h |   7 ++
 .../controller/include/controller/ble_ll_ctrl.h |   2 +-
 net/nimble/controller/src/ble_ll.c              |   4 +
 net/nimble/controller/src/ble_ll_conn.c         |  77 ++++++++++++++
 net/nimble/controller/src/ble_ll_conn_hci.c     | 106 +++++++++++++++++++
 net/nimble/controller/src/ble_ll_conn_priv.h    |  15 +++
 net/nimble/controller/src/ble_ll_ctrl.c         |  44 ++++++--
 net/nimble/controller/src/ble_ll_hci.c          |  42 +++++++-
 net/nimble/host/include/host/host_hci.h         |   2 +
 net/nimble/host/src/ble_hs_startup.c            |  10 ++
 net/nimble/host/src/host_dbg.c                  |  25 +++++
 net/nimble/host/src/host_hci_cmd.c              |  15 +++
 net/nimble/include/nimble/hci_common.h          |   8 +-
 13 files changed, 346 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 035ca39..38a3a22 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -110,6 +110,7 @@ union ble_ll_conn_sm_flags {
         uint32_t send_ltk_req:1;
         uint32_t encrypted:1;
         uint32_t encrypt_chg_sent:1;
+        uint32_t le_ping_supp:1;
     } cfbit;
     uint32_t conn_flags;
 } __attribute__((packed));
@@ -178,6 +179,7 @@ struct ble_ll_conn_sm
     uint16_t completed_pkts;
     uint16_t comp_id;
     uint16_t sub_vers_nr;
+    uint16_t auth_pyld_tmo;         /* could be ifdef'd. 10 msec units */
 
     uint32_t access_addr;
     uint32_t crcinit;               /* only low 24 bits used */
@@ -230,6 +232,10 @@ struct ble_ll_conn_sm
     /* For scheduling connections */
     struct ble_ll_sched_item conn_sch;
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    struct os_callout_func auth_pyld_timer;
+#endif
+
     /*
      * XXX: a note on all these structures for control procedures. First off,
      * all of these need to be ifdef'd to save memory. Another thing to
@@ -261,6 +267,7 @@ struct ble_ll_conn_sm
 #define CONN_F_CONN_REQ_TXD(csm)    ((csm)->csmflags.cfbit.conn_req_txd)
 #define CONN_F_ENCRYPTED(csm)       ((csm)->csmflags.cfbit.encrypted)
 #define CONN_F_ENC_CHANGE_SENT(csm) ((csm)->csmflags.cfbit.encrypt_chg_sent)
+#define CONN_F_LE_PING_SUPP(csm)    ((csm)->csmflags.cfbit.le_ping_supp)
 
 /* 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/9fc076cc/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 a5cd99b..f652faf 100644
--- a/net/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -32,7 +32,7 @@
 #define BLE_LL_CTRL_PROC_VERSION_XCHG   (4)
 #define BLE_LL_CTRL_PROC_TERMINATE      (5)
 #define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6)
-#define BLE_LL_CRTL_PROC_LE_PING        (7)
+#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_IDLE           (255)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 0459ff0..f1b5f6c 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -1167,6 +1167,10 @@ ble_ll_init(uint8_t ll_task_prio, uint8_t num_acl_pkts, uint16_t acl_pkt_size)
     ble_ll_resolv_init();
 #endif
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    features |= BLE_LL_FEAT_LE_PING;
+#endif
+
     /* Initialize random number generation */
     ble_ll_rand_init();
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 7b69a65..312c26f 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1265,6 +1265,44 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime)
     return rc;
 }
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+/**
+ * Callback for the Authenticated payload timer. This function is called
+ * when the authenticated payload timer expires. When the authenticated
+ * payload timeout expires, we should
+ *  -> Send the authenticated payload timeout event.
+ *  -> Start the LE ping procedure.
+ *  -> Restart the timer.
+ *
+ * @param arg
+ */
+void
+ble_ll_conn_auth_pyld_timer_cb(void *arg)
+{
+    struct ble_ll_conn_sm *connsm;
+
+    connsm = (struct ble_ll_conn_sm *)arg;
+    ble_ll_auth_pyld_tmo_event_send(connsm);
+    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING);
+    ble_ll_conn_auth_pyld_timer_start(connsm);
+}
+
+/**
+ * Start (or restart) the authenticated payload timer
+ *
+ * @param connsm
+ */
+void
+ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm)
+{
+    int32_t tmo;
+
+    /* Timeout in is in 10 msec units */
+    tmo = (int32_t)BLE_LL_CONN_AUTH_PYLD_OS_TMO(connsm->auth_pyld_tmo);
+    os_callout_reset(&connsm->auth_pyld_timer.cf_c, tmo);
+}
+#endif
+
 /**
  * Connection supervision timer callback; means that the connection supervision
  * timeout has been reached and we should perform the appropriate actions.
@@ -1434,6 +1472,15 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
     connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED;
 #endif
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    connsm->auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO;
+    CONN_F_LE_PING_SUPP(connsm) = 1;
+    os_callout_func_init(&connsm->auth_pyld_timer,
+                         &g_ble_ll_data.ll_evq,
+                         ble_ll_conn_auth_pyld_timer_cb,
+                         connsm);
+#endif
+
     /* Add to list of active connections */
     SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
 }
@@ -1513,6 +1560,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
     /* Stop any control procedures that might be running */
     os_callout_stop(&connsm->ctrl_proc_rsp_timer.cf_c);
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    os_callout_stop(&connsm->auth_pyld_timer.cf_c);
+#endif
+
     /* Remove from the active connection list */
     SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
 
@@ -1842,6 +1893,20 @@ ble_ll_conn_event_end(void *arg)
         connsm->slave_cur_tx_win_usecs = 0;
     }
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    /*
+     * If we are encrypted and have passed the authenticated payload timeout
+     * we need to send an event to tell the host. Unfortunately, I think we
+     * need one of these per connection and we have to set this timer
+     * fairly accurately. So we need to another event in the connection.
+     * This sucks.
+     *
+     * The way this works is that whenever the timer expires it just gets reset
+     * and we send the autheticated payload timeout event. Note that this timer
+     * should run even when encryption is paused.
+     */
+#endif
+
     /* Move to next connection event */
     if (ble_ll_conn_next_event(connsm)) {
         ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL);
@@ -2410,6 +2475,18 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
                 goto conn_rx_data_pdu_end;
             }
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+            /*
+             * Reset authenticated payload timeout if valid MIC. NOTE: we dont
+             * check the MIC failure bit as that would have terminated the
+             * connection
+             */
+            if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
+                CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
+                ble_ll_conn_auth_pyld_timer_start(connsm);
+            }
+#endif
+
             /* Update RSSI */
             connsm->conn_rssi = hdr->rxinfo.rssi;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 08ced85..e1bc978 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -298,6 +298,31 @@ ble_ll_conn_num_comp_pkts_event_send(void)
     }
 }
 
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+/**
+ * Send a authenticated payload timeout event
+ *
+ * NOTE: we currently only send this event when we have a reason to send it;
+ * not when it fails.
+ *
+ * @param reason The BLE error code to send as a disconnect reason
+ */
+void
+ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm)
+{
+    uint8_t *evbuf;
+
+    if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_AUTH_PYLD_TMO)) {
+        evbuf = os_memblock_get(&g_hci_cmd_pool);
+        if (evbuf) {
+            evbuf[0] = BLE_HCI_EVCODE_AUTH_PYLD_TMO;
+            evbuf[1] = sizeof(uint16_t);
+            htole16(evbuf + 2, connsm->conn_handle);
+            ble_ll_hci_event_send(evbuf);
+        }
+    }
+}
+#endif
 
 /**
  * Send a disconnection complete event.
@@ -1035,3 +1060,84 @@ ltk_key_cmd_complete:
     return rc;
 }
 #endif
+
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+/**
+ * Read authenticated payload timeout (OGF=3, OCF==0x007B)
+ *
+ * @param cmdbuf
+ * @param rsplen
+ *
+ * @return int
+ */
+int
+ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
+{
+    int rc;
+    uint16_t handle;
+    struct ble_ll_conn_sm *connsm;
+
+    handle = le16toh(cmdbuf);
+    connsm = ble_ll_conn_find_active_conn(handle);
+    if (!connsm) {
+        rc = BLE_ERR_UNK_CONN_ID;
+    } else {
+        htole16(rsp + 2, connsm->auth_pyld_tmo);
+        rc = BLE_ERR_SUCCESS;
+    }
+
+    htole16(rsp, handle);
+    *rsplen = BLE_HCI_RD_AUTH_PYLD_TMO_LEN;
+    return rc;
+}
+
+/**
+ * Write authenticated payload timeout (OGF=3, OCF=00x7C)
+ *
+ * @param cmdbuf
+ * @param rsplen
+ *
+ * @return int
+ */
+int
+ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
+{
+    int rc;
+    uint16_t handle;
+    uint16_t tmo;
+    uint32_t min_tmo;
+    struct ble_ll_conn_sm *connsm;
+
+    rc = BLE_ERR_SUCCESS;
+
+    handle = le16toh(cmdbuf);
+    connsm = ble_ll_conn_find_active_conn(handle);
+    if (!connsm) {
+        rc = BLE_ERR_UNK_CONN_ID;
+        goto wr_auth_exit;
+    }
+
+    /*
+     * The timeout is in units of 10 msecs. We need to make sure that the
+     * timeout is greater than or equal to connItvl * (1 + slaveLatency)
+     */
+    tmo = le16toh(cmdbuf + 2);
+    min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+    min_tmo *= (connsm->slave_latency + 1);
+    min_tmo /= 10000;
+
+    if (tmo < min_tmo) {
+        rc = BLE_ERR_INV_HCI_CMD_PARMS;
+    } else {
+        connsm->auth_pyld_tmo = tmo;
+        if (os_callout_queued(&connsm->auth_pyld_timer.cf_c)) {
+            ble_ll_conn_auth_pyld_timer_start(connsm);
+        }
+    }
+
+wr_auth_exit:
+    htole16(rsp, handle);
+    *rsplen = BLE_HCI_WR_AUTH_PYLD_TMO_LEN;
+    return rc;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 7794a6a..c94093e 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -51,6 +51,11 @@
 /* Offset (in bytes) of advertising address in connect request */
 #define BLE_LL_CONN_REQ_ADVA_OFF    (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
 
+/* Default authenticated payload timeout (30 seconds; in 10 msecs increments) */
+#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO       (3000)
+#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x)     \
+    ((((uint32_t)(x)) * 10 * OS_TICKS_PER_SEC) / 1000)
+
 /* Global Link Layer connection parameters */
 struct ble_ll_conn_global_params
 {
@@ -115,6 +120,7 @@ uint8_t ble_ll_conn_calc_used_chans(uint8_t *chmap);
 /* HCI */
 void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
                                     uint8_t reason);
+void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
 int ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf);
 int ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf);
 int ble_ll_conn_create(uint8_t *cmdbuf);
@@ -135,4 +141,13 @@ int ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf,
                                  uint8_t *rsplen);
 int ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf);
 int ble_ll_conn_hci_le_ltk_reply(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t ocf);
+int ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp,
+                                     uint8_t *rsplen);
+int ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp,
+                                     uint8_t *rsplen);
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
+#else
+#define ble_ll_conn_auth_pyld_timer_start(x)
+#endif
 #endif /* H_BLE_LL_CONN_PRIV_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 73a5ac2..3ba69af 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -137,6 +137,21 @@ ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
 }
 
 /**
+ * Process a received LL_PING_RSP control pdu.
+ *
+ * NOTE: we dont have to reset the callout since this packet will have had a
+ * valid MIC and that will restart the authenticated payload timer
+ *
+ * @param connsm
+ */
+static void
+ble_ll_ctrl_rx_ping_rsp(struct ble_ll_conn_sm *connsm)
+{
+    /* Stop the control procedure */
+    ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_LE_PING);
+}
+
+/**
  * Called when we receive either a connection parameter request or response.
  *
  * @param connsm
@@ -274,7 +289,6 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
     /* Get opcode of unknown LL control frame */
     opcode = dptr[0];
 
-    /* XXX: add others here */
     /* Convert opcode to control procedure id */
     switch (opcode) {
     case BLE_LL_CTRL_LENGTH_REQ:
@@ -290,13 +304,18 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
     case BLE_LL_CTRL_CONN_PARM_REQ:
         ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ;
         break;
+    case BLE_LL_CTRL_PING_REQ:
+        CONN_F_LE_PING_SUPP(connsm) = 0;
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+        os_callout_stop(&connsm->auth_pyld_timer.cf_c);
+#endif
+        ctrl_proc = BLE_LL_CTRL_PROC_LE_PING;
+        break;
     default:
         ctrl_proc = BLE_LL_CTRL_PROC_NUM;
         break;
     }
 
-    /* XXX: are there any other events that we need to send when we get
-       the unknown response? */
     /* If we are running this one currently, stop it */
     if (connsm->cur_ctrl_proc == ctrl_proc) {
         /* Stop the control procedure */
@@ -304,7 +323,6 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
         if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) {
             ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
         } else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) {
-            /* XXX: should only get this if a slave initiated this */
             ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
         }
     }
@@ -679,6 +697,9 @@ ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm)
         /* We are encrypted */
         connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED;
         ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+        ble_ll_conn_auth_pyld_timer_start(connsm);
+#endif
         rc = BLE_ERR_MAX;
     } else {
         /* Procedure has completed but slave needs to send START_ENC_RSP */
@@ -1274,6 +1295,9 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
             opcode = BLE_LL_CTRL_CONN_PARM_REQ;
             ble_ll_ctrl_conn_param_pdu_make(connsm, ctrdata, NULL);
             break;
+        case BLE_LL_CTRL_PROC_LE_PING:
+            opcode = BLE_LL_CTRL_PING_REQ;
+            break;
         case BLE_LL_CTRL_PROC_DATA_LEN_UPD:
             opcode = BLE_LL_CTRL_LENGTH_REQ;
             ble_ll_ctrl_datalen_upd_make(connsm, dptr);
@@ -1559,6 +1583,9 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
     case BLE_LL_CTRL_PAUSE_ENC_REQ:
         feature = BLE_LL_FEAT_LE_ENCRYPTION;
         break;
+    case BLE_LL_CTRL_PING_REQ:
+        feature = BLE_LL_FEAT_LE_PING;
+        break;
     default:
         feature = 0;
         break;
@@ -1670,8 +1697,10 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
         break;
 #endif
     case BLE_LL_CTRL_PING_REQ:
-        /* XXX: implement */
-        rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
+        rsp_opcode = BLE_LL_CTRL_PING_RSP;
+        break;
+    case BLE_LL_CTRL_PING_RSP:
+        ble_ll_ctrl_rx_ping_rsp(connsm);
         break;
     case BLE_LL_CTRL_CONN_PARM_REQ:
         rsp_opcode = ble_ll_ctrl_rx_conn_param_req(connsm, dptr, rspbuf);
@@ -1817,6 +1846,9 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
     case BLE_LL_CTRL_START_ENC_RSP:
         if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
             connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED;
+            if (CONN_F_LE_PING_SUPP(connsm)) {
+                ble_ll_conn_auth_pyld_timer_start(connsm);
+            }
         }
         break;
     case BLE_LL_CTRL_PAUSE_ENC_RSP:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 d6e574d..fd75fbb 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -36,6 +36,7 @@
 /* LE event mask */
 static uint8_t g_ble_ll_hci_le_event_mask[BLE_HCI_SET_LE_EVENT_MASK_LEN];
 static uint8_t g_ble_ll_hci_event_mask[BLE_HCI_SET_EVENT_MASK_LEN];
+static uint8_t g_ble_ll_hci_event_mask2[BLE_HCI_SET_EVENT_MASK_LEN];
 
 /**
  * ll hci get num cmd pkts
@@ -437,7 +438,11 @@ ble_ll_hci_is_le_event_enabled(int subev)
 /**
  * Checks to see if an event has been disabled by the host.
  *
- * @param evcode This is the event code for the event (0 - 63).
+ * NOTE: there are two "pages" of event masks; the first page is for event
+ * codes between 0 and 63 and the second page is for event codes 64 and
+ * greater.
+ *
+ * @param evcode This is the event code for the event.
  *
  * @return uint8_t 0: event is not enabled; otherwise event is enabled.
  */
@@ -447,12 +452,20 @@ ble_ll_hci_is_event_enabled(int evcode)
     uint8_t enabled;
     uint8_t bytenum;
     uint8_t bitmask;
+    uint8_t *evptr;
     int bitpos;
 
-    bitpos = evcode - 1;
+    if (evcode >= 64) {
+        evptr = &g_ble_ll_hci_event_mask2[0];
+        bitpos = evcode - 64;
+    } else {
+        evptr = &g_ble_ll_hci_event_mask[0];
+        bitpos = evcode - 1;
+    }
+
     bytenum = bitpos / 8;
     bitmask = 1 << (bitpos & 0x7);
-    enabled = g_ble_ll_hci_event_mask[bytenum] & bitmask;
+    enabled = evptr[bytenum] & bitmask;
 
     return enabled;
 }
@@ -746,6 +759,9 @@ ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
 {
     int rc;
     uint8_t len;
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    uint8_t *rspbuf;
+#endif
 
     /* Assume error; if all pass rc gets set to 0 */
     rc = BLE_ERR_INV_HCI_CMD_PARMS;
@@ -755,6 +771,9 @@ ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
 
     /* Move past HCI command header */
     cmdbuf += BLE_HCI_CMD_HDR_LEN;
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
+#endif
 
     switch (ocf) {
     case BLE_HCI_OCF_CB_SET_EVENT_MASK:
@@ -768,6 +787,20 @@ ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
             rc = ble_ll_reset();
         }
         break;
+    case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
+        if (len == BLE_HCI_SET_EVENT_MASK_LEN) {
+            memcpy(g_ble_ll_hci_event_mask2, cmdbuf, len);
+            rc = BLE_ERR_SUCCESS;
+        }
+        break;
+#if (BLE_LL_CFG_FEAT_LE_PING == 1)
+    case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO:
+        rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, rspbuf, rsplen);
+        break;
+    case BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO:
+        rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, rspbuf, rsplen);
+        break;
+#endif
     default:
         rc = BLE_ERR_UNKNOWN_HCI_CMD;
         break;
@@ -1000,4 +1033,7 @@ ble_ll_hci_init(void)
     g_ble_ll_hci_event_mask[3] = 0xff;
     g_ble_ll_hci_event_mask[4] = 0xff;
     g_ble_ll_hci_event_mask[5] = 0x1f;
+
+    /* Set page 2 to 0 */
+    memset(g_ble_ll_hci_event_mask2, 0, BLE_HCI_SET_EVENT_MASK_LEN);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/net/nimble/host/include/host/host_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/host_hci.h b/net/nimble/host/include/host/host_hci.h
index 12da775..af7c2c2 100644
--- a/net/nimble/host/include/host/host_hci.h
+++ b/net/nimble/host/include/host/host_hci.h
@@ -32,6 +32,8 @@ int host_hci_cmd_send(uint8_t ogf, uint8_t ocf, uint8_t len, void *cmddata);
 int host_hci_cmd_send_buf(void *cmddata);
 void host_hci_cmd_build_set_event_mask(uint64_t event_mask,
                                        uint8_t *dst, int dst_len);
+void host_hci_cmd_build_set_event_mask2(uint64_t event_mask, uint8_t *dst,
+                                        int dst_len);
 void host_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
                                    uint8_t *dst, int dst_len);
 int host_hci_cmd_disconnect(uint16_t handle, uint8_t reason);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 310c5b8..16834ec 100644
--- a/net/nimble/host/src/ble_hs_startup.c
+++ b/net/nimble/host/src/ble_hs_startup.c
@@ -157,6 +157,16 @@ ble_hs_startup_set_evmask_tx(void)
         return rc;
     }
 
+    /**
+     * Enable the following events:
+     *     0x0000000000800000 Authenticated Payload Timeout Event
+     */
+    host_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
+    rc = ble_hci_cmd_tx_empty_ack(buf);
+    if (rc != 0) {
+        return rc;
+    }
+
     return 0;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/net/nimble/host/src/host_dbg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_dbg.c b/net/nimble/host/src/host_dbg.c
index d7a31e3..6b58624 100644
--- a/net/nimble/host/src/host_dbg.c
+++ b/net/nimble/host/src/host_dbg.c
@@ -275,6 +275,28 @@ host_hci_dbg_num_comp_pkts_disp(uint8_t *evdata, uint8_t len)
     }
 }
 
+/**
+ * Display the authenticated payload timeout event
+ *
+ * @param evdata
+ * @param len
+ */
+static void
+host_hci_dbg_auth_pyld_tmo_disp(uint8_t *evdata, uint8_t len)
+{
+    uint16_t handle;
+
+    if (len != sizeof(uint16_t)) {
+        BLE_HS_LOG(DEBUG, "ERR: AuthPyldTmoEvent bad length %u\n", len);
+        return;
+
+    }
+
+    handle = le16toh(evdata);
+    BLE_HS_LOG(DEBUG, "AuthPyldTmo: handle=%u\n", handle);
+}
+
+
 static void
 host_hci_dbg_cmd_comp_info_params(uint8_t status, uint8_t ocf, uint8_t *evdata)
 {
@@ -471,6 +493,9 @@ host_hci_dbg_event_disp(uint8_t *evbuf)
     case BLE_HCI_EVCODE_LE_META:
         host_hci_dbg_le_event_disp(evdata[0], len, evdata + 1);
         break;
+    case BLE_HCI_EVCODE_AUTH_PYLD_TMO:
+        host_hci_dbg_auth_pyld_tmo_disp(evdata, len);
+        break;
     default:
         BLE_HS_LOG(DEBUG, "Unknown event 0x%x len=%u\n", evcode, len);
         break;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
index 887ddfb..09c6944 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -323,6 +323,21 @@ host_hci_cmd_build_set_event_mask(uint64_t event_mask,
     host_hci_cmd_body_set_event_mask(event_mask, dst);
 }
 
+void
+host_hci_cmd_build_set_event_mask2(uint64_t event_mask,
+                                  uint8_t *dst, int dst_len)
+{
+    BLE_HS_DBG_ASSERT(
+        dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_EVENT_MASK_LEN);
+
+    host_hci_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND,
+                       BLE_HCI_OCF_CB_SET_EVENT_MASK2,
+                       BLE_HCI_SET_EVENT_MASK_LEN, dst);
+    dst += BLE_HCI_CMD_HDR_LEN;
+
+    host_hci_cmd_body_set_event_mask(event_mask, dst);
+}
+
 static void
 host_hci_cmd_body_disconnect(uint16_t handle, uint8_t reason, uint8_t *dst)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fc076cc/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 962df49..0292be5 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -61,8 +61,10 @@
 /* List of OCF for Controller and Baseband commands (OGF=0x03) */
 #define BLE_HCI_OCF_CB_SET_EVENT_MASK       (0x0001)
 #define BLE_HCI_OCF_CB_RESET                (0x0003)
-#define BLE_HCI_OCF_CB_SET_EV_FILT          (0x0005)
 #define BLE_HCI_OCF_CB_READ_TX_PWR          (0x002D)
+#define BLE_HCI_OCF_CB_SET_EVENT_MASK2      (0x0063)
+#define BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO     (0x007B)
+#define BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO     (0x007C)
 
 /* List of OCF for Info Param commands (OGF=0x04) */
 #define BLE_HCI_OCF_IP_RD_LOCAL_VER         (0x0001)
@@ -129,6 +131,10 @@
 /* --- Set event mask (OGF 0x03, OCF 0x0001 --- */
 #define BLE_HCI_SET_EVENT_MASK_LEN          (8)
 
+/* --- Read/Write authenticated payload timeout (ocf 0x007B/0x007C) */
+#define BLE_HCI_RD_AUTH_PYLD_TMO_LEN        (4)
+#define BLE_HCI_WR_AUTH_PYLD_TMO_LEN        (2)
+
 /* --- Read local version information (OGF 0x04, OCF 0x0001) --- */
 /* NOTE: does not include status field in command complete event! */
 #define BLE_HCI_RD_LOC_VER_INFO_RSPLEN      (8)