You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/04/06 02:37:27 UTC

[6/6] incubator-mynewt-core git commit: ble host: cancel sm proc when connection broken.

ble host: cancel sm proc when connection broken.


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

Branch: refs/heads/develop
Commit: 655d02396b4c5302df067e7f3eb43ead1a72995a
Parents: 6e099aa
Author: Christopher Collins <cc...@apache.org>
Authored: Tue Apr 5 17:34:23 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Apr 5 17:36:32 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_l2cap.h |  1 +
 net/nimble/host/src/ble_gap.c            |  1 +
 net/nimble/host/src/ble_l2cap_sm.c       | 83 ++++++++++++++++++++++++++-
 3 files changed, 83 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/655d0239/net/nimble/host/include/host/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_l2cap.h b/net/nimble/host/include/host/ble_l2cap.h
index 76c838b..01e25a6 100644
--- a/net/nimble/host/include/host/ble_l2cap.h
+++ b/net/nimble/host/include/host/ble_l2cap.h
@@ -100,5 +100,6 @@ int ble_l2cap_sig_update(uint16_t conn_handle,
 
 
 int ble_l2cap_sm_set_tk(uint16_t conn_handle, uint8_t *tk);
+void ble_l2cap_sm_connection_broken(uint16_t conn_handle);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/655d0239/net/nimble/host/src/ble_gap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index 3cfe4b0..4342103 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -772,6 +772,7 @@ ble_gap_conn_broken(uint16_t conn_handle)
     ble_gap_unlock();
 
     ble_gattc_connection_broken(conn_handle);
+    ble_l2cap_sm_connection_broken(conn_handle);
 
     STATS_INC(ble_gap_stats, disconnect);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/655d0239/net/nimble/host/src/ble_l2cap_sm.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sm.c b/net/nimble/host/src/ble_l2cap_sm.c
index 6d89466..15d654e 100644
--- a/net/nimble/host/src/ble_l2cap_sm.c
+++ b/net/nimble/host/src/ble_l2cap_sm.c
@@ -283,6 +283,29 @@ ble_l2cap_sm_dispatch_get(uint8_t op)
     return ble_l2cap_sm_dispatch[op];
 }
 
+/* Indicates the handle of the specified proc's unserviced HCI reservation, if
+ * any.  If there is no such handle associated with the proc,
+ * BLE_HCI_SCHED_HANDLE_NONE is returned.
+ *
+ * Lock restrictions: None.
+ *
+ * @param proc                  The proc object to query.
+ *
+ * @return                      The HCI handle, or BLE_HCI_SCHED_HANDLE_NONE.
+ */
+static uint8_t
+ble_l2cap_sm_proc_outstanding_hci_handle(struct ble_l2cap_sm_proc *proc)
+{
+    switch (proc->fsm_proc.op) {
+    case BLE_L2CAP_SM_PROC_OP_LTK:
+    case BLE_L2CAP_SM_PROC_OP_START_ENCRYPT_TXED:
+        return proc->hci.handle;
+
+    default:
+        return BLE_HCI_SCHED_HANDLE_NONE;
+    }
+}
+
 /**
  * Allocates a proc entry.
  *
@@ -311,9 +334,22 @@ ble_l2cap_sm_proc_alloc(void)
 static void
 ble_l2cap_sm_proc_free(struct ble_fsm_proc *proc)
 {
+    struct ble_l2cap_sm_proc *sm_proc;
+    uint8_t hci_handle;
     int rc;
 
     if (proc != NULL) {
+        sm_proc = (struct ble_l2cap_sm_proc *)proc;
+
+        /* If this proc has an unserviced HCI reservation, cancel it before
+         * freeing the proc.
+         */
+        hci_handle = ble_l2cap_sm_proc_outstanding_hci_handle(sm_proc);
+        if (hci_handle != BLE_HCI_SCHED_HANDLE_NONE) {
+            rc = ble_hci_sched_cancel(hci_handle);
+            BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+        }
+
         rc = os_memblock_put(&ble_l2cap_sm_proc_pool, proc);
         BLE_HS_DBG_ASSERT_EVAL(rc == 0);
     }
@@ -687,6 +723,7 @@ ble_l2cap_sm_random_kick(struct ble_l2cap_sm_proc *proc)
     }
 
     if (!(proc->flags & BLE_L2CAP_SM_PROC_F_INITIATOR)) {
+        proc->hci.handle = BLE_HCI_SCHED_HANDLE_NONE;
         proc->fsm_proc.op = BLE_L2CAP_SM_PROC_OP_LTK;
     }
 
@@ -781,6 +818,11 @@ ble_l2cap_sm_lt_key_req_reply_tx(void *arg)
 
     BLE_HS_DBG_ASSERT(proc->fsm_proc.op == BLE_L2CAP_SM_PROC_OP_LTK_TXED);
 
+    /* Indicate that the HCI reservation has been serviced.  If there is a
+     * failure, we shouldn't try to cancel the reservation.
+     */
+    proc->hci.handle = BLE_HCI_SCHED_HANDLE_NONE;
+
     cmd.conn_handle = proc->fsm_proc.conn_handle;
     memcpy(cmd.long_term_key, proc->hci.key, 16);
 
@@ -837,7 +879,13 @@ ble_l2cap_sm_start_encrypt_tx(void *arg)
 
     proc = arg;
 
-    BLE_HS_DBG_ASSERT(proc->fsm_proc.op == BLE_L2CAP_SM_PROC_OP_START_ENCRYPT_TXED);
+    BLE_HS_DBG_ASSERT(proc->fsm_proc.op ==
+                      BLE_L2CAP_SM_PROC_OP_START_ENCRYPT_TXED);
+
+    /* Indicate that the HCI reservation has been serviced.  If there is a
+     * failure, we shouldn't try to cancel the reservation.
+     */
+    proc->hci.handle = BLE_HCI_SCHED_HANDLE_NONE;
 
     cmd.connection_handle = proc->fsm_proc.conn_handle;
     cmd.encrypted_diversifier = ble_l2cap_sm_gen_ediv();
@@ -862,6 +910,7 @@ ble_l2cap_sm_start_encrypt_kick(struct ble_l2cap_sm_proc *proc)
         return BLE_HS_EDONE;
     }
 
+    proc->hci.handle = BLE_HCI_SCHED_HANDLE_NONE;
     proc->fsm_proc.op = BLE_L2CAP_SM_PROC_OP_START_ENCRYPT_TXED;
 
     return 0;
@@ -1239,7 +1288,7 @@ ble_l2cap_sm_heartbeat(void)
                               ble_l2cap_sm_proc_extract_expired_cb, NULL);
 
     /* Notify application of each failure and free the corresponding procedure
-     * objects.
+     * object.
      */
     while ((fsm_proc = STAILQ_FIRST(&exp_list)) != NULL) {
         proc = (struct ble_l2cap_sm_proc *)fsm_proc;
@@ -1327,6 +1376,36 @@ ble_l2cap_sm_set_tk(uint16_t conn_handle, uint8_t *tk)
     return 0;
 }
 
+void
+ble_l2cap_sm_connection_broken(uint16_t conn_handle)
+{
+    struct ble_fsm_proc_list list;
+    struct ble_l2cap_sm_proc *proc;
+    struct ble_fsm_proc *fsm_proc;
+
+    /* Extract all procs associated with the broken connection and insert them
+     * into the temporary list.
+     */
+    ble_fsm_proc_extract_list(
+        &ble_l2cap_sm_fsm, &list, ble_l2cap_sm_proc_extract_cb,
+        &(struct ble_l2cap_sm_extract_arg) {
+            .conn_handle = conn_handle,
+            .op = BLE_L2CAP_SM_PROC_OP_NONE,
+            .initiator = -1,
+        }
+    );
+
+    /* Free each affected procedure object.  There is no need to notify the
+     * application, as it has already been notified of the connection failure.
+     */
+    while ((fsm_proc = STAILQ_FIRST(&list)) != NULL) {
+        proc = (struct ble_l2cap_sm_proc *)fsm_proc;
+
+        STAILQ_REMOVE_HEAD(&list, next);
+        ble_l2cap_sm_proc_free(&proc->fsm_proc);
+    }
+}
+
 /**
  * Lock restrictions:
  *     o Caller unlocks ble_hs_conn.