You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/01/13 01:49:57 UTC

[2/3] incubator-mynewt-larva git commit: Cleanup and comments for ble_gattc.c

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/17ac9193/net/nimble/host/src/ble_gattc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index ffb66bf..4c094b5 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -29,8 +29,35 @@
 #include "ble_att_priv.h"
 #include "ble_gatt_priv.h"
 
-struct ble_gattc_entry {
-    STAILQ_ENTRY(ble_gattc_entry) next;
+/*****************************************************************************
+ * $definitions / declarations                                               *
+ *****************************************************************************/
+
+#define BLE_GATT_NUM_ENTRIES                    16      /* XXX Configurable. */
+#define BLE_GATT_HEARTBEAT_PERIOD               1000    /* Milliseconds. */
+#define BLE_GATT_UNRESPONSIVE_TIMEOUT           5000    /* Milliseconds. */
+
+#define BLE_GATT_OP_NONE                        UINT8_MAX
+#define BLE_GATT_OP_MTU                         0
+#define BLE_GATT_OP_DISC_ALL_SVCS               1
+#define BLE_GATT_OP_DISC_SVC_UUID               2
+#define BLE_GATT_OP_FIND_INC_SVCS               3
+#define BLE_GATT_OP_DISC_ALL_CHRS               4
+#define BLE_GATT_OP_DISC_CHRS_UUID              5
+#define BLE_GATT_OP_DISC_ALL_DSCS               6
+#define BLE_GATT_OP_READ                        7
+#define BLE_GATT_OP_READ_UUID                   8
+#define BLE_GATT_OP_READ_LONG                   9
+#define BLE_GATT_OP_READ_MULT                   10
+#define BLE_GATT_OP_WRITE_NO_RSP                11
+#define BLE_GATT_OP_WRITE                       12
+#define BLE_GATT_OP_WRITE_LONG                  13
+#define BLE_GATT_OP_INDICATE                    14
+#define BLE_GATT_OP_MAX                         15
+
+/** Represents an in-progress GATT procedure. */
+struct ble_gattc_proc {
+    STAILQ_ENTRY(ble_gattc_proc) next;
 
     uint8_t op;
     uint8_t flags;
@@ -138,132 +165,195 @@ struct ble_gattc_entry {
     };
 };
 
-#define BLE_GATT_HEARTBEAT_PERIOD               1000 /* Milliseconds. */
-#define BLE_GATT_UNRESPONSIVE_TIMEOUT           5000 /* Milliseconds. */
+/** Procedure has a tx pending. */
+#define BLE_GATT_ENTRY_F_PENDING    0x01
 
-#define BLE_GATT_OP_NONE                        UINT8_MAX
-#define BLE_GATT_OP_MTU                         0
-#define BLE_GATT_OP_DISC_ALL_SVCS               1
-#define BLE_GATT_OP_DISC_SVC_UUID               2
-#define BLE_GATT_OP_FIND_INC_SVCS               3
-#define BLE_GATT_OP_DISC_ALL_CHRS               4
-#define BLE_GATT_OP_DISC_CHRS_UUID              5
-#define BLE_GATT_OP_DISC_ALL_DSCS               6
-#define BLE_GATT_OP_READ                        7
-#define BLE_GATT_OP_READ_UUID                   8
-#define BLE_GATT_OP_READ_LONG                   9
-#define BLE_GATT_OP_READ_MULT                   10
-#define BLE_GATT_OP_WRITE_NO_RSP                11
-#define BLE_GATT_OP_WRITE                       12
-#define BLE_GATT_OP_WRITE_LONG                  13
-#define BLE_GATT_OP_INDICATE                    14
-#define BLE_GATT_OP_MAX                         15
+/** Procedure currently expects an ATT response. */
+#define BLE_GATT_ENTRY_F_EXPECTING  0x02
+
+/** Procedure failed to tx due to too many outstanding txes. */
+#define BLE_GATT_ENTRY_F_CONGESTED  0x04
 
+/** Procedure failed to tx due to memory exhaustion. */
+#define BLE_GATT_ENTRY_F_NO_MEM     0x08
+
+/**
+ * Handles unresponsive timeouts and periodic retries in case of resource
+ * shortage.
+ */
 static struct os_callout_func ble_gattc_heartbeat_timer;
 
-typedef int ble_gattc_kick_fn(struct ble_gattc_entry *entry);
-typedef void ble_gattc_err_fn(struct ble_gattc_entry *entry, int status,
+/**
+ * Kick functions - these trigger the pending ATT transmit for an active GATT
+ * procedure.
+ */
+typedef int ble_gattc_kick_fn(struct ble_gattc_proc *proc);
+typedef void ble_gattc_err_fn(struct ble_gattc_proc *proc, int status,
                               uint16_t att_handle);
 
-static int ble_gattc_mtu_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_disc_all_svcs_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_disc_svc_uuid_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_find_inc_svcs_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_disc_all_chrs_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_disc_chr_uuid_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_disc_all_dscs_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_read_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_read_uuid_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_read_long_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_read_mult_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_write_no_rsp_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_write_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_write_long_kick(struct ble_gattc_entry *entry);
-static int ble_gattc_indicate_kick(struct ble_gattc_entry *entry);
-
-static void ble_gattc_mtu_err(struct ble_gattc_entry *entry, int status,
+static int ble_gattc_mtu_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_disc_all_svcs_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_disc_svc_uuid_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_find_inc_svcs_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_disc_all_chrs_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_disc_chr_uuid_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_disc_all_dscs_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_read_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_read_uuid_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_read_long_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_read_mult_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_write_no_rsp_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_write_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_write_long_kick(struct ble_gattc_proc *proc);
+static int ble_gattc_indicate_kick(struct ble_gattc_proc *proc);
+
+/**
+ * Error functions - these handle an incoming ATT error response and apply it
+ * to the appropriate active GATT procedure.
+ */
+static void ble_gattc_mtu_err(struct ble_gattc_proc *proc, int status,
                               uint16_t att_handle);
-static void ble_gattc_disc_all_svcs_err(struct ble_gattc_entry *entry,
+static void ble_gattc_disc_all_svcs_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_disc_svc_uuid_err(struct ble_gattc_entry *entry,
+static void ble_gattc_disc_svc_uuid_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_find_inc_svcs_err(struct ble_gattc_entry *entry,
+static void ble_gattc_find_inc_svcs_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_disc_all_chrs_err(struct ble_gattc_entry *entry,
+static void ble_gattc_disc_all_chrs_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_disc_chr_uuid_err(struct ble_gattc_entry *entry,
+static void ble_gattc_disc_chr_uuid_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_disc_all_dscs_err(struct ble_gattc_entry *entry,
+static void ble_gattc_disc_all_dscs_err(struct ble_gattc_proc *proc,
                                         int status, uint16_t att_handle);
-static void ble_gattc_read_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_read_err(struct ble_gattc_proc *proc, int status,
                                uint16_t att_handle);
-static void ble_gattc_read_uuid_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_read_uuid_err(struct ble_gattc_proc *proc, int status,
                                     uint16_t att_handle);
-static void ble_gattc_read_long_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_read_long_err(struct ble_gattc_proc *proc, int status,
                                     uint16_t att_handle);
-static void ble_gattc_read_mult_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status,
                                     uint16_t att_handle);
-static void ble_gattc_write_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_write_err(struct ble_gattc_proc *proc, int status,
                                 uint16_t att_handle);
-static void ble_gattc_write_long_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status,
                                      uint16_t att_handle);
-static void ble_gattc_indicate_err(struct ble_gattc_entry *entry, int status,
+static void ble_gattc_indicate_err(struct ble_gattc_proc *proc, int status,
                                    uint16_t att_handle);
 
-static int ble_gattc_find_inc_svcs_rx_adata(
-    struct ble_gattc_entry *entry, struct ble_hs_conn *conn,
-    struct ble_att_read_type_adata *adata);
-static int ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_entry *entry,
-                                               struct ble_hs_conn *conn,
-                                               int status);
-static int ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_entry *entry,
-                                               struct ble_hs_conn *conn,
-                                               int status,
-                                               void *value, int value_len);
-
-static int ble_gattc_disc_all_chrs_rx_adata(
-    struct ble_gattc_entry *entry, struct ble_hs_conn *conn,
-    struct ble_att_read_type_adata *adata);
-static int ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_entry *entry,
-                                               struct ble_hs_conn *conn,
-                                               int status);
-static int ble_gattc_disc_chr_uuid_rx_adata(
-    struct ble_gattc_entry *entry, struct ble_hs_conn *conn,
-    struct ble_att_read_type_adata *adata);
-static int ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_entry *entry,
-                                               struct ble_hs_conn *conn,
-                                               int status);
-static int ble_gattc_read_rx_read_rsp(struct ble_gattc_entry *entry,
-                                      struct ble_hs_conn *conn, int status,
-                                      void *value, int value_len);
-static int ble_gattc_read_long_rx_read_rsp(struct ble_gattc_entry *entry,
-                                           struct ble_hs_conn *conn,
-                                           int status, void *value,
-                                           int value_len);
-static int ble_gattc_read_uuid_rx_adata(
-    struct ble_gattc_entry *entry, struct ble_hs_conn *conn,
-    struct ble_att_read_type_adata *adata);
-static int ble_gattc_read_uuid_rx_complete(struct ble_gattc_entry *entry,
-                                           struct ble_hs_conn *conn,
-                                           int status);
-
-static int ble_gattc_write_long_rx_prep(struct ble_gattc_entry *entry,
-                                        struct ble_hs_conn *conn,
-                                        int status,
-                                        struct ble_att_prep_write_cmd *rsp,
-                                        void *attr_data, uint16_t attr_len);
-static int ble_gattc_write_long_rx_exec(struct ble_gattc_entry *entry,
-                                        struct ble_hs_conn *conn,
-                                        int status);
-
-struct ble_gattc_dispatch_entry {
-    ble_gattc_kick_fn *kick_cb;
-    ble_gattc_err_fn *err_cb;
+/**
+ * Receive functions - these handle specific incoming responses and apply them
+ * to the appropriate active GATT procedure.
+ */
+static int
+ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc,
+                                 struct ble_hs_conn *conn,
+                                 struct ble_att_read_type_adata *adata);
+static int
+ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc,
+                                    struct ble_hs_conn *conn,
+                                    int status);
+static int
+ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc,
+                                    struct ble_hs_conn *conn,
+                                    int status, void *value, int value_len);
+static int
+ble_gattc_disc_all_chrs_rx_adata(struct ble_gattc_proc *proc,
+                                 struct ble_hs_conn *conn,
+                                 struct ble_att_read_type_adata *adata);
+static int
+ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_proc *proc,
+                                    struct ble_hs_conn *conn,
+                                    int status);
+static int
+ble_gattc_disc_chr_uuid_rx_adata(struct ble_gattc_proc *proc,
+                                 struct ble_hs_conn *conn,
+                                 struct ble_att_read_type_adata *adata);
+static int
+ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_proc *proc,
+                                    struct ble_hs_conn *conn,
+                                    int status);
+static int
+ble_gattc_read_rx_read_rsp(struct ble_gattc_proc *proc,
+                           struct ble_hs_conn *conn, int status,
+                           void *value, int value_len);
+static int
+ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc,
+                                struct ble_hs_conn *conn, int status,
+                                void *value, int value_len);
+static int
+ble_gattc_read_uuid_rx_adata(struct ble_gattc_proc *proc,
+                             struct ble_hs_conn *conn,
+                             struct ble_att_read_type_adata *adata);
+static int
+ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc,
+                                struct ble_hs_conn *conn,
+                                int status);
+static int
+ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc,
+                             struct ble_hs_conn *conn,
+                             int status, struct ble_att_prep_write_cmd *rsp,
+                             void *attr_data, uint16_t attr_len);
+static int
+ble_gattc_write_long_rx_exec(struct ble_gattc_proc *proc,
+                             struct ble_hs_conn *conn, int status);
+
+
+typedef int ble_gattc_rx_adata_fn(struct ble_gattc_proc *proc,
+                                  struct ble_hs_conn *conn,
+                                  struct ble_att_read_type_adata *adata);
+struct ble_gattc_rx_adata_entry {
+    uint8_t op;
+    ble_gattc_rx_adata_fn *cb;
+};
+
+typedef int ble_gattc_rx_complete_fn(struct ble_gattc_proc *proc,
+                                     struct ble_hs_conn *conn,
+                                     int rc);
+struct ble_gattc_rx_complete_entry {
+    uint8_t op;
+    ble_gattc_rx_complete_fn *cb;
+};
+
+typedef int ble_gattc_rx_attr_fn(struct ble_gattc_proc *proc,
+                                 struct ble_hs_conn *conn, int status,
+                                 void *value, int value_len);
+struct ble_gattc_rx_attr_entry {
+    uint8_t op;
+    ble_gattc_rx_attr_fn *cb;
+};
+
+static const struct ble_gattc_rx_adata_entry
+    ble_gattc_rx_read_type_elem_entries[] = {
+
+    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_adata },
+    { BLE_GATT_OP_DISC_ALL_CHRS,    ble_gattc_disc_all_chrs_rx_adata },
+    { BLE_GATT_OP_DISC_CHRS_UUID,   ble_gattc_disc_chr_uuid_rx_adata },
+    { BLE_GATT_OP_READ_UUID,        ble_gattc_read_uuid_rx_adata },
 };
 
-static const struct ble_gattc_dispatch_entry
-    ble_gattc_dispatch[BLE_GATT_OP_MAX] = {
+static const struct ble_gattc_rx_complete_entry
+    ble_gattc_rx_read_type_complete_entries[] = {
+
+    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_complete },
+    { BLE_GATT_OP_DISC_ALL_CHRS,    ble_gattc_disc_all_chrs_rx_complete },
+    { BLE_GATT_OP_DISC_CHRS_UUID,   ble_gattc_disc_chr_uuid_rx_complete },
+    { BLE_GATT_OP_READ_UUID,        ble_gattc_read_uuid_rx_complete },
+};
+
+static const struct ble_gattc_rx_attr_entry ble_gattc_rx_read_rsp_entries[] = {
+    { BLE_GATT_OP_READ,             ble_gattc_read_rx_read_rsp },
+    { BLE_GATT_OP_READ_LONG,        ble_gattc_read_long_rx_read_rsp },
+    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_read_rsp },
+};
 
+/**
+ * Dispatch entries - this array maps GATT procedure types to their
+ * corresponding kick and error functions.
+ */
+static const struct ble_gattc_dispatch_entry {
+    ble_gattc_kick_fn *kick_cb;
+    ble_gattc_err_fn *err_cb;
+} ble_gattc_dispatch[BLE_GATT_OP_MAX] = {
     [BLE_GATT_OP_MTU] = {
         .kick_cb = ble_gattc_mtu_kick,
         .err_cb = ble_gattc_mtu_err,
@@ -326,83 +416,32 @@ static const struct ble_gattc_dispatch_entry
     },
 };
 
-typedef int ble_gattc_rx_adata_fn(struct ble_gattc_entry *entry,
-                                  struct ble_hs_conn *conn, 
-                                  struct ble_att_read_type_adata *adata);
-struct ble_gattc_rx_adata_entry {
-    uint8_t op;
-    ble_gattc_rx_adata_fn *cb;
-};
-
-typedef int ble_gattc_rx_complete_fn(struct ble_gattc_entry *entry,
-                                     struct ble_hs_conn *conn,
-                                     int rc);
-struct ble_gattc_rx_complete_entry {
-    uint8_t op;
-    ble_gattc_rx_complete_fn *cb;
-};
-
-typedef int ble_gattc_rx_attr_fn(struct ble_gattc_entry *entry,
-                                 struct ble_hs_conn *conn, int status,
-                                 void *value, int value_len);
-struct ble_gattc_rx_attr_entry {
-    uint8_t op;
-    ble_gattc_rx_attr_fn *cb;
-};
-
-static const struct ble_gattc_rx_adata_entry
-    ble_gattc_rx_read_type_elem_entries[] = {
-
-    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_adata },
-    { BLE_GATT_OP_DISC_ALL_CHRS,    ble_gattc_disc_all_chrs_rx_adata },
-    { BLE_GATT_OP_DISC_CHRS_UUID,   ble_gattc_disc_chr_uuid_rx_adata },
-    { BLE_GATT_OP_READ_UUID,        ble_gattc_read_uuid_rx_adata },
-};
-
-static const struct ble_gattc_rx_complete_entry
-    ble_gattc_rx_read_type_complete_entries[] = {
-
-    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_complete },
-    { BLE_GATT_OP_DISC_ALL_CHRS,    ble_gattc_disc_all_chrs_rx_complete },
-    { BLE_GATT_OP_DISC_CHRS_UUID,   ble_gattc_disc_chr_uuid_rx_complete },
-    { BLE_GATT_OP_READ_UUID,        ble_gattc_read_uuid_rx_complete },
-};
-
-static const struct ble_gattc_rx_attr_entry ble_gattc_rx_read_rsp_entries[] = {
-    { BLE_GATT_OP_READ,             ble_gattc_read_rx_read_rsp },
-    { BLE_GATT_OP_READ_LONG,        ble_gattc_read_long_rx_read_rsp },
-    { BLE_GATT_OP_FIND_INC_SVCS,    ble_gattc_find_inc_svcs_rx_read_rsp },
-};
-
-#define BLE_GATT_ENTRY_F_PENDING    0x01
-#define BLE_GATT_ENTRY_F_EXPECTING  0x02
-#define BLE_GATT_ENTRY_F_CONGESTED  0x04
-#define BLE_GATT_ENTRY_F_NO_MEM     0x08
-
-#define BLE_GATT_NUM_ENTRIES        16
-static void *ble_gattc_entry_mem;
-static struct os_mempool ble_gattc_entry_pool;
+static void *ble_gattc_proc_mem;
+static struct os_mempool ble_gattc_proc_pool;
 
-static STAILQ_HEAD(, ble_gattc_entry) ble_gattc_list;
+static STAILQ_HEAD(, ble_gattc_proc) ble_gattc_list;
 
 /*****************************************************************************
  * $debug                                                                    *
  *****************************************************************************/
 
+/**
+ * Ensures all procedure entries are in a valid state.
+ */
 static void
 ble_gattc_assert_sanity(void)
 {
 #ifdef BLE_HS_DEBUG
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     unsigned mask;
     int num_set;
 
-    STAILQ_FOREACH(entry, &ble_gattc_list, next) {
+    STAILQ_FOREACH(proc, &ble_gattc_list, next) {
         /* Ensure exactly one flag is set. */
         num_set = 0;
         mask = 0x01;
         while (mask <= UINT8_MAX) {
-            if (entry->flags & mask) {
+            if (proc->flags & mask) {
                 num_set++;
             }
             mask <<= 1;
@@ -438,78 +477,115 @@ ble_gattc_rx_entry_find_(uint8_t op, const void *rx_entries, int num_entries)
     return NULL;
 }
 
+/**
+ * Searches an array of RX entries for one with the specified op code.  This is
+ * defined as a macro so that it works with any array type.
+ *
+ * @param op_arg                The GATT procedure op code to search for.
+ * @param rx_entries            The array to search.
+ *
+ * @return                      The matching entry on success; null on failure.
+ */
 #define BLE_GATTC_RX_ENTRY_FIND(op_arg, rx_entries)                         \
     ble_gattc_rx_entry_find_((op_arg), (rx_entries),                        \
                              sizeof (rx_entries) / sizeof (rx_entries[0]))  \
 
 /*****************************************************************************
- * @entry                                                                    *
+ * $proc                                                                    *
  *****************************************************************************/
 
-static const struct ble_gattc_dispatch_entry *
-ble_gattc_dispatch_get(uint8_t op)
-{
-    assert(op < BLE_GATT_OP_MAX);
-    return ble_gattc_dispatch + op;
-}
-
-static struct ble_gattc_entry *
-ble_gattc_entry_alloc(void)
+/**
+ * Allocates a proc entry.
+ *
+ * @return                      An entry on success; null on failure.
+ */
+static struct ble_gattc_proc *
+ble_gattc_proc_alloc(void)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
 
-    entry = os_memblock_get(&ble_gattc_entry_pool);
-    if (entry != NULL) {
-        memset(entry, 0, sizeof *entry);
+    proc = os_memblock_get(&ble_gattc_proc_pool);
+    if (proc != NULL) {
+        memset(proc, 0, sizeof *proc);
     }
 
-    return entry;
+    return proc;
 }
 
+/**
+ * Frees the specified proc entry.  No-op if passed a null pointer.
+ */
 static void
-ble_gattc_entry_free(struct ble_gattc_entry *entry)
+ble_gattc_proc_free(struct ble_gattc_proc *proc)
 {
     int rc;
 
-    rc = os_memblock_put(&ble_gattc_entry_pool, entry);
-    assert(rc == 0);
+    if (proc != NULL) {
+        rc = os_memblock_put(&ble_gattc_proc_pool, proc);
+        assert(rc == 0);
+    }
 }
 
+/**
+ * Removes the specified proc entry from the global list without freeing it.
+ *
+ * @param proc                  The proc to remove.
+ * @param prev                  The proc that is previous to "proc" in the
+ *                                  list; null if "proc" is the list head.
+ */
 static void
-ble_gattc_entry_remove(struct ble_gattc_entry *entry,
-                       struct ble_gattc_entry *prev)
+ble_gattc_proc_remove(struct ble_gattc_proc *proc, struct ble_gattc_proc *prev)
 {
     if (prev == NULL) {
-        assert(STAILQ_FIRST(&ble_gattc_list) == entry);
+        assert(STAILQ_FIRST(&ble_gattc_list) == proc);
         STAILQ_REMOVE_HEAD(&ble_gattc_list, next);
     } else {
-        assert(STAILQ_NEXT(prev, next) == entry);
-        STAILQ_NEXT(prev, next) = STAILQ_NEXT(entry, next);
+        assert(STAILQ_NEXT(prev, next) == proc);
+        STAILQ_NEXT(prev, next) = STAILQ_NEXT(proc, next);
     }
 }
 
+/**
+ * Removes and frees the speicifed proc entry.
+ *
+ * @param proc                  The proc to remove and free.
+ * @param prev                  The proc that is previous to "proc" in the
+ *                                  list; null if "proc" is the list head.
+ */
 static void
-ble_gattc_entry_remove_free(struct ble_gattc_entry *entry,
-                            struct ble_gattc_entry *prev)
+ble_gattc_proc_remove_free(struct ble_gattc_proc *proc,
+                           struct ble_gattc_proc *prev)
 {
-    ble_gattc_entry_remove(entry, prev);
-    ble_gattc_entry_free(entry);
+    ble_gattc_proc_remove(proc, prev);
+    ble_gattc_proc_free(proc);
 }
 
+/**
+ * Tests if a proc entry fits the specified criteria.
+ *
+ * @param proc                  The procedure to test.
+ * @param conn_handle           The connection handle to match against.
+ * @param op                    The op code to match against, or
+ *                                  BLE_GATT_OP_NONE to ignore this criterion.
+ * @param expecting_only        1=Only match entries expecting a response;
+ *                                  0=Ignore this criterion.
+ *
+ * @return                      1 if the proc matches; 0 otherwise.
+ */
 static int
-ble_gattc_entry_matches(struct ble_gattc_entry *entry, uint16_t conn_handle,
-                        uint8_t att_op, int expecting_only)
+ble_gattc_proc_matches(struct ble_gattc_proc *proc, uint16_t conn_handle,
+                       uint8_t op, int expecting_only)
 {
-    if (conn_handle != entry->conn_handle) {
+    if (conn_handle != proc->conn_handle) {
         return 0;
     }
 
-    if (att_op != entry->op && att_op != BLE_GATT_OP_NONE) {
+    if (op != proc->op && op != BLE_GATT_OP_NONE) {
         return 0;
     }
 
     if (expecting_only &&
-        !(entry->flags & BLE_GATT_ENTRY_F_EXPECTING)) {
+        !(proc->flags & BLE_GATT_ENTRY_F_EXPECTING)) {
 
         return 0;
     }
@@ -517,59 +593,94 @@ ble_gattc_entry_matches(struct ble_gattc_entry *entry, uint16_t conn_handle,
     return 1;
 }
 
-static struct ble_gattc_entry *
-ble_gattc_find(uint16_t conn_handle, uint8_t att_op, int expecting_only,
-               struct ble_gattc_entry **out_prev)
+/**
+ * Searched the global proc list for an entry that fits the specified criteria.
+ *
+ * @param conn_handle           The connection handle to match against.
+ * @param op                    The op code to match against, or
+ *                                  BLE_GATT_OP_NONE to ignore this criterion.
+ * @param expecting_only        1=Only match entries expecting a response;
+ *                                  0=Ignore this criterion.
+ * @param out_prev              On success, the address of the result's
+ *                                  previous entry gets written here.  Pass
+ *                                  null if you don't need this information.
+ *
+ * @return                      1 if the proc matches; 0 otherwise.
+ */
+static struct ble_gattc_proc *
+ble_gattc_proc_find(uint16_t conn_handle, uint8_t op, int expecting_only,
+                    struct ble_gattc_proc **out_prev)
 {
-    struct ble_gattc_entry *entry;
-    struct ble_gattc_entry *prev;
+    struct ble_gattc_proc *proc;
+    struct ble_gattc_proc *prev;
 
     prev = NULL;
-    STAILQ_FOREACH(entry, &ble_gattc_list, next) {
-        if (ble_gattc_entry_matches(entry, conn_handle, att_op,
-                                    expecting_only)) {
+    STAILQ_FOREACH(proc, &ble_gattc_list, next) {
+        if (ble_gattc_proc_matches(proc, conn_handle, op, expecting_only)) {
             if (out_prev != NULL) {
                 *out_prev = prev;
             }
-            return entry;
+            return proc;
         }
 
-        prev = entry;
+        prev = proc;
     }
 
     return NULL;
 }
 
+/**
+ * Sets the specified proc entry's "pending" flag (i.e., indicates that the
+ * GATT procedure is stalled until it transmits its next ATT request.
+ */
 static void
-ble_gattc_entry_set_pending(struct ble_gattc_entry *entry)
+ble_gattc_proc_set_pending(struct ble_gattc_proc *proc)
 {
-    assert(!(entry->flags & BLE_GATT_ENTRY_F_PENDING));
+    assert(!(proc->flags & BLE_GATT_ENTRY_F_PENDING));
 
-    entry->flags &= ~BLE_GATT_ENTRY_F_EXPECTING;
-    entry->flags |= BLE_GATT_ENTRY_F_PENDING;
+    proc->flags &= ~BLE_GATT_ENTRY_F_EXPECTING;
+    proc->flags |= BLE_GATT_ENTRY_F_PENDING;
     ble_hs_kick_gatt();
 }
 
+/**
+ * Sets the specified proc entry's "expecting" flag (i.e., indicates that the
+ * GATT procedure is stalled until it receives an ATT response.
+ */
 static void
-ble_gattc_entry_set_expecting(struct ble_gattc_entry *entry,
-                              struct ble_gattc_entry *prev)
+ble_gattc_proc_set_expecting(struct ble_gattc_proc *proc,
+                             struct ble_gattc_proc *prev)
 {
-    assert(!(entry->flags & BLE_GATT_ENTRY_F_EXPECTING));
+    assert(!(proc->flags & BLE_GATT_ENTRY_F_EXPECTING));
 
-    ble_gattc_entry_remove(entry, prev);
-    entry->flags &= ~BLE_GATT_ENTRY_F_PENDING;
-    entry->flags |= BLE_GATT_ENTRY_F_EXPECTING;
-    entry->tx_time = os_time_get();
-    STAILQ_INSERT_TAIL(&ble_gattc_list, entry, next);
+    ble_gattc_proc_remove(proc, prev);
+    proc->flags &= ~BLE_GATT_ENTRY_F_PENDING;
+    proc->flags |= BLE_GATT_ENTRY_F_EXPECTING;
+    proc->tx_time = os_time_get();
+    STAILQ_INSERT_TAIL(&ble_gattc_list, proc, next);
 }
 
+/**
+ * Creates a new proc entry and sets its fields to the specified values.  The
+ * entry is automatically inserted into the global proc list, and its "pending"
+ * flag is set.
+ *
+ * @param conn_handle           The handle of the connection associated with
+ *                                  the GATT procedure.
+ * @param op                    The op code for the proc entry (one of the
+ *                                  BLE_GATT_OP_[...] constants).
+ * @param out_proc              On success, the new entry's address gets
+ *                                  written here.
+ *
+ * @return                      0 on success; BLE_HS error code on failure.
+ */
 static int
-ble_gattc_new_entry(uint16_t conn_handle, uint8_t op,
-                    struct ble_gattc_entry **entry)
+ble_gattc_new_proc(uint16_t conn_handle, uint8_t op,
+                   struct ble_gattc_proc **out_proc)
 {
     struct ble_hs_conn *conn;
 
-    *entry = NULL;
+    *out_proc = NULL;
 
     /* Ensure we have a connection with the specified handle. */
     conn = ble_hs_conn_find(conn_handle);
@@ -577,48 +688,106 @@ ble_gattc_new_entry(uint16_t conn_handle, uint8_t op,
         return BLE_HS_ENOTCONN;
     }
 
-    *entry = ble_gattc_entry_alloc();
-    if (*entry == NULL) {
+    *out_proc = ble_gattc_proc_alloc();
+    if (*out_proc == NULL) {
         return BLE_HS_ENOMEM;
     }
 
-    memset(*entry, 0, sizeof **entry);
-    (*entry)->op = op;
-    (*entry)->conn_handle = conn_handle;
+    memset(*out_proc, 0, sizeof **out_proc);
+    (*out_proc)->op = op;
+    (*out_proc)->conn_handle = conn_handle;
 
-    STAILQ_INSERT_TAIL(&ble_gattc_list, *entry, next);
+    STAILQ_INSERT_TAIL(&ble_gattc_list, *out_proc, next);
 
-    ble_gattc_entry_set_pending(*entry);
+    ble_gattc_proc_set_pending(*out_proc);
 
     return 0;
 }
 
+/**
+ * Determines if the specified proc entry's "pending" flag can be set.
+ */
+static int
+ble_gattc_proc_can_pend(struct ble_gattc_proc *proc)
+{
+    return !(proc->flags & (BLE_GATT_ENTRY_F_CONGESTED |
+                            BLE_GATT_ENTRY_F_NO_MEM |
+                            BLE_GATT_ENTRY_F_EXPECTING));
+}
+
+/**
+ * Postpones tx for the specified proc entry if appropriate.  The determination
+ * of whether tx should be postponed is based on the return code of the
+ * previous transmit attempt.  This function should be called immediately after
+ * transmission fails.  A tx can be postponed if the failure was caused by
+ * congestion or memory exhaustion.  All other failures cannot be postponed,
+ * and the procedure should be aborted entirely.
+ *
+ * @param proc                  The proc entry to check for postponement.
+ * @param rc                    The return code of the previous tx attempt.
+ *
+ * @return                      1 if the transmit should be postponed; else 0.
+ */
 static int
-ble_gattc_entry_can_pend(struct ble_gattc_entry *entry)
+ble_gattc_tx_postpone_chk(struct ble_gattc_proc *proc, int rc)
+{
+    switch (rc) {
+    case BLE_HS_ECONGESTED:
+        proc->flags |= BLE_GATT_ENTRY_F_CONGESTED;
+        return 1;
+
+    case BLE_HS_ENOMEM:
+        proc->flags |= BLE_GATT_ENTRY_F_NO_MEM;
+        return 1;
+
+    default:
+        return 0;
+    }
+}
+
+/*****************************************************************************
+ * $util                                                                     *
+ *****************************************************************************/
+
+/**
+ * Retrieves the dispatch entry with the specified op code.
+ */
+static const struct ble_gattc_dispatch_entry *
+ble_gattc_dispatch_get(uint8_t op)
 {
-    return !(entry->flags & (BLE_GATT_ENTRY_F_CONGESTED |
-                             BLE_GATT_ENTRY_F_NO_MEM |
-                             BLE_GATT_ENTRY_F_EXPECTING));
+    assert(op < BLE_GATT_OP_MAX);
+    return ble_gattc_dispatch + op;
 }
 
+/**
+ * Applies periodic checks and actions to all active procedures.
+ *
+ * All procedures that failed due to memory exaustion have their pending flag
+ * set so they can be retried.
+ *
+ * All procedures that have been expecting a response for longer than five
+ * seconds are aborted, and their corresponding connection is terminated.
+ *
+ * Called by the heartbeat timer; executed every second.
+ */
 static void
-ble_gattc_heartbeat(void *arg)
+ble_gattc_heartbeat(void *unused)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     uint32_t now;
     int rc;
 
     now = os_time_get();
 
-    STAILQ_FOREACH(entry, &ble_gattc_list, next) {
-        if (entry->flags & BLE_GATT_ENTRY_F_NO_MEM) {
-            entry->flags &= ~BLE_GATT_ENTRY_F_NO_MEM;
-            if (ble_gattc_entry_can_pend(entry)) {
-                ble_gattc_entry_set_pending(entry);
+    STAILQ_FOREACH(proc, &ble_gattc_list, next) {
+        if (proc->flags & BLE_GATT_ENTRY_F_NO_MEM) {
+            proc->flags &= ~BLE_GATT_ENTRY_F_NO_MEM;
+            if (ble_gattc_proc_can_pend(proc)) {
+                ble_gattc_proc_set_pending(proc);
             }
-        } else if (entry->flags & BLE_GATT_ENTRY_F_EXPECTING) {
-            if (now - entry->tx_time >= BLE_GATT_UNRESPONSIVE_TIMEOUT) {
-                rc = ble_gap_conn_terminate(entry->conn_handle);
+        } else if (proc->flags & BLE_GATT_ENTRY_F_EXPECTING) {
+            if (now - proc->tx_time >= BLE_GATT_UNRESPONSIVE_TIMEOUT) {
+                rc = ble_gap_conn_terminate(proc->conn_handle);
                 assert(rc == 0); /* XXX */
             }
         }
@@ -630,25 +799,10 @@ ble_gattc_heartbeat(void *arg)
 }
 
 /**
- * @return                      1 if the transmit should be postponed; else 0.
+ * Returns a pointer to a GATT error object with the specified fields.  The
+ * returned object is statically allocated, so this function is not reentrant.
+ * This function should only ever be called by the ble_hs task.
  */
-static int
-ble_gattc_tx_postpone_chk(struct ble_gattc_entry *entry, int rc)
-{
-    switch (rc) {
-    case BLE_HS_ECONGESTED:
-        entry->flags |= BLE_GATT_ENTRY_F_CONGESTED;
-        return 1;
-
-    case BLE_HS_ENOMEM:
-        entry->flags |= BLE_GATT_ENTRY_F_NO_MEM;
-        return 1;
-
-    default:
-        return 0;
-    }
-}
-
 struct ble_gatt_error *
 ble_gattc_error(int status, uint16_t att_handle)
 {
@@ -667,32 +821,42 @@ ble_gattc_error(int status, uint16_t att_handle)
  * $mtu                                                                      *
  *****************************************************************************/
 
+/**
+ * Calls an mtu-exchange proc's callback with the specified parameters.  If the
+ * proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_mtu_cb(struct ble_gattc_entry *entry, int status,
-                 uint16_t att_handle, uint16_t mtu)
+ble_gattc_mtu_cb(struct ble_gattc_proc *proc, int status, uint16_t att_handle,
+                 uint16_t mtu)
 {
     int rc;
 
-    if (entry->mtu.cb == NULL) {
+    if (proc->mtu.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->mtu.cb(entry->conn_handle,
-                           ble_gattc_error(status, att_handle),
-                           mtu, entry->mtu.cb_arg);
+        rc = proc->mtu.cb(proc->conn_handle,
+                          ble_gattc_error(status, att_handle),
+                          mtu, proc->mtu.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified mtu-exchange proc.
+ */
 static int
-ble_gattc_mtu_kick(struct ble_gattc_entry *entry)
+ble_gattc_mtu_kick(struct ble_gattc_proc *proc)
 {
     struct ble_att_mtu_cmd req;
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
@@ -710,43 +874,57 @@ ble_gattc_mtu_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_mtu_cb(entry, rc, 0, 0);
+    ble_gattc_mtu_cb(proc, rc, 0, 0);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified mtu-exchange proc.
+ */
 static void
-ble_gattc_mtu_err(struct ble_gattc_entry *entry, int status,
-                  uint16_t att_handle)
+ble_gattc_mtu_err(struct ble_gattc_proc *proc, int status, uint16_t att_handle)
 {
-    ble_gattc_mtu_cb(entry, status, att_handle, 0);
+    ble_gattc_mtu_cb(proc, status, att_handle, 0);
 }
 
+/**
+ * Handles an incoming ATT exchange mtu response for the specified mtu-exchange
+ * proc.
+ */
 static int
-ble_gattc_mtu_rx_rsp(struct ble_gattc_entry *entry,
-                     struct ble_hs_conn *conn,
+ble_gattc_mtu_rx_rsp(struct ble_gattc_proc *proc, struct ble_hs_conn *conn,
                      uint16_t chan_mtu)
 {
-    ble_gattc_mtu_cb(entry, 0, 0, chan_mtu);
+    ble_gattc_mtu_cb(proc, 0, 0, chan_mtu);
     return 1;
 }
 
+/**
+ * Initiates GATT procedure: Exchange MTU.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_MTU, &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_MTU, &proc);
     if (rc != 0) {
         return rc;
     }
 
-    entry->mtu.cb = cb;
-    entry->mtu.cb_arg = cb_arg;
+    proc->mtu.cb = cb;
+    proc->mtu.cb_arg = cb_arg;
 
     return 0;
 }
@@ -755,33 +933,43 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
  * $discover all services                                                    *
  *****************************************************************************/
 
+/**
+ * Calls a discover-all-services proc's callback with the specified parameters.
+ * If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_disc_all_svcs_cb(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_svcs_cb(struct ble_gattc_proc *proc,
                            uint16_t status, uint16_t att_handle,
                            struct ble_gatt_service *service)
 {
     int rc;
 
-    if (entry->disc_all_svcs.cb == NULL) {
+    if (proc->disc_all_svcs.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->disc_all_svcs.cb(entry->conn_handle,
-                                     ble_gattc_error(status, att_handle),
-                                     service, entry->disc_all_svcs.cb_arg);
+        rc = proc->disc_all_svcs.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle),
+                                    service, proc->disc_all_svcs.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified discover-all-services proc.
+ */
 static int
-ble_gattc_disc_all_svcs_kick(struct ble_gattc_entry *entry)
+ble_gattc_disc_all_svcs_kick(struct ble_gattc_proc *proc)
 {
     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);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
@@ -790,7 +978,7 @@ ble_gattc_disc_all_svcs_kick(struct ble_gattc_entry *entry)
     rc = ble_uuid_16_to_128(BLE_ATT_UUID_PRIMARY_SERVICE, uuid128);
     assert(rc == 0);
 
-    req.bagq_start_handle = entry->disc_all_svcs.prev_handle + 1;
+    req.bagq_start_handle = proc->disc_all_svcs.prev_handle + 1;
     req.bagq_end_handle = 0xffff;
     rc = ble_att_clt_tx_read_group_type(conn, &req, uuid128);
     if (rc != 0) {
@@ -800,16 +988,20 @@ ble_gattc_disc_all_svcs_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_disc_all_svcs_cb(entry, rc, 0, NULL);
+    ble_gattc_disc_all_svcs_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * discover-all-services proc.
+ */
 static void
-ble_gattc_disc_all_svcs_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_all_svcs_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
     if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
@@ -817,11 +1009,15 @@ ble_gattc_disc_all_svcs_err(struct ble_gattc_entry *entry, int status,
         status = 0;
     }
 
-    ble_gattc_disc_all_svcs_cb(entry, status, att_handle, NULL);
+    ble_gattc_disc_all_svcs_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming attribute data entry from a read-group-type response for
+ * the specified discover-all-services proc.
+ */
 static int
-ble_gattc_disc_all_svcs_rx_adata(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_svcs_rx_adata(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_read_group_type_adata *adata)
 {
@@ -848,13 +1044,13 @@ ble_gattc_disc_all_svcs_rx_adata(struct ble_gattc_entry *entry,
         goto done;
     }
 
-    if (adata->end_group_handle <= entry->disc_all_svcs.prev_handle) {
+    if (adata->end_group_handle <= proc->disc_all_svcs.prev_handle) {
         /* Peer sent services out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
 
-    entry->disc_all_svcs.prev_handle = adata->end_group_handle;
+    proc->disc_all_svcs.prev_handle = adata->end_group_handle;
 
     service.start_handle = adata->att_handle;
     service.end_handle = adata->end_group_handle;
@@ -862,43 +1058,55 @@ ble_gattc_disc_all_svcs_rx_adata(struct ble_gattc_entry *entry,
     rc = 0;
 
 done:
-    cbrc = ble_gattc_disc_all_svcs_cb(entry, rc, 0, &service);
+    cbrc = ble_gattc_disc_all_svcs_cb(proc, rc, 0, &service);
     if (rc == 0) {
         rc = cbrc;
     }
     return rc;
 }
 
+/**
+ * Handles a notification that an incoming read-group-type response has been
+ * fully processed.
+ */
 static int
-ble_gattc_disc_all_svcs_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_svcs_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->disc_all_svcs.prev_handle == 0xffff) {
+    if (status != 0 || proc->disc_all_svcs.prev_handle == 0xffff) {
         /* Error or all svcs discovered. */
-        ble_gattc_disc_all_svcs_cb(entry, status, 0, NULL);
+        ble_gattc_disc_all_svcs_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Discover All Primary Services.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
                         void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_ALL_SVCS,
-                             &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_DISC_ALL_SVCS, &proc);
     if (rc != 0) {
         return rc;
     }
-    entry->disc_all_svcs.prev_handle = 0x0000;
-    entry->disc_all_svcs.cb = cb;
-    entry->disc_all_svcs.cb_arg = cb_arg;
+    proc->disc_all_svcs.prev_handle = 0x0000;
+    proc->disc_all_svcs.cb = cb;
+    proc->disc_all_svcs.cb_arg = cb_arg;
 
     return 0;
 }
@@ -907,43 +1115,53 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
  * $discover service by uuid                                                 *
  *****************************************************************************/
 
+/**
+ * Calls a discover-service-by-uuid proc's callback with the specified
+ * parameters.  If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_disc_svc_uuid_cb(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_svc_uuid_cb(struct ble_gattc_proc *proc, int status,
                            uint16_t att_handle,
                            struct ble_gatt_service *service)
 {
     int rc;
 
-    if (entry->disc_svc_uuid.cb == NULL) {
+    if (proc->disc_svc_uuid.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->disc_svc_uuid.cb(entry->conn_handle,
-                                     ble_gattc_error(status, att_handle),
-                                     service, entry->disc_svc_uuid.cb_arg);
+        rc = proc->disc_svc_uuid.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle),
+                                    service, proc->disc_svc_uuid.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified discover-service-by-uuid proc.
+ */
 static int
-ble_gattc_disc_svc_uuid_kick(struct ble_gattc_entry *entry)
+ble_gattc_disc_svc_uuid_kick(struct ble_gattc_proc *proc)
 {
     struct ble_att_find_type_value_req req;
     struct ble_hs_conn *conn;
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
     }
 
-    req.bavq_start_handle = entry->disc_svc_uuid.prev_handle + 1;
+    req.bavq_start_handle = proc->disc_svc_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_svc_uuid.service_uuid, 16);
+                                        proc->disc_svc_uuid.service_uuid, 16);
     if (rc != 0) {
         goto err;
     }
@@ -951,16 +1169,20 @@ ble_gattc_disc_svc_uuid_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_disc_svc_uuid_cb(entry, rc, 0, NULL);
+    ble_gattc_disc_svc_uuid_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * discover-service-by-uuid proc.
+ */
 static void
-ble_gattc_disc_svc_uuid_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_svc_uuid_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
     if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
@@ -968,11 +1190,15 @@ ble_gattc_disc_svc_uuid_err(struct ble_gattc_entry *entry, int status,
         status = 0;
     }
 
-    ble_gattc_disc_svc_uuid_cb(entry, status, att_handle, NULL);
+    ble_gattc_disc_svc_uuid_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming "handles info" entry from a find-type-value response for
+ * the specified discover-service-by-uuid proc.
+ */
 static int
-ble_gattc_disc_svc_uuid_rx_hinfo(struct ble_gattc_entry *entry,
+ble_gattc_disc_svc_uuid_rx_hinfo(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_find_type_value_hinfo *hinfo)
 {
@@ -980,87 +1206,110 @@ ble_gattc_disc_svc_uuid_rx_hinfo(struct ble_gattc_entry *entry,
     int cbrc;
     int rc;
 
-    if (hinfo->group_end_handle <= entry->disc_svc_uuid.prev_handle) {
+    if (hinfo->group_end_handle <= proc->disc_svc_uuid.prev_handle) {
         /* Peer sent services out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
 
-    entry->disc_svc_uuid.prev_handle = hinfo->group_end_handle;
+    proc->disc_svc_uuid.prev_handle = hinfo->group_end_handle;
 
     service.start_handle = hinfo->attr_handle;
     service.end_handle = hinfo->group_end_handle;
-    memcpy(service.uuid128, entry->disc_svc_uuid.service_uuid, 16);
+    memcpy(service.uuid128, proc->disc_svc_uuid.service_uuid, 16);
 
     rc = 0;
 
 done:
-    cbrc = ble_gattc_disc_svc_uuid_cb(entry, rc, 0, &service);
+    cbrc = ble_gattc_disc_svc_uuid_cb(proc, rc, 0, &service);
     if (rc != 0) {
         rc = cbrc;
     }
     return rc;
 }
 
+/**
+ * Handles a notification that a find-type-value response has been fully
+ * processed for the specified discover-service-by-uuid proc.
+ */
 static int
-ble_gattc_disc_svc_uuid_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_disc_svc_uuid_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->disc_svc_uuid.prev_handle == 0xffff) {
+    if (status != 0 || proc->disc_svc_uuid.prev_handle == 0xffff) {
         /* Error or all svcs discovered. */
-        ble_gattc_disc_svc_uuid_cb(entry, status, 0, NULL);
+        ble_gattc_disc_svc_uuid_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Discover Primary Service by Service UUID.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param service_uuid128       The 128-bit UUID of the service to discover.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, void *service_uuid128,
                            ble_gatt_disc_svc_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_SVC_UUID,
-                             &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_DISC_SVC_UUID, &proc);
     if (rc != 0) {
         return rc;
     }
-    memcpy(entry->disc_svc_uuid.service_uuid, service_uuid128, 16);
-    entry->disc_svc_uuid.prev_handle = 0x0000;
-    entry->disc_svc_uuid.cb = cb;
-    entry->disc_svc_uuid.cb_arg = cb_arg;
+    memcpy(proc->disc_svc_uuid.service_uuid, service_uuid128, 16);
+    proc->disc_svc_uuid.prev_handle = 0x0000;
+    proc->disc_svc_uuid.cb = cb;
+    proc->disc_svc_uuid.cb_arg = cb_arg;
 
     return 0;
 }
 
 /*****************************************************************************
- * $find included svcs                                                   *
+ * $find included svcs                                                       *
  *****************************************************************************/
 
+/**
+ * Calls a find-included-services proc's callback with the specified
+ * parameters.  If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_find_inc_svcs_cb(struct ble_gattc_entry *entry, int status,
+ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status,
                            uint16_t att_handle,
                            struct ble_gatt_service *service)
 {
     int rc;
 
-    if (entry->find_inc_svcs.cb == NULL) {
+    if (proc->find_inc_svcs.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->find_inc_svcs.cb(entry->conn_handle,
-                                     ble_gattc_error(status, att_handle),
-                                     service, entry->find_inc_svcs.cb_arg);
+        rc = proc->find_inc_svcs.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle),
+                                    service, proc->find_inc_svcs.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified find-included-services proc.
+ */
 static int
-ble_gattc_find_inc_svcs_kick(struct ble_gattc_entry *entry)
+ble_gattc_find_inc_svcs_kick(struct ble_gattc_proc *proc)
 {
     struct ble_att_read_type_req read_type_req;
     struct ble_att_read_req read_req;
@@ -1068,16 +1317,16 @@ ble_gattc_find_inc_svcs_kick(struct ble_gattc_entry *entry)
     uint8_t uuid128[16];
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
     }
 
-    if (entry->find_inc_svcs.cur_start == 0) {
+    if (proc->find_inc_svcs.cur_start == 0) {
         /* Find the next included service. */
-        read_type_req.batq_start_handle = entry->find_inc_svcs.prev_handle + 1;
-        read_type_req.batq_end_handle = entry->find_inc_svcs.end_handle;
+        read_type_req.batq_start_handle = proc->find_inc_svcs.prev_handle + 1;
+        read_type_req.batq_end_handle = proc->find_inc_svcs.end_handle;
 
         rc = ble_uuid_16_to_128(BLE_ATT_UUID_INCLUDE, uuid128);
         assert(rc == 0);
@@ -1085,7 +1334,7 @@ ble_gattc_find_inc_svcs_kick(struct ble_gattc_entry *entry)
         rc = ble_att_clt_tx_read_type(conn, &read_type_req, uuid128);
     } else {
         /* Read the UUID of the previously found service. */
-        read_req.barq_handle = entry->find_inc_svcs.cur_start;
+        read_req.barq_handle = proc->find_inc_svcs.cur_start;
         rc = ble_att_clt_tx_read(conn, &read_req);
     }
     if (rc != 0) {
@@ -1095,30 +1344,38 @@ ble_gattc_find_inc_svcs_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_find_inc_svcs_cb(entry, rc, 0, NULL);
+    ble_gattc_find_inc_svcs_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * find-included-services proc.
+ */
 static void
-ble_gattc_find_inc_svcs_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_find_inc_svcs_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
-    if (entry->find_inc_svcs.cur_start == 0 &&
+    if (proc->find_inc_svcs.cur_start == 0 &&
         status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
 
         /* Discovery is complete. */
         status = 0;
     }
 
-    ble_gattc_find_inc_svcs_cb(entry, status, att_handle, NULL);
+    ble_gattc_find_inc_svcs_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming read-response for the specified find-included-services
+ * proc.
+ */
 static int
-ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_entry *entry,
+ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status,
                                     void *value, int value_len)
 {
@@ -1126,7 +1383,7 @@ ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_entry *entry,
     int cbrc;
     int rc;
 
-    if (entry->find_inc_svcs.cur_start == 0) {
+    if (proc->find_inc_svcs.cur_start == 0) {
         /* Unexpected read response; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
@@ -1143,27 +1400,31 @@ ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_entry *entry,
         goto done;
     }
 
-    service.start_handle = entry->find_inc_svcs.cur_start;
-    service.end_handle = entry->find_inc_svcs.cur_end;
+    service.start_handle = proc->find_inc_svcs.cur_start;
+    service.end_handle = proc->find_inc_svcs.cur_end;
     memcpy(service.uuid128, value, 16);
 
     /* We are done with this service; proceed to the next. */
-    entry->find_inc_svcs.cur_start = 0;
-    entry->find_inc_svcs.cur_end = 0;
-    ble_gattc_entry_set_pending(entry);
+    proc->find_inc_svcs.cur_start = 0;
+    proc->find_inc_svcs.cur_end = 0;
+    ble_gattc_proc_set_pending(proc);
 
     rc = 0;
 
 done:
-    cbrc = ble_gattc_find_inc_svcs_cb(entry, rc, 0, &service);
+    cbrc = ble_gattc_find_inc_svcs_cb(proc, rc, 0, &service);
     if (rc == 0) {
         rc = cbrc;
     }
     return rc;
 }
 
+/**
+ * Handles an incoming "attribute data" entry from a read-by-type response for
+ * the specified find-included-services proc.
+ */
 static int
-ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_entry *entry,
+ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_read_type_adata *adata)
 {
@@ -1173,7 +1434,7 @@ ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_entry *entry,
     int cbrc;
     int rc;
 
-    if (entry->find_inc_svcs.cur_start != 0) {
+    if (proc->find_inc_svcs.cur_start != 0) {
         /* We only read one 128-bit UUID service at a time.  Ignore the
          * additional services in the response.
          */
@@ -1182,18 +1443,18 @@ ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_entry *entry,
 
     call_cb = 1;
 
-    if (adata->att_handle <= entry->find_inc_svcs.prev_handle) {
+    if (adata->att_handle <= proc->find_inc_svcs.prev_handle) {
         /* Peer sent services out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
 
-    entry->find_inc_svcs.prev_handle = adata->att_handle;
+    proc->find_inc_svcs.prev_handle = adata->att_handle;
 
     switch (adata->value_len) {
     case BLE_GATTS_INC_SVC_LEN_NO_UUID:
-        entry->find_inc_svcs.cur_start = le16toh(adata->value + 0);
-        entry->find_inc_svcs.cur_end = le16toh(adata->value + 2);
+        proc->find_inc_svcs.cur_start = le16toh(adata->value + 0);
+        proc->find_inc_svcs.cur_end = le16toh(adata->value + 2);
         call_cb = 0;
         break;
 
@@ -1217,7 +1478,7 @@ ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_entry *entry,
 
 done:
     if (call_cb) {
-        cbrc = ble_gattc_find_inc_svcs_cb(entry, 0, 0, &service);
+        cbrc = ble_gattc_find_inc_svcs_cb(proc, 0, 0, &service);
         if (rc != 0) {
             rc = cbrc;
         }
@@ -1226,37 +1487,54 @@ done:
     return rc;
 }
 
+/**
+ * Handles a notification that a read-by-type response has been fully
+ * processed for the specified find-included-services proc.
+ */
 static int
-ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->find_inc_svcs.prev_handle == 0xffff) {
+    if (status != 0 || proc->find_inc_svcs.prev_handle == 0xffff) {
         /* Error or all svcs discovered. */
-        ble_gattc_find_inc_svcs_cb(entry, status, 0, NULL);
+        ble_gattc_find_inc_svcs_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Find Included Services.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param start_handle          The handle to begin the search at (generally
+ *                                  the service definition handle).
+ * @param end_handle            The handle to end the search at (generally the
+ *                                  last handle in the service).
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
                         uint16_t end_handle,
                         ble_gatt_disc_svc_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_FIND_INC_SVCS, &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_FIND_INC_SVCS, &proc);
     if (rc != 0) {
         return rc;
     }
-    entry->find_inc_svcs.prev_handle = start_handle - 1;
-    entry->find_inc_svcs.end_handle = end_handle;
-    entry->find_inc_svcs.cb = cb;
-    entry->find_inc_svcs.cb_arg = cb_arg;
+    proc->find_inc_svcs.prev_handle = start_handle - 1;
+    proc->find_inc_svcs.end_handle = end_handle;
+    proc->find_inc_svcs.cb = cb;
+    proc->find_inc_svcs.cb_arg = cb_arg;
 
     return 0;
 }
@@ -1265,33 +1543,43 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
  * $discover all characteristics                                             *
  *****************************************************************************/
 
+/**
+ * Calls a discover-all-characteristics proc's callback with the specified
+ * parameters.  If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_disc_all_chrs_cb(struct ble_gattc_entry *entry, int status,
-                           uint16_t att_handle,
-                           struct ble_gatt_chr *chr)
+ble_gattc_disc_all_chrs_cb(struct ble_gattc_proc *proc, int status,
+                           uint16_t att_handle, struct ble_gatt_chr *chr)
 {
     int rc;
 
-    if (entry->disc_all_chrs.cb == NULL) {
+    if (proc->disc_all_chrs.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->disc_all_chrs.cb(entry->conn_handle, 
-                                     ble_gattc_error(status, att_handle), chr,
-                                     entry->disc_all_chrs.cb_arg);
+        rc = proc->disc_all_chrs.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle), chr,
+                                    proc->disc_all_chrs.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified discover-all-characteristics
+ * proc.
+ */
 static int
-ble_gattc_disc_all_chrs_kick(struct ble_gattc_entry *entry)
+ble_gattc_disc_all_chrs_kick(struct ble_gattc_proc *proc)
 {
     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);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
@@ -1300,8 +1588,8 @@ ble_gattc_disc_all_chrs_kick(struct ble_gattc_entry *entry)
     rc = ble_uuid_16_to_128(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
     assert(rc == 0);
 
-    req.batq_start_handle = entry->disc_all_chrs.prev_handle + 1;
-    req.batq_end_handle = entry->disc_all_chrs.end_handle;
+    req.batq_start_handle = proc->disc_all_chrs.prev_handle + 1;
+    req.batq_end_handle = proc->disc_all_chrs.end_handle;
 
     rc = ble_att_clt_tx_read_type(conn, &req, uuid128);
     if (rc != 0) {
@@ -1311,16 +1599,20 @@ ble_gattc_disc_all_chrs_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_disc_all_chrs_cb(entry, rc, 0, NULL);
+    ble_gattc_disc_all_chrs_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * discover-all-characteristics proc.
+ */
 static void
-ble_gattc_disc_all_chrs_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_all_chrs_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
     if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
@@ -1328,11 +1620,15 @@ ble_gattc_disc_all_chrs_err(struct ble_gattc_entry *entry, int status,
         status = 0;
     }
 
-    ble_gattc_disc_all_chrs_cb(entry, status, att_handle, NULL);
+    ble_gattc_disc_all_chrs_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming "attribute data" entry from a read-by-type response for
+ * the specified discover-all-characteristics proc.
+ */
 static int
-ble_gattc_disc_all_chrs_rx_adata(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_chrs_rx_adata(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_read_type_adata *adata)
 {
@@ -1366,17 +1662,17 @@ ble_gattc_disc_all_chrs_rx_adata(struct ble_gattc_entry *entry,
     chr.properties = adata->value[0];
     chr.value_handle = le16toh(adata->value + 1);
 
-    if (adata->att_handle <= entry->disc_all_chrs.prev_handle) {
+    if (adata->att_handle <= proc->disc_all_chrs.prev_handle) {
         /* Peer sent characteristics out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
-    entry->disc_all_chrs.prev_handle = adata->att_handle;
+    proc->disc_all_chrs.prev_handle = adata->att_handle;
 
     rc = 0;
 
 done:
-    cbrc = ble_gattc_disc_all_chrs_cb(entry, rc, 0, &chr);
+    cbrc = ble_gattc_disc_all_chrs_cb(proc, rc, 0, &chr);
     if (rc == 0) {
         rc = cbrc;
     }
@@ -1384,38 +1680,56 @@ done:
     return rc;
 }
 
+/**
+ * Handles a notification that a read-by-type response has been fully
+ * processed for the specified discover-all-characteristics proc.
+ */
 static int
-ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->disc_all_chrs.prev_handle ==
-                       entry->disc_all_chrs.end_handle) {
+    if (status != 0 ||
+        proc->disc_all_chrs.prev_handle == proc->disc_all_chrs.end_handle) {
+
         /* Error or all svcs discovered. */
-        ble_gattc_disc_all_chrs_cb(entry, status, 0, NULL);
+        ble_gattc_disc_all_chrs_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Discover All Characteristics of a Service.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param start_handle          The handle to begin the search at (generally
+ *                                  the service definition handle).
+ * @param end_handle            The handle to end the search at (generally the
+ *                                  last handle in the service).
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
                         uint16_t end_handle, ble_gatt_chr_fn *cb,
                         void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_ALL_CHRS, &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_DISC_ALL_CHRS, &proc);
     if (rc != 0) {
         return rc;
     }
-    entry->disc_all_chrs.prev_handle = start_handle - 1;
-    entry->disc_all_chrs.end_handle = end_handle;
-    entry->disc_all_chrs.cb = cb;
-    entry->disc_all_chrs.cb_arg = cb_arg;
+    proc->disc_all_chrs.prev_handle = start_handle - 1;
+    proc->disc_all_chrs.end_handle = end_handle;
+    proc->disc_all_chrs.cb = cb;
+    proc->disc_all_chrs.cb_arg = cb_arg;
 
     return 0;
 }
@@ -1424,32 +1738,43 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
  * $discover characteristic by uuid                                          *
  *****************************************************************************/
 
+/**
+ * Calls a discover-characteristic-by-uuid proc's callback with the specified
+ * parameters.  If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_disc_chr_uuid_cb(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_chr_uuid_cb(struct ble_gattc_proc *proc, int status,
                            uint16_t att_handle, struct ble_gatt_chr *chr)
 {
     int rc;
 
-    if (entry->disc_chr_uuid.cb == NULL) {
+    if (proc->disc_chr_uuid.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->disc_chr_uuid.cb(entry->conn_handle, 
-                                     ble_gattc_error(status, att_handle), chr,
-                                     entry->disc_chr_uuid.cb_arg);
+        rc = proc->disc_chr_uuid.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle), chr,
+                                    proc->disc_chr_uuid.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified
+ * discover-characteristic-by-uuid proc.
+ */
 static int
-ble_gattc_disc_chr_uuid_kick(struct ble_gattc_entry *entry)
+ble_gattc_disc_chr_uuid_kick(struct ble_gattc_proc *proc)
 {
     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);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
@@ -1458,8 +1783,8 @@ ble_gattc_disc_chr_uuid_kick(struct ble_gattc_entry *entry)
     rc = ble_uuid_16_to_128(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
     assert(rc == 0);
 
-    req.batq_start_handle = entry->disc_chr_uuid.prev_handle + 1;
-    req.batq_end_handle = entry->disc_chr_uuid.end_handle;
+    req.batq_start_handle = proc->disc_chr_uuid.prev_handle + 1;
+    req.batq_end_handle = proc->disc_chr_uuid.end_handle;
 
     rc = ble_att_clt_tx_read_type(conn, &req, uuid128);
     if (rc != 0) {
@@ -1469,16 +1794,20 @@ ble_gattc_disc_chr_uuid_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_disc_chr_uuid_cb(entry, rc, 0, NULL);
+    ble_gattc_disc_chr_uuid_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * discover-characteristic-by-uuid proc.
+ */
 static void
-ble_gattc_disc_chr_uuid_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_chr_uuid_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
     if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
@@ -1486,11 +1815,15 @@ ble_gattc_disc_chr_uuid_err(struct ble_gattc_entry *entry, int status,
         status = 0;
     }
 
-    ble_gattc_disc_chr_uuid_cb(entry, status, att_handle, NULL);
+    ble_gattc_disc_chr_uuid_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming "attribute data" entry from a read-by-type response for
+ * the specified discover-characteristics-by-uuid proc.
+ */
 static int
-ble_gattc_disc_chr_uuid_rx_adata(struct ble_gattc_entry *entry,
+ble_gattc_disc_chr_uuid_rx_adata(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_read_type_adata *adata)
 {
@@ -1524,21 +1857,21 @@ ble_gattc_disc_chr_uuid_rx_adata(struct ble_gattc_entry *entry,
     chr.properties = adata->value[0];
     chr.value_handle = le16toh(adata->value + 1);
 
-    if (adata->att_handle <= entry->disc_chr_uuid.prev_handle) {
+    if (adata->att_handle <= proc->disc_chr_uuid.prev_handle) {
         /* Peer sent characteristics out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
 
-    entry->disc_chr_uuid.prev_handle = adata->att_handle;
+    proc->disc_chr_uuid.prev_handle = adata->att_handle;
 
     rc = 0;
 
 done:
     if (rc != 0 ||
-        memcmp(chr.uuid128, entry->disc_chr_uuid.chr_uuid, 16) == 0) {
+        memcmp(chr.uuid128, proc->disc_chr_uuid.chr_uuid, 16) == 0) {
 
-        cbrc = ble_gattc_disc_chr_uuid_cb(entry, rc, 0, &chr);
+        cbrc = ble_gattc_disc_chr_uuid_cb(proc, rc, 0, &chr);
         if (rc == 0) {
             rc = cbrc;
         }
@@ -1547,39 +1880,59 @@ done:
     return rc;
 }
 
+/**
+ * Handles a notification that a read-by-type response has been fully
+ * processed for the specified discover-characteristics-by-uuid proc.
+ */
 static int
-ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->disc_chr_uuid.prev_handle ==
-                       entry->disc_chr_uuid.end_handle) {
+    if (status != 0 ||
+        proc->disc_chr_uuid.prev_handle == proc->disc_chr_uuid.end_handle) {
+
         /* Error or all svcs discovered. */
-        ble_gattc_disc_chr_uuid_cb(entry, status, 0, NULL);
+        ble_gattc_disc_chr_uuid_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Discover Characteristics by UUID.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param start_handle          The handle to begin the search at (generally
+ *                                  the service definition handle).
+ * @param end_handle            The handle to end the search at (generally the
+ *                                  last handle in the service).
+ * @param chr_uuid128           The 128-bit UUID of the characteristic to
+ *                                  discover.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
                             uint16_t end_handle, void *uuid128,
                             ble_gatt_chr_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_CHRS_UUID, &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_DISC_CHRS_UUID, &proc);
     if (rc != 0) {
         return rc;
     }
-    memcpy(entry->disc_chr_uuid.chr_uuid, uuid128, 16);
-    entry->disc_chr_uuid.prev_handle = start_handle - 1;
-    entry->disc_chr_uuid.end_handle = end_handle;
-    entry->disc_chr_uuid.cb = cb;
-    entry->disc_chr_uuid.cb_arg = cb_arg;
+    memcpy(proc->disc_chr_uuid.chr_uuid, uuid128, 16);
+    proc->disc_chr_uuid.prev_handle = start_handle - 1;
+    proc->disc_chr_uuid.end_handle = end_handle;
+    proc->disc_chr_uuid.cb = cb;
+    proc->disc_chr_uuid.cb_arg = cb_arg;
 
     return 0;
 }
@@ -1588,39 +1941,49 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
  * $discover all characteristic descriptors                                  *
  *****************************************************************************/
 
+/**
+ * Calls a discover-all-descriptors proc's callback with the specified
+ * parameters.  If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_disc_all_dscs_cb(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_all_dscs_cb(struct ble_gattc_proc *proc, int status,
                            uint16_t att_handle, struct ble_gatt_dsc *dsc)
 {
     int rc;
 
-    if (entry->disc_all_dscs.cb == NULL) {
+    if (proc->disc_all_dscs.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->disc_all_dscs.cb(entry->conn_handle,
-                                     ble_gattc_error(status, att_handle),
-                                     entry->disc_all_dscs.chr_val_handle,
-                                     dsc, entry->disc_all_dscs.cb_arg);
+        rc = proc->disc_all_dscs.cb(proc->conn_handle,
+                                    ble_gattc_error(status, att_handle),
+                                    proc->disc_all_dscs.chr_val_handle,
+                                    dsc, proc->disc_all_dscs.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified discover-all-descriptors proc.
+ */
 static int
-ble_gattc_disc_all_dscs_kick(struct ble_gattc_entry *entry)
+ble_gattc_disc_all_dscs_kick(struct ble_gattc_proc *proc)
 {
     struct ble_att_find_info_req req;
     struct ble_hs_conn *conn;
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
     }
 
-    req.bafq_start_handle = entry->disc_all_dscs.prev_handle + 1;
-    req.bafq_end_handle = entry->disc_all_dscs.end_handle;
+    req.bafq_start_handle = proc->disc_all_dscs.prev_handle + 1;
+    req.bafq_end_handle = proc->disc_all_dscs.end_handle;
 
     rc = ble_att_clt_tx_find_info(conn, &req);
     if (rc != 0) {
@@ -1630,16 +1993,20 @@ ble_gattc_disc_all_dscs_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_disc_all_dscs_cb(entry, rc, 0, NULL);
+    ble_gattc_disc_all_dscs_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * discover-all-descriptors proc.
+ */
 static void
-ble_gattc_disc_all_dscs_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_disc_all_dscs_err(struct ble_gattc_proc *proc, int status,
                             uint16_t att_handle)
 {
     if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
@@ -1647,11 +2014,15 @@ ble_gattc_disc_all_dscs_err(struct ble_gattc_entry *entry, int status,
         status = 0;
     }
 
-    ble_gattc_disc_all_dscs_cb(entry, status, att_handle, NULL);
+    ble_gattc_disc_all_dscs_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming "information data" entry from a find-information
+ * response for the specified discover-all-descriptors proc.
+ */
 static int
-ble_gattc_disc_all_dscs_rx_idata(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_dscs_rx_idata(struct ble_gattc_proc *proc,
                                  struct ble_hs_conn *conn,
                                  struct ble_att_find_info_idata *idata)
 {
@@ -1659,12 +2030,12 @@ ble_gattc_disc_all_dscs_rx_idata(struct ble_gattc_entry *entry,
     int cbrc;
     int rc;
 
-    if (idata->attr_handle <= entry->disc_all_dscs.prev_handle) {
+    if (idata->attr_handle <= proc->disc_all_dscs.prev_handle) {
         /* Peer sent descriptors out of order; terminate procedure. */
         rc = BLE_HS_EBADDATA;
         goto done;
     }
-    entry->disc_all_dscs.prev_handle = idata->attr_handle;
+    proc->disc_all_dscs.prev_handle = idata->attr_handle;
 
     rc = 0;
 
@@ -1672,46 +2043,64 @@ done:
     dsc.handle = idata->attr_handle;
     memcpy(dsc.uuid128, idata->uuid128, 16);
 
-    cbrc = ble_gattc_disc_all_dscs_cb(entry, rc, 0, &dsc);
+    cbrc = ble_gattc_disc_all_dscs_cb(proc, rc, 0, &dsc);
     if (rc == 0) {
         rc = cbrc;
     }
     return rc;
 }
 
+/**
+ * Handles a notification that a find-information response has been fully
+ * processed for the specified discover-all-descriptors proc.
+ */
 static int
-ble_gattc_disc_all_dscs_rx_complete(struct ble_gattc_entry *entry,
+ble_gattc_disc_all_dscs_rx_complete(struct ble_gattc_proc *proc,
                                     struct ble_hs_conn *conn, int status)
 {
-    if (status != 0 || entry->disc_all_dscs.prev_handle ==
-                       entry->disc_all_dscs.end_handle) {
+    if (status != 0 ||
+        proc->disc_all_dscs.prev_handle == proc->disc_all_dscs.end_handle) {
+
         /* Error or all descriptors discovered. */
-        ble_gattc_disc_all_dscs_cb(entry, status, 0, NULL);
+        ble_gattc_disc_all_dscs_cb(proc, status, 0, NULL);
         return 1;
     } else {
         /* Send follow-up request. */
-        ble_gattc_entry_set_pending(entry);
+        ble_gattc_proc_set_pending(proc);
         return 0;
     }
 }
 
+/**
+ * Initiates GATT procedure: Discover All Characteristic Descriptors.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param chr_val_handle        The handle of the characteristic value
+ *                                  attribute.
+ * @param chr_end_handle        The last handle in the characteristic
+ *                                  definition.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_val_handle,
                         uint16_t chr_end_handle,
                         ble_gatt_dsc_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_DISC_ALL_DSCS, &entry);
+    rc = ble_gattc_new_proc(conn_handle, BLE_GATT_OP_DISC_ALL_DSCS, &proc);
     if (rc != 0) {
         return rc;
     }
-    entry->disc_all_dscs.chr_val_handle = chr_val_handle;
-    entry->disc_all_dscs.prev_handle = chr_val_handle;
-    entry->disc_all_dscs.end_handle = chr_end_handle;
-    entry->disc_all_dscs.cb = cb;
-    entry->disc_all_dscs.cb_arg = cb_arg;
+    proc->disc_all_dscs.chr_val_handle = chr_val_handle;
+    proc->disc_all_dscs.prev_handle = chr_val_handle;
+    proc->disc_all_dscs.end_handle = chr_end_handle;
+    proc->disc_all_dscs.cb = cb;
+    proc->disc_all_dscs.cb_arg = cb_arg;
 
     return 0;
 }
@@ -1720,37 +2109,48 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_val_handle,
  * $read                                                                     *
  *****************************************************************************/
 
+/**
+ * Calls a read-characteristic proc's callback with the specified parameters.
+ * If the proc has no callback, this function is a no-op.
+ *
+ * @return                      The return code of the callback (or 0 if there
+ *                                  is no callback).
+ */
 static int
-ble_gattc_read_cb(struct ble_gattc_entry *entry, int status,
+ble_gattc_read_cb(struct ble_gattc_proc *proc, int status,
                   uint16_t att_handle, struct ble_gatt_attr *attr)
 {
     int rc;
 
-    if (entry->read.cb == NULL) {
+    if (proc->read.cb == NULL) {
         rc = 0;
     } else {
-        rc = entry->read.cb(entry->conn_handle,
-                            ble_gattc_error(status, att_handle), attr,
-                            entry->read.cb_arg);
+        rc = proc->read.cb(proc->conn_handle,
+                           ble_gattc_error(status, att_handle), attr,
+                           proc->read.cb_arg);
     }
 
     return rc;
 }
 
+/**
+ * Triggers a pending transmit for the specified read-characteristic-value
+ * proc.
+ */
 static int
-ble_gattc_read_kick(struct ble_gattc_entry *entry)
+ble_gattc_read_kick(struct ble_gattc_proc *proc)
 {
     struct ble_att_read_req req;
     struct ble_hs_conn *conn;
     int rc;
 
-    conn = ble_hs_conn_find(entry->conn_handle);
+    conn = ble_hs_conn_find(proc->conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
         goto err;
     }
 
-    req.barq_handle = entry->read.handle;
+    req.barq_handle = proc->read.handle;
     rc = ble_att_clt_tx_read(conn, &req);
     if (rc != 0) {
         goto err;
@@ -1759,53 +2159,71 @@ ble_gattc_read_kick(struct ble_gattc_entry *entry)
     return 0;
 
 err:
-    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+    if (ble_gattc_tx_postpone_chk(proc, rc)) {
         return BLE_HS_EAGAIN;
     }
 
-    ble_gattc_read_cb(entry, rc, 0, NULL);
+    ble_gattc_read_cb(proc, rc, 0, NULL);
     return rc;
 }
 
+/**
+ * Handles an incoming ATT error response for the specified
+ * read-characteristic-value proc.
+ */
 static void
-ble_gattc_read_err(struct ble_gattc_entry *entry, int status,
+ble_gattc_read_err(struct ble_gattc_proc *proc, int status,
                    uint16_t att_handle)
 {
-    ble_gattc_read_cb(entry, status, att_handle, NULL);
+    ble_gattc_read_cb(proc, status, att_handle, NULL);
 }
 
+/**
+ * Handles an incoming read-response for the specified
+ * read-characteristic-value proc.
+ */
 static int
-ble_gattc_read_rx_read_rsp(struct ble_gattc_entry *entry,
+ble_gattc_read_rx_read_rsp(struct ble_gattc_proc *proc,
                            struct ble_hs_conn *conn, int status,
                            void *value, int value_len)
 {
     struct ble_gatt_attr attr;
 
-    attr.handle = entry->read.handle;
+    attr.handle = proc->read.handle;
     attr.offset = 0;
     attr.value_len = value_len;
     attr.value = value;
 
-    ble_gattc_read_cb(entry, status, 0, &attr);
+    ble_gattc_read_cb(proc, status, 0, &attr);
 
     /* The read operation only has a single request / response exchange. */
     return 1;
 }
 
+/**
+ * Initiates GATT procedure: Read Characteristic Value.
+ *
+ * @param conn_handle           The connection over which to execute the
+ *                                  procedure.
+ * @param attr_handle           The handle of the characteristic value to read.
+ * @param cb                    The function to call to report procedure status
+ *                                  updates; null for no callback.
+ * @param cb_arg                The argument to pass to the callback function.
+ */
 int
 ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
                ble_gatt_attr_fn *cb, void *cb_arg)
 {
-    struct ble_gattc_entry *entry;
+    struct ble_gattc_proc *proc;
     int rc;
 
-    rc = ble_gattc_new_entry(conn

<TRUNCATED>