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/06 00:14:43 UTC
[1/4] incubator-mynewt-larva git commit: Fix some host test project
bugs.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master 2fdc71732 -> 6545cc0bb
Fix some host test project bugs.
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/2d071909
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/2d071909
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/2d071909
Branch: refs/heads/master
Commit: 2d0719090a76697e9955469544bd9111c40200d5
Parents: 2fdc717
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 5 11:47:42 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Jan 5 11:47:42 2016 -0800
----------------------------------------------------------------------
project/centtest/src/main.c | 2 +-
project/prphtest/src/main.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/2d071909/project/centtest/src/main.c
----------------------------------------------------------------------
diff --git a/project/centtest/src/main.c b/project/centtest/src/main.c
index 42d247f..3b15657 100755
--- a/project/centtest/src/main.c
+++ b/project/centtest/src/main.c
@@ -181,7 +181,7 @@ centtest_print_adv_rpt(struct ble_gap_conn_adv_rpt *adv)
console_printf(" flags=0x%02x\n", adv->fields.flags);
console_printf(" name=");
console_write((char *)adv->fields.name, adv->fields.name_len);
- console_printf("%s\n");
+ console_printf("\n");
}
static void
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/2d071909/project/prphtest/src/main.c
----------------------------------------------------------------------
diff --git a/project/prphtest/src/main.c b/project/prphtest/src/main.c
index 92841af..b2a6cb0 100755
--- a/project/prphtest/src/main.c
+++ b/project/prphtest/src/main.c
@@ -241,6 +241,7 @@ prphtest_task_handler(void *arg)
prphtest_register_attrs();
+ memset(&fields, 0, sizeof fields);
fields.name = (uint8_t *)"nimble";
fields.name_len = 6;
fields.name_is_complete = 1;
[3/4] incubator-mynewt-larva git commit: Notification tests.
Posted by cc...@apache.org.
Notification tests.
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/b296dd4c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/b296dd4c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/b296dd4c
Branch: refs/heads/master
Commit: b296dd4cb10602a08600aa6d9d57ee210a6ebffb
Parents: 8764e91
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 5 14:52:16 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Jan 5 15:13:50 2016 -0800
----------------------------------------------------------------------
net/nimble/host/src/ble_att.c | 7 ++
net/nimble/host/src/ble_att_cmd.c | 4 +-
net/nimble/host/src/ble_att_priv.h | 3 +
net/nimble/host/src/ble_att_svr.c | 4 +
net/nimble/host/src/test/ble_att_svr_test.c | 104 +++++++++++++++++++++++
5 files changed, 120 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b296dd4c/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 8437389..05da354 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -103,6 +103,13 @@ ble_att_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
}
void
+ble_att_set_notify_cb(ble_att_svr_notify_fn *cb, void *cb_arg)
+{
+ ble_att_svr_notify_cb = cb;
+ ble_att_svr_notify_cb_arg = cb_arg;
+}
+
+void
ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu)
{
if (peer_mtu < BLE_ATT_MTU_DFLT) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b296dd4c/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 cae2189..918e452 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -694,7 +694,7 @@ ble_att_notify_req_write(void *payload, int len,
}
u8ptr = payload;
- u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_RSP;
+ u8ptr[0] = BLE_ATT_OP_NOTIFY_REQ;
htole16(u8ptr + 1, req->banq_handle);
return 0;
@@ -733,7 +733,7 @@ ble_att_indicate_req_write(void *payload, int len,
}
u8ptr = payload;
- u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_RSP;
+ u8ptr[0] = BLE_ATT_OP_INDICATE_REQ;
htole16(u8ptr + 1, req->baiq_handle);
return 0;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b296dd4c/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 d9f2eed..3b8d2ff 100644
--- a/net/nimble/host/src/ble_att_priv.h
+++ b/net/nimble/host/src/ble_att_priv.h
@@ -95,6 +95,9 @@ void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu);
struct os_mbuf *ble_att_get_pkthdr(void);
/*** @svr */
+extern ble_att_svr_notify_fn *ble_att_svr_notify_cb;
+extern void *ble_att_svr_notify_cb_arg;
+
int ble_att_svr_find_by_uuid(uint8_t *uuid, struct ble_att_svr_entry **ha_ptr);
uint16_t ble_att_svr_prev_handle(void);
int ble_att_svr_rx_mtu(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b296dd4c/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 8c7e985..419191b 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -2200,6 +2200,10 @@ ble_att_svr_rx_notify(struct ble_hs_conn *conn,
rc = ble_att_notify_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
assert(rc == 0);
+ if (req.banq_handle == 0) {
+ return BLE_HS_EBADDATA;
+ }
+
os_mbuf_adj(*rxom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
attr_data = ble_att_svr_flat_buf;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b296dd4c/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 c39837e..3d0d8a9 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -38,6 +38,11 @@ static int ble_att_svr_test_attr_w_1_len;
static uint8_t ble_att_svr_test_attr_w_2[1024];
static int ble_att_svr_test_attr_w_2_len;
+static uint16_t ble_att_svr_test_n_conn_handle;
+static uint16_t ble_att_svr_test_n_attr_handle;
+static uint8_t ble_att_svr_test_attr_n[1024];
+static int ble_att_svr_test_attr_n_len;
+
static void
ble_att_svr_test_misc_init(struct ble_hs_conn **conn,
struct ble_l2cap_chan **att_chan)
@@ -720,6 +725,81 @@ ble_att_svr_test_misc_exec_write(struct ble_hs_conn *conn,
}
}
+static void
+ble_att_svr_test_misc_rx_notify(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ struct ble_att_notify_req req;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+
+ req.banq_handle = attr_handle;
+ rc = ble_att_notify_req_write(buf, sizeof buf, &req);
+ TEST_ASSERT_FATAL(rc == 0);
+ off = BLE_ATT_NOTIFY_REQ_BASE_SZ;
+
+ memcpy(buf + off, attr_val, attr_len);
+ off += attr_len;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, off);
+ if (good) {
+ TEST_ASSERT(rc == 0);
+ } else {
+ TEST_ASSERT(rc == BLE_HS_EBADDATA);
+ }
+}
+
+static int
+ble_att_svr_test_misc_notify_cb(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t *attr_val, uint16_t attr_len,
+ void *arg)
+{
+ int *iarg;
+
+ iarg = arg;
+
+ ble_att_svr_test_n_conn_handle = conn_handle;
+ ble_att_svr_test_n_attr_handle = attr_handle;
+ TEST_ASSERT_FATAL(attr_len <= sizeof ble_att_svr_test_attr_n);
+ ble_att_svr_test_attr_n_len = attr_len;
+ memcpy(ble_att_svr_test_attr_n, attr_val, attr_len);
+
+ return *iarg;
+}
+
+static void
+ble_att_svr_test_misc_verify_notify(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ int cbrc;
+
+ cbrc = 0;
+ ble_att_set_notify_cb(ble_att_svr_test_misc_notify_cb, &cbrc);
+
+ ble_att_svr_test_n_conn_handle = 0xffff;
+ ble_att_svr_test_n_attr_handle = 0;
+ ble_att_svr_test_attr_n_len = 0;
+
+ ble_att_svr_test_misc_rx_notify(conn, chan, attr_handle, attr_val,
+ attr_len, good);
+
+ if (good) {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == conn->bhc_handle);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == attr_handle);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == attr_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_n, attr_val, attr_len) == 0);
+ } else {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == 0xffff);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == 0);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == 0);
+ }
+}
+
TEST_CASE(ble_att_svr_test_mtu)
{
/*** MTU too low; should pretend peer sent default value instead. */
@@ -1664,6 +1744,29 @@ TEST_CASE(ble_att_svr_test_prep_write)
ble_att_svr_test_misc_verify_w_2(data, 61);
}
+TEST_CASE(ble_att_svr_test_notify)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+
+ ble_att_svr_test_misc_init(&conn, &chan);
+
+ /*** Successful notifies; verify callback is executed. */
+ /* 3-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn, chan, 10,
+ (uint8_t[]) { 1, 2, 3 }, 3, 1);
+ /* 1-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn, chan, 1,
+ (uint8_t[]) { 0xff }, 1, 1);
+ /* 0-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn, chan, 43, NULL, 0, 1);
+
+ /*** Bad notifies; verify callback is not executed. */
+ /* Attribute handle of 0. */
+ ble_att_svr_test_misc_verify_notify(conn, chan, 0,
+ (uint8_t[]) { 1, 2, 3 }, 3, 0);
+}
+
TEST_SUITE(ble_att_svr_suite)
{
ble_att_svr_test_mtu();
@@ -1674,6 +1777,7 @@ TEST_SUITE(ble_att_svr_suite)
ble_att_svr_test_read_type();
ble_att_svr_test_read_group_type();
ble_att_svr_test_prep_write();
+ ble_att_svr_test_notify();
}
int
[2/4] incubator-mynewt-larva git commit: Notifications and
indications.
Posted by cc...@apache.org.
Notifications and indications.
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/8764e91d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/8764e91d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/8764e91d
Branch: refs/heads/master
Commit: 8764e91d808bb997ee8b73cb8ea81d203e6d3652
Parents: 2d07190
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 5 14:12:52 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Jan 5 14:12:52 2016 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/ble_att.h | 9 ++
net/nimble/host/include/host/ble_gatt.h | 2 +-
net/nimble/host/src/ble_att.c | 3 +
net/nimble/host/src/ble_att_clt.c | 132 +++++++++++++++--
net/nimble/host/src/ble_att_cmd.c | 78 ++++++++++
net/nimble/host/src/ble_att_cmd.h | 36 +++++
net/nimble/host/src/ble_att_priv.h | 20 +++
net/nimble/host/src/ble_att_svr.c | 138 ++++++++++++++++-
net/nimble/host/src/ble_gatt_priv.h | 5 +
net/nimble/host/src/ble_gattc.c | 214 ++++++++++++++++++++++++++-
net/nimble/host/src/ble_gatts.c | 63 +++++++-
11 files changed, 672 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 a0d36e3..929df5b 100644
--- a/net/nimble/host/include/host/ble_att.h
+++ b/net/nimble/host/include/host/ble_att.h
@@ -56,6 +56,9 @@
#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_NOTIFY_REQ 0x1b
+#define BLE_ATT_OP_INDICATE_REQ 0x1d
+#define BLE_ATT_OP_INDICATE_RSP 0x1e
#define BLE_ATT_OP_WRITE_CMD 0x52
#define BLE_ATT_ATTR_MAX_LEN 512
@@ -99,4 +102,10 @@ int ble_att_svr_register_uuid16(uint16_t uuid16, uint8_t flags,
uint16_t *handle_id, ble_att_svr_access_fn *cb,
void *cb_arg);
+typedef int ble_att_svr_notify_fn(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t *attr_val, uint16_t attr_len,
+ void *arg);
+
+void ble_att_set_notify_cb(ble_att_svr_notify_fn *cb, void *cb_arg);
+
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 0a9d35f..f076b04 100644
--- a/net/nimble/host/include/host/ble_gatt.h
+++ b/net/nimble/host/include/host/ble_gatt.h
@@ -86,7 +86,6 @@ int ble_gatt_init(void);
#define BLE_GATT_ACCESS_OP_WRITE_CHR 1
#define BLE_GATT_ACCESS_OP_READ_DSC 2
#define BLE_GATT_ACCESS_OP_WRITE_DSC 3
-/* XXX: Notify, listen. */
union ble_gatt_access_ctxt;
typedef int ble_gatt_access_fn(uint16_t conn_handle, uint16_t attr_handle,
@@ -157,6 +156,7 @@ typedef void ble_gatt_register_fn(uint8_t op,
int ble_gatt_register_services(const struct ble_gatt_svc_def *svcs,
ble_gatt_register_fn *register_cb,
void *cb_arg);
+void ble_gatts_chr_updated(uint16_t chr_def_handle);
union ble_gatt_register_ctxt {
struct {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 a90a6da..8437389 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -48,6 +48,9 @@ static struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
{ 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 },
+ { 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 },
};
#define BLE_ATT_RX_DISPATCH_SZ \
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 41fabc5..42934e4 100644
--- a/net/nimble/host/src/ble_att_clt.c
+++ b/net/nimble/host/src/ble_att_clt.c
@@ -627,6 +627,33 @@ ble_att_clt_rx_find_type_value(struct ble_hs_conn *conn,
}
static int
+ble_att_clt_append_blob(struct ble_l2cap_chan *chan, struct os_mbuf *txom,
+ void *blob, int blob_len)
+{
+ uint16_t mtu;
+ int extra_len;
+ int cmd_len;
+ int rc;
+
+ mtu = ble_l2cap_chan_mtu(chan);
+ cmd_len = OS_MBUF_PKTLEN(txom) + blob_len;
+ extra_len = cmd_len - mtu;
+ if (extra_len > 0) {
+ blob_len -= extra_len;
+ }
+ if (blob_len <= 0) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ rc = os_mbuf_append(txom, blob, blob_len);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
ble_att_clt_tx_write_req_or_cmd(struct ble_hs_conn *conn,
struct ble_att_write_req *req,
void *value, uint16_t value_len,
@@ -634,8 +661,6 @@ ble_att_clt_tx_write_req_or_cmd(struct ble_hs_conn *conn,
{
struct ble_l2cap_chan *chan;
struct os_mbuf *txom;
- uint16_t mtu;
- int extra_len;
int rc;
txom = NULL;
@@ -652,13 +677,7 @@ ble_att_clt_tx_write_req_or_cmd(struct ble_hs_conn *conn,
}
assert(rc == 0);
- mtu = ble_l2cap_chan_mtu(chan);
- extra_len = BLE_ATT_WRITE_REQ_BASE_SZ + value_len - mtu;
- if (extra_len > 0) {
- value_len -= extra_len;
- }
-
- rc = os_mbuf_append(txom, value, value_len);
+ rc = ble_att_clt_append_blob(chan, txom, value, value_len);
if (rc != 0) {
goto err;
}
@@ -716,3 +735,98 @@ ble_att_clt_rx_write(struct ble_hs_conn *conn,
return 0;
}
+
+int
+ble_att_clt_tx_notify(struct ble_hs_conn *conn, struct ble_att_notify_req *req,
+ void *value, uint16_t value_len)
+{
+ struct ble_l2cap_chan *chan;
+ struct os_mbuf *txom;
+ int rc;
+
+ txom = NULL;
+
+ if (req->banq_handle == 0) {
+ rc = BLE_HS_EINVAL;
+ goto err;
+ }
+
+ rc = ble_att_clt_prep_req(conn, &chan, &txom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_att_notify_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_tx_indicate(struct ble_hs_conn *conn,
+ struct ble_att_indicate_req *req,
+ void *value, uint16_t value_len)
+{
+ struct ble_l2cap_chan *chan;
+ struct os_mbuf *txom;
+ int rc;
+
+ txom = NULL;
+
+ if (req->baiq_handle == 0) {
+ rc = BLE_HS_EINVAL;
+ goto err;
+ }
+
+ rc = ble_att_clt_prep_req(conn, &chan, &txom,
+ BLE_ATT_INDICATE_REQ_BASE_SZ);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_att_indicate_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_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
+{
+ /* No payload. */
+ ble_gattc_rx_indicate_rsp(conn);
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 2a244d6..cae2189 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -660,3 +660,81 @@ ble_att_exec_write_rsp_write(void *payload, int len)
return 0;
}
+
+int
+ble_att_notify_req_parse(void *payload, int len,
+ struct ble_att_notify_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_NOTIFY_REQ_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ if (u8ptr[0] != BLE_ATT_OP_NOTIFY_REQ) {
+ return BLE_HS_EINVAL;
+ }
+
+ req->banq_handle = le16toh(u8ptr + 1);
+
+ return 0;
+
+}
+
+int
+ble_att_notify_req_write(void *payload, int len,
+ struct ble_att_notify_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_NOTIFY_REQ_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_RSP;
+ htole16(u8ptr + 1, req->banq_handle);
+
+ return 0;
+}
+
+int
+ble_att_indicate_req_parse(void *payload, int len,
+ struct ble_att_indicate_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_INDICATE_REQ_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ if (u8ptr[0] != BLE_ATT_OP_INDICATE_REQ) {
+ return BLE_HS_EINVAL;
+ }
+
+ req->baiq_handle = le16toh(u8ptr + 1);
+
+ return 0;
+
+}
+
+int
+ble_att_indicate_req_write(void *payload, int len,
+ struct ble_att_indicate_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_INDICATE_REQ_BASE_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = BLE_ATT_OP_EXEC_WRITE_RSP;
+ htole16(u8ptr + 1, req->baiq_handle);
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 dad8623..7028bbb 100644
--- a/net/nimble/host/src/ble_att_cmd.h
+++ b/net/nimble/host/src/ble_att_cmd.h
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#ifndef H_BLE_ATT_CMD_
+#define H_BLE_ATT_CMD_
+
#include <inttypes.h>
struct ble_l2cap_chan;
@@ -226,6 +229,29 @@ struct ble_att_exec_write_req {
*/
#define BLE_ATT_EXEC_WRITE_RSP_SZ 1
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Attribute Handle | 2 |
+ * | Attribute Value | 0 to (ATT_MTU-3) |
+ */
+#define BLE_ATT_NOTIFY_REQ_BASE_SZ 3
+struct ble_att_notify_req {
+ uint16_t banq_handle;
+};
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Attribute Handle | 2 |
+ * | Attribute Value | 0 to (ATT_MTU-3) |
+ */
+#define BLE_ATT_INDICATE_REQ_BASE_SZ 3
+struct ble_att_indicate_req {
+ uint16_t baiq_handle;
+};
int ble_att_error_rsp_parse(void *payload, int len,
struct ble_att_error_rsp *rsp);
@@ -291,3 +317,13 @@ int ble_att_exec_write_req_write(void *payload, int len,
struct ble_att_exec_write_req *req);
int ble_att_exec_write_rsp_parse(void *payload, int len);
int ble_att_exec_write_rsp_write(void *payload, int len);
+int ble_att_notify_req_parse(void *payload, int len,
+ struct ble_att_notify_req *req);
+int ble_att_notify_req_write(void *payload, int len,
+ struct ble_att_notify_req *req);
+int ble_att_indicate_req_parse(void *payload, int len,
+ struct ble_att_indicate_req *req);
+int ble_att_indicate_req_write(void *payload, int len,
+ struct ble_att_indicate_req *req);
+
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 db8252a..d9f2eed 100644
--- a/net/nimble/host/src/ble_att_priv.h
+++ b/net/nimble/host/src/ble_att_priv.h
@@ -32,6 +32,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_notify_req;
+struct ble_att_indicate_req;
#define BLE_ATT_MTU_DFLT 23 /* Also the minimum. */
#define BLE_ATT_MTU_MAX 256 /* XXX: I'm making this up! */
@@ -119,7 +121,16 @@ int ble_att_svr_rx_prep_write(struct ble_hs_conn *conn,
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_rx_notify(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
+int ble_att_svr_rx_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
void ble_att_svr_prep_clear(struct ble_att_svr_conn *basc);
+int ble_att_svr_read_handle(struct ble_hs_conn *conn, uint16_t attr_handle,
+ struct ble_att_svr_access_ctxt *ctxt,
+ uint8_t *out_att_err);
int ble_att_svr_init(void);
/*** @clt */
@@ -165,5 +176,14 @@ int ble_att_clt_tx_write_cmd(struct ble_hs_conn *conn,
int ble_att_clt_rx_write(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf **rxom);
+int ble_att_clt_tx_notify(struct ble_hs_conn *conn,
+ struct ble_att_notify_req *req,
+ void *value, uint16_t value_len);
+int ble_att_clt_tx_indicate(struct ble_hs_conn *conn,
+ struct ble_att_indicate_req *req,
+ void *value, uint16_t value_len);
+int ble_att_clt_rx_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 57c705a..8c7e985 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -51,6 +51,9 @@ static struct os_mbuf_pool ble_att_svr_prep_mbuf_pool;
static uint8_t ble_att_svr_flat_buf[BLE_ATT_ATTR_MAX_LEN];
+ble_att_svr_notify_fn *ble_att_svr_notify_cb;
+void *ble_att_svr_notify_cb_arg;
+
/**
* Locks the host attribute list.
*
@@ -327,20 +330,20 @@ ble_att_svr_read(struct ble_hs_conn *conn, struct ble_att_svr_entry *entry,
uint8_t att_err;
int rc;
- if (!(entry->ha_flags & HA_FLAG_PERM_READ)) {
- att_err = BLE_ATT_ERR_READ_NOT_PERMITTED;
- rc = BLE_HS_ENOTSUP;
- goto err;
- }
-
- /* XXX: Check security. */
-
if (conn == NULL) {
conn_handle = 0xffff; /* XXX */
} else {
conn_handle = conn->bhc_handle;
+
+ if (!(entry->ha_flags & HA_FLAG_PERM_READ)) {
+ att_err = BLE_ATT_ERR_READ_NOT_PERMITTED;
+ rc = BLE_HS_ENOTSUP;
+ goto err;
+ }
}
+ /* XXX: Check security. */
+
assert(entry->ha_cb != NULL);
rc = entry->ha_cb(conn_handle, entry->ha_handle_id,
entry->ha_uuid, BLE_ATT_ACCESS_OP_READ, ctxt,
@@ -360,6 +363,29 @@ err:
return rc;
}
+int
+ble_att_svr_read_handle(struct ble_hs_conn *conn, uint16_t attr_handle,
+ struct ble_att_svr_access_ctxt *ctxt,
+ uint8_t *out_att_err)
+{
+ struct ble_att_svr_entry *entry;
+ int rc;
+
+ entry = NULL;
+ rc = ble_att_svr_find_by_handle(attr_handle, &entry);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_att_svr_read(conn, entry, ctxt, out_att_err);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+
static int
ble_att_svr_write(struct ble_hs_conn *conn, struct ble_att_svr_entry *entry,
struct ble_att_svr_access_ctxt *ctxt, uint8_t *out_att_err)
@@ -2152,6 +2178,101 @@ err:
return rc;
}
+int
+ble_att_svr_rx_notify(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
+{
+ struct ble_att_notify_req req;
+ uint16_t attr_len;
+ void *attr_data;
+ int rc;
+
+ if (OS_MBUF_PKTLEN(*rxom) < BLE_ATT_NOTIFY_REQ_BASE_SZ) {
+ return BLE_HS_EBADDATA;
+ }
+
+ *rxom = os_mbuf_pullup(*rxom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
+ if (*rxom == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ rc = ble_att_notify_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
+ assert(rc == 0);
+
+ os_mbuf_adj(*rxom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
+
+ attr_data = ble_att_svr_flat_buf;
+ attr_len = OS_MBUF_PKTLEN(*rxom);
+ os_mbuf_copydata(*rxom, 0, attr_len, attr_data);
+
+ if (ble_att_svr_notify_cb != NULL) {
+ rc = ble_att_svr_notify_cb(conn->bhc_handle, req.banq_handle,
+ attr_data, attr_len,
+ ble_att_svr_notify_cb_arg);
+ if (rc != 0) {
+ return BLE_HS_EAPP;
+ }
+ }
+
+ return 0;
+}
+
+int
+ble_att_svr_rx_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
+{
+ struct ble_att_indicate_req req;
+ uint16_t err_handle;
+ uint16_t attr_len;
+ uint8_t att_err;
+ void *attr_data;
+ int rc;
+
+ if (OS_MBUF_PKTLEN(*rxom) < BLE_ATT_INDICATE_REQ_BASE_SZ) {
+ att_err = BLE_ATT_ERR_INVALID_PDU;
+ err_handle = 0;
+ rc = BLE_HS_EBADDATA;
+ goto err;
+ }
+
+ *rxom = os_mbuf_pullup(*rxom, BLE_ATT_INDICATE_REQ_BASE_SZ);
+ if (*rxom == NULL) {
+ att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+ err_handle = 0;
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ rc = ble_att_indicate_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
+ assert(rc == 0);
+
+ os_mbuf_adj(*rxom, BLE_ATT_INDICATE_REQ_BASE_SZ);
+
+ attr_data = ble_att_svr_flat_buf;
+ attr_len = OS_MBUF_PKTLEN(*rxom);
+ os_mbuf_copydata(*rxom, 0, attr_len, attr_data);
+
+ if (ble_att_svr_notify_cb != NULL) {
+ att_err = ble_att_svr_notify_cb(conn->bhc_handle, req.baiq_handle,
+ attr_data, attr_len,
+ ble_att_svr_notify_cb_arg);
+ if (att_err != 0) {
+ err_handle = req.baiq_handle;
+ rc = BLE_HS_EAPP;
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ ble_att_svr_tx_error_rsp(conn, chan, BLE_ATT_OP_INDICATE_REQ, err_handle,
+ att_err);
+ return rc;
+}
+
static void
ble_att_svr_free_mem(void)
{
@@ -2216,6 +2337,7 @@ ble_att_svr_init(void)
}
ble_att_svr_id = 0;
+ ble_att_svr_notify_cb = NULL;
return 0;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 2445104..c222f79 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -54,6 +54,10 @@ 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_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
+ ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle,
+ ble_gatt_attr_fn *cb, void *cb_arg);
int ble_gattc_exchange_mtu(uint16_t conn_handle);
@@ -72,6 +76,7 @@ void ble_gattc_rx_find_type_value_hinfo(struct ble_hs_conn *conn,
struct ble_att_clt_adata *adata);
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_indicate_rsp(struct ble_hs_conn *conn);
void ble_gattc_connection_txable(uint16_t conn_handle);
void ble_gattc_connection_broken(uint16_t conn_handle);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/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 4ad7eba..b44113c 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -74,6 +74,18 @@ struct ble_gattc_entry {
ble_gatt_attr_fn *cb;
void *cb_arg;
} write;
+
+ struct {
+ struct ble_gatt_attr attr;
+ ble_gatt_attr_fn *cb;
+ void *cb_arg;
+ } notify;
+
+ struct {
+ struct ble_gatt_attr attr;
+ ble_gatt_attr_fn *cb;
+ void *cb_arg;
+ } indicate;
};
};
@@ -88,7 +100,9 @@ struct ble_gattc_entry {
#define BLE_GATT_OP_READ 4
#define BLE_GATT_OP_WRITE_NO_RSP 5
#define BLE_GATT_OP_WRITE 6
-#define BLE_GATT_OP_MAX 7
+#define BLE_GATT_OP_NOTIFY 7
+#define BLE_GATT_OP_INDICATE 8
+#define BLE_GATT_OP_MAX 9
static struct os_callout_func ble_gattc_heartbeat_timer;
@@ -102,6 +116,8 @@ static int ble_gattc_kick_disc_all_chars(struct ble_gattc_entry *entry);
static int ble_gattc_kick_read(struct ble_gattc_entry *entry);
static int ble_gattc_kick_write_no_rsp(struct ble_gattc_entry *entry);
static int ble_gattc_kick_write(struct ble_gattc_entry *entry);
+static int ble_gattc_kick_notify(struct ble_gattc_entry *entry);
+static int ble_gattc_kick_indicate(struct ble_gattc_entry *entry);
static void ble_gattc_err_mtu(struct ble_gattc_entry *entry, int status);
static void ble_gattc_err_disc_all_services(struct ble_gattc_entry *entry,
@@ -112,6 +128,7 @@ static void ble_gattc_err_disc_all_chars(struct ble_gattc_entry *entry,
int status);
static void ble_gattc_err_read(struct ble_gattc_entry *entry, int status);
static void ble_gattc_err_write(struct ble_gattc_entry *entry, int status);
+static void ble_gattc_err_indicate(struct ble_gattc_entry *entry, int status);
struct ble_gattc_dispatch_entry {
ble_gattc_kick_fn *kick_cb;
@@ -149,6 +166,14 @@ static const struct ble_gattc_dispatch_entry
.kick_cb = ble_gattc_kick_write,
.err_cb = ble_gattc_err_write,
},
+ [BLE_GATT_OP_NOTIFY] = {
+ .kick_cb = ble_gattc_kick_notify,
+ .err_cb = NULL,
+ },
+ [BLE_GATT_OP_INDICATE] = {
+ .kick_cb = ble_gattc_kick_indicate,
+ .err_cb = ble_gattc_err_indicate,
+ },
};
#define BLE_GATT_ENTRY_F_PENDING 0x01
@@ -1152,7 +1177,7 @@ ble_gattc_rx_write_rsp(struct ble_hs_conn *conn)
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)
+ uint16_t value_len, ble_gatt_attr_fn *cb, void *cb_arg)
{
struct ble_gattc_entry *entry;
int rc;
@@ -1172,6 +1197,191 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
}
/*****************************************************************************
+ * $notify *
+ *****************************************************************************/
+
+static int
+ble_gattc_notify_cb(struct ble_gattc_entry *entry, int status)
+{
+ int rc;
+
+ if (entry->notify.cb == NULL) {
+ rc = 0;
+ } else {
+ rc = entry->notify.cb(entry->conn_handle, status, &entry->notify.attr,
+ entry->notify.cb_arg);
+ }
+
+ return rc;
+}
+
+static int
+ble_gattc_kick_notify(struct ble_gattc_entry *entry)
+{
+ struct ble_att_svr_access_ctxt ctxt;
+ struct ble_att_notify_req 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;
+ }
+
+ rc = ble_att_svr_read_handle(NULL, entry->notify.attr.handle, &ctxt,
+ NULL);
+ if (rc != 0) {
+ goto err;
+ }
+ entry->notify.attr.value = ctxt.attr_data;
+ entry->notify.attr.value_len = ctxt.attr_len;
+
+ req.banq_handle = entry->notify.attr.handle;
+ rc = ble_att_clt_tx_notify(conn, &req, entry->notify.attr.value,
+ entry->notify.attr.value_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ /* No response expected; call callback immediately and return nonzero to
+ * indicate the entry should be freed.
+ */
+ ble_gattc_notify_cb(entry, 0);
+
+ return 1;
+
+err:
+ if (ble_gattc_tx_postpone_chk(entry, rc)) {
+ return BLE_HS_EAGAIN;
+ }
+
+ ble_gattc_notify_cb(entry, rc);
+ return rc;
+}
+
+int
+ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle,
+ 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_NOTIFY, &entry);
+ if (rc != 0) {
+ return rc;
+ }
+
+ entry->notify.attr.handle = chr_val_handle;
+ entry->notify.cb = cb;
+ entry->notify.cb_arg = cb_arg;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * $indicate *
+ *****************************************************************************/
+
+static int
+ble_gattc_indicate_cb(struct ble_gattc_entry *entry, int status)
+{
+ int rc;
+
+ if (entry->indicate.cb == NULL) {
+ rc = 0;
+ } else {
+ rc = entry->indicate.cb(entry->conn_handle, status,
+ &entry->indicate.attr, entry->indicate.cb_arg);
+ }
+
+ return rc;
+}
+
+static int
+ble_gattc_kick_indicate(struct ble_gattc_entry *entry)
+{
+ struct ble_att_svr_access_ctxt ctxt;
+ struct ble_att_indicate_req 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;
+ }
+
+ rc = ble_att_svr_read_handle(NULL, entry->indicate.attr.handle, &ctxt,
+ NULL);
+ if (rc != 0) {
+ goto err;
+ }
+ entry->indicate.attr.value = ctxt.attr_data;
+ entry->indicate.attr.value_len = ctxt.attr_len;
+
+ req.baiq_handle = entry->indicate.attr.handle;
+ rc = ble_att_clt_tx_indicate(conn, &req, entry->indicate.attr.value,
+ entry->indicate.attr.value_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ return 0;
+
+err:
+ if (ble_gattc_tx_postpone_chk(entry, rc)) {
+ return BLE_HS_EAGAIN;
+ }
+
+ ble_gattc_indicate_cb(entry, rc);
+ return rc;
+}
+
+static void
+ble_gattc_err_indicate(struct ble_gattc_entry *entry, int status)
+{
+ ble_gattc_indicate_cb(entry, status);
+}
+
+void
+ble_gattc_rx_indicate_rsp(struct ble_hs_conn *conn)
+{
+ struct ble_gattc_entry *entry;
+ struct ble_gattc_entry *prev;
+
+ entry = ble_gattc_find(conn->bhc_handle, BLE_GATT_OP_INDICATE, 1, &prev);
+ if (entry == NULL) {
+ /* Not expecting a response from this device. */
+ return;
+ }
+
+ ble_gattc_indicate_cb(entry, 0);
+
+ /* The indicate operation only has a single request / response exchange. */
+ ble_gattc_entry_remove_free(entry, prev);
+}
+
+int
+ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
+ 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_INDICATE, &entry);
+ if (rc != 0) {
+ return rc;
+ }
+
+ entry->indicate.attr.handle = chr_val_handle;
+ entry->indicate.cb = cb;
+ entry->indicate.cb_arg = cb_arg;
+
+ return 0;
+}
+
+/*****************************************************************************
* @misc *
*****************************************************************************/
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8764e91d/net/nimble/host/src/ble_gatts.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatts.c b/net/nimble/host/src/ble_gatts.c
index 505ca67..1c06d4f 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -293,21 +293,35 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
return flags;
}
-static struct ble_gatts_clt_cfg *
-ble_gatts_clt_cfg_find(struct ble_gatts_conn *gatts_conn,
- uint16_t chr_def_handle)
+static int
+ble_gatts_clt_cfg_find_idx(struct ble_gatts_clt_cfg *cfgs,
+ uint16_t chr_def_handle)
{
struct ble_gatts_clt_cfg *cfg;
int i;
- for (i = 0; i < gatts_conn->num_clt_cfgs; i++) {
- cfg = gatts_conn->clt_cfgs + i;
+ for (i = 0; i < ble_gatts_num_cfgable_chrs; i++) {
+ cfg = cfgs + i;
if (cfg->chr_def_handle == chr_def_handle) {
- return cfg;
+ return i;
}
}
- return NULL;
+ return -1;
+}
+
+static struct ble_gatts_clt_cfg *
+ble_gatts_clt_cfg_find(struct ble_gatts_clt_cfg *cfgs,
+ uint16_t chr_def_handle)
+{
+ int idx;
+
+ idx = ble_gatts_clt_cfg_find_idx(cfgs, chr_def_handle);
+ if (idx == -1) {
+ return NULL;
+ } else {
+ return cfgs + idx;
+ }
}
static int
@@ -338,7 +352,8 @@ ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
return BLE_ATT_ERR_UNLIKELY;
}
- clt_cfg = ble_gatts_clt_cfg_find(&conn->bhc_gatt_svr, attr_handle - 2);
+ clt_cfg = ble_gatts_clt_cfg_find(conn->bhc_gatt_svr.clt_cfgs,
+ attr_handle - 2);
if (clt_cfg == 0) {
assert(0); // XXX temporary.
return BLE_ATT_ERR_UNLIKELY;
@@ -827,6 +842,38 @@ ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn)
return 0;
}
+void
+ble_gatts_chr_updated(uint16_t chr_def_handle)
+{
+ struct ble_gatts_clt_cfg *clt_cfg;
+ struct ble_hs_conn *conn;
+ int idx;
+
+ /* Determine if notifications / indications are enabled for this
+ * characteristic, and remember the client config offset.
+ */
+ idx = ble_gatts_clt_cfg_find_idx(ble_gatts_clt_cfgs, chr_def_handle);
+ if (idx == -1) {
+ return;
+ }
+
+ /* XXX: Lock connection list. */
+ for (conn = ble_hs_conn_first();
+ conn != NULL;
+ conn = SLIST_NEXT(conn, bhc_next)) {
+
+ assert(conn->bhc_gatt_svr.num_clt_cfgs > idx);
+ clt_cfg = conn->bhc_gatt_svr.clt_cfgs + idx;
+ assert(clt_cfg->chr_def_handle == chr_def_handle);
+
+ if (clt_cfg->flags & BLE_GATT_CHR_F_INDICATE) {
+ /* XXX: Schedule indication. */
+ } else if (clt_cfg->flags & BLE_GATT_CHR_F_NOTIFY) {
+ /* XXX: Schedule notification. */
+ }
+ }
+}
+
static void
ble_gatts_free_mem(void)
{
[4/4] incubator-mynewt-larva git commit: Indication tests.
Posted by cc...@apache.org.
Indication tests.
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/6545cc0b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/6545cc0b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/6545cc0b
Branch: refs/heads/master
Commit: 6545cc0bbd1198447fde5db4104e02ba968cd9d6
Parents: b296dd4
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 5 15:13:22 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Jan 5 15:13:53 2016 -0800
----------------------------------------------------------------------
net/nimble/host/src/ble_att_cmd.c | 32 +++++++
net/nimble/host/src/ble_att_cmd.h | 11 ++-
net/nimble/host/src/ble_att_svr.c | 77 ++++++++++++----
net/nimble/host/src/test/ble_att_svr_test.c | 106 ++++++++++++++++++++++-
4 files changed, 202 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6545cc0b/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 918e452..4be12f3 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -738,3 +738,35 @@ ble_att_indicate_req_write(void *payload, int len,
return 0;
}
+
+int
+ble_att_indicate_rsp_parse(void *payload, int len)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_INDICATE_RSP_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ if (u8ptr[0] != BLE_ATT_OP_INDICATE_RSP) {
+ return BLE_HS_EINVAL;
+ }
+
+ return 0;
+}
+
+int
+ble_att_indicate_rsp_write(void *payload, int len)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_ATT_INDICATE_RSP_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = BLE_ATT_OP_INDICATE_RSP;
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6545cc0b/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 7028bbb..73c8ea2 100644
--- a/net/nimble/host/src/ble_att_cmd.h
+++ b/net/nimble/host/src/ble_att_cmd.h
@@ -248,11 +248,18 @@ struct ble_att_notify_req {
* | Attribute Handle | 2 |
* | Attribute Value | 0 to (ATT_MTU-3) |
*/
-#define BLE_ATT_INDICATE_REQ_BASE_SZ 3
+#define BLE_ATT_INDICATE_REQ_BASE_SZ 3
struct ble_att_indicate_req {
uint16_t baiq_handle;
};
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ */
+#define BLE_ATT_INDICATE_RSP_SZ 1
+
int ble_att_error_rsp_parse(void *payload, int len,
struct ble_att_error_rsp *rsp);
int ble_att_error_rsp_write(void *payload, int len,
@@ -325,5 +332,7 @@ int ble_att_indicate_req_parse(void *payload, int len,
struct ble_att_indicate_req *req);
int ble_att_indicate_req_write(void *payload, int len,
struct ble_att_indicate_req *req);
+int ble_att_indicate_rsp_parse(void *payload, int len);
+int ble_att_indicate_rsp_write(void *payload, int len);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6545cc0b/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 419191b..ef9a338 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -2085,7 +2085,7 @@ err:
}
/**
- * @return 0 on success; ATT error code on failure.
+ * @return 0 on success; nonzero on failure.
*/
static int
ble_att_svr_tx_exec_write_rsp(struct ble_hs_conn *conn,
@@ -2222,36 +2222,75 @@ ble_att_svr_rx_notify(struct ble_hs_conn *conn,
return 0;
}
+/**
+ * @return 0 on success; nonzero on failure.
+ */
+static int
+ble_att_svr_tx_indicate_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_HS_ENOMEM;
+ goto err;
+ }
+
+ dst = os_mbuf_extend(txom, BLE_ATT_INDICATE_RSP_SZ);
+ if (dst == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ rc = ble_att_indicate_rsp_write(dst, BLE_ATT_INDICATE_RSP_SZ);
+ 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_svr_rx_indicate(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf **rxom)
{
struct ble_att_indicate_req req;
- uint16_t err_handle;
uint16_t attr_len;
- uint8_t att_err;
void *attr_data;
+ int txrc;
int rc;
if (OS_MBUF_PKTLEN(*rxom) < BLE_ATT_INDICATE_REQ_BASE_SZ) {
- att_err = BLE_ATT_ERR_INVALID_PDU;
- err_handle = 0;
rc = BLE_HS_EBADDATA;
- goto err;
+ goto done;
}
*rxom = os_mbuf_pullup(*rxom, BLE_ATT_INDICATE_REQ_BASE_SZ);
if (*rxom == NULL) {
- att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- err_handle = 0;
rc = BLE_HS_ENOMEM;
- goto err;
+ goto done;
}
rc = ble_att_indicate_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
assert(rc == 0);
+ if (req.baiq_handle == 0) {
+ rc = BLE_HS_EBADDATA;
+ goto done;
+ }
+
os_mbuf_adj(*rxom, BLE_ATT_INDICATE_REQ_BASE_SZ);
attr_data = ble_att_svr_flat_buf;
@@ -2259,21 +2298,21 @@ ble_att_svr_rx_indicate(struct ble_hs_conn *conn,
os_mbuf_copydata(*rxom, 0, attr_len, attr_data);
if (ble_att_svr_notify_cb != NULL) {
- att_err = ble_att_svr_notify_cb(conn->bhc_handle, req.baiq_handle,
- attr_data, attr_len,
- ble_att_svr_notify_cb_arg);
- if (att_err != 0) {
- err_handle = req.baiq_handle;
+ rc = ble_att_svr_notify_cb(conn->bhc_handle, req.baiq_handle,
+ attr_data, attr_len,
+ ble_att_svr_notify_cb_arg);
+ if (rc != 0) {
rc = BLE_HS_EAPP;
- goto err;
+ goto done;
}
}
- return 0;
+done:
+ txrc = ble_att_svr_tx_indicate_rsp(conn, chan);
+ if (rc == 0) {
+ rc = txrc;
+ }
-err:
- ble_att_svr_tx_error_rsp(conn, chan, BLE_ATT_OP_INDICATE_REQ, err_handle,
- att_err);
return rc;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6545cc0b/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 3d0d8a9..e1578d0 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -752,6 +752,7 @@ ble_att_svr_test_misc_rx_notify(struct ble_hs_conn *conn,
}
}
+static int ble_att_svr_test_misc_notify_cb_arg;
static int
ble_att_svr_test_misc_notify_cb(uint16_t conn_handle, uint16_t attr_handle,
uint8_t *attr_val, uint16_t attr_len,
@@ -760,6 +761,7 @@ ble_att_svr_test_misc_notify_cb(uint16_t conn_handle, uint16_t attr_handle,
int *iarg;
iarg = arg;
+ TEST_ASSERT(iarg == &ble_att_svr_test_misc_notify_cb_arg);
ble_att_svr_test_n_conn_handle = conn_handle;
ble_att_svr_test_n_attr_handle = attr_handle;
@@ -776,10 +778,9 @@ ble_att_svr_test_misc_verify_notify(struct ble_hs_conn *conn,
uint16_t attr_handle,
void *attr_val, int attr_len, int good)
{
- int cbrc;
-
- cbrc = 0;
- ble_att_set_notify_cb(ble_att_svr_test_misc_notify_cb, &cbrc);
+ ble_att_svr_test_misc_notify_cb_arg = 0;
+ ble_att_set_notify_cb(ble_att_svr_test_misc_notify_cb,
+ &ble_att_svr_test_misc_notify_cb_arg);
ble_att_svr_test_n_conn_handle = 0xffff;
ble_att_svr_test_n_attr_handle = 0;
@@ -800,6 +801,79 @@ ble_att_svr_test_misc_verify_notify(struct ble_hs_conn *conn,
}
}
+static void
+ble_att_svr_test_misc_verify_tx_indicate_rsp(struct ble_l2cap_chan *chan)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ ble_hs_process_tx_data_queue();
+
+ om = os_mbuf_pullup(ble_hs_test_util_prev_tx, BLE_ATT_INDICATE_RSP_SZ);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = ble_att_indicate_rsp_parse(om->om_data, om->om_len);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_att_svr_test_misc_rx_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ struct ble_att_indicate_req req;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+
+ req.baiq_handle = attr_handle;
+ rc = ble_att_indicate_req_write(buf, sizeof buf, &req);
+ TEST_ASSERT_FATAL(rc == 0);
+ off = BLE_ATT_INDICATE_REQ_BASE_SZ;
+
+ memcpy(buf + off, attr_val, attr_len);
+ off += attr_len;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, off);
+ if (good) {
+ TEST_ASSERT(rc == 0);
+ } else {
+ TEST_ASSERT(rc == BLE_HS_EBADDATA);
+ }
+}
+
+static void
+ble_att_svr_test_misc_verify_indicate(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ ble_att_svr_test_misc_notify_cb_arg = 0;
+ ble_att_set_notify_cb(ble_att_svr_test_misc_notify_cb,
+ &ble_att_svr_test_misc_notify_cb_arg);
+
+ ble_att_svr_test_n_conn_handle = 0xffff;
+ ble_att_svr_test_n_attr_handle = 0;
+ ble_att_svr_test_attr_n_len = 0;
+
+ ble_att_svr_test_misc_rx_indicate(conn, chan, attr_handle, attr_val,
+ attr_len, good);
+
+ if (good) {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == conn->bhc_handle);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == attr_handle);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == attr_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_n, attr_val, attr_len) == 0);
+ } else {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == 0xffff);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == 0);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == 0);
+ }
+
+ ble_att_svr_test_misc_verify_tx_indicate_rsp(chan);
+}
+
TEST_CASE(ble_att_svr_test_mtu)
{
/*** MTU too low; should pretend peer sent default value instead. */
@@ -1767,6 +1841,29 @@ TEST_CASE(ble_att_svr_test_notify)
(uint8_t[]) { 1, 2, 3 }, 3, 0);
}
+TEST_CASE(ble_att_svr_test_indicate)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+
+ ble_att_svr_test_misc_init(&conn, &chan);
+
+ /*** Successful indicates; verify callback is executed. */
+ /* 3-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn, chan, 10,
+ (uint8_t[]) { 1, 2, 3 }, 3, 1);
+ /* 1-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn, chan, 1,
+ (uint8_t[]) { 0xff }, 1, 1);
+ /* 0-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn, chan, 43, NULL, 0, 1);
+
+ /*** Bad indicates; verify callback is not executed. */
+ /* Attribute handle of 0. */
+ ble_att_svr_test_misc_verify_indicate(conn, chan, 0,
+ (uint8_t[]) { 1, 2, 3 }, 3, 0);
+}
+
TEST_SUITE(ble_att_svr_suite)
{
ble_att_svr_test_mtu();
@@ -1778,6 +1875,7 @@ TEST_SUITE(ble_att_svr_suite)
ble_att_svr_test_read_group_type();
ble_att_svr_test_prep_write();
ble_att_svr_test_notify();
+ ble_att_svr_test_indicate();
}
int