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 2018/12/05 12:24:18 UTC

[mynewt-nimble] 13/13: nimble/ll: Improve handling truncated advertising events

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

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

commit 859cb352c6f26d4a9c558f2cf63e36864bd8838e
Author: Ɓukasz Rymanowski <lu...@codecoup.pl>
AuthorDate: Fri Nov 9 10:26:39 2018 +0100

    nimble/ll: Improve handling truncated advertising events
    
    This patch make sure that each truncated advertising event is corretly
    sent to host
---
 nimble/controller/include/controller/ble_ll_scan.h |   2 +
 nimble/controller/src/ble_ll_scan.c                | 173 ++++++++++++++++-----
 nimble/controller/src/ble_ll_sched.c               |   5 +-
 3 files changed, 136 insertions(+), 44 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index 5aa34f0..65bff1c 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -94,6 +94,7 @@ struct ble_ll_scan_params
 #define BLE_LL_AUX_HAS_ADDRA            0x08
 #define BLE_LL_AUX_IGNORE_BIT           0x10
 #define BLE_LL_AUX_HAS_DIR_ADDRA        0x20
+#define BLE_LL_AUX_TRUNCATED_SENT       0x40
 
 #define BLE_LL_SET_AUX_FLAG(aux_data, flag) ((aux_data)->flags |= flag)
 #define BLE_LL_CHECK_AUX_FLAG(aux_data, flag) (!!((aux_data)->flags & flag))
@@ -253,6 +254,7 @@ int ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
 
 /* Called to clean up current aux data */
 void ble_ll_scan_clean_cur_aux_data(void);
+void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
 
 #ifdef __cplusplus
 }
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index e3996c4..1fd0bf5 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -410,6 +410,112 @@ next_dup_adv:
     return NULL;
 }
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+static struct ble_ll_ext_adv_report *
+ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from)
+{
+    struct ble_ll_ext_adv_report *evt;
+
+    evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc(
+                                                    BLE_HCI_TRANS_BUF_EVT_LO);
+    if (!evt) {
+        return NULL;
+    }
+
+    if (copy_from) {
+        memcpy(evt, copy_from, sizeof(*evt));
+    } else {
+        memset(evt, 0, sizeof(*evt));
+
+        evt->event_meta = BLE_HCI_EVCODE_LE_META;
+        evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT;
+        /* We support only one report per event now */
+        evt->num_reports = 1;
+        /* Init TX Power with "Not available" which is 127 */
+        evt->tx_power = 127;
+        /* Init RSSI with "Not available" which is 127 */
+        evt->rssi = 127;
+        /* Init SID with "Not available" which is 0xFF */
+        evt->sid = 0xFF;
+        /* Init address type with "anonymous" which is 0xFF */
+        evt->addr_type = 0xFF;
+    }
+
+    return evt;
+}
+
+static void
+ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data *aux_data)
+{
+    struct ble_ll_ext_adv_report *evt;
+
+    if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+        goto done;
+    }
+
+    BLE_LL_ASSERT(aux_data);
+
+    if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) {
+        /* if not chained, there is nothing to do here */
+        goto done;
+    }
+
+    if (aux_data->evt) {
+        evt = aux_data->evt;
+        aux_data->evt = NULL;
+    } else {
+        evt = ble_ll_scan_init_ext_adv_report(NULL);
+        if (!evt) {
+            goto done;
+        }
+    }
+
+    evt->event_len = sizeof(*evt);
+    evt->evt_type = aux_data->evt_type;
+    evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
+    BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
+
+    if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_ADDRA)) {
+        memcpy(evt->addr, aux_data->addr, 6);
+        evt->addr_type = aux_data->addr_type;
+    }
+
+    if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_DIR_ADDRA)) {
+        memcpy(evt->dir_addr, aux_data->dir_addr, 6);
+        evt->dir_addr_type = aux_data->dir_addr_type;
+    }
+
+    evt->sid = (aux_data->adi >> 12);
+    ble_ll_hci_event_send((uint8_t *)evt);
+
+done:
+    ble_ll_scan_aux_data_unref(aux_data);
+}
+#endif
+
+void
+ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data)
+{
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    /*
+     * Check if tuncated has been sent
+     *
+     * Normally reference counter here should be 2. 1 for outstanding
+     * complete event and one for ongoing scanning. If there is only 1
+     * that means, advertising event is already completed
+     * (truncated was sent to the host) and we just need to drop last reference.
+     * Otherwise we should try to send truncated event to the host.
+     */
+    if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT)) {
+        ble_ll_scan_send_truncated_if_chained(aux_data);
+    }
+
+    if (ble_ll_scan_aux_data_unref(aux_data) > 0) {
+        BLE_LL_ASSERT(0);
+    }
+
+#endif
+}
 /**
  * Do scan machine clean up on PHY disabled
  *
@@ -422,7 +528,7 @@ ble_ll_scan_clean_cur_aux_data(void)
 
     /* If scanner was reading aux ptr, we need to clean it up */
     if (scansm && scansm->cur_aux_data) {
-        ble_ll_scan_aux_data_unref(scansm->cur_aux_data);
+        ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
         scansm->cur_aux_data = NULL;
     }
 #endif
@@ -577,40 +683,6 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd)
 }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-
-static struct ble_ll_ext_adv_report *
-ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from)
-{
-    struct ble_ll_ext_adv_report *evt;
-
-    evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc(
-                                                    BLE_HCI_TRANS_BUF_EVT_LO);
-    if (!evt) {
-        return NULL;
-    }
-
-    if (copy_from) {
-        memcpy(evt, copy_from, sizeof(*evt));
-    } else {
-        memset(evt, 0, sizeof(*evt));
-
-        evt->event_meta = BLE_HCI_EVCODE_LE_META;
-        evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT;
-        /* We support only one report per event now */
-        evt->num_reports = 1;
-        /* Init TX Power with "Not available" which is 127 */
-        evt->tx_power = 127;
-        /* Init RSSI with "Not available" which is 127 */
-        evt->rssi = 127;
-        /* Init SID with "Not available" which is 0xFF */
-        evt->sid = 0xFF;
-        /* Init address type with "anonymous" which is 0xFF */
-        evt->addr_type = 0xFF;
-    }
-
-    return evt;
-}
-
 static int
 ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
                                       uint8_t addr_type, uint8_t *addr,
@@ -2385,8 +2457,7 @@ ble_ll_scan_wfr_timer_exp(void)
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (scansm->cur_aux_data) {
-        /*TODO handle chain incomplete, data truncated */
-        ble_ll_scan_aux_data_unref(scansm->cur_aux_data);
+        ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
         scansm->cur_aux_data = NULL;
         STATS_INC(ble_ll_stats, aux_missed_adv);
         ble_ll_scan_chk_resume();
@@ -2489,6 +2560,7 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE);
             } else {
                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
+                BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
                 rc = -1;
             }
         } else if (aux_data ) {
@@ -2559,14 +2631,23 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
     int rc;
+    uint8_t evt_possibly_truncated = 0;
 #endif
 
     /* Set scan response check flag */
     scan_rsp_chk = BLE_MBUF_HDR_SCAN_RSP_RCV(hdr);
 
     /* We dont care about scan requests or connect requests */
-    if (!BLE_MBUF_HDR_CRC_OK(hdr) || (ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) ||
-        (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+    if (!BLE_MBUF_HDR_CRC_OK(hdr)) {
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
+            evt_possibly_truncated = 1;
+        }
+#endif
+        goto scan_continue;
+    }
+
+    if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) || (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
         goto scan_continue;
     }
 
@@ -2574,7 +2655,10 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
                                     &adv_addr, &txadd,
                                     &init_addr, &init_addr_type,
                                     &ext_adv_mode)) {
-       goto scan_continue;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        evt_possibly_truncated = 1;
+#endif
+        goto scan_continue;
     }
 
     ident_addr = adv_addr;
@@ -2667,6 +2751,7 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd
         }
 
         if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
+            evt_possibly_truncated = 1;
             goto scan_continue;
         }
 
@@ -2754,8 +2839,12 @@ scan_continue:
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (aux_data) {
-        /* This is ref for handover to LL */
-        ble_ll_scan_aux_data_unref(aux_data);
+        if (evt_possibly_truncated) {
+            ble_ll_scan_end_adv_evt(aux_data);
+        } else {
+            /* This is ref for handover to LL */
+            ble_ll_scan_aux_data_unref(aux_data);
+        }
     }
 #endif
     /*
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index 9a22ede..ffdbf8e 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -250,8 +250,9 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
                 break;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
             case BLE_LL_SCHED_TYPE_AUX_SCAN:
-                ble_ll_scan_aux_data_unref((struct ble_ll_aux_data *)
+                ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)
                                           entry->cb_arg);
+
                 break;
 #endif
             default:
@@ -1361,7 +1362,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
             return 1;
         }
 
-        ble_ll_scan_aux_data_unref((struct ble_ll_aux_data *)sch->cb_arg);
+        ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)sch->cb_arg);
         TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link);
         sch->enqueued = 0;
         sch = TAILQ_FIRST(&g_ble_ll_sched_q);