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/05/11 19:37:08 UTC

incubator-mynewt-core git commit: BLE Host - Always set timer for GATT client procs.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop c70353c19 -> 7eb9d5ca2


BLE Host - Always set timer for GATT client procs.


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

Branch: refs/heads/develop
Commit: 7eb9d5ca2ecdb348f355628e09847e6997d7f0f3
Parents: c70353c
Author: Christopher Collins <cc...@apache.org>
Authored: Wed May 11 12:36:42 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed May 11 12:36:42 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/src/ble_att_svr.c             |   4 +-
 net/nimble/host/src/ble_gattc.c               | 257 +++++++----
 net/nimble/host/src/test/ble_gatt_conn_test.c | 508 ++++++++++++++++++---
 3 files changed, 610 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7eb9d5ca/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 6aff564..76bf0e8 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -328,7 +328,9 @@ ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
 
     entry = ble_att_svr_find_by_handle(attr_handle);
     if (entry == NULL) {
-        *out_att_err = BLE_ATT_ERR_INVALID_HANDLE;
+        if (out_att_err != NULL) {
+            *out_att_err = BLE_ATT_ERR_INVALID_HANDLE;
+        }
         return BLE_HS_ENOENT;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7eb9d5ca/net/nimble/host/src/ble_gattc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index bee3c39..b957a43 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -695,9 +695,10 @@ ble_gattc_extract_by_conn(uint16_t conn_handle,
                 STAILQ_REMOVE_AFTER(&ble_gattc_procs, prev, next);
             }
             STAILQ_INSERT_TAIL(dst_list, proc, next);
+        } else {
+            prev = proc;
         }
 
-        prev = proc;
         proc = next;
     }
 
@@ -913,7 +914,8 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_MTU;
@@ -924,30 +926,27 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
     ble_gattc_log_proc_init("exchange mtu\n");
 
     ble_hs_lock();
-
     rc = ble_att_conn_chan_find(proc->conn_handle, &conn, &chan);
     if (rc == 0) {
         req.bamc_mtu = chan->blc_my_mtu;
     }
-
     ble_hs_unlock();
 
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
     rc = ble_att_clt_tx_mtu(proc->conn_handle, &req);
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, mtu_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, mtu_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -1130,8 +1129,8 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, disc_all_svcs_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_DISC_ALL_SVCS;
@@ -1143,8 +1142,16 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
     ble_gattc_log_proc_init("discover all services\n");
 
     rc = ble_gattc_disc_all_svcs_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
+
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, disc_all_svcs_fail);
+    }
 
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -1307,8 +1314,8 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, void *service_uuid128,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, disc_svc_uuid_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_DISC_SVC_UUID;
@@ -1321,8 +1328,16 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, void *service_uuid128,
     ble_gattc_log_disc_svc_uuid(proc);
 
     rc = ble_gattc_disc_svc_uuid_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, disc_svc_uuid_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -1595,8 +1610,8 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, find_inc_svcs_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_FIND_INC_SVCS;
@@ -1609,9 +1624,17 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
     ble_gattc_log_find_inc_svcs(proc);
 
     rc = ble_gattc_find_inc_svcs_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, find_inc_svcs_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -1803,8 +1826,8 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, disc_all_chrs_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_DISC_ALL_CHRS;
@@ -1817,9 +1840,17 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
     ble_gattc_log_disc_all_chrs(proc);
 
     rc = ble_gattc_disc_all_chrs_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, disc_all_chrs_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -2021,8 +2052,8 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, disc_chrs_uuid_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_DISC_CHR_UUID;
@@ -2036,9 +2067,17 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
     ble_gattc_log_disc_chr_uuid(proc);
 
     rc = ble_gattc_disc_chr_uuid_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, disc_chrs_uuid_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -2202,8 +2241,8 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_def_handle,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, disc_all_dscs_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_DISC_ALL_DSCS;
@@ -2217,9 +2256,17 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_def_handle,
     ble_gattc_log_disc_all_dscs(proc);
 
     rc = ble_gattc_disc_all_dscs_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, disc_all_dscs_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -2315,7 +2362,7 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
         rc = BLE_HS_ENOMEM;
-        goto err;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_READ;
@@ -2329,16 +2376,15 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
     req.barq_handle = attr_handle;
     rc = ble_att_clt_tx_read(proc->conn_handle, &req);
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, read_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, read_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -2457,7 +2503,7 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
         rc = BLE_HS_ENOMEM;
-        goto err;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_READ_UUID;
@@ -2471,16 +2517,15 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
     req.batq_end_handle = end_handle;
     rc = ble_att_clt_tx_read_type(conn_handle, &req, uuid128);
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, read_uuid_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, read_uuid_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -2628,8 +2673,8 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, read_long_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_READ_LONG;
@@ -2642,9 +2687,17 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle,
     ble_gattc_log_read_long(proc);
 
     rc = ble_gattc_read_long_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, read_long_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -2663,6 +2716,7 @@ ble_gattc_read_mult_cb(struct ble_gattc_proc *proc, int status,
                        uint16_t att_handle, uint8_t *attr_data,
                        uint16_t attr_data_len)
 {
+    struct ble_gatt_attr *attrp;
     struct ble_gatt_attr attr;
     int rc;
 
@@ -2675,12 +2729,18 @@ ble_gattc_read_mult_cb(struct ble_gattc_proc *proc, int status,
     if (proc->read_mult.cb == NULL) {
         rc = 0;
     } else {
-        attr.handle = 0;
-        attr.offset = 0;
-        attr.value_len = attr_data_len;
-        attr.value = attr_data;
+        if (status != 0) {
+            attrp = NULL;
+        } else {
+            attrp = &attr;
+            attr.handle = 0;
+            attr.offset = 0;
+            attr.value_len = attr_data_len;
+            attr.value = attr_data;
+        }
+
         rc = proc->read_mult.cb(proc->conn_handle,
-                                ble_gattc_error(status, att_handle), &attr,
+                                ble_gattc_error(status, att_handle), attrp,
                                 proc->read_mult.cb_arg);
     }
 
@@ -2726,7 +2786,7 @@ ble_gattc_read_mult(uint16_t conn_handle, uint16_t *handles,
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
         rc = BLE_HS_ENOMEM;
-        goto err;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_READ_MULT;
@@ -2738,16 +2798,15 @@ ble_gattc_read_mult(uint16_t conn_handle, uint16_t *handles,
 
     rc = ble_att_clt_tx_read_mult(conn_handle, handles, num_handles);
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, read_mult_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, read_mult_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -2870,7 +2929,7 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
         rc = BLE_HS_ENOMEM;
-        goto err;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_WRITE;
@@ -2884,16 +2943,15 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
     req.bawq_handle = attr_handle;
     rc = ble_att_clt_tx_write_req(conn_handle, &req, value, value_len);
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, write_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, write_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 
@@ -3087,8 +3145,8 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, void *value,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, write_long_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_WRITE_LONG;
@@ -3103,9 +3161,17 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, void *value,
     ble_gattc_log_write_long(proc);
 
     rc = ble_gattc_write_long_go(proc, 0);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, write_long_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -3287,8 +3353,8 @@ ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs,
 
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
-        STATS_INC(ble_gattc_stats, write_reliable_fail);
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_WRITE_RELIABLE;
@@ -3302,9 +3368,17 @@ ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs,
     ble_gattc_log_write_reliable(proc);
 
     rc = ble_gattc_write_reliable_go(proc, 1);
-    ble_gattc_process_status(proc, rc);
+    if (rc != 0) {
+        goto done;
+    }
 
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, write_reliable_fail);
+    }
+
+    ble_gattc_process_status(proc, rc);
+    return rc;
 }
 
 /*****************************************************************************
@@ -3473,7 +3547,7 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
     proc = ble_gattc_proc_alloc();
     if (proc == NULL) {
         rc = BLE_HS_ENOMEM;
-        goto err;
+        goto done;
     }
 
     proc->op = BLE_GATT_OP_INDICATE;
@@ -3489,7 +3563,7 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
     if (rc != 0) {
         /* Fatal error; application disallowed attribute read. */
         rc = BLE_HS_EAPP;
-        goto err;
+        goto done;
     }
 
     req.baiq_handle = chr_val_handle;
@@ -3497,16 +3571,15 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
                                  ctxt.attr_data, ctxt.data_len);
 
     if (rc != 0) {
-        goto err;
+        goto done;
     }
 
-    ble_gattc_proc_insert(proc);
-
-    return 0;
+done:
+    if (rc != 0) {
+        STATS_INC(ble_gattc_stats, indicate_fail);
+    }
 
-err:
-    STATS_INC(ble_gattc_stats, indicate_fail);
-    ble_gattc_proc_free((void *)proc);
+    ble_gattc_process_status(proc, rc);
     return rc;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7eb9d5ca/net/nimble/host/src/test/ble_gatt_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_conn_test.c b/net/nimble/host/src/test/ble_gatt_conn_test.c
index 994f719..4cff95b 100644
--- a/net/nimble/host/src/test/ble_gatt_conn_test.c
+++ b/net/nimble/host/src/test/ble_gatt_conn_test.c
@@ -24,49 +24,254 @@
 #include "host/ble_hs_test.h"
 #include "ble_hs_test_util.h"
 
-#define BLE_GATT_BREAK_TEST_DISC_SERVICE_HANDLE     1
-#define BLE_GATT_BREAK_TEST_DISC_CHR_HANDLE         2
-#define BLE_GATT_BREAK_TEST_READ_HANDLE             3
-#define BLE_GATT_BREAK_TEST_WRITE_HANDLE            4
 #define BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE        0x9383
 #define BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE       0x1234
 
 static uint8_t ble_gatt_conn_test_write_value[] = { 1, 3, 64, 21, 6 };
 
+struct ble_gatt_conn_test_cb_arg {
+    uint16_t exp_conn_handle;
+    int called;
+};
+
+static int
+ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
+                           uint8_t *uuid128, uint8_t op,
+                           struct ble_att_svr_access_ctxt *ctxt,
+                           void *arg)
+{
+    static uint8_t data = 1;
+
+    switch (op) {
+    case BLE_ATT_ACCESS_OP_READ:
+        ctxt->attr_data = &data;
+        ctxt->data_len = 1;
+        return 0;
+
+    default:
+        return -1;
+    }
+}
+
+static int
+ble_gatt_conn_test_mtu_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+                          uint16_t mtu, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(mtu == 0);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
 static int
-ble_gatt_conn_test_disc_service_cb(uint16_t conn_handle,
+ble_gatt_conn_test_disc_all_svcs_cb(uint16_t conn_handle,
                                    struct ble_gatt_error *error,
                                    struct ble_gatt_service *service,
                                    void *arg)
 {
-    int *called;
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
 
-    called = arg;
-    *called = 1;
+    cb_arg = arg;
 
-    TEST_ASSERT(conn_handle == BLE_GATT_BREAK_TEST_DISC_SERVICE_HANDLE);
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
     TEST_ASSERT_FATAL(error != NULL);
     TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
     TEST_ASSERT(service == NULL);
 
+    cb_arg->called++;
+
     return 0;
 }
 
 static int
-ble_gatt_conn_test_disc_chr_cb(uint16_t conn_handle,
-                               struct ble_gatt_error *error,
-                               struct ble_gatt_chr *chr, void *arg)
+ble_gatt_conn_test_disc_svc_uuid_cb(uint16_t conn_handle,
+                                    struct ble_gatt_error *error,
+                                    struct ble_gatt_service *service,
+                                    void *arg)
 {
-    int *called;
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
 
-    called = arg;
-    *called = 1;
+    cb_arg = arg;
 
-    TEST_ASSERT(conn_handle == BLE_GATT_BREAK_TEST_DISC_CHR_HANDLE);
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(service == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_find_inc_svcs_cb(uint16_t conn_handle,
+                                    struct ble_gatt_error *error,
+                                    struct ble_gatt_service *service,
+                                    void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(service == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_all_chrs_cb(uint16_t conn_handle,
+                                    struct ble_gatt_error *error,
+                                    struct ble_gatt_chr *chr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
     TEST_ASSERT_FATAL(error != NULL);
     TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
     TEST_ASSERT(chr == NULL);
 
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_chr_uuid_cb(uint16_t conn_handle,
+                                    struct ble_gatt_error *error,
+                                    struct ble_gatt_chr *chr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(chr == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_all_dscs_cb(uint16_t conn_handle,
+                                    struct ble_gatt_error *error,
+                                    uint16_t chr_def_handle,
+                                    struct ble_gatt_dsc *dsc,
+                                    void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(dsc == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_read_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+                           struct ble_gatt_attr *attr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attr == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
+                                struct ble_gatt_error *error,
+                                struct ble_gatt_attr *attr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attr == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
+                                struct ble_gatt_error *error,
+                                struct ble_gatt_attr *attr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attr == NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+static int
+ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
+                                struct ble_gatt_error *error,
+                                struct ble_gatt_attr *attr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attr == NULL);
+
+    cb_arg->called++;
+
     return 0;
 }
 
@@ -74,94 +279,266 @@ static int
 ble_gatt_conn_test_write_cb(uint16_t conn_handle, struct ble_gatt_error *error,
                             struct ble_gatt_attr *attr, void *arg)
 {
-    int *called;
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
 
-    called = arg;
-    *called = 1;
+    cb_arg = arg;
 
-    TEST_ASSERT(conn_handle == BLE_GATT_BREAK_TEST_WRITE_HANDLE);
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
     TEST_ASSERT_FATAL(error != NULL);
     TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
     TEST_ASSERT(attr != NULL);
     TEST_ASSERT(attr->handle == BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE);
 
+    cb_arg->called++;
+
     return 0;
 }
 
 static int
-ble_gatt_conn_test_read_cb(uint16_t conn_handle, struct ble_gatt_error *error,
-                           struct ble_gatt_attr *attr, void *arg)
+ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
+                                 struct ble_gatt_error *error,
+                                 struct ble_gatt_attr *attr, void *arg)
 {
-    int *called;
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
 
-    called = arg;
-    *called = 1;
+    cb_arg = arg;
 
-    TEST_ASSERT(conn_handle == BLE_GATT_BREAK_TEST_READ_HANDLE);
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
     TEST_ASSERT_FATAL(error != NULL);
     TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
-    TEST_ASSERT(attr == NULL);
+    TEST_ASSERT(attr != NULL);
+    TEST_ASSERT(attr->handle == BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_write_rel_cb(uint16_t conn_handle,
+                                struct ble_gatt_error *error,
+                                struct ble_gatt_attr *attrs, uint8_t num_attrs,
+                                void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attrs != NULL);
+
+    cb_arg->called++;
+
+    return 0;
+}
+
+static int
+ble_gatt_conn_test_indicate_cb(uint16_t conn_handle,
+                               struct ble_gatt_error *error,
+                               struct ble_gatt_attr *attr, void *arg)
+{
+    struct ble_gatt_conn_test_cb_arg *cb_arg;
+
+    cb_arg = arg;
+
+    TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
+    TEST_ASSERT(!cb_arg->called);
+    TEST_ASSERT_FATAL(error != NULL);
+    TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(attr != NULL);
+
+    cb_arg->called++;
 
     return 0;
 }
 
 TEST_CASE(ble_gatt_conn_test_disconnect)
 {
-    int disc_s_called;
-    int disc_c_called;
-    int read_called;
-    int write_called;
+    struct ble_gatt_conn_test_cb_arg mtu_arg            = { 0 };
+    struct ble_gatt_conn_test_cb_arg disc_all_svcs_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg disc_svc_uuid_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg find_inc_svcs_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg disc_all_chrs_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg disc_chr_uuid_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg disc_all_dscs_arg  = { 0 };
+    struct ble_gatt_conn_test_cb_arg read_arg           = { 0 };
+    struct ble_gatt_conn_test_cb_arg read_uuid_arg      = { 0 };
+    struct ble_gatt_conn_test_cb_arg read_long_arg      = { 0 };
+    struct ble_gatt_conn_test_cb_arg read_mult_arg      = { 0 };
+    struct ble_gatt_conn_test_cb_arg write_arg          = { 0 };
+    struct ble_gatt_conn_test_cb_arg write_long_arg     = { 0 };
+    struct ble_gatt_conn_test_cb_arg write_rel_arg      = { 0 };
+    struct ble_gatt_conn_test_cb_arg indicate_arg       = { 0 };
+    uint16_t attr_handle;
     int rc;
 
     ble_hs_test_util_init();
 
+    /*** Register an attribute to allow indicatations to be sent. */
+    rc = ble_att_svr_register(BLE_UUID16(0x1212), HA_FLAG_PERM_READ,
+                              &attr_handle,
+                              ble_gatt_conn_test_attr_cb, NULL);
+    TEST_ASSERT(rc == 0);
+
     /* Create three connections. */
-    ble_hs_test_util_create_conn(BLE_GATT_BREAK_TEST_DISC_SERVICE_HANDLE,
-                                 ((uint8_t[]){1,2,3,4,5,6,7,8}), NULL, NULL);
-    ble_hs_test_util_create_conn(BLE_GATT_BREAK_TEST_DISC_CHR_HANDLE,
-                                 ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL);
-    ble_hs_test_util_create_conn(BLE_GATT_BREAK_TEST_READ_HANDLE,
-                                 ((uint8_t[]){3,4,5,6,7,8,9,10}), NULL, NULL);
-    ble_hs_test_util_create_conn(BLE_GATT_BREAK_TEST_WRITE_HANDLE,
-                                 ((uint8_t[]){4,5,6,7,8,9,10,11}), NULL, NULL);
-
-    /* Schedule some GATT procedures. */
-    rc = ble_gattc_disc_all_svcs(BLE_GATT_BREAK_TEST_DISC_SERVICE_HANDLE,
-                                 ble_gatt_conn_test_disc_service_cb,
-                                 &disc_s_called);
+    ble_hs_test_util_create_conn(1, ((uint8_t[]){1,2,3,4,5,6,7,8}),
+                                 NULL, NULL);
+    ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+                                 NULL, NULL);
+    ble_hs_test_util_create_conn(3, ((uint8_t[]){3,4,5,6,7,8,9,10}),
+                                 NULL, NULL);
+
+    /*** Schedule some GATT procedures. */
+    /* Connection 1. */
+    mtu_arg.exp_conn_handle = 1;
+    ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, &mtu_arg);
+
+    disc_all_svcs_arg.exp_conn_handle = 1;
+    rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb,
+                                 &disc_all_svcs_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    disc_svc_uuid_arg.exp_conn_handle = 1;
+    rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16(0x1111),
+                                    ble_gatt_conn_test_disc_svc_uuid_cb,
+                                    &disc_svc_uuid_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    find_inc_svcs_arg.exp_conn_handle = 1;
+    rc = ble_gattc_find_inc_svcs(1, 1, 0xffff,
+                                 ble_gatt_conn_test_find_inc_svcs_cb,
+                                 &find_inc_svcs_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    disc_all_chrs_arg.exp_conn_handle = 1;
+    rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
+                                 ble_gatt_conn_test_disc_all_chrs_cb,
+                                 &disc_all_chrs_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    /* Connection 2. */
+    disc_all_dscs_arg.exp_conn_handle = 2;
+    rc = ble_gattc_disc_all_dscs(2, 1, 0xffff,
+                                 ble_gatt_conn_test_disc_all_dscs_cb,
+                                 &disc_all_dscs_arg);
+
+    disc_chr_uuid_arg.exp_conn_handle = 2;
+    rc = ble_gattc_disc_chrs_by_uuid(2, 1, 0xffff, BLE_UUID16(0x2222),
+                                     ble_gatt_conn_test_disc_chr_uuid_cb,
+                                     &disc_chr_uuid_arg);
+
+    read_arg.exp_conn_handle = 2;
+    rc = ble_gattc_read(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+                        ble_gatt_conn_test_read_cb, &read_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
-    rc = ble_gattc_disc_all_chrs(BLE_GATT_BREAK_TEST_DISC_CHR_HANDLE,
-                                1, 0xffff, ble_gatt_conn_test_disc_chr_cb,
-                                &disc_c_called);
+    read_uuid_arg.exp_conn_handle = 2;
+    rc = ble_gattc_read_by_uuid(2, 1, 0xffff, BLE_UUID16(0x3333),
+                                ble_gatt_conn_test_read_uuid_cb,
+                                &read_uuid_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
-    rc = ble_gattc_read(BLE_GATT_BREAK_TEST_READ_HANDLE,
-                        BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
-                        ble_gatt_conn_test_read_cb, &read_called);
+    read_long_arg.exp_conn_handle = 2;
+    rc = ble_gattc_read_long(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+                             ble_gatt_conn_test_read_long_cb, &read_long_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
-    rc = ble_gattc_write(BLE_GATT_BREAK_TEST_WRITE_HANDLE,
-                         BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+    /* Connection 3. */
+    read_mult_arg.exp_conn_handle = 3;
+    rc = ble_gattc_read_mult(3, ((uint16_t[3]){5,6,7}), 3,
+                             ble_gatt_conn_test_read_mult_cb, &read_mult_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    write_arg.exp_conn_handle = 3;
+    rc = ble_gattc_write(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
                          ble_gatt_conn_test_write_value,
                          sizeof ble_gatt_conn_test_write_value,
-                         ble_gatt_conn_test_write_cb, &write_called);
+                         ble_gatt_conn_test_write_cb, &write_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
-    /* Start the procedures. */
-    ble_hs_test_util_tx_all();
+    write_long_arg.exp_conn_handle = 3;
+    rc = ble_gattc_write_long(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+                              ble_gatt_conn_test_write_value,
+                              sizeof ble_gatt_conn_test_write_value,
+                              ble_gatt_conn_test_write_long_cb,
+                              &write_long_arg);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    write_rel_arg.exp_conn_handle = 3;
+    rc = ble_gattc_write_reliable(3,
+                                  ((struct ble_gatt_attr[]){{8, 0, NULL, 0}}),
+                                  1, ble_gatt_conn_test_write_rel_cb,
+                                  &write_rel_arg);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    /* Break the connections; verify callbacks got called. */
-    ble_gattc_connection_broken(BLE_GATT_BREAK_TEST_DISC_SERVICE_HANDLE);
-    ble_gattc_connection_broken(BLE_GATT_BREAK_TEST_DISC_CHR_HANDLE);
-    ble_gattc_connection_broken(BLE_GATT_BREAK_TEST_READ_HANDLE);
-    ble_gattc_connection_broken(BLE_GATT_BREAK_TEST_WRITE_HANDLE);
-    /* XXX: Add remaining procedures. */
+    indicate_arg.exp_conn_handle = 3;
+    rc = ble_gattc_indicate(3, attr_handle,
+                            ble_gatt_conn_test_indicate_cb,
+                            &indicate_arg);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    TEST_ASSERT(disc_s_called == 1);
-    TEST_ASSERT(disc_c_called == 1);
-    TEST_ASSERT(read_called == 1);
-    TEST_ASSERT(write_called == 1);
+    /*** Start the procedures. */
+    ble_hs_test_util_tx_all();
+
+    /*** Break the connections; verify proper callbacks got called. */
+    /* Connection 1. */
+    ble_gattc_connection_broken(1);
+    TEST_ASSERT(mtu_arg.called == 1);
+    TEST_ASSERT(disc_all_svcs_arg.called == 1);
+    TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+    TEST_ASSERT(find_inc_svcs_arg.called == 1);
+    TEST_ASSERT(disc_all_chrs_arg.called == 1);
+    TEST_ASSERT(disc_chr_uuid_arg.called == 0);
+    TEST_ASSERT(disc_all_dscs_arg.called == 0);
+    TEST_ASSERT(read_arg.called == 0);
+    TEST_ASSERT(read_uuid_arg.called == 0);
+    TEST_ASSERT(read_long_arg.called == 0);
+    TEST_ASSERT(read_mult_arg.called == 0);
+    TEST_ASSERT(write_arg.called == 0);
+    TEST_ASSERT(write_long_arg.called == 0);
+    TEST_ASSERT(write_rel_arg.called == 0);
+    TEST_ASSERT(indicate_arg.called == 0);
+
+    /* Connection 2. */
+    ble_gattc_connection_broken(2);
+    TEST_ASSERT(mtu_arg.called == 1);
+    TEST_ASSERT(disc_all_svcs_arg.called == 1);
+    TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+    TEST_ASSERT(find_inc_svcs_arg.called == 1);
+    TEST_ASSERT(disc_all_chrs_arg.called == 1);
+    TEST_ASSERT(disc_chr_uuid_arg.called == 1);
+    TEST_ASSERT(disc_all_dscs_arg.called == 1);
+    TEST_ASSERT(read_arg.called == 1);
+    TEST_ASSERT(read_uuid_arg.called == 1);
+    TEST_ASSERT(read_long_arg.called == 1);
+    TEST_ASSERT(read_mult_arg.called == 0);
+    TEST_ASSERT(write_arg.called == 0);
+    TEST_ASSERT(write_long_arg.called == 0);
+    TEST_ASSERT(write_rel_arg.called == 0);
+    TEST_ASSERT(indicate_arg.called == 0);
+
+    /* Connection 3. */
+    ble_gattc_connection_broken(3);
+    TEST_ASSERT(mtu_arg.called == 1);
+    TEST_ASSERT(disc_all_svcs_arg.called == 1);
+    TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+    TEST_ASSERT(find_inc_svcs_arg.called == 1);
+    TEST_ASSERT(disc_all_chrs_arg.called == 1);
+    TEST_ASSERT(disc_chr_uuid_arg.called == 1);
+    TEST_ASSERT(disc_all_dscs_arg.called == 1);
+    TEST_ASSERT(read_arg.called == 1);
+    TEST_ASSERT(read_uuid_arg.called == 1);
+    TEST_ASSERT(read_long_arg.called == 1);
+    TEST_ASSERT(read_mult_arg.called == 1);
+    TEST_ASSERT(write_arg.called == 1);
+    TEST_ASSERT(write_long_arg.called == 1);
+    TEST_ASSERT(write_rel_arg.called == 1);
+    TEST_ASSERT(indicate_arg.called == 1);
 }
 
 TEST_SUITE(ble_gatt_break_suite)
@@ -176,4 +553,3 @@ ble_gatt_conn_test_all(void)
 
     return tu_any_failed;
 }
-