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/01/06 03:29:57 UTC

[2/2] incubator-mynewt-larva git commit: Discover Characteristics by UUID GATT procedure.

Discover Characteristics by UUID GATT procedure.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/f77968f0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/f77968f0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/f77968f0

Branch: refs/heads/master
Commit: f77968f019286dd442f95fbf3f7b0f6100f063c8
Parents: 2abaf0e
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 5 18:15:17 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Jan 5 18:29:43 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_gatt.h         |   3 +
 net/nimble/host/src/ble_gatt.c                  |   9 +
 net/nimble/host/src/ble_gatt_priv.h             |   3 +
 net/nimble/host/src/ble_gattc.c                 |  83 ++++--
 net/nimble/host/src/test/ble_gatt_disc_c_test.c | 253 ++++++++++++++++++-
 5 files changed, 318 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/f77968f0/net/nimble/host/include/host/ble_gatt.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gatt.h b/net/nimble/host/include/host/ble_gatt.h
index f076b04..a8a6bf5 100644
--- a/net/nimble/host/include/host/ble_gatt.h
+++ b/net/nimble/host/include/host/ble_gatt.h
@@ -60,6 +60,9 @@ int ble_gatt_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
 int ble_gatt_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
                             uint16_t end_handle, ble_gatt_chr_fn *cb,
                             void *cb_arg);
+int ble_gatt_disc_chars_by_uuid(uint16_t conn_handle, uint16_t start_handle,
+                                uint16_t end_handle, void *uuid128,
+                                ble_gatt_chr_fn *cb, void *cb_arg);
 int ble_gatt_read(uint16_t conn_handle, uint16_t attr_handle,
                   ble_gatt_attr_fn *cb, void *cb_arg);
 int ble_gatt_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/f77968f0/net/nimble/host/src/ble_gatt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt.c b/net/nimble/host/src/ble_gatt.c
index 0214866..c192537 100644
--- a/net/nimble/host/src/ble_gatt.c
+++ b/net/nimble/host/src/ble_gatt.c
@@ -41,6 +41,15 @@ ble_gatt_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
 }
 
 int
+ble_gatt_disc_chars_by_uuid(uint16_t conn_handle, uint16_t start_handle,
+                            uint16_t end_handle, void *uuid128,
+                            ble_gatt_chr_fn *cb, void *cb_arg)
+{
+    return ble_gattc_disc_chars_by_uuid(conn_handle, start_handle, end_handle,
+                                        uuid128, cb, cb_arg);
+}
+
+int
 ble_gatt_read(uint16_t conn_handle, uint16_t attr_handle,
               ble_gatt_attr_fn *cb, void *cb_arg)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/f77968f0/net/nimble/host/src/ble_gatt_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt_priv.h b/net/nimble/host/src/ble_gatt_priv.h
index f7f3748..414a954 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -46,6 +46,9 @@ int ble_gattc_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
 int ble_gattc_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
                              uint16_t end_handle, ble_gatt_chr_fn *cb,
                              void *cb_arg);
+int ble_gattc_disc_chars_by_uuid(uint16_t conn_handle, uint16_t start_handle,
+                                 uint16_t end_handle, void *uuid128,
+                                 ble_gatt_chr_fn *cb, void *cb_arg);
 int ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
                    ble_gatt_attr_fn *cb, void *cb_arg);
 int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/f77968f0/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 ffdf42b..cda2864 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -57,6 +57,7 @@ struct ble_gattc_entry {
         } disc_service_uuid;
 
         struct {
+            uint8_t chr_uuid[16];
             uint16_t prev_handle;
             uint16_t end_handle;
             ble_gatt_chr_fn *cb;
@@ -91,11 +92,12 @@ struct ble_gattc_entry {
 #define BLE_GATT_OP_DISC_ALL_SERVICES           1
 #define BLE_GATT_OP_DISC_SERVICE_UUID           2
 #define BLE_GATT_OP_DISC_ALL_CHARS              3
-#define BLE_GATT_OP_READ                        4
-#define BLE_GATT_OP_WRITE_NO_RSP                5
-#define BLE_GATT_OP_WRITE                       6
-#define BLE_GATT_OP_INDICATE                    7
-#define BLE_GATT_OP_MAX                         8
+#define BLE_GATT_OP_DISC_CHARS_UUID             4
+#define BLE_GATT_OP_READ                        5
+#define BLE_GATT_OP_WRITE_NO_RSP                6
+#define BLE_GATT_OP_WRITE                       7
+#define BLE_GATT_OP_INDICATE                    8
+#define BLE_GATT_OP_MAX                         9
 
 static struct os_callout_func ble_gattc_heartbeat_timer;
 
@@ -113,11 +115,11 @@ static int ble_gattc_kick_indicate(struct ble_gattc_entry *entry);
 
 static void ble_gattc_err_mtu(struct ble_gattc_entry *entry, int status);
 static void ble_gattc_err_disc_all_services(struct ble_gattc_entry *entry,
-                                           int status);
+                                            int status);
 static void ble_gattc_err_disc_service_uuid(struct ble_gattc_entry *entry,
-                                           int status);
+                                            int status);
 static void ble_gattc_err_disc_all_chars(struct ble_gattc_entry *entry,
-                                        int status);
+                                         int status);
 static void ble_gattc_err_read(struct ble_gattc_entry *entry, int status);
 static void ble_gattc_err_write(struct ble_gattc_entry *entry, int status);
 static void ble_gattc_err_indicate(struct ble_gattc_entry *entry, int status);
@@ -146,6 +148,10 @@ static const struct ble_gattc_dispatch_entry
         .kick_cb = ble_gattc_kick_disc_all_chars,
         .err_cb = ble_gattc_err_disc_all_chars,
     },
+    [BLE_GATT_OP_DISC_CHARS_UUID] = {
+        .kick_cb = ble_gattc_kick_disc_all_chars,
+        .err_cb = ble_gattc_err_disc_all_chars,
+    },
     [BLE_GATT_OP_READ] = {
         .kick_cb = ble_gattc_kick_read,
         .err_cb = ble_gattc_err_read,
@@ -252,7 +258,7 @@ ble_gattc_entry_matches(struct ble_gattc_entry *entry, uint16_t conn_handle,
 
 static struct ble_gattc_entry *
 ble_gattc_find(uint16_t conn_handle, uint8_t att_op, int expecting_only,
-              struct ble_gattc_entry **out_prev)
+               struct ble_gattc_entry **out_prev)
 {
     struct ble_gattc_entry *entry;
     struct ble_gattc_entry *prev;
@@ -260,7 +266,7 @@ ble_gattc_find(uint16_t conn_handle, uint8_t att_op, int expecting_only,
     prev = NULL;
     STAILQ_FOREACH(entry, &ble_gattc_list, next) {
         if (ble_gattc_entry_matches(entry, conn_handle, att_op,
-                                   expecting_only)) {
+                                    expecting_only)) {
             if (out_prev != NULL) {
                 *out_prev = prev;
             }
@@ -766,7 +772,7 @@ ble_gattc_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
 }
 
 /*****************************************************************************
- * @discover all characteristics                                             *
+ * $discover all characteristics                                             *
  *****************************************************************************/
 
 static int
@@ -834,7 +840,7 @@ ble_gattc_err_disc_all_chars(struct ble_gattc_entry *entry, int status)
 
 void
 ble_gattc_rx_read_type_adata(struct ble_hs_conn *conn,
-                            struct ble_att_clt_adata *adata)
+                             struct ble_att_clt_adata *adata)
 {
     struct ble_gattc_entry *entry;
     struct ble_gattc_entry *prev;
@@ -843,9 +849,11 @@ ble_gattc_rx_read_type_adata(struct ble_hs_conn *conn,
     int cbrc;
     int rc;
 
-    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_DISC_ALL_CHARS, 1,
-                          &prev);
-    if (entry == NULL) {
+    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_NONE, 1, &prev);
+    if (entry == NULL ||
+        (entry->op != BLE_GATT_OP_DISC_ALL_CHARS &&
+         entry->op != BLE_GATT_OP_DISC_CHARS_UUID)) {
+
         /* Not expecting a response from this device. */
         return;
     }
@@ -880,8 +888,16 @@ ble_gattc_rx_read_type_adata(struct ble_hs_conn *conn,
     rc = 0;
 
 done:
-    cbrc = ble_gattc_disc_all_chars_cb(entry, rc, &chr);
-    if (rc != 0 || cbrc != 0) {
+    if (entry->op == BLE_GATT_OP_DISC_ALL_CHARS ||
+        memcmp(chr.uuid128, entry->disc_all_chars.chr_uuid, 16) == 0) {
+
+        cbrc = ble_gattc_disc_all_chars_cb(entry, rc, &chr);
+        if (rc == 0) {
+            rc = cbrc;
+        }
+    }
+
+    if (rc != 0) {
         ble_gattc_entry_remove_free(entry, prev);
     }
 }
@@ -892,9 +908,11 @@ ble_gattc_rx_read_type_complete(struct ble_hs_conn *conn, int rc)
     struct ble_gattc_entry *entry;
     struct ble_gattc_entry *prev;
 
-    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_DISC_ALL_CHARS, 1,
-                          &prev);
-    if (entry == NULL) {
+    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_NONE, 1, &prev);
+    if (entry == NULL ||
+        (entry->op != BLE_GATT_OP_DISC_ALL_CHARS &&
+         entry->op != BLE_GATT_OP_DISC_CHARS_UUID)) {
+
         /* Not expecting a response from this device. */
         return;
     }
@@ -931,6 +949,31 @@ ble_gattc_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
 }
 
 /*****************************************************************************
+ * $discover characteristic by uuid                                          *
+ *****************************************************************************/
+
+int
+ble_gattc_disc_chars_by_uuid(uint16_t conn_handle, uint16_t start_handle,
+                             uint16_t end_handle, void *uuid128,
+                             ble_gatt_chr_fn *cb, void *cb_arg)
+{
+    struct ble_gattc_entry *entry;
+    int rc;
+
+    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_CHARS_UUID, &entry);
+    if (rc != 0) {
+        return rc;
+    }
+    memcpy(entry->disc_all_chars.chr_uuid, uuid128, 16);
+    entry->disc_all_chars.prev_handle = start_handle - 1;
+    entry->disc_all_chars.end_handle = end_handle;
+    entry->disc_all_chars.cb = cb;
+    entry->disc_all_chars.cb_arg = cb_arg;
+
+    return 0;
+}
+
+/*****************************************************************************
  * @read                                                                     *
  *****************************************************************************/
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/f77968f0/net/nimble/host/src/test/ble_gatt_disc_c_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_disc_c_test.c b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
index e8be637..e8cc467 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_c_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
@@ -16,6 +16,7 @@
 
 #include <string.h>
 #include <errno.h>
+#include <limits.h>
 #include "testutil/testutil.h"
 #include "nimble/ble.h"
 #include "host/ble_hs_test.h"
@@ -51,7 +52,7 @@ ble_gatt_disc_c_test_init(void)
 }
 
 static int
-ble_gatt_disc_c_test_misc_rx_all_rsp_once(
+ble_gatt_disc_c_test_misc_rx_rsp_once(
     struct ble_hs_conn *conn, struct ble_gatt_disc_c_test_char *chars)
 {
     struct ble_att_read_type_rsp rsp;
@@ -116,7 +117,7 @@ ble_gatt_disc_c_test_misc_rx_all_rsp_once(
 }
 
 static void
-ble_gatt_disc_c_test_misc_rx_all_rsp(struct ble_hs_conn *conn,
+ble_gatt_disc_c_test_misc_rx_rsp(struct ble_hs_conn *conn,
                                      uint16_t end_handle,
                                      struct ble_gatt_disc_c_test_char *chars)
 {
@@ -125,7 +126,7 @@ ble_gatt_disc_c_test_misc_rx_all_rsp(struct ble_hs_conn *conn,
 
     idx = 0;
     while (chars[idx].decl_handle != 0) {
-        count = ble_gatt_disc_c_test_misc_rx_all_rsp_once(conn, chars + idx);
+        count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn, chars + idx);
         if (count == 0) {
             break;
         }
@@ -142,12 +143,17 @@ ble_gatt_disc_c_test_misc_rx_all_rsp(struct ble_hs_conn *conn,
 }
 
 static void
-ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char *chars)
+ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char *chars,
+                                       int stop_after)
 {
     uint16_t uuid16;
     int i;
 
-    for (i = 0; chars[i].decl_handle != 0; i++) {
+    if (stop_after == 0) {
+        stop_after = INT_MAX;
+    }
+
+    for (i = 0; i < stop_after && chars[i].decl_handle != 0; i++) {
         TEST_ASSERT(chars[i].decl_handle ==
                     ble_gatt_disc_c_test_chars[i].decl_handle);
         TEST_ASSERT(chars[i].value_handle ==
@@ -171,10 +177,13 @@ ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle, int status,
                              struct ble_gatt_chr *chr, void *arg)
 {
     struct ble_gatt_chr *dst;
+    int *stop_after;
 
     TEST_ASSERT(status == 0);
     TEST_ASSERT(!ble_gatt_disc_c_test_rx_complete);
 
+    stop_after = arg;
+
     if (chr == NULL) {
         ble_gatt_disc_c_test_rx_complete = 1;
     } else {
@@ -185,32 +194,66 @@ ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle, int status,
         *dst = *chr;
     }
 
+    if (*stop_after > 0) {
+        (*stop_after)--;
+        if (*stop_after == 0) {
+            ble_gatt_disc_c_test_rx_complete = 1;
+            return 1;
+        }
+    }
+
     return 0;
 }
 
 static void
 ble_gatt_disc_c_test_misc_all(uint16_t start_handle, uint16_t end_handle,
+                              int stop_after,
                               struct ble_gatt_disc_c_test_char *chars)
 {
     struct ble_hs_conn *conn;
+    int num_left;
     int rc;
 
     ble_gatt_disc_c_test_init();
 
     conn = ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}));
 
+    num_left = stop_after;
     rc = ble_gatt_disc_all_chars(2, start_handle, end_handle,
-                                  ble_gatt_disc_c_test_misc_cb, NULL);
+                                  ble_gatt_disc_c_test_misc_cb, &num_left);
+    TEST_ASSERT(rc == 0);
+
+    ble_gatt_disc_c_test_misc_rx_rsp(conn, end_handle, chars);
+    ble_gatt_disc_c_test_misc_verify_chars(chars, stop_after);
+}
+
+static void
+ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle, uint16_t end_handle,
+                               int stop_after, uint8_t *uuid128,
+                               struct ble_gatt_disc_c_test_char *rsp_chars,
+                               struct ble_gatt_disc_c_test_char *ret_chars)
+{
+    struct ble_hs_conn *conn;
+    int rc;
+
+    ble_gatt_disc_c_test_init();
+
+    conn = ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}));
+
+    rc = ble_gatt_disc_chars_by_uuid(2, start_handle, end_handle,
+                                     uuid128,
+                                     ble_gatt_disc_c_test_misc_cb,
+                                     &stop_after);
     TEST_ASSERT(rc == 0);
 
-    ble_gatt_disc_c_test_misc_rx_all_rsp(conn, end_handle, chars);
-    ble_gatt_disc_c_test_misc_verify_chars(chars);
+    ble_gatt_disc_c_test_misc_rx_rsp(conn, end_handle, rsp_chars);
+    ble_gatt_disc_c_test_misc_verify_chars(ret_chars, 0);
 }
 
 TEST_CASE(ble_gatt_disc_c_test_disc_all)
 {
     /*** One 16-bit characteristic. */
-    ble_gatt_disc_c_test_misc_all(50, 100,
+    ble_gatt_disc_c_test_misc_all(50, 100, 0,
                                   (struct ble_gatt_disc_c_test_char[]) {
         {
             .decl_handle = 55,
@@ -220,7 +263,7 @@ TEST_CASE(ble_gatt_disc_c_test_disc_all)
     });
 
     /*** Two 16-bit characteristics. */
-    ble_gatt_disc_c_test_misc_all(50, 100,
+    ble_gatt_disc_c_test_misc_all(50, 100, 0,
                                   (struct ble_gatt_disc_c_test_char[]) {
         {
             .decl_handle = 55,
@@ -234,7 +277,7 @@ TEST_CASE(ble_gatt_disc_c_test_disc_all)
     });
 
     /*** Five 16-bit characteristics. */
-    ble_gatt_disc_c_test_misc_all(50, 100,
+    ble_gatt_disc_c_test_misc_all(50, 100, 0,
                                   (struct ble_gatt_disc_c_test_char[]) {
         {
             .decl_handle = 55,
@@ -260,7 +303,7 @@ TEST_CASE(ble_gatt_disc_c_test_disc_all)
     });
 
     /*** Interleaved 16-bit and 128-bit characteristics. */
-    ble_gatt_disc_c_test_misc_all(50, 100,
+    ble_gatt_disc_c_test_misc_all(50, 100, 0,
                                   (struct ble_gatt_disc_c_test_char[]) {
         {
             .decl_handle = 83,
@@ -286,7 +329,7 @@ TEST_CASE(ble_gatt_disc_c_test_disc_all)
     });
 
     /*** Ends with final handle ID. */
-    ble_gatt_disc_c_test_misc_all(50, 100,
+    ble_gatt_disc_c_test_misc_all(50, 100, 0,
                                   (struct ble_gatt_disc_c_test_char[]) {
         {
             .decl_handle = 55,
@@ -298,11 +341,195 @@ TEST_CASE(ble_gatt_disc_c_test_disc_all)
             .uuid16 = 0x64ba,
         }, { 0 }
     });
+
+    /*** Stop after two characteristics. */
+    ble_gatt_disc_c_test_misc_all(50, 100, 2,
+                                  (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 57,
+            .value_handle = 58,
+            .uuid16 = 0x64ba,
+        }, {
+            .decl_handle = 59,
+            .value_handle = 60,
+            .uuid16 = 0x5372,
+        }, {
+            .decl_handle = 61,
+            .value_handle = 62,
+            .uuid16 = 0xab93,
+        }, {
+            .decl_handle = 63,
+            .value_handle = 64,
+            .uuid16 = 0x0023,
+        }, { 0 }
+    });
+}
+
+TEST_CASE(ble_gatt_disc_c_test_disc_uuid)
+{
+    /*** One 16-bit characteristic. */
+    ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16(0x2010),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, { 0 } }
+    );
+
+    /*** No matching characteristics. */
+    ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16(0x2010),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x1234,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        { 0 } }
+    );
+
+    /*** 2/5 16-bit characteristics. */
+    ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16(0x2010),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 57,
+            .value_handle = 58,
+            .uuid16 = 0x64ba,
+        }, {
+            .decl_handle = 59,
+            .value_handle = 60,
+            .uuid16 = 0x5372,
+        }, {
+            .decl_handle = 61,
+            .value_handle = 62,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 63,
+            .value_handle = 64,
+            .uuid16 = 0x0023,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 61,
+            .value_handle = 62,
+            .uuid16 = 0x2010,
+        }, { 0 } }
+    );
+
+    /*** Interleaved 16-bit and 128-bit characteristics. */
+    ble_gatt_disc_c_test_misc_uuid(
+        50, 100, 0,
+        ((uint8_t[]){ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 83,
+            .value_handle = 84,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 87,
+            .value_handle = 88,
+            .uuid128 = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
+        }, {
+            .decl_handle = 91,
+            .value_handle = 92,
+            .uuid16 = 0x0003,
+        }, {
+            .decl_handle = 93,
+            .value_handle = 94,
+            .uuid128 = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
+        }, {
+            .decl_handle = 98,
+            .value_handle = 99,
+            .uuid16 = 0xabfa,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 87,
+            .value_handle = 88,
+            .uuid128 = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
+        }, {
+            .decl_handle = 93,
+            .value_handle = 94,
+            .uuid128 = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
+        }, { 0 } }
+    );
+
+    /*** Ends with final handle ID. */
+    ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16(0x64ba),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 99,
+            .value_handle = 100,
+            .uuid16 = 0x64ba,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 99,
+            .value_handle = 100,
+            .uuid16 = 0x64ba,
+        }, { 0 } }
+    );
+
+    /*** Stop after first characteristic. */
+    ble_gatt_disc_c_test_misc_uuid(50, 100, 1, BLE_UUID16(0x2010),
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 57,
+            .value_handle = 58,
+            .uuid16 = 0x64ba,
+        }, {
+            .decl_handle = 59,
+            .value_handle = 60,
+            .uuid16 = 0x5372,
+        }, {
+            .decl_handle = 61,
+            .value_handle = 62,
+            .uuid16 = 0x2010,
+        }, {
+            .decl_handle = 63,
+            .value_handle = 64,
+            .uuid16 = 0x0023,
+        }, { 0 } },
+        (struct ble_gatt_disc_c_test_char[]) {
+        {
+            .decl_handle = 55,
+            .value_handle = 56,
+            .uuid16 = 0x2010,
+        }, { 0 } }
+    );
 }
 
 TEST_SUITE(ble_gatt_disc_c_test_suite)
 {
     ble_gatt_disc_c_test_disc_all();
+    ble_gatt_disc_c_test_disc_uuid();
 }
 
 int