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/03 02:53:55 UTC

incubator-mynewt-larva git commit: ATT Read, Read By Group Type.

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master af9cb85b7 -> e878a3d55


ATT Read, Read By Group Type.


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

Branch: refs/heads/master
Commit: e878a3d55a9097d482072ed6cee80f1eb7fab61d
Parents: af9cb85
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Dec 2 17:53:09 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Dec 2 17:53:09 2015 -0800

----------------------------------------------------------------------
 libs/os/include/os/os_mbuf.h         |   1 +
 net/nimble/host/src/ble_gatt.c       |  30 ++---
 net/nimble/host/src/ble_hs_att.h     |  13 ++-
 net/nimble/host/src/ble_hs_att_clt.c | 188 ++++++++++++++++++++++++++----
 net/nimble/host/src/ble_hs_att_cmd.c |  82 +++++++++++++
 net/nimble/host/src/ble_hs_att_cmd.h |  38 ++++++
 net/nimble/host/src/ble_hs_uuid.c    |  68 ++++++++++-
 net/nimble/host/src/ble_hs_uuid.h    |   6 +-
 8 files changed, 383 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/libs/os/include/os/os_mbuf.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index effa8c2..d5cc471 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -17,6 +17,7 @@
 #ifndef _OS_MBUF_H 
 #define _OS_MBUF_H 
 
+#include "os/queue.h"
 #include "os/os_eventq.h"
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/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 1533317..c5c2764 100644
--- a/net/nimble/host/src/ble_gatt.c
+++ b/net/nimble/host/src/ble_gatt.c
@@ -314,6 +314,21 @@ ble_gatt_rx_error(struct ble_hs_conn *conn, struct ble_hs_att_error_rsp *rsp)
     }
 }
 
+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)
 {
@@ -330,21 +345,6 @@ ble_gatt_rx_mtu(struct ble_hs_conn *conn, uint16_t chan_mtu)
     ble_gatt_entry_remove_free(entry, prev);
 }
 
-int
-ble_gatt_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_find_info(struct ble_hs_conn *conn, int status,
                       uint16_t last_handle_id)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_att.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.h b/net/nimble/host/src/ble_hs_att.h
index 013405a..d0d0032 100644
--- a/net/nimble/host/src/ble_hs_att.h
+++ b/net/nimble/host/src/ble_hs_att.h
@@ -25,6 +25,9 @@ struct ble_l2cap_chan;
 struct ble_hs_att_find_info_req;
 struct ble_hs_att_error_rsp;
 struct ble_hs_att_mtu_cmd;
+struct ble_hs_att_read_req;
+struct ble_hs_att_read_group_type_req;
+struct ble_hs_att_read_group_type_rsp;
 
 #define BLE_HS_ATT_MTU_DFLT         23  /* Also the minimum. */
 #define BLE_HS_ATT_MTU_MAX          256 /* XXX: I'm making this up! */
@@ -137,7 +140,7 @@ int ble_hs_att_svr_rx_write(struct ble_hs_conn *conn,
                             struct os_mbuf *om);
 int ble_hs_att_svr_init(void);
 
-/*** @cnt */
+/*** @clt */
 void ble_hs_att_clt_entry_list_free(struct ble_hs_att_clt_entry_list *list);
 int ble_hs_att_clt_entry_insert(struct ble_hs_conn *conn, uint16_t handle_id,
                                 uint8_t *uuid);
@@ -150,11 +153,19 @@ int ble_hs_att_clt_tx_mtu(struct ble_hs_conn *conn,
 int ble_hs_att_clt_rx_mtu(struct ble_hs_conn *conn,
                           struct ble_l2cap_chan *chan,
                           struct os_mbuf *om);
+int ble_hs_att_clt_tx_read(struct ble_hs_conn *conn,
+                           struct ble_hs_att_read_req *req);
 int ble_hs_att_clt_tx_find_info(struct ble_hs_conn *conn,
                                 struct ble_hs_att_find_info_req *req);
 int ble_hs_att_clt_rx_find_info(struct ble_hs_conn *conn,
                                 struct ble_l2cap_chan *chan,
                                 struct os_mbuf *om);
+int ble_hs_att_clt_tx_read_group_type(
+    struct ble_hs_conn *conn, struct ble_hs_att_read_group_type_req *req,
+    void *uuid128);
+int ble_hs_att_clt_rx_read_group_type_rsp(struct ble_hs_conn *conn,
+                                          struct ble_l2cap_chan *chan,
+                                          struct os_mbuf *om);
 int ble_hs_att_clt_init(void);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_att_clt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att_clt.c b/net/nimble/host/src/ble_hs_att_clt.c
index 5da4bb5..fb73971 100644
--- a/net/nimble/host/src/ble_hs_att_clt.c
+++ b/net/nimble/host/src/ble_hs_att_clt.c
@@ -121,17 +121,35 @@ ble_hs_att_clt_find_entry_uuid128(struct ble_hs_conn *conn, void *uuid128)
 
 static int
 ble_hs_att_clt_prep_req(struct ble_hs_conn *conn, struct ble_l2cap_chan **chan,
-                        struct os_mbuf **txom)
+                        struct os_mbuf **txom, uint16_t initial_sz)
 {
+    void *buf;
+    int rc;
+
     *chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
     assert(*chan != NULL);
 
     *txom = os_mbuf_get_pkthdr(&ble_hs_mbuf_pool, 0);
     if (*txom == NULL) {
-        return ENOMEM;
+        rc = ENOMEM;
+        goto err;
     }
 
+    buf = os_mbuf_extend(*txom, initial_sz);
+    if (buf == NULL) {
+        rc = ENOMEM;
+        goto err;
+    }
+
+    /* The caller expects the initial buffer to be at the start of the mbuf. */
+    assert(buf == (*txom)->om_data);
+
     return 0;
+
+err:
+    os_mbuf_free_chain(*txom);
+    *txom = NULL;
+    return rc;
 }
 
 uint16_t
@@ -155,7 +173,6 @@ ble_hs_att_clt_tx_mtu(struct ble_hs_conn *conn, struct ble_hs_att_mtu_cmd *req)
 {
     struct ble_l2cap_chan *chan;
     struct os_mbuf *txom;
-    void *buf;
     int rc;
 
     txom = NULL;
@@ -165,18 +182,12 @@ ble_hs_att_clt_tx_mtu(struct ble_hs_conn *conn, struct ble_hs_att_mtu_cmd *req)
         goto err;
     }
 
-    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom);
+    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom, BLE_HS_ATT_MTU_CMD_SZ);
     if (rc != 0) {
         goto err;
     }
 
-    buf = os_mbuf_extend(txom, BLE_HS_ATT_MTU_CMD_SZ);
-    if (buf == NULL) {
-        rc = ENOMEM;
-        goto err;
-    }
-
-    rc = ble_hs_att_mtu_req_write(buf, BLE_HS_ATT_MTU_CMD_SZ, req);
+    rc = ble_hs_att_mtu_req_write(txom->om_data, txom->om_len, req);
     if (rc != 0) {
         goto err;
     }
@@ -187,7 +198,7 @@ ble_hs_att_clt_tx_mtu(struct ble_hs_conn *conn, struct ble_hs_att_mtu_cmd *req)
         goto err;
     }
 
-    rc = 0;
+    return 0;
 
 err:
     os_mbuf_free_chain(txom);
@@ -222,7 +233,6 @@ ble_hs_att_clt_tx_find_info(struct ble_hs_conn *conn,
 {
     struct ble_l2cap_chan *chan;
     struct os_mbuf *txom;
-    void *buf;
     int rc;
 
     txom = NULL;
@@ -234,18 +244,13 @@ ble_hs_att_clt_tx_find_info(struct ble_hs_conn *conn,
         goto err;
     }
 
-    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom);
+    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom,
+                                 BLE_HS_ATT_FIND_INFO_REQ_SZ);
     if (rc != 0) {
         goto err;
     }
 
-    buf = os_mbuf_extend(txom, BLE_HS_ATT_FIND_INFO_REQ_SZ);
-    if (buf == NULL) {
-        rc = ENOMEM;
-        goto err;
-    }
-
-    rc = ble_hs_att_find_info_req_write(buf, BLE_HS_ATT_FIND_INFO_REQ_SZ, req);
+    rc = ble_hs_att_find_info_req_write(txom->om_data, txom->om_len, req);
     if (rc != 0) {
         goto err;
     }
@@ -256,7 +261,7 @@ ble_hs_att_clt_tx_find_info(struct ble_hs_conn *conn,
         goto err;
     }
 
-    rc = 0;
+    return 0;
 
 err:
     os_mbuf_free_chain(txom);
@@ -338,6 +343,145 @@ done:
 }
 
 int
+ble_hs_att_clt_tx_read(struct ble_hs_conn *conn,
+                       struct ble_hs_att_read_req *req)
+{
+    struct ble_l2cap_chan *chan;
+    struct os_mbuf *txom;
+    int rc;
+
+    txom = NULL;
+
+    if (req->bharq_handle == 0) {
+        rc = EINVAL;
+        goto err;
+    }
+
+    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom, BLE_HS_ATT_READ_REQ_SZ);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_hs_att_read_req_write(txom->om_data, txom->om_len, req);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_l2cap_tx(chan, txom);
+    txom = NULL;
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    os_mbuf_free_chain(txom);
+    return rc;
+}
+
+int
+ble_hs_att_clt_tx_read_group_type(struct ble_hs_conn *conn,
+                                  struct ble_hs_att_read_group_type_req *req,
+                                  void *uuid128)
+{
+    struct ble_l2cap_chan *chan;
+    struct os_mbuf *txom;
+    int rc;
+
+    txom = NULL;
+
+    if (req->bhagq_start_handle == 0 ||
+        req->bhagq_start_handle > req->bhagq_end_handle) {
+
+        rc = EINVAL;
+        goto err;
+    }
+
+    rc = ble_hs_att_clt_prep_req(conn, &chan, &txom,
+                                 BLE_HS_ATT_READ_GROUP_TYPE_REQ_BASE_SZ);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_hs_att_read_group_type_req_write(txom->om_data, txom->om_len,
+                                              req);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_hs_uuid_append(txom, uuid128);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_l2cap_tx(chan, txom);
+    txom = NULL;
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    os_mbuf_free_chain(txom);
+    return rc;
+}
+
+struct ble_hs_att_clt_adata {
+    uint16_t att_handle;
+    uint16_t end_group_handle;
+    void *value;
+};
+
+static int
+ble_hs_att_clt_parse_attribute_data(struct os_mbuf *om, int data_len,
+                                    struct ble_hs_att_clt_adata *adata)
+{
+    /* XXX: Pull up om */
+
+    adata->att_handle = le16toh(om->om_data + 0);
+    adata->end_group_handle = le16toh(om->om_data + 2);
+    adata->value = om->om_data + 6;
+
+    return 0;
+}
+
+int
+ble_hs_att_clt_rx_read_group_type_rsp(struct ble_hs_conn *conn,
+                                      struct ble_l2cap_chan *chan,
+                                      struct os_mbuf *om)
+{
+    struct ble_hs_att_read_group_type_rsp rsp;
+    struct ble_hs_att_clt_adata adata;
+    int rc;
+
+    /* XXX: Pull up om */
+
+    rc = ble_hs_att_read_group_type_rsp_parse(om->om_data, om->om_len, &rsp);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* XXX: Verify group handle is valid. */
+
+    while (OS_MBUF_PKTHDR(om)->omp_len > 0) {
+        rc = ble_hs_att_clt_parse_attribute_data(om, rsp.bhagp_length, &adata);
+        if (rc != 0) {
+            break;
+        }
+
+        /* Save attribute mapping? */
+
+        /* XXX: Pass adata to GATT callback. */
+
+        os_mbuf_adj(om, rsp.bhagp_length);
+    }
+
+    return 0;
+}
+
+int
 ble_hs_att_clt_init(void)
 {
     int rc;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att_cmd.c b/net/nimble/host/src/ble_hs_att_cmd.c
index 11200ee..5cd5746 100644
--- a/net/nimble/host/src/ble_hs_att_cmd.c
+++ b/net/nimble/host/src/ble_hs_att_cmd.c
@@ -15,8 +15,10 @@
  */
 
 #include <errno.h>
+#include <string.h>
 #include "os/os.h"
 #include "nimble/ble.h"
+#include "ble_hs_uuid.h"
 #include "ble_l2cap.h"
 #include "ble_hs_att_cmd.h"
 
@@ -361,6 +363,86 @@ ble_hs_att_read_req_write(void *payload, int len,
 }
 
 int
+ble_hs_att_read_group_type_req_parse(
+    void *payload, int len, struct ble_hs_att_read_group_type_req *req)
+{
+    uint8_t *u8ptr;
+
+    if (len < BLE_HS_ATT_READ_GROUP_TYPE_REQ_BASE_SZ) {
+        return EMSGSIZE;
+    }
+
+    u8ptr = payload;
+
+    if (u8ptr[0] != BLE_HS_ATT_OP_READ_GROUP_TYPE_REQ) {
+        return EINVAL;
+    }
+
+    req->bhagq_start_handle = le16toh(u8ptr + 1);
+    req->bhagq_end_handle = le16toh(u8ptr + 3);
+
+    return 0;
+}
+
+int
+ble_hs_att_read_group_type_req_write(
+    void *payload, int len, struct ble_hs_att_read_group_type_req *req)
+{
+    uint8_t *u8ptr;
+
+    if (len < BLE_HS_ATT_READ_GROUP_TYPE_REQ_BASE_SZ) {
+        return EMSGSIZE;
+    }
+
+    u8ptr = payload;
+
+    u8ptr[0] = BLE_HS_ATT_OP_READ_GROUP_TYPE_REQ;
+    htole16(u8ptr + 1, req->bhagq_start_handle);
+    htole16(u8ptr + 3, req->bhagq_end_handle);
+
+    return 0;
+}
+
+int
+ble_hs_att_read_group_type_rsp_parse(
+    void *payload, int len, struct ble_hs_att_read_group_type_rsp *rsp)
+{
+    uint8_t *u8ptr;
+
+    if (len < BLE_HS_ATT_READ_GROUP_TYPE_RSP_BASE_SZ) {
+        return EMSGSIZE;
+    }
+
+    u8ptr = payload;
+
+    if (u8ptr[0] != BLE_HS_ATT_OP_READ_GROUP_TYPE_RSP) {
+        return EINVAL;
+    }
+
+    rsp->bhagp_length = u8ptr[1];
+
+    return 0;
+}
+
+int
+ble_hs_att_read_group_type_rsp_write(
+    void *payload, int len, struct ble_hs_att_read_group_type_rsp *rsp)
+{
+    uint8_t *u8ptr;
+
+    if (len < BLE_HS_ATT_READ_GROUP_TYPE_RSP_BASE_SZ) {
+        return EMSGSIZE;
+    }
+
+    u8ptr = payload;
+
+    u8ptr[0] = BLE_HS_ATT_OP_READ_GROUP_TYPE_RSP;
+    u8ptr[1] = rsp->bhagp_length;
+
+    return 0;
+}
+
+int
 ble_hs_att_write_req_parse(void *payload, int len,
                            struct ble_hs_att_write_req *req)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_att_cmd.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att_cmd.h b/net/nimble/host/src/ble_hs_att_cmd.h
index 3362187..828cb11 100644
--- a/net/nimble/host/src/ble_hs_att_cmd.h
+++ b/net/nimble/host/src/ble_hs_att_cmd.h
@@ -28,6 +28,8 @@ struct ble_l2cap_chan;
 #define BLE_HS_ATT_OP_READ_TYPE_RSP         0x09
 #define BLE_HS_ATT_OP_READ_REQ              0x0a
 #define BLE_HS_ATT_OP_READ_RSP              0x0b
+#define BLE_HS_ATT_OP_READ_GROUP_TYPE_REQ   0x10
+#define BLE_HS_ATT_OP_READ_GROUP_TYPE_RSP   0x11
 #define BLE_HS_ATT_OP_WRITE_REQ             0x12
 #define BLE_HS_ATT_OP_WRITE_RSP             0x13
 
@@ -161,6 +163,34 @@ struct ble_hs_att_read_req {
  * | Parameter                          | Size (octets)     |
  * +------------------------------------+-------------------+
  * | Attribute Opcode                   | 1                 |
+ * | Starting Handle                    | 2                 |
+ * | Ending Handle                      | 2                 |
+ * | Attribute Group Type               | 2 or 16           |
+ */
+#define BLE_HS_ATT_READ_GROUP_TYPE_REQ_BASE_SZ  5
+#define BLE_HS_ATT_READ_GROUP_TYPE_REQ_SZ_16    7
+#define BLE_HS_ATT_READ_GROUP_TYPE_REQ_SZ_128   21
+struct ble_hs_att_read_group_type_req {
+    uint16_t bhagq_start_handle;
+    uint16_t bhagq_end_handle;
+};
+
+/**
+ * | Parameter                          | Size (octets)     |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode                   | 1                 |
+ * | Length                             | 1                 |
+ * | Attribute Data List                | 2 to (ATT_MTU-2)  |
+ */
+#define BLE_HS_ATT_READ_GROUP_TYPE_RSP_BASE_SZ  2
+struct ble_hs_att_read_group_type_rsp {
+    uint8_t bhagp_length;
+};
+
+/**
+ * | Parameter                          | Size (octets)     |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode                   | 1                 |
  * | Attribute Handle                   | 2                 |
  * | Attribute Value                    | 0 to (ATT_MTU-3)  |
  */
@@ -205,6 +235,14 @@ int ble_hs_att_read_type_rsp_parse(void *payload, int len,
                                    struct ble_hs_att_read_type_rsp *rsp);
 int ble_hs_att_read_type_rsp_write(void *payload, int len,
                                    struct ble_hs_att_read_type_rsp *rsp);
+int ble_hs_att_read_group_type_req_parse(
+    void *payload, int len, struct ble_hs_att_read_group_type_req *req);
+int ble_hs_att_read_group_type_req_write(
+    void *payload, int len, struct ble_hs_att_read_group_type_req *req);
+int ble_hs_att_read_group_type_rsp_parse(
+    void *payload, int len, struct ble_hs_att_read_group_type_rsp *rsp);
+int ble_hs_att_read_group_type_rsp_write(
+    void *payload, int len, struct ble_hs_att_read_group_type_rsp *rsp);
 int ble_hs_att_write_req_parse(void *payload, int len,
                                struct ble_hs_att_write_req *req);
 int ble_hs_att_write_req_write(void *payload, int len,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_uuid.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_uuid.c b/net/nimble/host/src/ble_hs_uuid.c
index 5abcd0f..bedadae 100644
--- a/net/nimble/host/src/ble_hs_uuid.c
+++ b/net/nimble/host/src/ble_hs_uuid.c
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
+#include <assert.h>
 #include <inttypes.h>
 #include <string.h>
 #include <errno.h>
+#include "os/os_mbuf.h"
 #include "nimble/ble.h"
 #include "ble_hs_uuid.h"
 
@@ -34,26 +36,29 @@ static uint8_t ble_hs_uuid_base[16] = {
  *                                  0 if the UUID could not be converted.
  */
 uint16_t
-ble_hs_uuid_16bit(uint8_t *uuid128)
+ble_hs_uuid_16bit(void *uuid128)
 {
     uint16_t uuid16;
+    uint8_t *u8ptr;
     int rc;
 
+    u8ptr = uuid128;
+
     /* The UUID can only be converted if its final 96 bits are equal to the
      * base UUID.
      */
-    rc = memcmp(uuid128 + 4, ble_hs_uuid_base + 4,
+    rc = memcmp(u8ptr + 4, ble_hs_uuid_base + 4,
                 sizeof ble_hs_uuid_base - 4);
     if (rc != 0) {
         return 0;
     }
 
-    if (uuid128[0] != 0 || uuid128[1] != 0) {
+    if (u8ptr[0] != 0 || u8ptr[1] != 0) {
         /* This UUID has a 32-bit form, but not a 16-bit form. */
         return 0;
     }
 
-    uuid16 = (uuid128[2] << 8) + uuid128[3];
+    uuid16 = (u8ptr[2] << 8) + u8ptr[3];
     if (uuid16 == 0) {
         return 0;
     }
@@ -77,3 +82,58 @@ ble_hs_uuid_from_16bit(uint16_t uuid16, void *uuid128)
 
     return 0;
 }
+
+int
+ble_hs_uuid_append(struct os_mbuf *om, void *uuid128)
+{
+    uint16_t uuid16;
+    void *buf;
+    int rc;
+
+    uuid16 = ble_hs_uuid_16bit(uuid128);
+    if (uuid16 != 0) {
+        buf = os_mbuf_extend(om, 2);
+        if (buf == NULL) {
+            return ENOMEM;
+        }
+
+        htole16(buf, uuid16);
+    } else {
+        rc = os_mbuf_append(om, uuid128, 16);
+        if (rc != 0) {
+            return ENOMEM;
+        }
+    }
+
+    return 0;
+}
+
+int
+ble_hs_uuid_extract(struct os_mbuf *om, int off, void *uuid128)
+{
+    uint16_t uuid16;
+    int remlen;
+    int rc;
+
+    remlen = OS_MBUF_PKTHDR(om)->omp_len;
+    switch (remlen) {
+    case 2:
+        rc = os_mbuf_copydata(om, off, 2, &uuid16);
+        assert(rc == 0);
+
+        uuid16 = le16toh(&uuid16);
+        rc = ble_hs_uuid_from_16bit(uuid16, uuid128);
+        if (rc != 0) {
+            return rc;
+        }
+        return 0;
+
+    case 16:
+        rc = os_mbuf_copydata(om, off, 16, uuid128);
+        assert(rc == 0);
+        return 0;
+
+    default:
+        return EMSGSIZE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/e878a3d5/net/nimble/host/src/ble_hs_uuid.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_uuid.h b/net/nimble/host/src/ble_hs_uuid.h
index 48b20e4..1515a60 100644
--- a/net/nimble/host/src/ble_hs_uuid.h
+++ b/net/nimble/host/src/ble_hs_uuid.h
@@ -17,7 +17,11 @@
 #ifndef H_BLE_HS_UUID_
 #define H_BLE_HS_UUID_
 
-uint16_t ble_hs_uuid_16bit(uint8_t *uuid128);
+struct os_mbuf;
+
+uint16_t ble_hs_uuid_16bit(void *uuid128);
 int ble_hs_uuid_from_16bit(uint16_t uuid16, void *dst);
+int ble_hs_uuid_append(struct os_mbuf *om, void *uuid128);
+int ble_hs_uuid_extract(struct os_mbuf *om, int off, void *uuid128);
 
 #endif /* _BLE_HOST_UUID_H */