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

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

commit 29d3a155c3c5b12aff9ffbca49514a9dfcb61b46
Author: Szymon Czapracki <szymonczapra...@gmail.com>
AuthorDate: Fri Aug 2 15:01:04 2019 +0200

    apps/bttester: Modify gatt database
    
    Slim down overall number of gatt services, characteristics etc.
    Make database static, remove functions for adding or deleting values.
---
 apps/bttester/src/bttester.c |    1 -
 apps/bttester/src/bttester.h |    9 +
 apps/bttester/src/gatt.c     | 2449 +++++++++++++++++++-----------------------
 3 files changed, 1115 insertions(+), 1344 deletions(-)

diff --git a/apps/bttester/src/bttester.c b/apps/bttester/src/bttester.c
index 02021d0..54b14da 100644
--- a/apps/bttester/src/bttester.c
+++ b/apps/bttester/src/bttester.c
@@ -254,7 +254,6 @@ static u8_t *recv_cb(u8_t *buf, size_t *off)
 
        len = sys_le16_to_cpu(cmd->len);
        if (len > BTP_MTU - sizeof(*cmd)) {
-               SYS_LOG_ERR("BT tester: invalid packet length");
                *off = 0;
                return buf;
        }
diff --git a/apps/bttester/src/bttester.h b/apps/bttester/src/bttester.h
index f9780ca..d3d4f73 100644
--- a/apps/bttester/src/bttester.h
+++ b/apps/bttester/src/bttester.h
@@ -651,6 +651,8 @@ struct gatt_attr {
 
 #define GATT_GET_ATTRIBUTE_VALUE       0x1d
 struct gatt_get_attribute_value_cmd {
+       u8_t address_type;
+       u8_t address[6];
        u16_t handle;
 } __packed;
 struct gatt_get_attribute_value_rp {
@@ -659,6 +661,13 @@ struct gatt_get_attribute_value_rp {
        u8_t value[0];
 } __packed;
 
+#define GATT_CHANGE_DATABASE           0x1e
+struct gatt_change_database {
+    u16_t start_handle;
+    u16_t end_handle;
+    u8_t visibility;
+} __packed;
+
 /* GATT events */
 #define GATT_EV_NOTIFICATION           0x80
 struct gatt_notification_ev {
diff --git a/apps/bttester/src/gatt.c b/apps/bttester/src/gatt.c
index fe24275..72a7831 100644
--- a/apps/bttester/src/gatt.c
+++ b/apps/bttester/src/gatt.c
@@ -1,13 +1,13 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership.  The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
+ * with the License.    You may obtain a copy of the License at
  *
- *  http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
@@ -41,855 +41,504 @@
 #define CONTROLLER_INDEX 0
 #define MAX_BUFFER_SIZE 2048
 
-static const ble_uuid_t *uuid_ccc =
-       BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
-
-static int gatt_chr_perm_map[] = {
-       BLE_GATT_CHR_F_READ,
-       BLE_GATT_CHR_F_WRITE,
-       BLE_GATT_CHR_F_READ_ENC,
-       BLE_GATT_CHR_F_WRITE_ENC,
-       BLE_GATT_CHR_F_READ_AUTHEN,
-       BLE_GATT_CHR_F_WRITE_AUTHEN,
-       BLE_GATT_CHR_F_READ_AUTHOR,
-       BLE_GATT_CHR_F_WRITE_AUTHOR,
-};
-
-static int gatt_dsc_perm_map[] = {
-       BLE_ATT_F_READ,
-       BLE_ATT_F_WRITE,
-       BLE_ATT_F_READ_ENC,
-       BLE_ATT_F_WRITE_ENC,
-       BLE_ATT_F_READ_AUTHEN,
-       BLE_ATT_F_WRITE_AUTHEN,
-       BLE_ATT_F_READ_AUTHOR,
-       BLE_ATT_F_WRITE_AUTHOR,
-};
-
-/* GATT server context */
-#define SERVER_MAX_VALUES      14
-
-struct gatt_value {
-       struct os_mbuf *buf;
-       u8_t enc_key_size;
-       u8_t flags[1];
-       u16_t val_handle;
-       u8_t type;
-       void *ptr;
-};
-
-enum {
-       GATT_VALUE_TYPE_CHR,
-       GATT_VALUE_TYPE_DSC,
-};
-
-static struct gatt_value gatt_values[SERVER_MAX_VALUES];
-
 /* 0000xxxx-8c26-476f-89a7-a108033a69c7 */
-#define PTS_UUID_DECLARE(uuid16)                                \
+#define PTS_UUID_DECLARE(uuid16)                                    \
     ((const ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT(   \
-        0xc7, 0x69, 0x3a, 0x03, 0x08, 0xa1, 0xa7, 0x89,         \
-        0x6f, 0x47, 0x26, 0x8c, uuid16, uuid16 >> 8, 0x00, 0x00 \
+       0xc7, 0x69, 0x3a, 0x03, 0x08, 0xa1, 0xa7, 0x89,             \
+       0x6f, 0x47, 0x26, 0x8c, uuid16, uuid16 >> 8, 0x00, 0x00     \
     )))
 
-#define  PTS_SVC                         0x0001
-#define  PTS_CHR_NO_PERM                 0x0002
-#define  PTS_CHR_READ                    0x0003
-#define  PTS_CHR_RELIABLE_WRITE          0x0004
-#define  PTS_CHR_WRITE_NO_RSP            0x0005
-#define  PTS_CHR_READ_WRITE              0x0006
-#define  PTS_CHR_READ_WRITE_ENC          0x0007
-#define  PTS_CHR_READ_WRITE_AUTHEN       0x0008
-#define  PTS_CHR_READ_WRITE_AUTHOR       0x0009
-#define  PTS_DSC_READ                    0x000a
-#define  PTS_DSC_WRITE                   0x000b
-#define  PTS_DSC_READ_WRITE              0x000c
-#define  PTS_DSC_READ_WRITE_ENC          0x000d
-#define  PTS_DSC_READ_WRITE_AUTHEN       0x000e
-#define  PTS_INC_SVC                     0x000f
-#define  PTS_CHR_READ_WRITE_ALT          0x0010
-
-/*
- * gatt_buf - cache used by a gatt client (to cache data read/discovered)
- * and gatt server (to store attribute user_data).
- * It is not intended to be used by client and server at the same time.
- */
-static struct {
-       u16_t len;
-       u8_t buf[MAX_BUFFER_SIZE];
-} gatt_buf;
-
-static void *gatt_buf_add(const void *data, size_t len)
-{
-       void *ptr = gatt_buf.buf + gatt_buf.len;
+/* 0000xxxx-8c26-476f-89a7-a108033a69c6 */
+#define PTS_UUID_DECLARE_ALT(uuid16)                            \
+    ((const ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT(   \
+       0xc6, 0x69, 0x3a, 0x03, 0x08, 0xa1, 0xa7, 0x89,             \
+       0x6f, 0x47, 0x26, 0x8c, uuid16, uuid16 >> 8, 0x00, 0x00     \
+    )))
 
-       if ((len + gatt_buf.len) > MAX_BUFFER_SIZE) {
-               return NULL;
-       }
+#define  PTS_SVC                           0x0001
+#define  PTS_CHR_READ                      0x0002
+#define  PTS_CHR_WRITE                     0x0003
+#define  PTS_CHR_RELIABLE_WRITE            0x0004
+#define  PTS_CHR_WRITE_NO_RSP              0x0005
+#define  PTS_CHR_READ_WRITE                0x0006
+#define  PTS_CHR_READ_WRITE_ENC            0x0007
+#define  PTS_CHR_READ_WRITE_AUTHEN         0x0008
+#define  PTS_DSC_READ                      0x0009
+#define  PTS_DSC_WRITE                     0x000a
+#define  PTS_DSC_READ_WRITE                0x000b
+#define  PTS_CHR_NOTIFY                    0x0025
+#define  PTS_LONG_CHR_READ_WRITE           0x0015
+#define  PTS_LONG_CHR_READ_WRITE_ALT       0x0016
+#define  PTS_LONG_DSC_READ_WRITE           0x001b
+#define  PTS_INC_SVC                       0x001e
+#define  PTS_CHR_READ_WRITE_ALT            0x001f
+
+static uint8_t gatt_svr_pts_static_long_val[300];
+static uint8_t gatt_svr_pts_static_val[30];
+static uint8_t gatt_svr_pts_static_short_val;
+static bool notify_state;
+static uint16_t myconn_handle;
+static struct os_callout notify_tx_timer;
+uint16_t notify_handle;
 
-       if (data) {
-               memcpy(ptr, data, len);
-       } else {
-               (void)memset(ptr, 0, len);
-       }
+struct find_attr_data {
+                ble_uuid_any_t *uuid;
+                int attr_type;
+                void *ptr;
+                uint16_t handle;
+};
 
-       gatt_buf.len += len;
+static int
+gatt_svr_read_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                        struct ble_gatt_access_ctxt *ctxt,
+                        void *arg);
 
-       SYS_LOG_DBG("%d/%d used", gatt_buf.len, MAX_BUFFER_SIZE);
+static int
+gatt_svr_read_write_auth_test(uint16_t conn_handle, uint16_t attr_handle,
+                             struct ble_gatt_access_ctxt *ctxt,
+                             void *arg);
 
-       return ptr;
-}
+static int
+gatt_svr_read_write_enc_test(uint16_t conn_handle, uint16_t attr_handle,
+                            struct ble_gatt_access_ctxt *ctxt,
+                            void *arg);
 
-static const struct ble_gatt_dsc_def cccd_def = {
-       .att_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE,
-};
+static int
+gatt_svr_dsc_read_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                            struct ble_gatt_access_ctxt *ctxt,
+                            void *arg);
 
-static void *gatt_buf_reserve(size_t len)
-{
-       return gatt_buf_add(NULL, len);
-}
+static int
+gatt_svr_write_no_rsp_test(uint16_t conn_handle, uint16_t attr_handle,
+                          struct ble_gatt_access_ctxt *ctxt,
+                          void *arg);
 
-static void gatt_buf_clear(void)
-{
-       (void)memset(&gatt_buf, 0, sizeof(gatt_buf));
-}
+static int
+gatt_svr_rel_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                       struct ble_gatt_access_ctxt *ctxt,
+                       void *arg);
 
-static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle,
+static int
+gatt_svr_read_write_long_test(uint16_t conn_handle, uint16_t attr_handle,
                              struct ble_gatt_access_ctxt *ctxt,
                              void *arg);
 
+static int
+gatt_svr_dsc_read_test(uint16_t conn_handle, uint16_t attr_handle,
+                      struct ble_gatt_access_ctxt *ctxt,
+                      void *arg);
 
-static const struct ble_gatt_svc_def gatt_svr_inc_svcs[] = {
-       {
-               .type = BLE_GATT_SVC_TYPE_PRIMARY,
-               .uuid = PTS_UUID_DECLARE(PTS_INC_SVC),
-               .characteristics = (struct ble_gatt_chr_def[]) {{
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_ALT),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_WRITE,
-                       .arg = &gatt_values[13],
-                       .val_handle = &gatt_values[13].val_handle,
-               }, {
-                       0,
-               } },
-       },
-
-       {
-               0, /* No more services. */
-       },
-};
+static int
+gatt_svr_dsc_read_write_long_test(uint16_t conn_handle, uint16_t attr_handle,
+                                 struct ble_gatt_access_ctxt *ctxt,
+                                 void *arg);
 
-static const struct ble_gatt_svc_def *inc_svcs[] = {
-       &gatt_svr_inc_svcs[0],
-       NULL,
-};
 
 static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
        {
                /*** Service: PTS test. */
                .type = BLE_GATT_SVC_TYPE_PRIMARY,
                .uuid = PTS_UUID_DECLARE(PTS_SVC),
-               .includes = inc_svcs,
                .characteristics = (struct ble_gatt_chr_def[]) { {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_NO_PERM),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = 0,
-                       .arg = &gatt_values[0],
-                       .val_handle = &gatt_values[0].val_handle,
-               }, {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_READ),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_NOTIFY |
-                                BLE_GATT_CHR_F_INDICATE,
-                       .arg = &gatt_values[1],
-                       .val_handle = &gatt_values[1].val_handle,
-               }, {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_RELIABLE_WRITE),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_WRITE |
-                                BLE_GATT_CHR_F_RELIABLE_WRITE,
-                       .arg = &gatt_values[2],
-                       .val_handle = &gatt_values[2].val_handle,
-               }, {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_WRITE_NO_RSP),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_WRITE_NO_RSP,
-                       .arg = &gatt_values[3],
-                       .val_handle = &gatt_values[3].val_handle,
-               }, {
                        .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE),
-                       .access_cb = gatt_svr_access_cb,
+                       .access_cb = gatt_svr_read_write_test,
                        .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_WRITE |
-                                BLE_GATT_CHR_F_NOTIFY |
-                                BLE_GATT_CHR_F_INDICATE,
-                       .arg = &gatt_values[4],
-                       .val_handle = &gatt_values[4].val_handle,
+                                BLE_GATT_CHR_F_WRITE,
                        .descriptors = (struct ble_gatt_dsc_def[]) { {
-                                  .uuid = PTS_UUID_DECLARE(PTS_DSC_READ_WRITE),
-                                  .access_cb = gatt_svr_access_cb,
-                                  .att_flags = BLE_ATT_F_READ | 
BLE_ATT_F_WRITE,
-                                  .arg = &gatt_values[5],
+                               .uuid = PTS_UUID_DECLARE(PTS_DSC_READ_WRITE),
+                               .access_cb = gatt_svr_dsc_read_write_test,
+                               .att_flags = BLE_ATT_F_READ |
+                                            BLE_ATT_F_WRITE,
+                       }, {
+                       .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_READ_WRITE),
+                       .access_cb = gatt_svr_dsc_read_write_long_test,
+                       .att_flags = BLE_ATT_F_READ |
+                                    BLE_ATT_F_WRITE,
                        }, {
-                               0
+                       .uuid = PTS_UUID_DECLARE(PTS_DSC_READ),
+                       .access_cb = gatt_svr_dsc_read_test,
+                       .att_flags = BLE_ATT_F_READ,
+                       }, {
+                               0, /* No more descriptors in this 
characteristic */
                        } }
                }, {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_ENC),
-                       .access_cb = gatt_svr_access_cb,
+                       .uuid = PTS_UUID_DECLARE(PTS_CHR_WRITE_NO_RSP),
+                       .access_cb = gatt_svr_write_no_rsp_test,
                        .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_READ_ENC |
                                 BLE_GATT_CHR_F_WRITE |
-                                BLE_GATT_CHR_F_WRITE_ENC,
-                       .min_key_size = 0x0f,
-                       .arg = &gatt_values[6],
-                       .val_handle = &gatt_values[6].val_handle,
+                                BLE_GATT_CHR_F_WRITE_NO_RSP,
                }, {
                        .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_AUTHEN),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_READ_AUTHEN |
+                       .access_cb = gatt_svr_read_write_auth_test,
+                       .flags = BLE_GATT_CHR_F_READ_AUTHEN |
+                                BLE_GATT_CHR_F_READ |
+                                BLE_GATT_CHR_F_WRITE_AUTHEN |
                                 BLE_GATT_CHR_F_WRITE |
                                 BLE_GATT_CHR_F_WRITE_AUTHEN,
-                       .arg = &gatt_values[7],
-                       .val_handle = &gatt_values[7].val_handle,
                }, {
-                       .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_AUTHOR),
-                       .access_cb = gatt_svr_access_cb,
-                       .flags = BLE_GATT_CHR_F_READ |
-                                BLE_GATT_CHR_F_READ_AUTHOR |
+                       .uuid = PTS_UUID_DECLARE(PTS_CHR_RELIABLE_WRITE),
+                       .access_cb = gatt_svr_rel_write_test,
+                       .flags = BLE_GATT_CHR_F_WRITE |
+                                BLE_GATT_CHR_F_RELIABLE_WRITE,
+               }, {
+                       .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_ENC),
+                       .access_cb = gatt_svr_read_write_enc_test,
+                       .flags = BLE_GATT_CHR_F_READ_ENC |
+                                BLE_GATT_CHR_F_READ |
                                 BLE_GATT_CHR_F_WRITE |
-                                BLE_GATT_CHR_F_WRITE_AUTHOR,
-                       .arg = &gatt_values[8],
-                       .val_handle = &gatt_values[8].val_handle,
-
-                       .descriptors = (struct ble_gatt_dsc_def[]){ {
-                               .uuid = PTS_UUID_DECLARE(PTS_DSC_READ),
-                               .access_cb = gatt_svr_access_cb,
-                               .att_flags = BLE_ATT_F_READ,
-                               .arg = &gatt_values[9],
-                       }, {
-                               .uuid = PTS_UUID_DECLARE(PTS_DSC_WRITE),
-                               .access_cb = gatt_svr_access_cb,
-                               .att_flags = BLE_ATT_F_WRITE,
-                               .arg = &gatt_values[10],
-                       }, {
-                               .uuid = 
PTS_UUID_DECLARE(PTS_DSC_READ_WRITE_ENC),
-                               .access_cb = gatt_svr_access_cb,
-                               .att_flags = BLE_ATT_F_READ |
-                                            BLE_ATT_F_READ_ENC |
-                                            BLE_ATT_F_WRITE |
-                                            BLE_ATT_F_WRITE_ENC,
-                               .min_key_size = 0x0f,
-                               .arg = &gatt_values[11],
-                       }, {
-                               .uuid = 
PTS_UUID_DECLARE(PTS_DSC_READ_WRITE_AUTHEN),
-                               .access_cb = gatt_svr_access_cb,
-                               .att_flags = BLE_ATT_F_READ |
-                                            BLE_ATT_F_READ_AUTHEN |
-                                            BLE_ATT_F_WRITE |
-                                            BLE_ATT_F_WRITE_AUTHEN,
-                               .arg = &gatt_values[12],
-                       }, {
-                               0, /* No more descriptors in this 
characteristic. */
-                       } }
+                                BLE_GATT_CHR_F_WRITE_ENC,
+                       .min_key_size = 0x16,
+               }, {
+                       .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE),
+                       .access_cb = gatt_svr_read_write_long_test,
+                       .flags = BLE_GATT_CHR_F_WRITE |
+                                BLE_GATT_CHR_F_READ,
+               }, {
+                       .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE_ALT),
+                       .access_cb = gatt_svr_read_write_long_test,
+                       .flags = BLE_GATT_CHR_F_WRITE |
+                                BLE_GATT_CHR_F_READ,
+               }, {
+                       .uuid = PTS_UUID_DECLARE(PTS_CHR_NOTIFY),
+                       .access_cb = gatt_svr_read_write_test,
+                       .val_handle = &notify_handle,
+                       .flags = BLE_GATT_CHR_F_NOTIFY |
+                                BLE_GATT_CHR_F_INDICATE,
                }, {
                        0, /* No more characteristics in this service. */
                } },
        },
 
        {
+               .type = BLE_GATT_SVC_TYPE_PRIMARY,
+               .uuid = PTS_UUID_DECLARE_ALT(PTS_SVC),
+               .characteristics = (struct ble_gatt_chr_def[]) { {
+                       .uuid = PTS_UUID_DECLARE_ALT(PTS_CHR_READ_WRITE),
+                       .access_cb = gatt_svr_read_write_test,
+                       .flags = BLE_GATT_CHR_F_WRITE |
+                                BLE_GATT_CHR_F_READ,
+               }, {
+                       0, /* No more characteristics in this service */
+               } },
+       },
+
+       {
                0, /* No more services. */
        },
 };
 
-static void init_gatt_values(void)
+static int
+gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
+                  void *dst, uint16_t *len)
 {
-       int i = 0;
-       const struct ble_gatt_svc_def *svc;
-       const struct ble_gatt_chr_def *chr;
-       const struct ble_gatt_dsc_def *dsc;
-
-       /* GATT/SR/GAR/BV-05-C fails when a characteristic value is empty */
-
-       for (svc = gatt_svr_svcs; svc && svc->uuid; svc++) {
-               for (chr = svc->characteristics; chr && chr->uuid; chr++) {
-                       assert(i < SERVER_MAX_VALUES);
-                       gatt_values[i].type = GATT_VALUE_TYPE_CHR;
-                       gatt_values[i].ptr = (void *)chr;
-                       gatt_values[i].buf = os_msys_get(0, 0);
-                       os_mbuf_extend(gatt_values[i].buf, 1);
-                       ++i;
-
-                       for (dsc = chr->descriptors; dsc && dsc->uuid; dsc++) {
-                               assert(i < SERVER_MAX_VALUES);
-                               gatt_values[i].type = GATT_VALUE_TYPE_DSC;
-                               gatt_values[i].ptr = (void *)dsc;
-                               gatt_values[i].buf = os_msys_get(0, 0);
-                               os_mbuf_extend(gatt_values[i].buf, 1);
-                               ++i;
-                       }
-               }
-       }
+       uint16_t om_len;
+       int rc;
 
-       for (svc = gatt_svr_inc_svcs; svc && svc->uuid; svc++) {
-               for (chr = svc->characteristics; chr && chr->uuid; chr++) {
-                       assert(i < SERVER_MAX_VALUES);
-                       gatt_values[i].type = GATT_VALUE_TYPE_CHR;
-                       gatt_values[i].ptr = (void *)chr;
-                       gatt_values[i].buf = os_msys_get(0, 0);
-                       os_mbuf_extend(gatt_values[i].buf, 1);
-                       ++i;
-
-                       for (dsc = chr->descriptors; dsc && dsc->uuid; dsc++) {
-                               assert(i < SERVER_MAX_VALUES);
-                               gatt_values[i].type = GATT_VALUE_TYPE_DSC;
-                               gatt_values[i].ptr = (void *)dsc;
-                               gatt_values[i].buf = os_msys_get(0, 0);
-                               os_mbuf_extend(gatt_values[i].buf, 1);
-                               ++i;
-                       }
-               }
+       om_len = OS_MBUF_PKTLEN(om);
+       if (om_len < min_len || om_len > max_len) {
+               return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
        }
-}
 
-/* Convert UUID from BTP command to bt_uuid */
-static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
-                       ble_uuid_any_t *bt_uuid)
-{
-       u16_t le16;
-
-       switch (len) {
-       case 0x02: /* UUID 16 */
-               bt_uuid->u.type = BLE_UUID_TYPE_16;
-               memcpy(&le16, uuid, sizeof(le16));
-               BLE_UUID16(bt_uuid)->value = sys_le16_to_cpu(le16);
-               break;
-       case 0x10: /* UUID 128*/
-               bt_uuid->u.type = BLE_UUID_TYPE_128;
-               memcpy(BLE_UUID128(bt_uuid)->value, uuid, 16);
-               break;
-       default:
-               return BTP_STATUS_FAILED;
+       rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
+       if (rc != 0) {
+               return BLE_ATT_ERR_UNLIKELY;
        }
 
-       return BTP_STATUS_SUCCESS;
+       return 0;
 }
 
-static void supported_commands(u8_t *data, u16_t len)
+static uint16_t
+extract_uuid16_from_pts_uuid128(const ble_uuid_t *uuid)
 {
-       u8_t cmds[4];
-       struct gatt_read_supported_commands_rp *rp = (void *) cmds;
-
-       SYS_LOG_DBG("");
-
-       memset(cmds, 0, sizeof(cmds));
-
-       tester_set_bit(cmds, GATT_READ_SUPPORTED_COMMANDS);
-       tester_set_bit(cmds, GATT_ADD_SERVICE);
-       tester_set_bit(cmds, GATT_ADD_CHARACTERISTIC);
-       tester_set_bit(cmds, GATT_ADD_DESCRIPTOR);
-       tester_set_bit(cmds, GATT_ADD_INCLUDED_SERVICE);
-       tester_set_bit(cmds, GATT_SET_VALUE);
-       tester_set_bit(cmds, GATT_START_SERVER);
-       tester_set_bit(cmds, GATT_SET_ENC_KEY_SIZE);
-       tester_set_bit(cmds, GATT_EXCHANGE_MTU);
-       tester_set_bit(cmds, GATT_DISC_ALL_PRIM_SVCS);
-       tester_set_bit(cmds, GATT_DISC_PRIM_UUID);
-       tester_set_bit(cmds, GATT_FIND_INCLUDED);
-       tester_set_bit(cmds, GATT_DISC_ALL_CHRC);
-       tester_set_bit(cmds, GATT_DISC_CHRC_UUID);
-       tester_set_bit(cmds, GATT_DISC_ALL_DESC);
-       tester_set_bit(cmds, GATT_READ);
-       tester_set_bit(cmds, GATT_READ_LONG);
-       tester_set_bit(cmds, GATT_READ_MULTIPLE);
-       tester_set_bit(cmds, GATT_WRITE_WITHOUT_RSP);
-#if 0
-       tester_set_bit(cmds, GATT_SIGNED_WRITE_WITHOUT_RSP);
-#endif
-       tester_set_bit(cmds, GATT_WRITE);
-       tester_set_bit(cmds, GATT_WRITE_LONG);
-       tester_set_bit(cmds, GATT_CFG_NOTIFY);
-       tester_set_bit(cmds, GATT_CFG_INDICATE);
-       tester_set_bit(cmds, GATT_GET_ATTRIBUTES);
-       tester_set_bit(cmds, GATT_GET_ATTRIBUTE_VALUE);
+       const uint8_t *u8ptr;
+       uint16_t uuid16;
 
-       tester_send(BTP_SERVICE_ID_GATT, GATT_READ_SUPPORTED_COMMANDS,
-                   CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
+       u8ptr = BLE_UUID128(uuid)->value;
+       uuid16 = u8ptr[12];
+       uuid16 |= (uint16_t)u8ptr[13] << 8;
+       return uuid16;
 }
 
-enum attr_type {
-    BLE_GATT_ATTR_SVC = 0,
-    BLE_GATT_ATTR_CHR,
-    BLE_GATT_ATTR_DSC,
-};
-
-struct find_attr_data {
-       ble_uuid_any_t *uuid;
-       int attr_type;
-       void *ptr;
-       uint16_t handle;
-};
-
-static void find_attr_by_uuid_cb(const struct ble_gatt_svc_def *svc,
-                                uint16_t handle, uint16_t end_group_handle,
-                                void *arg)
+static int
+gatt_svr_read_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                        struct ble_gatt_access_ctxt *ctxt,
+                        void *arg)
 {
-       struct find_attr_data *foreach = arg;
-       const struct ble_gatt_svc_def **includes;
-       const struct ble_gatt_chr_def *chr;
-       const struct ble_gatt_dsc_def *dsc;
+       uint16_t uuid16;
+       int rc;
 
-       SYS_LOG_DBG("");
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
 
-       if (foreach->attr_type == BLE_GATT_ATTR_SVC &&
-           ble_uuid_cmp(&foreach->uuid->u, svc->uuid) == 0) {
-               foreach->ptr = (void *) svc;
-               foreach->handle = handle;
-               return;
-       }
-       handle += 1;
-
-       if (svc->includes) {
-               for (includes = &svc->includes[0];
-                    *includes != NULL; ++includes) {
-                       handle += 1;
-               }
+       switch (uuid16) {
+               case PTS_CHR_READ_WRITE:
+       if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+               rc = gatt_svr_chr_write(ctxt->om, 0,
+                                       sizeof gatt_svr_pts_static_short_val,
+                                       &gatt_svr_pts_static_short_val, NULL);
+       return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_short_val,
+                                       sizeof gatt_svr_pts_static_short_val);
+       return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       for (chr = svc->characteristics; chr && chr->uuid; ++chr) {
-               if (foreach->attr_type == BLE_GATT_ATTR_CHR &&
-                   ble_uuid_cmp(&foreach->uuid->u, chr->uuid) == 0) {
-                       foreach->ptr = (void *) chr;
-                       foreach->handle = handle;
-                       return;
-               }
-               handle += 2;
-
-               if ((chr->flags & BLE_GATT_CHR_F_NOTIFY) ||
-                   (chr->flags & BLE_GATT_CHR_F_INDICATE)) {
-                       if (foreach->attr_type == BLE_GATT_ATTR_DSC &&
-                           ble_uuid_cmp(&foreach->uuid->u, uuid_ccc) == 0) {
-                               foreach->ptr = (void *) &cccd_def;
-                               foreach->handle = handle;
-                       }
-                       handle += 1;
-               }
-
-               for (dsc = chr->descriptors; dsc && dsc->uuid; ++dsc) {
-                       if (foreach->attr_type == BLE_GATT_ATTR_DSC &&
-                           ble_uuid_cmp(&foreach->uuid->u, dsc->uuid) == 0) {
-                               foreach->ptr = (void *) dsc;
-                               foreach->handle = handle;
-                               return;
-                       }
-                       handle += 1;
-               }
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
 }
 
-static void find_attr_by_handle_cb(const struct ble_gatt_svc_def *svc,
-                                  uint16_t handle, uint16_t end_group_handle,
-                                  void *arg)
+static int
+gatt_svr_read_write_long_test(uint16_t conn_handle, uint16_t attr_handle,
+                             struct ble_gatt_access_ctxt *ctxt,
+                             void *arg)
 {
-       struct find_attr_data *foreach = arg;
-       const struct ble_gatt_svc_def **includes;
-       const struct ble_gatt_chr_def *chr;
-       const struct ble_gatt_dsc_def *dsc;
-
-       SYS_LOG_DBG("");
+       uint16_t uuid16;
+       int rc;
 
-       handle += 1;
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
 
-       if (svc->includes) {
-               for (includes = &svc->includes[0];
-                    *includes != NULL; ++includes) {
-                       handle += 1;
-               }
+       switch (uuid16) {
+       case PTS_LONG_CHR_READ_WRITE:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof 
gatt_svr_pts_static_long_val,
+                                               &gatt_svr_pts_static_long_val, 
NULL);
+               return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
+                                   sizeof gatt_svr_pts_static_long_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+       }
+       case PTS_LONG_CHR_READ_WRITE_ALT:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof 
gatt_svr_pts_static_long_val,
+                                               &gatt_svr_pts_static_long_val, 
NULL);
+                       return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
+                                   sizeof gatt_svr_pts_static_long_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       for (chr = svc->characteristics; chr && chr->uuid; ++chr) {
-               if (handle == foreach->handle) {
-                       foreach->attr_type = BLE_GATT_ATTR_CHR;
-                       foreach->ptr = (void *) chr;
-                       return;
-               }
-               handle += 2;
-
-               if ((chr->flags & BLE_GATT_CHR_F_NOTIFY) ||
-                   (chr->flags & BLE_GATT_CHR_F_INDICATE)) {
-                       handle += 1;
-               }
-
-               for (dsc = chr->descriptors; dsc && dsc->uuid; ++dsc) {
-                       if (handle == foreach->handle) {
-                               foreach->attr_type = BLE_GATT_ATTR_DSC;
-                               foreach->ptr = (void *) dsc;
-                               return;
-                       }
-                       handle += 1;
-               }
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
 }
 
-static void add_service(u8_t *data, u16_t len)
+static int
+gatt_svr_read_write_auth_test(uint16_t conn_handle, uint16_t attr_handle,
+                             struct ble_gatt_access_ctxt *ctxt,
+                             void *arg)
 {
-       const struct gatt_add_service_cmd *cmd = (void *) data;
-       struct gatt_add_service_rp rp;
-       const struct ble_gatt_svc_def *svc;
-       struct find_attr_data find_data;
-       ble_uuid_any_t uuid;
-       int type;
-
-       SYS_LOG_DBG("");
+       uint16_t uuid16;
+       int rc;
 
-       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
-               SYS_LOG_ERR("Invalid service UUID");
-               goto fail;
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
+
+       switch (uuid16) {
+       case PTS_CHR_READ_WRITE_AUTHEN:
+               if (ctxt->op == BLE_GATT_CHR_F_WRITE_AUTHEN) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof gatt_svr_pts_static_val,
+                                               &gatt_svr_pts_static_val, NULL);
+                       return rc;
+       } else if (ctxt->op == BLE_GATT_CHR_F_READ_AUTHEN) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
+                                   sizeof gatt_svr_pts_static_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+       } else if (BLE_GATT_ACCESS_OP_WRITE_CHR) {
+               rc = gatt_svr_chr_write(ctxt->om, 0,
+                                       sizeof gatt_svr_pts_static_val,
+                                       &gatt_svr_pts_static_val, NULL);
+       return rc;
+       } else if (BLE_GATT_ACCESS_OP_READ_CHR) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
+                                   sizeof gatt_svr_pts_static_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       switch (cmd->type) {
-       case GATT_SERVICE_PRIMARY:
-               type = BLE_GATT_SVC_TYPE_PRIMARY;
-               break;
-       case GATT_SERVICE_SECONDARY:
-               type = BLE_GATT_SVC_TYPE_SECONDARY;
-               break;
        default:
-               SYS_LOG_ERR("Invalid service type");
-               goto fail;
-       }
-
-       memset(&find_data, 0, sizeof(find_data));
-
-       find_data.uuid = &uuid;
-       find_data.attr_type = BLE_GATT_ATTR_SVC;
-
-       ble_gatts_lcl_svc_foreach(find_attr_by_uuid_cb, &find_data);
-
-       svc = find_data.ptr;
-       if (svc == NULL) {
-               SYS_LOG_ERR("Could not find service");
-               goto fail;
-       }
-
-       if (type != svc->type) {
-               SYS_LOG_ERR("Service type mismatch");
-               goto fail;
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
-
-       rp.svc_id = find_data.handle;
-
-       tester_send(BTP_SERVICE_ID_GATT, GATT_ADD_SERVICE, CONTROLLER_INDEX,
-                   (u8_t *) &rp, sizeof(rp));
-
-       return;
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_ADD_SERVICE, CONTROLLER_INDEX,
-                  BTP_STATUS_FAILED);
 }
 
-static size_t read_value(uint16_t conn_handle, uint16_t attr_handle,
-                        struct ble_gatt_access_ctxt *ctxt,
-                        void *arg)
+static int
+gatt_svr_read_write_enc_test(uint16_t conn_handle, uint16_t attr_handle,
+                            struct ble_gatt_access_ctxt *ctxt,
+                            void *arg)
 {
-       const struct gatt_value *value = arg;
-       char str[BLE_UUID_STR_LEN];
+       uint16_t uuid16;
        int rc;
 
-       SYS_LOG_DBG("");
-
-       memset(str, '\0', sizeof(str));
-
-       if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
-               if (ctxt->chr->flags & BLE_GATT_CHR_F_READ_AUTHOR) {
-                       return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
-               }
-
-               ble_uuid_to_str(ctxt->chr->uuid, str);
-       } else {
-               if (ctxt->dsc->att_flags & BLE_ATT_F_READ_AUTHOR) {
-                       return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
-               }
-
-               ble_uuid_to_str(ctxt->dsc->uuid, str);
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
+
+       switch (uuid16) {
+       case PTS_CHR_READ_WRITE_ENC:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+                       rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
+                                           sizeof gatt_svr_pts_static_val);
+                       return rc;
+       } else if (ctxt->op == BLE_GATT_CHR_F_READ_ENC) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
+                                   sizeof gatt_svr_pts_static_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+               rc = gatt_svr_chr_write(ctxt->om, 0,
+                                       sizeof gatt_svr_pts_static_val,
+                                       &gatt_svr_pts_static_val, NULL);
+               return rc;
+       } else if (ctxt->op == BLE_GATT_CHR_F_WRITE_ENC) {
+               rc = gatt_svr_chr_write(ctxt->om, 0,
+                                       sizeof gatt_svr_pts_static_val,
+                                       &gatt_svr_pts_static_val, NULL);
+               return rc;
+       }
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
-
-       rc = os_mbuf_appendfrom(ctxt->om, value->buf,
-                               0, os_mbuf_len(value->buf));
-       return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-}
-
-static void attr_value_changed_ev(u16_t handle, struct os_mbuf *data)
-{
-       struct gatt_attr_value_changed_ev *ev;
-       struct os_mbuf *buf = os_msys_get(0, 0);
-
-       SYS_LOG_DBG("");
-
-       net_buf_simple_init(buf, 0);
-       ev = net_buf_simple_add(buf, sizeof(*ev));
-
-       ev->handle = sys_cpu_to_le16(handle);
-       ev->data_length = sys_cpu_to_le16(os_mbuf_len(data));
-       os_mbuf_appendfrom(buf, data, 0, os_mbuf_len(data));
-
-       tester_send_buf(BTP_SERVICE_ID_GATT, GATT_EV_ATTR_VALUE_CHANGED,
-                       CONTROLLER_INDEX, buf);
 }
 
-static size_t write_value(uint16_t conn_handle, uint16_t attr_handle,
-                         struct ble_gatt_access_ctxt *ctxt,
-                         void *arg)
+static int
+gatt_svr_dsc_read_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                            struct ble_gatt_access_ctxt *ctxt,
+                            void *arg)
 {
-       struct gatt_value *value = arg;
-       uint16_t write_len, current_len;
+       uint16_t uuid16;
        int rc;
 
-       SYS_LOG_DBG("");
-
-       if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
-               if (ctxt->chr->flags & BLE_GATT_CHR_F_WRITE_AUTHOR) {
-                       return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
-               }
-       } else {
-               if (ctxt->dsc->att_flags & BLE_ATT_F_WRITE_AUTHOR) {
-                       return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
-               }
-       }
-
-       write_len = os_mbuf_len(ctxt->om);
-       current_len = os_mbuf_len(value->buf);
-
-       SYS_LOG_DBG("current_len = %d", current_len);
-       SYS_LOG_DBG("write_len = %d", write_len);
-       if (write_len > current_len) {
-               return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
+
+       switch (uuid16) {
+       case PTS_DSC_READ_WRITE:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof 
gatt_svr_pts_static_short_val,
+                                               &gatt_svr_pts_static_short_val, 
NULL);
+                       return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_short_val,
+                                   sizeof gatt_svr_pts_static_short_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       os_mbuf_adj(value->buf, -current_len);
-       rc = os_mbuf_appendfrom(value->buf, ctxt->om, 0, write_len);
-       if (rc != 0) {
+       default:
+               assert(0);
                return BLE_ATT_ERR_UNLIKELY;
        }
-
-       attr_value_changed_ev(attr_handle, value->buf);
-
-       return 0;
 }
 
-
-static int gatt_svr_access_cb(uint16_t conn_handle, uint16_t attr_handle,
-                             struct ble_gatt_access_ctxt *ctxt,
-                             void *arg)
-{
-       SYS_LOG_DBG("");
-
-       switch (ctxt->op) {
-               case BLE_GATT_ACCESS_OP_READ_CHR:
-               case BLE_GATT_ACCESS_OP_READ_DSC:
-                       return read_value(conn_handle, attr_handle,
-                                         ctxt, arg);
-               case BLE_GATT_ACCESS_OP_WRITE_CHR:
-               case BLE_GATT_ACCESS_OP_WRITE_DSC:
-                       return write_value(conn_handle, attr_handle,
-                                          ctxt, arg);
-               default:
-                       assert(0);
-                       return BLE_ATT_ERR_UNLIKELY;
-       }
-
-       /* Unknown characteristic; the nimble stack should not have called this
-        * function.
-        */
-       assert(0);
-       return BLE_ATT_ERR_UNLIKELY;
-}
-
-static void add_characteristic(u8_t *data, u16_t len)
+static int
+gatt_svr_dsc_read_write_long_test(uint16_t conn_handle, uint16_t attr_handle,
+                                 struct ble_gatt_access_ctxt *ctxt,
+                                 void *arg)
 {
-       const struct gatt_add_characteristic_cmd *cmd = (void *) data;
-       struct gatt_add_characteristic_rp rp;
-       const struct ble_gatt_chr_def *chr;
-       struct find_attr_data find_data;
-       ble_uuid_any_t uuid;
-       uint16_t flags = 0;
-       int i;
-
-       SYS_LOG_DBG("");
-
-       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
-               SYS_LOG_ERR("Invalid characteristic UUID");
-               goto fail;
-       }
-
-       if (cmd->svc_id) {
-               SYS_LOG_ERR("Characteristic must be added sequentially");
-               goto fail;
-       }
-
-       memset(&find_data, 0, sizeof(find_data));
-
-       find_data.uuid = &uuid;
-       find_data.attr_type = BLE_GATT_ATTR_CHR;
-
-       ble_gatts_lcl_svc_foreach(find_attr_by_uuid_cb, &find_data);
+       uint16_t uuid16;
+       int rc;
 
-       chr = find_data.ptr;
-       if (chr == NULL) {
-               SYS_LOG_ERR("Could not find characteristic");
-               goto fail;
-       }
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
 
-       for (i = 0; i < 8; ++i) {
-               if (cmd->permissions & BIT(i)) {
-                       flags |= gatt_chr_perm_map[i];
-               }
+       switch (uuid16) {
+       case PTS_LONG_DSC_READ_WRITE:
+       if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) {
+               rc = gatt_svr_chr_write(ctxt->om, 0,
+                                       sizeof gatt_svr_pts_static_long_val,
+                                       &gatt_svr_pts_static_long_val, NULL);
+               return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
+                                   sizeof gatt_svr_pts_static_long_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       if ((chr->flags > 0) && ((flags & chr->flags) == 0)) {
-               SYS_LOG_ERR("Invalid flags");
-               goto fail;
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
-
-       rp.char_id = find_data.handle;
-
-       tester_send(BTP_SERVICE_ID_GATT, GATT_ADD_CHARACTERISTIC,
-                   CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
-       return;
-
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_ADD_CHARACTERISTIC,
-                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
 }
 
-static void add_descriptor(u8_t *data, u16_t len)
+static int
+gatt_svr_dsc_read_test(uint16_t conn_handle, uint16_t attr_handle,
+                      struct ble_gatt_access_ctxt *ctxt,
+                      void *arg)
 {
-       const struct gatt_add_descriptor_cmd *cmd = (void *) data;
-       struct gatt_add_descriptor_rp rp;
-       const struct ble_gatt_dsc_def *dsc;
-       struct find_attr_data find_data;
-       ble_uuid_any_t uuid;
-       uint16_t att_flags = 0;
-       int i;
-
-       SYS_LOG_DBG("");
-
-       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
-               SYS_LOG_ERR("Invalid descriptor UUID");
-               goto fail;
-       }
-
-       if (cmd->char_id) {
-               SYS_LOG_ERR("Descriptor must be added sequentially");
-               goto fail;
-       }
-
-       memset(&find_data, 0, sizeof(find_data));
-
-       find_data.uuid = &uuid;
-       find_data.attr_type = BLE_GATT_ATTR_DSC;
-
-       ble_gatts_lcl_svc_foreach(find_attr_by_uuid_cb, &find_data);
-
-       dsc = find_data.ptr;
-       if (dsc == NULL) {
-               SYS_LOG_ERR("Could not find descriptor");
-               goto fail;
-       }
+       uint16_t uuid16;
+       int rc;
 
-       att_flags = cmd->permissions;
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
 
-       for (i = 0; i < 8; ++i) {
-               if (cmd->permissions & BIT(i)) {
-                       att_flags |= gatt_dsc_perm_map[i];
-               }
+       switch (uuid16) {
+       case PTS_DSC_READ:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
+                       rc = os_mbuf_append(ctxt->om, 
&gatt_svr_pts_static_long_val,
+                                           sizeof 
gatt_svr_pts_static_long_val);
+                       return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
        }
-
-       if ((att_flags & dsc->att_flags) == 0) {
-               SYS_LOG_ERR("Invalid flags");
-               goto fail;
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
-
-       rp.desc_id = find_data.handle;
-
-       tester_send(BTP_SERVICE_ID_GATT, GATT_ADD_DESCRIPTOR, CONTROLLER_INDEX,
-                   (u8_t *) &rp, sizeof(rp));
-       return;
-
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_ADD_DESCRIPTOR,
-                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
 }
 
-static void add_included(u8_t *data, u16_t len)
+static int
+gatt_svr_write_no_rsp_test(uint16_t conn_handle, uint16_t attr_handle,
+                          struct ble_gatt_access_ctxt *ctxt,
+                          void *arg)
 {
-       const struct gatt_add_included_service_cmd *cmd = (void *) data;
-       struct gatt_add_included_service_rp rp;
-       u16_t included_service_id = 0;
-
-       included_service_id = cmd->svc_id;
+       uint16_t uuid16;
+       int rc;
 
-       rp.included_service_id = sys_cpu_to_le16(included_service_id);
-       tester_send(BTP_SERVICE_ID_GATT, GATT_ADD_INCLUDED_SERVICE,
-                   CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
+
+       switch (uuid16) {
+       case PTS_CHR_WRITE_NO_RSP:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof 
gatt_svr_pts_static_short_val,
+                                               &gatt_svr_pts_static_short_val, 
NULL);
+                       return rc;
+       } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+               rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_short_val,
+                                   sizeof gatt_svr_pts_static_short_val);
+               return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+       }
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
+       }
 }
 
-static void set_value(u8_t *data, u16_t len)
+static int
+gatt_svr_rel_write_test(uint16_t conn_handle, uint16_t attr_handle,
+                       struct ble_gatt_access_ctxt *ctxt,
+                       void *arg)
 {
-       const struct gatt_set_value_cmd *cmd = (void *) data;
-       const struct ble_gatt_chr_def *chr;
-       struct find_attr_data find_data;
-       struct gatt_value *gatt_value = NULL;
-       u16_t value_len;
-       const u8_t *value;
-
-       SYS_LOG_DBG("%d id", cmd->attr_id);
-
-       memset(&find_data, 0, sizeof(find_data));
-
-       find_data.handle = sys_le16_to_cpu(cmd->attr_id);
-
-       ble_gatts_lcl_svc_foreach(find_attr_by_handle_cb, &find_data);
+       uint16_t uuid16;
+       int rc;
 
-       if (find_data.ptr == NULL) {
-               SYS_LOG_ERR("Could not find attribute");
-               goto fail;
-       }
+       uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
+       assert(uuid16 != 0);
 
-       if (find_data.attr_type == BLE_GATT_ATTR_CHR) {
-               gatt_value = ((struct ble_gatt_chr_def *)find_data.ptr)->arg;
-       } else if (find_data.attr_type == BLE_GATT_ATTR_DSC) {
-               gatt_value = ((struct ble_gatt_dsc_def *)find_data.ptr)->arg;
+       switch (uuid16) {
+       case PTS_CHR_RELIABLE_WRITE:
+               if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+                       rc = gatt_svr_chr_write(ctxt->om, 0,
+                                               sizeof gatt_svr_pts_static_val,
+                                               &gatt_svr_pts_static_val, NULL);
+                       return rc;
        }
 
-       assert(gatt_value != NULL);
-
-       value_len = sys_le16_to_cpu(cmd->len);
-       value = cmd->value;
-
-       os_mbuf_adj(gatt_value->buf, - os_mbuf_len(gatt_value->buf));
-       os_mbuf_append(gatt_value->buf, value, value_len);
-
-       SYS_LOG_DBG("os_mbuf_len = %d", os_mbuf_len(gatt_value->buf));
-
-       if (gatt_value->type == GATT_VALUE_TYPE_CHR) {
-               chr = gatt_value->ptr;
-               if (chr->flags & BLE_GATT_CHR_F_INDICATE ||
-                   chr->flags & BLE_GATT_CHR_F_NOTIFY) {
-                       ble_gatts_chr_updated(*chr->val_handle);
-               }
+       default:
+               assert(0);
+               return BLE_ATT_ERR_UNLIKELY;
        }
-
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_SET_VALUE, CONTROLLER_INDEX,
-                  BTP_STATUS_SUCCESS);
-       return;
-
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_SET_VALUE,
-                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
 }
 
 static void start_server(u8_t *data, u16_t len)
@@ -909,79 +558,115 @@ static void start_server(u8_t *data, u16_t len)
                    (u8_t *) &rp, sizeof(rp));
 }
 
-static void set_enc_key_size(u8_t *data, u16_t len)
+/* Convert UUID from BTP command to bt_uuid */
+static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
+                       ble_uuid_any_t *bt_uuid)
 {
-       const struct gatt_set_enc_key_size_cmd *cmd = (void *) data;
-       struct find_attr_data find_data;
-       struct gatt_value *val = NULL;
-       u8_t status = BTP_STATUS_SUCCESS;
+       u16_t le16;
 
-       /* Fail if requested key size is invalid */
-       if (cmd->key_size < 0x07 || cmd->key_size > 0x0f) {
-               status = BTP_STATUS_FAILED;
-               goto done;
+       switch (len) {
+       case 0x02: /* UUID 16 */
+               bt_uuid->u.type = BLE_UUID_TYPE_16;
+               memcpy(&le16, uuid, sizeof(le16));
+               BLE_UUID16(bt_uuid)->value = sys_le16_to_cpu(le16);
+               break;
+       case 0x10: /* UUID 128*/
+               bt_uuid->u.type = BLE_UUID_TYPE_128;
+               memcpy(BLE_UUID128(bt_uuid)->value, uuid, 16);
+       break;
+       default:
+               return BTP_STATUS_FAILED;
        }
+       return BTP_STATUS_SUCCESS;
+}
 
-       memset(&find_data, 0, sizeof(find_data));
-
-       find_data.handle = sys_le16_to_cpu(cmd->attr_id);
+/*
+ * gatt_buf - cache used by a gatt client (to cache data read/discovered)
+ * and gatt server (to store attribute user_data).
+ * It is not intended to be used by client and server at the same time.
+ */
+static struct {
+       u16_t len;
+       u8_t buf[MAX_BUFFER_SIZE];
+} gatt_buf;
 
-       ble_gatts_lcl_svc_foreach(find_attr_by_handle_cb, &find_data);
+static void *gatt_buf_add(const void *data, size_t len)
+{
+       void *ptr = gatt_buf.buf + gatt_buf.len;
 
-       if (find_data.ptr == NULL) {
-               SYS_LOG_ERR("Could not find attribute");
-               status = BTP_STATUS_FAILED;
-               goto done;
+       if ((len + gatt_buf.len) > MAX_BUFFER_SIZE) {
+               return NULL;
        }
 
-       if (find_data.attr_type == BLE_GATT_ATTR_CHR) {
-               val = ((struct ble_gatt_chr_def *)find_data.ptr)->arg;
-       } else if (find_data.attr_type == BLE_GATT_ATTR_DSC) {
-               val = ((struct ble_gatt_dsc_def *)find_data.ptr)->arg;
+       if (data) {
+               memcpy(ptr, data, len);
+       } else {
+               (void)memset(ptr, 0, len);
        }
 
-       assert(val != NULL);
-       assert(val->ptr != NULL);
+       gatt_buf.len += len;
 
-       switch(val->type) {
-       case GATT_VALUE_TYPE_CHR:
-               ((struct ble_gatt_chr_def *) val->ptr)->min_key_size =
-                       cmd->key_size;
-               break;
-       case GATT_VALUE_TYPE_DSC:
-               ((struct ble_gatt_dsc_def *) val->ptr)->min_key_size =
-                       cmd->key_size;
-               break;
-       default:
-               break;
-       }
+       SYS_LOG_DBG("%d/%d used", gatt_buf.len, MAX_BUFFER_SIZE);
 
-done:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_SET_ENC_KEY_SIZE, CONTROLLER_INDEX,
-                  status);
+       return ptr;
 }
 
-static int exchange_func(uint16_t conn_handle,
-                        const struct ble_gatt_error *error,
-                        uint16_t mtu, void *arg)
+static void *gatt_buf_reserve(size_t len)
 {
-       SYS_LOG_DBG("");
+       return gatt_buf_add(NULL, len);
+}
+
+static void gatt_buf_clear(void)
+{
+       (void)memset(&gatt_buf, 0, sizeof(gatt_buf));
+}
+
+static void discover_destroy(void)
+{
+       gatt_buf_clear();
+}
+
+static void read_destroy()
+{
+       gatt_buf_clear();
+}
+
+static int read_cb(uint16_t conn_handle,
+                  const struct ble_gatt_error *error,
+                  struct ble_gatt_attr *attr,
+                  void *arg)
+{
+       struct gatt_read_rp *rp = (void *) gatt_buf.buf;
+       u8_t btp_opcode = (uint8_t) (int) arg;
+
+       SYS_LOG_DBG("status=%d", error->status);
 
-       if (error->status) {
-               tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
+       if (error->status != 0 && error->status != BLE_HS_EDONE) {
+               rp->att_response = (uint8_t) BLE_HS_ATT_ERR(error->status);
+               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+               read_destroy();
+               return 0;
+}
 
+       if (!gatt_buf_add(attr->om->om_data, attr->om->om_len)) {
+               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
+               CONTROLLER_INDEX, BTP_STATUS_FAILED);
+               read_destroy();
                return 0;
        }
 
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU, CONTROLLER_INDEX,
-                  BTP_STATUS_SUCCESS);
+       rp->data_length += attr->om->om_len;
+       tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+       CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+       read_destroy();
 
        return 0;
 }
 
-static void exchange_mtu(u8_t *data, u16_t len)
+static void read(u8_t *data, u16_t len)
 {
+       const struct gatt_read_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
        int rc;
 
@@ -992,72 +677,63 @@ static void exchange_mtu(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (ble_gattc_exchange_mtu(conn.conn_handle, exchange_func, NULL)) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
                goto fail;
        }
 
-       return;
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU,
-                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
-}
+       if (ble_gattc_read(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
+                          read_cb, (void *)GATT_READ)) {
+               discover_destroy();
+               goto fail;
+       }
 
+       return;
 
-static void discover_destroy(void)
-{
-       gatt_buf_clear();
+fail:
+tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ, CONTROLLER_INDEX,
+          BTP_STATUS_FAILED);
 }
 
-static int disc_prim_uuid_cb(uint16_t conn_handle,
-                            const struct ble_gatt_error *error,
-                            const struct ble_gatt_svc *gatt_svc, void *arg)
+static int read_long_cb(uint16_t conn_handle,
+                       const struct ble_gatt_error *error,
+                       struct ble_gatt_attr *attr,
+                       void *arg)
 {
-       struct gatt_disc_prim_uuid_rp *rp = (void *) gatt_buf.buf;
-       struct gatt_service *service;
-       const ble_uuid_any_t *uuid;
-       u8_t uuid_length;
-       u8_t opcode = (u8_t) (int) arg;
+       struct gatt_read_rp *rp = (void *) gatt_buf.buf;
+       u8_t btp_opcode = (uint8_t) (int) arg;
 
-       SYS_LOG_DBG("");
+       SYS_LOG_DBG("status=%d", error->status);
 
-       if (error->status != 0) {
-               tester_send(BTP_SERVICE_ID_GATT, opcode,
+       if (error->status != 0 && error->status != BLE_HS_EDONE) {
+               rp->att_response = (uint8_t) BLE_HS_ATT_ERR(error->status);
+               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
                            CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               discover_destroy();
+               read_destroy();
                return 0;
        }
 
-       uuid = &gatt_svc->uuid;
-       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
-
-       service = gatt_buf_reserve(sizeof(*service) + uuid_length);
-       if (!service) {
-               tester_rsp(BTP_SERVICE_ID_GATT, opcode,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
-               discover_destroy();
-               return BLE_HS_EDONE;
+       if (error->status == BLE_HS_EDONE) {
+               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+               read_destroy();
+               return 0;
        }
 
-       service->start_handle = sys_cpu_to_le16(gatt_svc->start_handle);
-       service->end_handle = sys_cpu_to_le16(gatt_svc->end_handle);
-       service->uuid_length = uuid_length;
-
-       if (uuid->u.type == BLE_UUID_TYPE_16) {
-               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
-
-               memcpy(service->uuid, &u16, uuid_length);
-       } else {
-               memcpy(service->uuid, BLE_UUID128(uuid)->value,
-                      uuid_length);
+       if (gatt_buf_add(attr->om->om_data, attr->om->om_len) == NULL) {
+               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
+                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
+               read_destroy();
+               return 0;
        }
 
-       rp->services_count++;
+       rp->data_length += attr->om->om_len;
 
        return 0;
 }
 
-static void disc_all_prim_svcs(u8_t *data, u16_t len)
+static void read_long(u8_t *data, u16_t len)
 {
+       const struct gatt_read_long_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
        int rc;
 
@@ -1068,13 +744,14 @@ static void disc_all_prim_svcs(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_disc_all_prim_svcs_rp))) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
                goto fail;
        }
 
-       if (ble_gattc_disc_all_svcs(conn.conn_handle,
-                                   disc_prim_uuid_cb,
-                                   (void *) GATT_DISC_ALL_PRIM_SVCS)) {
+       if (ble_gattc_read_long(conn.conn_handle,
+                               sys_le16_to_cpu(cmd->handle),
+                               sys_le16_to_cpu(cmd->offset),
+                               read_long_cb, (void *)GATT_READ_LONG)) {
                discover_destroy();
                goto fail;
        }
@@ -1082,104 +759,88 @@ static void disc_all_prim_svcs(u8_t *data, u16_t len)
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_PRIM_SVCS,
-                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ_LONG, CONTROLLER_INDEX,
+                  BTP_STATUS_FAILED);
 }
 
-static void disc_prim_uuid(u8_t *data, u16_t len)
+static void read_multiple(u8_t *data, u16_t len)
 {
-       const struct gatt_disc_prim_uuid_cmd *cmd = (void *) data;
+       const struct gatt_read_multiple_cmd *cmd = (void *) data;
+       u16_t handles[cmd->handles_count];
        struct ble_gap_conn_desc conn;
-       ble_uuid_any_t uuid;
-       int rc;
+       int rc, i;
 
        SYS_LOG_DBG("");
 
-       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
-       if (rc) {
-               goto fail;
+       for (i = 0; i < ARRAY_SIZE(handles); i++) {
+               handles[i] = sys_le16_to_cpu(cmd->handles[i]);
        }
 
-       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
+       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
+       if (rc) {
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_disc_prim_uuid_rp))) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
                goto fail;
        }
 
-       if (ble_gattc_disc_svc_by_uuid(conn.conn_handle,
-                                      &uuid.u, disc_prim_uuid_cb,
-                                      (void *) GATT_DISC_PRIM_UUID)) {
+       if (ble_gattc_read_mult(conn.conn_handle, handles,
+               cmd->handles_count, read_cb, (void *)GATT_READ_MULTIPLE)) {
                discover_destroy();
                goto fail;
-       }
+}
 
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_PRIM_UUID, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ_MULTIPLE, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static int find_included_cb(uint16_t conn_handle,
-                           const struct ble_gatt_error *error,
-                           const struct ble_gatt_svc *gatt_svc, void *arg)
+static void write_without_rsp(u8_t *data, u16_t len, u8_t op, bool sign)
 {
-       struct gatt_find_included_rp *rp = (void *) gatt_buf.buf;
-       struct gatt_included *included;
-       const ble_uuid_any_t *uuid;
-       int service_handle = (int) arg;
-       u8_t uuid_length;
+       const struct gatt_write_without_rsp_cmd *cmd = (void *) data;
+       struct ble_gap_conn_desc conn;
+       u8_t status = BTP_STATUS_SUCCESS;
+       int rc;
 
        SYS_LOG_DBG("");
 
-       if (error->status != 0) {
-               tester_send(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED,
-                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               discover_destroy();
-               return 0;
+       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
+       if (rc) {
+               status = BTP_STATUS_FAILED;
+               goto rsp;
        }
 
-       uuid = &gatt_svc->uuid;
-       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
-
-
-       included = gatt_buf_reserve(sizeof(*included) + uuid_length);
-       if (!included) {
-               tester_rsp(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
-               discover_destroy();
-               return BLE_HS_EDONE;
+       if (ble_gattc_write_no_rsp_flat(conn.conn_handle,
+                                       sys_le16_to_cpu(cmd->handle), cmd->data,
+                                       sys_le16_to_cpu(cmd->data_length))) {
+               status = BTP_STATUS_FAILED;
        }
 
-       /* FIXME */
-       included->included_handle = sys_cpu_to_le16(service_handle + 1 +
-                                                   rp->services_count);
-       included->service.start_handle = 
sys_cpu_to_le16(gatt_svc->start_handle);
-       included->service.end_handle = sys_cpu_to_le16(gatt_svc->end_handle);
-       included->service.uuid_length = uuid_length;
-
-       if (uuid->u.type == BLE_UUID_TYPE_16) {
-               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+rsp:
+       tester_rsp(BTP_SERVICE_ID_GATT, op, CONTROLLER_INDEX, status);
+}
 
-               memcpy(included->service.uuid, &u16, uuid_length);
-       } else {
-               memcpy(included->service.uuid, BLE_UUID128(uuid)->value,
-                      uuid_length);
-       }
+static int write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error,
+                    struct ble_gatt_attr *attr,
+                    void *arg)
+{
+       uint8_t err = (uint8_t) error->status;
+       u8_t btp_opcode = (uint8_t) (int) arg;
 
-       rp->services_count++;
+       SYS_LOG_DBG("");
 
+       tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+                   CONTROLLER_INDEX, &err, sizeof(err));
        return 0;
 }
 
-static void find_included(u8_t *data, u16_t len)
+static void write(u8_t *data, u16_t len)
 {
-       const struct gatt_find_included_cmd *cmd = (void *) data;
+       const struct gatt_write_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       uint16_t start_handle, end_handle;
-       int service_handle_arg;
        int rc;
 
        SYS_LOG_DBG("");
@@ -1189,119 +850,121 @@ static void find_included(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_find_included_rp))) {
-               goto fail;
-       }
-
-       start_handle = sys_le16_to_cpu(cmd->start_handle);
-       end_handle = sys_le16_to_cpu(cmd->end_handle);
-       service_handle_arg = start_handle;
-
-       if (ble_gattc_find_inc_svcs(conn.conn_handle, start_handle, end_handle,
-                                   find_included_cb,
-                                   (void *)service_handle_arg)) {
-               discover_destroy();
+       if (ble_gattc_write_flat(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
+                                cmd->data, sys_le16_to_cpu(cmd->data_length),
+                                write_rsp, (void *) GATT_WRITE)) {
                goto fail;
        }
 
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static int disc_chrc_cb(uint16_t conn_handle,
-                       const struct ble_gatt_error *error,
-                       const struct ble_gatt_chr *gatt_chr, void *arg)
+static void write_long(u8_t *data, u16_t len)
 {
-       struct gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf;
-       struct gatt_characteristic *chrc;
-       const ble_uuid_any_t *uuid;
-       u8_t btp_opcode = (uint8_t) (int) arg;
-       u8_t uuid_length;
+       const struct gatt_write_long_cmd *cmd = (void *) data;
+       struct ble_gap_conn_desc conn;
+       struct os_mbuf *om = NULL;
+       int rc;
 
        SYS_LOG_DBG("");
 
-       if (error->status != 0) {
-               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
-                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               discover_destroy();
-               return 0;
+       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
+       if (rc) {
+               goto fail;
        }
 
-       uuid = &gatt_chr->uuid;
-       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
+       om = ble_hs_mbuf_from_flat(cmd->data, 
sys_le16_to_cpu(cmd->data_length));
 
-       chrc = gatt_buf_reserve(sizeof(*chrc) + uuid_length);
-       if (!chrc) {
-               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
-               discover_destroy();
-               return BLE_HS_EDONE;
+       if (!om) {
+               SYS_LOG_ERR("Insufficient resources");
+               goto fail;
        }
 
-       chrc->characteristic_handle = sys_cpu_to_le16(gatt_chr->def_handle);
-       chrc->properties = gatt_chr->properties;
-       chrc->value_handle = sys_cpu_to_le16(gatt_chr->val_handle);
-       chrc->uuid_length = uuid_length;
+       if (ble_gattc_write_long(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
+                                sys_le16_to_cpu(cmd->offset), om, write_rsp,
+                                (void *) GATT_WRITE_LONG)) {
+               goto fail;
+}
 
-       if (uuid->u.type == BLE_UUID_TYPE_16) {
-               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+       return;
 
-               memcpy(chrc->uuid, &u16, uuid_length);
-       } else {
-               memcpy(chrc->uuid, BLE_UUID128(uuid)->value,
-                      uuid_length);
-       }
+fail:
+       os_mbuf_free_chain(om);
 
-       rp->characteristics_count++;
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE_LONG, CONTROLLER_INDEX,
+                  BTP_STATUS_FAILED);
+}
+
+static int reliable_write_rsp(uint16_t conn_handle,
+                             const struct ble_gatt_error *error,
+                             struct ble_gatt_attr *attrs,
+                             uint8_t num_attrs,
+                             void *arg)
+{
+       uint8_t err = (uint8_t) error->status;
 
+       SYS_LOG_DBG("Reliable write status %d", err);
+
+       tester_send(BTP_SERVICE_ID_GATT, GATT_RELIABLE_WRITE,
+                   CONTROLLER_INDEX, &err, sizeof(err));
        return 0;
 }
 
-static void disc_all_chrc(u8_t *data, u16_t len)
+static void reliable_write(u8_t *data, u16_t len)
 {
-       const struct gatt_disc_all_chrc_cmd *cmd = (void *) data;
+       const struct gatt_reliable_write_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       uint16_t start_handle, end_handle;
+       struct ble_gatt_attr attr;
+       struct os_mbuf *om = NULL;
        int rc;
 
        SYS_LOG_DBG("");
 
        rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
        if (rc) {
-               SYS_LOG_DBG("Conn find failed");
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_disc_chrc_rp))) {
-               SYS_LOG_DBG("Buf reserve failed");
+       om = ble_hs_mbuf_from_flat(cmd->data, 
sys_le16_to_cpu(cmd->data_length));
+       /* This is required, because Nimble checks if
+       * the data is longer than offset
+       */
+       if (os_mbuf_extend(om, sys_le16_to_cpu(cmd->offset) + 1) == NULL) {
                goto fail;
        }
 
-       start_handle = sys_le16_to_cpu(cmd->start_handle);
-       end_handle = sys_le16_to_cpu(cmd->end_handle);
+       attr.handle = sys_le16_to_cpu(cmd->handle);
+       attr.offset = sys_le16_to_cpu(cmd->offset);
+       attr.om = om;
 
-       rc = ble_gattc_disc_all_chrs(conn.conn_handle, start_handle, end_handle,
-                                    disc_chrc_cb, (void *)GATT_DISC_ALL_CHRC);
-       if (rc) {
-               discover_destroy();
+       if (ble_gattc_write_reliable(conn.conn_handle, &attr, 1,
+                                    reliable_write_rsp, NULL)) {
                goto fail;
        }
 
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_CHRC, CONTROLLER_INDEX,
+       os_mbuf_free_chain(om);
+
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE_LONG, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static void disc_chrc_uuid(u8_t *data, u16_t len)
+static struct bt_gatt_subscribe_params {
+       u16_t ccc_handle;
+       u16_t value;
+       u16_t value_handle;
+} subscribe_params;
+
+static void read_uuid(u8_t *data, u16_t len)
 {
-       const struct gatt_disc_chrc_uuid_cmd *cmd = (void *) data;
+       const struct gatt_read_uuid_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       uint16_t start_handle, end_handle;
        ble_uuid_any_t uuid;
        int rc;
 
@@ -1316,16 +979,14 @@ static void disc_chrc_uuid(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_disc_chrc_rp))) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
                goto fail;
        }
 
-       start_handle = sys_le16_to_cpu(cmd->start_handle);
-       end_handle = sys_le16_to_cpu(cmd->end_handle);
-
-       if (ble_gattc_disc_chrs_by_uuid(conn.conn_handle, start_handle,
-                                       end_handle, &uuid.u, disc_chrc_cb,
-                                       (void *)GATT_DISC_CHRC_UUID)) {
+       if (ble_gattc_read_by_uuid(conn.conn_handle,
+                                  sys_le16_to_cpu(cmd->start_handle),
+                                  sys_le16_to_cpu(cmd->end_handle), &uuid.u,
+                                  read_long_cb, (void *)GATT_READ_UUID)) {
                discover_destroy();
                goto fail;
        }
@@ -1333,207 +994,106 @@ static void disc_chrc_uuid(u8_t *data, u16_t len)
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_CHRC_UUID, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static int disc_all_desc_cb(uint16_t conn_handle,
-                           const struct ble_gatt_error *error,
-                           uint16_t chr_val_handle,
-                           const struct ble_gatt_dsc *gatt_dsc,
-                           void *arg)
+static int disc_prim_uuid_cb(uint16_t conn_handle,
+                            const struct ble_gatt_error *error,
+                            const struct ble_gatt_svc *gatt_svc, void *arg)
 {
-       struct gatt_disc_all_desc_rp *rp = (void *) gatt_buf.buf;
-       struct gatt_descriptor *dsc;
+       struct gatt_disc_prim_uuid_rp *rp = (void *) gatt_buf.buf;
+       struct gatt_service *service;
        const ble_uuid_any_t *uuid;
        u8_t uuid_length;
+       u8_t opcode = (u8_t) (int) arg;
 
        SYS_LOG_DBG("");
 
        if (error->status != 0) {
-               tester_send(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC,
-                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+               tester_send(BTP_SERVICE_ID_GATT, opcode,
+               CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
                discover_destroy();
                return 0;
        }
 
-       uuid = &gatt_dsc->uuid;
+       uuid = &gatt_svc->uuid;
        uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
 
-       dsc = gatt_buf_reserve(sizeof(*dsc) + uuid_length);
-       if (!dsc) {
-               tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
+       service = gatt_buf_reserve(sizeof(*service) + uuid_length);
+       if (!service) {
+               tester_rsp(BTP_SERVICE_ID_GATT, opcode,
+               CONTROLLER_INDEX, BTP_STATUS_FAILED);
                discover_destroy();
                return BLE_HS_EDONE;
        }
 
-       dsc->descriptor_handle = sys_cpu_to_le16(gatt_dsc->handle);
-       dsc->uuid_length = uuid_length;
+       service->start_handle = sys_cpu_to_le16(gatt_svc->start_handle);
+       service->end_handle = sys_cpu_to_le16(gatt_svc->end_handle);
+       service->uuid_length = uuid_length;
 
        if (uuid->u.type == BLE_UUID_TYPE_16) {
                u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
-
-               memcpy(dsc->uuid, &u16, uuid_length);
+               memcpy(service->uuid, &u16, uuid_length);
        } else {
-               memcpy(dsc->uuid, BLE_UUID128(uuid)->value,
-                      uuid_length);
+               memcpy(service->uuid, BLE_UUID128(uuid)->value,
+               uuid_length);
        }
 
-       rp->descriptors_count++;
+       rp->services_count++;
 
        return 0;
 }
 
-static void disc_all_desc(u8_t *data, u16_t len)
+static int disc_all_desc_cb(uint16_t conn_handle,
+                           const struct ble_gatt_error *error,
+                           uint16_t chr_val_handle,
+                           const struct ble_gatt_dsc *gatt_dsc,
+                           void *arg)
 {
-       const struct gatt_disc_all_desc_cmd *cmd = (void *) data;
-       struct ble_gap_conn_desc conn;
-       uint16_t start_handle, end_handle;
-       int rc;
+       struct gatt_disc_all_desc_rp *rp = (void *) gatt_buf.buf;
+       struct gatt_descriptor *dsc;
+       const ble_uuid_any_t *uuid;
+       u8_t uuid_length;
 
        SYS_LOG_DBG("");
 
-       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
-       if (rc) {
-               goto fail;
-       }
-
-       if (!gatt_buf_reserve(sizeof(struct gatt_disc_all_desc_rp))) {
-               goto fail;
-       }
-
-       start_handle = sys_le16_to_cpu(cmd->start_handle) - 1;
-       end_handle = sys_le16_to_cpu(cmd->end_handle);
-
-       rc = ble_gattc_disc_all_dscs(conn.conn_handle, start_handle, end_handle,
-                                    disc_all_desc_cb, NULL);
-
-       SYS_LOG_DBG("rc=%d", rc);
-
-       if (rc) {
-               discover_destroy();
-               goto fail;
-       }
-
-       return;
-
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC, CONTROLLER_INDEX,
-                  BTP_STATUS_FAILED);
-}
-
-static void read_destroy(void)
-{
-       gatt_buf_clear();
-}
-
-static int read_cb(uint16_t conn_handle,
-                  const struct ble_gatt_error *error,
-                  struct ble_gatt_attr *attr,
-                  void *arg)
-{
-       struct gatt_read_rp *rp = (void *) gatt_buf.buf;
-       u8_t btp_opcode = (uint8_t) (int) arg;
-
-       SYS_LOG_DBG("status=%d", error->status);
-
-       if (error->status != 0 && error->status != BLE_HS_EDONE) {
-               rp->att_response = (uint8_t) BLE_HS_ATT_ERR(error->status);
-               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
-                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               read_destroy();
-               return 0;
-       }
-
-       if (!gatt_buf_add(attr->om->om_data, attr->om->om_len)) {
-               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
-                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
-               read_destroy();
-               return 0;
-       }
-
-       rp->data_length += attr->om->om_len;
-
-       tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
-                   CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-       read_destroy();
-
-       return 0;
-}
-
-static int read_long_cb(uint16_t conn_handle,
-                       const struct ble_gatt_error *error,
-                       struct ble_gatt_attr *attr,
-                       void *arg)
-{
-       struct gatt_read_rp *rp = (void *) gatt_buf.buf;
-       u8_t btp_opcode = (uint8_t) (int) arg;
-
-       SYS_LOG_DBG("status=%d", error->status);
-
-       if (error->status != 0 && error->status != BLE_HS_EDONE) {
-               rp->att_response = (uint8_t) BLE_HS_ATT_ERR(error->status);
-               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+       if (error->status != 0) {
+               tester_send(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC,
                            CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               read_destroy();
+               discover_destroy();
                return 0;
        }
 
-       if (error->status == BLE_HS_EDONE) {
-               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
-                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
-               read_destroy();
-               return 0;
-       }
+       uuid = &gatt_dsc->uuid;
+       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
 
-       if (gatt_buf_add(attr->om->om_data, attr->om->om_len) == NULL) {
-               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
+       dsc = gatt_buf_reserve(sizeof(*dsc) + uuid_length);
+       if (!dsc) {
+               tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC,
                           CONTROLLER_INDEX, BTP_STATUS_FAILED);
-               read_destroy();
-               return 0;
-       }
-
-       rp->data_length += attr->om->om_len;
-
-       return 0;
-}
-
-static void read(u8_t *data, u16_t len)
-{
-       const struct gatt_read_cmd *cmd = (void *) data;
-       struct ble_gap_conn_desc conn;
-       int rc;
-
-       SYS_LOG_DBG("");
-
-       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
-       if (rc) {
-               goto fail;
+               discover_destroy();
+               return BLE_HS_EDONE;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
-               goto fail;
-       }
+       dsc->descriptor_handle = sys_cpu_to_le16(gatt_dsc->handle);
+       dsc->uuid_length = uuid_length;
 
-       if (ble_gattc_read(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
-                          read_cb, (void *)GATT_READ)) {
-               discover_destroy();
-               goto fail;
+       if (uuid->u.type == BLE_UUID_TYPE_16) {
+               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+               memcpy(dsc->uuid, &u16, uuid_length);
+       } else {
+               memcpy(dsc->uuid, BLE_UUID128(uuid)->value, uuid_length);
        }
 
-       return;
+       rp->descriptors_count++;
 
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ, CONTROLLER_INDEX,
-                  BTP_STATUS_FAILED);
+       return 0;
 }
 
-static void read_uuid(u8_t *data, u16_t len)
+static void disc_all_prim_svcs(u8_t *data, u16_t len)
 {
-       const struct gatt_read_uuid_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       ble_uuid_any_t uuid;
        int rc;
 
        SYS_LOG_DBG("");
@@ -1543,19 +1103,12 @@ static void read_uuid(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
-               goto fail;
-       }
-
-       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_disc_all_prim_svcs_rp))) {
                goto fail;
        }
 
-       if (ble_gattc_read_by_uuid(conn.conn_handle,
-                                  sys_le16_to_cpu(cmd->start_handle),
-                                  sys_le16_to_cpu(cmd->end_handle),
-                                  &uuid.u,
-                                  read_long_cb, (void *)GATT_READ_UUID)) {
+       if (ble_gattc_disc_all_svcs(conn.conn_handle, disc_prim_uuid_cb,
+                                   (void *) GATT_DISC_ALL_PRIM_SVCS)) {
                discover_destroy();
                goto fail;
        }
@@ -1563,14 +1116,15 @@ static void read_uuid(u8_t *data, u16_t len)
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ, CONTROLLER_INDEX,
-                  BTP_STATUS_FAILED);
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_PRIM_SVCS,
+                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
 }
 
-static void read_long(u8_t *data, u16_t len)
+static void disc_all_desc(u8_t *data, u16_t len)
 {
-       const struct gatt_read_long_cmd *cmd = (void *) data;
+       const struct gatt_disc_all_desc_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
+       uint16_t start_handle, end_handle;
        int rc;
 
        SYS_LOG_DBG("");
@@ -1580,14 +1134,19 @@ static void read_long(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_disc_all_desc_rp))) {
                goto fail;
        }
 
-       if (ble_gattc_read_long(conn.conn_handle,
-                               sys_le16_to_cpu(cmd->handle),
-                               sys_le16_to_cpu(cmd->offset),
-                               read_long_cb, (void *)GATT_READ_LONG)) {
+       start_handle = sys_le16_to_cpu(cmd->start_handle) - 1;
+       end_handle = sys_le16_to_cpu(cmd->end_handle);
+
+       rc = ble_gattc_disc_all_dscs(conn.conn_handle, start_handle, end_handle,
+       disc_all_desc_cb, NULL);
+
+       SYS_LOG_DBG("rc=%d", rc);
+
+       if (rc) {
                discover_destroy();
                goto fail;
        }
@@ -1595,93 +1154,115 @@ static void read_long(u8_t *data, u16_t len)
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ_LONG, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_DESC, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static void read_multiple(u8_t *data, u16_t len)
+static int find_included_cb(uint16_t conn_handle,
+                           const struct ble_gatt_error *error,
+                           const struct ble_gatt_svc *gatt_svc, void *arg)
 {
-       const struct gatt_read_multiple_cmd *cmd = (void *) data;
-       u16_t handles[cmd->handles_count];
-       struct ble_gap_conn_desc conn;
-       int rc, i;
+       struct gatt_find_included_rp *rp = (void *) gatt_buf.buf;
+       struct gatt_included *included;
+       const ble_uuid_any_t *uuid;
+       int service_handle = (int) arg;
+       u8_t uuid_length;
 
        SYS_LOG_DBG("");
 
-       for (i = 0; i < ARRAY_SIZE(handles); i++) {
-               handles[i] = sys_le16_to_cpu(cmd->handles[i]);
+       if (error->status != 0) {
+               tester_send(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED,
+                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+               discover_destroy();
+               return 0;
        }
 
-       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
-       if (rc) {
-               goto fail;
-       }
+       uuid = &gatt_svc->uuid;
+       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
 
-       if (!gatt_buf_reserve(sizeof(struct gatt_read_rp))) {
-               goto fail;
-       }
 
-       if (ble_gattc_read_mult(conn.conn_handle, handles,
-                               cmd->handles_count, read_cb,
-                               (void *)GATT_READ_MULTIPLE)) {
+       included = gatt_buf_reserve(sizeof(*included) + uuid_length);
+       if (!included) {
+               tester_rsp(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED,
+                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
                discover_destroy();
-               goto fail;
+               return BLE_HS_EDONE;
        }
 
-       return;
+       /* FIXME */
+       included->included_handle = sys_cpu_to_le16(service_handle + 1 +
+       rp->services_count);
+       included->service.start_handle = 
sys_cpu_to_le16(gatt_svc->start_handle);
+       included->service.end_handle = sys_cpu_to_le16(gatt_svc->end_handle);
+       included->service.uuid_length = uuid_length;
 
-fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_READ_MULTIPLE, CONTROLLER_INDEX,
-                  BTP_STATUS_FAILED);
+       if (uuid->u.type == BLE_UUID_TYPE_16) {
+               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+               memcpy(included->service.uuid, &u16, uuid_length);
+       } else {
+               memcpy(included->service.uuid, BLE_UUID128(uuid)->value,
+                      uuid_length);
+       }
+
+       rp->services_count++;
+
+       return 0;
 }
 
-static void write_without_rsp(u8_t *data, u16_t len, u8_t op,
-                             bool sign)
+static int disc_chrc_cb(uint16_t conn_handle,
+                       const struct ble_gatt_error *error,
+                       const struct ble_gatt_chr *gatt_chr, void *arg)
 {
-       const struct gatt_write_without_rsp_cmd *cmd = (void *) data;
-       struct ble_gap_conn_desc conn;
-       u8_t status = BTP_STATUS_SUCCESS;
-       int rc;
+       struct gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf;
+       struct gatt_characteristic *chrc;
+       const ble_uuid_any_t *uuid;
+       u8_t btp_opcode = (uint8_t) (int) arg;
+       u8_t uuid_length;
 
        SYS_LOG_DBG("");
 
-       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
-       if (rc) {
-               status = BTP_STATUS_FAILED;
-               goto rsp;
+       if (error->status != 0) {
+               tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
+                           CONTROLLER_INDEX, gatt_buf.buf, gatt_buf.len);
+               discover_destroy();
+               return 0;
        }
 
-       if (ble_gattc_write_no_rsp_flat(conn.conn_handle,
-                                       sys_le16_to_cpu(cmd->handle),
-                                       cmd->data,
-                                       sys_le16_to_cpu(cmd->data_length))) {
-               status = BTP_STATUS_FAILED;
+       uuid = &gatt_chr->uuid;
+       uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16);
+
+       chrc = gatt_buf_reserve(sizeof(*chrc) + uuid_length);
+       if (!chrc) {
+               tester_rsp(BTP_SERVICE_ID_GATT, btp_opcode,
+                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
+               discover_destroy();
+               return BLE_HS_EDONE;
        }
 
-rsp:
-       tester_rsp(BTP_SERVICE_ID_GATT, op, CONTROLLER_INDEX, status);
-}
+       chrc->characteristic_handle = sys_cpu_to_le16(gatt_chr->def_handle);
+       chrc->properties = gatt_chr->properties;
+       chrc->value_handle = sys_cpu_to_le16(gatt_chr->val_handle);
+       chrc->uuid_length = uuid_length;
 
-static int write_rsp(uint16_t conn_handle,
-                    const struct ble_gatt_error *error,
-                    struct ble_gatt_attr *attr,
-                    void *arg)
-{
-       uint8_t err = (uint8_t) error->status;
-       u8_t btp_opcode = (uint8_t) (int) arg;
+       if (uuid->u.type == BLE_UUID_TYPE_16) {
+               u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
+               memcpy(chrc->uuid, &u16, uuid_length);
+       } else {
+               memcpy(chrc->uuid, BLE_UUID128(uuid)->value,
+               uuid_length);
+       }
 
-       SYS_LOG_DBG("");
+       rp->characteristics_count++;
 
-       tester_send(BTP_SERVICE_ID_GATT, btp_opcode,
-                   CONTROLLER_INDEX, &err,
-                   sizeof(err));
        return 0;
 }
 
-static void write(u8_t *data, u16_t len)
+static void disc_chrc_uuid(u8_t *data, u16_t len)
 {
-       const struct gatt_write_cmd *cmd = (void *) data;
+       const struct gatt_disc_chrc_uuid_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
+       uint16_t start_handle, end_handle;
+       ble_uuid_any_t uuid;
        int rc;
 
        SYS_LOG_DBG("");
@@ -1691,24 +1272,36 @@ static void write(u8_t *data, u16_t len)
                goto fail;
        }
 
-       if (ble_gattc_write_flat(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
-                                cmd->data, sys_le16_to_cpu(cmd->data_length),
-                                write_rsp, (void *) GATT_WRITE)) {
+       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
+               goto fail;
+       }
+
+       if (!gatt_buf_reserve(sizeof(struct gatt_disc_chrc_rp))) {
+               goto fail;
+       }
+
+       start_handle = sys_le16_to_cpu(cmd->start_handle);
+       end_handle = sys_le16_to_cpu(cmd->end_handle);
+
+       if (ble_gattc_disc_chrs_by_uuid(conn.conn_handle, start_handle,
+                                       end_handle, &uuid.u, disc_chrc_cb,
+                                       (void *)GATT_DISC_CHRC_UUID)) {
+               discover_destroy();
                goto fail;
        }
 
        return;
 
 fail:
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_CHRC_UUID, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static void write_long(u8_t *data, u16_t len)
+static void disc_prim_uuid(u8_t *data, u16_t len)
 {
-       const struct gatt_write_long_cmd *cmd = (void *) data;
+       const struct gatt_disc_prim_uuid_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       struct os_mbuf *om = NULL;
+       ble_uuid_any_t uuid;
        int rc;
 
        SYS_LOG_DBG("");
@@ -1718,150 +1311,141 @@ static void write_long(u8_t *data, u16_t len)
                goto fail;
        }
 
-       om = ble_hs_mbuf_from_flat(cmd->data, 
sys_le16_to_cpu(cmd->data_length));
+       if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) {
+               goto fail;
+       }
 
-       if (!om) {
-               SYS_LOG_ERR("Insufficient resources");
+       if (!gatt_buf_reserve(sizeof(struct gatt_disc_prim_uuid_rp))) {
                goto fail;
        }
 
-       if (ble_gattc_write_long(conn.conn_handle, sys_le16_to_cpu(cmd->handle),
-                                sys_le16_to_cpu(cmd->offset), om, write_rsp,
-                                (void *) GATT_WRITE_LONG)) {
+       if (ble_gattc_disc_svc_by_uuid(conn.conn_handle,
+                                      &uuid.u, disc_prim_uuid_cb,
+                                      (void *) GATT_DISC_PRIM_UUID)) {
+               discover_destroy();
                goto fail;
        }
 
        return;
 
 fail:
-       os_mbuf_free_chain(om);
-
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE_LONG, CONTROLLER_INDEX,
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_PRIM_UUID, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static int reliable_write_rsp(uint16_t conn_handle,
-                             const struct ble_gatt_error *error,
-                             struct ble_gatt_attr *attrs,
-                             uint8_t num_attrs,
-                             void *arg)
-{
-       uint8_t err = (uint8_t) error->status;
-
-       SYS_LOG_DBG("");
-
-       tester_send(BTP_SERVICE_ID_GATT, GATT_RELIABLE_WRITE,
-                   CONTROLLER_INDEX, &err,
-                   sizeof(err));
-       return 0;
-}
-
-static void reliable_write(u8_t *data, u16_t len)
+static void disc_all_chrc(u8_t *data, u16_t len)
 {
-       const struct gatt_reliable_write_cmd *cmd = (void *) data;
+       const struct gatt_disc_all_chrc_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       struct ble_gatt_attr attr;
-       struct os_mbuf *om = NULL;
+       uint16_t start_handle, end_handle;
        int rc;
 
        SYS_LOG_DBG("");
 
        rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
        if (rc) {
+               SYS_LOG_DBG("Conn find failed");
                goto fail;
        }
 
-       om = ble_hs_mbuf_from_flat(cmd->data, 
sys_le16_to_cpu(cmd->data_length));
-       /* This is required, because Nimble checks if
-        * the data is longer than offset
-        */
-       if (os_mbuf_extend(om, sys_le16_to_cpu(cmd->offset) + 1) == NULL) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_disc_chrc_rp))) {
+               SYS_LOG_DBG("Buf reserve failed");
                goto fail;
        }
 
-       attr.handle = sys_le16_to_cpu(cmd->handle);
-       attr.offset = sys_le16_to_cpu(cmd->offset);
-       attr.om = om;
+       start_handle = sys_le16_to_cpu(cmd->start_handle);
+       end_handle = sys_le16_to_cpu(cmd->end_handle);
 
-       if (ble_gattc_write_reliable(conn.conn_handle, &attr, 1,
-                                    reliable_write_rsp, NULL)) {
+       rc = ble_gattc_disc_all_chrs(conn.conn_handle, start_handle, end_handle,
+       disc_chrc_cb, (void *)GATT_DISC_ALL_CHRC);
+       if (rc) {
+               discover_destroy();
                goto fail;
        }
 
        return;
 
-       fail:
-       os_mbuf_free_chain(om);
-
-       tester_rsp(BTP_SERVICE_ID_GATT, GATT_WRITE_LONG, CONTROLLER_INDEX,
+fail:
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_DISC_ALL_CHRC, CONTROLLER_INDEX,
                   BTP_STATUS_FAILED);
 }
 
-static struct bt_gatt_subscribe_params {
-       u16_t ccc_handle;
-       u16_t value;
-       u16_t value_handle;
-} subscribe_params;
-
-int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
-                            u8_t indication, struct os_mbuf *om)
+static void find_included(u8_t *data, u16_t len)
 {
-       struct gatt_notification_ev *ev;
+       const struct gatt_find_included_cmd *cmd = (void *) data;
        struct ble_gap_conn_desc conn;
-       struct os_mbuf *buf = os_msys_get(0, 0);
-       const ble_addr_t *addr;
+       uint16_t start_handle, end_handle;
+       int service_handle_arg;
+       int rc;
 
        SYS_LOG_DBG("");
 
-       if (!subscribe_params.ccc_handle) {
+       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
+       if (rc) {
                goto fail;
        }
 
-       if (ble_gap_conn_find(conn_handle, &conn)) {
+       if (!gatt_buf_reserve(sizeof(struct gatt_find_included_rp))) {
                goto fail;
        }
 
-       net_buf_simple_init(buf, 0);
-       ev = net_buf_simple_add(buf, sizeof(*ev));
-
-       addr = &conn.peer_ota_addr;
+       start_handle = sys_le16_to_cpu(cmd->start_handle);
+       end_handle = sys_le16_to_cpu(cmd->end_handle);
+       service_handle_arg = start_handle;
 
-       ev->address_type = addr->type;
-       memcpy(ev->address, addr->val, sizeof(ev->address));
-       ev->type = (u8_t) (indication ? 0x02 : 0x01);
-       ev->handle = sys_cpu_to_le16(attr_handle);
-       ev->data_length = sys_cpu_to_le16(os_mbuf_len(om));
-       os_mbuf_appendfrom(buf, om, 0, os_mbuf_len(om));
+       if (ble_gattc_find_inc_svcs(conn.conn_handle, start_handle, end_handle,
+                                   find_included_cb,
+                                   (void *)service_handle_arg)) {
+               discover_destroy();
+               goto fail;
+       }
 
-       tester_send_buf(BTP_SERVICE_ID_GATT, GATT_EV_NOTIFICATION,
-                       CONTROLLER_INDEX, buf);
+       return;
 
 fail:
-       os_mbuf_free_chain(buf);
-       return 0;
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_FIND_INCLUDED, CONTROLLER_INDEX,
+                  BTP_STATUS_FAILED);
 }
 
-int tester_gatt_subscribe_ev(u16_t conn_handle, u16_t attr_handle, u8_t reason,
-                            u8_t prev_notify, u8_t cur_notify,
-                            u8_t prev_indicate, u8_t cur_indicate)
+static int exchange_func(uint16_t conn_handle,
+                        const struct ble_gatt_error *error,
+                        uint16_t mtu, void *arg)
 {
        SYS_LOG_DBG("");
 
-       if (cur_notify == 0 && cur_indicate == 0) {
-               SYS_LOG_INF("Unsubscribed");
-               memset(&subscribe_params, 0, sizeof(subscribe_params));
-               return 0;
-       }
+       if (error->status) {
+               tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU,
+                          CONTROLLER_INDEX, BTP_STATUS_FAILED);
 
-       if (cur_notify) {
-               SYS_LOG_INF("Subscribed to notifications");
+       return 0;
+}
+
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU, CONTROLLER_INDEX,
+                  BTP_STATUS_SUCCESS);
+
+       return 0;
+}
+
+static void exchange_mtu(u8_t *data, u16_t len)
+{
+       struct ble_gap_conn_desc conn;
+       int rc;
+
+       SYS_LOG_DBG("");
+
+       rc = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
+       if (rc) {
+               goto fail;
        }
 
-       if (cur_indicate) {
-               SYS_LOG_INF("Subscribed to indications");
+       if (ble_gattc_exchange_mtu(conn.conn_handle, exchange_func, NULL)) {
+               goto fail;
        }
 
-       return 0;
+       return;
+fail:
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_EXCHANGE_MTU,
+                  CONTROLLER_INDEX, BTP_STATUS_FAILED);
 }
 
 static int enable_subscription(u16_t conn_handle, u16_t ccc_handle,
@@ -1871,8 +1455,7 @@ static int enable_subscription(u16_t conn_handle, u16_t 
ccc_handle,
 
        SYS_LOG_DBG("");
 
-       op = (uint8_t) (value == 0x0001 ? GATT_CFG_NOTIFY :
-                       GATT_CFG_INDICATE);
+       op = (uint8_t) (value == 0x0001 ? GATT_CFG_NOTIFY : GATT_CFG_INDICATE);
 
        if (ble_gattc_write_flat(conn_handle, ccc_handle,
                                 &value, sizeof(value), NULL, NULL)) {
@@ -2029,7 +1612,7 @@ static void get_attrs(u8_t *data, u16_t len)
 
                if (entry->ha_handle_id < start_handle) {
                        entry = ble_att_svr_find_by_uuid(entry,
-                                                        uuid_ptr, end_handle);
+                       uuid_ptr, end_handle);
                        continue;
                }
 
@@ -2040,12 +1623,12 @@ static void get_attrs(u8_t *data, u16_t len)
                if (entry->ha_uuid->type == BLE_UUID_TYPE_16) {
                        gatt_attr->type_length = 2;
                        net_buf_simple_add_le16(buf,
-                                               
BLE_UUID16(entry->ha_uuid)->value);
+                       BLE_UUID16(entry->ha_uuid)->value);
                } else {
                        gatt_attr->type_length = 16;
                        net_buf_simple_add_mem(buf,
-                                              
BLE_UUID128(entry->ha_uuid)->value,
-                                              gatt_attr->type_length);
+                       BLE_UUID128(entry->ha_uuid)->value,
+                       gatt_attr->type_length);
                }
 
                count++;
@@ -2070,56 +1653,129 @@ static void get_attr_val(u8_t *data, u16_t len)
 {
        const struct gatt_get_attribute_value_cmd *cmd = (void *) data;
        struct gatt_get_attribute_value_rp *rp;
+       struct ble_gap_conn_desc conn;
        struct os_mbuf *buf = os_msys_get(0, 0);
        u16_t handle = sys_cpu_to_le16(cmd->handle);
        uint8_t out_att_err;
+       int conn_status;
 
-       SYS_LOG_DBG("");
+       conn_status = ble_gap_conn_find_by_addr((ble_addr_t *)data, &conn);
 
-       net_buf_simple_init(buf, 0);
-       rp = net_buf_simple_add(buf, sizeof(*rp));
+       if (conn_status) {
+               net_buf_simple_init(buf, 0);
+               rp = net_buf_simple_add(buf, sizeof(*rp));
 
-       ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
-                               handle, 0, buf,
-                               &out_att_err);
+               ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
+                                       handle, 0, buf,
+                                       &out_att_err);
 
-       rp->att_response = out_att_err;
-       rp->value_length = os_mbuf_len(buf) - sizeof(*rp);
+               rp->att_response = out_att_err;
+               rp->value_length = os_mbuf_len(buf) - sizeof(*rp);
 
-       tester_send_buf(BTP_SERVICE_ID_GATT, GATT_GET_ATTRIBUTE_VALUE,
-                       CONTROLLER_INDEX, buf);
+               tester_send_buf(BTP_SERVICE_ID_GATT, GATT_GET_ATTRIBUTE_VALUE,
+                               CONTROLLER_INDEX, buf);
+
+               goto free;
+       } else {
+               net_buf_simple_init(buf, 0);
+               rp = net_buf_simple_add(buf, sizeof(*rp));
 
+               ble_att_svr_read_handle(conn.conn_handle,
+               handle, 0, buf,
+               &out_att_err);
+
+               rp->att_response = out_att_err;
+               rp->value_length = os_mbuf_len(buf) - sizeof(*rp);
+
+               tester_send_buf(BTP_SERVICE_ID_GATT, GATT_GET_ATTRIBUTE_VALUE,
+                               CONTROLLER_INDEX, buf);
+
+               goto free;
+       }
+
+free:
        os_mbuf_free_chain(buf);
 }
 
+static void change_database(u8_t *data, u16_t len)
+{
+       const struct gatt_change_database *cmd = (void *) data;
+       int rc;
+
+       SYS_LOG_DBG("")
+
+       rc = ble_gatts_svc_set_visibility(cmd->start_handle, cmd->visibility);
+       if (rc) {
+               goto fail;
+       }
+
+       ble_gatts_show_local();
+
+       ble_svc_gatt_changed(cmd->start_handle, cmd->end_handle);
+
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_CHANGE_DATABASE, CONTROLLER_INDEX,
+                  BTP_STATUS_SUCCESS);
+
+       return;
+
+fail:
+       tester_rsp(BTP_SERVICE_ID_GATT, GATT_CHANGE_DATABASE, CONTROLLER_INDEX,
+                  BTP_STATUS_FAILED);
+}
+
+static void supported_commands(u8_t *data, u16_t len)
+{
+       u8_t cmds[4];
+       struct gatt_read_supported_commands_rp *rp = (void *) cmds;
+
+       SYS_LOG_DBG("");
+
+       memset(cmds, 0, sizeof(cmds));
+
+       tester_set_bit(cmds, GATT_READ_SUPPORTED_COMMANDS);
+       tester_set_bit(cmds, GATT_START_SERVER);
+       tester_set_bit(cmds, GATT_EXCHANGE_MTU);
+       tester_set_bit(cmds, GATT_DISC_ALL_PRIM_SVCS);
+       tester_set_bit(cmds, GATT_DISC_PRIM_UUID);
+       tester_set_bit(cmds, GATT_FIND_INCLUDED);
+       tester_set_bit(cmds, GATT_DISC_ALL_CHRC);
+       tester_set_bit(cmds, GATT_DISC_CHRC_UUID);
+       tester_set_bit(cmds, GATT_DISC_ALL_DESC);
+       tester_set_bit(cmds, GATT_READ);
+       tester_set_bit(cmds, GATT_READ_LONG);
+       tester_set_bit(cmds, GATT_READ_MULTIPLE);
+       tester_set_bit(cmds, GATT_WRITE_WITHOUT_RSP);
+#if 0
+       tester_set_bit(cmds, GATT_SIGNED_WRITE_WITHOUT_RSP);
+#endif
+       tester_set_bit(cmds, GATT_WRITE);
+       tester_set_bit(cmds, GATT_WRITE_LONG);
+       tester_set_bit(cmds, GATT_CFG_NOTIFY);
+       tester_set_bit(cmds, GATT_CFG_INDICATE);
+       tester_set_bit(cmds, GATT_GET_ATTRIBUTES);
+       tester_set_bit(cmds, GATT_GET_ATTRIBUTE_VALUE);
+       tester_set_bit(cmds, GATT_CHANGE_DATABASE);
+
+       tester_send(BTP_SERVICE_ID_GATT, GATT_READ_SUPPORTED_COMMANDS,
+       CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
+}
+
+enum attr_type {
+       BLE_GATT_ATTR_SVC = 0,
+       BLE_GATT_ATTR_CHR,
+       BLE_GATT_ATTR_DSC,
+};
+
 void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
-                       u16_t len)
+                                                u16_t len)
 {
        switch (opcode) {
        case GATT_READ_SUPPORTED_COMMANDS:
                supported_commands(data, len);
                return;
-       case GATT_ADD_SERVICE:
-               add_service(data, len);
-               return;
-       case GATT_ADD_CHARACTERISTIC:
-               add_characteristic(data, len);
-               return;
-       case GATT_ADD_DESCRIPTOR:
-               add_descriptor(data, len);
-               return;
-       case GATT_ADD_INCLUDED_SERVICE:
-               add_included(data, len);
-               return;
-       case GATT_SET_VALUE:
-               set_value(data, len);
-               return;
        case GATT_START_SERVER:
                start_server(data, len);
                return;
-       case GATT_SET_ENC_KEY_SIZE:
-               set_enc_key_size(data, len);
-               return;
        case GATT_EXCHANGE_MTU:
                exchange_mtu(data, len);
                return;
@@ -2141,6 +1797,9 @@ void tester_handle_gatt(u8_t opcode, u8_t index, u8_t 
*data,
        case GATT_DISC_ALL_DESC:
                disc_all_desc(data, len);
                return;
+       case GATT_CHANGE_DATABASE:
+               change_database(data, len);
+               return;
        case GATT_READ:
                read(data, len);
                return;
@@ -2183,58 +1842,164 @@ void tester_handle_gatt(u8_t opcode, u8_t index, u8_t 
*data,
        default:
                tester_rsp(BTP_SERVICE_ID_GATT, opcode, index,
                           BTP_STATUS_UNKNOWN_CMD);
-               return;
+       return;
        }
 }
 
-void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
+                            u8_t indication, struct os_mbuf *om)
 {
-       char buf[BLE_UUID_STR_LEN];
+       struct gatt_notification_ev *ev;
+       struct ble_gap_conn_desc conn;
+       struct os_mbuf *buf = os_msys_get(0, 0);
+       const ble_addr_t *addr;
 
-       switch (ctxt->op) {
-               case BLE_GATT_REGISTER_OP_SVC:
-                       MODLOG_DFLT(DEBUG,
-                                   "registered service %s with handle=%d\n",
-                                   ble_uuid_to_str(ctxt->svc.svc_def->uuid,
-                                                   buf),
-                                   ctxt->svc.handle);
-                       break;
-
-               case BLE_GATT_REGISTER_OP_CHR:
-                       MODLOG_DFLT(DEBUG, "registering characteristic %s with "
-                                          "def_handle=%d val_handle=%d\n",
-                                   ble_uuid_to_str(ctxt->chr.chr_def->uuid,
-                                                   buf),
-                                   ctxt->chr.def_handle,
-                                   ctxt->chr.val_handle);
-                       break;
-
-               case BLE_GATT_REGISTER_OP_DSC:
-                       MODLOG_DFLT(DEBUG,
-                                   "registering descriptor %s with 
handle=%d\n",
-                                   ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, 
buf),
-                                   ctxt->dsc.handle);
-                       break;
-
-               default:
-                       assert(0);
-                       break;
+       SYS_LOG_DBG("");
+
+       if (!subscribe_params.ccc_handle) {
+               goto fail;
+       }
+
+       if (ble_gap_conn_find(conn_handle, &conn)) {
+               goto fail;
        }
+
+       net_buf_simple_init(buf, 0);
+       ev = net_buf_simple_add(buf, sizeof(*ev));
+
+       addr = &conn.peer_ota_addr;
+
+       ev->address_type = addr->type;
+       memcpy(ev->address, addr->val, sizeof(ev->address));
+       ev->type = (u8_t) (indication ? 0x02 : 0x01);
+       ev->handle = sys_cpu_to_le16(attr_handle);
+       ev->data_length = sys_cpu_to_le16(os_mbuf_len(om));
+       os_mbuf_appendfrom(buf, om, 0, os_mbuf_len(om));
+
+       tester_send_buf(BTP_SERVICE_ID_GATT, GATT_EV_NOTIFICATION,
+                       CONTROLLER_INDEX, buf);
+
+fail:
+       os_mbuf_free_chain(buf);
+       return 0;
 }
 
-int gatt_svr_init(void)
+void notify_test_stop(void)
+{
+       os_callout_stop(&notify_tx_timer);
+}
+
+void notify_test_reset(void)
 {
        int rc;
 
-       rc = ble_gatts_count_cfg(gatt_svr_inc_svcs);
-       if (rc != 0) {
-               return rc;
+       rc = os_callout_reset(&notify_tx_timer, OS_TICKS_PER_SEC);
+       assert(rc == 0);
+}
+
+void notify_test(struct os_event *ev)
+{
+       uint8_t notify_value = 90;
+       static uint8_t ntf[1];
+       int rc;
+       struct os_mbuf *om;
+
+       if (!notify_state) {
+               notify_test_stop();
+               notify_value = 90;
+               return;
        }
 
-       rc = ble_gatts_add_svcs(gatt_svr_inc_svcs);
-       if (rc != 0) {
-               return rc;
+       ntf[0] = notify_value;
+
+       notify_value++;
+       if (notify_value == 160) {
+               notify_value = 90;
+       }
+
+       om = ble_hs_mbuf_from_flat(ntf, sizeof(ntf));
+
+       rc = ble_gattc_notify_custom(myconn_handle, notify_handle, om);
+       rc = ble_gattc_indicate_custom(myconn_handle, notify_handle, om);
+
+       assert(rc == 0);
+       notify_test_reset();
+}
+
+int tester_gatt_subscribe_ev(u16_t conn_handle, u16_t attr_handle, u8_t reason,
+                            u8_t prev_notify, u8_t cur_notify,
+                            u8_t prev_indicate, u8_t cur_indicate)
+{
+       SYS_LOG_DBG("");
+       myconn_handle = conn_handle;
+       os_callout_init(&notify_tx_timer, os_eventq_dflt_get(), notify_test, 
NULL);
+
+       if (cur_notify == 0 && cur_indicate == 0) {
+               SYS_LOG_INF("Unsubscribed");
+               memset(&subscribe_params, 0, sizeof(subscribe_params));
+               return 0;
+       }
+
+       if (cur_notify) {
+                       SYS_LOG_INF("Subscribed to notifications");
+               if (attr_handle == notify_handle) {
+                       notify_state = cur_notify;
+                       notify_test_reset();
+               } else if (attr_handle != notify_handle) {
+                       notify_state = cur_notify;
+                       notify_test_stop();
+               }
+       }
+
+       if (cur_indicate) {
+               SYS_LOG_INF("Subscribed to indications");
+               if (attr_handle == notify_handle) {
+                       notify_state = cur_indicate;
+                       notify_test_reset();
+               } else if (attr_handle != notify_handle) {
+                       notify_state = cur_indicate;
+                       notify_test_stop();
+               }
+       }
+
+       return 0;
+}
+
+void
+gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+       char buf[BLE_UUID_STR_LEN];
+
+       switch (ctxt->op) {
+       case BLE_GATT_REGISTER_OP_SVC:
+               MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
+               ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+                               ctxt->svc.handle);
+               break;
+
+       case BLE_GATT_REGISTER_OP_CHR:
+               MODLOG_DFLT(DEBUG, "registering characteristic %s with "
+                           "def_handle=%d val_handle=%d\n",
+                           ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+                           ctxt->chr.def_handle,
+                           ctxt->chr.val_handle);
+       break;
+
+       case BLE_GATT_REGISTER_OP_DSC:
+               MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
+                           ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+                           ctxt->dsc.handle);
+               break;
+
+       default:
+               assert(0);
+               break;
        }
+}
+
+int gatt_svr_init(void)
+{
+       int rc;
 
        rc = ble_gatts_count_cfg(gatt_svr_svcs);
        if (rc != 0) {
@@ -2246,8 +2011,6 @@ int gatt_svr_init(void)
                return rc;
        }
 
-       init_gatt_values();
-
        return 0;
 }
 

Reply via email to