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/12 21:29:53 UTC

[2/4] incubator-mynewt-larva git commit: ATT client prep/exec ; GATT long write.

ATT client prep/exec ; GATT long write.


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

Branch: refs/heads/master
Commit: de91aec397b0d783b44a52a8e0cee5724a60054f
Parents: bde3e1d
Author: Christopher Collins <cc...@gmail.com>
Authored: Mon Jan 11 18:08:17 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Mon Jan 11 18:08:17 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_gatt.h |   2 +
 net/nimble/host/src/ble_att.c           |   2 +
 net/nimble/host/src/ble_att_clt.c       | 155 ++++++++++++++++++++
 net/nimble/host/src/ble_att_cmd.h       |   1 +
 net/nimble/host/src/ble_att_priv.h      |  13 ++
 net/nimble/host/src/ble_gatt_priv.h     |   5 +
 net/nimble/host/src/ble_gattc.c         | 207 ++++++++++++++++++++++++++-
 7 files changed, 383 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/include/host/ble_gatt.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gatt.h b/net/nimble/host/include/host/ble_gatt.h
index b5c9ba7..d847eae 100644
--- a/net/nimble/host/include/host/ble_gatt.h
+++ b/net/nimble/host/include/host/ble_gatt.h
@@ -109,6 +109,8 @@ int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,
                            ble_gatt_attr_fn *cb, void *cb_arg);
 int ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
                     uint16_t value_len, ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, void *value,
+                         uint16_t value_len, ble_gatt_attr_fn *cb, void *cb_arg);
 
 int ble_gattc_init(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/src/ble_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att.c b/net/nimble/host/src/ble_att.c
index ccaf113..b167687 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -51,7 +51,9 @@ static struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
     { BLE_ATT_OP_WRITE_REQ,            ble_att_svr_rx_write },
     { BLE_ATT_OP_WRITE_RSP,            ble_att_clt_rx_write },
     { BLE_ATT_OP_PREP_WRITE_REQ,       ble_att_svr_rx_prep_write },
+    { BLE_ATT_OP_PREP_WRITE_RSP,       ble_att_clt_rx_prep_write },
     { BLE_ATT_OP_EXEC_WRITE_REQ,       ble_att_svr_rx_exec_write },
+    { BLE_ATT_OP_EXEC_WRITE_RSP,       ble_att_clt_rx_exec_write },
     { BLE_ATT_OP_NOTIFY_REQ,           ble_att_svr_rx_notify },
     { BLE_ATT_OP_INDICATE_REQ,         ble_att_svr_rx_indicate },
     { BLE_ATT_OP_INDICATE_RSP,         ble_att_clt_rx_indicate },

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/src/ble_att_clt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_clt.c b/net/nimble/host/src/ble_att_clt.c
index 5e0522e..1e5893b 100644
--- a/net/nimble/host/src/ble_att_clt.c
+++ b/net/nimble/host/src/ble_att_clt.c
@@ -936,6 +936,161 @@ ble_att_clt_rx_write(struct ble_hs_conn *conn,
 }
 
 /*****************************************************************************
+ * $prepare write request                                                    *
+ *****************************************************************************/
+
+int
+ble_att_clt_tx_prep_write(struct ble_hs_conn *conn,
+                          struct ble_att_prep_write_cmd *req,
+                          void *value, uint16_t value_len)
+{
+    struct ble_l2cap_chan *chan;
+    struct os_mbuf *txom;
+    int rc;
+
+    txom = NULL;
+
+    if (req->bapc_handle == 0) {
+        rc = BLE_HS_EINVAL;
+        goto err;
+    }
+
+    if (req->bapc_offset >= BLE_ATT_ATTR_MAX_LEN) {
+        rc = BLE_HS_EINVAL;
+        goto err;
+    }
+
+    rc = ble_att_clt_prep_req(conn, &chan, &txom,
+                              BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+    if (rc != 0) {
+        goto err;
+    }
+
+    if (value_len > ble_l2cap_chan_mtu(chan) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) {
+        rc = BLE_HS_EINVAL;
+        goto err;
+    }
+
+    rc = ble_att_prep_write_req_write(txom->om_data, txom->om_len, req);
+    assert(rc == 0);
+
+    rc = ble_att_clt_append_blob(chan, txom, value, value_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_l2cap_tx(conn, chan, txom);
+    txom = NULL;
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    os_mbuf_free_chain(txom);
+    return rc;
+}
+
+int
+ble_att_clt_rx_prep_write(struct ble_hs_conn *conn,
+                          struct ble_l2cap_chan *chan,
+                          struct os_mbuf **rxom)
+{
+    struct ble_att_prep_write_cmd rsp;
+    int rc;
+
+    if (OS_MBUF_PKTLEN(*rxom) < BLE_ATT_PREP_WRITE_CMD_BASE_SZ) {
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+
+    *rxom = os_mbuf_pullup(*rxom, OS_MBUF_PKTLEN(*rxom));
+    if (*rxom == NULL) {
+        rc = BLE_HS_ENOMEM;
+        goto err;
+    }
+
+    rc = ble_att_prep_write_rsp_parse((*rxom)->om_data, (*rxom)->om_len,
+                                      &rsp);
+    assert(rc == 0);
+
+    /* Strip the base from the front of the response. */
+    os_mbuf_adj(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+
+    ble_gattc_rx_prep_write_rsp(conn, 0, &rsp, (*rxom)->om_data,
+                                (*rxom)->om_len);
+    return 0;
+
+err:
+    ble_gattc_rx_prep_write_rsp(conn, rc, NULL, NULL, 0);
+    return rc;
+}
+
+/*****************************************************************************
+ * $execute write request                                                    *
+ *****************************************************************************/
+
+int
+ble_att_clt_tx_exec_write(struct ble_hs_conn *conn,
+                          struct ble_att_exec_write_req *req)
+{
+    struct ble_l2cap_chan *chan;
+    struct os_mbuf *txom;
+    int rc;
+
+    txom = NULL;
+
+    if ((req->baeq_flags & BLE_ATT_EXEC_WRITE_F_RESERVED) != 0) {
+        rc = BLE_HS_EINVAL;
+        goto err;
+    }
+
+    rc = ble_att_clt_prep_req(conn, &chan, &txom, BLE_ATT_EXEC_WRITE_REQ_SZ);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = ble_att_exec_write_req_write(txom->om_data, txom->om_len, req);
+    assert(rc == 0);
+
+    rc = ble_l2cap_tx(conn, chan, txom);
+    txom = NULL;
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    os_mbuf_free_chain(txom);
+    return rc;
+}
+
+int
+ble_att_clt_rx_exec_write(struct ble_hs_conn *conn,
+                          struct ble_l2cap_chan *chan,
+                          struct os_mbuf **rxom)
+{
+    int rc;
+
+    *rxom = os_mbuf_pullup(*rxom, BLE_ATT_EXEC_WRITE_RSP_SZ);
+    if (*rxom == NULL) {
+        rc = BLE_HS_EBADDATA;
+        goto done;
+    }
+
+    rc = ble_att_exec_write_rsp_parse((*rxom)->om_data, (*rxom)->om_len);
+    assert(rc == 0);
+
+    rc = 0;
+
+done:
+    ble_gattc_rx_exec_write_rsp(conn, rc);
+    return rc;
+}
+
+/*****************************************************************************
  * $handle value notification                                                *
  *****************************************************************************/
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/src/ble_att_cmd.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.h b/net/nimble/host/src/ble_att_cmd.h
index 9595401..2d7d084 100644
--- a/net/nimble/host/src/ble_att_cmd.h
+++ b/net/nimble/host/src/ble_att_cmd.h
@@ -261,6 +261,7 @@ struct ble_att_exec_write_req {
 };
 
 #define BLE_ATT_EXEC_WRITE_F_CONFIRM    0x01
+#define BLE_ATT_EXEC_WRITE_F_RESERVED   0xfe
 
 /**
  * | Parameter                          | Size (octets)     |

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/src/ble_att_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_priv.h b/net/nimble/host/src/ble_att_priv.h
index b5fc5a3..a644acb 100644
--- a/net/nimble/host/src/ble_att_priv.h
+++ b/net/nimble/host/src/ble_att_priv.h
@@ -33,6 +33,8 @@ struct ble_att_read_group_type_req;
 struct ble_att_read_group_type_rsp;
 struct ble_att_find_type_value_req;
 struct ble_att_write_req;
+struct ble_att_prep_write_cmd;
+struct ble_att_exec_write_req;
 struct ble_att_notify_req;
 struct ble_att_indicate_req;
 
@@ -218,6 +220,17 @@ int ble_att_clt_tx_write_req(struct ble_hs_conn *conn,
 int ble_att_clt_tx_write_cmd(struct ble_hs_conn *conn,
                              struct ble_att_write_req *req,
                              void *value, uint16_t value_len);
+int ble_att_clt_tx_prep_write(struct ble_hs_conn *conn,
+                              struct ble_att_prep_write_cmd *req,
+                              void *value, uint16_t value_len);
+int ble_att_clt_rx_prep_write(struct ble_hs_conn *conn,
+                              struct ble_l2cap_chan *chan,
+                              struct os_mbuf **rxom);
+int ble_att_clt_tx_exec_write(struct ble_hs_conn *conn,
+                              struct ble_att_exec_write_req *req);
+int ble_att_clt_rx_exec_write(struct ble_hs_conn *conn,
+                              struct ble_l2cap_chan *chan,
+                              struct os_mbuf **rxom);
 int ble_att_clt_rx_write(struct ble_hs_conn *conn,
                          struct ble_l2cap_chan *chan,
                          struct os_mbuf **rxom);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/net/nimble/host/src/ble_gatt_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt_priv.h b/net/nimble/host/src/ble_gatt_priv.h
index a8f088a..932ff61 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -22,6 +22,7 @@ struct ble_att_read_type_adata;
 struct ble_att_find_type_value_hinfo;
 struct ble_att_find_info_idata;
 struct ble_att_read_group_type_adata;
+struct ble_att_prep_write_cmd;
 
 #define BLE_GATT_CHR_DECL_SZ_16     5
 #define BLE_GATT_CHR_DECL_SZ_128    19
@@ -64,6 +65,10 @@ void ble_gattc_rx_find_type_value_hinfo(
     struct ble_hs_conn *conn, struct ble_att_find_type_value_hinfo *hinfo);
 void ble_gattc_rx_find_type_value_complete(struct ble_hs_conn *conn, int rc);
 void ble_gattc_rx_write_rsp(struct ble_hs_conn *conn);
+void ble_gattc_rx_prep_write_rsp(struct ble_hs_conn *conn, int status,
+                                 struct ble_att_prep_write_cmd *rsp,
+                                 void *attr_data, uint16_t attr_data_len);
+void ble_gattc_rx_exec_write_rsp(struct ble_hs_conn *conn, int status);
 void ble_gattc_rx_indicate_rsp(struct ble_hs_conn *conn);
 void ble_gattc_rx_find_info_idata(struct ble_hs_conn *conn,
                                   struct ble_att_find_info_idata *idata);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/de91aec3/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 0132e93..c37dcba 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -127,6 +127,12 @@ struct ble_gattc_entry {
             struct ble_gatt_attr attr;
             ble_gatt_attr_fn *cb;
             void *cb_arg;
+        } write_long;
+
+        struct {
+            struct ble_gatt_attr attr;
+            ble_gatt_attr_fn *cb;
+            void *cb_arg;
         } indicate;
     };
 };
@@ -148,8 +154,9 @@ struct ble_gattc_entry {
 #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_INDICATE                    13
-#define BLE_GATT_OP_MAX                         14
+#define BLE_GATT_OP_WRITE_LONG                  13
+#define BLE_GATT_OP_INDICATE                    14
+#define BLE_GATT_OP_MAX                         15
 
 static struct os_callout_func ble_gattc_heartbeat_timer;
 
@@ -170,6 +177,7 @@ 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,
@@ -196,6 +204,8 @@ static void ble_gattc_read_mult_err(struct ble_gattc_entry *entry, int status,
                                     uint16_t att_handle);
 static void ble_gattc_write_err(struct ble_gattc_entry *entry, int status,
                                 uint16_t att_handle);
+static void ble_gattc_write_long_err(struct ble_gattc_entry *entry, int status,
+                                     uint16_t att_handle);
 static void ble_gattc_indicate_err(struct ble_gattc_entry *entry, int status,
                                    uint16_t att_handle);
 
@@ -235,6 +245,15 @@ 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;
@@ -295,6 +314,10 @@ static const struct ble_gattc_dispatch_entry
         .kick_cb = ble_gattc_write_kick,
         .err_cb = ble_gattc_write_err,
     },
+    [BLE_GATT_OP_WRITE_LONG] = {
+        .kick_cb = ble_gattc_write_long_kick,
+        .err_cb = ble_gattc_write_long_err,
+    },
     [BLE_GATT_OP_INDICATE] = {
         .kick_cb = ble_gattc_indicate_kick,
         .err_cb = ble_gattc_indicate_err,
@@ -2243,6 +2266,145 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
 }
 
 /*****************************************************************************
+ * $write long                                                               *
+ *****************************************************************************/
+
+static int
+ble_gattc_write_long_cb(struct ble_gattc_entry *entry, int status,
+                        uint16_t att_handle)
+{
+    int rc;
+
+    if (entry->write_long.cb == NULL) {
+        rc = 0;
+    } else {
+        rc = entry->write_long.cb(entry->conn_handle, 
+                                  ble_gattc_error(status, att_handle),
+                                  &entry->write_long.attr,
+                                  entry->write_long.cb_arg);
+    }
+
+    return rc;
+}
+
+static int
+ble_gattc_write_long_kick(struct ble_gattc_entry *entry)
+{
+    struct ble_att_prep_write_cmd prep_req;
+    struct ble_att_exec_write_req exec_req;
+    struct ble_hs_conn *conn;
+    int rc;
+
+    conn = ble_hs_conn_find(entry->conn_handle);
+    if (conn == NULL) {
+        rc = BLE_HS_ENOTCONN;
+        goto err;
+    }
+
+    if (entry->write_long.attr.offset < entry->write_long.attr.value_len) {
+        prep_req.bapc_handle = entry->write_long.attr.handle;
+        prep_req.bapc_offset = entry->write_long.attr.offset;
+        rc = ble_att_clt_tx_prep_write(conn, &prep_req,
+                                       entry->write_long.attr.value,
+                                       entry->write_long.attr.value_len);
+    } else {
+        exec_req.baeq_flags = BLE_ATT_EXEC_WRITE_F_CONFIRM;
+        rc = ble_att_clt_tx_exec_write(conn, &exec_req);
+    }
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    if (ble_gattc_tx_postpone_chk(entry, rc)) {
+        return BLE_HS_EAGAIN;
+    }
+
+    ble_gattc_write_long_cb(entry, rc, 0);
+    return rc;
+}
+
+static void
+ble_gattc_write_long_err(struct ble_gattc_entry *entry, int status,
+                         uint16_t att_handle)
+{
+    ble_gattc_write_long_cb(entry, status, att_handle);
+}
+
+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)
+{
+    int rc;
+
+    if (status != 0) {
+        rc = status;
+        goto err;
+    }
+
+    /* Verify the response. */
+    if (rsp->bapc_handle != entry->write_long.attr.handle) {
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+    if (rsp->bapc_offset != entry->write_long.attr.offset) {
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+    if (rsp->bapc_offset + attr_len > entry->write_long.attr.value_len) {
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+    if (memcmp(attr_data, entry->write_long.attr.value, attr_len) != 0) {
+        rc = BLE_HS_EBADDATA;
+        goto err;
+    }
+
+    entry->write_long.attr.offset += attr_len;
+
+    return 0;
+
+err:
+    /* XXX: Might need to cancel pending writes. */
+    ble_gattc_write_long_cb(entry, rc, 0);
+    return 1;
+}
+
+static int
+ble_gattc_write_long_rx_exec(struct ble_gattc_entry *entry,
+                             struct ble_hs_conn *conn,
+                             int status)
+{
+    ble_gattc_write_cb(entry, status, 0);
+    return 1;
+}
+
+int
+ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, void *value,
+                     uint16_t value_len, ble_gatt_attr_fn *cb, void *cb_arg)
+{
+    struct ble_gattc_entry *entry;
+    int rc;
+
+    rc = ble_gattc_new_entry(conn_handle, BLE_GATT_OP_WRITE_LONG, &entry);
+    if (rc != 0) {
+        return rc;
+    }
+
+    entry->write_long.attr.handle = attr_handle;
+    entry->write_long.attr.value = value;
+    entry->write_long.attr.value_len = value_len;
+    entry->write_long.cb = cb;
+    entry->write_long.cb_arg = cb_arg;
+
+    return 0;
+}
+
+/*****************************************************************************
  * $notify                                                                   *
  *****************************************************************************/
 
@@ -2684,6 +2846,47 @@ ble_gattc_rx_write_rsp(struct ble_hs_conn *conn)
 }
 
 void
+ble_gattc_rx_prep_write_rsp(struct ble_hs_conn *conn, int status,
+                            struct ble_att_prep_write_cmd *rsp,
+                            void *attr_data, uint16_t attr_data_len)
+{
+    struct ble_gattc_entry *entry;
+    struct ble_gattc_entry *prev;
+    int rc;
+
+    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_WRITE_LONG, 1, &prev);
+    if (entry == NULL) {
+        /* Not expecting a response from this device. */
+        return;
+    }
+
+    rc = ble_gattc_write_long_rx_prep(entry, conn, status, rsp, attr_data,
+                                      attr_data_len);
+    if (rc != 0) {
+        ble_gattc_entry_remove_free(entry, prev);
+    }
+}
+
+void
+ble_gattc_rx_exec_write_rsp(struct ble_hs_conn *conn, int status)
+{
+    struct ble_gattc_entry *entry;
+    struct ble_gattc_entry *prev;
+    int rc;
+
+    entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_WRITE_LONG, 1, &prev);
+    if (entry == NULL) {
+        /* Not expecting a response from this device. */
+        return;
+    }
+
+    rc = ble_gattc_write_long_rx_exec(entry, conn, status);
+    if (rc != 0) {
+        ble_gattc_entry_remove_free(entry, prev);
+    }
+}
+
+void
 ble_gattc_rx_indicate_rsp(struct ble_hs_conn *conn)
 {
     struct ble_gattc_entry *entry;