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/09/12 18:24:43 UTC

incubator-mynewt-core git commit: MYNEWT-386: Controller should always send connection complete event

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 61a210874 -> d56270d97


MYNEWT-386: Controller should always send connection complete event

The following changes were made to insure that the controller will
always send a connection complete event to the host. When either
a connection create command is sent or a start advertising command
is sent, the controller will attempt to allocate an event buffer
with which to send the connection complete event. If this fails,
the controller will return an error: BLE_ERR_MEM_CAPACITY. If
this succeeds, the controller will then be able to send the
connection complete event to the host.


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

Branch: refs/heads/develop
Commit: d56270d97a068e8f0b4116210b66cd01d9c28e20
Parents: 61a2108
Author: William San Filippo <wi...@runtime.io>
Authored: Mon Sep 12 11:20:13 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Mon Sep 12 11:22:56 2016 -0700

----------------------------------------------------------------------
 apps/bletest/src/main.c                         |  20 ++-
 .../controller/include/controller/ble_ll_adv.h  |   3 +
 net/nimble/controller/src/ble_ll_adv.c          |  51 +++++++-
 net/nimble/controller/src/ble_ll_conn.c         |  40 +++++-
 net/nimble/controller/src/ble_ll_conn_hci.c     | 130 +++++++++++--------
 net/nimble/controller/src/ble_ll_conn_priv.h    |   3 +-
 6 files changed, 186 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index d21cc50..066d52e 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -113,7 +113,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_CFG_ADV_ITVL            (60000 / BLE_HCI_ADV_ITVL)
 #define BLETEST_CFG_ADV_TYPE            BLE_HCI_ADV_TYPE_ADV_IND
 #define BLETEST_CFG_ADV_FILT_POLICY     (BLE_HCI_ADV_FILT_NONE)
-#define BLETEST_CFG_ADV_ADDR_RES_EN     (1)
+#define BLETEST_CFG_ADV_ADDR_RES_EN     (0)
 
 /* Scan config */
 #define BLETEST_CFG_SCAN_ITVL           (700000 / BLE_HCI_SCAN_ITVL)
@@ -170,6 +170,7 @@ uint16_t g_bletest_completed_pkts;
 uint16_t g_bletest_outstanding_pkts;
 uint16_t g_bletest_ltk_reply_handle;
 uint32_t g_bletest_hw_id[4];
+struct hci_create_conn g_cc;
 
 /* --- For LE encryption testing --- */
 /* Key: 0x4C68384139F574D836BCF34E9DFB01BF */
@@ -482,11 +483,10 @@ bletest_init_initiator(void)
 {
     int rc;
     uint8_t rand_addr[BLE_DEV_ADDR_LEN];
-    struct hci_create_conn cc;
     struct hci_create_conn *hcc;
 
     /* Enable initiating */
-    hcc = &cc;
+    hcc = &g_cc;
     hcc->conn_itvl_max = BLETEST_CFG_CONN_ITVL;
     hcc->conn_itvl_min = BLETEST_CFG_CONN_ITVL;
     hcc->conn_latency = BLETEST_CFG_SLAVE_LATENCY;
@@ -529,8 +529,7 @@ bletest_init_initiator(void)
         }
 #endif
 
-    rc = bletest_hci_le_create_connection(hcc);
-    assert(rc == 0);
+    bletest_hci_le_create_connection(hcc);
 }
 
 void
@@ -573,6 +572,10 @@ bletest_execute_initiator(void)
                     bletest_init_initiator();
                 }
             }
+        } else {
+            if (ble_ll_scan_enabled() == 0) {
+                bletest_hci_le_create_connection(&g_cc);
+            }
         }
     } else {
         if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
@@ -716,7 +719,12 @@ bletest_execute_advertiser(void)
                 g_bletest_cur_peer_addr[5] += 1;
                 g_dev_addr[5] += 1;
                 bletest_init_advertising();
-                rc = bletest_hci_le_set_adv_enable(1);
+                bletest_hci_le_set_adv_enable(1);
+            }
+        } else {
+            /* If we failed to start advertising we should keep trying */
+            if (ble_ll_adv_enabled() == 0) {
+                bletest_hci_le_set_adv_enable(1);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/net/nimble/controller/include/controller/ble_ll_adv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_adv.h b/net/nimble/controller/include/controller/ble_ll_adv.h
index 33a73ab..8d9a16d 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -116,6 +116,9 @@ int ble_ll_adv_set_adv_params(uint8_t *cmd);
 int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen);
 
 /*---- API used by BLE LL ----*/
+/* Returns the event allocated to send the connection complete event */
+uint8_t *ble_ll_adv_get_conn_comp_ev(void);
+
 /* Returns local resolvable private address */
 uint8_t *ble_ll_adv_get_local_rpa(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/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 ceb5025..3e2ce1f 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -25,6 +25,7 @@
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
 #include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "controller/ble_ll.h"
@@ -94,6 +95,7 @@ struct ble_ll_adv_sm
     uint8_t initiator_addr[BLE_DEV_ADDR_LEN];
     uint8_t adv_data[BLE_ADV_DATA_MAX_LEN];
     uint8_t scan_rsp_data[BLE_SCAN_RSP_DATA_MAX_LEN];
+    uint8_t *conn_comp_ev;
     struct os_event adv_txdone_ev;
     struct ble_ll_sched_item adv_sch;
 };
@@ -658,6 +660,12 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
         }
         OS_EXIT_CRITICAL(sr);
 
+        /* If there is an event buf we need to free it */
+        if (advsm->conn_comp_ev) {
+            ble_hci_trans_buf_free(advsm->conn_comp_ev);
+            advsm->conn_comp_ev = NULL;
+        }
+
         /* Disable advertising */
         advsm->enabled = 0;
     }
@@ -679,6 +687,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
 {
     uint8_t adv_chan;
     uint8_t *addr;
+    uint8_t *evbuf;
 
     /*
      * This is not in the specification. I will reject the command with a
@@ -693,6 +702,27 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
         }
     }
 
+    /*
+     * Get an event with which to send the connection complete event if
+     * this is connectable
+     */
+    switch (advsm->adv_type) {
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
+    case BLE_HCI_ADV_TYPE_ADV_IND:
+        /* We expect this to be NULL but if not we wont allocate one... */
+        if (advsm->conn_comp_ev == NULL) {
+            evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+            if (!evbuf) {
+                return BLE_ERR_MEM_CAPACITY;
+            }
+            advsm->conn_comp_ev = evbuf;
+        }
+        break;
+    default:
+        break;
+    }
+
     /* Set advertising address */
     if ((advsm->own_addr_type & 1) == 0) {
         addr = g_dev_addr;
@@ -1310,7 +1340,9 @@ ble_ll_adv_event_done(void *arg)
         if (advsm->adv_pdu_start_time >= advsm->adv_dir_hd_end_time) {
             /* Disable advertising */
             advsm->enabled = 0;
-            ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO);
+            ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO,
+                                        advsm->conn_comp_ev);
+            advsm->conn_comp_ev = NULL;
             ble_ll_scan_chk_resume();
             return;
         }
@@ -1357,6 +1389,23 @@ ble_ll_adv_can_chg_whitelist(void)
 }
 
 /**
+ * Returns the event allocated to send the connection complete event
+ *
+ * @return uint8_t* Pointer to event buffer
+ */
+uint8_t *
+ble_ll_adv_get_conn_comp_ev(void)
+{
+    uint8_t *evbuf;
+
+    evbuf = g_ble_ll_adv_sm.conn_comp_ev;
+    assert(evbuf != NULL);
+    g_ble_ll_adv_sm.conn_comp_ev = NULL;
+
+    return evbuf;
+}
+
+/**
  * Returns the local resolvable private address currently being using by
  * the advertiser
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/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 642e8c6..43944a8 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -34,6 +34,7 @@
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_ctrl.h"
 #include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_adv.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "ble_ll_conn_priv.h"
@@ -134,6 +135,9 @@ static const uint16_t g_ble_sca_ppm_tbl[8] =
     500, 250, 150, 100, 75, 50, 30, 20
 };
 
+/* Global connection complete event. Used when initiating */
+uint8_t *g_ble_ll_conn_comp_ev;
+
 /* Global LL connection parameters */
 struct ble_ll_conn_global_params g_ble_ll_conn_params;
 
@@ -211,6 +215,24 @@ STATS_NAME_START(ble_ll_conn_stats)
     STATS_NAME(ble_ll_conn_stats, mic_failures)
 STATS_NAME_END(ble_ll_conn_stats)
 
+/**
+ * Get the event buffer allocated to send the connection complete event
+ * when we are initiating.
+ *
+ * @return uint8_t*
+ */
+static uint8_t *
+ble_ll_init_get_conn_comp_ev(void)
+{
+    uint8_t *evbuf;
+
+    evbuf = g_ble_ll_conn_comp_ev;
+    assert(evbuf != NULL);
+    g_ble_ll_conn_comp_ev = NULL;
+
+    return evbuf;
+}
+
 #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1)
 /**
  * Called to determine if the received PDU is an empty PDU or not.
@@ -1548,6 +1570,7 @@ ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
 void
 ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
 {
+    uint8_t *evbuf;
     struct os_mbuf *m;
     struct os_mbuf_pkthdr *pkthdr;
 
@@ -1602,7 +1625,8 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
      */
     if (ble_err) {
         if (ble_err == BLE_ERR_UNK_CONN_ID) {
-            ble_ll_conn_comp_event_send(connsm, ble_err);
+            evbuf = ble_ll_init_get_conn_comp_ev();
+            ble_ll_conn_comp_event_send(connsm, ble_err, evbuf);
         } else {
             ble_ll_disconn_comp_event_send(connsm, ble_err);
         }
@@ -1779,6 +1803,7 @@ static int
 ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
 {
     int rc;
+    uint8_t *evbuf;
     uint32_t usecs;
 
     /* Set state to created */
@@ -1837,7 +1862,12 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
                 ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
             }
         }
-        ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+            evbuf = ble_ll_adv_get_conn_comp_ev();
+        } else {
+            evbuf = ble_ll_init_get_conn_comp_ev();
+        }
+        ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf);
     }
 
     return rc;
@@ -3140,6 +3170,12 @@ ble_ll_conn_module_reset(void)
         ble_ll_conn_end(connsm, BLE_ERR_SUCCESS);
     }
 
+    /* Free the global connection complete event if there is one */
+    if (g_ble_ll_conn_comp_ev) {
+        ble_hci_trans_buf_free(g_ble_ll_conn_comp_ev);
+        g_ble_ll_conn_comp_ev = NULL;
+    }
+
     /* Now go through and end all the connections */
     while (1) {
         connsm = SLIST_FIRST(&g_ble_ll_conn_active_list);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/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 5d44d27..1242cc4 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -39,6 +39,32 @@
  * event to the host. This is the os time at which we can send an event.
  */
 static uint32_t g_ble_ll_last_num_comp_pkt_evt;
+extern uint8_t *g_ble_ll_conn_comp_ev;
+
+/**
+ * Allocate an event to send a connection complete event when initiating
+ *
+ * @return int 0: success -1: failure
+ */
+static int
+ble_ll_init_alloc_conn_comp_ev(void)
+{
+    int rc;
+    uint8_t *evbuf;
+
+    rc = 0;
+    evbuf = g_ble_ll_conn_comp_ev;
+    if (evbuf == NULL) {
+        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+        if (!evbuf) {
+            rc = -1;
+        } else {
+            g_ble_ll_conn_comp_ev = evbuf;
+        }
+    }
+
+    return rc;
+}
 
 /**
  * Called to check that the connection parameters are within range
@@ -128,12 +154,12 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
  * @param status The BLE error code associated with the event
  */
 void
-ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
+ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
+                            uint8_t *evbuf)
 {
     uint8_t peer_addr_type;
     uint8_t enabled;
     uint8_t enh_enabled;
-    uint8_t *evbuf;
     uint8_t *evdata;
     uint8_t *rpa;
 
@@ -141,65 +167,62 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
     enh_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE);
 
     if (enabled || enh_enabled) {
-        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
-        if (evbuf) {
-            /* Put common elements in event */
-            evbuf[0] = BLE_HCI_EVCODE_LE_META;
-            if (enh_enabled) {
-                evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
-                evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
-            } else {
-                evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
-                evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
-            }
-            evbuf[3] = status;
+        /* Put common elements in event */
+        evbuf[0] = BLE_HCI_EVCODE_LE_META;
+        if (enh_enabled) {
+            evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
+        } else {
+            evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+        }
+        evbuf[3] = status;
 
-            if (connsm) {
-                htole16(evbuf + 4, connsm->conn_handle);
-                evbuf[6] = connsm->conn_role - 1;
-                peer_addr_type = connsm->peer_addr_type;
+        if (connsm) {
+            htole16(evbuf + 4, connsm->conn_handle);
+            evbuf[6] = connsm->conn_role - 1;
+            peer_addr_type = connsm->peer_addr_type;
 
-                evdata = evbuf + 14;
-                if (enh_enabled) {
-                    memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
-                    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-                        if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-                            rpa = ble_ll_scan_get_local_rpa();
-                        } else {
-                            rpa = NULL;
-                        }
+            evdata = evbuf + 14;
+            if (enh_enabled) {
+                memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
+                if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                    if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+                        rpa = ble_ll_scan_get_local_rpa();
                     } else {
-                        rpa = ble_ll_adv_get_local_rpa();
-                    }
-                    if (rpa) {
-                        memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
+                        rpa = NULL;
                     }
-
-                    if (connsm->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
-                        if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-                            rpa = ble_ll_scan_get_peer_rpa();
-                        } else {
-                            rpa = ble_ll_adv_get_peer_rpa();
-                        }
-                        memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
-                    }
-                    evdata += 12;
                 } else {
-                    if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
-                        peer_addr_type -= 2;
+                    rpa = ble_ll_adv_get_local_rpa();
+                }
+                if (rpa) {
+                    memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
+                }
+
+                if (connsm->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                        rpa = ble_ll_scan_get_peer_rpa();
+                    } else {
+                        rpa = ble_ll_adv_get_peer_rpa();
                     }
+                    memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
                 }
+                evdata += 12;
+            } else {
+                if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                    peer_addr_type -= 2;
+                }
+            }
 
-                evbuf[7] = peer_addr_type;
-                memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
+            evbuf[7] = peer_addr_type;
+            memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
 
-                htole16(evdata, connsm->conn_itvl);
-                htole16(evdata + 2, connsm->slave_latency);
-                htole16(evdata + 4, connsm->supervision_tmo);
-                evdata[6] = connsm->master_sca;
-            }
-            ble_ll_hci_event_send(evbuf);
+            htole16(evdata, connsm->conn_itvl);
+            htole16(evdata + 2, connsm->slave_latency);
+            htole16(evdata + 4, connsm->supervision_tmo);
+            evdata[6] = connsm->master_sca;
         }
+        ble_ll_hci_event_send(evbuf);
     }
 }
 
@@ -462,6 +485,11 @@ ble_ll_conn_create(uint8_t *cmdbuf)
         return BLE_ERR_CONN_LIMIT;
     }
 
+    /* Make sure we can allocate an event to send the connection complete */
+    if (ble_ll_init_alloc_conn_comp_ev()) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
     /* Initialize state machine in master role and start state machine */
     ble_ll_conn_master_init(connsm, hcc);
     ble_ll_conn_sm_new(connsm);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d56270d9/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 b8c4fa1..2ccd38e 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -133,7 +133,8 @@ int ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf);
 int ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int negative_reply);
 int ble_ll_conn_create_cancel(void);
 void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
-void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status);
+void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
+                                 uint8_t *evbuf);
 void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
 int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
                                     uint16_t latency, uint16_t spvn_tmo);