You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/12/09 23:08:27 UTC

[2/5] incubator-mynewt-larva git commit: Organize GATT code by procedure.

Organize GATT code by procedure.


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

Branch: refs/heads/master
Commit: 2844303f5e4a30dfce116dc3da2e4f75a9ab4514
Parents: d85dc98
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Dec 9 11:43:27 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Dec 9 11:43:27 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_gatt.c | 546 +++++++++++++++++++-----------------
 1 file changed, 296 insertions(+), 250 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/2844303f/net/nimble/host/src/ble_gatt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt.c b/net/nimble/host/src/ble_gatt.c
index 55e4b0b..9b5dfc5 100644
--- a/net/nimble/host/src/ble_gatt.c
+++ b/net/nimble/host/src/ble_gatt.c
@@ -139,6 +139,10 @@ static struct os_mempool ble_gatt_entry_pool;
 
 static STAILQ_HEAD(, ble_gatt_entry) ble_gatt_list;
 
+/*****************************************************************************
+ * @entry                                                                    *
+ *****************************************************************************/
+
 static const struct ble_gatt_dispatch_entry *
 ble_gatt_dispatch_get(uint8_t op)
 {
@@ -282,6 +286,10 @@ ble_gatt_new_entry(uint16_t conn_handle, struct ble_gatt_entry **entry)
     return 0;
 }
 
+/*****************************************************************************
+ * @mtu                                                                      *
+ *****************************************************************************/
+
 static int
 ble_gatt_kick_mtu(struct ble_gatt_entry *entry)
 {
@@ -307,136 +315,86 @@ ble_gatt_kick_mtu(struct ble_gatt_entry *entry)
     return 0;
 }
 
-static int
-ble_gatt_kick_disc_all_services(struct ble_gatt_entry *entry)
+void
+ble_gatt_rx_mtu(struct ble_hs_conn *conn, uint16_t chan_mtu)
 {
-    struct ble_att_read_group_type_req req;
-    struct ble_hs_conn *conn;
-    uint8_t uuid128[16];
-    int rc;
-
-    conn = ble_hs_conn_find(entry->conn_handle);
-    if (conn == NULL) {
-        return ENOTCONN;
-    }
-
-    rc = ble_hs_uuid_from_16bit(BLE_ATT_UUID_PRIMARY_SERVICE, uuid128);
-    assert(rc == 0);
+    struct ble_gatt_entry *entry;
+    struct ble_gatt_entry *prev;
 
-    req.bagq_start_handle = entry->disc_all_services.prev_handle + 1;
-    req.bagq_end_handle = 0xffff;
-    rc = ble_att_clt_tx_read_group_type(conn, &req, uuid128);
-    if (rc != 0) {
-        return rc;
+    entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_MTU, 1, &prev);
+    if (entry == NULL) {
+        /* Not expecting a response from this device. */
+        return;
     }
 
-    return 0;
+    /* XXX: Call success callback. */
+    ble_gatt_entry_remove_free(entry, prev);
 }
 
-static int
-ble_gatt_kick_disc_service_uuid(struct ble_gatt_entry *entry)
+int
+ble_gatt_exchange_mtu(uint16_t conn_handle)
 {
-    struct ble_att_find_type_value_req req;
-    struct ble_hs_conn *conn;
+    struct ble_gatt_entry *entry;
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
-    if (conn == NULL) {
-        return ENOTCONN;
-    }
-
-    req.bavq_start_handle = entry->disc_service_uuid.prev_handle + 1;
-    req.bavq_end_handle = 0xffff;
-    req.bavq_attr_type = BLE_ATT_UUID_PRIMARY_SERVICE;
-
-    rc = ble_att_clt_tx_find_type_value(conn, &req,
-                                        entry->disc_service_uuid.service_uuid,
-                                        16);
+    rc = ble_gatt_new_entry(conn_handle, &entry);
     if (rc != 0) {
         return rc;
     }
+    entry->op = BLE_GATT_OP_MTU;
 
     return 0;
 }
 
+/*****************************************************************************
+ * @discover all services                                                    *
+ *****************************************************************************/
+
 static int
-ble_gatt_kick_disc_all_chars(struct ble_gatt_entry *entry)
+ble_gatt_disc_all_services_cb(struct ble_gatt_entry *entry, int status,
+                              struct ble_gatt_service *service)
 {
-    struct ble_att_read_type_req req;
-    struct ble_hs_conn *conn;
-    uint8_t uuid128[16];
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
-    if (conn == NULL) {
-        return ENOTCONN;
-    }
-
-    rc = ble_hs_uuid_from_16bit(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
-    assert(rc == 0);
-
-    req.batq_start_handle = entry->disc_all_chars.prev_handle + 1;
-    req.batq_end_handle = entry->disc_all_chars.end_handle;
-
-    rc = ble_att_clt_tx_read_type(conn, &req, uuid128);
-    if (rc != 0) {
-        return rc;
+    if (entry->disc_all_services.cb == NULL) {
+        rc = 0;
+    } else {
+        rc = entry->disc_all_services.cb(entry->conn_handle, status, service,
+                                         entry->disc_all_services.cb_arg);
     }
 
-    return 0;
+    return rc;
 }
 
 static int
-ble_gatt_kick_read(struct ble_gatt_entry *entry)
+ble_gatt_kick_disc_all_services(struct ble_gatt_entry *entry)
 {
-    struct ble_att_read_req req;
+    struct ble_att_read_group_type_req req;
     struct ble_hs_conn *conn;
+    uint8_t uuid128[16];
     int rc;
 
     conn = ble_hs_conn_find(entry->conn_handle);
     if (conn == NULL) {
-        return ENOTCONN;
+        rc = ENOTCONN;
+        goto err;
     }
 
-    req.barq_handle = entry->read.handle;
-    rc = ble_att_clt_tx_read(conn, &req);
+    rc = ble_hs_uuid_from_16bit(BLE_ATT_UUID_PRIMARY_SERVICE, uuid128);
+    assert(rc == 0);
+
+    req.bagq_start_handle = entry->disc_all_services.prev_handle + 1;
+    req.bagq_end_handle = 0xffff;
+    rc = ble_att_clt_tx_read_group_type(conn, &req, uuid128);
     if (rc != 0) {
-        return rc;
+        goto err;
     }
 
     return 0;
-}
 
-void
-ble_gatt_wakeup(void)
-{
-    const struct ble_gatt_dispatch_entry *dispatch;
-    struct ble_gatt_entry *entry;
-    struct ble_gatt_entry *prev;
-    struct ble_gatt_entry *next;
-    struct ble_gatt_entry *last;
-    int rc;
-
-    last = STAILQ_LAST(&ble_gatt_list, ble_gatt_entry, next);
-
-    prev = NULL;
-    entry = STAILQ_FIRST(&ble_gatt_list);
-    while (prev != last) {
-        next = STAILQ_NEXT(entry, next);
-
-        if (entry->flags & BLE_GATT_ENTRY_F_PENDING) {
-            dispatch = ble_gatt_dispatch_get(entry->op);
-            rc = dispatch->kick_cb(entry);
-            if (rc == 0) {
-                ble_gatt_entry_set_expecting(entry, prev);
-            } else {
-                ble_gatt_entry_remove_free(entry, prev);
-            }
-        }
-
-        prev = entry;
-        entry = next;
-    }
+err:
+    ble_gatt_disc_all_services_cb(entry, rc, NULL);
+    return rc;
 }
 
 static int
@@ -454,116 +412,12 @@ ble_gatt_rx_err_disc_all_services(struct ble_gatt_entry *entry,
         status = rsp->baep_error_code;
     }
 
-    entry->disc_all_services.cb(conn->bhc_handle, status, NULL,
-                                entry->disc_all_services.cb_arg);
-
-    return 0;
-}
-
-static int
-ble_gatt_rx_err_disc_service_uuid(struct ble_gatt_entry *entry,
-                                  struct ble_hs_conn *conn,
-                                  struct ble_att_error_rsp *rsp)
-{
-    uint8_t status;
-
-    if (rsp->baep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
-        /* Discovery is complete. */
-        status = 0;
-    } else {
-        /* Discovery failure. */
-        status = rsp->baep_error_code;
-    }
-
-    entry->disc_service_uuid.cb(conn->bhc_handle, status, NULL,
-                                entry->disc_service_uuid.cb_arg);
-
-    return 0;
-}
-
-static int
-ble_gatt_rx_err_disc_all_chars(struct ble_gatt_entry *entry,
-                               struct ble_hs_conn *conn,
-                               struct ble_att_error_rsp *rsp)
-{
-    uint8_t status;
-
-    if (rsp->baep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
-        /* Discovery is complete. */
-        status = 0;
-    } else {
-        /* Discovery failure. */
-        status = rsp->baep_error_code;
-    }
-
-    entry->disc_all_chars.cb(conn->bhc_handle, status, NULL,
-                             entry->disc_all_chars.cb_arg);
-
-    return 0;
-}
-
-static int
-ble_gatt_rx_err_read(struct ble_gatt_entry *entry,
-                     struct ble_hs_conn *conn,
-                     struct ble_att_error_rsp *rsp)
-{
-    entry->read.cb(conn->bhc_handle, rsp->baep_error_code, NULL,
-                   entry->disc_all_chars.cb_arg);
+    ble_gatt_disc_all_services_cb(entry, status, NULL);
 
     return 0;
 }
 
 void
-ble_gatt_rx_err(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp)
-{
-    const struct ble_gatt_dispatch_entry *dispatch;
-    struct ble_gatt_entry *entry;
-    struct ble_gatt_entry *prev;
-
-    entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_NONE, 1, &prev);
-    if (entry == NULL) {
-        /* Not expecting a response from this device. */
-        return;
-    }
-
-    dispatch = ble_gatt_dispatch_get(entry->op);
-    dispatch->rx_err_cb(entry, conn, rsp);
-
-    ble_gatt_entry_remove_free(entry, prev);
-}
-
-int
-ble_gatt_exchange_mtu(uint16_t conn_handle)
-{
-    struct ble_gatt_entry *entry;
-    int rc;
-
-    rc = ble_gatt_new_entry(conn_handle, &entry);
-    if (rc != 0) {
-        return rc;
-    }
-    entry->op = BLE_GATT_OP_MTU;
-
-    return 0;
-}
-
-void
-ble_gatt_rx_mtu(struct ble_hs_conn *conn, uint16_t chan_mtu)
-{
-    struct ble_gatt_entry *entry;
-    struct ble_gatt_entry *prev;
-
-    entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_MTU, 1, &prev);
-    if (entry == NULL) {
-        /* Not expecting a response from this device. */
-        return;
-    }
-
-    /* XXX: Call success callback. */
-    ble_gatt_entry_remove_free(entry, prev);
-}
-
-void
 ble_gatt_rx_read_group_type_adata(struct ble_hs_conn *conn,
                                   struct ble_att_clt_adata *adata)
 {
@@ -607,8 +461,7 @@ ble_gatt_rx_read_group_type_adata(struct ble_hs_conn *conn,
     rc = 0;
 
 done:
-    cbrc = entry->disc_all_services.cb(conn->bhc_handle, rc, &service,
-                                       entry->disc_all_services.cb_arg);
+    cbrc = ble_gatt_disc_all_services_cb(entry, rc, &service);
     if (rc != 0 || cbrc != 0) {
         ble_gatt_entry_remove_free(entry, prev);
     }
@@ -629,8 +482,7 @@ ble_gatt_rx_read_group_type_complete(struct ble_hs_conn *conn, int rc)
 
     if (rc != 0 || entry->disc_all_services.prev_handle == 0xffff) {
         /* Error or all services discovered. */
-        entry->disc_all_services.cb(conn->bhc_handle, rc, NULL,
-                                    entry->disc_all_services.cb_arg);
+        ble_gatt_disc_all_services_cb(entry, rc, NULL);
         ble_gatt_entry_remove_free(entry, prev);
     } else {
         /* Send follow-up request. */
@@ -638,6 +490,76 @@ ble_gatt_rx_read_group_type_complete(struct ble_hs_conn *conn, int rc)
     }
 }
 
+int
+ble_gatt_disc_all_services(uint16_t conn_handle, ble_gatt_disc_service_fn *cb,
+                           void *cb_arg)
+{
+    struct ble_gatt_entry *entry;
+    int rc;
+
+    rc = ble_gatt_new_entry(conn_handle, &entry);
+    if (rc != 0) {
+        return rc;
+    }
+    entry->op = BLE_GATT_OP_DISC_ALL_SERVICES;
+    entry->disc_all_services.prev_handle = 0x0000;
+    entry->disc_all_services.cb = cb;
+    entry->disc_all_services.cb_arg = cb_arg;
+
+    return 0;
+}
+
+/*****************************************************************************
+ * @discover service by uuid                                                 *
+ *****************************************************************************/
+
+static int
+ble_gatt_kick_disc_service_uuid(struct ble_gatt_entry *entry)
+{
+    struct ble_att_find_type_value_req req;
+    struct ble_hs_conn *conn;
+    int rc;
+
+    conn = ble_hs_conn_find(entry->conn_handle);
+    if (conn == NULL) {
+        return ENOTCONN;
+    }
+
+    req.bavq_start_handle = entry->disc_service_uuid.prev_handle + 1;
+    req.bavq_end_handle = 0xffff;
+    req.bavq_attr_type = BLE_ATT_UUID_PRIMARY_SERVICE;
+
+    rc = ble_att_clt_tx_find_type_value(conn, &req,
+                                        entry->disc_service_uuid.service_uuid,
+                                        16);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+ble_gatt_rx_err_disc_service_uuid(struct ble_gatt_entry *entry,
+                                  struct ble_hs_conn *conn,
+                                  struct ble_att_error_rsp *rsp)
+{
+    uint8_t status;
+
+    if (rsp->baep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
+        /* Discovery is complete. */
+        status = 0;
+    } else {
+        /* Discovery failure. */
+        status = rsp->baep_error_code;
+    }
+
+    entry->disc_service_uuid.cb(conn->bhc_handle, status, NULL,
+                                entry->disc_service_uuid.cb_arg);
+
+    return 0;
+}
+
 void
 ble_gatt_rx_find_type_value_hinfo(struct ble_hs_conn *conn,
                                   struct ble_att_clt_adata *adata)
@@ -689,6 +611,78 @@ ble_gatt_rx_find_type_value_complete(struct ble_hs_conn *conn, int rc)
     }
 }
 
+int
+ble_gatt_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
+                              ble_gatt_disc_service_fn *cb, void *cb_arg)
+{
+    struct ble_gatt_entry *entry;
+    int rc;
+
+    rc = ble_gatt_new_entry(conn_handle, &entry);
+    if (rc != 0) {
+        return rc;
+    }
+    entry->op = BLE_GATT_OP_DISC_SERVICE_UUID;
+    memcpy(entry->disc_service_uuid.service_uuid, service_uuid128, 16);
+    entry->disc_service_uuid.prev_handle = 0x0000;
+    entry->disc_service_uuid.cb = cb;
+    entry->disc_service_uuid.cb_arg = cb_arg;
+
+    return 0;
+}
+
+/*****************************************************************************
+ * @discover all characteristics                                             *
+ *****************************************************************************/
+
+static int
+ble_gatt_kick_disc_all_chars(struct ble_gatt_entry *entry)
+{
+    struct ble_att_read_type_req req;
+    struct ble_hs_conn *conn;
+    uint8_t uuid128[16];
+    int rc;
+
+    conn = ble_hs_conn_find(entry->conn_handle);
+    if (conn == NULL) {
+        return ENOTCONN;
+    }
+
+    rc = ble_hs_uuid_from_16bit(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
+    assert(rc == 0);
+
+    req.batq_start_handle = entry->disc_all_chars.prev_handle + 1;
+    req.batq_end_handle = entry->disc_all_chars.end_handle;
+
+    rc = ble_att_clt_tx_read_type(conn, &req, uuid128);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+ble_gatt_rx_err_disc_all_chars(struct ble_gatt_entry *entry,
+                               struct ble_hs_conn *conn,
+                               struct ble_att_error_rsp *rsp)
+{
+    uint8_t status;
+
+    if (rsp->baep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
+        /* Discovery is complete. */
+        status = 0;
+    } else {
+        /* Discovery failure. */
+        status = rsp->baep_error_code;
+    }
+
+    entry->disc_all_chars.cb(conn->bhc_handle, status, NULL,
+                             entry->disc_all_chars.cb_arg);
+
+    return 0;
+}
+
 void
 ble_gatt_rx_read_type_adata(struct ble_hs_conn *conn,
                             struct ble_att_clt_adata *adata)
@@ -743,6 +737,63 @@ ble_gatt_rx_read_type_complete(struct ble_hs_conn *conn, int rc)
     }
 }
 
+int
+ble_gatt_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
+                        uint16_t end_handle, ble_gatt_attr_fn *cb,
+                        void *cb_arg)
+{
+    struct ble_gatt_entry *entry;
+    int rc;
+
+    rc = ble_gatt_new_entry(conn_handle, &entry);
+    if (rc != 0) {
+        return rc;
+    }
+    entry->op = BLE_GATT_OP_DISC_ALL_CHARS;
+    entry->disc_all_chars.prev_handle = start_handle - 1;
+    entry->disc_all_chars.end_handle = end_handle;
+    entry->disc_all_chars.cb = cb;
+    entry->disc_all_chars.cb_arg = cb_arg;
+
+    return 0;
+}
+
+/*****************************************************************************
+ * @read                                                                     *
+ *****************************************************************************/
+
+static int
+ble_gatt_kick_read(struct ble_gatt_entry *entry)
+{
+    struct ble_att_read_req req;
+    struct ble_hs_conn *conn;
+    int rc;
+
+    conn = ble_hs_conn_find(entry->conn_handle);
+    if (conn == NULL) {
+        return ENOTCONN;
+    }
+
+    req.barq_handle = entry->read.handle;
+    rc = ble_att_clt_tx_read(conn, &req);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+ble_gatt_rx_err_read(struct ble_gatt_entry *entry,
+                     struct ble_hs_conn *conn,
+                     struct ble_att_error_rsp *rsp)
+{
+    entry->read.cb(conn->bhc_handle, rsp->baep_error_code, NULL,
+                   entry->disc_all_chars.cb_arg);
+
+    return 0;
+}
+
 void
 ble_gatt_rx_read_rsp(struct ble_hs_conn *conn, int status, void *value,
                      int value_len)
@@ -768,8 +819,8 @@ ble_gatt_rx_read_rsp(struct ble_hs_conn *conn, int status, void *value,
 }
 
 int
-ble_gatt_disc_all_services(uint16_t conn_handle, ble_gatt_disc_service_fn *cb,
-                           void *cb_arg)
+ble_gatt_read(uint16_t conn_handle, uint16_t attr_handle,
+              ble_gatt_attr_fn *cb, void *cb_arg)
 {
     struct ble_gatt_entry *entry;
     int rc;
@@ -778,72 +829,67 @@ ble_gatt_disc_all_services(uint16_t conn_handle, ble_gatt_disc_service_fn *cb,
     if (rc != 0) {
         return rc;
     }
-    entry->op = BLE_GATT_OP_DISC_ALL_SERVICES;
-    entry->disc_all_services.prev_handle = 0x0000;
-    entry->disc_all_services.cb = cb;
-    entry->disc_all_services.cb_arg = cb_arg;
+    entry->op = BLE_GATT_OP_READ;
+    entry->read.handle = attr_handle;
+    entry->read.cb = cb;
+    entry->read.cb_arg = cb_arg;
 
     return 0;
 }
 
-int
-ble_gatt_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
-                              ble_gatt_disc_service_fn *cb, void *cb_arg)
+/*****************************************************************************
+ * @misc                                                                     *
+ *****************************************************************************/
+
+void
+ble_gatt_wakeup(void)
 {
+    const struct ble_gatt_dispatch_entry *dispatch;
     struct ble_gatt_entry *entry;
+    struct ble_gatt_entry *prev;
+    struct ble_gatt_entry *next;
+    struct ble_gatt_entry *last;
     int rc;
 
-    rc = ble_gatt_new_entry(conn_handle, &entry);
-    if (rc != 0) {
-        return rc;
-    }
-    entry->op = BLE_GATT_OP_DISC_SERVICE_UUID;
-    memcpy(entry->disc_service_uuid.service_uuid, service_uuid128, 16);
-    entry->disc_service_uuid.prev_handle = 0x0000;
-    entry->disc_service_uuid.cb = cb;
-    entry->disc_service_uuid.cb_arg = cb_arg;
+    last = STAILQ_LAST(&ble_gatt_list, ble_gatt_entry, next);
 
-    return 0;
-}
+    prev = NULL;
+    entry = STAILQ_FIRST(&ble_gatt_list);
+    while (prev != last) {
+        next = STAILQ_NEXT(entry, next);
 
-int
-ble_gatt_disc_all_chars(uint16_t conn_handle, uint16_t start_handle,
-                        uint16_t end_handle, ble_gatt_attr_fn *cb,
-                        void *cb_arg)
-{
-    struct ble_gatt_entry *entry;
-    int rc;
+        if (entry->flags & BLE_GATT_ENTRY_F_PENDING) {
+            dispatch = ble_gatt_dispatch_get(entry->op);
+            rc = dispatch->kick_cb(entry);
+            if (rc == 0) {
+                ble_gatt_entry_set_expecting(entry, prev);
+            } else {
+                ble_gatt_entry_remove_free(entry, prev);
+            }
+        }
 
-    rc = ble_gatt_new_entry(conn_handle, &entry);
-    if (rc != 0) {
-        return rc;
+        prev = entry;
+        entry = next;
     }
-    entry->op = BLE_GATT_OP_DISC_ALL_CHARS;
-    entry->disc_all_chars.prev_handle = start_handle - 1;
-    entry->disc_all_chars.end_handle = end_handle;
-    entry->disc_all_chars.cb = cb;
-    entry->disc_all_chars.cb_arg = cb_arg;
-
-    return 0;
 }
 
-int
-ble_gatt_read(uint16_t conn_handle, uint16_t attr_handle,
-              ble_gatt_attr_fn *cb, void *cb_arg)
+void
+ble_gatt_rx_err(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp)
 {
+    const struct ble_gatt_dispatch_entry *dispatch;
     struct ble_gatt_entry *entry;
-    int rc;
+    struct ble_gatt_entry *prev;
 
-    rc = ble_gatt_new_entry(conn_handle, &entry);
-    if (rc != 0) {
-        return rc;
+    entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_NONE, 1, &prev);
+    if (entry == NULL) {
+        /* Not expecting a response from this device. */
+        return;
     }
-    entry->op = BLE_GATT_OP_READ;
-    entry->read.handle = attr_handle;
-    entry->read.cb = cb;
-    entry->read.cb_arg = cb_arg;
 
-    return 0;
+    dispatch = ble_gatt_dispatch_get(entry->op);
+    dispatch->rx_err_cb(entry, conn, rsp);
+
+    ble_gatt_entry_remove_free(entry, prev);
 }
 
 int