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/16 04:55:03 UTC
[3/3] incubator-mynewt-larva git commit: ATT prepare write and
execute write commands.
ATT prepare write and execute write commands.
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/762dccc3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/762dccc3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/762dccc3
Branch: refs/heads/master
Commit: 762dccc393780191a5544a62f3b507535f1d6534
Parents: 27f8daf
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Dec 15 15:33:22 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Dec 15 19:54:24 2015 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/ble_att.h | 11 +-
net/nimble/host/src/ble_att.c | 2 +
net/nimble/host/src/ble_att_cmd.c | 132 +++++++
net/nimble/host/src/ble_att_cmd.h | 52 ++-
net/nimble/host/src/ble_att_priv.h | 19 +
net/nimble/host/src/ble_att_svr.c | 431 ++++++++++++++++++++++-
net/nimble/host/src/ble_hs.c | 27 +-
net/nimble/host/src/ble_hs_conn.c | 2 -
net/nimble/host/src/ble_hs_conn.h | 3 +-
net/nimble/host/src/ble_hs_misc.c | 23 ++
net/nimble/host/src/ble_hs_priv.h | 4 +
net/nimble/host/src/test/ble_att_svr_test.c | 11 +-
12 files changed, 664 insertions(+), 53 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/include/host/ble_att.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_att.h b/net/nimble/host/include/host/ble_att.h
index c97f7f6..0b611da 100644
--- a/net/nimble/host/include/host/ble_att.h
+++ b/net/nimble/host/include/host/ble_att.h
@@ -25,7 +25,10 @@
#define BLE_ATT_ERR_INVALID_HANDLE 0x01
#define BLE_ATT_ERR_INVALID_PDU 0x04
#define BLE_ATT_ERR_REQ_NOT_SUPPORTED 0x06
+#define BLE_ATT_ERR_INVALID_OFFSET 0x07
+#define BLE_ATT_ERR_PREPARE_QUEUE_FULL 0x09
#define BLE_ATT_ERR_ATTR_NOT_FOUND 0x0a
+#define BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN 0x0d
#define BLE_ATT_ERR_UNLIKELY 0x0e
#define BLE_ATT_ERR_UNSUPPORTED_GROUP 0x10
#define BLE_ATT_ERR_INSUFFICIENT_RES 0x11
@@ -45,8 +48,14 @@
#define BLE_ATT_OP_READ_GROUP_TYPE_RSP 0x11
#define BLE_ATT_OP_WRITE_REQ 0x12
#define BLE_ATT_OP_WRITE_RSP 0x13
+#define BLE_ATT_OP_PREP_WRITE_REQ 0x16
+#define BLE_ATT_OP_PREP_WRITE_RSP 0x17
+#define BLE_ATT_OP_EXEC_WRITE_REQ 0x18
+#define BLE_ATT_OP_EXEC_WRITE_RSP 0x19
#define BLE_ATT_OP_WRITE_CMD 0x52
+#define BLE_ATT_ATTR_MAX_LEN 512
+
union ble_att_svr_handle_arg {
struct {
void *attr_data;
@@ -54,7 +63,7 @@ union ble_att_svr_handle_arg {
} aha_read;
struct {
- struct os_mbuf *om;
+ void *attr_data;
int attr_len;
} aha_write;
};
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/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 b308ccb..a90a6da 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -46,6 +46,8 @@ static struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
{ BLE_ATT_OP_READ_GROUP_TYPE_RSP, ble_att_clt_rx_read_group_type },
{ 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_EXEC_WRITE_REQ, ble_att_svr_rx_exec_write },
};
#define BLE_ATT_RX_DISPATCH_SZ \
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.c b/net/nimble/host/src/ble_att_cmd.c
index 6b9a781..ce6f364 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -511,3 +511,135 @@ ble_att_write_cmd_write(void *payload, int len, struct ble_att_write_req *req)
return 0;
}
+
+static int
+ble_att_prep_write_cmd_parse(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd, int is_req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_PREP_WRITE_CMD_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ if (is_req) {
+ if (u8ptr[0] != BLE_ATT_OP_PREP_WRITE_REQ) {
+ return BLE_HS_EINVAL;
+ }
+ } else {
+ if (u8ptr[0] != BLE_ATT_OP_PREP_WRITE_RSP) {
+ return BLE_HS_EINVAL;
+ }
+ }
+
+ cmd->bapc_handle = le16toh(u8ptr + 1);
+ cmd->bapc_offset = le16toh(u8ptr + 3);
+
+ return 0;
+}
+
+static int
+ble_att_prep_write_cmd_write(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd, int is_req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_PREP_WRITE_CMD_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ if (is_req) {
+ u8ptr[0] = BLE_ATT_OP_PREP_WRITE_REQ;
+ } else {
+ u8ptr[0] = BLE_ATT_OP_PREP_WRITE_RSP;
+ }
+ htole16(u8ptr + 1, cmd->bapc_handle);
+ htole16(u8ptr + 3, cmd->bapc_offset);
+
+ return 0;
+}
+
+int
+ble_att_prep_write_req_parse(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd)
+{
+ return ble_att_prep_write_cmd_parse(payload, len, cmd, 1);
+}
+
+int
+ble_att_prep_write_req_write(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd)
+{
+ return ble_att_prep_write_cmd_write(payload, len, cmd, 1);
+}
+
+int
+ble_att_prep_write_rsp_parse(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd)
+{
+ return ble_att_prep_write_cmd_parse(payload, len, cmd, 0);
+}
+
+int
+ble_att_prep_write_rsp_write(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd)
+{
+ return ble_att_prep_write_cmd_write(payload, len, cmd, 0);
+}
+
+int
+ble_att_exec_write_req_parse(void *payload, int len,
+ struct ble_att_exec_write_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_EXEC_WRITE_REQ_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ if (u8ptr[0] != BLE_ATT_OP_EXEC_WRITE_REQ) {
+ return BLE_HS_EINVAL;
+ }
+
+ req->baeq_flags = u8ptr[1];
+
+ return 0;
+}
+
+int
+ble_att_exec_write_req_write(void *payload, int len,
+ struct ble_att_exec_write_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_EXEC_WRITE_REQ_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_REQ;
+ u8ptr[1] = req->baeq_flags;
+
+ return 0;
+}
+
+int
+ble_att_exec_write_rsp_write(void *payload, int len)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_EXEC_WRITE_RSP_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_REQ;
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/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 bd48ab7..df2f160 100644
--- a/net/nimble/host/src/ble_att_cmd.h
+++ b/net/nimble/host/src/ble_att_cmd.h
@@ -185,12 +185,47 @@ struct ble_att_read_group_type_rsp {
* | Attribute Handle | 2 |
* | Attribute Value | 0 to (ATT_MTU-3) |
*/
-#define BLE_ATT_WRITE_REQ_BASE_SZ 3
+#define BLE_ATT_WRITE_REQ_BASE_SZ 3
struct ble_att_write_req {
uint16_t bawq_handle;
};
-#define BLE_ATT_WRITE_RSP_SZ 1
+#define BLE_ATT_WRITE_RSP_SZ 1
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Attribute Handle | 2 |
+ * | Value Offset | 2 |
+ * | Part Attribute Value | 0 to (ATT_MTU-5) |
+ */
+#define BLE_ATT_PREP_WRITE_CMD_BASE_SZ 5
+struct ble_att_prep_write_cmd {
+ uint16_t bapc_handle;
+ uint16_t bapc_offset;
+};
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Flags | 1 |
+ */
+#define BLE_ATT_EXEC_WRITE_REQ_SZ 2
+struct ble_att_exec_write_req {
+ uint8_t baeq_flags;
+};
+
+#define BLE_ATT_EXEC_WRITE_F_CONFIRM 0x01
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ */
+#define BLE_ATT_EXEC_WRITE_RSP_SZ 1
+
int ble_att_error_rsp_parse(void *payload, int len,
struct ble_att_error_rsp *rsp);
@@ -242,3 +277,16 @@ int ble_att_write_cmd_parse(void *payload, int len,
struct ble_att_write_req *req);
int ble_att_write_cmd_write(void *payload, int len,
struct ble_att_write_req *req);
+int ble_att_prep_write_req_parse(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd);
+int ble_att_prep_write_req_write(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd);
+int ble_att_prep_write_rsp_parse(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd);
+int ble_att_prep_write_rsp_write(void *payload, int len,
+ struct ble_att_prep_write_cmd *cmd);
+int ble_att_exec_write_req_parse(void *payload, int len,
+ struct ble_att_exec_write_req *req);
+int ble_att_exec_write_req_write(void *payload, int len,
+ struct ble_att_exec_write_req *req);
+int ble_att_exec_write_rsp_write(void *payload, int len);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/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 92e9fd7..5b840f0 100644
--- a/net/nimble/host/src/ble_att_priv.h
+++ b/net/nimble/host/src/ble_att_priv.h
@@ -36,6 +36,19 @@ struct ble_att_write_req;
#define BLE_ATT_MTU_DFLT 23 /* Also the minimum. */
#define BLE_ATT_MTU_MAX 256 /* XXX: I'm making this up! */
+struct ble_att_prep_entry {
+ SLIST_ENTRY(ble_att_prep_entry) bape_next;
+ uint16_t bape_handle;
+ uint16_t bape_offset;
+ struct os_mbuf *bape_value;
+};
+
+struct ble_att_svr_conn {
+ /** This list is sorted by attribute handle ID. */
+ SLIST_HEAD(, ble_att_prep_entry) basc_prep_list;
+ uint32_t basc_prep_write_rx_time;
+};
+
/**
* Called from ble_att_svr_walk(). Called on each entry in the
* ble_att_svr_list.
@@ -87,6 +100,12 @@ int ble_att_svr_rx_read(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
struct os_mbuf **rxom);
int ble_att_svr_rx_write(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
struct os_mbuf **rxom);
+int ble_att_svr_rx_prep_write(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
+int ble_att_svr_rx_exec_write(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
int ble_att_svr_init(void);
/*** @clt */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index d216bc3..4efaf5f 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -19,10 +19,11 @@
#include <assert.h>
#include "os/os.h"
#include "nimble/ble.h"
+#include "host/ble_hs_uuid.h"
+#include "ble_hs_priv.h"
#include "ble_hs_priv.h"
#include "ble_l2cap.h"
#include "ble_hs_conn.h"
-#include "host/ble_hs_uuid.h"
#include "ble_att_cmd.h"
#include "ble_att_priv.h"
@@ -35,6 +36,22 @@ static struct os_mutex ble_att_svr_list_mutex;
static void *ble_att_svr_entry_mem;
static struct os_mempool ble_att_svr_entry_pool;
+
+#define BLE_ATT_SVR_PREP_MBUF_BUF_SIZE (128)
+#define BLE_ATT_SVR_PREP_MBUF_MEMBLOCK_SIZE \
+ (BLE_ATT_SVR_PREP_MBUF_BUF_SIZE + sizeof(struct os_mbuf) + \
+ sizeof(struct os_mbuf_pkthdr))
+
+#define BLE_ATT_SVR_NUM_PREP_ENTRIES 8
+#define BLE_ATT_SVR_NUM_PREP_MBUFS 12
+static void *ble_att_svr_prep_entry_mem;
+static struct os_mempool ble_att_svr_prep_entry_pool;
+static void *ble_att_svr_prep_mbuf_mem;
+static struct os_mempool ble_att_svr_prep_mbuf_mempool;
+static struct os_mbuf_pool ble_att_svr_prep_mbuf_pool;
+
+static uint8_t ble_att_svr_flat_buf[BLE_ATT_ATTR_MAX_LEN];
+
/**
* Locks the host attribute list.
*
@@ -1464,8 +1481,10 @@ ble_att_svr_rx_write(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
goto send_err;
}
- arg.aha_write.om = *rxom;
+ arg.aha_write.attr_data = ble_att_svr_flat_buf;
arg.aha_write.attr_len = OS_MBUF_PKTLEN(*rxom);
+ os_mbuf_copydata(*rxom, 0, arg.aha_write.attr_len,
+ arg.aha_write.attr_data);
rc = entry->ha_fn(entry, BLE_ATT_OP_WRITE_REQ, &arg);
if (rc != 0) {
goto send_err;
@@ -1484,43 +1503,423 @@ send_err:
return rc;
}
+static void
+ble_att_svr_prep_free(struct ble_att_prep_entry *entry)
+{
+ os_mbuf_free_chain(entry->bape_value);
+ os_memblock_put(&ble_att_svr_prep_entry_pool, entry);
+}
+
+static struct ble_att_prep_entry *
+ble_att_svr_prep_alloc(void)
+{
+ struct ble_att_prep_entry *entry;
+
+ entry = os_memblock_get(&ble_att_svr_prep_entry_pool);
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ memset(entry, 0, sizeof *entry);
+ entry->bape_value = os_mbuf_get_pkthdr(&ble_att_svr_prep_mbuf_pool, 0);
+ if (entry->bape_value == NULL) {
+ ble_att_svr_prep_free(entry);
+ return NULL;
+ }
+
+ return entry;
+}
+
+static struct ble_att_prep_entry *
+ble_att_svr_prep_find_prev(struct ble_att_svr_conn *basc, uint16_t handle,
+ uint16_t offset)
+{
+ struct ble_att_prep_entry *entry;
+ struct ble_att_prep_entry *prev;
+
+ prev = NULL;
+ SLIST_FOREACH(entry, &basc->basc_prep_list, bape_next) {
+ if (entry->bape_handle > handle) {
+ break;
+ }
+
+ if (entry->bape_handle == handle && entry->bape_offset > offset) {
+ break;
+ }
+
+ prev = entry;
+ }
+
+ return prev;
+}
+
+static void
+ble_att_svr_prep_clear(struct ble_att_svr_conn *basc)
+{
+ struct ble_att_prep_entry *entry;
+
+ while ((entry = SLIST_FIRST(&basc->basc_prep_list)) != NULL) {
+ SLIST_REMOVE_HEAD(&basc->basc_prep_list, bape_next);
+ ble_att_svr_prep_free(entry);
+ }
+}
+
+static int
+ble_att_svr_prep_validate(struct ble_att_svr_conn *basc, uint16_t *err_handle)
+{
+ struct ble_att_prep_entry *entry;
+ struct ble_att_prep_entry *prev;
+ int cur_len;
+
+ prev = NULL;
+ SLIST_FOREACH(entry, &basc->basc_prep_list, bape_next) {
+ if (prev == NULL || prev->bape_handle != entry->bape_handle) {
+ /* Ensure attribute write starts at offset 0. */
+ if (entry->bape_offset != 0) {
+ *err_handle = entry->bape_handle;
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+ } else {
+ /* Ensure entry continues where previous left off. */
+ if (prev->bape_offset + OS_MBUF_PKTLEN(prev->bape_value) !=
+ entry->bape_offset) {
+
+ *err_handle = entry->bape_handle;
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+ }
+
+ cur_len = entry->bape_offset + OS_MBUF_PKTLEN(prev->bape_value);
+ if (cur_len > BLE_ATT_ATTR_MAX_LEN) {
+ *err_handle = entry->bape_handle;
+ return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+ }
+
+ prev = entry;
+ }
+
+ return 0;
+}
+
+static int
+ble_att_svr_prep_write(struct ble_att_svr_conn *basc, uint16_t *err_handle)
+{
+ union ble_att_svr_handle_arg arg;
+ struct ble_att_prep_entry *entry;
+ struct ble_att_prep_entry *next;
+ struct ble_att_svr_entry *attr;
+ int buf_off;
+ int rc;
+
+ /* First, validate the contents of the prepare queue. */
+ rc = ble_att_svr_prep_validate(basc, err_handle);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* Contents are valid; perform the writes. */
+ buf_off = 0;
+ entry = SLIST_FIRST(&basc->basc_prep_list);
+ while (entry != NULL) {
+ next = SLIST_NEXT(entry, bape_next);
+
+ rc = os_mbuf_copydata(entry->bape_value, 0,
+ OS_MBUF_PKTLEN(entry->bape_value),
+ ble_att_svr_flat_buf + buf_off);
+ assert(rc == 0);
+ buf_off += OS_MBUF_PKTLEN(entry->bape_value);
+
+ /* If this is the last entry for this attribute, perform the write. */
+ if (next == NULL || entry->bape_handle != next->bape_handle) {
+ attr = NULL;
+ rc = ble_att_svr_find_by_handle(entry->bape_handle, &attr);
+ if (rc != 0) {
+ *err_handle = entry->bape_handle;
+ return BLE_ATT_ERR_INVALID_HANDLE;
+ }
+
+ arg.aha_write.attr_data = ble_att_svr_flat_buf;
+ arg.aha_write.attr_len = buf_off;
+ rc = attr->ha_fn(attr, BLE_ATT_OP_WRITE_REQ, &arg);
+ if (rc != 0) {
+ *err_handle = entry->bape_handle;
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+
+ buf_off = 0;
+ }
+
+ entry = next;
+ }
+
+ return 0;
+}
+
int
-ble_att_svr_init(void)
+ble_att_svr_rx_prep_write(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
{
+ struct ble_att_prep_write_cmd req;
+ struct ble_att_prep_entry *prep_entry;
+ struct ble_att_prep_entry *prep_prev;
+ struct ble_att_svr_entry *attr_entry;
+ struct os_mbuf *srcom;
+ struct os_mbuf *txom;
int rc;
- STAILQ_INIT(&ble_att_svr_list);
+ /* Initialize some values in case of early error. */
+ prep_entry = NULL;
+ req.bapc_handle = 0;
- rc = os_mutex_init(&ble_att_svr_list_mutex);
+ *rxom = os_mbuf_pullup(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ if (*rxom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ rc = ble_att_prep_write_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
if (rc != 0) {
goto err;
}
- free(ble_att_svr_entry_mem);
- ble_att_svr_entry_mem = malloc(
- OS_MEMPOOL_BYTES(BLE_ATT_SVR_NUM_ENTRIES,
- sizeof (struct ble_att_svr_entry)));
- if (ble_att_svr_entry_mem == NULL) {
+ os_mbuf_adj(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+
+ attr_entry = NULL;
+ rc = ble_att_svr_find_by_handle(req.bapc_handle, &attr_entry);
+ if (rc != 0) {
+ rc = BLE_ATT_ERR_INVALID_HANDLE;
+ goto err;
+ }
+
+ prep_entry = ble_att_svr_prep_alloc();
+ if (prep_entry == NULL) {
+ rc = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
+ goto err;
+ }
+
+ prep_prev = ble_att_svr_prep_find_prev(&conn->bhc_att_svr, req.bapc_handle,
+ req.bapc_offset);
+ if (prep_prev == NULL) {
+ SLIST_INSERT_HEAD(&conn->bhc_att_svr.basc_prep_list, prep_entry,
+ bape_next);
+ } else {
+ SLIST_INSERT_AFTER(prep_prev, prep_entry, bape_next);
+ }
+
+ /* Append attribute value from request onto prep mbuf. */
+ for (srcom = *rxom; srcom != NULL; srcom = SLIST_NEXT(srcom, om_next)) {
+ rc = os_mbuf_append(prep_entry->bape_value, srcom->om_data,
+ srcom->om_len);
+ if (rc != 0) {
+ rc = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
+ goto err;
+ }
+ }
+
+ /* The receive buffer now contains the attribute value. Repurpose this
+ * buffer for the response. Prepend a response header.
+ */
+ *rxom = os_mbuf_prepend(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ if (*rxom == NULL) {
+ goto err;
+ }
+ txom = *rxom;
+
+ rc = ble_att_prep_write_rsp_write(txom->om_data,
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ, &req);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_l2cap_tx(conn, chan, txom);
+ if (rc != 0) {
+ rc = BLE_ATT_ERR_UNLIKELY;
+ goto err;
+ }
+
+ /* Make sure the receive buffer doesn't get freed since we are using it for
+ * the response.
+ */
+ *rxom = NULL;
+
+ return 0;
+
+err:
+ if (prep_entry != NULL) {
+ if (prep_prev == NULL) {
+ SLIST_REMOVE_HEAD(&conn->bhc_att_svr.basc_prep_list, bape_next);
+ } else {
+ SLIST_NEXT(prep_prev, bape_next) =
+ SLIST_NEXT(prep_entry, bape_next);
+ }
+
+ ble_att_svr_prep_free(prep_entry);
+ }
+
+ ble_att_svr_tx_error_rsp(conn, chan, BLE_ATT_OP_PREP_WRITE_REQ,
+ req.bapc_handle, rc);
+ return rc;
+}
+
+static int
+ble_att_svr_tx_exec_write_rsp(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan)
+{
+ struct os_mbuf *txom;
+ uint8_t *dst;
+ int rc;
+
+ txom = ble_att_get_pkthdr();
+ if (txom == NULL) {
+ rc = BLE_ATT_ERR_INSUFFICIENT_RES;
+ goto err;
+ }
+
+ dst = os_mbuf_extend(txom, BLE_ATT_EXEC_WRITE_RSP_SZ);
+ if (dst == NULL) {
+ rc = BLE_ATT_ERR_INSUFFICIENT_RES;
+ goto err;
+ }
+
+ rc = ble_att_exec_write_rsp_write(dst, BLE_ATT_EXEC_WRITE_RSP_SZ);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_l2cap_tx(conn, chan, txom);
+ txom = NULL;
+ if (rc != 0) {
+ rc = BLE_ATT_ERR_UNLIKELY;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
+}
+
+int
+ble_att_svr_rx_exec_write(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
+{
+ struct ble_att_exec_write_req req;
+ uint16_t err_handle;
+ int rc;
+
+ /* Initialize some values in case of early error. */
+ err_handle = 0;
+
+ *rxom = os_mbuf_pullup(*rxom, BLE_ATT_EXEC_WRITE_REQ_SZ);
+ if (*rxom == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
}
- rc = os_mempool_init(&ble_att_svr_entry_pool,
- BLE_ATT_SVR_NUM_ENTRIES,
- sizeof (struct ble_att_svr_entry),
- ble_att_svr_entry_mem,
- "ble_att_svr_entry_pool");
+ rc = ble_att_exec_write_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
if (rc != 0) {
goto err;
}
- ble_att_svr_id = 0;
+ if (req.baeq_flags & BLE_ATT_EXEC_WRITE_F_CONFIRM) {
+ /* Perform attribute writes. */
+ rc = ble_att_svr_prep_write(&conn->bhc_att_svr, &err_handle);
+ } else {
+ rc = 0;
+ }
+
+ /* Erase all prep entries. */
+ ble_att_svr_prep_clear(&conn->bhc_att_svr);
+
+ if (rc != 0) {
+ goto err;
+ }
+
+ /* Send response. */
+ rc = ble_att_svr_tx_exec_write_rsp(conn, chan);
+ if (rc != 0) {
+ goto err;
+ }
return 0;
err:
+ ble_att_svr_tx_error_rsp(conn, chan, BLE_ATT_OP_EXEC_WRITE_REQ,
+ err_handle, rc);
+ return rc;
+}
+
+static void
+ble_att_svr_free_mem(void)
+{
free(ble_att_svr_entry_mem);
ble_att_svr_entry_mem = NULL;
+ free(ble_att_svr_prep_entry_mem);
+ ble_att_svr_prep_entry_mem = NULL;
+
+ free(ble_att_svr_prep_mbuf_mem);
+ ble_att_svr_prep_mbuf_mem = NULL;
+}
+
+int
+ble_att_svr_init(void)
+{
+ int rc;
+
+ ble_att_svr_free_mem();
+
+ STAILQ_INIT(&ble_att_svr_list);
+
+ rc = os_mutex_init(&ble_att_svr_list_mutex);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_hs_misc_malloc_mempool(&ble_att_svr_entry_mem,
+ &ble_att_svr_entry_pool,
+ BLE_ATT_SVR_NUM_ENTRIES,
+ sizeof (struct ble_att_svr_entry),
+ "ble_att_svr_entry_pool");
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_hs_misc_malloc_mempool(&ble_att_svr_prep_entry_mem,
+ &ble_att_svr_prep_entry_pool,
+ BLE_ATT_SVR_NUM_PREP_ENTRIES,
+ sizeof (struct ble_att_prep_entry),
+ "ble_att_prep_entry_pool");
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_hs_misc_malloc_mempool(&ble_att_svr_prep_mbuf_mem,
+ &ble_att_svr_prep_mbuf_mempool,
+ BLE_ATT_SVR_NUM_PREP_MBUFS,
+ BLE_ATT_SVR_PREP_MBUF_MEMBLOCK_SIZE,
+ "ble_att_prep_mbuf_mempool");
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = os_mbuf_pool_init(&ble_att_svr_prep_mbuf_pool,
+ &ble_att_svr_prep_mbuf_mempool,
+ BLE_ATT_SVR_PREP_MBUF_MEMBLOCK_SIZE,
+ BLE_ATT_SVR_NUM_PREP_MBUFS);
+ if (rc != 0) {
+ rc = BLE_HS_EOS;
+ goto err;
+ }
+
+ ble_att_svr_id = 0;
+
+ return 0;
+
+err:
+ ble_att_svr_free_mem();
return rc;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_hs.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index 0cae900..92a8e9f 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -79,7 +79,7 @@ struct ble_hs_pkt {
struct tpq_elem bhp_tpq_elem;
struct os_mbuf *bhp_om;
};
-static os_membuf_t *ble_hs_pkt_mem;
+static void *ble_hs_pkt_mem;
static struct os_mempool ble_hs_pkt_pool;
static struct tpq ble_hs_rx_q;
@@ -264,28 +264,20 @@ ble_hs_init(uint8_t prio)
BLE_HS_MBUF_MEMBLOCK_SIZE,
ble_hs_mbuf_mem, "ble_hs_mbuf_pool");
if (rc != 0) {
- rc = BLE_HS_EINVAL; // XXX
+ rc = BLE_HS_EOS;
goto err;
}
rc = os_mbuf_pool_init(&ble_hs_mbuf_pool, &ble_hs_mbuf_mempool,
BLE_HS_MBUF_MEMBLOCK_SIZE, BLE_HS_NUM_MBUFS);
if (rc != 0) {
- rc = BLE_HS_EINVAL; // XXX
+ rc = BLE_HS_EOS;
goto err;
}
- ble_hs_pkt_mem = malloc(
- OS_MEMPOOL_BYTES(BLE_HS_PKT_MAX,
- sizeof (struct ble_hs_pkt)));
- if (ble_hs_pkt_mem == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
- }
- rc = os_mempool_init(&ble_hs_pkt_pool, BLE_HS_PKT_MAX,
- sizeof (struct ble_hs_pkt),
- ble_hs_pkt_mem, "ble_hs_pkt_pool");
+ rc = ble_hs_misc_malloc_mempool(&ble_hs_pkt_mem, &ble_hs_pkt_pool,
+ BLE_HS_PKT_MAX, sizeof (struct ble_hs_pkt),
+ "ble_hs_pkt_pool");
if (rc != 0) {
- rc = BLE_HS_EINVAL; // XXX
goto err;
}
@@ -316,13 +308,6 @@ ble_hs_init(uint8_t prio)
goto err;
}
-#if 0
- rc = ble_hs_hci_batch_init();
- if (rc != 0) {
- goto err;
- }
-#endif
-
rc = ble_gatt_init();
if (rc != 0) {
goto err;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_hs_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.c b/net/nimble/host/src/ble_hs_conn.c
index b573bc7..43f401c 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -57,8 +57,6 @@ ble_hs_conn_alloc(void)
}
SLIST_INSERT_HEAD(&conn->bhc_channels, chan, blc_next);
- SLIST_INIT(&conn->bhc_att_clt_list);
-
return conn;
err:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_hs_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.h b/net/nimble/host/src/ble_hs_conn.h
index de75254..0951376 100644
--- a/net/nimble/host/src/ble_hs_conn.h
+++ b/net/nimble/host/src/ble_hs_conn.h
@@ -31,8 +31,7 @@ struct ble_hs_conn {
struct ble_l2cap_chan_list bhc_channels;
- /** Mapping of peer's ATT attributes to handle IDs. */
- struct ble_att_clt_entry_list bhc_att_clt_list;
+ struct ble_att_svr_conn bhc_att_svr;
};
struct ble_hs_conn *ble_hs_conn_alloc(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_hs_misc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
new file mode 100644
index 0000000..9c076f5
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include "os/os.h"
+#include "ble_hs_priv.h"
+
+int
+ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
+ int num_entries, int entry_size, char *name)
+{
+ int rc;
+
+ *mem = malloc(OS_MEMPOOL_BYTES(num_entries, entry_size));
+ if (*mem == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ rc = os_mempool_init(pool, num_entries, entry_size, *mem, name);
+ if (rc != 0) {
+ free(*mem);
+ return BLE_HS_EOS;
+ }
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/ble_hs_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_priv.h b/net/nimble/host/src/ble_hs_priv.h
index 6daedd6..00357dc 100644
--- a/net/nimble/host/src/ble_hs_priv.h
+++ b/net/nimble/host/src/ble_hs_priv.h
@@ -20,6 +20,7 @@
#include <inttypes.h>
#include "host/ble_hs.h"
struct os_mbuf;
+struct os_mempool;
#define BLE_HOST_HCI_EVENT_CTLR_EVENT (OS_EVENT_T_PERUSER + 0)
#define BLE_HS_KICK_HCI_EVENT (OS_EVENT_T_PERUSER + 1)
@@ -36,4 +37,7 @@ int ble_hs_tx_data(struct os_mbuf *om);
void ble_hs_kick_hci(void);
void ble_hs_kick_gatt(void);
+int ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
+ int num_entries, int entry_size, char *name);
+
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/762dccc3/net/nimble/host/src/test/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c
index cfc1793..03e345a 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -214,23 +214,16 @@ static int
ble_att_svr_test_misc_attr_fn_w_1(struct ble_att_svr_entry *entry, uint8_t op,
union ble_att_svr_handle_arg *arg)
{
- struct os_mbuf_pkthdr *omp;
- int rc;
-
switch (op) {
case BLE_ATT_OP_WRITE_REQ:
- omp = OS_MBUF_PKTHDR(arg->aha_write.om);
- rc = os_mbuf_copydata(arg->aha_write.om, 0, arg->aha_write.attr_len,
- ble_att_svr_test_attr_w_1);
- TEST_ASSERT(rc == 0);
+ memcpy(ble_att_svr_test_attr_w_1, arg->aha_write.attr_data,
+ arg->aha_write.attr_len);
ble_att_svr_test_attr_w_1_len = arg->aha_write.attr_len;
return 0;
default:
return -1;
}
-
- (void)omp;
}
static void