summaryrefslogtreecommitdiff
path: root/net/nimble/host/src
diff options
context:
space:
mode:
Diffstat (limited to 'net/nimble/host/src')
-rw-r--r--net/nimble/host/src/ble_att.c109
-rw-r--r--net/nimble/host/src/ble_att_clt.c846
-rw-r--r--net/nimble/host/src/ble_att_cmd.c236
-rw-r--r--net/nimble/host/src/ble_att_cmd_priv.h127
-rw-r--r--net/nimble/host/src/ble_att_priv.h97
-rw-r--r--net/nimble/host/src/ble_att_svr.c899
-rw-r--r--net/nimble/host/src/ble_eddystone.c15
-rw-r--r--net/nimble/host/src/ble_gap.c2102
-rw-r--r--net/nimble/host/src/ble_gap_priv.h25
-rw-r--r--net/nimble/host/src/ble_gatt_priv.h24
-rw-r--r--net/nimble/host/src/ble_gattc.c1131
-rw-r--r--net/nimble/host/src/ble_gatts.c1077
-rw-r--r--net/nimble/host/src/ble_hci_cmd.c298
-rw-r--r--net/nimble/host/src/ble_hs.c369
-rw-r--r--net/nimble/host/src/ble_hs_adv.c134
-rw-r--r--net/nimble/host/src/ble_hs_adv_priv.h19
-rw-r--r--net/nimble/host/src/ble_hs_atomic.c20
-rw-r--r--net/nimble/host/src/ble_hs_atomic_priv.h1
-rw-r--r--net/nimble/host/src/ble_hs_cfg.c34
-rw-r--r--net/nimble/host/src/ble_hs_conn.c64
-rw-r--r--net/nimble/host/src/ble_hs_conn_priv.h22
-rw-r--r--net/nimble/host/src/ble_hs_dbg.c (renamed from net/nimble/host/src/host_dbg.c)50
-rw-r--r--net/nimble/host/src/ble_hs_dbg_priv.h (renamed from net/nimble/host/src/host_dbg_priv.h)7
-rw-r--r--net/nimble/host/src/ble_hs_hci.c518
-rw-r--r--net/nimble/host/src/ble_hs_hci_cmd.c (renamed from net/nimble/host/src/host_hci_cmd.c)515
-rw-r--r--net/nimble/host/src/ble_hs_hci_evt.c (renamed from net/nimble/host/src/host_hci.c)502
-rw-r--r--net/nimble/host/src/ble_hs_hci_priv.h158
-rw-r--r--net/nimble/host/src/ble_hs_hci_util.c (renamed from net/nimble/host/src/ble_hci_util.c)75
-rw-r--r--net/nimble/host/src/ble_hs_id.c248
-rw-r--r--net/nimble/host/src/ble_hs_id_priv.h (renamed from net/nimble/host/src/ble_hci_util_priv.h)16
-rw-r--r--net/nimble/host/src/ble_hs_log.c47
-rw-r--r--net/nimble/host/src/ble_hs_mbuf.c198
-rw-r--r--net/nimble/host/src/ble_hs_mbuf_priv.h11
-rw-r--r--net/nimble/host/src/ble_hs_misc.c73
-rw-r--r--net/nimble/host/src/ble_hs_priv.h84
-rw-r--r--net/nimble/host/src/ble_hs_pvcy.c146
-rw-r--r--net/nimble/host/src/ble_hs_pvcy_priv.h31
-rw-r--r--net/nimble/host/src/ble_hs_startup.c66
-rw-r--r--net/nimble/host/src/ble_ibeacon.c16
-rw-r--r--net/nimble/host/src/ble_l2cap.c25
-rw-r--r--net/nimble/host/src/ble_l2cap_priv.h7
-rw-r--r--net/nimble/host/src/ble_l2cap_sig.c59
-rw-r--r--net/nimble/host/src/ble_l2cap_sig_cmd.c22
-rw-r--r--net/nimble/host/src/ble_l2cap_sig_priv.h2
-rw-r--r--net/nimble/host/src/ble_sm.c162
-rw-r--r--net/nimble/host/src/ble_sm_alg.c78
-rw-r--r--net/nimble/host/src/ble_sm_cmd.c162
-rw-r--r--net/nimble/host/src/ble_sm_lgcy.c7
-rw-r--r--net/nimble/host/src/ble_sm_priv.h28
-rw-r--r--net/nimble/host/src/ble_sm_sc.c91
-rw-r--r--net/nimble/host/src/ble_uuid.c29
-rw-r--r--net/nimble/host/src/ble_uuid_priv.h28
-rw-r--r--net/nimble/host/src/test/ble_att_clt_test.c58
-rw-r--r--net/nimble/host/src/test/ble_att_svr_test.c460
-rw-r--r--net/nimble/host/src/test/ble_gap_test.c1327
-rw-r--r--net/nimble/host/src/test/ble_gatt_conn_test.c126
-rw-r--r--net/nimble/host/src/test/ble_gatt_disc_c_test.c22
-rw-r--r--net/nimble/host/src/test/ble_gatt_disc_d_test.c93
-rw-r--r--net/nimble/host/src/test/ble_gatt_disc_s_test.c24
-rw-r--r--net/nimble/host/src/test/ble_gatt_find_s_test.c22
-rw-r--r--net/nimble/host/src/test/ble_gatt_read_test.c248
-rw-r--r--net/nimble/host/src/test/ble_gatt_write_test.c163
-rw-r--r--net/nimble/host/src/test/ble_gatts_notify_test.c589
-rw-r--r--net/nimble/host/src/test/ble_gatts_read_test.c261
-rw-r--r--net/nimble/host/src/test/ble_gatts_reg_test.c292
-rw-r--r--net/nimble/host/src/test/ble_hs_adv_test.c468
-rw-r--r--net/nimble/host/src/test/ble_hs_conn_test.c92
-rw-r--r--net/nimble/host/src/test/ble_hs_hci_test.c (renamed from net/nimble/host/src/test/ble_host_hci_test.c)35
-rw-r--r--net/nimble/host/src/test/ble_hs_test.c21
-rw-r--r--net/nimble/host/src/test/ble_hs_test_util.c844
-rw-r--r--net/nimble/host/src/test/ble_hs_test_util.h103
-rw-r--r--net/nimble/host/src/test/ble_l2cap_test.c17
-rw-r--r--net/nimble/host/src/test/ble_os_test.c92
-rw-r--r--net/nimble/host/src/test/ble_sm_lgcy_test.c3
-rw-r--r--net/nimble/host/src/test/ble_sm_sc_test.c3
-rw-r--r--net/nimble/host/src/test/ble_sm_test.c3
-rw-r--r--net/nimble/host/src/test/ble_sm_test_util.c158
-rw-r--r--net/nimble/host/src/test/ble_sm_test_util.h3
-rw-r--r--net/nimble/host/src/test/ble_uuid_test.c5
79 files changed, 10826 insertions, 5816 deletions
diff --git a/net/nimble/host/src/ble_att.c b/net/nimble/host/src/ble_att.c
index 68e1c7b2..a6d39b82 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -22,9 +22,7 @@
#include "bsp/bsp.h"
#include "ble_hs_priv.h"
-static bssnz_t uint8_t ble_att_flat_buf[BLE_ATT_ATTR_MAX_LEN];
-
-static uint16_t ble_att_preferred_mtu;
+static uint16_t ble_att_preferred_mtu_val;
/** Dispatch table for incoming ATT requests. Sorted by op code. */
typedef int ble_att_rx_fn(uint16_t conn_handle, struct os_mbuf **om);
@@ -145,15 +143,12 @@ ble_att_rx_dispatch_entry_find(uint8_t op)
return NULL;
}
-int
+void
ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan)
{
- int rc;
-
- rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT,
- out_conn, out_chan);
- return rc;
+ ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
+ out_conn, out_chan);
}
void
@@ -390,17 +385,29 @@ ble_att_inc_rx_stat(uint8_t att_op)
}
}
-/**
- * Retrieves a pointer to the global ATT flat buffer. This buffer is only used
- * by the host parent task, so users can assume exclusive access.
- */
-uint8_t *
-ble_att_get_flat_buf(void)
+void
+ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan,
+ struct os_mbuf *txom)
{
- BLE_HS_DBG_ASSERT(ble_hs_is_parent_task());
- return ble_att_flat_buf;
+ int32_t extra_len;
+ uint16_t mtu;
+
+ mtu = ble_l2cap_chan_mtu(att_chan);
+ extra_len = OS_MBUF_PKTLEN(txom) - mtu;
+ if (extra_len > 0) {
+ os_mbuf_adj(txom, -extra_len);
+ }
}
+/**
+ * Retrieves the ATT MTU of the specified connection. If an MTU exchange for
+ * this connection has occurred, the MTU is the lower of the two peers'
+ * preferred values. Otherwise, the MTU is the default value of 23.
+ *
+ * @param conn_handle The handle of the connection to query.
+ *
+ * @return The specified connection's ATT MTU.
+ */
uint16_t
ble_att_mtu(uint16_t conn_handle)
{
@@ -422,6 +429,16 @@ ble_att_mtu(uint16_t conn_handle)
return mtu;
}
+void
+ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu)
+{
+ if (peer_mtu < BLE_ATT_MTU_DFLT) {
+ peer_mtu = BLE_ATT_MTU_DFLT;
+ }
+
+ chan->blc_peer_mtu = peer_mtu;
+}
+
static int
ble_att_rx(uint16_t conn_handle, struct os_mbuf **om)
{
@@ -449,19 +466,40 @@ ble_att_rx(uint16_t conn_handle, struct os_mbuf **om)
return 0;
}
-void
-ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu)
+/**
+ * Retrieves the preferred ATT MTU.
+ *
+ * @return The preferred ATT MTU.
+ */
+uint16_t
+ble_att_preferred_mtu(void)
{
- if (peer_mtu < BLE_ATT_MTU_DFLT) {
- peer_mtu = BLE_ATT_MTU_DFLT;
- }
-
- chan->blc_peer_mtu = peer_mtu;
+ return ble_att_preferred_mtu_val;
}
+/**
+ * Sets the preferred ATT MTU; the device will indicate this value in all
+ * subseqeunt ATT MTU exchanges. The ATT MTU of a connection is equal to the
+ * lower of the two peers' preferred MTU values. The ATT MTU is what dictates
+ * the maximum size of any message sent during a GATT procedure.
+ *
+ * The specified MTU must be within the following range: [23, BLE_ATT_MTU_MAX].
+ * 23 is a minimum imposed by the Bluetooth specification; BLE_ATT_MTU_MAX is a
+ * NimBLE compile-time setting.
+ *
+ * @param mtu The preferred ATT MTU.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if the specifeid value is not
+ * within the allowed range.
+ */
int
ble_att_set_preferred_mtu(uint16_t mtu)
{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ int i;
+
if (mtu < BLE_ATT_MTU_DFLT) {
return BLE_HS_EINVAL;
}
@@ -469,9 +507,24 @@ ble_att_set_preferred_mtu(uint16_t mtu)
return BLE_HS_EINVAL;
}
- ble_att_preferred_mtu = mtu;
+ ble_att_preferred_mtu_val = mtu;
+
+ /* Set my_mtu for established connections that haven't exchanged. */
+ ble_hs_lock();
- /* XXX: Set my_mtu for established connections that haven't exchanged. */
+ i = 0;
+ while ((conn = ble_hs_conn_find_by_idx(i)) != NULL) {
+ chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+ BLE_HS_DBG_ASSERT(chan != NULL);
+
+ if (!(chan->blc_flags & BLE_L2CAP_CHAN_F_TXED_MTU)) {
+ chan->blc_my_mtu = mtu;
+ }
+
+ i++;
+ }
+
+ ble_hs_unlock();
return 0;
}
@@ -487,7 +540,7 @@ ble_att_create_chan(void)
}
chan->blc_cid = BLE_L2CAP_CID_ATT;
- chan->blc_my_mtu = ble_att_preferred_mtu;
+ chan->blc_my_mtu = ble_att_preferred_mtu_val;
chan->blc_default_mtu = BLE_ATT_MTU_DFLT;
chan->blc_rx_fn = ble_att_rx;
@@ -499,7 +552,7 @@ ble_att_init(void)
{
int rc;
- ble_att_preferred_mtu = BLE_ATT_MTU_PREFERRED_DFLT;
+ ble_att_preferred_mtu_val = BLE_ATT_MTU_PREFERRED_DFLT;
rc = stats_init_and_reg(
STATS_HDR(ble_att_stats), STATS_SIZE_INIT_PARMS(ble_att_stats,
diff --git a/net/nimble/host/src/ble_att_clt.c b/net/nimble/host/src/ble_att_clt.c
index dba3527b..2e7352ba 100644
--- a/net/nimble/host/src/ble_att_clt.c
+++ b/net/nimble/host/src/ble_att_clt.c
@@ -29,84 +29,40 @@
static int
ble_att_clt_init_req(uint16_t initial_sz, struct os_mbuf **out_txom)
{
+ struct os_mbuf *om;
void *buf;
int rc;
- *out_txom = ble_hs_misc_pkthdr();
- if (*out_txom == NULL) {
+ *out_txom = NULL;
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ if (om == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
}
- buf = os_mbuf_extend(*out_txom, initial_sz);
+ buf = os_mbuf_extend(om, initial_sz);
if (buf == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
}
/* The caller expects the initial buffer to be at the start of the mbuf. */
- BLE_HS_DBG_ASSERT(buf == (*out_txom)->om_data);
+ BLE_HS_DBG_ASSERT(buf == om->om_data);
+ *out_txom = om;
return 0;
err:
- os_mbuf_free_chain(*out_txom);
- *out_txom = NULL;
+ os_mbuf_free_chain(om);
return rc;
}
static int
-ble_att_clt_append_blob(uint16_t conn_handle, struct os_mbuf *txom,
- void *blob, int blob_len)
-{
- int rc;
-
- if (blob_len < 0) {
- return BLE_HS_EINVAL;
- }
- if (blob_len == 0) {
- return 0;
- }
-
- rc = os_mbuf_append(txom, blob, blob_len);
- if (rc != 0) {
- return rc;
- }
-
- return 0;
-}
-
-static int
-ble_att_clt_copy_attr_to_flatbuf(struct os_mbuf *om, void **out_attr_val,
- uint16_t *out_attr_len)
-{
- uint8_t *flat_buf;
- uint16_t attr_len;
-
- /* Make sure the attribute value isn't too big. */
- attr_len = OS_MBUF_PKTLEN(om);
- if (attr_len > BLE_ATT_ATTR_MAX_LEN) {
- *out_attr_len = 0;
- *out_attr_val = NULL;
- return BLE_HS_EBADDATA;
- }
-
- /* Copy the attribute data into the global ATT flat buffer. */
- flat_buf = ble_att_get_flat_buf();
- os_mbuf_copydata(om, 0, attr_len, flat_buf);
- *out_attr_val = flat_buf;
- *out_attr_len = attr_len;
- return 0;
-}
-
-static int
ble_att_clt_tx_req(uint16_t conn_handle, struct os_mbuf *txom)
{
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
- uint16_t total_len;
- uint16_t mtu;
- int extra_len;
int rc;
BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1);
@@ -114,25 +70,16 @@ ble_att_clt_tx_req(uint16_t conn_handle, struct os_mbuf *txom)
ble_hs_lock();
- rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
- if (rc == 0) {
- /* Reduce the size of the transmission to fit the connection's ATT
- * MTU.
- */
- total_len = OS_MBUF_PKTLEN(txom);
- mtu = ble_l2cap_chan_mtu(chan);
- extra_len = total_len - mtu;
- if (extra_len > 0) {
- os_mbuf_adj(txom, -extra_len);
- }
-
- rc = ble_l2cap_tx(conn, chan, txom);
- txom = NULL;
- }
+ ble_att_conn_chan_find(conn_handle, &conn, &chan);
+ ble_att_truncate_to_mtu(chan, txom);
+ rc = ble_l2cap_tx(conn, chan, txom);
ble_hs_unlock();
- os_mbuf_free_chain(txom);
+ if (rc != 0) {
+ os_mbuf_free_chain(txom);
+ }
+
return rc;
}
@@ -141,17 +88,17 @@ ble_att_clt_tx_req(uint16_t conn_handle, struct os_mbuf *txom)
*****************************************************************************/
int
-ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **om)
+ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom)
{
struct ble_att_error_rsp rsp;
int rc;
- rc = ble_hs_misc_pullup_base(om, BLE_ATT_ERROR_RSP_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_ERROR_RSP_SZ);
if (rc != 0) {
return rc;
}
- ble_att_error_rsp_parse((*om)->om_data, (*om)->om_len, &rsp);
+ ble_att_error_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &rsp);
BLE_ATT_LOG_CMD(0, "error rsp", conn_handle, ble_att_error_rsp_log, &rsp);
ble_gattc_rx_err(conn_handle, &rsp);
@@ -163,62 +110,51 @@ ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **om)
* $mtu exchange *
*****************************************************************************/
-static int
-ble_att_clt_build_mtu_req(struct ble_att_mtu_cmd *req,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_MTU_CMD_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_mtu_req_write(txom->om_data, txom->om_len, req);
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
-ble_att_clt_tx_mtu(uint16_t conn_handle, struct ble_att_mtu_cmd *req)
+ble_att_clt_tx_mtu(uint16_t conn_handle, const struct ble_att_mtu_cmd *req)
{
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "mtu req", conn_handle, ble_att_mtu_cmd_log, req);
-
if (req->bamc_mtu < BLE_ATT_MTU_DFLT) {
return BLE_HS_EINVAL;
}
- rc = ble_att_clt_build_mtu_req(req, &txom);
+ ble_hs_lock();
+
+ ble_att_conn_chan_find(conn_handle, &conn, &chan);
+ if (chan == NULL) {
+ rc = BLE_HS_ENOTCONN;
+ } else if (chan->blc_flags & BLE_L2CAP_CHAN_F_TXED_MTU) {
+ rc = BLE_HS_EALREADY;
+ } else {
+ rc = 0;
+ }
+ ble_hs_unlock();
+
if (rc != 0) {
return rc;
}
+ rc = ble_att_clt_init_req(BLE_ATT_MTU_CMD_SZ, &txom);
+ if (rc != 0) {
+ return rc;
+ }
+ ble_att_mtu_req_write(txom->om_data, txom->om_len, req);
+
rc = ble_att_clt_tx_req(conn_handle, txom);
if (rc != 0) {
return rc;
}
+ BLE_ATT_LOG_CMD(1, "mtu req", conn_handle, ble_att_mtu_cmd_log, req);
+
ble_hs_lock();
- rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
- if (rc == 0) {
- chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
- }
+ ble_att_conn_chan_find(conn_handle, &conn, &chan);
+ chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
ble_hs_unlock();
@@ -226,7 +162,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, struct ble_att_mtu_cmd *req)
}
int
-ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **om)
+ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
{
struct ble_att_mtu_cmd cmd;
struct ble_l2cap_chan *chan;
@@ -235,20 +171,20 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **om)
mtu = 0;
- rc = ble_hs_misc_pullup_base(om, BLE_ATT_MTU_CMD_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_MTU_CMD_SZ);
if (rc == 0) {
- ble_att_mtu_cmd_parse((*om)->om_data, (*om)->om_len, &cmd);
+ ble_att_mtu_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
BLE_ATT_LOG_CMD(0, "mtu rsp", conn_handle, ble_att_mtu_cmd_log, &cmd);
ble_hs_lock();
- rc = ble_att_conn_chan_find(conn_handle, NULL, &chan);
- if (rc == 0) {
- ble_att_set_peer_mtu(chan, cmd.bamc_mtu);
- mtu = ble_l2cap_chan_mtu(chan);
- }
+ ble_att_conn_chan_find(conn_handle, NULL, &chan);
+ ble_att_set_peer_mtu(chan, cmd.bamc_mtu);
+ mtu = ble_l2cap_chan_mtu(chan);
ble_hs_unlock();
+
+ ble_gap_mtu_event(conn_handle, BLE_L2CAP_CID_ATT, mtu);
}
ble_gattc_rx_mtu(conn_handle, rc, mtu);
@@ -259,27 +195,9 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **om)
* $find information *
*****************************************************************************/
-static int
-ble_att_clt_build_find_info_req(struct ble_att_find_info_req *req,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- rc = ble_att_clt_init_req(BLE_ATT_FIND_INFO_REQ_SZ, &txom);
- if (rc != 0) {
- return rc;
- }
-
- ble_att_find_info_req_write(txom->om_data, txom->om_len, req);
- *out_txom = txom;
-
- return 0;
-}
-
int
ble_att_clt_tx_find_info(uint16_t conn_handle,
- struct ble_att_find_info_req *req)
+ const struct ble_att_find_info_req *req)
{
#if !NIMBLE_OPT(ATT_CLT_FIND_INFO)
return BLE_HS_ENOTSUP;
@@ -288,25 +206,26 @@ ble_att_clt_tx_find_info(uint16_t conn_handle,
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "find info req", conn_handle,
- ble_att_find_info_req_log, req);
-
if (req->bafq_start_handle == 0 ||
req->bafq_start_handle > req->bafq_end_handle) {
return BLE_HS_EINVAL;
}
- rc = ble_att_clt_build_find_info_req(req, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_FIND_INFO_REQ_SZ, &txom);
if (rc != 0) {
return rc;
}
+ ble_att_find_info_req_write(txom->om_data, txom->om_len, req);
rc = ble_att_clt_tx_req(conn_handle, txom);
if (rc != 0) {
return rc;
}
+ BLE_ATT_LOG_CMD(1, "find info req", conn_handle,
+ ble_att_find_info_req_log, req);
+
return 0;
}
@@ -331,7 +250,7 @@ ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format,
return BLE_HS_EBADDATA;
}
- rc = ble_hs_misc_pullup_base(rxom, entry_len);
+ rc = ble_hs_mbuf_pullup_base(rxom, entry_len);
if (rc != 0) {
return rc;
}
@@ -374,7 +293,7 @@ ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om)
struct ble_att_find_info_rsp rsp;
int rc;
- rc = ble_hs_misc_pullup_base(om, BLE_ATT_FIND_INFO_RSP_BASE_SZ);
+ rc = ble_hs_mbuf_pullup_base(om, BLE_ATT_FIND_INFO_RSP_BASE_SZ);
if (rc != 0) {
goto done;
}
@@ -408,63 +327,53 @@ done:
* $find by type value *
*****************************************************************************/
-static int
-ble_att_clt_build_find_type_value_req(struct ble_att_find_type_value_req *req,
- void *attribute_value, int value_len,
- struct os_mbuf **out_txom)
-{
- int rc;
-
- rc = ble_att_clt_init_req(BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ, out_txom);
- if (rc != 0) {
- return rc;
- }
-
- ble_att_find_type_value_req_write((*out_txom)->om_data,
- (*out_txom)->om_len,
- req);
- rc = os_mbuf_append(*out_txom, attribute_value, value_len);
- if (rc != 0) {
- os_mbuf_free_chain(*out_txom);
- return BLE_HS_ENOMEM;
- }
-
- return 0;
-}
-
int
ble_att_clt_tx_find_type_value(uint16_t conn_handle,
- struct ble_att_find_type_value_req *req,
- void *attribute_value, int value_len)
+ const struct ble_att_find_type_value_req *req,
+ const void *attribute_value, int value_len)
{
#if !NIMBLE_OPT(ATT_CLT_FIND_TYPE)
return BLE_HS_ENOTSUP;
#endif
- BLE_ATT_LOG_CMD(1, "find type value req", conn_handle,
- ble_att_find_type_value_req_log, req);
-
struct os_mbuf *txom;
int rc;
+ txom = NULL;
+
if (req->bavq_start_handle == 0 ||
req->bavq_start_handle > req->bavq_end_handle) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_find_type_value_req(req, attribute_value, value_len,
- &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ, &txom);
if (rc != 0) {
- return rc;
+ goto err;
+ }
+
+ ble_att_find_type_value_req_write(txom->om_data, txom->om_len, req);
+ rc = os_mbuf_append(txom, attribute_value, value_len);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "find type value req", conn_handle,
+ ble_att_find_type_value_req_log, req);
+
return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
}
static int
@@ -524,42 +433,10 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom)
* $read by type *
*****************************************************************************/
-static int
-ble_att_clt_build_read_type_req(struct ble_att_read_type_req *req,
- void *uuid128, struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_READ_TYPE_REQ_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_read_type_req_write(txom->om_data, txom->om_len, req);
-
- rc = ble_uuid_append(txom, uuid128);
- if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_read_type(uint16_t conn_handle,
- struct ble_att_read_type_req *req,
- void *uuid128)
+ const struct ble_att_read_type_req *req,
+ const void *uuid128)
{
#if !NIMBLE_OPT(ATT_CLT_READ_TYPE)
return BLE_HS_ENOTSUP;
@@ -568,25 +445,40 @@ ble_att_clt_tx_read_type(uint16_t conn_handle,
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "read type req", conn_handle,
- ble_att_read_type_req_log, req);
+ txom = NULL;
if (req->batq_start_handle == 0 ||
req->batq_start_handle > req->batq_end_handle) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_read_type_req(req, uuid128, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_READ_TYPE_REQ_BASE_SZ, &txom);
if (rc != 0) {
- return rc;
+ goto err;
+ }
+
+ ble_att_read_type_req_write(txom->om_data, txom->om_len, req);
+ rc = ble_uuid_append(txom, uuid128);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "read type req", conn_handle,
+ ble_att_read_type_req_log, req);
+
+ return 0;
+
+err:
+ os_mbuf_free_chain(txom);
return 0;
}
@@ -596,7 +488,7 @@ ble_att_clt_parse_read_type_adata(struct os_mbuf **om, int data_len,
{
int rc;
- rc = ble_hs_misc_pullup_base(om, data_len);
+ rc = ble_hs_mbuf_pullup_base(om, data_len);
if (rc != 0) {
return rc;
}
@@ -619,7 +511,7 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom)
struct ble_att_read_type_rsp rsp;
int rc;
- rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_READ_TYPE_RSP_BASE_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_READ_TYPE_RSP_BASE_SZ);
if (rc != 0) {
goto done;
}
@@ -653,34 +545,8 @@ done:
* $read *
*****************************************************************************/
-static int
-ble_att_clt_build_read_req(struct ble_att_read_req *req,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_READ_REQ_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_read_req_write(txom->om_data, txom->om_len, req);
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
-ble_att_clt_tx_read(uint16_t conn_handle, struct ble_att_read_req *req)
+ble_att_clt_tx_read(uint16_t conn_handle, const struct ble_att_read_req *req)
{
#if !NIMBLE_OPT(ATT_CLT_READ)
return BLE_HS_ENOTSUP;
@@ -689,23 +555,23 @@ ble_att_clt_tx_read(uint16_t conn_handle, struct ble_att_read_req *req)
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "read req", conn_handle,
- ble_att_read_req_log, req);
-
if (req->barq_handle == 0) {
return BLE_HS_EINVAL;
}
- rc = ble_att_clt_build_read_req(req, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_READ_REQ_SZ, &txom);
if (rc != 0) {
return rc;
}
+ ble_att_read_req_write(txom->om_data, txom->om_len, req);
rc = ble_att_clt_tx_req(conn_handle, txom);
if (rc != 0) {
return rc;
}
+ BLE_ATT_LOG_CMD(1, "read req", conn_handle, ble_att_read_req_log, req);
+
return 0;
}
@@ -716,10 +582,6 @@ ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- uint16_t value_len;
- void *value;
- int rc;
-
BLE_ATT_LOG_EMPTY_CMD(0, "read rsp", conn_handle);
/* Reponse consists of a one-byte opcode (already verified) and a variable
@@ -727,47 +589,18 @@ ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
*/
os_mbuf_adj(*rxom, BLE_ATT_READ_RSP_BASE_SZ);
- /* Copy the attribute data into the global ATT flat buffer. */
- rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len);
-
/* Pass the Attribute Value field to GATT. */
- ble_gattc_rx_read_rsp(conn_handle, rc, value, value_len);
- return rc;
+ ble_gattc_rx_read_rsp(conn_handle, 0, rxom);
+ return 0;
}
/*****************************************************************************
* $read blob *
*****************************************************************************/
-static int
-ble_att_clt_build_read_blob_req(struct ble_att_read_blob_req *req,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_READ_BLOB_REQ_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_read_blob_req_write(txom->om_data, txom->om_len, req);
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_read_blob(uint16_t conn_handle,
- struct ble_att_read_blob_req *req)
+ const struct ble_att_read_blob_req *req)
{
#if !NIMBLE_OPT(ATT_CLT_READ_BLOB)
return BLE_HS_ENOTSUP;
@@ -776,23 +609,24 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle,
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "read blob req", conn_handle,
- ble_att_read_blob_req_log, req);
-
if (req->babq_handle == 0) {
return BLE_HS_EINVAL;
}
- rc = ble_att_clt_build_read_blob_req(req, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_READ_BLOB_REQ_SZ, &txom);
if (rc != 0) {
return rc;
}
+ ble_att_read_blob_req_write(txom->om_data, txom->om_len, req);
rc = ble_att_clt_tx_req(conn_handle, txom);
if (rc != 0) {
return rc;
}
+ BLE_ATT_LOG_CMD(1, "read blob req", conn_handle,
+ ble_att_read_blob_req_log, req);
+
return 0;
}
@@ -803,10 +637,6 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- uint16_t value_len;
- void *value;
- int rc;
-
BLE_ATT_LOG_EMPTY_CMD(0, "read blob rsp", conn_handle);
/* Reponse consists of a one-byte opcode (already verified) and a variable
@@ -814,12 +644,9 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
*/
os_mbuf_adj(*rxom, BLE_ATT_READ_BLOB_RSP_BASE_SZ);
- /* Copy the attribute data into the global ATT flat buffer. */
- rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len);
-
/* Pass the Attribute Value field to GATT. */
- ble_gattc_rx_read_blob_rsp(conn_handle, rc, value, value_len);
- return rc;
+ ble_gattc_rx_read_blob_rsp(conn_handle, 0, rxom);
+ return 0;
}
/*****************************************************************************
@@ -827,7 +654,8 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
*****************************************************************************/
static int
-ble_att_clt_build_read_mult_req(uint16_t *att_handles, int num_att_handles,
+ble_att_clt_build_read_mult_req(const uint16_t *att_handles,
+ int num_att_handles,
struct os_mbuf **out_txom)
{
struct os_mbuf *txom;
@@ -835,39 +663,34 @@ ble_att_clt_build_read_mult_req(uint16_t *att_handles, int num_att_handles,
int rc;
int i;
- txom = NULL;
+ *out_txom = NULL;
rc = ble_att_clt_init_req(BLE_ATT_READ_MULT_REQ_BASE_SZ, &txom);
if (rc != 0) {
- goto done;
+ goto err;
}
-
ble_att_read_mult_req_write(txom->om_data, txom->om_len);
for (i = 0; i < num_att_handles; i++) {
buf = os_mbuf_extend(txom, 2);
if (buf == NULL) {
rc = BLE_HS_ENOMEM;
- goto done;
+ goto err;
}
htole16(buf, att_handles[i]);
}
- rc = 0;
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
*out_txom = txom;
+ return 0;
+
+err:
+ os_mbuf_free_chain(txom);
return rc;
}
int
-ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t *att_handles,
+ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *att_handles,
int num_att_handles)
{
#if !NIMBLE_OPT(ATT_CLT_READ_MULT)
@@ -903,10 +726,6 @@ ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- uint16_t value_len;
- void *value;
- int rc;
-
BLE_ATT_LOG_EMPTY_CMD(0, "read mult rsp", conn_handle);
/* Reponse consists of a one-byte opcode (already verified) and a variable
@@ -914,53 +733,19 @@ ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom)
*/
os_mbuf_adj(*rxom, BLE_ATT_READ_MULT_RSP_BASE_SZ);
- /* Copy the attribute data into the global ATT flat buffer. */
- rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len);
-
/* Pass the Attribute Value field to GATT. */
- ble_gattc_rx_read_mult_rsp(conn_handle, rc, value, value_len);
- return rc;
+ ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom);
+ return 0;
}
/*****************************************************************************
* $read by group type *
*****************************************************************************/
-static int
-ble_att_clt_build_read_group_type_req(struct ble_att_read_group_type_req *req,
- void *uuid128, struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_read_group_type_req_write(txom->om_data, txom->om_len, req);
-
- rc = ble_uuid_append(txom, uuid128);
- if (rc != 0) {
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_read_group_type(uint16_t conn_handle,
- struct ble_att_read_group_type_req *req,
- void *uuid128)
+ const struct ble_att_read_group_type_req *req,
+ const void *uuid128)
{
#if !NIMBLE_OPT(ATT_CLT_READ_GROUP_TYPE)
return BLE_HS_ENOTSUP;
@@ -971,26 +756,38 @@ ble_att_clt_tx_read_group_type(uint16_t conn_handle,
txom = NULL;
- BLE_ATT_LOG_CMD(1, "read group type req", conn_handle,
- ble_att_read_group_type_req_log, req);
-
if (req->bagq_start_handle == 0 ||
req->bagq_start_handle > req->bagq_end_handle) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_read_group_type_req(req, uuid128, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ, &txom);
if (rc != 0) {
- return rc;
+ goto err;
+ }
+ ble_att_read_group_type_req_write(txom->om_data, txom->om_len, req);
+
+ rc = ble_uuid_append(txom, uuid128);
+ if (rc != 0) {
+ goto err;
}
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "read group type req", conn_handle,
+ ble_att_read_group_type_req_log, req);
+
return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
}
static int
@@ -1004,7 +801,7 @@ ble_att_clt_parse_read_group_type_adata(
return BLE_HS_EMSGSIZE;
}
- rc = ble_hs_misc_pullup_base(om, data_len);
+ rc = ble_hs_mbuf_pullup_base(om, data_len);
if (rc != 0) {
return rc;
}
@@ -1028,7 +825,7 @@ ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom)
struct ble_att_read_group_type_rsp rsp;
int rc;
- rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
if (rc != 0) {
goto done;
}
@@ -1063,55 +860,21 @@ done:
*****************************************************************************/
static int
-ble_att_clt_build_write_req_or_cmd(uint16_t conn_handle,
- struct ble_att_write_req *req,
- void *value, uint16_t value_len, int is_req,
- struct os_mbuf **out_txom)
+ble_att_clt_tx_write_req_or_cmd(uint16_t conn_handle,
+ const struct ble_att_write_req *req,
+ struct os_mbuf *txom, int is_req)
{
- struct os_mbuf *txom;
int rc;
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_WRITE_REQ_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
+ txom = os_mbuf_prepend_pullup(txom, BLE_ATT_WRITE_REQ_BASE_SZ);
+ if (txom == NULL) {
+ return BLE_HS_ENOMEM;
}
if (is_req) {
- ble_att_write_req_write(txom->om_data, txom->om_len, req);
+ ble_att_write_req_write(txom->om_data, BLE_ATT_WRITE_REQ_BASE_SZ, req);
} else {
- ble_att_write_cmd_write(txom->om_data, txom->om_len, req);
- }
-
- rc = ble_att_clt_append_blob(conn_handle, txom, value, value_len);
- if (rc != 0) {
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
-static int
-ble_att_clt_tx_write_req_or_cmd(uint16_t conn_handle,
- struct ble_att_write_req *req,
- void *value, uint16_t value_len,
- int is_req)
-{
- struct os_mbuf *txom;
- int rc;
-
- rc = ble_att_clt_build_write_req_or_cmd(conn_handle, req, value, value_len,
- is_req, &txom);
- if (rc != 0) {
- return rc;
+ ble_att_write_cmd_write(txom->om_data, BLE_ATT_WRITE_REQ_BASE_SZ, req);
}
rc = ble_att_clt_tx_req(conn_handle, txom);
@@ -1123,8 +886,9 @@ ble_att_clt_tx_write_req_or_cmd(uint16_t conn_handle,
}
int
-ble_att_clt_tx_write_req(uint16_t conn_handle, struct ble_att_write_req *req,
- void *value, uint16_t value_len)
+ble_att_clt_tx_write_req(uint16_t conn_handle,
+ const struct ble_att_write_req *req,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(ATT_CLT_WRITE)
return BLE_HS_ENOTSUP;
@@ -1132,17 +896,20 @@ ble_att_clt_tx_write_req(uint16_t conn_handle, struct ble_att_write_req *req,
int rc;
+ rc = ble_att_clt_tx_write_req_or_cmd(conn_handle, req, txom, 1);
+ if (rc != 0) {
+ return rc;
+ }
+
BLE_ATT_LOG_CMD(1, "write req", conn_handle, ble_att_write_cmd_log, req);
- rc = ble_att_clt_tx_write_req_or_cmd(conn_handle, req, value, value_len,
- 1);
- return rc;
+ return 0;
}
int
ble_att_clt_tx_write_cmd(uint16_t conn_handle,
- struct ble_att_write_req *req,
- void *value, uint16_t value_len)
+ const struct ble_att_write_req *req,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(ATT_CLT_WRITE_NO_RSP)
return BLE_HS_ENOTSUP;
@@ -1150,11 +917,14 @@ ble_att_clt_tx_write_cmd(uint16_t conn_handle,
int rc;
+ rc = ble_att_clt_tx_write_req_or_cmd(conn_handle, req, txom, 0);
+ if (rc != 0) {
+ return rc;
+ }
+
BLE_ATT_LOG_CMD(1, "write cmd", conn_handle, ble_att_write_cmd_log, req);
- rc = ble_att_clt_tx_write_req_or_cmd(conn_handle, req, value, value_len,
- 0);
- return rc;
+ return 0;
}
int
@@ -1175,80 +945,57 @@ ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom)
* $prepare write request *
*****************************************************************************/
-static int
-ble_att_clt_build_prep_write_req(uint16_t conn_handle,
- struct ble_att_prep_write_cmd *req,
- void *value, uint16_t value_len,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_PREP_WRITE_CMD_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_prep_write_req_write(txom->om_data, txom->om_len, req);
-
- rc = ble_att_clt_append_blob(conn_handle, txom, value, value_len);
- if (rc != 0) {
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_prep_write(uint16_t conn_handle,
- struct ble_att_prep_write_cmd *req,
- void *value, uint16_t value_len)
+ const struct ble_att_prep_write_cmd *req,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(ATT_CLT_PREP_WRITE)
return BLE_HS_ENOTSUP;
#endif
- struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "prep write req", conn_handle,
- ble_att_prep_write_cmd_log, req);
-
if (req->bapc_handle == 0) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- if (req->bapc_offset + value_len > BLE_ATT_ATTR_MAX_LEN) {
- return BLE_HS_EINVAL;
+ if (req->bapc_offset + OS_MBUF_PKTLEN(txom) > BLE_ATT_ATTR_MAX_LEN) {
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- if (value_len >
+ if (OS_MBUF_PKTLEN(txom) >
ble_att_mtu(conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_prep_write_req(conn_handle, req, value, value_len,
- &txom);
- if (rc != 0) {
- return rc;
+ txom = os_mbuf_prepend_pullup(txom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
+ ble_att_prep_write_req_write(txom->om_data, BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ req);
+
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "prep write req", conn_handle,
+ ble_att_prep_write_cmd_log, req);
+
return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
}
int
@@ -1259,16 +1006,12 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom)
#endif
struct ble_att_prep_write_cmd rsp;
- uint16_t value_len;
- void *value;
int rc;
/* Initialize some values in case of early error. */
memset(&rsp, 0, sizeof rsp);
- value = NULL;
- value_len = 0;
- rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
if (rc != 0) {
goto done;
}
@@ -1280,12 +1023,9 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom)
/* Strip the base from the front of the response. */
os_mbuf_adj(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
- /* Copy the attribute data into the global ATT flat buffer. */
- rc = ble_att_clt_copy_attr_to_flatbuf(*rxom, &value, &value_len);
-
done:
/* Notify GATT client that the full response has been parsed. */
- ble_gattc_rx_prep_write_rsp(conn_handle, rc, &rsp, value, value_len);
+ ble_gattc_rx_prep_write_rsp(conn_handle, rc, &rsp, rxom);
return rc;
}
@@ -1293,35 +1033,9 @@ done:
* $execute write request *
*****************************************************************************/
-static int
-ble_att_clt_build_exec_write_req(struct ble_att_exec_write_req *req,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_EXEC_WRITE_REQ_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_exec_write_req_write(txom->om_data, txom->om_len, req);
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_exec_write(uint16_t conn_handle,
- struct ble_att_exec_write_req *req)
+ const struct ble_att_exec_write_req *req)
{
#if !NIMBLE_OPT(ATT_CLT_EXEC_WRITE)
return BLE_HS_ENOTSUP;
@@ -1330,23 +1044,24 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle,
struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "exec write req", conn_handle,
- ble_att_exec_write_req_log, req);
-
if ((req->baeq_flags & BLE_ATT_EXEC_WRITE_F_RESERVED) != 0) {
return BLE_HS_EINVAL;
}
- rc = ble_att_clt_build_exec_write_req(req, &txom);
+ rc = ble_att_clt_init_req(BLE_ATT_EXEC_WRITE_REQ_SZ, &txom);
if (rc != 0) {
return rc;
}
+ ble_att_exec_write_req_write(txom->om_data, txom->om_len, req);
rc = ble_att_clt_tx_req(conn_handle, txom);
if (rc != 0) {
return rc;
}
+ BLE_ATT_LOG_CMD(1, "exec write req", conn_handle,
+ ble_att_exec_write_req_log, req);
+
return 0;
}
@@ -1361,7 +1076,7 @@ ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom)
BLE_ATT_LOG_EMPTY_CMD(0, "exec write rsp", conn_handle);
- rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_EXEC_WRITE_RSP_SZ);
+ rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_EXEC_WRITE_RSP_SZ);
if (rc == 0) {
ble_att_exec_write_rsp_parse((*rxom)->om_data, (*rxom)->om_len);
}
@@ -1374,138 +1089,87 @@ ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom)
* $handle value notification *
*****************************************************************************/
-static int
-ble_att_clt_build_notify_req(uint16_t conn_handle,
- struct ble_att_notify_req *req,
- void *value, uint16_t value_len,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_NOTIFY_REQ_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_notify_req_write(txom->om_data, txom->om_len, req);
-
- rc = ble_att_clt_append_blob(conn_handle, txom, value, value_len);
- if (rc != 0) {
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
-ble_att_clt_tx_notify(uint16_t conn_handle, struct ble_att_notify_req *req,
- void *value, uint16_t value_len)
+ble_att_clt_tx_notify(uint16_t conn_handle,
+ const struct ble_att_notify_req *req,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(ATT_CLT_NOTIFY)
return BLE_HS_ENOTSUP;
#endif
- struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "notify req", conn_handle, ble_att_notify_req_log, req);
-
if (req->banq_handle == 0) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_notify_req(conn_handle, req, value, value_len,
- &txom);
- if (rc != 0) {
- return rc;
+ txom = os_mbuf_prepend_pullup(txom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
+ ble_att_notify_req_write(txom->om_data, BLE_ATT_NOTIFY_REQ_BASE_SZ, req);
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "notify req", conn_handle, ble_att_notify_req_log, req);
+
return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
}
/*****************************************************************************
* $handle value indication *
*****************************************************************************/
-static int
-ble_att_clt_build_indicate_req(uint16_t conn_handle,
- struct ble_att_indicate_req *req,
- void *value, uint16_t value_len,
- struct os_mbuf **out_txom)
-{
- struct os_mbuf *txom;
- int rc;
-
- txom = NULL;
-
- rc = ble_att_clt_init_req(BLE_ATT_INDICATE_REQ_BASE_SZ, &txom);
- if (rc != 0) {
- goto done;
- }
-
- ble_att_indicate_req_write(txom->om_data, txom->om_len, req);
-
- rc = ble_att_clt_append_blob(conn_handle, txom, value, value_len);
- if (rc != 0) {
- goto done;
- }
-
-done:
- if (rc != 0) {
- os_mbuf_free_chain(txom);
- txom = NULL;
- }
-
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_clt_tx_indicate(uint16_t conn_handle,
- struct ble_att_indicate_req *req,
- void *value, uint16_t value_len)
+ const struct ble_att_indicate_req *req,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(ATT_CLT_INDICATE)
return BLE_HS_ENOTSUP;
#endif
- struct os_mbuf *txom;
int rc;
- BLE_ATT_LOG_CMD(1, "indicate req", conn_handle, ble_att_indicate_req_log,
- req);
-
if (req->baiq_handle == 0) {
- return BLE_HS_EINVAL;
+ rc = BLE_HS_EINVAL;
+ goto err;
}
- rc = ble_att_clt_build_indicate_req(conn_handle, req, value, value_len,
- &txom);
- if (rc != 0) {
- return rc;
+ txom = os_mbuf_prepend_pullup(txom, BLE_ATT_INDICATE_REQ_BASE_SZ);
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
+ ble_att_indicate_req_write(txom->om_data, BLE_ATT_INDICATE_REQ_BASE_SZ,
+ req);
+
rc = ble_att_clt_tx_req(conn_handle, txom);
+ txom = NULL;
if (rc != 0) {
- return rc;
+ goto err;
}
+ BLE_ATT_LOG_CMD(1, "indicate req", conn_handle, ble_att_indicate_req_log,
+ req);
+
return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
}
int
diff --git a/net/nimble/host/src/ble_att_cmd.c b/net/nimble/host/src/ble_att_cmd.c
index 5df08466..05c68749 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -26,10 +26,11 @@
#include "host/ble_uuid.h"
#include "ble_hs_priv.h"
-static void *
-ble_att_init_parse(uint8_t op, void *payload, int min_len, int actual_len)
+static const void *
+ble_att_init_parse(uint8_t op, const void *payload,
+ int min_len, int actual_len)
{
- uint8_t *u8ptr;
+ const uint8_t *u8ptr;
BLE_HS_DBG_ASSERT(actual_len >= min_len);
@@ -40,20 +41,6 @@ ble_att_init_parse(uint8_t op, void *payload, int min_len, int actual_len)
}
static void *
-ble_att_init_parse_2op(uint8_t op1, uint8_t op2, void *payload,
- int min_len, int actual_len)
-{
- uint8_t *u8ptr;
-
- BLE_HS_DBG_ASSERT(actual_len >= min_len);
-
- u8ptr = payload;
- BLE_HS_DBG_ASSERT(u8ptr[0] == op1 || u8ptr[0] == op2);
-
- return u8ptr + 1;
-}
-
-static void *
ble_att_init_write(uint8_t op, void *payload, int min_len, int actual_len)
{
uint8_t *u8ptr;
@@ -68,7 +55,7 @@ ble_att_init_write(uint8_t op, void *payload, int min_len, int actual_len)
static void
ble_att_error_rsp_swap(struct ble_att_error_rsp *dst,
- struct ble_att_error_rsp *src)
+ const struct ble_att_error_rsp *src)
{
dst->baep_req_op = src->baep_req_op;
dst->baep_handle = TOFROMLE16(src->baep_handle);
@@ -76,9 +63,10 @@ ble_att_error_rsp_swap(struct ble_att_error_rsp *dst,
}
void
-ble_att_error_rsp_parse(void *payload, int len, struct ble_att_error_rsp *dst)
+ble_att_error_rsp_parse(const void *payload, int len,
+ struct ble_att_error_rsp *dst)
{
- struct ble_att_error_rsp *src;
+ const struct ble_att_error_rsp *src;
src = ble_att_init_parse(BLE_ATT_OP_ERROR_RSP, payload,
BLE_ATT_ERROR_RSP_SZ, len);
@@ -86,7 +74,8 @@ ble_att_error_rsp_parse(void *payload, int len, struct ble_att_error_rsp *dst)
}
void
-ble_att_error_rsp_write(void *payload, int len, struct ble_att_error_rsp *src)
+ble_att_error_rsp_write(void *payload, int len,
+ const struct ble_att_error_rsp *src)
{
struct ble_att_error_rsp *dst;
@@ -96,30 +85,44 @@ ble_att_error_rsp_write(void *payload, int len, struct ble_att_error_rsp *src)
}
void
-ble_att_error_rsp_log(struct ble_att_error_rsp *cmd)
+ble_att_error_rsp_log(const struct ble_att_error_rsp *cmd)
{
BLE_HS_LOG(DEBUG, "req_op=%d handle=0x%04x error_code=%d",
cmd->baep_req_op, cmd->baep_handle, cmd->baep_error_code);
}
static void
-ble_att_mtu_cmd_swap(struct ble_att_mtu_cmd *dst, struct ble_att_mtu_cmd *src)
+ble_att_mtu_cmd_swap(struct ble_att_mtu_cmd *dst,
+ const struct ble_att_mtu_cmd *src)
{
dst->bamc_mtu = TOFROMLE16(src->bamc_mtu);
}
void
-ble_att_mtu_cmd_parse(void *payload, int len, struct ble_att_mtu_cmd *dst)
+ble_att_mtu_req_parse(const void *payload, int len,
+ struct ble_att_mtu_cmd *dst)
+{
+ const struct ble_att_mtu_cmd *src;
+
+ src = ble_att_init_parse(BLE_ATT_OP_MTU_REQ, payload, BLE_ATT_MTU_CMD_SZ,
+ len);
+ ble_att_mtu_cmd_swap(dst, src);
+}
+
+void
+ble_att_mtu_rsp_parse(const void *payload, int len,
+ struct ble_att_mtu_cmd *dst)
{
- struct ble_att_mtu_cmd *src;
+ const struct ble_att_mtu_cmd *src;
- src = ble_att_init_parse_2op(BLE_ATT_OP_MTU_REQ, BLE_ATT_OP_MTU_RSP,
- payload, BLE_ATT_MTU_CMD_SZ, len);
+ src = ble_att_init_parse(BLE_ATT_OP_MTU_RSP, payload, BLE_ATT_MTU_CMD_SZ,
+ len);
ble_att_mtu_cmd_swap(dst, src);
}
void
-ble_att_mtu_req_write(void *payload, int len, struct ble_att_mtu_cmd *src)
+ble_att_mtu_req_write(void *payload, int len,
+ const struct ble_att_mtu_cmd *src)
{
struct ble_att_mtu_cmd *dst;
@@ -129,7 +132,8 @@ ble_att_mtu_req_write(void *payload, int len, struct ble_att_mtu_cmd *src)
}
void
-ble_att_mtu_rsp_write(void *payload, int len, struct ble_att_mtu_cmd *src)
+ble_att_mtu_rsp_write(void *payload, int len,
+ const struct ble_att_mtu_cmd *src)
{
struct ble_att_mtu_cmd *dst;
@@ -139,24 +143,24 @@ ble_att_mtu_rsp_write(void *payload, int len, struct ble_att_mtu_cmd *src)
}
void
-ble_att_mtu_cmd_log(struct ble_att_mtu_cmd *cmd)
+ble_att_mtu_cmd_log(const struct ble_att_mtu_cmd *cmd)
{
BLE_HS_LOG(DEBUG, "mtu=%d", cmd->bamc_mtu);
}
static void
ble_att_find_info_req_swap(struct ble_att_find_info_req *dst,
- struct ble_att_find_info_req *src)
+ const struct ble_att_find_info_req *src)
{
dst->bafq_start_handle = TOFROMLE16(src->bafq_start_handle);
dst->bafq_end_handle = TOFROMLE16(src->bafq_end_handle);
}
void
-ble_att_find_info_req_parse(void *payload, int len,
+ble_att_find_info_req_parse(const void *payload, int len,
struct ble_att_find_info_req *dst)
{
- struct ble_att_find_info_req *src;
+ const struct ble_att_find_info_req *src;
src = ble_att_init_parse(BLE_ATT_OP_FIND_INFO_REQ, payload,
BLE_ATT_FIND_INFO_REQ_SZ, len);
@@ -165,7 +169,7 @@ ble_att_find_info_req_parse(void *payload, int len,
void
ble_att_find_info_req_write(void *payload, int len,
- struct ble_att_find_info_req *src)
+ const struct ble_att_find_info_req *src)
{
struct ble_att_find_info_req *dst;
@@ -175,7 +179,7 @@ ble_att_find_info_req_write(void *payload, int len,
}
void
-ble_att_find_info_req_log(struct ble_att_find_info_req *cmd)
+ble_att_find_info_req_log(const struct ble_att_find_info_req *cmd)
{
BLE_HS_LOG(DEBUG, "start_handle=0x%04x end_handle=0x%04x",
cmd->bafq_start_handle, cmd->bafq_end_handle);
@@ -183,16 +187,16 @@ ble_att_find_info_req_log(struct ble_att_find_info_req *cmd)
static void
ble_att_find_info_rsp_swap(struct ble_att_find_info_rsp *dst,
- struct ble_att_find_info_rsp *src)
+ const struct ble_att_find_info_rsp *src)
{
dst->bafp_format = src->bafp_format;
}
void
-ble_att_find_info_rsp_parse(void *payload, int len,
+ble_att_find_info_rsp_parse(const void *payload, int len,
struct ble_att_find_info_rsp *dst)
{
- struct ble_att_find_info_rsp *src;
+ const struct ble_att_find_info_rsp *src;
src = ble_att_init_parse(BLE_ATT_OP_FIND_INFO_RSP, payload,
BLE_ATT_FIND_INFO_RSP_BASE_SZ, len);
@@ -201,7 +205,7 @@ ble_att_find_info_rsp_parse(void *payload, int len,
void
ble_att_find_info_rsp_write(void *payload, int len,
- struct ble_att_find_info_rsp *src)
+ const struct ble_att_find_info_rsp *src)
{
struct ble_att_find_info_rsp *dst;
@@ -211,14 +215,14 @@ ble_att_find_info_rsp_write(void *payload, int len,
}
void
-ble_att_find_info_rsp_log(struct ble_att_find_info_rsp *cmd)
+ble_att_find_info_rsp_log(const struct ble_att_find_info_rsp *cmd)
{
BLE_HS_LOG(DEBUG, "format=%d", cmd->bafp_format);
}
static void
ble_att_find_type_value_req_swap(struct ble_att_find_type_value_req *dst,
- struct ble_att_find_type_value_req *src)
+ const struct ble_att_find_type_value_req *src)
{
dst->bavq_start_handle = TOFROMLE16(src->bavq_start_handle);
dst->bavq_end_handle = TOFROMLE16(src->bavq_end_handle);
@@ -226,10 +230,10 @@ ble_att_find_type_value_req_swap(struct ble_att_find_type_value_req *dst,
}
void
-ble_att_find_type_value_req_parse(void *payload, int len,
+ble_att_find_type_value_req_parse(const void *payload, int len,
struct ble_att_find_type_value_req *dst)
{
- struct ble_att_find_type_value_req *src;
+ const struct ble_att_find_type_value_req *src;
src = ble_att_init_parse(BLE_ATT_OP_FIND_TYPE_VALUE_REQ, payload,
BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ, len);
@@ -237,8 +241,8 @@ ble_att_find_type_value_req_parse(void *payload, int len,
}
void
-ble_att_find_type_value_req_write(void *payload, int len,
- struct ble_att_find_type_value_req *src)
+ble_att_find_type_value_req_write(
+ void *payload, int len, const struct ble_att_find_type_value_req *src)
{
struct ble_att_find_type_value_req *dst;
@@ -248,7 +252,7 @@ ble_att_find_type_value_req_write(void *payload, int len,
}
void
-ble_att_find_type_value_req_log(struct ble_att_find_type_value_req *cmd)
+ble_att_find_type_value_req_log(const struct ble_att_find_type_value_req *cmd)
{
BLE_HS_LOG(DEBUG, "start_handle=0x%04x end_handle=0x%04x attr_type=%d",
cmd->bavq_start_handle, cmd->bavq_end_handle,
@@ -257,17 +261,17 @@ ble_att_find_type_value_req_log(struct ble_att_find_type_value_req *cmd)
static void
ble_att_read_type_req_swap(struct ble_att_read_type_req *dst,
- struct ble_att_read_type_req *src)
+ const struct ble_att_read_type_req *src)
{
dst->batq_start_handle = TOFROMLE16(src->batq_start_handle);
dst->batq_end_handle = TOFROMLE16(src->batq_end_handle);
}
void
-ble_att_read_type_req_parse(void *payload, int len,
+ble_att_read_type_req_parse(const void *payload, int len,
struct ble_att_read_type_req *dst)
{
- struct ble_att_read_type_req *src;
+ const struct ble_att_read_type_req *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_TYPE_REQ, payload,
BLE_ATT_READ_TYPE_REQ_BASE_SZ, len);
@@ -276,7 +280,7 @@ ble_att_read_type_req_parse(void *payload, int len,
void
ble_att_read_type_req_write(void *payload, int len,
- struct ble_att_read_type_req *src)
+ const struct ble_att_read_type_req *src)
{
struct ble_att_read_type_req *dst;
@@ -286,7 +290,7 @@ ble_att_read_type_req_write(void *payload, int len,
}
void
-ble_att_read_type_req_log(struct ble_att_read_type_req *cmd)
+ble_att_read_type_req_log(const struct ble_att_read_type_req *cmd)
{
BLE_HS_LOG(DEBUG, "start_handle=0x%04x end_handle=0x%04x",
cmd->batq_start_handle, cmd->batq_end_handle);
@@ -294,16 +298,16 @@ ble_att_read_type_req_log(struct ble_att_read_type_req *cmd)
static void
ble_att_read_type_rsp_swap(struct ble_att_read_type_rsp *dst,
- struct ble_att_read_type_rsp *src)
+ const struct ble_att_read_type_rsp *src)
{
dst->batp_length = src->batp_length;
}
void
-ble_att_read_type_rsp_parse(void *payload, int len,
+ble_att_read_type_rsp_parse(const void *payload, int len,
struct ble_att_read_type_rsp *dst)
{
- struct ble_att_read_type_rsp *src;
+ const struct ble_att_read_type_rsp *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_TYPE_RSP, payload,
BLE_ATT_READ_TYPE_RSP_BASE_SZ, len);
@@ -312,7 +316,7 @@ ble_att_read_type_rsp_parse(void *payload, int len,
void
ble_att_read_type_rsp_write(void *payload, int len,
- struct ble_att_read_type_rsp *src)
+ const struct ble_att_read_type_rsp *src)
{
struct ble_att_read_type_rsp *dst;
@@ -322,22 +326,23 @@ ble_att_read_type_rsp_write(void *payload, int len,
}
void
-ble_att_read_type_rsp_log(struct ble_att_read_type_rsp *cmd)
+ble_att_read_type_rsp_log(const struct ble_att_read_type_rsp *cmd)
{
BLE_HS_LOG(DEBUG, "length=%d", cmd->batp_length);
}
static void
ble_att_read_req_swap(struct ble_att_read_req *dst,
- struct ble_att_read_req *src)
+ const struct ble_att_read_req *src)
{
dst->barq_handle = TOFROMLE16(src->barq_handle);
}
void
-ble_att_read_req_parse(void *payload, int len, struct ble_att_read_req *dst)
+ble_att_read_req_parse(const void *payload, int len,
+ struct ble_att_read_req *dst)
{
- struct ble_att_read_req *src;
+ const struct ble_att_read_req *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_REQ, payload,
BLE_ATT_READ_REQ_SZ, len);
@@ -345,7 +350,8 @@ ble_att_read_req_parse(void *payload, int len, struct ble_att_read_req *dst)
}
void
-ble_att_read_req_write(void *payload, int len, struct ble_att_read_req *src)
+ble_att_read_req_write(void *payload, int len,
+ const struct ble_att_read_req *src)
{
struct ble_att_read_req *dst;
@@ -355,24 +361,24 @@ ble_att_read_req_write(void *payload, int len, struct ble_att_read_req *src)
}
void
-ble_att_read_req_log(struct ble_att_read_req *cmd)
+ble_att_read_req_log(const struct ble_att_read_req *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x", cmd->barq_handle);
}
static void
ble_att_read_blob_req_swap(struct ble_att_read_blob_req *dst,
- struct ble_att_read_blob_req *src)
+ const struct ble_att_read_blob_req *src)
{
dst->babq_handle = TOFROMLE16(src->babq_handle);
dst->babq_offset = TOFROMLE16(src->babq_offset);
}
void
-ble_att_read_blob_req_parse(void *payload, int len,
+ble_att_read_blob_req_parse(const void *payload, int len,
struct ble_att_read_blob_req *dst)
{
- struct ble_att_read_blob_req *src;
+ const struct ble_att_read_blob_req *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_BLOB_REQ, payload,
BLE_ATT_READ_BLOB_REQ_SZ, len);
@@ -381,7 +387,7 @@ ble_att_read_blob_req_parse(void *payload, int len,
void
ble_att_read_blob_req_write(void *payload, int len,
- struct ble_att_read_blob_req *src)
+ const struct ble_att_read_blob_req *src)
{
struct ble_att_read_blob_req *dst;
@@ -391,14 +397,14 @@ ble_att_read_blob_req_write(void *payload, int len,
}
void
-ble_att_read_blob_req_log(struct ble_att_read_blob_req *cmd)
+ble_att_read_blob_req_log(const struct ble_att_read_blob_req *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x offset=%d", cmd->babq_handle,
cmd->babq_offset);
}
void
-ble_att_read_mult_req_parse(void *payload, int len)
+ble_att_read_mult_req_parse(const void *payload, int len)
{
ble_att_init_parse(BLE_ATT_OP_READ_MULT_REQ, payload,
BLE_ATT_READ_MULT_REQ_BASE_SZ, len);
@@ -412,7 +418,7 @@ ble_att_read_mult_req_write(void *payload, int len)
}
void
-ble_att_read_mult_rsp_parse(void *payload, int len)
+ble_att_read_mult_rsp_parse(const void *payload, int len)
{
ble_att_init_parse(BLE_ATT_OP_READ_MULT_RSP, payload,
BLE_ATT_READ_MULT_RSP_BASE_SZ, len);
@@ -427,17 +433,17 @@ ble_att_read_mult_rsp_write(void *payload, int len)
static void
ble_att_read_group_type_req_swap(struct ble_att_read_group_type_req *dst,
- struct ble_att_read_group_type_req *src)
+ const struct ble_att_read_group_type_req *src)
{
dst->bagq_start_handle = TOFROMLE16(src->bagq_start_handle);
dst->bagq_end_handle = TOFROMLE16(src->bagq_end_handle);
}
void
-ble_att_read_group_type_req_parse(void *payload, int len,
+ble_att_read_group_type_req_parse(const void *payload, int len,
struct ble_att_read_group_type_req *dst)
{
- struct ble_att_read_group_type_req *src;
+ const struct ble_att_read_group_type_req *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_GROUP_TYPE_REQ, payload,
BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ, len);
@@ -445,8 +451,8 @@ ble_att_read_group_type_req_parse(void *payload, int len,
}
void
-ble_att_read_group_type_req_write(void *payload, int len,
- struct ble_att_read_group_type_req *src)
+ble_att_read_group_type_req_write(
+ void *payload, int len, const struct ble_att_read_group_type_req *src)
{
struct ble_att_read_group_type_req *dst;
@@ -456,7 +462,7 @@ ble_att_read_group_type_req_write(void *payload, int len,
}
void
-ble_att_read_group_type_req_log(struct ble_att_read_group_type_req *cmd)
+ble_att_read_group_type_req_log(const struct ble_att_read_group_type_req *cmd)
{
BLE_HS_LOG(DEBUG, "start_handle=0x%04x end_handle=0x%04x",
cmd->bagq_start_handle, cmd->bagq_end_handle);
@@ -464,16 +470,16 @@ ble_att_read_group_type_req_log(struct ble_att_read_group_type_req *cmd)
static void
ble_att_read_group_type_rsp_swap(struct ble_att_read_group_type_rsp *dst,
- struct ble_att_read_group_type_rsp *src)
+ const struct ble_att_read_group_type_rsp *src)
{
dst->bagp_length = src->bagp_length;
}
void
-ble_att_read_group_type_rsp_parse(void *payload, int len,
+ble_att_read_group_type_rsp_parse(const void *payload, int len,
struct ble_att_read_group_type_rsp *dst)
{
- struct ble_att_read_group_type_rsp *src;
+ const struct ble_att_read_group_type_rsp *src;
src = ble_att_init_parse(BLE_ATT_OP_READ_GROUP_TYPE_RSP, payload,
BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ, len);
@@ -481,8 +487,8 @@ ble_att_read_group_type_rsp_parse(void *payload, int len,
}
void
-ble_att_read_group_type_rsp_write(void *payload, int len,
- struct ble_att_read_group_type_rsp *src)
+ble_att_read_group_type_rsp_write(
+ void *payload, int len, const struct ble_att_read_group_type_rsp *src)
{
struct ble_att_read_group_type_rsp *dst;
@@ -492,22 +498,23 @@ ble_att_read_group_type_rsp_write(void *payload, int len,
}
void
-ble_att_read_group_type_rsp_log(struct ble_att_read_group_type_rsp *cmd)
+ble_att_read_group_type_rsp_log(const struct ble_att_read_group_type_rsp *cmd)
{
BLE_HS_LOG(DEBUG, "length=%d", cmd->bagp_length);
}
static void
ble_att_write_req_swap(struct ble_att_write_req *dst,
- struct ble_att_write_req *src)
+ const struct ble_att_write_req *src)
{
dst->bawq_handle = TOFROMLE16(src->bawq_handle);
}
void
-ble_att_write_req_parse(void *payload, int len, struct ble_att_write_req *dst)
+ble_att_write_req_parse(const void *payload, int len,
+ struct ble_att_write_req *dst)
{
- struct ble_att_write_req *src;
+ const struct ble_att_write_req *src;
src = ble_att_init_parse(BLE_ATT_OP_WRITE_REQ, payload,
BLE_ATT_WRITE_REQ_BASE_SZ, len);
@@ -515,9 +522,10 @@ ble_att_write_req_parse(void *payload, int len, struct ble_att_write_req *dst)
}
void
-ble_att_write_cmd_parse(void *payload, int len, struct ble_att_write_req *dst)
+ble_att_write_cmd_parse(const void *payload, int len,
+ struct ble_att_write_req *dst)
{
- struct ble_att_write_req *src;
+ const struct ble_att_write_req *src;
src = ble_att_init_parse(BLE_ATT_OP_WRITE_CMD, payload,
BLE_ATT_WRITE_REQ_BASE_SZ, len);
@@ -525,7 +533,8 @@ ble_att_write_cmd_parse(void *payload, int len, struct ble_att_write_req *dst)
}
void
-ble_att_write_req_write(void *payload, int len, struct ble_att_write_req *src)
+ble_att_write_req_write(void *payload, int len,
+ const struct ble_att_write_req *src)
{
struct ble_att_write_req *dst;
@@ -535,7 +544,8 @@ ble_att_write_req_write(void *payload, int len, struct ble_att_write_req *src)
}
void
-ble_att_write_cmd_write(void *payload, int len, struct ble_att_write_req *src)
+ble_att_write_cmd_write(void *payload, int len,
+ const struct ble_att_write_req *src)
{
struct ble_att_write_req *dst;
@@ -545,24 +555,24 @@ ble_att_write_cmd_write(void *payload, int len, struct ble_att_write_req *src)
}
void
-ble_att_write_cmd_log(struct ble_att_write_req *cmd)
+ble_att_write_cmd_log(const struct ble_att_write_req *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x", cmd->bawq_handle);
}
static void
ble_att_prep_write_cmd_swap(struct ble_att_prep_write_cmd *dst,
- struct ble_att_prep_write_cmd *src)
+ const struct ble_att_prep_write_cmd *src)
{
dst->bapc_handle = TOFROMLE16(src->bapc_handle);
dst->bapc_offset = TOFROMLE16(src->bapc_offset);
}
void
-ble_att_prep_write_req_parse(void *payload, int len,
+ble_att_prep_write_req_parse(const void *payload, int len,
struct ble_att_prep_write_cmd *dst)
{
- struct ble_att_prep_write_cmd *src;
+ const struct ble_att_prep_write_cmd *src;
src = ble_att_init_parse(BLE_ATT_OP_PREP_WRITE_REQ, payload,
BLE_ATT_PREP_WRITE_CMD_BASE_SZ, len);
@@ -571,7 +581,7 @@ ble_att_prep_write_req_parse(void *payload, int len,
void
ble_att_prep_write_req_write(void *payload, int len,
- struct ble_att_prep_write_cmd *src)
+ const struct ble_att_prep_write_cmd *src)
{
struct ble_att_prep_write_cmd *dst;
@@ -581,10 +591,10 @@ ble_att_prep_write_req_write(void *payload, int len,
}
void
-ble_att_prep_write_rsp_parse(void *payload, int len,
+ble_att_prep_write_rsp_parse(const void *payload, int len,
struct ble_att_prep_write_cmd *dst)
{
- struct ble_att_prep_write_cmd *src;
+ const struct ble_att_prep_write_cmd *src;
src = ble_att_init_parse(BLE_ATT_OP_PREP_WRITE_RSP, payload,
BLE_ATT_PREP_WRITE_CMD_BASE_SZ, len);
@@ -593,7 +603,7 @@ ble_att_prep_write_rsp_parse(void *payload, int len,
void
ble_att_prep_write_rsp_write(void *payload, int len,
- struct ble_att_prep_write_cmd *src)
+ const struct ble_att_prep_write_cmd *src)
{
struct ble_att_prep_write_cmd *dst;
@@ -603,7 +613,7 @@ ble_att_prep_write_rsp_write(void *payload, int len,
}
void
-ble_att_prep_write_cmd_log(struct ble_att_prep_write_cmd *cmd)
+ble_att_prep_write_cmd_log(const struct ble_att_prep_write_cmd *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x offset=%d", cmd->bapc_handle,
cmd->bapc_offset);
@@ -611,16 +621,16 @@ ble_att_prep_write_cmd_log(struct ble_att_prep_write_cmd *cmd)
static void
ble_att_exec_write_req_swap(struct ble_att_exec_write_req *dst,
- struct ble_att_exec_write_req *src)
+ const struct ble_att_exec_write_req *src)
{
dst->baeq_flags = src->baeq_flags;
}
void
-ble_att_exec_write_req_parse(void *payload, int len,
+ble_att_exec_write_req_parse(const void *payload, int len,
struct ble_att_exec_write_req *dst)
{
- struct ble_att_exec_write_req *src;
+ const struct ble_att_exec_write_req *src;
src = ble_att_init_parse(BLE_ATT_OP_EXEC_WRITE_REQ, payload,
BLE_ATT_EXEC_WRITE_REQ_SZ, len);
@@ -629,7 +639,7 @@ ble_att_exec_write_req_parse(void *payload, int len,
void
ble_att_exec_write_req_write(void *payload, int len,
- struct ble_att_exec_write_req *src)
+ const struct ble_att_exec_write_req *src)
{
struct ble_att_exec_write_req *dst;
@@ -639,13 +649,13 @@ ble_att_exec_write_req_write(void *payload, int len,
}
void
-ble_att_exec_write_req_log(struct ble_att_exec_write_req *cmd)
+ble_att_exec_write_req_log(const struct ble_att_exec_write_req *cmd)
{
BLE_HS_LOG(DEBUG, "flags=0x%02x", cmd->baeq_flags);
}
void
-ble_att_exec_write_rsp_parse(void *payload, int len)
+ble_att_exec_write_rsp_parse(const void *payload, int len)
{
ble_att_init_parse(BLE_ATT_OP_EXEC_WRITE_RSP, payload,
BLE_ATT_EXEC_WRITE_RSP_SZ, len);
@@ -660,16 +670,16 @@ ble_att_exec_write_rsp_write(void *payload, int len)
static void
ble_att_notify_req_swap(struct ble_att_notify_req *dst,
- struct ble_att_notify_req *src)
+ const struct ble_att_notify_req *src)
{
dst->banq_handle = TOFROMLE16(src->banq_handle);
}
void
-ble_att_notify_req_parse(void *payload, int len,
+ble_att_notify_req_parse(const void *payload, int len,
struct ble_att_notify_req *dst)
{
- struct ble_att_notify_req *src;
+ const struct ble_att_notify_req *src;
src = ble_att_init_parse(BLE_ATT_OP_NOTIFY_REQ, payload,
BLE_ATT_NOTIFY_REQ_BASE_SZ, len);
@@ -678,7 +688,7 @@ ble_att_notify_req_parse(void *payload, int len,
void
ble_att_notify_req_write(void *payload, int len,
- struct ble_att_notify_req *src)
+ const struct ble_att_notify_req *src)
{
struct ble_att_notify_req *dst;
@@ -688,23 +698,23 @@ ble_att_notify_req_write(void *payload, int len,
}
void
-ble_att_notify_req_log(struct ble_att_notify_req *cmd)
+ble_att_notify_req_log(const struct ble_att_notify_req *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x", cmd->banq_handle);
}
static void
ble_att_indicate_req_swap(struct ble_att_indicate_req *dst,
- struct ble_att_indicate_req *src)
+ const struct ble_att_indicate_req *src)
{
dst->baiq_handle = TOFROMLE16(src->baiq_handle);
}
void
-ble_att_indicate_req_parse(void *payload, int len,
+ble_att_indicate_req_parse(const void *payload, int len,
struct ble_att_indicate_req *dst)
{
- struct ble_att_indicate_req *src;
+ const struct ble_att_indicate_req *src;
src = ble_att_init_parse(BLE_ATT_OP_INDICATE_REQ, payload,
BLE_ATT_INDICATE_REQ_BASE_SZ, len);
@@ -713,7 +723,7 @@ ble_att_indicate_req_parse(void *payload, int len,
void
ble_att_indicate_req_write(void *payload, int len,
- struct ble_att_indicate_req *src)
+ const struct ble_att_indicate_req *src)
{
struct ble_att_indicate_req *dst;
@@ -723,13 +733,13 @@ ble_att_indicate_req_write(void *payload, int len,
}
void
-ble_att_indicate_req_log(struct ble_att_indicate_req *cmd)
+ble_att_indicate_req_log(const struct ble_att_indicate_req *cmd)
{
BLE_HS_LOG(DEBUG, "handle=0x%04x", cmd->baiq_handle);
}
void
-ble_att_indicate_rsp_parse(void *payload, int len)
+ble_att_indicate_rsp_parse(const void *payload, int len)
{
ble_att_init_parse(BLE_ATT_OP_INDICATE_RSP, payload,
BLE_ATT_INDICATE_RSP_SZ, len);
diff --git a/net/nimble/host/src/ble_att_cmd_priv.h b/net/nimble/host/src/ble_att_cmd_priv.h
index 38af5f2e..bfeb28f1 100644
--- a/net/nimble/host/src/ble_att_cmd_priv.h
+++ b/net/nimble/host/src/ble_att_cmd_priv.h
@@ -304,103 +304,108 @@ struct ble_att_indicate_req {
*/
#define BLE_ATT_INDICATE_RSP_SZ 1
-void ble_att_error_rsp_parse(void *payload, int len,
- struct ble_att_error_rsp *rsp);
+void ble_att_error_rsp_parse(const void *payload, int len,
+ struct ble_att_error_rsp *rsp);
void ble_att_error_rsp_write(void *payload, int len,
- struct ble_att_error_rsp *rsp);
-void ble_att_error_rsp_log(struct ble_att_error_rsp *cmd);
-void ble_att_mtu_cmd_parse(void *payload, int len,
- struct ble_att_mtu_cmd *cmd);
+ const struct ble_att_error_rsp *rsp);
+void ble_att_error_rsp_log(const struct ble_att_error_rsp *cmd);
+void ble_att_mtu_req_parse(const void *payload, int len,
+ struct ble_att_mtu_cmd *cmd);
void ble_att_mtu_req_write(void *payload, int len,
- struct ble_att_mtu_cmd *cmd);
-void ble_att_mtu_rsp_write(void *payload, int len,
+ const struct ble_att_mtu_cmd *cmd);
+void ble_att_mtu_rsp_parse(const void *payload, int len,
struct ble_att_mtu_cmd *cmd);
-void ble_att_mtu_cmd_log(struct ble_att_mtu_cmd *cmd);
-void ble_att_find_info_req_parse(void *payload, int len,
+void ble_att_mtu_rsp_write(void *payload, int len,
+ const struct ble_att_mtu_cmd *cmd);
+void ble_att_mtu_cmd_log(const struct ble_att_mtu_cmd *cmd);
+void ble_att_find_info_req_parse(const void *payload, int len,
struct ble_att_find_info_req *req);
void ble_att_find_info_req_write(void *payload, int len,
- struct ble_att_find_info_req *req);
-void ble_att_find_info_req_log(struct ble_att_find_info_req *cmd);
-void ble_att_find_info_rsp_parse(void *payload, int len,
+ const struct ble_att_find_info_req *req);
+void ble_att_find_info_req_log(const struct ble_att_find_info_req *cmd);
+void ble_att_find_info_rsp_parse(const void *payload, int len,
struct ble_att_find_info_rsp *rsp);
void ble_att_find_info_rsp_write(void *payload, int len,
- struct ble_att_find_info_rsp *rsp);
-void ble_att_find_info_rsp_log(struct ble_att_find_info_rsp *cmd);
-void ble_att_find_type_value_req_parse(void *payload, int len,
- struct ble_att_find_type_value_req *req);
-void ble_att_find_type_value_req_write(void *payload, int len,
- struct ble_att_find_type_value_req *req);
-void ble_att_find_type_value_req_log(struct ble_att_find_type_value_req *cmd);
-void ble_att_read_type_req_parse(void *payload, int len,
+ const struct ble_att_find_info_rsp *rsp);
+void ble_att_find_info_rsp_log(const struct ble_att_find_info_rsp *cmd);
+void ble_att_find_type_value_req_parse(
+ const void *payload, int len, struct ble_att_find_type_value_req *req);
+void ble_att_find_type_value_req_write(
+ void *payload, int len, const struct ble_att_find_type_value_req *req);
+void ble_att_find_type_value_req_log(
+ const struct ble_att_find_type_value_req *cmd);
+void ble_att_read_type_req_parse(const void *payload, int len,
struct ble_att_read_type_req *req);
void ble_att_read_type_req_write(void *payload, int len,
- struct ble_att_read_type_req *req);
-void ble_att_read_type_req_log(struct ble_att_read_type_req *cmd);
-void ble_att_read_type_rsp_parse(void *payload, int len,
+ const struct ble_att_read_type_req *req);
+void ble_att_read_type_req_log(const struct ble_att_read_type_req *cmd);
+void ble_att_read_type_rsp_parse(const void *payload, int len,
struct ble_att_read_type_rsp *rsp);
void ble_att_read_type_rsp_write(void *payload, int len,
- struct ble_att_read_type_rsp *rsp);
-void ble_att_read_type_rsp_log(struct ble_att_read_type_rsp *cmd);
-void ble_att_read_req_parse(void *payload, int len,
+ const struct ble_att_read_type_rsp *rsp);
+void ble_att_read_type_rsp_log(const struct ble_att_read_type_rsp *cmd);
+void ble_att_read_req_parse(const void *payload, int len,
struct ble_att_read_req *req);
void ble_att_read_req_write(void *payload, int len,
- struct ble_att_read_req *req);
-void ble_att_read_req_log(struct ble_att_read_req *cmd);
-void ble_att_read_blob_req_parse(void *payload, int len,
+ const struct ble_att_read_req *req);
+void ble_att_read_req_log(const struct ble_att_read_req *cmd);
+void ble_att_read_blob_req_parse(const void *payload, int len,
struct ble_att_read_blob_req *req);
void ble_att_read_blob_req_write(void *payload, int len,
- struct ble_att_read_blob_req *req);
-void ble_att_read_blob_req_log(struct ble_att_read_blob_req *cmd);
-void ble_att_read_mult_req_parse(void *payload, int len);
+ const struct ble_att_read_blob_req *req);
+void ble_att_read_blob_req_log(const struct ble_att_read_blob_req *cmd);
+void ble_att_read_mult_req_parse(const void *payload, int len);
void ble_att_read_mult_req_write(void *payload, int len);
-void ble_att_read_mult_rsp_parse(void *payload, int len);
+void ble_att_read_mult_rsp_parse(const void *payload, int len);
void ble_att_read_mult_rsp_write(void *payload, int len);
void ble_att_read_group_type_req_parse(
- void *payload, int len, struct ble_att_read_group_type_req *req);
+ const void *payload, int len, struct ble_att_read_group_type_req *req);
void ble_att_read_group_type_req_write(
- void *payload, int len, struct ble_att_read_group_type_req *req);
-void ble_att_read_group_type_req_log(struct ble_att_read_group_type_req *cmd);
+ void *payload, int len, const struct ble_att_read_group_type_req *req);
+void ble_att_read_group_type_req_log(
+ const struct ble_att_read_group_type_req *cmd);
void ble_att_read_group_type_rsp_parse(
- void *payload, int len, struct ble_att_read_group_type_rsp *rsp);
+ const void *payload, int len, struct ble_att_read_group_type_rsp *rsp);
void ble_att_read_group_type_rsp_write(
- void *payload, int len, struct ble_att_read_group_type_rsp *rsp);
-void ble_att_read_group_type_rsp_log(struct ble_att_read_group_type_rsp *cmd);
-void ble_att_write_req_parse(void *payload, int len,
+ void *payload, int len, const struct ble_att_read_group_type_rsp *rsp);
+void ble_att_read_group_type_rsp_log(
+ const struct ble_att_read_group_type_rsp *cmd);
+void ble_att_write_req_parse(const void *payload, int len,
struct ble_att_write_req *req);
void ble_att_write_req_write(void *payload, int len,
- struct ble_att_write_req *req);
-void ble_att_write_cmd_parse(void *payload, int len,
+ const struct ble_att_write_req *req);
+void ble_att_write_cmd_parse(const void *payload, int len,
struct ble_att_write_req *req);
void ble_att_write_cmd_write(void *payload, int len,
- struct ble_att_write_req *req);
-void ble_att_write_cmd_log(struct ble_att_write_req *cmd);
-void ble_att_prep_write_req_parse(void *payload, int len,
+ const struct ble_att_write_req *req);
+void ble_att_write_cmd_log(const struct ble_att_write_req *cmd);
+void ble_att_prep_write_req_parse(const void *payload, int len,
struct ble_att_prep_write_cmd *cmd);
void ble_att_prep_write_req_write(void *payload, int len,
- struct ble_att_prep_write_cmd *cmd);
-void ble_att_prep_write_cmd_log(struct ble_att_prep_write_cmd *cmd);
-void ble_att_prep_write_rsp_parse(void *payload, int len,
+ const struct ble_att_prep_write_cmd *cmd);
+void ble_att_prep_write_cmd_log(const struct ble_att_prep_write_cmd *cmd);
+void ble_att_prep_write_rsp_parse(const void *payload, int len,
struct ble_att_prep_write_cmd *cmd);
void ble_att_prep_write_rsp_write(void *payload, int len,
- struct ble_att_prep_write_cmd *cmd);
-void ble_att_exec_write_req_parse(void *payload, int len,
+ const struct ble_att_prep_write_cmd *cmd);
+void ble_att_exec_write_req_parse(const void *payload, int len,
struct ble_att_exec_write_req *req);
-void ble_att_exec_write_req_log(struct ble_att_exec_write_req *cmd);
+void ble_att_exec_write_req_log(const struct ble_att_exec_write_req *cmd);
void ble_att_exec_write_req_write(void *payload, int len,
- struct ble_att_exec_write_req *req);
-void ble_att_exec_write_rsp_parse(void *payload, int len);
+ const struct ble_att_exec_write_req *req);
+void ble_att_exec_write_rsp_parse(const void *payload, int len);
void ble_att_exec_write_rsp_write(void *payload, int len);
-void ble_att_notify_req_parse(void *payload, int len,
+void ble_att_notify_req_parse(const void *payload, int len,
struct ble_att_notify_req *req);
void ble_att_notify_req_write(void *payload, int len,
- struct ble_att_notify_req *req);
-void ble_att_notify_req_log(struct ble_att_notify_req *cmd);
-void ble_att_indicate_req_parse(void *payload, int len,
+ const struct ble_att_notify_req *req);
+void ble_att_notify_req_log(const struct ble_att_notify_req *cmd);
+void ble_att_indicate_req_parse(const void *payload, int len,
struct ble_att_indicate_req *req);
void ble_att_indicate_req_write(void *payload, int len,
- struct ble_att_indicate_req *req);
-void ble_att_indicate_rsp_parse(void *payload, int len);
+ const struct ble_att_indicate_req *req);
+void ble_att_indicate_rsp_parse(const void *payload, int len);
void ble_att_indicate_rsp_write(void *payload, int len);
-void ble_att_indicate_req_log(struct ble_att_indicate_req *cmd);
+void ble_att_indicate_req_log(const struct ble_att_indicate_req *cmd);
#endif
diff --git a/net/nimble/host/src/ble_att_priv.h b/net/nimble/host/src/ble_att_priv.h
index f908b9c1..ee9a9e98 100644
--- a/net/nimble/host/src/ble_att_priv.h
+++ b/net/nimble/host/src/ble_att_priv.h
@@ -100,10 +100,6 @@ STATS_SECT_START(ble_att_stats)
STATS_SECT_END
extern STATS_SECT_DECL(ble_att_stats) ble_att_stats;
-#define BLE_ATT_MTU_DFLT 23 /* Also the minimum. */
-#define BLE_ATT_MTU_MAX 240
-#define BLE_ATT_MTU_PREFERRED_DFLT 240
-
struct ble_att_prep_entry {
SLIST_ENTRY(ble_att_prep_entry) bape_next;
uint16_t bape_handle;
@@ -123,6 +119,29 @@ struct ble_att_svr_conn {
uint32_t basc_prep_write_rx_time;
};
+/**
+ * Handles a host attribute request.
+ *
+ * @param entry The host attribute being requested.
+ * @param op The operation being performed on the attribute.
+ * @param arg The request data associated with that host
+ * attribute.
+ *
+ * @return 0 on success;
+ * One of the BLE_ATT_ERR_[...] codes on
+ * failure.
+ */
+typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg);
+
+int ble_att_svr_register(const uint8_t *uuid, uint8_t flags,
+ uint16_t *handle_id,
+ ble_att_svr_access_fn *cb, void *cb_arg);
+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);
+
struct ble_att_svr_entry {
STAILQ_ENTRY(ble_att_svr_entry) ha_next;
@@ -139,11 +158,11 @@ SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry);
/*** @gen */
struct ble_l2cap_chan *ble_att_create_chan(void);
-int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
- struct ble_l2cap_chan **out_chan);
+void ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
+ struct ble_l2cap_chan **out_chan);
void ble_att_inc_tx_stat(uint8_t att_op);
-uint8_t *ble_att_get_flat_buf(void);
-uint16_t ble_att_mtu(uint16_t conn_handle);
+void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan,
+ struct os_mbuf *txom);
void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu);
int ble_att_init(void);
@@ -156,9 +175,12 @@ int ble_att_init(void);
/*** @svr */
struct ble_att_svr_entry *
-ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, uint8_t *uuid);
+ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at,
+ const uint8_t *uuid,
+ uint16_t end_handle);
uint16_t ble_att_svr_prev_handle(void);
-int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **om);
+int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom);
+struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id);
int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_svr_rx_find_type_value(uint16_t conn_handle,
struct os_mbuf **rxom);
@@ -185,7 +207,7 @@ int ble_att_svr_rx_indicate(uint16_t conn_handle,
struct os_mbuf **rxom);
void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list);
int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint16_t offset, struct os_mbuf *om,
uint8_t *out_att_err);
int ble_att_svr_init(void);
@@ -209,6 +231,7 @@ struct ble_att_read_type_adata {
uint16_t att_handle;
int value_len;
uint8_t *value;
+
};
/** An attribute-data entry in a read by group type response. */
@@ -220,53 +243,55 @@ struct ble_att_read_group_type_adata {
};
int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom);
-int ble_att_clt_tx_mtu(uint16_t conn_handle, struct ble_att_mtu_cmd *req);
+int ble_att_clt_tx_mtu(uint16_t conn_handle,
+ const struct ble_att_mtu_cmd *req);
int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom);
-int ble_att_clt_tx_read(uint16_t conn_handle, struct ble_att_read_req *req);
+int ble_att_clt_tx_read(uint16_t conn_handle,
+ const struct ble_att_read_req *req);
int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_blob(uint16_t conn_handle,
- struct ble_att_read_blob_req *req);
+ const struct ble_att_read_blob_req *req);
int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_mult(uint16_t conn_handle,
- uint16_t *handles, int num_handles);
+ const uint16_t *handles, int num_handles);
int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_type(uint16_t conn_handle,
- struct ble_att_read_type_req *req,
- void *uuid128);
+ const struct ble_att_read_type_req *req,
+ const void *uuid128);
int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom);
-int ble_att_clt_tx_read_group_type(uint16_t conn_handle,
- struct ble_att_read_group_type_req *req,
- void *uuid128);
+int ble_att_clt_tx_read_group_type(
+ uint16_t conn_handle, const struct ble_att_read_group_type_req *req,
+ const void *uuid128);
int ble_att_clt_rx_read_group_type(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_clt_tx_find_info(uint16_t conn_handle,
- struct ble_att_find_info_req *req);
-int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om);
-int ble_att_clt_tx_find_type_value(uint16_t conn_handle,
- struct ble_att_find_type_value_req *req,
- void *attribute_value, int value_len);
+ const struct ble_att_find_info_req *req);
+int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom);
+int ble_att_clt_tx_find_type_value(
+ uint16_t conn_handle, const struct ble_att_find_type_value_req *req,
+ const void *attribute_value, int value_len);
int ble_att_clt_rx_find_type_value(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_clt_tx_write_req(uint16_t conn_handle,
- struct ble_att_write_req *req,
- void *value, uint16_t value_len);
+ const struct ble_att_write_req *req,
+ struct os_mbuf *txom);
int ble_att_clt_tx_write_cmd(uint16_t conn_handle,
- struct ble_att_write_req *req,
- void *value, uint16_t value_len);
+ const struct ble_att_write_req *req,
+ struct os_mbuf *txom);
int ble_att_clt_tx_prep_write(uint16_t conn_handle,
- struct ble_att_prep_write_cmd *req,
- void *value, uint16_t value_len);
+ const struct ble_att_prep_write_cmd *req,
+ struct os_mbuf *txom);
int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_exec_write(uint16_t conn_handle,
- struct ble_att_exec_write_req *req);
+ const struct ble_att_exec_write_req *req);
int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_notify(uint16_t conn_handle,
- struct ble_att_notify_req *req,
- void *value, uint16_t value_len);
+ const struct ble_att_notify_req *req,
+ struct os_mbuf *txom);
int ble_att_clt_tx_indicate(uint16_t conn_handle,
- struct ble_att_indicate_req *req,
- void *value, uint16_t value_len);
+ const struct ble_att_indicate_req *req,
+ struct os_mbuf *txom);
int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom);
#endif
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 1017fc8e..5d64c25b 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -25,7 +25,9 @@
#include "host/ble_uuid.h"
#include "ble_hs_priv.h"
-static STAILQ_HEAD(, ble_att_svr_entry) ble_att_svr_list;
+STAILQ_HEAD(ble_att_svr_entry_list, ble_att_svr_entry);
+static struct ble_att_svr_entry_list ble_att_svr_list;
+
static uint16_t ble_att_svr_id;
static void *ble_att_svr_entry_mem;
@@ -72,7 +74,7 @@ ble_att_svr_next_id(void)
* @return 0 on success, non-zero error code on failure.
*/
int
-ble_att_svr_register(uint8_t *uuid, uint8_t flags, uint16_t *handle_id,
+ble_att_svr_register(const uint8_t *uuid, uint8_t flags, uint16_t *handle_id,
ble_att_svr_access_fn *cb, void *cb_arg)
{
struct ble_att_svr_entry *entry;
@@ -159,7 +161,7 @@ ble_att_svr_find_by_handle(uint16_t handle_id)
* Find a host attribute by UUID.
*
* @param uuid The ble_uuid_t to search for
- * @param ha_ptr On input: Indicates the starting point of the
+ * @param prev On input: Indicates the starting point of the
* walk; null means start at the beginning of
* the list, non-null means start at the
* following entry.
@@ -170,7 +172,8 @@ ble_att_svr_find_by_handle(uint16_t handle_id)
* @return 0 on success; BLE_HS_ENOENT on not found.
*/
struct ble_att_svr_entry *
-ble_att_svr_find_by_uuid(struct ble_att_svr_entry *prev, uint8_t *uuid)
+ble_att_svr_find_by_uuid(struct ble_att_svr_entry *prev, const uint8_t *uuid,
+ uint16_t end_handle)
{
struct ble_att_svr_entry *entry;
@@ -180,7 +183,10 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *prev, uint8_t *uuid)
entry = STAILQ_NEXT(prev, ha_next);
}
- for (; entry != NULL; entry = STAILQ_NEXT(entry, ha_next)) {
+ for (;
+ entry != NULL && entry->ha_handle_id <= end_handle;
+ entry = STAILQ_NEXT(entry, ha_next)) {
+
if (memcmp(entry->ha_uuid, uuid, sizeof entry->ha_uuid) == 0) {
return entry;
}
@@ -196,7 +202,7 @@ ble_att_svr_pullup_req_base(struct os_mbuf **om, int base_len,
uint8_t att_err;
int rc;
- rc = ble_hs_misc_pullup_base(om, base_len);
+ rc = ble_hs_mbuf_pullup_base(om, base_len);
if (rc == BLE_HS_ENOMEM) {
att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
} else {
@@ -210,42 +216,45 @@ ble_att_svr_pullup_req_base(struct os_mbuf **om, int base_len,
return rc;
}
-static int
+static void
ble_att_svr_get_sec_state(uint16_t conn_handle,
struct ble_gap_sec_state *out_sec_state)
{
struct ble_hs_conn *conn;
ble_hs_lock();
- conn = ble_hs_conn_find(conn_handle);
- if (conn != NULL) {
- *out_sec_state = conn->bhc_sec_state;
- }
- ble_hs_unlock();
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
- } else {
- return 0;
- }
+ conn = ble_hs_conn_find_assert(conn_handle);
+ *out_sec_state = conn->bhc_sec_state;
+
+ ble_hs_unlock();
}
static int
-ble_att_svr_check_security(uint16_t conn_handle, int is_read,
- struct ble_att_svr_entry *entry,
- uint8_t *out_att_err)
+ble_att_svr_check_perms(uint16_t conn_handle, int is_read,
+ struct ble_att_svr_entry *entry,
+ uint8_t *out_att_err)
{
struct ble_gap_sec_state sec_state;
int author;
int authen;
int enc;
- int rc;
if (is_read) {
+ if (!(entry->ha_flags & BLE_ATT_F_READ)) {
+ *out_att_err = BLE_ATT_ERR_READ_NOT_PERMITTED;
+ return BLE_HS_ENOTSUP;
+ }
+
enc = entry->ha_flags & BLE_ATT_F_READ_ENC;
authen = entry->ha_flags & BLE_ATT_F_READ_AUTHEN;
author = entry->ha_flags & BLE_ATT_F_READ_AUTHOR;
} else {
+ if (!(entry->ha_flags & BLE_ATT_F_WRITE)) {
+ *out_att_err = BLE_ATT_ERR_WRITE_NOT_PERMITTED;
+ return BLE_HS_ENOTSUP;
+ }
+
enc = entry->ha_flags & BLE_ATT_F_WRITE_ENC;
authen = entry->ha_flags & BLE_ATT_F_WRITE_AUTHEN;
author = entry->ha_flags & BLE_ATT_F_WRITE_AUTHOR;
@@ -256,21 +265,17 @@ ble_att_svr_check_security(uint16_t conn_handle, int is_read,
return 0;
}
- rc = ble_att_svr_get_sec_state(conn_handle, &sec_state);
- if (rc != 0) {
- return rc;
- }
-
+ ble_att_svr_get_sec_state(conn_handle, &sec_state);
if (enc && !sec_state.encrypted) {
/* XXX: Check security database; if required key present, respond with
* insufficient encryption error code.
*/
- *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHENT;
+ *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHEN;
return BLE_HS_ATT_ERR(*out_att_err);
}
if (authen && !sec_state.authenticated) {
- *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHENT;
+ *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHEN;
return BLE_HS_ATT_ERR(*out_att_err);
}
@@ -284,7 +289,8 @@ ble_att_svr_check_security(uint16_t conn_handle, int is_read,
static int
ble_att_svr_read(uint16_t conn_handle,
struct ble_att_svr_entry *entry,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint16_t offset,
+ struct os_mbuf *om,
uint8_t *out_att_err)
{
uint8_t att_err;
@@ -293,13 +299,7 @@ ble_att_svr_read(uint16_t conn_handle,
att_err = 0; /* Silence gcc warning. */
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- if (!(entry->ha_flags & BLE_ATT_F_READ)) {
- att_err = BLE_ATT_ERR_READ_NOT_PERMITTED;
- rc = BLE_HS_ENOTSUP;
- goto err;
- }
-
- rc = ble_att_svr_check_security(conn_handle, 1, entry, &att_err);
+ rc = ble_att_svr_check_perms(conn_handle, 1, entry, &att_err);
if (rc != 0) {
goto err;
}
@@ -307,8 +307,7 @@ ble_att_svr_read(uint16_t conn_handle,
BLE_HS_DBG_ASSERT(entry->ha_cb != NULL);
rc = entry->ha_cb(conn_handle, entry->ha_handle_id,
- entry->ha_uuid, BLE_ATT_ACCESS_OP_READ, ctxt,
- entry->ha_cb_arg);
+ BLE_ATT_ACCESS_OP_READ, offset, &om, entry->ha_cb_arg);
if (rc != 0) {
att_err = rc;
rc = BLE_HS_EAPP;
@@ -324,9 +323,51 @@ err:
return rc;
}
+static int
+ble_att_svr_read_flat(uint16_t conn_handle,
+ struct ble_att_svr_entry *entry,
+ uint16_t offset,
+ uint16_t max_len,
+ void *dst,
+ uint16_t *out_len,
+ uint8_t *out_att_err)
+{
+ struct os_mbuf *om;
+ uint16_t len;
+ int rc;
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ if (om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ rc = ble_att_svr_read(conn_handle, entry, offset, om, out_att_err);
+ if (rc != 0) {
+ goto done;
+ }
+
+ len = OS_MBUF_PKTLEN(om);
+ if (len > max_len) {
+ rc = BLE_HS_EMSGSIZE;
+ *out_att_err = BLE_ATT_ERR_UNLIKELY;
+ goto done;
+ }
+
+ rc = os_mbuf_copydata(om, 0, len, dst);
+ BLE_HS_DBG_ASSERT(rc == 0);
+
+ *out_len = len;
+ rc = 0;
+
+done:
+ os_mbuf_free_chain(om);
+ return rc;
+}
+
int
ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint16_t offset, struct os_mbuf *om,
uint8_t *out_att_err)
{
struct ble_att_svr_entry *entry;
@@ -340,7 +381,7 @@ ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
return BLE_HS_ENOENT;
}
- rc = ble_att_svr_read(conn_handle, entry, ctxt, out_att_err);
+ rc = ble_att_svr_read(conn_handle, entry, offset, om, out_att_err);
if (rc != 0) {
return rc;
}
@@ -348,30 +389,51 @@ ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
return 0;
}
+/**
+ * Reads a locally registered attribute. If the specified attribute handle
+ * coresponds to a GATT characteristic value or descriptor, the read is
+ * performed by calling the registered GATT access callback.
+ *
+ * @param attr_handle The 16-bit handle of the attribute to read.
+ * @param out_om On success, this is made to point to a
+ * newly-allocated mbuf containing the
+ * attribute data read.
+ *
+ * @return 0 on success;
+ * NimBLE host ATT return code if the attribute
+ * access callback reports failure;
+ * NimBLE host core return code on unexpected
+ * error.
+ */
int
-ble_att_svr_read_local(uint16_t attr_handle, void **out_data,
- uint16_t *out_attr_len)
+ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om)
{
- struct ble_att_svr_access_ctxt ctxt;
+ struct os_mbuf *om;
int rc;
- ctxt.offset = 0;
+ om = ble_hs_mbuf_bare_pkt();
+ if (om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
- rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, attr_handle, &ctxt,
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, attr_handle, 0, om,
NULL);
if (rc != 0) {
- return rc;
+ goto err;
}
- *out_attr_len = ctxt.data_len;
- *out_data = ctxt.attr_data;
-
+ *out_om = om;
return 0;
+
+err:
+ os_mbuf_free_chain(om);
+ return rc;
}
static int
ble_att_svr_write(uint16_t conn_handle, struct ble_att_svr_entry *entry,
- struct ble_att_svr_access_ctxt *ctxt, uint8_t *out_att_err)
+ uint16_t offset, struct os_mbuf **om, uint8_t *out_att_err)
{
uint8_t att_err;
int rc;
@@ -379,31 +441,22 @@ ble_att_svr_write(uint16_t conn_handle, struct ble_att_svr_entry *entry,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- if (!(entry->ha_flags & BLE_ATT_F_WRITE)) {
- att_err = BLE_ATT_ERR_WRITE_NOT_PERMITTED;
- rc = BLE_HS_ENOTSUP;
- goto err;
- }
-
- rc = ble_att_svr_check_security(conn_handle, 0, entry, &att_err);
+ rc = ble_att_svr_check_perms(conn_handle, 0, entry, &att_err);
if (rc != 0) {
- goto err;
+ goto done;
}
}
BLE_HS_DBG_ASSERT(entry->ha_cb != NULL);
rc = entry->ha_cb(conn_handle, entry->ha_handle_id,
- entry->ha_uuid, BLE_ATT_ACCESS_OP_WRITE, ctxt,
- entry->ha_cb_arg);
+ BLE_ATT_ACCESS_OP_WRITE, offset, om, entry->ha_cb_arg);
if (rc != 0) {
att_err = rc;
rc = BLE_HS_EAPP;
- goto err;
+ goto done;
}
- return 0;
-
-err:
+done:
if (out_att_err != NULL) {
*out_att_err = att_err;
}
@@ -412,7 +465,7 @@ err:
static int
ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint16_t offset, struct os_mbuf **om,
uint8_t *out_att_err)
{
struct ble_att_svr_entry *entry;
@@ -420,11 +473,13 @@ ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle,
entry = ble_att_svr_find_by_handle(attr_handle);
if (entry == NULL) {
- *out_att_err = BLE_ATT_ERR_INVALID_HANDLE;
+ if (out_att_err != NULL) {
+ *out_att_err = BLE_ATT_ERR_INVALID_HANDLE;
+ }
return BLE_HS_ENOENT;
}
- rc = ble_att_svr_write(conn_handle, entry, ctxt, out_att_err);
+ rc = ble_att_svr_write(conn_handle, entry, offset, om, out_att_err);
if (rc != 0) {
return rc;
}
@@ -434,20 +489,15 @@ ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle,
static int
ble_att_svr_tx_error_rsp(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- uint8_t req_op, uint16_t handle, uint8_t error_code)
+ struct os_mbuf *txom, uint8_t req_op,
+ uint16_t handle, uint8_t error_code)
{
struct ble_att_error_rsp rsp;
- struct os_mbuf *txom;
void *dst;
int rc;
BLE_HS_DBG_ASSERT(error_code != 0);
-
- txom = ble_hs_misc_pkthdr();
- if (txom == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
- }
+ BLE_HS_DBG_ASSERT(OS_MBUF_PKTLEN(txom) == 0);
dst = os_mbuf_extend(txom, BLE_ATT_ERROR_RSP_SZ);
if (dst == NULL) {
@@ -460,8 +510,6 @@ ble_att_svr_tx_error_rsp(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
rsp.baep_error_code = error_code;
ble_att_error_rsp_write(dst, BLE_ATT_ERROR_RSP_SZ, &rsp);
- BLE_ATT_LOG_CMD(1, "error rsp", conn->bhc_handle,
- ble_att_error_rsp_log, &rsp);
rc = ble_l2cap_tx(conn, chan, txom);
txom = NULL;
@@ -469,6 +517,9 @@ ble_att_svr_tx_error_rsp(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
goto err;
}
+ BLE_ATT_LOG_CMD(1, "error rsp", conn->bhc_handle,
+ ble_att_error_rsp_log, &rsp);
+
return 0;
err:
@@ -479,10 +530,10 @@ err:
/**
* Transmits a response or error message over the specified connection.
*
- * The specified rc value controls what gets sent as follows:
+ * The specified rc and err_status values control what gets sent as follows:
* o If rc == 0: tx an affirmative response.
- * o If rc == BLE_HS_ENOTCONN: tx nothing.
- * o Else: tx an error response.
+ * o Else if err_status != 0: tx an error response.
+ * o Else: tx nothing.
*
* In addition, if transmission of an affirmative response fails, an error is
* sent instead.
@@ -500,17 +551,14 @@ err:
* field.
*/
static int
-ble_att_svr_tx_rsp(uint16_t conn_handle, int rc, struct os_mbuf *txom,
+ble_att_svr_tx_rsp(uint16_t conn_handle, int rc, struct os_mbuf *om,
uint8_t att_op, uint8_t err_status, uint16_t err_handle)
{
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
int do_tx;
- if (rc == BLE_HS_ENOTCONN) {
- /* No connection; tx is not possible. */
- do_tx = 0;
- } else if (rc != 0 && err_status == 0) {
+ if (rc != 0 && err_status == 0) {
/* Processing failed, but err_status of 0 means don't send error. */
do_tx = 0;
} else {
@@ -521,30 +569,41 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int rc, struct os_mbuf *txom,
ble_hs_lock();
ble_att_conn_chan_find(conn_handle, &conn, &chan);
- if (chan == NULL) {
- rc = BLE_HS_ENOTCONN;
- } else {
- if (rc == 0) {
- BLE_HS_DBG_ASSERT(txom != NULL);
- ble_att_inc_tx_stat(txom->om_data[0]);
- rc = ble_l2cap_tx(conn, chan, txom);
- txom = NULL;
- if (rc != 0) {
- err_status = BLE_ATT_ERR_UNLIKELY;
- }
- }
+ BLE_HS_DBG_ASSERT(chan != NULL);
+ if (rc == 0) {
+ BLE_HS_DBG_ASSERT(om != NULL);
+
+ ble_att_inc_tx_stat(om->om_data[0]);
+ ble_att_truncate_to_mtu(chan, om);
+ rc = ble_l2cap_tx(conn, chan, om);
+ om = NULL;
if (rc != 0) {
- STATS_INC(ble_att_stats, error_rsp_tx);
- ble_att_svr_tx_error_rsp(conn, chan, att_op,
+ err_status = BLE_ATT_ERR_UNLIKELY;
+ }
+ }
+
+ if (rc != 0) {
+ STATS_INC(ble_att_stats, error_rsp_tx);
+
+ /* Reuse om for error response. */
+ if (om == NULL) {
+ om = ble_hs_mbuf_l2cap_pkt();
+ } else {
+ os_mbuf_adj(om, OS_MBUF_PKTLEN(om));
+ }
+ if (om != NULL) {
+ ble_att_svr_tx_error_rsp(conn, chan, om, att_op,
err_handle, err_status);
+ om = NULL;
}
}
ble_hs_unlock();
}
- os_mbuf_free_chain(txom);
+ /* Free mbuf if it was not consumed (i.e., if the send failed). */
+ os_mbuf_free_chain(om);
return rc;
}
@@ -564,17 +623,11 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **out_txom,
txom = NULL;
ble_hs_lock();
- rc = ble_att_conn_chan_find(conn_handle, NULL, &chan);
- if (rc == 0) {
- mtu = chan->blc_my_mtu;
- }
+ ble_att_conn_chan_find(conn_handle, NULL, &chan);
+ mtu = chan->blc_my_mtu;
ble_hs_unlock();
- if (rc != 0) {
- goto done;
- }
-
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -601,23 +654,24 @@ done:
}
int
-ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **om)
+ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
{
struct ble_att_mtu_cmd cmd;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
struct os_mbuf *txom;
+ uint16_t mtu;
uint8_t att_err;
int rc;
txom = NULL;
- rc = ble_att_svr_pullup_req_base(om, BLE_ATT_MTU_CMD_SZ, &att_err);
+ rc = ble_att_svr_pullup_req_base(rxom, BLE_ATT_MTU_CMD_SZ, &att_err);
if (rc != 0) {
goto done;
}
- ble_att_mtu_cmd_parse((*om)->om_data, (*om)->om_len, &cmd);
+ ble_att_mtu_req_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
BLE_ATT_LOG_CMD(0, "mtu req", conn_handle, ble_att_mtu_cmd_log, &cmd);
rc = ble_att_svr_build_mtu_rsp(conn_handle, &txom, &att_err);
@@ -632,12 +686,15 @@ done:
att_err, 0);
if (rc == 0) {
ble_hs_lock();
+
ble_att_conn_chan_find(conn_handle, &conn, &chan);
- if (chan != NULL) {
- ble_att_set_peer_mtu(chan, cmd.bamc_mtu);
- chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
- }
+ ble_att_set_peer_mtu(chan, cmd.bamc_mtu);
+ chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
+ mtu = ble_l2cap_chan_mtu(chan);
+
ble_hs_unlock();
+
+ ble_gap_mtu_event(conn_handle, BLE_L2CAP_CID_ATT, mtu);
}
return rc;
}
@@ -754,12 +811,8 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle,
txom = NULL;
mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -777,8 +830,6 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle,
}
ble_att_find_info_rsp_write(buf, BLE_ATT_FIND_INFO_RSP_BASE_SZ, &rsp);
- BLE_ATT_LOG_CMD(1, "find info rsp", conn_handle, ble_att_find_info_rsp_log,
- &rsp);
/* Write the variable length Information Data field, populating the format
* field as appropriate.
@@ -790,6 +841,9 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle,
goto done;
}
+ BLE_ATT_LOG_CMD(1, "find info rsp", conn_handle, ble_att_find_info_rsp_log,
+ &rsp);
+
rc = 0;
done:
@@ -986,8 +1040,9 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
struct os_mbuf *rxom, struct os_mbuf *txom,
uint16_t mtu, uint8_t *out_att_err)
{
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_svr_entry *ha;
+ uint8_t buf[16];
+ uint16_t attr_len;
uint16_t uuid16;
uint16_t first;
uint16_t prev;
@@ -1016,13 +1071,13 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
*/
uuid16 = ble_uuid_128_to_16(ha->ha_uuid);
if (uuid16 == req->bavq_attr_type) {
- ctxt.offset = 0;
- rc = ble_att_svr_read(conn_handle, ha, &ctxt, out_att_err);
+ rc = ble_att_svr_read_flat(conn_handle, ha, 0, sizeof buf, buf,
+ &attr_len, out_att_err);
if (rc != 0) {
goto done;
}
- rc = os_mbuf_memcmp(rxom, BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ,
- ctxt.attr_data, ctxt.data_len);
+ rc = os_mbuf_cmpf(rxom, BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ,
+ buf, attr_len);
if (rc == 0) {
match = 1;
}
@@ -1075,7 +1130,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle,
uint8_t *buf;
int rc;
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*out_att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -1093,10 +1148,6 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle,
/* Write the variable length Information Data field. */
mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
rc = ble_att_svr_fill_type_value(conn_handle, req, rxom, txom, mtu,
out_att_err);
@@ -1179,15 +1230,15 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
uint16_t *err_handle)
{
struct ble_att_read_type_rsp rsp;
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_svr_entry *entry;
struct os_mbuf *txom;
+ uint16_t attr_len;
uint16_t mtu;
+ uint8_t buf[19];
uint8_t *dptr;
int entry_written;
int txomlen;
int prev_attr_len;
- int attr_len;
int rc;
*att_err = 0; /* Silence unnecessary warning. */
@@ -1197,11 +1248,8 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
prev_attr_len = 0;
mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- return BLE_HS_ENOTCONN;
- }
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
*err_handle = 0;
@@ -1223,28 +1271,22 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
/* Find all matching attributes, writing a record for each. */
entry = NULL;
while (1) {
- entry = ble_att_svr_find_by_uuid(entry, uuid128);
+ entry = ble_att_svr_find_by_uuid(entry, uuid128, req->batq_end_handle);
if (entry == NULL) {
rc = BLE_HS_ENOENT;
break;
}
- if (entry->ha_handle_id > req->batq_end_handle) {
- break;
- }
-
if (entry->ha_handle_id >= req->batq_start_handle) {
- ctxt.offset = 0;
- rc = ble_att_svr_read(conn_handle, entry, &ctxt, att_err);
+ rc = ble_att_svr_read_flat(conn_handle, entry, 0, sizeof buf, buf,
+ &attr_len, att_err);
if (rc != 0) {
*err_handle = entry->ha_handle_id;
goto done;
}
- if (ctxt.data_len > mtu - 4) {
+ if (attr_len > mtu - 4) {
attr_len = mtu - 4;
- } else {
- attr_len = ctxt.data_len;
}
if (prev_attr_len == 0) {
@@ -1267,7 +1309,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
}
htole16(dptr + 0, entry->ha_handle_id);
- memcpy(dptr + 2, ctxt.attr_data, attr_len);
+ memcpy(dptr + 2, buf, attr_len);
entry_written = 1;
}
}
@@ -1335,6 +1377,7 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom)
BLE_ATT_LOG_CMD(0, "read type req", conn_handle, ble_att_read_type_req_log,
&req);
+
if (req.batq_start_handle > req.batq_end_handle ||
req.batq_start_handle == 0) {
@@ -1381,64 +1424,6 @@ done:
return rc;
}
-/**
- * @return 0 on success; nonzero on failure.
- */
-static int
-ble_att_svr_build_read_rsp(uint16_t conn_handle, void *attr_data, int attr_len,
- struct os_mbuf **out_txom, uint8_t *att_err)
-{
- struct os_mbuf *txom;
- uint16_t data_len;
- uint16_t mtu;
- uint8_t op;
- int rc;
-
- txom = NULL;
-
- mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
-
- txom = ble_hs_misc_pkthdr();
- if (txom == NULL) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- rc = BLE_HS_ENOMEM;
- goto done;
- }
-
- op = BLE_ATT_OP_READ_RSP;
- rc = os_mbuf_append(txom, &op, 1);
- if (rc != 0) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- rc = BLE_HS_ENOMEM;
- goto done;
- }
-
- /* Vol. 3, part F, 3.2.9; don't send more than ATT_MTU-1 bytes of data. */
- if (attr_len > mtu - 1) {
- data_len = mtu - 1;
- } else {
- data_len = attr_len;
- }
-
- rc = os_mbuf_append(txom, attr_data, data_len);
- if (rc != 0) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- rc = BLE_HS_ENOMEM;
- goto done;
- }
-
- BLE_ATT_LOG_EMPTY_CMD(1, "read rsp", conn_handle);
- rc = 0;
-
-done:
- *out_txom = txom;
- return rc;
-}
-
int
ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
{
@@ -1446,11 +1431,11 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_read_req req;
struct os_mbuf *txom;
uint16_t err_handle;
uint8_t att_err;
+ uint8_t *dptr;
int rc;
/* Initialize some values in case of early error. */
@@ -1467,74 +1452,31 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
ble_att_read_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
BLE_ATT_LOG_CMD(0, "read req", conn_handle, ble_att_read_req_log, &req);
- ctxt.offset = 0;
- rc = ble_att_svr_read_handle(conn_handle, req.barq_handle, &ctxt,
- &att_err);
- if (rc != 0) {
- err_handle = req.barq_handle;
- goto done;
- }
-
- rc = ble_att_svr_build_read_rsp(conn_handle, ctxt.attr_data, ctxt.data_len,
- &txom, &att_err);
- if (rc != 0) {
- err_handle = req.barq_handle;
- goto done;
- }
-
- rc = 0;
-
-done:
- rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_REQ,
- att_err, err_handle);
- return rc;
-}
-
-/**
- * @return 0 on success; nonzero on failure.
- */
-static int
-ble_att_svr_build_read_blob_rsp(void *attr_data, int attr_len, uint16_t mtu,
- struct os_mbuf **out_txom, uint8_t *att_err)
-{
- struct os_mbuf *txom;
- uint16_t data_len;
- uint8_t op;
- int rc;
-
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+ att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
goto done;
}
- op = BLE_ATT_OP_READ_BLOB_RSP;
- rc = os_mbuf_append(txom, &op, 1);
- if (rc != 0) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+ dptr = os_mbuf_extend(txom, 1);
+ if (dptr == NULL) {
+ att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
goto done;
}
+ *dptr = BLE_ATT_OP_READ_RSP;
- /* Vol. 3, part F, 3.2.9; don't send more than ATT_MTU-1 bytes of data. */
- if (attr_len > mtu - 1) {
- data_len = mtu - 1;
- } else {
- data_len = attr_len;
- }
-
- rc = os_mbuf_append(txom, attr_data, data_len);
+ rc = ble_att_svr_read_handle(conn_handle, req.barq_handle, 0, txom,
+ &att_err);
if (rc != 0) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- rc = BLE_HS_ENOMEM;
+ err_handle = req.barq_handle;
goto done;
}
- rc = 0;
-
done:
- *out_txom = txom;
+ rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_REQ,
+ att_err, err_handle);
return rc;
}
@@ -1545,11 +1487,10 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_read_blob_req req;
struct os_mbuf *txom;
uint16_t err_handle;
- uint16_t mtu;
+ uint8_t *dptr;
uint8_t att_err;
int rc;
@@ -1558,12 +1499,6 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
att_err = 0;
err_handle = 0;
- mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
-
rc = ble_att_svr_pullup_req_base(rxom, BLE_ATT_READ_BLOB_REQ_SZ, &att_err);
if (rc != 0) {
err_handle = 0;
@@ -1574,27 +1509,28 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
BLE_ATT_LOG_CMD(0, "read blob req", conn_handle, ble_att_read_blob_req_log,
&req);
- ctxt.offset = req.babq_offset;
- rc = ble_att_svr_read_handle(conn_handle, req.babq_handle, &ctxt,
- &att_err);
- if (rc != 0) {
- err_handle = req.babq_handle;
+ txom = ble_hs_mbuf_l2cap_pkt();
+ if (txom == NULL) {
+ att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+ rc = BLE_HS_ENOMEM;
goto done;
}
- if (ctxt.offset + ctxt.data_len <= mtu - 3) {
- att_err = BLE_ATT_ERR_ATTR_NOT_LONG;
- err_handle = req.babq_handle;
- rc = BLE_HS_ENOTSUP;
+ dptr = os_mbuf_extend(txom, 1);
+ if (dptr == NULL) {
+ att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+ rc = BLE_HS_ENOMEM;
goto done;
}
+ *dptr = BLE_ATT_OP_READ_BLOB_RSP;
- rc = ble_att_svr_build_read_blob_rsp(ctxt.attr_data, ctxt.data_len, mtu,
- &txom, &att_err);
+ rc = ble_att_svr_read_handle(conn_handle, req.babq_handle, req.babq_offset,
+ txom, &att_err);
if (rc != 0) {
err_handle = req.babq_handle;
goto done;
}
+
BLE_ATT_LOG_EMPTY_CMD(1, "read blob rsp", conn_handle);
rc = 0;
@@ -1612,24 +1548,15 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle,
uint8_t *att_err,
uint16_t *err_handle)
{
- struct ble_att_svr_access_ctxt ctxt;
struct os_mbuf *txom;
- uint16_t chunk_sz;
- uint16_t tx_space;
uint16_t handle;
uint16_t mtu;
uint8_t *dptr;
int rc;
- txom = NULL;
-
mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
*err_handle = 0;
@@ -1646,13 +1573,11 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle,
}
ble_att_read_mult_rsp_write(dptr, BLE_ATT_READ_MULT_RSP_BASE_SZ);
- tx_space = mtu - OS_MBUF_PKTLEN(txom);
-
/* Iterate through requested handles, reading the corresponding attribute
* for each. Stop when there are no more handles to process, or the
* response is full.
*/
- while (OS_MBUF_PKTLEN(*rxom) >= 2 && tx_space > 0) {
+ while (OS_MBUF_PKTLEN(*rxom) >= 2 && OS_MBUF_PKTLEN(txom) < mtu) {
/* Ensure the full 16-bit handle is contiguous at the start of the
* mbuf.
*/
@@ -1668,28 +1593,11 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle,
handle = le16toh((*rxom)->om_data);
os_mbuf_adj(*rxom, 2);
- ctxt.offset = 0;
- rc = ble_att_svr_read_handle(conn_handle, handle, &ctxt, att_err);
+ rc = ble_att_svr_read_handle(conn_handle, handle, 0, txom, att_err);
if (rc != 0) {
*err_handle = handle;
goto done;
}
-
- if (ctxt.data_len > tx_space) {
- chunk_sz = tx_space;
- } else {
- chunk_sz = ctxt.data_len;
- }
-
- rc = os_mbuf_append(txom, ctxt.attr_data, chunk_sz);
- if (rc != 0) {
- *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- *err_handle = handle;
- rc = BLE_HS_ENOMEM;
- goto done;
- }
-
- tx_space -= chunk_sz;
}
BLE_ATT_LOG_EMPTY_CMD(1, "read mult rsp", conn_handle);
@@ -1760,23 +1668,22 @@ static int
ble_att_svr_service_uuid(struct ble_att_svr_entry *entry, uint16_t *uuid16,
uint8_t *uuid128)
{
- struct ble_att_svr_access_ctxt ctxt;
+ uint16_t attr_len;
int rc;
- ctxt.offset = 0;
- rc = ble_att_svr_read(BLE_HS_CONN_HANDLE_NONE, entry, &ctxt, NULL);
+ rc = ble_att_svr_read_flat(BLE_HS_CONN_HANDLE_NONE, entry, 0, 16, uuid128,
+ &attr_len, NULL);
if (rc != 0) {
return rc;
}
- switch (ctxt.data_len) {
+ switch (attr_len) {
case 16:
*uuid16 = 0;
- memcpy(uuid128, ctxt.attr_data, 16);
return 0;
case 2:
- *uuid16 = le16toh(ctxt.attr_data);
+ *uuid16 = le16toh(uuid128);
if (*uuid16 == 0) {
return BLE_HS_EINVAL;
}
@@ -1852,15 +1759,9 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle,
*att_err = 0;
*err_handle = req->bagq_start_handle;
- txom = NULL;
-
mtu = ble_att_mtu(conn_handle);
- if (mtu == 0) {
- rc = BLE_HS_ENOTCONN;
- goto done;
- }
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -2091,7 +1992,7 @@ ble_att_svr_build_write_rsp(struct os_mbuf **out_txom, uint8_t *att_err)
uint8_t *dst;
int rc;
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -2121,7 +2022,6 @@ ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_write_req req;
struct os_mbuf *txom;
uint16_t err_handle;
@@ -2147,10 +2047,7 @@ ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom)
/* Strip the request base from the front of the mbuf. */
os_mbuf_adj(*rxom, BLE_ATT_WRITE_REQ_BASE_SZ);
- ctxt.attr_data = ble_att_get_flat_buf();
- ctxt.data_len = OS_MBUF_PKTLEN(*rxom);
- os_mbuf_copydata(*rxom, 0, ctxt.data_len, ctxt.attr_data);
- rc = ble_att_svr_write_handle(conn_handle, req.bawq_handle, &ctxt,
+ rc = ble_att_svr_write_handle(conn_handle, req.bawq_handle, 0, rxom,
&att_err);
if (rc != 0) {
err_handle = req.bawq_handle;
@@ -2179,7 +2076,6 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_write_req req;
uint8_t att_err;
int rc;
@@ -2197,10 +2093,7 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom)
/* Strip the request base from the front of the mbuf. */
os_mbuf_adj(*rxom, BLE_ATT_WRITE_REQ_BASE_SZ);
- ctxt.attr_data = ble_att_get_flat_buf();
- ctxt.data_len = OS_MBUF_PKTLEN(*rxom);
- os_mbuf_copydata(*rxom, 0, ctxt.data_len, ctxt.attr_data);
- rc = ble_att_svr_write_handle(conn_handle, req.bawq_handle, &ctxt,
+ rc = ble_att_svr_write_handle(conn_handle, req.bawq_handle, 0, rxom,
&att_err);
if (rc != 0) {
return rc;
@@ -2209,18 +2102,31 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom)
return 0;
}
+/**
+ * Writes a locally registered attribute. This function consumes the supplied
+ * mbuf regardless of the outcome. If the specified attribute handle
+ * coresponds to a GATT characteristic value or descriptor, the write is
+ * performed by calling the registered GATT access callback.
+ *
+ * @param attr_handle The 16-bit handle of the attribute to write.
+ * @param om The value to write to the attribute.
+ *
+ * @return 0 on success;
+ * NimBLE host ATT return code if the attribute
+ * access callback reports failure;
+ * NimBLE host core return code on unexpected
+ * error.
+ */
int
-ble_att_svr_write_local(uint16_t attr_handle, void *data, uint16_t data_len)
+ble_att_svr_write_local(uint16_t attr_handle, struct os_mbuf *om)
{
- struct ble_att_svr_access_ctxt ctxt;
int rc;
- ctxt.attr_data = data;
- ctxt.data_len = data_len;
- ctxt.offset = 0;
+ rc = ble_att_svr_write_handle(BLE_HS_CONN_HANDLE_NONE, attr_handle, 0,
+ &om, NULL);
- rc = ble_att_svr_write_handle(BLE_HS_CONN_HANDLE_NONE, attr_handle, &ctxt,
- NULL);
+ /* Free the mbuf if it wasn't relinquished to the application. */
+ os_mbuf_free_chain(om);
return rc;
}
@@ -2228,8 +2134,10 @@ ble_att_svr_write_local(uint16_t attr_handle, void *data, uint16_t data_len)
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);
+ if (entry != NULL) {
+ os_mbuf_free_chain(entry->bape_value);
+ os_memblock_put(&ble_att_svr_prep_entry_pool, entry);
+ }
}
static struct ble_att_prep_entry *
@@ -2243,7 +2151,7 @@ ble_att_svr_prep_alloc(void)
}
memset(entry, 0, sizeof *entry);
- entry->bape_value = ble_hs_misc_pkthdr();
+ entry->bape_value = ble_hs_mbuf_l2cap_pkt();
if (entry->bape_value == NULL) {
ble_att_svr_prep_free(entry);
return NULL;
@@ -2327,6 +2235,42 @@ ble_att_svr_prep_validate(struct ble_att_prep_entry_list *prep_list,
return 0;
}
+static void
+ble_att_svr_prep_extract(struct ble_att_prep_entry_list *prep_list,
+ uint16_t *out_attr_handle,
+ struct os_mbuf **out_om)
+{
+ struct ble_att_prep_entry *entry;
+ struct ble_att_prep_entry *first;
+ struct os_mbuf *om;
+ uint16_t attr_handle;
+
+ BLE_HS_DBG_ASSERT(!SLIST_EMPTY(prep_list));
+
+ first = SLIST_FIRST(prep_list);
+ attr_handle = first->bape_handle;
+ om = NULL;
+
+ while ((entry = SLIST_FIRST(prep_list)) != NULL) {
+ if (entry->bape_handle != attr_handle) {
+ break;
+ }
+
+ if (om == NULL) {
+ om = entry->bape_value;
+ } else {
+ os_mbuf_concat(om, entry->bape_value);
+ }
+ entry->bape_value = NULL;
+
+ SLIST_REMOVE_HEAD(prep_list, bape_next);
+ ble_att_svr_prep_free(entry);
+ }
+
+ *out_attr_handle = attr_handle;
+ *out_om = om;
+}
+
/**
* @return 0 on success; ATT error code on failure.
*/
@@ -2335,13 +2279,10 @@ ble_att_svr_prep_write(uint16_t conn_handle,
struct ble_att_prep_entry_list *prep_list,
uint16_t *err_handle)
{
- struct ble_att_svr_access_ctxt ctxt;
- struct ble_att_prep_entry *entry;
- struct ble_att_prep_entry *next;
struct ble_att_svr_entry *attr;
- uint8_t *flat_buf;
+ struct os_mbuf *om;
+ uint16_t attr_handle;
uint8_t att_err;
- int buf_off;
int rc;
*err_handle = 0; /* Silence unnecessary warning. */
@@ -2352,40 +2293,68 @@ ble_att_svr_prep_write(uint16_t conn_handle,
return rc;
}
- flat_buf = ble_att_get_flat_buf();
-
/* Contents are valid; perform the writes. */
- buf_off = 0;
- entry = SLIST_FIRST(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),
- flat_buf + buf_off);
- BLE_HS_DBG_ASSERT_EVAL(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 = ble_att_svr_find_by_handle(entry->bape_handle);
- if (attr == NULL) {
- *err_handle = entry->bape_handle;
- return BLE_ATT_ERR_INVALID_HANDLE;
- }
+ while (!SLIST_EMPTY(prep_list)) {
+ ble_att_svr_prep_extract(prep_list, &attr_handle, &om);
- ctxt.attr_data = flat_buf;
- ctxt.data_len = buf_off;
- rc = ble_att_svr_write(conn_handle, attr, &ctxt, &att_err);
- if (rc != 0) {
- *err_handle = entry->bape_handle;
- return att_err;
- }
+ /* Attribute existence was verified during prepare-write request
+ * processing.
+ */
+ attr = ble_att_svr_find_by_handle(attr_handle);
+ BLE_HS_DBG_ASSERT(attr != NULL);
- buf_off = 0;
+ rc = ble_att_svr_write(conn_handle, attr, 0, &om, &att_err);
+ os_mbuf_free_chain(om);
+ if (rc != 0) {
+ *err_handle = attr_handle;
+ return att_err;
}
+ }
+
+ return 0;
+}
- entry = next;
+static int
+ble_att_svr_insert_prep_entry(uint16_t conn_handle,
+ const struct ble_att_prep_write_cmd *req,
+ const struct os_mbuf *rxom,
+ uint8_t *out_att_err)
+{
+ struct ble_att_prep_entry *prep_entry;
+ struct ble_att_prep_entry *prep_prev;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ conn = ble_hs_conn_find_assert(conn_handle);
+
+ prep_entry = ble_att_svr_prep_alloc();
+ if (prep_entry == NULL) {
+ *out_att_err = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
+ return BLE_HS_ENOMEM;
+ }
+ prep_entry->bape_handle = req->bapc_handle;
+ prep_entry->bape_offset = req->bapc_offset;
+
+ /* Append attribute value from request onto prep mbuf. */
+ rc = os_mbuf_appendfrom(
+ prep_entry->bape_value,
+ rxom,
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ OS_MBUF_PKTLEN(rxom) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ if (rc != 0) {
+ ble_att_svr_prep_free(prep_entry);
+ *out_att_err = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
+ return rc;
+ }
+
+ 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);
}
return 0;
@@ -2399,18 +2368,13 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom)
#endif
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 ble_hs_conn *conn;
- struct os_mbuf *srcom;
struct os_mbuf *txom;
uint16_t err_handle;
uint8_t att_err;
int rc;
/* Initialize some values in case of early error. */
- prep_entry = NULL;
txom = NULL;
att_err = 0;
err_handle = 0;
@@ -2425,115 +2389,55 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom)
ble_att_prep_write_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
BLE_ATT_LOG_CMD(0, "prep write req", conn_handle,
ble_att_prep_write_cmd_log, &req);
-
- /* Strip the request base from the front of the mbuf. */
- os_mbuf_adj(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ err_handle = req.bapc_handle;
attr_entry = ble_att_svr_find_by_handle(req.bapc_handle);
+
+ /* A prepare write request gets rejected for the following reasons:
+ * 1. Insufficient authorization.
+ * 2. Insufficient authentication.
+ * 3. Insufficient encryption key size (XXX: Not checked).
+ * 4. Insufficient encryption (XXX: Not checked).
+ * 5. Invalid handle.
+ * 6. Write not permitted.
+ */
+
+ /* <5> */
if (attr_entry == NULL) {
rc = BLE_HS_ENOENT;
att_err = BLE_ATT_ERR_INVALID_HANDLE;
- err_handle = req.bapc_handle;
goto done;
}
- prep_entry = ble_att_svr_prep_alloc();
- if (prep_entry == NULL) {
- att_err = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
- err_handle = req.bapc_handle;
- rc = BLE_HS_ENOMEM;
+ /* <1>, <2>, <4>, <6> */
+ rc = ble_att_svr_check_perms(conn_handle, 0, attr_entry, &att_err);
+ if (rc != 0) {
goto done;
}
- prep_entry->bape_handle = req.bapc_handle;
- prep_entry->bape_offset = req.bapc_offset;
ble_hs_lock();
-
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- rc = BLE_HS_ENOTCONN;
- } else {
- 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) {
- att_err = BLE_ATT_ERR_PREPARE_QUEUE_FULL;
- err_handle = req.bapc_handle;
- break;
- }
- }
- }
-
+ rc = ble_att_svr_insert_prep_entry(conn_handle, &req, *rxom, &att_err);
ble_hs_unlock();
if (rc != 0) {
goto done;
}
- /* The receive buffer now contains the attribute value. Repurpose this
- * buffer for the response. Prepend a response header.
+ /* Reuse rxom for response. Response is identical to request except for
+ * op code.
*/
- *rxom = os_mbuf_prepend(*rxom, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
- if (*rxom == NULL) {
- att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
- err_handle = req.bapc_handle;
- rc = BLE_HS_ENOMEM;
- goto done;
- }
txom = *rxom;
+ *rxom = NULL;
+ txom->om_data[0] = BLE_ATT_OP_PREP_WRITE_RSP;
- ble_att_prep_write_rsp_write(txom->om_data, BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
- &req);
BLE_ATT_LOG_CMD(1, "prep write rsp", conn_handle,
ble_att_prep_write_cmd_log, &req);
rc = 0;
done:
- if (rc != 0 && rc != BLE_HS_ENOTCONN) {
- ble_hs_lock();
-
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- rc = BLE_HS_ENOTCONN;
- } else {
- 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_hs_unlock();
- }
-
rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ,
att_err, err_handle);
-
- /* Make sure the receive buffer doesn't get freed since we are using it for
- * the response.
- */
- *rxom = NULL;
return rc;
}
@@ -2547,7 +2451,7 @@ ble_att_svr_build_exec_write_rsp(struct os_mbuf **out_txom, uint8_t *att_err)
uint8_t *dst;
int rc;
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
*att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
rc = BLE_HS_ENOMEM;
@@ -2610,33 +2514,28 @@ ble_att_svr_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom)
done:
if (rc == 0) {
ble_hs_lock();
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- rc = BLE_HS_ENOTCONN;
- } else {
- /* Extract the list of prepared writes from the connection so
- * that they can be processed after the mutex is unlocked. They
- * aren't processed now because attribute writes involve executing
- * an application callback.
- */
- prep_list = conn->bhc_att_svr.basc_prep_list;
- SLIST_INIT(&conn->bhc_att_svr.basc_prep_list);
- }
+ conn = ble_hs_conn_find_assert(conn_handle);
+
+ /* Extract the list of prepared writes from the connection so
+ * that they can be processed after the mutex is unlocked. They
+ * aren't processed now because attribute writes involve executing
+ * an application callback.
+ */
+ prep_list = conn->bhc_att_svr.basc_prep_list;
+ SLIST_INIT(&conn->bhc_att_svr.basc_prep_list);
ble_hs_unlock();
- if (conn != NULL) {
- if (req.baeq_flags & BLE_ATT_EXEC_WRITE_F_CONFIRM) {
- /* Perform attribute writes. */
- att_err = ble_att_svr_prep_write(conn_handle, &prep_list,
- &err_handle);
- if (att_err != 0) {
- rc = BLE_HS_EAPP;
- }
+ if (req.baeq_flags & BLE_ATT_EXEC_WRITE_F_CONFIRM) {
+ /* Perform attribute writes. */
+ att_err = ble_att_svr_prep_write(conn_handle, &prep_list,
+ &err_handle);
+ if (att_err != 0) {
+ rc = BLE_HS_EAPP;
}
-
- /* Free the prep entries. */
- ble_att_svr_prep_clear(&prep_list);
}
+
+ /* Free the prep entries. */
+ ble_att_svr_prep_clear(&prep_list);
}
rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ,
@@ -2652,8 +2551,6 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom)
#endif
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) {
@@ -2676,11 +2573,8 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom)
/* Strip the request base from the front of the mbuf. */
os_mbuf_adj(*rxom, BLE_ATT_NOTIFY_REQ_BASE_SZ);
- attr_data = ble_att_get_flat_buf();
- attr_len = OS_MBUF_PKTLEN(*rxom);
- os_mbuf_copydata(*rxom, 0, attr_len, attr_data);
-
- ble_gap_notify_event(conn_handle, req.banq_handle, attr_data, attr_len, 0);
+ ble_gap_notify_rx_event(conn_handle, req.banq_handle, *rxom, 0);
+ *rxom = NULL;
return 0;
}
@@ -2695,7 +2589,7 @@ ble_att_svr_build_indicate_rsp(struct os_mbuf **out_txom)
uint8_t *dst;
int rc;
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
rc = BLE_HS_ENOMEM;
goto done;
@@ -2725,8 +2619,6 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom)
struct ble_att_indicate_req req;
struct os_mbuf *txom;
- uint16_t attr_len;
- void *attr_data;
int rc;
/* Initialize some values in case of early error. */
@@ -2754,11 +2646,8 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom)
/* Strip the request base from the front of the mbuf. */
os_mbuf_adj(*rxom, BLE_ATT_INDICATE_REQ_BASE_SZ);
- attr_data = ble_att_get_flat_buf();
- attr_len = OS_MBUF_PKTLEN(*rxom);
- os_mbuf_copydata(*rxom, 0, attr_len, attr_data);
-
- ble_gap_notify_event(conn_handle, req.baiq_handle, attr_data, attr_len, 1);
+ ble_gap_notify_rx_event(conn_handle, req.baiq_handle, *rxom, 1);
+ *rxom = NULL;
rc = ble_att_svr_build_indicate_rsp(&txom);
if (rc != 0) {
diff --git a/net/nimble/host/src/ble_eddystone.c b/net/nimble/host/src/ble_eddystone.c
index dbd8a716..2ca496f6 100644
--- a/net/nimble/host/src/ble_eddystone.c
+++ b/net/nimble/host/src/ble_eddystone.c
@@ -19,6 +19,7 @@
#include <string.h>
#include "host/ble_eddystone.h"
+#include "host/ble_hs_adv.h"
#include "ble_hs_priv.h"
#define BLE_EDDYSTONE_MAX_SVC_DATA_LEN 23
@@ -112,7 +113,11 @@ ble_eddystone_set_adv_data_gen(struct ble_hs_adv_fields *adv_fields,
* this struct before calling this function.
* @param uid The 16-byte UID to advertise.
*
- * @return 0 on success; BLE_HS_E... on failure.
+ * @return 0 on success;
+ * BLE_HS_EBUSY if advertising is in progress;
+ * BLE_HS_EMSGSIZE if the specified data is too
+ * large to fit in an advertisement;
+ * Other nonzero on failure.
*/
int
ble_eddystone_set_adv_data_uid(struct ble_hs_adv_fields *adv_fields, void *uid)
@@ -151,7 +156,11 @@ ble_eddystone_set_adv_data_uid(struct ble_hs_adv_fields *adv_fields, void *uid)
* BLE_EDDYSTONE_URL_SUFFIX_NONE if the suffix
* is embedded in the body argument.
*
- * @return 0 on success; BLE_HS_E... on failure.
+ * @return 0 on success;
+ * BLE_HS_EBUSY if advertising is in progress;
+ * BLE_HS_EMSGSIZE if the specified data is too
+ * large to fit in an advertisement;
+ * Other nonzero on failure.
*/
int
ble_eddystone_set_adv_data_url(struct ble_hs_adv_fields *adv_fields,
@@ -177,7 +186,7 @@ ble_eddystone_set_adv_data_url(struct ble_hs_adv_fields *adv_fields,
svc_data = ble_eddystone_set_svc_data_base(BLE_EDDYSTONE_FRAME_TYPE_URL);
- rc = ble_hci_util_read_adv_tx_pwr(&tx_pwr);
+ rc = ble_hs_hci_util_read_adv_tx_pwr(&tx_pwr);
if (rc != 0) {
return rc;
}
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index 309b7cf1..f53a7385 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -23,7 +23,7 @@
#include "bsp/bsp.h"
#include "os/os.h"
#include "nimble/nimble_opt.h"
-#include "host/host_hci.h"
+#include "host/ble_hs_adv.h"
#include "ble_hs_priv.h"
/**
@@ -65,18 +65,20 @@
#define BLE_GAP_OP_S_ADV 1
/**
+ * If an attempt to cancel an active procedure fails, the attempt is retried
+ * at this rate (ms).
+ */
+#define BLE_GAP_CANCEL_RETRY_RATE 100 /* ms */
+
+/**
* The maximum amount of user data that can be put into the advertising data.
- * The stack may automatically insert some fields on its own, limiting the
- * maximum amount of user data. The following fields are automatically
- * inserted:
- * o Flags (3 bytes)
- * o Tx-power-level (3 bytes) - Only if the application specified a
- * tx_pwr_llvl_present value of 1 in a call to ble_gap_set_adv_data().
+ * The stack will automatically insert the flags field on its own if requested
+ * by the application, limiting the maximum amount of user data.
*/
-#define BLE_GAP_ADV_DATA_LIMIT_PWR (BLE_HCI_MAX_ADV_DATA_LEN - 6)
-#define BLE_GAP_ADV_DATA_LIMIT_NO_PWR (BLE_HCI_MAX_ADV_DATA_LEN - 3)
+#define BLE_GAP_ADV_DATA_LIMIT_FLAGS (BLE_HCI_MAX_ADV_DATA_LEN - 3)
+#define BLE_GAP_ADV_DATA_LIMIT_NO_FLAGS BLE_HCI_MAX_ADV_DATA_LEN
-static const struct ble_gap_crt_params ble_gap_params_dflt = {
+static const struct ble_gap_conn_params ble_gap_conn_params_dflt = {
.scan_itvl = 0x0010,
.scan_window = 0x0010,
.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN,
@@ -87,41 +89,33 @@ static const struct ble_gap_crt_params ble_gap_params_dflt = {
.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN,
};
-static const struct ble_gap_adv_params ble_gap_adv_params_dflt = {
- .adv_itvl_min = 0,
- .adv_itvl_max = 0,
- .adv_type = BLE_HCI_ADV_TYPE_ADV_IND,
- .own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC,
- .adv_channel_map = BLE_HCI_ADV_CHANMASK_DEF,
- .adv_filter_policy = BLE_HCI_ADV_FILT_DEF,
-};
-
/**
* The state of the in-progress master connection. If no master connection is
* currently in progress, then the op field is set to BLE_GAP_OP_NULL.
*/
-static bssnz_t struct {
+struct ble_gap_master_state {
uint8_t op;
- unsigned exp_set:1;
+ uint8_t exp_set:1;
os_time_t exp_os_ticks;
+ ble_gap_event_fn *cb;
+ void *cb_arg;
+
union {
- struct {
- ble_gap_event_fn *cb;
- void *cb_arg;
- unsigned using_wl:1;
- unsigned our_addr_type:2;
+ struct {
+ uint8_t using_wl:1;
+ uint8_t our_addr_type:2;
+ uint8_t cancel:1;
} conn;
struct {
- uint8_t disc_mode;
- ble_gap_disc_fn *cb;
- void *cb_arg;
+ uint8_t limited:1;
} disc;
};
-} ble_gap_master;
+};
+static bssnz_t struct ble_gap_master_state ble_gap_master;
/**
* The state of the in-progress slave connection. If no slave connection is
@@ -130,6 +124,9 @@ static bssnz_t struct {
static bssnz_t struct {
uint8_t op;
+ unsigned exp_set:1;
+ os_time_t exp_os_ticks;
+
uint8_t conn_mode;
uint8_t disc_mode;
unsigned our_addr_type:2;
@@ -140,15 +137,16 @@ static bssnz_t struct {
uint8_t rsp_data[BLE_HCI_MAX_ADV_DATA_LEN];
uint8_t adv_data_len;
uint8_t rsp_data_len;
- int8_t tx_pwr_lvl;
- unsigned adv_pwr_lvl:1;
+ unsigned adv_auto_flags:1;
} ble_gap_slave;
-static int ble_gap_disc_tx_disable(void);
+static int ble_gap_adv_enable_tx(int enable);
+static int ble_gap_conn_cancel_tx(void);
+static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
struct ble_gap_snapshot {
- struct ble_gap_conn_desc desc;
+ struct ble_gap_conn_desc *desc;
ble_gap_event_fn *cb;
void *cb_arg;
};
@@ -184,6 +182,8 @@ STATS_NAME_START(ble_gap_stats)
STATS_NAME(ble_gap_stats, rx_conn_complete)
STATS_NAME(ble_gap_stats, discover_cancel)
STATS_NAME(ble_gap_stats, discover_cancel_fail)
+ STATS_NAME(ble_gap_stats, security_initiate)
+ STATS_NAME(ble_gap_stats, security_initiate_fail)
STATS_NAME_END(ble_gap_stats)
/*****************************************************************************
@@ -191,34 +191,49 @@ STATS_NAME_END(ble_gap_stats)
*****************************************************************************/
static void
-ble_gap_log_conn(uint8_t addr_type, uint8_t *addr,
- struct ble_gap_crt_params *params)
+ble_gap_log_duration(int32_t duration_ms)
+{
+ if (duration_ms == BLE_HS_FOREVER) {
+ BLE_HS_LOG(INFO, "duration=forever");
+ } else {
+ BLE_HS_LOG(INFO, "duration=%dms", duration_ms);
+ }
+}
+
+static void
+ble_gap_log_conn(uint8_t own_addr_type,
+ uint8_t peer_addr_type, const uint8_t *peer_addr,
+ const struct ble_gap_conn_params *params)
{
- BLE_HS_LOG(INFO, "addr_type=%d addr=", addr_type);
- if (addr == NULL) {
+ BLE_HS_LOG(INFO, "peer_addr_type=%d peer_addr=", peer_addr_type);
+ if (peer_addr == NULL) {
BLE_HS_LOG(INFO, "N/A");
} else {
- BLE_HS_LOG_ADDR(INFO, addr);
+ BLE_HS_LOG_ADDR(INFO, peer_addr);
}
BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d "
"latency=%d supervision_timeout=%d min_ce_len=%d "
- "max_ce_len=%d our_addr_type=%d",
+ "max_ce_len=%d own_addr_type=%d",
params->scan_itvl, params->scan_window, params->itvl_min,
params->itvl_max, params->latency, params->supervision_timeout,
- params->min_ce_len, params->max_ce_len, params->our_addr_type);
+ params->min_ce_len, params->max_ce_len, own_addr_type);
}
static void
-ble_gap_log_disc(uint8_t scan_type, uint8_t filter_policy, uint8_t addr_mode)
+ble_gap_log_disc(uint8_t own_addr_type, int32_t duration_ms,
+ const struct ble_gap_disc_params *disc_params)
{
- BLE_HS_LOG(INFO, "disc_mode=%d filter_policy=%d scan_type=%d addr_node %d",
- ble_gap_master.disc.disc_mode,
- filter_policy, scan_type, addr_mode);
+ BLE_HS_LOG(INFO, "own_addr_type=%d filter_policy=%d passive=%d limited=%d "
+ "filter_duplicates=%d ",
+ own_addr_type, disc_params->filter_policy, disc_params->passive,
+ disc_params->limited, disc_params->filter_duplicates);
+ ble_gap_log_duration(duration_ms);
}
static void
-ble_gap_log_update(uint16_t conn_handle, struct ble_gap_upd_params *params)
+ble_gap_log_update(uint16_t conn_handle,
+ const struct ble_gap_upd_params *params)
{
BLE_HS_LOG(INFO, "connection parameter update; "
"conn_handle=%d itvl_min=%d itvl_max=%d latency=%d "
@@ -229,10 +244,10 @@ ble_gap_log_update(uint16_t conn_handle, struct ble_gap_upd_params *params)
}
static void
-ble_gap_log_wl(struct ble_gap_white_entry *white_list,
+ble_gap_log_wl(const struct ble_gap_white_entry *white_list,
uint8_t white_list_count)
{
- struct ble_gap_white_entry *entry;
+ const struct ble_gap_white_entry *entry;
int i;
BLE_HS_LOG(INFO, "count=%d ", white_list_count);
@@ -247,25 +262,25 @@ ble_gap_log_wl(struct ble_gap_white_entry *white_list,
}
static void
-ble_gap_log_adv(const struct ble_gap_adv_params *adv_params,
- uint8_t *peer_addr, uint8_t peer_addr_type)
+ble_gap_log_adv(uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params)
{
- BLE_HS_LOG(INFO, "disc_mode=%d addr_type=%d addr=",
+ BLE_HS_LOG(INFO, "disc_mode=%d peer_addr_type=%d peer_addr=",
ble_gap_slave.disc_mode, peer_addr_type);
if(peer_addr) {
BLE_HS_LOG_ADDR(INFO, peer_addr);
} else {
BLE_HS_LOG(INFO, "none");
}
- BLE_HS_LOG(INFO, " adv_type=%d adv_channel_map=%d own_addr_type=%d "
+ BLE_HS_LOG(INFO, " adv_channel_map=%d own_addr_type=%d "
"adv_filter_policy=%d adv_itvl_min=%d adv_itvl_max=%d "
"adv_data_len=%d",
- adv_params->adv_type,
- adv_params->adv_channel_map,
- adv_params->own_addr_type,
- adv_params->adv_filter_policy,
- adv_params->adv_itvl_min,
- adv_params->adv_itvl_max,
+ adv_params->channel_map,
+ own_addr_type,
+ adv_params->filter_policy,
+ adv_params->itvl_min,
+ adv_params->itvl_max,
ble_gap_slave.adv_data_len);
}
@@ -294,14 +309,21 @@ ble_gap_fill_conn_desc(struct ble_hs_conn *conn,
desc->conn_itvl = conn->bhc_itvl;
desc->conn_latency = conn->bhc_latency;
desc->supervision_timeout = conn->bhc_supervision_timeout;
+ desc->master_clock_accuracy = conn->bhc_master_clock_accuracy;
desc->sec_state = conn->bhc_sec_state;
+
+ if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
+ desc->role = BLE_GAP_ROLE_MASTER;
+ } else {
+ desc->role = BLE_GAP_ROLE_SLAVE;
+ }
}
static void
ble_gap_conn_to_snapshot(struct ble_hs_conn *conn,
struct ble_gap_snapshot *snap)
{
- ble_gap_fill_conn_desc(conn, &snap->desc);
+ ble_gap_fill_conn_desc(conn, snap->desc);
snap->cb = conn->bhc_cb;
snap->cb_arg = conn->bhc_cb_arg;
}
@@ -341,7 +363,7 @@ ble_gap_find_snapshot(uint16_t handle, struct ble_gap_snapshot *snap)
* connection was found.
*/
int
-ble_gap_find_conn(uint16_t handle, struct ble_gap_conn_desc *out_desc)
+ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc)
{
struct ble_hs_conn *conn;
@@ -361,12 +383,40 @@ ble_gap_find_conn(uint16_t handle, struct ble_gap_conn_desc *out_desc)
}
}
+static int
+ble_gap_extract_conn_cb(uint16_t conn_handle,
+ ble_gap_event_fn **out_cb, void **out_cb_arg)
+{
+ const struct ble_hs_conn *conn;
+
+ BLE_HS_DBG_ASSERT(conn_handle != 0);
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ if (conn != NULL) {
+ *out_cb = conn->bhc_cb;
+ *out_cb_arg = conn->bhc_cb_arg;
+ } else {
+ *out_cb = NULL;
+ *out_cb_arg = NULL;
+ }
+
+ ble_hs_unlock();
+
+ if (conn == NULL) {
+ return BLE_HS_ENOTCONN;
+ } else {
+ return 0;
+ }
+}
+
/*****************************************************************************
* $misc *
*****************************************************************************/
static int
-ble_gap_call_event_cb(int event, struct ble_gap_conn_ctxt *ctxt,
+ble_gap_call_event_cb(struct ble_gap_event *event,
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
@@ -374,12 +424,12 @@ ble_gap_call_event_cb(int event, struct ble_gap_conn_ctxt *ctxt,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
if (cb != NULL) {
- rc = cb(event, ctxt, cb_arg);
+ rc = cb(event, cb_arg);
} else {
- if (event == BLE_GAP_EVENT_CONN_UPDATE_REQ) {
+ if (event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ) {
/* Just copy peer parameters back into the reply. */
- *ctxt->conn_update_req.self_params =
- *ctxt->conn_update_req.peer_params;
+ *event->conn_update_req.self_params =
+ *event->conn_update_req.peer_params;
}
rc = 0;
}
@@ -387,34 +437,25 @@ ble_gap_call_event_cb(int event, struct ble_gap_conn_ctxt *ctxt,
return rc;
}
-static void
-ble_gap_slave_extract_cb(ble_gap_event_fn **out_cb, void **out_cb_arg)
-{
- ble_hs_lock();
-
- *out_cb = ble_gap_slave.cb;
- *out_cb_arg = ble_gap_slave.cb_arg;
- ble_gap_slave.op = BLE_GAP_OP_NULL;
- ble_hs_unlock();
-}
-
-static void
-ble_gap_adv_finished(int event)
+static int
+ble_gap_call_conn_event_cb(struct ble_gap_event *event, uint16_t conn_handle)
{
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_conn_desc desc;
ble_gap_event_fn *cb;
void *cb_arg;
+ int rc;
- ble_gap_slave_extract_cb(&cb, &cb_arg);
- if (cb != NULL) {
- memset(&ctxt, 0, sizeof ctxt);
- desc.conn_handle = BLE_HS_CONN_HANDLE_NONE;
- ctxt.desc = &desc;
+ rc = ble_gap_extract_conn_cb(conn_handle, &cb, &cb_arg);
+ if (rc != 0) {
+ return rc;
+ }
- cb(event, &ctxt, cb_arg);
+ rc = ble_gap_call_event_cb(event, cb, cb_arg);
+ if (rc != 0) {
+ return rc;
}
+
+ return 0;
}
static void
@@ -422,63 +463,73 @@ ble_gap_master_reset_state(void)
{
ble_gap_master.op = BLE_GAP_OP_NULL;
ble_gap_master.exp_set = 0;
+ ble_gap_master.conn.cancel = 0;
+}
+
+static void
+ble_gap_slave_reset_state(void)
+{
+ ble_gap_slave.op = BLE_GAP_OP_NULL;
+ ble_gap_slave.exp_set = 0;
}
static void
-ble_gap_master_extract_cb(ble_gap_event_fn **out_cb, void **out_cb_arg)
+ble_gap_master_extract_state(struct ble_gap_master_state *out_state,
+ int reset_state)
{
ble_hs_lock();
- *out_cb = ble_gap_master.conn.cb;
- *out_cb_arg = ble_gap_master.conn.cb_arg;
- ble_gap_master_reset_state();
+ *out_state = ble_gap_master;
+
+ if (reset_state) {
+ ble_gap_master_reset_state();
+ }
ble_hs_unlock();
}
-static int
-ble_gap_master_connect_failure(int status)
+static void
+ble_gap_slave_extract_cb(ble_gap_event_fn **out_cb, void **out_cb_arg)
{
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_conn_desc desc;
+ ble_hs_lock();
+
+ *out_cb = ble_gap_slave.cb;
+ *out_cb_arg = ble_gap_slave.cb_arg;
+ ble_gap_slave_reset_state();
+
+ ble_hs_unlock();
+}
+
+static void
+ble_gap_adv_finished(void)
+{
+ struct ble_gap_event event;
ble_gap_event_fn *cb;
void *cb_arg;
- int rc;
-
- memset(&desc, 0, sizeof ctxt);
- ble_gap_master_extract_cb(&cb, &cb_arg);
+ ble_gap_slave_extract_cb(&cb, &cb_arg);
if (cb != NULL) {
- memset(&ctxt, 0, sizeof ctxt);
- desc.conn_handle = BLE_HS_CONN_HANDLE_NONE;
- ctxt.desc = &desc;
- ctxt.connect.status = status;
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_ADV_COMPLETE;
- rc = cb(BLE_GAP_EVENT_CONNECT, &ctxt, cb_arg);
- } else {
- rc = 0;
+ cb(&event, cb_arg);
}
-
- return rc;
}
static int
-ble_gap_master_connect_cancel(void)
+ble_gap_master_connect_failure(int status)
{
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_conn_desc desc;
- ble_gap_event_fn *cb;
- void *cb_arg;
+ struct ble_gap_master_state state;
+ struct ble_gap_event event;
int rc;
- memset(&desc, 0, sizeof ctxt);
- desc.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+ ble_gap_master_extract_state(&state, 1);
+ if (state.cb != NULL) {
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_CONNECT;
+ event.connect.status = status;
- ble_gap_master_extract_cb(&cb, &cb_arg);
- if (cb != NULL) {
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &desc;
- rc = cb(BLE_GAP_EVENT_CONN_CANCEL, &ctxt, cb_arg);
+ rc = state.cb(&event, state.cb_arg);
} else {
rc = 0;
}
@@ -487,58 +538,128 @@ ble_gap_master_connect_cancel(void)
}
static void
-ble_gap_call_master_disc_cb(int event, int status, struct ble_hs_adv *adv,
- struct ble_hs_adv_fields *fields, int reset_state)
+ble_gap_master_connect_cancelled(void)
{
- struct ble_gap_disc_desc desc;
- ble_gap_disc_fn *cb;
- void *cb_arg;
+ struct ble_gap_master_state state;
+ struct ble_gap_event event;
- ble_hs_lock();
+ ble_gap_master_extract_state(&state, 1);
+ if (state.cb != NULL) {
+ /* The GAP event type depends on whether 1) the application manually
+ * cancelled the connect procedure or 2) the connect procedure timed
+ * out.
+ */
+ memset(&event, 0, sizeof event);
+ if (state.conn.cancel) {
+ event.type = BLE_GAP_EVENT_CONN_CANCEL;
+ } else {
+ event.type = BLE_GAP_EVENT_CONNECT;
+ event.connect.status = BLE_HS_ETIMEOUT;
+ event.connect.conn_handle = BLE_HS_CONN_HANDLE_NONE;
- if (adv != NULL) {
- desc.event_type = adv->event_type;
- desc.addr_type = adv->addr_type;
- desc.length_data = adv->length_data;
- desc.rssi = adv->rssi;
- memcpy(desc.addr, adv->addr, sizeof adv->addr);
- desc.data = adv->data;
- desc.fields = fields;
- } else {
- memset(&desc, 0, sizeof desc);
+ }
+ state.cb(&event, state.cb_arg);
}
+}
- cb = ble_gap_master.disc.cb;
- cb_arg = ble_gap_master.disc.cb_arg;
+static void
+ble_gap_disc_report(struct ble_gap_disc_desc *desc)
+{
+ struct ble_gap_master_state state;
+ struct ble_gap_event event;
- if (reset_state) {
- ble_gap_master_reset_state();
+ ble_gap_master_extract_state(&state, 0);
+
+ if (state.cb != NULL) {
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_DISC;
+ event.disc = *desc;
+
+ state.cb(&event, state.cb_arg);
}
+}
- ble_hs_unlock();
+static void
+ble_gap_disc_complete(void)
+{
+ struct ble_gap_master_state state;
+ struct ble_gap_event event;
- if (cb != NULL) {
- cb(event, status, &desc, cb_arg);
+ ble_gap_master_extract_state(&state, 1);
+
+ if (state.cb != NULL) {
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_DISC_COMPLETE;
+
+ ble_gap_call_event_cb(&event, state.cb, state.cb_arg);
}
}
static void
ble_gap_update_notify(uint16_t conn_handle, int status)
{
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
- int rc;
+ struct ble_gap_event event;
- rc = ble_gap_find_snapshot(conn_handle, &snap);
- if (rc != 0) {
- return;
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_CONN_UPDATE;
+ event.conn_update.conn_handle = conn_handle;
+ event.conn_update.status = status;
+
+ ble_gap_call_conn_event_cb(&event, conn_handle);
+}
+
+static uint32_t
+ble_gap_master_ticks_until_exp(void)
+{
+ int32_t ticks;
+
+ if (ble_gap_master.op == BLE_GAP_OP_NULL || !ble_gap_master.exp_set) {
+ /* Timer not set; infinity ticks until next event. */
+ return BLE_HS_FOREVER;
}
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.conn_update.status = status;
- ble_gap_call_event_cb(BLE_GAP_EVENT_CONN_UPDATE, &ctxt,
- snap.cb, snap.cb_arg);
+ ticks = ble_gap_master.exp_os_ticks - os_time_get();
+ if (ticks > 0) {
+ /* Timer not expired yet. */
+ return ticks;
+ }
+
+ /* Timer just expired. */
+ return 0;
+}
+
+static uint32_t
+ble_gap_slave_ticks_until_exp(void)
+{
+ int32_t ticks;
+
+ if (ble_gap_slave.op == BLE_GAP_OP_NULL || !ble_gap_slave.exp_set) {
+ /* Timer not set; infinity ticks until next event. */
+ return BLE_HS_FOREVER;
+ }
+
+ ticks = ble_gap_slave.exp_os_ticks - os_time_get();
+ if (ticks > 0) {
+ /* Timer not expired yet. */
+ return ticks;
+ }
+
+ /* Timer just expired. */
+ return 0;
+}
+
+static void
+ble_gap_heartbeat_sched(void)
+{
+ int32_t mst_ticks;
+ int32_t slv_ticks;
+ int32_t ticks;
+
+ mst_ticks = ble_gap_master_ticks_until_exp();
+ slv_ticks = ble_gap_slave_ticks_until_exp();
+ ticks = min(mst_ticks, slv_ticks);
+
+ ble_hs_heartbeat_sched(ticks);
}
static void
@@ -546,29 +667,34 @@ ble_gap_master_set_timer(uint32_t ticks_from_now)
{
ble_gap_master.exp_os_ticks = os_time_get() + ticks_from_now;
ble_gap_master.exp_set = 1;
+
+ ble_gap_heartbeat_sched();
+}
+
+static void
+ble_gap_slave_set_timer(uint32_t ticks_from_now)
+{
+ ble_gap_slave.exp_os_ticks = os_time_get() + ticks_from_now;
+ ble_gap_slave.exp_set = 1;
+
+ ble_gap_heartbeat_sched();
}
/**
* Called when an error is encountered while the master-connection-fsm is
- * active. Resets the state machine, clears the HCI ack callback, and notifies
- * the host task that the next hci_batch item can be processed.
+ * active.
*/
static void
ble_gap_master_failed(int status)
{
switch (ble_gap_master.op) {
- case BLE_GAP_OP_M_DISC:
- STATS_INC(ble_gap_stats, discover_fail);
- ble_gap_call_master_disc_cb(BLE_GAP_EVENT_DISC_COMPLETE, status,
- NULL, NULL, 1);
- break;
-
case BLE_GAP_OP_M_CONN:
STATS_INC(ble_gap_stats, initiate_fail);
ble_gap_master_connect_failure(status);
break;
default:
+ BLE_HS_DBG_ASSERT(0);
break;
}
}
@@ -581,25 +707,35 @@ ble_gap_update_failed(uint16_t conn_handle, int status)
ble_gap_update_notify(conn_handle, status);
}
-static void
-ble_gap_conn_broken(struct ble_gap_snapshot *snap, int reason)
+void
+ble_gap_conn_broken(uint16_t conn_handle, int reason)
{
- struct ble_gap_conn_ctxt ctxt;
+ struct ble_gap_snapshot snap;
+ struct ble_gap_event event;
+ int rc;
- /* XXX: Consider removing the connection from the list and handing it to
- * each fo the "connection_broken" functions below.
- */
+ memset(&event, 0, sizeof event);
+ snap.desc = &event.disconnect.conn;
+
+ rc = ble_gap_find_snapshot(conn_handle, &snap);
+ if (rc != 0) {
+ /* No longer connected. */
+ return;
+ }
- ble_sm_connection_broken(snap->desc.conn_handle);
- ble_gattc_connection_broken(snap->desc.conn_handle);
+ /* Indicate the connection termination to each module. The order matters
+ * here: gatts must come before gattc to ensure the application does not
+ * get informed of spurious notify-tx events.
+ */
+ ble_sm_connection_broken(conn_handle);
+ ble_gatts_connection_broken(conn_handle);
+ ble_gattc_connection_broken(conn_handle);
- ble_hs_atomic_conn_delete(snap->desc.conn_handle);
+ ble_hs_atomic_conn_delete(conn_handle);
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap->desc;
- ctxt.disconnect.reason = reason;
- ble_gap_call_event_cb(BLE_GAP_EVENT_DISCONNECT, &ctxt,
- snap->cb, snap->cb_arg);
+ event.type = BLE_GAP_EVENT_DISCONNECT;
+ event.disconnect.reason = reason;
+ ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg);
STATS_INC(ble_gap_stats, disconnect);
}
@@ -611,28 +747,19 @@ ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt)
return;
#endif
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
- int status;
- int rc;
+ struct ble_gap_event event;
STATS_INC(ble_gap_stats, rx_disconnect);
- rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
- if (rc != 0) {
- /* No longer connected. */
- return;
- }
-
if (evt->status == 0) {
- status = BLE_HS_HCI_ERR(evt->reason);
- ble_gap_conn_broken(&snap, status);
+ ble_gap_conn_broken(evt->connection_handle,
+ BLE_HS_HCI_ERR(evt->reason));
} else {
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.term_failure.status = BLE_HS_HCI_ERR(evt->status);
- ble_gap_call_event_cb(BLE_GAP_EVENT_TERM_FAILURE, &ctxt,
- snap.cb, snap.cb_arg);
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_TERM_FAILURE;
+ event.term_failure.conn_handle = evt->connection_handle;
+ event.term_failure.status = BLE_HS_HCI_ERR(evt->status);
+ ble_gap_call_conn_event_cb(&event, evt->connection_handle);
}
}
@@ -643,12 +770,13 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt)
return;
#endif
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
+ struct ble_gap_event event;
struct ble_hs_conn *conn;
STATS_INC(ble_gap_stats, rx_update_complete);
+ memset(&event, 0, sizeof event);
+
ble_hs_lock();
conn = ble_hs_conn_find(evt->connection_handle);
@@ -658,25 +786,20 @@ ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt)
conn->bhc_latency = evt->conn_latency;
conn->bhc_supervision_timeout = evt->supervision_timeout;
}
-
- ble_gap_conn_to_snapshot(conn, &snap);
}
conn->bhc_flags &= ~BLE_HS_CONN_F_UPDATE;
ble_hs_unlock();
- if (conn != NULL) {
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.conn_update.status = BLE_HS_HCI_ERR(evt->status);
- ble_gap_call_event_cb(BLE_GAP_EVENT_CONN_UPDATE, &ctxt,
- snap.cb, snap.cb_arg);
- }
+ event.type = BLE_GAP_EVENT_CONN_UPDATE;
+ event.conn_update.conn_handle = evt->connection_handle;
+ event.conn_update.status = BLE_HS_HCI_ERR(evt->status);
+ ble_gap_call_conn_event_cb(&event, evt->connection_handle);
}
/**
- * Tells you if the BLE host is in the process of creating a master connection.
+ * Tells you if there is an active central GAP procedure (connect or discover).
*/
int
ble_gap_master_in_progress(void)
@@ -685,21 +808,6 @@ ble_gap_master_in_progress(void)
}
/**
- * Tells you if the BLE host is in the process of creating a slave connection.
- */
-int
-ble_gap_slave_in_progress(void)
-{
- return ble_gap_slave.op != BLE_GAP_OP_NULL;
-}
-
-static int
-ble_gap_currently_advertising(void)
-{
- return ble_gap_slave.op == BLE_GAP_OP_S_ADV;
-}
-
-/**
* Attempts to complete the master connection process in response to a
* "connection complete" event from the controller. If the master connection
* FSM is in a state that can accept this event, and the peer device address is
@@ -764,7 +872,7 @@ ble_gap_accept_slave_conn(uint8_t addr_type, uint8_t *addr)
{
int rc;
- if (!ble_gap_currently_advertising()) {
+ if (!ble_gap_adv_active()) {
rc = BLE_HS_ENOENT;
} else {
switch (ble_gap_slave.conn_mode) {
@@ -795,7 +903,7 @@ ble_gap_accept_slave_conn(uint8_t addr_type, uint8_t *addr)
}
void
-ble_gap_rx_adv_report(struct ble_hs_adv *adv)
+ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
{
#if !NIMBLE_OPT(ROLE_OBSERVER)
return;
@@ -810,20 +918,23 @@ ble_gap_rx_adv_report(struct ble_hs_adv *adv)
return;
}
- rc = ble_hs_adv_parse_fields(&fields, adv->data, adv->length_data);
+ rc = ble_hs_adv_parse_fields(&fields, desc->data, desc->length_data);
if (rc != 0) {
/* XXX: Increment stat. */
return;
}
- if (ble_gap_master.disc.disc_mode == BLE_GAP_DISC_MODE_LTD &&
+ /* If a limited discovery procedure is active, discard non-limited
+ * advertisements.
+ */
+ if (ble_gap_master.disc.limited &&
!(fields.flags & BLE_HS_ADV_F_DISC_LTD)) {
return;
}
- ble_gap_call_master_disc_cb(BLE_GAP_EVENT_DISC_SUCCESS, 0, adv,
- &fields, 0);
+ desc->fields = &fields;
+ ble_gap_disc_report(desc);
}
/**
@@ -836,25 +947,21 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
return BLE_HS_ENOTSUP;
#endif
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
+ struct ble_gap_event event;
struct ble_hs_conn *conn;
- struct ble_gap_enhanced_conn enhanced_conn;
int rc;
STATS_INC(ble_gap_stats, rx_conn_complete);
- /* Determine if this event refers to a completed connection or a connection
- * in progress.
- */
- rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
-
/* Apply the event to the existing connection if it exists. */
- if (rc == 0) {
+ if (evt->status != BLE_ERR_UNK_CONN_ID &&
+ ble_hs_atomic_conn_flags(evt->connection_handle, NULL) == 0) {
+
/* XXX: Does this ever happen? */
if (evt->status != 0) {
- ble_gap_conn_broken(&snap, BLE_HS_HCI_ERR(evt->status));
+ ble_gap_conn_broken(evt->connection_handle,
+ BLE_HS_HCI_ERR(evt->status));
}
return 0;
}
@@ -865,8 +972,8 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
/* Determine the role from the status code. */
switch (evt->status) {
case BLE_ERR_DIR_ADV_TMO:
- if (ble_gap_slave_in_progress()) {
- ble_gap_adv_finished(BLE_GAP_EVENT_ADV_COMPLETE);
+ if (ble_gap_adv_active()) {
+ ble_gap_adv_finished();
}
break;
@@ -874,7 +981,7 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
if (ble_gap_master_in_progress()) {
if (evt->status == BLE_ERR_UNK_CONN_ID) {
/* Connect procedure successfully cancelled. */
- ble_gap_master_connect_cancel();
+ ble_gap_master_connect_cancelled();
} else {
ble_gap_master_failed(BLE_HS_HCI_ERR(evt->status));
}
@@ -910,40 +1017,43 @@ ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt)
BLE_HS_DBG_ASSERT(conn != NULL);
conn->bhc_handle = evt->connection_handle;
- memcpy(conn->bhc_addr, evt->peer_addr, sizeof conn->bhc_addr);
- conn->bhc_addr_type = evt->peer_addr_type;
- memcpy(conn->our_rpa_addr, evt->local_rpa, sizeof(conn->our_rpa_addr));
- memcpy(conn->peer_rpa_addr, evt->peer_rpa, sizeof(conn->peer_rpa_addr));
+ memcpy(conn->bhc_peer_addr, evt->peer_addr, sizeof conn->bhc_peer_addr);
+ conn->bhc_peer_addr_type = evt->peer_addr_type;
+ memcpy(conn->bhc_our_rpa_addr, evt->local_rpa,
+ sizeof conn->bhc_our_rpa_addr);
+ memcpy(conn->bhc_peer_rpa_addr, evt->peer_rpa,
+ sizeof conn->bhc_peer_rpa_addr);
conn->bhc_itvl = evt->conn_itvl;
conn->bhc_latency = evt->conn_latency;
conn->bhc_supervision_timeout = evt->supervision_timeout;
+ conn->bhc_master_clock_accuracy = evt->master_clk_acc;
if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER) {
+ conn->bhc_cb = ble_gap_master.cb;
+ conn->bhc_cb_arg = ble_gap_master.cb_arg;
conn->bhc_flags |= BLE_HS_CONN_F_MASTER;
- conn->bhc_cb = ble_gap_master.conn.cb;
- conn->our_addr_type = ble_gap_master.conn.our_addr_type;
- conn->bhc_cb_arg = ble_gap_master.conn.cb_arg;
+ conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type;
ble_gap_master_reset_state();
} else {
conn->bhc_cb = ble_gap_slave.cb;
conn->bhc_cb_arg = ble_gap_slave.cb_arg;
- conn->our_addr_type = ble_gap_slave.our_addr_type;
- ble_gap_slave.op = BLE_GAP_OP_NULL;
+ conn->bhc_our_addr_type = ble_gap_slave.our_addr_type;
+ ble_gap_slave_reset_state();
}
- memcpy(conn->our_rpa_addr, evt->local_rpa, 6);
- memcpy(conn->peer_rpa_addr, evt->peer_rpa, 6);
+ memcpy(conn->bhc_our_rpa_addr, evt->local_rpa, 6);
+ memcpy(conn->bhc_peer_rpa_addr, evt->peer_rpa, 6);
- ble_gap_conn_to_snapshot(conn, &snap);
+ ble_hs_lock();
+
+ memset(&event, 0, sizeof event);
+ ble_hs_conn_insert(conn);
- ble_hs_atomic_conn_insert(conn);
+ ble_hs_unlock();
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- memcpy(enhanced_conn.local_rpa, evt->local_rpa,6);
- memcpy(enhanced_conn.peer_rpa, evt->peer_rpa,6);
- ctxt.connect.enhanced_conn = &enhanced_conn;
- ctxt.connect.status = 0;
- ble_gap_call_event_cb(BLE_GAP_EVENT_CONNECT, &ctxt, snap.cb, snap.cb_arg);
+ event.type = BLE_GAP_EVENT_CONNECT;
+ event.connect.conn_handle = evt->connection_handle;
+ event.connect.status = 0;
+ ble_gap_call_conn_event_cb(&event, evt->connection_handle);
return 0;
}
@@ -952,62 +1062,77 @@ int
ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
struct ble_gap_upd_params *params)
{
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
+ struct ble_gap_event event;
int rc;
- rc = ble_gap_find_snapshot(conn_handle, &snap);
- if (rc != 0) {
- return rc;
- }
-
- if (snap.cb != NULL) {
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.conn_update_req.peer_params = params;
- rc = snap.cb(BLE_GAP_EVENT_L2CAP_UPDATE_REQ, &ctxt, snap.cb_arg);
- } else {
- rc = 0;
- }
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_L2CAP_UPDATE_REQ;
+ event.conn_update_req.conn_handle = conn_handle;
+ event.conn_update_req.peer_params = params;
+ rc = ble_gap_call_conn_event_cb(&event, conn_handle);
return rc;
}
-static uint32_t
-ble_gap_master_ticks_until_exp(void)
+static int32_t
+ble_gap_master_heartbeat(void)
{
- int32_t ticks;
+ uint32_t ticks_until_exp;
+ int rc;
- if (ble_gap_master.op == BLE_GAP_OP_NULL || !ble_gap_master.exp_set) {
- /* Timer not set; infinity ticks until next event. */
- return UINT32_MAX;
+ ticks_until_exp = ble_gap_master_ticks_until_exp();
+ if (ticks_until_exp != 0) {
+ /* Timer not expired yet. */
+ return ticks_until_exp;
}
- ticks = ble_gap_master.exp_os_ticks - os_time_get();
- if (ticks > 0) {
- /* Timer not expired yet. */
- return ticks;
+ /*** Timer expired; process event. */
+
+ switch (ble_gap_master.op) {
+ case BLE_GAP_OP_M_CONN:
+ rc = ble_gap_conn_cancel_tx();
+ if (rc != 0) {
+ /* Failed to stop connecting; try again in 100 ms. */
+ return BLE_GAP_CANCEL_RETRY_RATE;
+ } else {
+ /* Stop the timer now that the cancel command has been acked. */
+ ble_gap_master.exp_set = 0;
+
+ /* Timeout gets reported when we receive a connection complete
+ * event indicating the connect procedure has been cancelled.
+ */
+ /* XXX: Set a timer to reset the controller if a connection
+ * complete event isn't received within a reasonable interval.
+ */
+ }
+ break;
+
+ case BLE_GAP_OP_M_DISC:
+ /* When a discovery procedure times out, it is not a failure. */
+ rc = ble_gap_disc_enable_tx(0, 0);
+ if (rc != 0) {
+ /* Failed to stop discovery; try again in 100 ms. */
+ return BLE_GAP_CANCEL_RETRY_RATE;
+ }
+
+ ble_gap_disc_complete();
+ break;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ break;
}
- /* Timer just expired. */
- return 0;
+ return BLE_HS_FOREVER;
}
-/**
- * Handles timed-out master procedures.
- *
- * Called by the heartbeat timer; executed at least once a second.
- *
- * @return The number of ticks until this function should
- * be called again.
- */
-uint32_t
-ble_gap_heartbeat(void)
+static int32_t
+ble_gap_slave_heartbeat(void)
{
uint32_t ticks_until_exp;
int rc;
- ticks_until_exp = ble_gap_master_ticks_until_exp();
+ ticks_until_exp = ble_gap_slave_ticks_until_exp();
if (ticks_until_exp != 0) {
/* Timer not expired yet. */
return ticks_until_exp;
@@ -1015,23 +1140,40 @@ ble_gap_heartbeat(void)
/*** Timer expired; process event. */
- /* Clear the timer. */
- ble_gap_master.exp_set = 0;
+ /* Stop advertising. */
+ rc = ble_gap_adv_enable_tx(0);
+ if (rc != 0) {
+ /* Failed to stop advertising; try again in 100 ms. */
+ return 100;
+ }
- switch (ble_gap_master.op) {
- case BLE_GAP_OP_M_DISC:
- /* When a discovery procedure times out, it is not a failure. */
- rc = ble_gap_disc_tx_disable();
- ble_gap_call_master_disc_cb(BLE_GAP_EVENT_DISC_COMPLETE, rc,
- NULL, NULL, 1);
- break;
+ /* Clear the timer and cancel the current procedure. */
+ ble_gap_slave_reset_state();
- default:
- ble_gap_master_failed(BLE_HS_ETIMEOUT);
- break;
- }
+ /* Indicate to application that advertising has stopped. */
+ ble_gap_adv_finished();
+
+ return BLE_HS_FOREVER;
+}
- return UINT32_MAX;
+/**
+ * Handles timed-out master procedures.
+ *
+ * Called by the heartbeat timer; executed at least once a second.
+ *
+ * @return The number of ticks until this function should
+ * be called again.
+ */
+int32_t
+ble_gap_heartbeat(void)
+{
+ int32_t master_ticks;
+ int32_t slave_ticks;
+
+ master_ticks = ble_gap_master_heartbeat();
+ slave_ticks = ble_gap_slave_heartbeat();
+
+ return min(master_ticks, slave_ticks);
}
/*****************************************************************************
@@ -1053,18 +1195,18 @@ ble_gap_wl_busy(void)
}
static int
-ble_gap_wl_tx_add(struct ble_gap_white_entry *entry)
+ble_gap_wl_tx_add(const struct ble_gap_white_entry *entry)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CHG_WHITE_LIST_LEN];
int rc;
- rc = host_hci_cmd_build_le_add_to_whitelist(entry->addr, entry->addr_type,
- buf, sizeof buf);
+ rc = ble_hs_hci_cmd_build_le_add_to_whitelist(
+ entry->addr, entry->addr_type, buf, sizeof buf);
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1078,8 +1220,8 @@ ble_gap_wl_tx_clear(void)
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
int rc;
- host_hci_cmd_build_le_clear_whitelist(buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_clear_whitelist(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1087,8 +1229,16 @@ ble_gap_wl_tx_clear(void)
return 0;
}
+/**
+ * Overwrites the controller's white list with the specified contents.
+ *
+ * @param white_list The entries to write to the white list.
+ * @param white_list_count The number of entries in the white list.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
int
-ble_gap_wl_set(struct ble_gap_white_entry *white_list,
+ble_gap_wl_set(const struct ble_gap_white_entry *white_list,
uint8_t white_list_count)
{
#if !NIMBLE_OPT(WHITELIST)
@@ -1100,9 +1250,11 @@ ble_gap_wl_set(struct ble_gap_white_entry *white_list,
STATS_INC(ble_gap_stats, wl_set);
+ ble_hs_lock();
+
if (white_list_count == 0) {
rc = BLE_HS_EINVAL;
- goto err;
+ goto done;
}
for (i = 0; i < white_list_count; i++) {
@@ -1110,13 +1262,13 @@ ble_gap_wl_set(struct ble_gap_white_entry *white_list,
white_list[i].addr_type != BLE_ADDR_TYPE_RANDOM) {
rc = BLE_HS_EINVAL;
- goto err;
+ goto done;
}
}
if (ble_gap_wl_busy()) {
rc = BLE_HS_EBUSY;
- goto err;
+ goto done;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: set whitelist; ");
@@ -1125,20 +1277,24 @@ ble_gap_wl_set(struct ble_gap_white_entry *white_list,
rc = ble_gap_wl_tx_clear();
if (rc != 0) {
- goto err;
+ goto done;
}
for (i = 0; i < white_list_count; i++) {
rc = ble_gap_wl_tx_add(white_list + i);
if (rc != 0) {
- goto err;
+ goto done;
}
}
- return 0;
+ rc = 0;
-err:
- STATS_INC(ble_gap_stats, wl_set_fail);
+done:
+ ble_hs_unlock();
+
+ if (rc != 0) {
+ STATS_INC(ble_gap_stats, wl_set_fail);
+ }
return rc;
}
@@ -1147,13 +1303,13 @@ err:
*****************************************************************************/
static int
-ble_gap_adv_disable_tx(void)
+ble_gap_adv_enable_tx(int enable)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_ENABLE_LEN];
int rc;
- host_hci_cmd_build_le_set_adv_enable(0, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_set_adv_enable(!!enable, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1161,6 +1317,16 @@ ble_gap_adv_disable_tx(void)
return 0;
}
+/**
+ * Stops the currently-active advertising procedure. A success return
+ * code indicates that advertising has been fully aborted; a new advertising
+ * procedure can be initiated immediately.
+ *
+ * @return 0 on success;
+ * BLE_HS_EALREADY if there is no active
+ * advertising procedure;
+ * Other nonzero on error.
+ */
int
ble_gap_adv_stop(void)
{
@@ -1172,25 +1338,31 @@ ble_gap_adv_stop(void)
STATS_INC(ble_gap_stats, adv_stop);
+ ble_hs_lock();
+
/* Do nothing if advertising is already disabled. */
- if (!ble_gap_currently_advertising()) {
+ if (!ble_gap_adv_active()) {
rc = BLE_HS_EALREADY;
- goto err;
+ goto done;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: stop advertising.\n");
- rc = ble_gap_adv_disable_tx();
+ rc = ble_gap_adv_enable_tx(0);
if (rc != 0) {
- goto err;
+ goto done;
}
- ble_gap_slave.op = BLE_GAP_OP_NULL;
+ ble_gap_slave_reset_state();
- return 0;
+ rc = 0;
-err:
- STATS_INC(ble_gap_stats, adv_set_fields_fail);
+done:
+ ble_hs_unlock();
+
+ if (rc != 0) {
+ STATS_INC(ble_gap_stats, adv_set_fields_fail);
+ }
return rc;
}
@@ -1198,62 +1370,20 @@ err:
* $advertise *
*****************************************************************************/
-static void
-ble_gap_adv_itvls(uint8_t disc_mode, uint8_t conn_mode,
- uint16_t *out_itvl_min, uint16_t *out_itvl_max)
-{
- switch (conn_mode) {
- case BLE_GAP_CONN_MODE_NON:
- *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN;
- *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX;
- break;
-
- case BLE_GAP_CONN_MODE_UND:
- *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
- *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
- break;
-
- case BLE_GAP_CONN_MODE_DIR:
- *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
- *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
- break;
-
- default:
- BLE_HS_DBG_ASSERT(0);
- break;
- }
-}
-
-static int
-ble_gap_adv_enable_tx(void)
-{
- uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN];
- int rc;
-
- host_hci_cmd_build_le_set_adv_enable(1, buf, sizeof buf);
-
- rc = ble_hci_cmd_tx_empty_ack(buf);
- if (rc != 0) {
- return rc;
- }
-
- return 0;
-}
-
static int
ble_gap_adv_rsp_data_tx(void)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_RSP_DATA_LEN];
int rc;
- rc = host_hci_cmd_build_le_set_scan_rsp_data(ble_gap_slave.rsp_data,
- ble_gap_slave.rsp_data_len,
- buf, sizeof buf);
+ rc = ble_hs_hci_cmd_build_le_set_scan_rsp_data(ble_gap_slave.rsp_data,
+ ble_gap_slave.rsp_data_len,
+ buf, sizeof buf);
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1261,11 +1391,9 @@ ble_gap_adv_rsp_data_tx(void)
return 0;
}
-static int
-ble_gap_adv_data_tx(void)
+static void
+ble_gap_adv_data_set_flags(void)
{
- uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_DATA_LEN];
- uint8_t adv_data_len;
uint8_t flags;
int rc;
@@ -1290,31 +1418,38 @@ ble_gap_adv_data_tx(void)
flags |= BLE_HS_ADV_F_BREDR_UNSUP;
- /* Encode the flags AD field if it is nonzero. */
- adv_data_len = ble_gap_slave.adv_data_len;
if (flags != 0) {
rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &flags,
- ble_gap_slave.adv_data, &adv_data_len,
+ ble_gap_slave.adv_data,
+ &ble_gap_slave.adv_data_len,
BLE_HCI_MAX_ADV_DATA_LEN);
- BLE_HS_DBG_ASSERT(rc == 0);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
+}
- /* Encode the transmit power AD field. */
- if (ble_gap_slave.adv_pwr_lvl) {
- rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1,
- &ble_gap_slave.tx_pwr_lvl,
- ble_gap_slave.adv_data,
- &adv_data_len, BLE_HCI_MAX_ADV_DATA_LEN);
- BLE_HS_DBG_ASSERT(rc == 0);
+static int
+ble_gap_adv_data_tx(void)
+{
+ uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_DATA_LEN];
+ int rc;
+
+ /* Calculate the flags AD field if requested by application. Clear the
+ * auto flag after encoding the flags so that we don't get repeated flags
+ * fields on subsequent advertising procedures.
+ */
+ if (ble_gap_slave.adv_auto_flags) {
+ ble_gap_adv_data_set_flags();
+ ble_gap_slave.adv_auto_flags = 0;
}
- rc = host_hci_cmd_build_le_set_adv_data(ble_gap_slave.adv_data,
- adv_data_len, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_build_le_set_adv_data(ble_gap_slave.adv_data,
+ ble_gap_slave.adv_data_len,
+ buf, sizeof buf);
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1323,41 +1458,103 @@ ble_gap_adv_data_tx(void)
}
static int
-ble_gap_adv_params_tx(const struct ble_gap_adv_params *adv_params,
- uint8_t *peer_addr, uint8_t peer_addr_type)
+ble_gap_adv_type(const struct ble_gap_adv_params *adv_params)
+{
+ switch (adv_params->conn_mode) {
+ case BLE_GAP_CONN_MODE_NON:
+ if (adv_params->disc_mode == BLE_GAP_DISC_MODE_NON) {
+ return BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
+ } else {
+ return BLE_HCI_ADV_TYPE_ADV_SCAN_IND;
+ }
+
+ case BLE_GAP_CONN_MODE_UND:
+ return BLE_HCI_ADV_TYPE_ADV_IND;
+
+ case BLE_GAP_CONN_MODE_DIR:
+ if (adv_params->high_duty_cycle) {
+ return BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
+ } else {
+ return BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD;
+ }
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_HCI_ADV_TYPE_ADV_IND;
+ }
+}
+
+static void
+ble_gap_adv_dflt_itvls(uint8_t conn_mode,
+ uint16_t *out_itvl_min, uint16_t *out_itvl_max)
+{
+ switch (conn_mode) {
+ case BLE_GAP_CONN_MODE_NON:
+ *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN;
+ *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX;
+ break;
+
+ case BLE_GAP_CONN_MODE_UND:
+ *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+ *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
+ break;
+
+ case BLE_GAP_CONN_MODE_DIR:
+ *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+ *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
+ break;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ break;
+ }
+}
+
+static int
+ble_gap_adv_params_tx(uint8_t own_addr_type,
+ uint8_t peer_addr_type, const uint8_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params)
+
{
struct hci_adv_params hci_adv_params;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN];
int rc;
- uint8_t peer[6];
- if(peer_addr) {
- memcpy(peer, peer_addr, 6);
- } else {
- memset(peer, 0, 6);
+ if (peer_addr == NULL) {
+ peer_addr = ble_hs_misc_null_addr;
}
- hci_adv_params.adv_channel_map = adv_params->adv_channel_map;
- hci_adv_params.own_addr_type = adv_params->own_addr_type;
- hci_adv_params.adv_filter_policy = adv_params->adv_filter_policy;
- hci_adv_params.adv_itvl_min = adv_params->adv_itvl_min;
- hci_adv_params.adv_itvl_max = adv_params->adv_itvl_max;
+ hci_adv_params.own_addr_type = own_addr_type;
hci_adv_params.peer_addr_type = peer_addr_type;
- hci_adv_params.adv_type = adv_params->adv_type;
-
- if ((ble_gap_slave.conn_mode == BLE_GAP_CONN_MODE_DIR) ||
- (adv_params->own_addr_type == BLE_ADDR_TYPE_RPA_PUB_DEFAULT) ||
- (adv_params->own_addr_type == BLE_ADDR_TYPE_RPA_RND_DEFAULT)) {
- memcpy(hci_adv_params.peer_addr,peer,
- sizeof(hci_adv_params.peer_addr));
+ memcpy(hci_adv_params.peer_addr, peer_addr,
+ sizeof hci_adv_params.peer_addr);
+
+ /* Fill optional fields if application did not specify them. */
+ if (adv_params->itvl_min == 0 && adv_params->itvl_max == 0) {
+ ble_gap_adv_dflt_itvls(adv_params->conn_mode,
+ &hci_adv_params.adv_itvl_min,
+ &hci_adv_params.adv_itvl_max);
+ } else {
+ hci_adv_params.adv_itvl_min = adv_params->itvl_min;
+ hci_adv_params.adv_itvl_max = adv_params->itvl_max;
}
+ if (adv_params->channel_map == 0) {
+ hci_adv_params.adv_channel_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP;
+ } else {
+ hci_adv_params.adv_channel_map = adv_params->channel_map;
+ }
+
+ /* Zero is the default value for filter policy and high duty cycle */
+ hci_adv_params.adv_filter_policy = adv_params->filter_policy;
- rc = host_hci_cmd_build_le_set_adv_params(&hci_adv_params, buf, sizeof buf);
+ hci_adv_params.adv_type = ble_gap_adv_type(adv_params);
+ rc = ble_hs_hci_cmd_build_le_set_adv_params(&hci_adv_params,
+ buf, sizeof buf);
if (rc != 0) {
- return rc;
+ return BLE_HS_EINVAL;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1365,67 +1562,47 @@ ble_gap_adv_params_tx(const struct ble_gap_adv_params *adv_params,
return 0;
}
-/**
- * Enables the specified discoverable mode and connectable mode, and initiates
- * the advertising process.
- *
- * @param discoverable_mode One of the following constants:
- * o BLE_GAP_DISC_MODE_NON
- * (non-discoverable; 3.C.9.2.2).
- * o BLE_GAP_DISC_MODE_LTD
- * (limited-discoverable; 3.C.9.2.3).
- * o BLE_GAP_DISC_MODE_GEN
- * (general-discoverable; 3.C.9.2.4).
- * @param connectable_mode One of the following constants:
- * o BLE_GAP_CONN_MODE_NON
- * (non-connectable; 3.C.9.3.2).
- * o BLE_GAP_CONN_MODE_DIR
- * (directed-connectable; 3.C.9.3.3).
- * o BLE_GAP_CONN_MODE_UND
- * (undirected-connectable; 3.C.9.3.4).
- *
- * @return 0 on success; nonzero on failure.
- */
-int
-ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
- uint8_t *peer_addr, uint8_t peer_addr_type,
- const struct ble_gap_adv_params *adv_params,
- ble_gap_event_fn *cb, void *cb_arg)
+static int
+ble_gap_adv_validate(uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params)
{
-#if !NIMBLE_OPT(ADVERTISE)
- return BLE_HS_ENOTSUP;
-#endif
-
- struct ble_gap_adv_params gap_adv_params;
- int rc;
-
- ble_hs_lock();
-
- STATS_INC(ble_gap_stats, adv_start);
-
- if (ble_gap_slave.op != BLE_GAP_OP_NULL) {
- rc = BLE_HS_EALREADY;
- goto done;
+ if (adv_params == NULL) {
+ return BLE_HS_EINVAL;
}
- if (discoverable_mode >= BLE_GAP_DISC_MODE_MAX) {
- rc = BLE_HS_EINVAL;
- goto done;
+ if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+ return BLE_HS_EINVAL;
}
- /* Don't initiate a connection procedure if we won't be able to allocate a
- * connection object on completion.
- */
- if (connectable_mode != BLE_GAP_CONN_MODE_NON &&
- !ble_hs_conn_can_alloc()) {
+ if (adv_params->disc_mode >= BLE_GAP_DISC_MODE_MAX) {
+ return BLE_HS_EINVAL;
+ }
- rc = BLE_HS_ENOMEM;
- goto done;
+ if (ble_gap_slave.op != BLE_GAP_OP_NULL) {
+ return BLE_HS_EALREADY;
}
- switch (connectable_mode) {
+ switch (adv_params->conn_mode) {
case BLE_GAP_CONN_MODE_NON:
+ /* High duty cycle only allowed for directed advertising. */
+ if (adv_params->high_duty_cycle) {
+ return BLE_HS_EINVAL;
+ }
+ break;
+
case BLE_GAP_CONN_MODE_UND:
+ /* High duty cycle only allowed for directed advertising. */
+ if (adv_params->high_duty_cycle) {
+ return BLE_HS_EINVAL;
+ }
+
+ /* Don't allow connectable advertising if we won't be able to allocate
+ * a new connection.
+ */
+ if (!ble_hs_conn_can_alloc()) {
+ return BLE_HS_ENOMEM;
+ }
break;
case BLE_GAP_CONN_MODE_DIR:
@@ -1434,76 +1611,117 @@ ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
peer_addr_type != BLE_ADDR_TYPE_RPA_PUB_DEFAULT &&
peer_addr_type != BLE_ADDR_TYPE_RPA_RND_DEFAULT) {
- rc = BLE_HS_EINVAL;
- goto done;
+ return BLE_HS_EINVAL;
+ }
+ if (peer_addr == NULL) {
+ return BLE_HS_EINVAL;
+ }
+
+ /* Don't allow connectable advertising if we won't be able to allocate
+ * a new connection.
+ */
+ if (!ble_hs_conn_can_alloc()) {
+ return BLE_HS_ENOMEM;
}
break;
default:
- rc = BLE_HS_EINVAL;
- goto done;
- }
-
- if(adv_params == NULL) {
- gap_adv_params = ble_gap_adv_params_dflt;
- } else {
- gap_adv_params = *adv_params;
+ return BLE_HS_EINVAL;
}
- if(gap_adv_params.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
- rc = BLE_HS_EINVAL;
- goto done;
- }
+ return 0;
+}
- ble_gap_slave.cb = cb;
- ble_gap_slave.cb_arg = cb_arg;
- ble_gap_slave.conn_mode = connectable_mode;
- ble_gap_slave.disc_mode = discoverable_mode;
- ble_gap_slave.our_addr_type = gap_adv_params.own_addr_type;
+/**
+ * Initiates advertising.
+ *
+ * @param own_addr_type The type of address the stack should use for
+ * itself. Valid values are:
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * o BLE_ADDR_TYPE_RPA_PUB_DEFAULT
+ * o BLE_ADDR_TYPE_RPA_RND_DEFAULT
+ * @param peer_addr_type Address type of the peer's identity address.
+ * Valid values are:
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * This parameter is ignored unless directed
+ * advertising is being used.
+ * @param peer_addr The peer's six-byte identity address.
+ * This parameter is ignored unless directed
+ * advertising is being used.
+ * @param duration_ms The duration of the advertisement procedure.
+ * On expiration, the procedure ends and a
+ * BLE_GAP_EVENT_ADV_COMPLETE event is
+ * reported. Units are milliseconds. Specify
+ * BLE_HS_FOREVER for no expiration.
+ * @param adv_params Additional arguments specifying the particulars
+ * of the advertising procedure.
+ * @param cb The callback to associate with this advertising
+ * procedure. If advertising ends, the event
+ * is reported through this callback. If
+ * advertising results in a connection, the
+ * connection inherits this callback as its
+ * event-reporting mechanism.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_gap_adv_start(uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr, int32_t duration_ms,
+ const struct ble_gap_adv_params *adv_params,
+ ble_gap_event_fn *cb, void *cb_arg)
+{
+#if !NIMBLE_OPT(ADVERTISE)
+ return BLE_HS_ENOTSUP;
+#endif
- ble_gap_adv_itvls(discoverable_mode, connectable_mode,
- &gap_adv_params.adv_itvl_min,
- &gap_adv_params.adv_itvl_max);
+ uint32_t duration_ticks;
+ int rc;
- if (gap_adv_params.own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
- ble_hs_pvcy_set_our_nrpa();
- }
+ STATS_INC(ble_gap_stats, adv_start);
- switch (connectable_mode) {
- case BLE_GAP_CONN_MODE_NON:
- gap_adv_params.adv_type = BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
- break;
+ ble_hs_lock();
- case BLE_GAP_CONN_MODE_DIR:
- gap_adv_params.adv_type = BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
- break;
+ rc = ble_gap_adv_validate(own_addr_type, peer_addr_type, peer_addr,
+ adv_params);
+ if (rc != 0) {
+ goto done;
+ }
- case BLE_GAP_CONN_MODE_UND:
- gap_adv_params.adv_type = BLE_HCI_ADV_TYPE_ADV_IND;
- break;
+ if (duration_ms != BLE_HS_FOREVER) {
+ rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
+ if (rc != 0) {
+ /* Duration too great. */
+ rc = BLE_HS_EINVAL;
+ goto done;
+ }
+ }
- default:
- BLE_HS_DBG_ASSERT(0);
- break;
+ rc = ble_hs_id_use_addr(own_addr_type);
+ if (rc != 0) {
+ return rc;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: advertise; ");
- ble_gap_log_adv(&gap_adv_params, peer_addr, peer_addr_type);
+ ble_gap_log_adv(own_addr_type, peer_addr_type, peer_addr, adv_params);
BLE_HS_LOG(INFO, "\n");
- rc = ble_gap_adv_params_tx(&gap_adv_params, peer_addr, peer_addr_type);
+ ble_gap_slave.cb = cb;
+ ble_gap_slave.cb_arg = cb_arg;
+ ble_gap_slave.conn_mode = adv_params->conn_mode;
+ ble_gap_slave.disc_mode = adv_params->disc_mode;
+ ble_gap_slave.our_addr_type = own_addr_type;
+
+ rc = ble_gap_adv_params_tx(own_addr_type, peer_addr_type, peer_addr,
+ adv_params);
if (rc != 0) {
goto done;
}
- if (ble_gap_slave.adv_pwr_lvl) {
- rc = ble_hci_util_read_adv_tx_pwr(&ble_gap_slave.tx_pwr_lvl);
- if (rc != 0) {
- goto done;
- }
- }
-
- if (ble_gap_slave.conn_mode != BLE_GAP_CONN_MODE_DIR) {
+ if (adv_params->conn_mode != BLE_GAP_CONN_MODE_DIR) {
rc = ble_gap_adv_data_tx();
if (rc != 0) {
goto done;
@@ -1515,27 +1733,42 @@ ble_gap_adv_start(uint8_t discoverable_mode, uint8_t connectable_mode,
}
}
- rc = ble_gap_adv_enable_tx();
+ ble_gap_slave.op = BLE_GAP_OP_S_ADV;
+
+ rc = ble_gap_adv_enable_tx(1);
if (rc != 0) {
+ ble_gap_slave_reset_state();
goto done;
}
- ble_gap_slave.op = BLE_GAP_OP_S_ADV;
+ if (duration_ms != BLE_HS_FOREVER) {
+ ble_gap_slave_set_timer(duration_ticks);
+ }
rc = 0;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, adv_start_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
+/**
+ * Configures the data to include in subsequent advertisements.
+ *
+ * @param adv_fields Specifies the advertisement data.
+ *
+ * @return 0 on success;
+ * BLE_HS_EBUSY if advertising is in progress;
+ * BLE_HS_EMSGSIZE if the specified data is too
+ * large to fit in an advertisement;
+ * Other nonzero on failure.
+ */
int
-ble_gap_adv_set_fields(struct ble_hs_adv_fields *adv_fields)
+ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields)
{
#if !NIMBLE_OPT(ADVERTISE)
return BLE_HS_ENOTSUP;
@@ -1544,31 +1777,55 @@ ble_gap_adv_set_fields(struct ble_hs_adv_fields *adv_fields)
int max_sz;
int rc;
+ STATS_INC(ble_gap_stats, adv_set_fields);
+
ble_hs_lock();
- STATS_INC(ble_gap_stats, adv_set_fields);
+ /* Don't allow advertising fields to be set while advertising is active. */
+ if (ble_gap_slave.op != BLE_GAP_OP_NULL) {
+ rc = BLE_HS_EBUSY;
+ goto done;
+ }
- if (adv_fields->tx_pwr_lvl_is_present) {
- max_sz = BLE_GAP_ADV_DATA_LIMIT_PWR;
+ /* If application has requested the stack to calculate the flags field
+ * automatically (flags == 0), there is less room for user data.
+ */
+ if (adv_fields->flags_is_present && adv_fields->flags == 0) {
+ max_sz = BLE_GAP_ADV_DATA_LIMIT_FLAGS;
+ ble_gap_slave.adv_auto_flags = 1;
} else {
- max_sz = BLE_GAP_ADV_DATA_LIMIT_NO_PWR;
+ max_sz = BLE_GAP_ADV_DATA_LIMIT_NO_FLAGS;
+ ble_gap_slave.adv_auto_flags = 0;
}
rc = ble_hs_adv_set_fields(adv_fields, ble_gap_slave.adv_data,
&ble_gap_slave.adv_data_len, max_sz);
- if (rc == 0) {
- ble_gap_slave.adv_pwr_lvl = adv_fields->tx_pwr_lvl_is_present;
- } else {
- STATS_INC(ble_gap_stats, adv_set_fields_fail);
+ if (rc != 0) {
+ goto done;
}
+done:
ble_hs_unlock();
+ if (rc != 0) {
+ STATS_INC(ble_gap_stats, adv_set_fields_fail);
+ }
return rc;
}
+/**
+ * Configures the data to include in subsequent scan responses.
+ *
+ * @param adv_fields Specifies the scan response data.
+ *
+ * @return 0 on success;
+ * BLE_HS_EBUSY if advertising is in progress;
+ * BLE_HS_EMSGSIZE if the specified data is too
+ * large to fit in an advertisement;
+ * Other nonzero on failure.
+ */
int
-ble_gap_adv_rsp_set_fields(struct ble_hs_adv_fields *rsp_fields)
+ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
{
#if !NIMBLE_OPT(ADVERTISE)
return BLE_HS_ENOTSUP;
@@ -1576,34 +1833,58 @@ ble_gap_adv_rsp_set_fields(struct ble_hs_adv_fields *rsp_fields)
int rc;
+ STATS_INC(ble_gap_stats, adv_rsp_set_fields);
+
ble_hs_lock();
- STATS_INC(ble_gap_stats, adv_rsp_set_fields);
+ /* Don't allow response fields to be set while advertising is active. */
+ if (ble_gap_slave.op != BLE_GAP_OP_NULL) {
+ rc = BLE_HS_EBUSY;
+ goto done;
+ }
rc = ble_hs_adv_set_fields(rsp_fields, ble_gap_slave.rsp_data,
&ble_gap_slave.rsp_data_len,
BLE_HCI_MAX_ADV_DATA_LEN);
if (rc != 0) {
- STATS_INC(ble_gap_stats, adv_rsp_set_fields_fail);
+ goto done;
}
+done:
ble_hs_unlock();
+ if (rc != 0) {
+ STATS_INC(ble_gap_stats, adv_rsp_set_fields_fail);
+ }
return rc;
}
+/**
+ * Indicates whether an advertisement procedure is currently in progress.
+ *
+ * @return 0: No advertisement procedure in progress;
+ * 1: Advertisement procedure in progress.
+ */
+int
+ble_gap_adv_active(void)
+{
+ /* Assume read is atomic; mutex not necessary. */
+ return ble_gap_slave.op == BLE_GAP_OP_S_ADV;
+}
+
/*****************************************************************************
* $discovery procedures *
*****************************************************************************/
static int
-ble_gap_disc_tx_disable(void)
+ble_gap_disc_enable_tx(int enable, int filter_duplicates)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN];
int rc;
- host_hci_cmd_build_le_set_scan_enable(0, 0, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_set_scan_enable(!!enable, !!filter_duplicates,
+ buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1612,37 +1893,30 @@ ble_gap_disc_tx_disable(void)
}
static int
-ble_gap_disc_tx_enable(void)
+ble_gap_disc_tx_params(uint8_t own_addr_type,
+ const struct ble_gap_disc_params *disc_params)
{
- uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN];
+ uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
+ uint8_t scan_type;
int rc;
- host_hci_cmd_build_le_set_scan_enable(1, 0, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
- if (rc != 0) {
- return rc;
+ if (disc_params->passive) {
+ scan_type = BLE_HCI_SCAN_TYPE_PASSIVE;
+ } else {
+ scan_type = BLE_HCI_SCAN_TYPE_ACTIVE;
}
- return 0;
-}
-
-static int
-ble_gap_disc_tx_params(uint8_t scan_type, uint8_t filter_policy,
- uint8_t addr_mode)
-{
- uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
- int rc;
-
- rc = host_hci_cmd_build_le_set_scan_params(
- scan_type,
- BLE_GAP_SCAN_FAST_INTERVAL_MIN,
- BLE_GAP_SCAN_FAST_WINDOW,
- addr_mode,
- filter_policy,
- buf, sizeof buf);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+ rc = ble_hs_hci_cmd_build_le_set_scan_params(scan_type,
+ disc_params->itvl,
+ disc_params->window,
+ own_addr_type,
+ disc_params->filter_policy,
+ buf, sizeof buf);
+ if (rc != 0) {
+ return BLE_HS_EINVAL;
+ }
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1665,16 +1939,16 @@ ble_gap_disc_cancel(void)
{
int rc;
- ble_hs_lock();
-
STATS_INC(ble_gap_stats, discover_cancel);
- if (ble_gap_master.op != BLE_GAP_OP_M_DISC) {
+ ble_hs_lock();
+
+ if (!ble_gap_disc_active()) {
rc = BLE_HS_EALREADY;
goto done;
}
- rc = ble_gap_disc_tx_disable();
+ rc = ble_gap_disc_enable_tx(0, 0);
if (rc != 0) {
goto done;
}
@@ -1682,123 +1956,190 @@ ble_gap_disc_cancel(void)
ble_gap_master_reset_state();
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, discover_cancel_fail);
}
- ble_hs_unlock();
-
return rc;
}
+static void
+ble_gap_disc_fill_dflts(struct ble_gap_disc_params *disc_params)
+{
+ if (disc_params->itvl == 0) {
+ if (disc_params->limited) {
+ disc_params->itvl = BLE_GAP_LIM_DISC_SCAN_INT;
+ } else {
+ disc_params->itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN;
+ }
+ }
+
+ if (disc_params->window == 0) {
+ if (disc_params->limited) {
+ disc_params->window = BLE_GAP_LIM_DISC_SCAN_WINDOW;
+ } else {
+ disc_params->window = BLE_GAP_SCAN_FAST_WINDOW;
+ }
+ }
+}
+
+static int
+ble_gap_disc_validate(uint8_t own_addr_type,
+ const struct ble_gap_disc_params *disc_params)
+{
+ if (disc_params == NULL) {
+ return BLE_HS_EINVAL;
+ }
+
+ if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+ return BLE_HS_EINVAL;
+ }
+
+ if (ble_gap_conn_active()) {
+ return BLE_HS_EBUSY;
+ }
+
+ if (ble_gap_disc_active()) {
+ return BLE_HS_EALREADY;
+ }
+
+ return 0;
+}
+
/**
- * Performs the Limited or General Discovery Procedures, as described in
- * vol. 3, part C, section 9.2.5 / 9.2.6.
+ * Performs the Limited or General Discovery Procedures.
+ *
+ * @param own_addr_type The type of address the stack should use for
+ * itself when sending scan requests. Valid
+ * values are:
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * o BLE_ADDR_TYPE_RPA_PUB_DEFAULT
+ * o BLE_ADDR_TYPE_RPA_RND_DEFAULT
+ * This parameter is ignored unless active
+ * scanning is being used.
+ * @param duration_ms The duration of the discovery procedure.
+ * On expiration, the procedure ends and a
+ * BLE_GAP_EVENT_DISC_COMPLETE event is
+ * reported. Units are milliseconds. Specify
+ * BLE_HS_FOREVER for no expiration.
+ * @param disc_params Additional arguments specifying the particulars
+ * of the discovery procedure.
+ * @param cb The callback to associate with this discovery
+ * procedure. Advertising reports and
+ * discovery termination events are reported
+ * through this callback.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
*
* @return 0 on success; nonzero on failure.
*/
int
-ble_gap_disc(uint32_t duration_ms, uint8_t discovery_mode,
- uint8_t scan_type, uint8_t filter_policy, uint8_t addr_mode,
- ble_gap_disc_fn *cb, void *cb_arg)
+ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
+ const struct ble_gap_disc_params *disc_params,
+ ble_gap_event_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(ROLE_OBSERVER)
return BLE_HS_ENOTSUP;
#endif
+ struct ble_gap_disc_params params;
uint32_t duration_ticks;
int rc;
- ble_hs_lock();
-
- if (ble_gap_master.op != BLE_GAP_OP_NULL) {
- rc = BLE_HS_EALREADY;
- goto done;
- }
-
STATS_INC(ble_gap_stats, discover);
- if (discovery_mode != BLE_GAP_DISC_MODE_LTD &&
- discovery_mode != BLE_GAP_DISC_MODE_GEN) {
-
- rc = BLE_HS_EINVAL;
- goto done;
- }
+ ble_hs_lock();
- if (scan_type != BLE_HCI_SCAN_TYPE_PASSIVE &&
- scan_type != BLE_HCI_SCAN_TYPE_ACTIVE) {
+ /* Make a copy of the parameter strcuture and fill unspecified values with
+ * defaults.
+ */
+ params = *disc_params;
+ ble_gap_disc_fill_dflts(&params);
- rc = BLE_HS_EINVAL;
+ rc = ble_gap_disc_validate(own_addr_type, &params);
+ if (rc != 0) {
goto done;
}
- if((addr_mode != BLE_HCI_ADV_OWN_ADDR_PUBLIC) &&
- (addr_mode != BLE_HCI_ADV_OWN_ADDR_RANDOM) &&
- (addr_mode != BLE_HCI_ADV_OWN_ADDR_PRIV_PUB) &&
- (addr_mode != BLE_HCI_ADV_OWN_ADDR_PRIV_RAND)) {
- rc = BLE_HS_EINVAL;
- goto done;
- }
-
- if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
- rc = BLE_HS_EINVAL;
- goto done;
+ if (duration_ms == 0) {
+ duration_ms = BLE_GAP_DISC_DUR_DFLT;
}
- if (duration_ms == 0) {
- duration_ms = BLE_GAP_GEN_DISC_SCAN_MIN;
+ if (duration_ms != BLE_HS_FOREVER) {
+ rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
+ if (rc != 0) {
+ /* Duration too great. */
+ rc = BLE_HS_EINVAL;
+ goto done;
+ }
}
- rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
- if (rc != 0) {
- /* Duration too great. */
- rc = BLE_HS_EINVAL;
- goto done;
+ if (!params.passive) {
+ rc = ble_hs_id_use_addr(own_addr_type);
+ if (rc != 0) {
+ return rc;
+ }
}
- ble_gap_master.disc.disc_mode = discovery_mode;
- ble_gap_master.disc.cb = cb;
- ble_gap_master.disc.cb_arg = cb_arg;
+ ble_gap_master.disc.limited = params.limited;
+ ble_gap_master.cb = cb;
+ ble_gap_master.cb_arg = cb_arg;
BLE_HS_LOG(INFO, "GAP procedure initiated: discovery; ");
- ble_gap_log_disc(scan_type, filter_policy, addr_mode);
+ ble_gap_log_disc(own_addr_type, duration_ms, &params);
BLE_HS_LOG(INFO, "\n");
- if (addr_mode == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
- ble_hs_pvcy_set_our_nrpa();
- }
-
- rc = ble_gap_disc_tx_params(scan_type, filter_policy, addr_mode);
+ rc = ble_gap_disc_tx_params(own_addr_type, &params);
if (rc != 0) {
goto done;
}
- rc = ble_gap_disc_tx_enable();
+ ble_gap_master.op = BLE_GAP_OP_M_DISC;
+
+ rc = ble_gap_disc_enable_tx(1, params.filter_duplicates);
if (rc != 0) {
+ ble_gap_master_reset_state();
goto done;
}
- ble_gap_master_set_timer(duration_ticks);
- ble_gap_master.op = BLE_GAP_OP_M_DISC;
+ if (duration_ms != BLE_HS_FOREVER) {
+ ble_gap_master_set_timer(duration_ticks);
+ }
rc = 0;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, discover_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
+/**
+ * Indicates whether a discovery procedure is currently in progress.
+ *
+ * @return 0: No discovery procedure in progress;
+ * 1: Discovery procedure in progress.
+ */
+int
+ble_gap_disc_active(void)
+{
+ /* Assume read is atomic; mutex not necessary. */
+ return ble_gap_master.op == BLE_GAP_OP_M_DISC;
+}
+
/*****************************************************************************
* $connection establishment procedures *
*****************************************************************************/
static int
-ble_gap_conn_create_tx(int addr_type, uint8_t *addr,
- struct ble_gap_crt_params *params)
+ble_gap_conn_create_tx(uint8_t own_addr_type,
+ uint8_t peer_addr_type, const uint8_t *peer_addr,
+ const struct ble_gap_conn_params *params)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CREATE_CONN_LEN];
struct hci_create_conn hcc;
@@ -1807,18 +2148,21 @@ ble_gap_conn_create_tx(int addr_type, uint8_t *addr,
hcc.scan_itvl = params->scan_itvl;
hcc.scan_window = params->scan_window;
- if (addr_type == BLE_GAP_ADDR_TYPE_WL) {
+ if (peer_addr_type == BLE_GAP_ADDR_TYPE_WL) {
+ /* Application wants to connect to any device in the white list. The
+ * peer address type and peer address fields are ignored by the
+ * controller; fill them with dummy values.
+ */
hcc.filter_policy = BLE_HCI_CONN_FILT_USE_WL;
- hcc.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
+ hcc.peer_addr_type = 0;
memset(hcc.peer_addr, 0, sizeof hcc.peer_addr);
} else {
hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL;
- hcc.peer_addr_type = addr_type;
- memcpy(hcc.peer_addr, addr, sizeof hcc.peer_addr);
+ hcc.peer_addr_type = peer_addr_type;
+ memcpy(hcc.peer_addr, peer_addr, sizeof hcc.peer_addr);
}
- /* TODO error check our_addr_type */
- hcc.own_addr_type = params->our_addr_type;
+ hcc.own_addr_type = own_addr_type;
hcc.conn_itvl_min = params->itvl_min;
hcc.conn_itvl_max = params->itvl_max;
hcc.conn_latency = params->latency;
@@ -1826,12 +2170,12 @@ ble_gap_conn_create_tx(int addr_type, uint8_t *addr,
hcc.min_ce_len = params->min_ce_len;
hcc.max_ce_len = params->max_ce_len;
- rc = host_hci_cmd_build_le_create_connection(&hcc, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_build_le_create_connection(&hcc, buf, sizeof buf);
if (rc != 0) {
return BLE_HS_EUNKNOWN;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1840,108 +2184,193 @@ ble_gap_conn_create_tx(int addr_type, uint8_t *addr,
}
/**
- * Performs the Direct Connection Establishment Procedure, as described in
- * vol. 3, part C, section 9.3.8.
+ * Initiates a connect procedure.
*
- * @param addr_type The peer's address type; one of:
- * o BLE_HCI_CONN_PEER_ADDR_PUBLIC
- * o BLE_HCI_CONN_PEER_ADDR_RANDOM
- * o BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT
- * o BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT
- * o BLE_GAP_ADDR_TYPE_WL
- * @param addr The address of the peer to connect to.
+ * @param own_addr_type The type of address the stack should use for
+ * itself during connection establishment.
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * o BLE_ADDR_TYPE_RPA_PUB_DEFAULT
+ * o BLE_ADDR_TYPE_RPA_RND_DEFAULT
+ * @param peer_addr_type The peer's address type. One of:
+ * o BLE_HCI_CONN_PEER_ADDR_PUBLIC
+ * o BLE_HCI_CONN_PEER_ADDR_RANDOM
+ * o BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT
+ * o BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT
+ * o BLE_GAP_ADDR_TYPE_WL
+ * @param peer_addr The identity address of the peer to connect to.
+ * This parameter is ignored when the white
+ * list is used.
+ * @param duration_ms The duration of the discovery procedure.
+ * On expiration, the procedure ends and a
+ * BLE_GAP_EVENT_DISC_COMPLETE event is
+ * reported. Units are milliseconds.
+ * @param conn_params Additional arguments specifying the particulars
+ * of the connect procedure. Specify null for
+ * default values.
+ * @param cb The callback to associate with this connect
+ * procedure. When the connect procedure
+ * completes, the result is reported through
+ * this callback. If the connect procedure
+ * succeeds, the connection inherits this
+ * callback as its event-reporting mechanism.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
*
* @return 0 on success; nonzero on failure.
*/
int
-ble_gap_conn_initiate(int addr_type, uint8_t *addr,
- struct ble_gap_crt_params *params,
- ble_gap_event_fn *cb, void *cb_arg)
+ble_gap_connect(uint8_t own_addr_type,
+ uint8_t peer_addr_type, const uint8_t *peer_addr,
+ int32_t duration_ms,
+ const struct ble_gap_conn_params *conn_params,
+ ble_gap_event_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(ROLE_CENTRAL)
return BLE_HS_ENOTSUP;
#endif
+ uint32_t duration_ticks;
int rc;
+ STATS_INC(ble_gap_stats, initiate);
+
ble_hs_lock();
- if (ble_gap_master.op != BLE_GAP_OP_NULL) {
+ if (ble_gap_conn_active()) {
rc = BLE_HS_EALREADY;
goto done;
}
- STATS_INC(ble_gap_stats, initiate);
+ if (ble_gap_disc_active()) {
+ rc = BLE_HS_EBUSY;
+ goto done;
+ }
- if (addr_type != BLE_HCI_CONN_PEER_ADDR_PUBLIC &&
- addr_type != BLE_HCI_CONN_PEER_ADDR_RANDOM &&
- addr_type != BLE_HCI_CONN_PEER_ADDR_PUB_ID &&
- addr_type != BLE_HCI_CONN_PEER_ADDR_RAND_ID &&
- addr_type != BLE_GAP_ADDR_TYPE_WL) {
+ if (!ble_hs_conn_can_alloc()) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ if (peer_addr_type != BLE_HCI_CONN_PEER_ADDR_PUBLIC &&
+ peer_addr_type != BLE_HCI_CONN_PEER_ADDR_RANDOM &&
+ peer_addr_type != BLE_HCI_CONN_PEER_ADDR_PUB_ID &&
+ peer_addr_type != BLE_HCI_CONN_PEER_ADDR_RAND_ID &&
+ peer_addr_type != BLE_GAP_ADDR_TYPE_WL) {
rc = BLE_HS_EINVAL;
goto done;
}
- if (params == NULL) {
- params = (void *)&ble_gap_params_dflt;
+ if (conn_params == NULL) {
+ conn_params = &ble_gap_conn_params_dflt;
+ }
+
+ if (duration_ms == 0) {
+ duration_ms = BLE_GAP_CONN_DUR_DFLT;
+ }
+
+ if (duration_ms != BLE_HS_FOREVER) {
+ rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
+ if (rc != 0) {
+ /* Duration too great. */
+ rc = BLE_HS_EINVAL;
+ goto done;
+ }
}
- /* XXX: Verify params. */
+ /* XXX: Verify conn_params. */
+
+ rc = ble_hs_id_use_addr(own_addr_type);
+ if (rc != 0) {
+ return rc;
+ }
BLE_HS_LOG(INFO, "GAP procedure initiated: connect; ");
- ble_gap_log_conn(addr_type, addr, params);
+ ble_gap_log_conn(own_addr_type, peer_addr_type, peer_addr, conn_params);
BLE_HS_LOG(INFO, "\n");
- ble_gap_master.conn.cb = cb;
- ble_gap_master.conn.cb_arg = cb_arg;
- ble_gap_master.conn.using_wl = addr_type == BLE_GAP_ADDR_TYPE_WL;
- ble_gap_master.conn.our_addr_type = params->our_addr_type;
+ ble_gap_master.cb = cb;
+ ble_gap_master.cb_arg = cb_arg;
+ ble_gap_master.conn.using_wl = peer_addr_type == BLE_GAP_ADDR_TYPE_WL;
+ ble_gap_master.conn.our_addr_type = own_addr_type;
- rc = ble_gap_conn_create_tx(addr_type, addr, params);
+ ble_gap_master.op = BLE_GAP_OP_M_CONN;
+
+ rc = ble_gap_conn_create_tx(own_addr_type, peer_addr_type, peer_addr,
+ conn_params);
if (rc != 0) {
+ ble_gap_master_reset_state();
goto done;
}
- ble_gap_master.op = BLE_GAP_OP_M_CONN;
+ if (duration_ms != BLE_HS_FOREVER) {
+ ble_gap_master_set_timer(duration_ticks);
+ }
rc = 0;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, initiate_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
+/**
+ * Indicates whether a connect procedure is currently in progress.
+ *
+ * @return 0: No connect procedure in progress;
+ * 1: Connect procedure in progress.
+ */
+int
+ble_gap_conn_active(void)
+{
+ /* Assume read is atomic; mutex not necessary. */
+ return ble_gap_master.op == BLE_GAP_OP_M_CONN;
+}
+
/*****************************************************************************
* $terminate connection procedure *
*****************************************************************************/
+/**
+ * Terminates an established connection.
+ *
+ * @param conn_handle The handle corresponding to the connection to
+ * terminate.
+ * @param hci_reason The HCI error code to indicate as the reason
+ * for termination.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOTCONN if there is no connection with
+ * the specified handle;
+ * Other nonzero on failure.
+ */
int
-ble_gap_terminate(uint16_t conn_handle)
+ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_DISCONNECT_CMD_LEN];
int rc;
- ble_hs_lock();
-
STATS_INC(ble_gap_stats, terminate);
+ ble_hs_lock();
+
if (!ble_hs_conn_exists(conn_handle)) {
rc = BLE_HS_ENOTCONN;
goto done;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: terminate connection; "
- "conn_handle=%d\n", conn_handle);
+ "conn_handle=%d hci_reason=%d\n",
+ conn_handle, hci_reason);
- host_hci_cmd_build_disconnect(conn_handle, BLE_ERR_REM_USER_CONN_TERM,
- buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_disconnect(conn_handle, hci_reason,
+ buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
goto done;
}
@@ -1949,12 +2378,11 @@ ble_gap_terminate(uint16_t conn_handle)
rc = 0;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, terminate_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
@@ -1962,38 +2390,59 @@ done:
* $cancel *
*****************************************************************************/
-int
-ble_gap_cancel(void)
+static int
+ble_gap_conn_cancel_tx(void)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
int rc;
- ble_hs_lock();
+ ble_hs_hci_cmd_build_le_create_conn_cancel(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Aborts a connect procedure in progress.
+ *
+ * @return 0 on success;
+ * BLE_HS_EALREADY if there is no active connect
+ * procedure.
+ * Other nonzero on error.
+ */
+int
+ble_gap_conn_cancel(void)
+{
+ int rc;
STATS_INC(ble_gap_stats, cancel);
- if (!ble_gap_master_in_progress()) {
- rc = BLE_HS_ENOENT;
+ ble_hs_lock();
+
+ if (!ble_gap_conn_active()) {
+ rc = BLE_HS_EALREADY;
goto done;
}
BLE_HS_LOG(INFO, "GAP procedure initiated: cancel connection\n");
- host_hci_cmd_build_le_create_conn_cancel(buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_gap_conn_cancel_tx();
if (rc != 0) {
goto done;
}
+ ble_gap_master.conn.cancel = 1;
rc = 0;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, cancel_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
@@ -2017,8 +2466,8 @@ ble_gap_tx_param_pos_reply(uint16_t conn_handle,
pos_reply.min_ce_len = params->min_ce_len;
pos_reply.max_ce_len = params->max_ce_len;
- host_hci_cmd_build_le_conn_param_reply(&pos_reply, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_conn_param_reply(&pos_reply, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -2036,8 +2485,8 @@ ble_gap_tx_param_neg_reply(uint16_t conn_handle, uint8_t reject_reason)
neg_reply.handle = conn_handle;
neg_reply.reason = reject_reason;
- host_hci_cmd_build_le_conn_param_neg_reply(&neg_reply, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_conn_param_neg_reply(&neg_reply, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -2054,18 +2503,13 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
struct ble_gap_upd_params peer_params;
struct ble_gap_upd_params self_params;
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
+ struct ble_gap_event event;
uint8_t reject_reason;
int rc;
reject_reason = 0; /* Silence warning. */
- rc = ble_gap_find_snapshot(evt->connection_handle, &snap);
- if (rc != 0) {
- /* We are not connected to the sender. */
- return;
- }
+ memset(&event, 0, sizeof event);
peer_params.itvl_min = evt->itvl_min;
peer_params.itvl_max = evt->itvl_max;
@@ -2080,12 +2524,12 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
*/
self_params = peer_params;
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.conn_update_req.self_params = &self_params;
- ctxt.conn_update_req.peer_params = &peer_params;
- rc = ble_gap_call_event_cb(BLE_GAP_EVENT_CONN_UPDATE_REQ, &ctxt,
- snap.cb, snap.cb_arg);
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_CONN_UPDATE_REQ;
+ event.conn_update_req.conn_handle = evt->connection_handle;
+ event.conn_update_req.self_params = &self_params;
+ event.conn_update_req.peer_params = &peer_params;
+ rc = ble_gap_call_conn_event_cb(&event, evt->connection_handle);
if (rc != 0) {
reject_reason = rc;
}
@@ -2104,7 +2548,8 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
}
static int
-ble_gap_update_tx(uint16_t conn_handle, struct ble_gap_upd_params *params)
+ble_gap_update_tx(uint16_t conn_handle,
+ const struct ble_gap_upd_params *params)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_UPDATE_LEN];
struct hci_conn_update cmd;
@@ -2118,12 +2563,12 @@ ble_gap_update_tx(uint16_t conn_handle, struct ble_gap_upd_params *params)
cmd.min_ce_len = params->min_ce_len;
cmd.max_ce_len = params->max_ce_len;
- rc = host_hci_cmd_build_le_conn_update(&cmd, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_build_le_conn_update(&cmd, buf, sizeof buf);
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -2131,8 +2576,25 @@ ble_gap_update_tx(uint16_t conn_handle, struct ble_gap_upd_params *params)
return 0;
}
+/**
+ * Initiates a connection parameter update procedure.
+ *
+ * @param conn_handle The handle corresponding to the connection to
+ * update.
+ * @param params The connection parameters to attempt to update
+ * to.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOTCONN if the there is no connection
+ * with the specified handle;
+ * BLE_HS_EALREADY if a connection update
+ * procedure for this connection is already in
+ * progress;
+ * Other nonzero on error.
+ */
int
-ble_gap_update_params(uint16_t conn_handle, struct ble_gap_upd_params *params)
+ble_gap_update_params(uint16_t conn_handle,
+ const struct ble_gap_upd_params *params)
{
#if !NIMBLE_OPT(CONNECT)
return BLE_HS_ENOTSUP;
@@ -2141,10 +2603,10 @@ ble_gap_update_params(uint16_t conn_handle, struct ble_gap_upd_params *params)
struct ble_hs_conn *conn;
int rc;
- ble_hs_lock();
-
STATS_INC(ble_gap_stats, update);
+ ble_hs_lock();
+
conn = ble_hs_conn_find(conn_handle);
if (conn == NULL) {
rc = BLE_HS_ENOTCONN;
@@ -2168,12 +2630,11 @@ ble_gap_update_params(uint16_t conn_handle, struct ble_gap_upd_params *params)
conn->bhc_flags |= BLE_HS_CONN_F_UPDATE;
done:
+ ble_hs_unlock();
+
if (rc != 0) {
STATS_INC(ble_gap_stats, update_fail);
}
-
- ble_hs_unlock();
-
return rc;
}
@@ -2181,6 +2642,19 @@ done:
* $security *
*****************************************************************************/
+/**
+ * Initiates the GAP encryption procedure.
+ *
+ * @param conn_handle The handle corresponding to the connection to
+ * encrypt.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOTCONN if the there is no connection
+ * with the specified handle;
+ * BLE_HS_EALREADY if an encrpytion procedure for
+ * this connection is already in progress;
+ * Other nonzero on error.
+ */
int
ble_gap_security_initiate(uint16_t conn_handle)
{
@@ -2195,6 +2669,8 @@ ble_gap_security_initiate(uint16_t conn_handle)
struct ble_hs_conn *conn;
int rc;
+ STATS_INC(ble_gap_stats, security_initiate);
+
ble_hs_lock();
conn = ble_hs_conn_find(conn_handle);
if (conn != NULL) {
@@ -2208,7 +2684,8 @@ ble_gap_security_initiate(uint16_t conn_handle)
ble_hs_unlock();
if (conn == NULL) {
- return BLE_HS_ENOTCONN;
+ rc = BLE_HS_ENOTCONN;
+ goto done;
}
if (conn_flags & BLE_HS_CONN_F_MASTER) {
@@ -2221,11 +2698,27 @@ ble_gap_security_initiate(uint16_t conn_handle)
rc = ble_sm_enc_initiate(conn_handle, value_sec.ltk,
value_sec.ediv, value_sec.rand_num,
value_sec.authenticated);
+ if (rc != 0) {
+ goto done;
+ }
} else {
rc = ble_sm_pair_initiate(conn_handle);
+ if (rc != 0) {
+ goto done;
+ }
}
} else {
rc = ble_sm_slave_initiate(conn_handle);
+ if (rc != 0) {
+ goto done;
+ }
+ }
+
+ rc = 0;
+
+done:
+ if (rc != 0) {
+ STATS_INC(ble_gap_stats, security_initiate_fail);
}
return rc;
@@ -2243,7 +2736,7 @@ ble_gap_pair_initiate(uint16_t conn_handle)
int
ble_gap_encryption_initiate(uint16_t conn_handle,
- uint8_t *ltk,
+ const uint8_t *ltk,
uint16_t ediv,
uint64_t rand_val,
int auth)
@@ -2270,38 +2763,22 @@ ble_gap_encryption_initiate(uint16_t conn_handle,
void
ble_gap_passkey_event(uint16_t conn_handle,
- struct ble_gap_passkey_action *passkey_action)
+ struct ble_gap_passkey_params *passkey_params)
{
#if !NIMBLE_OPT(SM)
return;
#endif
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
- struct ble_hs_conn *conn;
-
- ble_hs_lock();
-
- conn = ble_hs_conn_find(conn_handle);
- if (conn != NULL) {
- ble_gap_conn_to_snapshot(conn, &snap);
- }
-
- ble_hs_unlock();
-
- if (conn == NULL) {
- /* No longer connected. */
- return;
- }
+ struct ble_gap_event event;
BLE_HS_LOG(DEBUG, "send passkey action request %d\n",
- passkey_action->action);
+ passkey_params->action);
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.passkey_action = *passkey_action;
- ble_gap_call_event_cb(BLE_GAP_EVENT_PASSKEY_ACTION, &ctxt,
- snap.cb, snap.cb_arg);
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_PASSKEY_ACTION;
+ event.passkey.conn_handle = conn_handle;
+ event.passkey.params = *passkey_params;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
}
void
@@ -2311,59 +2788,134 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
return;
#endif
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
- int rc;
-
- rc = ble_gap_find_snapshot(conn_handle, &snap);
- if (rc != 0) {
- /* No longer connected. */
- return;
- }
+ struct ble_gap_event event;
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.enc_change.status = status;
- ble_gap_call_event_cb(BLE_GAP_EVENT_ENC_CHANGE, &ctxt,
- snap.cb, snap.cb_arg);
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_ENC_CHANGE;
+ event.enc_change.conn_handle = conn_handle;
+ event.enc_change.status = status;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
if (status == 0 && security_restored) {
- BLE_HS_DBG_ASSERT(snap.desc.sec_state.bonded);
ble_gatts_bonding_restored(conn_handle);
}
}
/*****************************************************************************
+ * $rssi *
+ *****************************************************************************/
+
+/**
+ * Retrieves the most-recently measured RSSI for the specified connection. A
+ * connection's RSSI is updated whenever a data channel PDU is received.
+ *
+ * @param conn_handle Specifies the connection to query.
+ * @param out_rssi On success, the retrieved RSSI is written here.
+ *
+ * @return 0 on success;
+ * A BLE host HCI return code if the controller
+ * rejected the request;
+ * A BLE host core return code on unexpected
+ * error.
+ */
+int
+ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi)
+{
+ int rc;
+
+ rc = ble_hs_hci_util_read_rssi(conn_handle, out_rssi);
+ return rc;
+}
+
+/*****************************************************************************
* $notify *
*****************************************************************************/
void
-ble_gap_notify_event(uint16_t conn_handle, uint16_t attr_handle,
- void *attr_data, uint16_t attr_len, int is_indication)
+ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
+ struct os_mbuf *om, int is_indication)
{
- /* XXX: Early return if notifications and indications disabled. */
- struct ble_gap_conn_ctxt ctxt;
- struct ble_gap_snapshot snap;
- int rc;
+#if !NIMBLE_OPT(GATT_NOTIFY) && !NIMBLE_OPT(GATT_INDICATE)
+ return;
+#endif
- rc = ble_gap_find_snapshot(conn_handle, &snap);
- if (rc != 0) {
- /* No longer connected. */
- return;
- }
+ struct ble_gap_event event;
- memset(&ctxt, 0, sizeof ctxt);
- ctxt.desc = &snap.desc;
- ctxt.notify.attr_handle = attr_handle;
- ctxt.notify.attr_data = attr_data;
- ctxt.notify.attr_len = attr_len;
- ctxt.notify.indication = is_indication;
- ble_gap_call_event_cb(BLE_GAP_EVENT_NOTIFY, &ctxt, snap.cb, snap.cb_arg);
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_NOTIFY_RX;
+ event.notify_rx.conn_handle = conn_handle;
+ event.notify_rx.attr_handle = attr_handle;
+ event.notify_rx.om = om;
+ event.notify_rx.indication = is_indication;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
+
+ os_mbuf_free_chain(event.notify_rx.om);
}
-void ble_gap_init_identity_addr(uint8_t *addr)
+void
+ble_gap_notify_tx_event(int status, uint16_t conn_handle, uint16_t attr_handle,
+ int is_indication)
{
- ble_hs_pvcy_set_our_id_addr(addr);
+#if !NIMBLE_OPT(GATT_NOTIFY) && !NIMBLE_OPT(GATT_INDICATE)
+ return;
+#endif
+
+ struct ble_gap_event event;
+
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_NOTIFY_TX;
+ event.notify_tx.conn_handle = conn_handle;
+ event.notify_tx.status = status;
+ event.notify_tx.attr_handle = attr_handle;
+ event.notify_tx.indication = is_indication;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
+}
+
+/*****************************************************************************
+ * $subscribe *
+ *****************************************************************************/
+
+void
+ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t reason,
+ uint8_t prev_notify, uint8_t cur_notify,
+ uint8_t prev_indicate, uint8_t cur_indicate)
+{
+ struct ble_gap_event event;
+
+ BLE_HS_DBG_ASSERT(prev_notify != cur_notify ||
+ prev_indicate != cur_indicate);
+ BLE_HS_DBG_ASSERT(reason == BLE_GAP_SUBSCRIBE_REASON_WRITE ||
+ reason == BLE_GAP_SUBSCRIBE_REASON_TERM ||
+ reason == BLE_GAP_SUBSCRIBE_REASON_RESTORE);
+
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_SUBSCRIBE;
+ event.subscribe.conn_handle = conn_handle;
+ event.subscribe.attr_handle = attr_handle;
+ event.subscribe.reason = reason;
+ event.subscribe.prev_notify = !!prev_notify;
+ event.subscribe.cur_notify = !!cur_notify;
+ event.subscribe.prev_indicate = !!prev_indicate;
+ event.subscribe.cur_indicate = !!cur_indicate;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
+}
+
+/*****************************************************************************
+ * $mtu *
+ *****************************************************************************/
+
+void
+ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu)
+{
+ struct ble_gap_event event;
+
+ memset(&event, 0, sizeof event);
+ event.type = BLE_GAP_EVENT_MTU;
+ event.mtu.conn_handle = conn_handle;
+ event.mtu.channel_id = cid;
+ event.mtu.value = mtu;
+ ble_gap_call_conn_event_cb(&event, conn_handle);
}
/*****************************************************************************
diff --git a/net/nimble/host/src/ble_gap_priv.h b/net/nimble/host/src/ble_gap_priv.h
index 547dffb7..eed5a18f 100644
--- a/net/nimble/host/src/ble_gap_priv.h
+++ b/net/nimble/host/src/ble_gap_priv.h
@@ -28,7 +28,7 @@ struct hci_le_conn_param_req;
struct hci_le_conn_complete;
struct hci_disconn_complete;
struct hci_encrypt_change;
-struct ble_hci_ack;
+struct ble_hs_hci_ack;
struct ble_hs_adv;
STATS_SECT_START(ble_gap_stats)
@@ -61,6 +61,8 @@ STATS_SECT_START(ble_gap_stats)
STATS_SECT_ENTRY(rx_conn_complete)
STATS_SECT_ENTRY(discover_cancel)
STATS_SECT_ENTRY(discover_cancel_fail)
+ STATS_SECT_ENTRY(security_initiate)
+ STATS_SECT_ENTRY(security_initiate_fail)
STATS_SECT_END
extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
@@ -68,8 +70,7 @@ extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
#define BLE_GAP_CONN_MODE_MAX 3
#define BLE_GAP_DISC_MODE_MAX 3
-int ble_gap_locked_by_cur_task(void);
-void ble_gap_rx_adv_report(struct ble_hs_adv *adv);
+void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc);
int ble_gap_rx_conn_complete(struct hci_le_conn_complete *evt);
void ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt);
void ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt);
@@ -79,14 +80,20 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
void ble_gap_enc_event(uint16_t conn_handle, int status,
int security_restored);
void ble_gap_passkey_event(uint16_t conn_handle,
- struct ble_gap_passkey_action *passkey_action);
-void ble_gap_notify_event(uint16_t conn_handle, uint16_t attr_handle,
- void *attr_data, uint16_t attr_len,
- int is_indication);
+ struct ble_gap_passkey_params *passkey_params);
+void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
+ struct os_mbuf *om, int is_indication);
+void ble_gap_notify_tx_event(int status, uint16_t conn_handle,
+ uint16_t attr_handle, int is_indication);
+void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t reason,
+ uint8_t prev_notify, uint8_t cur_notify,
+ uint8_t prev_indicate, uint8_t cur_indicate);
+void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu);
int ble_gap_master_in_progress(void);
-int ble_gap_slave_in_progress(void);
-uint32_t ble_gap_heartbeat(void);
+void ble_gap_conn_broken(uint16_t conn_handle, int reason);
+int32_t ble_gap_heartbeat(void);
int ble_gap_init(void);
diff --git a/net/nimble/host/src/ble_gatt_priv.h b/net/nimble/host/src/ble_gatt_priv.h
index 5955b913..7c0f020a 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -84,8 +84,6 @@ extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats;
#define BLE_GATT_CHR_DECL_SZ_16 5
#define BLE_GATT_CHR_DECL_SZ_128 19
-#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902
-
typedef uint8_t ble_gatts_conn_flags;
struct ble_gatts_conn {
@@ -97,22 +95,19 @@ struct ble_gatts_conn {
/*** @client. */
int ble_gattc_locked_by_cur_task(void);
-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);
+void ble_gatts_indicate_fail_notconn(uint16_t conn_handle);
void ble_gattc_rx_err(uint16_t conn_handle, struct ble_att_error_rsp *rsp);
void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu);
void ble_gattc_rx_read_type_adata(uint16_t conn_handle,
struct ble_att_read_type_adata *adata);
void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status);
-void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, void *value,
- int value_len);
+void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status,
+ struct os_mbuf **rxom);
void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
- void *value, int value_len);
+ struct os_mbuf **rxom);
void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status,
- void *value, int value_len);
+ struct os_mbuf **rxom);
void ble_gattc_rx_read_group_type_adata(
uint16_t conn_handle, struct ble_att_read_group_type_adata *adata);
void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc);
@@ -122,7 +117,7 @@ void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status);
void ble_gattc_rx_write_rsp(uint16_t conn_handle);
void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status,
struct ble_att_prep_write_cmd *rsp,
- void *attr_data, uint16_t attr_data_len);
+ struct os_mbuf **rxom);
void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status);
void ble_gattc_rx_indicate_rsp(uint16_t conn_handle);
void ble_gattc_rx_find_info_idata(uint16_t conn_handle,
@@ -130,7 +125,7 @@ void ble_gattc_rx_find_info_idata(uint16_t conn_handle,
void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status);
void ble_gattc_connection_txable(uint16_t conn_handle);
void ble_gattc_connection_broken(uint16_t conn_handle);
-uint32_t ble_gattc_heartbeat(void);
+int32_t ble_gattc_heartbeat(void);
int ble_gattc_any_jobs(void);
int ble_gattc_init(void);
@@ -138,7 +133,7 @@ int ble_gattc_init(void);
/*** @server. */
#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001
#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002
-#define BLE_GATTS_CLT_CFG_F_INDICATE_PENDING 0x0080 /* Internal only. */
+#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */
#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc
#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4
@@ -146,10 +141,11 @@ int ble_gattc_init(void);
int ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle);
int ble_gatts_send_next_indicate(uint16_t conn_handle);
+void ble_gatts_tx_notifications(void);
void ble_gatts_bonding_restored(uint16_t conn_handle);
+void ble_gatts_connection_broken(uint16_t conn_handle);
/*** @misc. */
-void ble_gatts_conn_deinit(struct ble_gatts_conn *gatts_conn);
int ble_gatts_conn_can_alloc(void);
int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn);
int ble_gatts_start(void);
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index 29e6b4ef..3dee6799 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -138,7 +138,7 @@ struct ble_gattc_proc {
} disc_chr_uuid;
struct {
- uint16_t chr_def_handle;
+ uint16_t chr_val_handle;
uint16_t prev_handle;
uint16_t end_handle;
ble_gatt_dsc_fn *cb;
@@ -182,17 +182,16 @@ struct ble_gattc_proc {
} write_long;
struct {
- struct ble_gatt_attr *attrs;
- int num_attrs;
- int cur_attr;
+ struct ble_gatt_attr attrs[NIMBLE_OPT(GATT_WRITE_MAX_ATTRS)];
+ uint8_t num_attrs;
+ uint8_t cur_attr;
+ uint16_t length;
ble_gatt_reliable_attr_fn *cb;
void *cb_arg;
} write_reliable;
struct {
- ble_gatt_attr_fn *cb;
uint16_t chr_val_handle;
- void *cb_arg;
} indicate;
};
};
@@ -248,10 +247,10 @@ typedef int ble_gattc_rx_adata_fn(struct ble_gattc_proc *proc,
typedef int ble_gattc_rx_prep_fn(struct ble_gattc_proc *proc, int status,
struct ble_att_prep_write_cmd *rsp,
- void *attr_data, uint16_t attr_len);
+ struct os_mbuf **om);
typedef int ble_gattc_rx_attr_fn(struct ble_gattc_proc *proc, int status,
- void *value, int value_len);
+ struct os_mbuf **om);
typedef int ble_gattc_rx_complete_fn(struct ble_gattc_proc *proc, int status);
typedef int ble_gattc_rx_exec_fn(struct ble_gattc_proc *proc, int status);
@@ -393,9 +392,9 @@ ble_gattc_log_proc_init(char *name)
}
static void
-ble_gattc_log_uuid(void *uuid128)
+ble_gattc_log_uuid(const void *uuid128)
{
- uint8_t *u8p;
+ const uint8_t *u8p;
u8p = uuid128;
BLE_HS_LOG(INFO, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
@@ -447,8 +446,8 @@ static void
ble_gattc_log_disc_all_dscs(struct ble_gattc_proc *proc)
{
ble_gattc_log_proc_init("discover all descriptors; ");
- BLE_HS_LOG(INFO, "chr_def_handle=%d end_handle=%d\n",
- proc->disc_all_dscs.chr_def_handle,
+ BLE_HS_LOG(INFO, "chr_val_handle=%d end_handle=%d\n",
+ proc->disc_all_dscs.chr_val_handle,
proc->disc_all_dscs.end_handle);
}
@@ -461,7 +460,7 @@ ble_gattc_log_read(uint16_t att_handle)
static void
ble_gattc_log_read_uuid(uint16_t start_handle, uint16_t end_handle,
- uint8_t *uuid128)
+ const uint8_t *uuid128)
{
uint16_t uuid16;
@@ -486,7 +485,7 @@ ble_gattc_log_read_long(struct ble_gattc_proc *proc)
}
static void
-ble_gattc_log_read_mult(uint16_t *handles, uint8_t num_handles)
+ble_gattc_log_read_mult(const uint16_t *handles, uint8_t num_handles)
{
int i;
@@ -518,7 +517,8 @@ ble_gattc_log_write_long(struct ble_gattc_proc *proc)
{
ble_gattc_log_proc_init("write long; ");
BLE_HS_LOG(INFO, "att_handle=%d len=%d\n",
- proc->write_long.attr.handle, proc->write_long.attr.value_len);
+ proc->write_long.attr.handle,
+ OS_MBUF_PKTLEN(proc->write_long.attr.om));
}
static void
@@ -603,10 +603,26 @@ static void
ble_gattc_proc_free(struct ble_gattc_proc *proc)
{
int rc;
+ int i;
if (proc != NULL) {
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ switch (proc->op) {
+ case BLE_GATT_OP_WRITE_LONG:
+ os_mbuf_free_chain(proc->write_long.attr.om);
+ break;
+
+ case BLE_GATT_OP_WRITE_RELIABLE:
+ for (i = 0; i < proc->write_reliable.num_attrs; i++) {
+ os_mbuf_free_chain(proc->write_reliable.attrs[i].om);
+ }
+ break;
+
+ default:
+ break;
+ }
+
rc = os_memblock_put(&ble_gattc_proc_pool, proc);
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
@@ -618,7 +634,7 @@ ble_gattc_proc_insert(struct ble_gattc_proc *proc)
ble_gattc_dbg_assert_proc_not_inserted(proc);
ble_hs_lock();
- STAILQ_INSERT_HEAD(&ble_gattc_procs, proc, next);
+ STAILQ_INSERT_TAIL(&ble_gattc_procs, proc, next);
ble_hs_unlock();
}
@@ -707,9 +723,26 @@ ble_gattc_extract(uint16_t conn_handle, uint8_t op)
return proc;
}
+static int
+ble_gattc_conn_op_matches(struct ble_gattc_proc *proc, uint16_t conn_handle,
+ uint8_t op)
+{
+ if (conn_handle != BLE_HS_CONN_HANDLE_NONE &&
+ conn_handle != proc->conn_handle) {
+
+ return 0;
+ }
+
+ if (op != BLE_GATT_OP_NONE && op != proc->op) {
+ return 0;
+ }
+
+ return 1;
+}
+
static void
-ble_gattc_extract_by_conn(uint16_t conn_handle,
- struct ble_gattc_proc_list *dst_list)
+ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op,
+ struct ble_gattc_proc_list *dst_list)
{
struct ble_gattc_proc *proc;
struct ble_gattc_proc *prev;
@@ -727,7 +760,7 @@ ble_gattc_extract_by_conn(uint16_t conn_handle,
while (proc != NULL) {
next = STAILQ_NEXT(proc, next);
- if (proc->conn_handle == conn_handle) {
+ if (ble_gattc_conn_op_matches(proc, conn_handle, op)) {
if (prev == NULL) {
STAILQ_REMOVE_HEAD(&ble_gattc_procs, next);
} else {
@@ -842,6 +875,35 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle,
sizeof (rx_entries) / sizeof (rx_entries)[0], \
(const void **)(out_rx_entry))
+
+/**
+ * Causes all GATT procedures matching the specified criteria to fail with the
+ * specified status code.
+ */
+static void
+ble_gattc_fail_procs(uint16_t conn_handle, uint8_t op, int status)
+{
+ struct ble_gattc_proc_list temp_list;
+ struct ble_gattc_proc *proc;
+ ble_gattc_err_fn *err_cb;
+
+ /* Remove all procs with the specified conn handle-op-pair and insert them
+ * into the temporary list.
+ */
+ ble_gattc_extract_by_conn_op(conn_handle, op, &temp_list);
+
+ /* Notify application of failed procedures and free the corresponding proc
+ * entries.
+ */
+ while ((proc = STAILQ_FIRST(&temp_list)) != NULL) {
+ err_cb = ble_gattc_err_dispatch_get(proc->op);
+ err_cb(proc, status, 0);
+
+ STAILQ_REMOVE_HEAD(&temp_list, next);
+ ble_gattc_proc_free(proc);
+ }
+}
+
/**
* Applies periodic checks and actions to all active procedures.
*
@@ -854,7 +916,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle,
* be called again; currently always
* UINT32_MAX.
*/
-uint32_t
+int32_t
ble_gattc_heartbeat(void)
{
struct ble_gattc_proc_list exp_list;
@@ -869,13 +931,13 @@ ble_gattc_heartbeat(void)
/* Terminate the connection associated with each timed-out procedure. */
while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
STATS_INC(ble_gattc_stats, proc_timeout);
- ble_gap_terminate(proc->conn_handle);
+ ble_gap_terminate(proc->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
STAILQ_REMOVE_HEAD(&exp_list, next);
ble_gattc_proc_free(proc);
}
- return UINT32_MAX;
+ return BLE_HS_FOREVER;
}
/**
@@ -883,13 +945,14 @@ ble_gattc_heartbeat(void)
* returned object is statically allocated, so this function is not reentrant.
* This function should only ever be called by the ble_hs task.
*/
-struct ble_gatt_error *
+static struct ble_gatt_error *
ble_gattc_error(int status, uint16_t att_handle)
{
static struct ble_gatt_error error;
- if (status == 0) {
- return NULL;
+ /* For consistency, always indicate a handle of 0 on success. */
+ if (status == 0 || status == BLE_HS_EDONE) {
+ att_handle = 0;
}
error.status = status;
@@ -917,7 +980,7 @@ ble_gattc_mtu_cb(struct ble_gattc_proc *proc, int status, uint16_t att_handle,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, mtu_fail);
}
@@ -949,7 +1012,10 @@ ble_gattc_mtu_err(struct ble_gattc_proc *proc, int status, uint16_t att_handle)
* procedure.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
@@ -976,16 +1042,10 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg)
ble_gattc_log_proc_init("exchange mtu\n");
ble_hs_lock();
- rc = ble_att_conn_chan_find(proc->conn_handle, &conn, &chan);
- if (rc == 0) {
- req.bamc_mtu = chan->blc_my_mtu;
- }
+ ble_att_conn_chan_find(proc->conn_handle, &conn, &chan);
+ req.bamc_mtu = chan->blc_my_mtu;
ble_hs_unlock();
- if (rc != 0) {
- goto done;
- }
-
rc = ble_att_clt_tx_mtu(proc->conn_handle, &req);
if (rc != 0) {
goto done;
@@ -1019,9 +1079,10 @@ ble_gattc_disc_all_svcs_cb(struct ble_gattc_proc *proc,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(service != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, disc_all_svcs_fail);
}
@@ -1077,7 +1138,7 @@ ble_gattc_disc_all_svcs_err(struct ble_gattc_proc *proc, int status,
if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_disc_all_svcs_cb(proc, status, att_handle, NULL);
@@ -1149,19 +1210,24 @@ ble_gattc_disc_all_svcs_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 || proc->disc_all_svcs.prev_handle == 0xffff) {
- /* Error or all svcs discovered. */
+ if (status != 0) {
ble_gattc_disc_all_svcs_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_disc_all_svcs_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
+ }
- return 0;
+ if (proc->disc_all_svcs.prev_handle == 0xffff) {
+ /* Service discovery complete. */
+ ble_gattc_disc_all_svcs_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
}
+
+ /* Send follow-up request. */
+ rc = ble_gattc_disc_all_svcs_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+
+ return 0;
}
/**
@@ -1171,7 +1237,8 @@ ble_gattc_disc_all_svcs_rx_complete(struct ble_gattc_proc *proc, int status)
* procedure.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
*/
int
ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb,
@@ -1233,9 +1300,10 @@ ble_gattc_disc_svc_uuid_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(service != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, disc_svc_uuid_fail);
}
@@ -1289,7 +1357,7 @@ ble_gattc_disc_svc_uuid_err(struct ble_gattc_proc *proc, int status,
if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_disc_svc_uuid_cb(proc, status, att_handle, NULL);
@@ -1343,18 +1411,24 @@ ble_gattc_disc_svc_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 || proc->disc_svc_uuid.prev_handle == 0xffff) {
- /* Error or all svcs discovered. */
+ if (status != 0) {
ble_gattc_disc_svc_uuid_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_disc_svc_uuid_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
- return 0;
}
+
+ if (proc->disc_svc_uuid.prev_handle == 0xffff) {
+ /* Service discovery complete. */
+ ble_gattc_disc_svc_uuid_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* Send follow-up request. */
+ rc = ble_gattc_disc_svc_uuid_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+
+ return 0;
}
/**
@@ -1365,10 +1439,13 @@ ble_gattc_disc_svc_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
* @param service_uuid128 The 128-bit UUID of the service to discover.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, void *service_uuid128,
+ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const void *svc_uuid128,
ble_gatt_disc_svc_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_DISC_SVC_UUID)
@@ -1388,7 +1465,7 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, void *service_uuid128,
proc->op = BLE_GATT_OP_DISC_SVC_UUID;
proc->conn_handle = conn_handle;
- memcpy(proc->disc_svc_uuid.service_uuid, service_uuid128, 16);
+ memcpy(proc->disc_svc_uuid.service_uuid, svc_uuid128, 16);
proc->disc_svc_uuid.prev_handle = 0x0000;
proc->disc_svc_uuid.cb = cb;
proc->disc_svc_uuid.cb_arg = cb_arg;
@@ -1428,9 +1505,10 @@ ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(service != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, find_inc_svcs_fail);
}
@@ -1499,7 +1577,7 @@ ble_gattc_find_inc_svcs_err(struct ble_gattc_proc *proc, int status,
status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_find_inc_svcs_cb(proc, status, att_handle, NULL);
@@ -1511,52 +1589,57 @@ ble_gattc_find_inc_svcs_err(struct ble_gattc_proc *proc, int status,
*/
static int
ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc, int status,
- void *value, int value_len)
+ struct os_mbuf **om)
{
struct ble_gatt_svc service;
- int cbrc;
+ uint16_t om_len;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ rc = ble_hs_mbuf_to_flat(*om, service.uuid128, 16, &om_len);
+ os_mbuf_free_chain(*om);
+ *om = NULL;
+
+ if (rc != 0 || om_len != 16) {
+ /* Invalid UUID. */
+ rc = BLE_HS_EBADDATA;
+ goto err;
+ }
+
if (proc->find_inc_svcs.cur_start == 0) {
/* Unexpected read response; terminate procedure. */
rc = BLE_HS_EBADDATA;
- goto done;
+ goto err;
}
if (status != 0) {
rc = status;
- goto done;
- }
-
- if (value_len != 16) {
- /* Invalid UUID. */
- rc = BLE_HS_EBADDATA;
- goto done;
+ goto err;
}
+ /* Report discovered service to application. */
service.start_handle = proc->find_inc_svcs.cur_start;
service.end_handle = proc->find_inc_svcs.cur_end;
- memcpy(service.uuid128, value, 16);
+ rc = ble_gattc_find_inc_svcs_cb(proc, 0, 0, &service);
+ if (rc != 0) {
+ /* Application has indicated that the procedure should be aborted. */
+ return BLE_HS_EDONE;
+ }
- /* We are done with this service; proceed to the next. */
+ /* Proceed to the next service. */
proc->find_inc_svcs.cur_start = 0;
proc->find_inc_svcs.cur_end = 0;
rc = ble_gattc_find_inc_svcs_go(proc, 1);
if (rc != 0) {
- goto done;
+ goto err;
}
- rc = 0;
+ return 0;
-done:
- cbrc = ble_gattc_find_inc_svcs_cb(proc, rc, 0, &service);
- if (rc != 0 || cbrc != 0) {
- return BLE_HS_EDONE;
- } else {
- return 0;
- }
+err:
+ ble_gattc_find_inc_svcs_cb(proc, rc, 0, NULL);
+ return BLE_HS_EDONE;
}
/**
@@ -1646,18 +1729,23 @@ ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 || proc->find_inc_svcs.prev_handle == 0xffff) {
- /* Error or all svcs discovered. */
+ if (status != 0) {
ble_gattc_find_inc_svcs_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_find_inc_svcs_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
- return 0;
}
+
+ if (proc->find_inc_svcs.prev_handle == 0xffff) {
+ /* Procedure complete. */
+ ble_gattc_find_inc_svcs_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* Send follow-up request. */
+ rc = ble_gattc_find_inc_svcs_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+ return 0;
}
/**
@@ -1671,7 +1759,10 @@ ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc, int status)
* last handle in the service).
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
@@ -1734,9 +1825,10 @@ ble_gattc_disc_all_chrs_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(chr != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, disc_all_chrs_fail);
}
@@ -1794,7 +1886,7 @@ ble_gattc_disc_all_chrs_err(struct ble_gattc_proc *proc, int status,
if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_disc_all_chrs_cb(proc, status, att_handle, NULL);
@@ -1869,20 +1961,23 @@ ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 ||
- proc->disc_all_chrs.prev_handle == proc->disc_all_chrs.end_handle) {
-
- /* Error or all svcs discovered. */
+ if (status != 0) {
ble_gattc_disc_all_chrs_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_disc_all_chrs_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
- return 0;
}
+
+ if (proc->disc_all_chrs.prev_handle == proc->disc_all_chrs.end_handle) {
+ /* Characteristic discovery complete. */
+ ble_gattc_disc_all_chrs_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* Send follow-up request. */
+ rc = ble_gattc_disc_all_chrs_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+ return 0;
}
/**
@@ -1896,7 +1991,10 @@ ble_gattc_disc_all_chrs_rx_complete(struct ble_gattc_proc *proc, int status)
* last handle in the service).
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
@@ -1959,9 +2057,10 @@ ble_gattc_disc_chr_uuid_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(chr != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, disc_chrs_uuid_fail);
}
@@ -2019,7 +2118,7 @@ ble_gattc_disc_chr_uuid_err(struct ble_gattc_proc *proc, int status,
if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_disc_chr_uuid_cb(proc, status, att_handle, NULL);
@@ -2076,11 +2175,14 @@ ble_gattc_disc_chr_uuid_rx_adata(struct ble_gattc_proc *proc,
rc = 0;
done:
- if (rc != 0 ||
- memcmp(chr.uuid128, proc->disc_chr_uuid.chr_uuid, 16) == 0) {
-
- cbrc = ble_gattc_disc_chr_uuid_cb(proc, rc, 0, &chr);
+ if (rc != 0) {
+ /* Failure. */
+ cbrc = ble_gattc_disc_chr_uuid_cb(proc, rc, 0, NULL);
+ } else if (memcmp(chr.uuid128, proc->disc_chr_uuid.chr_uuid, 16) == 0) {
+ /* Requested characteristic discovered. */
+ cbrc = ble_gattc_disc_chr_uuid_cb(proc, 0, 0, &chr);
} else {
+ /* Uninteresting characteristic; ignore. */
cbrc = 0;
}
@@ -2102,20 +2204,23 @@ ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 ||
- proc->disc_chr_uuid.prev_handle == proc->disc_chr_uuid.end_handle) {
-
- /* Error or all svcs discovered. */
+ if (status != 0) {
ble_gattc_disc_chr_uuid_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_disc_chr_uuid_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
- return 0;
}
+
+ if (proc->disc_chr_uuid.prev_handle == proc->disc_chr_uuid.end_handle) {
+ /* Characteristic discovery complete. */
+ ble_gattc_disc_chr_uuid_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* Send follow-up request. */
+ rc = ble_gattc_disc_chr_uuid_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+ return 0;
}
/**
@@ -2131,11 +2236,14 @@ ble_gattc_disc_chr_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
* discover.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
- uint16_t end_handle, void *uuid128,
+ uint16_t end_handle, const void *uuid128,
ble_gatt_chr_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_DISC_CHR_UUID)
@@ -2195,9 +2303,10 @@ ble_gattc_disc_all_dscs_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(dsc != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, disc_all_dscs_fail);
}
@@ -2206,7 +2315,7 @@ ble_gattc_disc_all_dscs_cb(struct ble_gattc_proc *proc, int status,
} else {
rc = proc->disc_all_dscs.cb(proc->conn_handle,
ble_gattc_error(status, att_handle),
- proc->disc_all_dscs.chr_def_handle,
+ proc->disc_all_dscs.chr_val_handle,
dsc, proc->disc_all_dscs.cb_arg);
}
@@ -2250,7 +2359,7 @@ ble_gattc_disc_all_dscs_err(struct ble_gattc_proc *proc, int status,
if (status == BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_FOUND)) {
/* Discovery is complete. */
- status = 0;
+ status = BLE_HS_EDONE;
}
ble_gattc_disc_all_dscs_cb(proc, status, att_handle, NULL);
@@ -2302,20 +2411,24 @@ ble_gattc_disc_all_dscs_rx_complete(struct ble_gattc_proc *proc, int status)
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0 ||
- proc->disc_all_dscs.prev_handle == proc->disc_all_dscs.end_handle) {
-
- /* Error or all descriptors discovered. */
+ if (status != 0) {
ble_gattc_disc_all_dscs_cb(proc, status, 0, NULL);
return BLE_HS_EDONE;
- } else {
- /* Send follow-up request. */
- rc = ble_gattc_disc_all_dscs_go(proc, 1);
- if (rc != 0) {
- return BLE_HS_EDONE;
- }
- return 0;
}
+
+ if (proc->disc_all_dscs.prev_handle == proc->disc_all_dscs.end_handle) {
+ /* All descriptors discovered. */
+ ble_gattc_disc_all_dscs_cb(proc, BLE_HS_EDONE, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* Send follow-up request. */
+ rc = ble_gattc_disc_all_dscs_go(proc, 1);
+ if (rc != 0) {
+ return BLE_HS_EDONE;
+ }
+
+ return 0;
}
/**
@@ -2323,16 +2436,19 @@ ble_gattc_disc_all_dscs_rx_complete(struct ble_gattc_proc *proc, int status)
*
* @param conn_handle The connection over which to execute the
* procedure.
- * @param chr_def_handle The handle of the characteristic definition
+ * @param chr_val_handle The handle of the characteristic value
* attribute.
* @param chr_end_handle The last handle in the characteristic
* definition.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_def_handle,
+ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_val_handle,
uint16_t chr_end_handle,
ble_gatt_dsc_fn *cb, void *cb_arg)
{
@@ -2353,8 +2469,8 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t chr_def_handle,
proc->op = BLE_GATT_OP_DISC_ALL_DSCS;
proc->conn_handle = conn_handle;
- proc->disc_all_dscs.chr_def_handle = chr_def_handle;
- proc->disc_all_dscs.prev_handle = chr_def_handle + 1;
+ proc->disc_all_dscs.chr_val_handle = chr_val_handle;
+ proc->disc_all_dscs.prev_handle = chr_val_handle;
proc->disc_all_dscs.end_handle = chr_end_handle;
proc->disc_all_dscs.cb = cb;
proc->disc_all_dscs.cb_arg = cb_arg;
@@ -2393,9 +2509,10 @@ ble_gattc_read_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(attr != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, read_fail);
}
@@ -2428,7 +2545,7 @@ ble_gattc_read_err(struct ble_gattc_proc *proc, int status,
*/
static int
ble_gattc_read_rx_read_rsp(struct ble_gattc_proc *proc, int status,
- void *value, int value_len)
+ struct os_mbuf **om)
{
struct ble_gatt_attr attr;
@@ -2436,11 +2553,13 @@ ble_gattc_read_rx_read_rsp(struct ble_gattc_proc *proc, int status,
attr.handle = proc->read.handle;
attr.offset = 0;
- attr.value_len = value_len;
- attr.value = value;
+ attr.om = *om;
ble_gattc_read_cb(proc, status, 0, &attr);
+ /* Indicate to the caller whether the application consumed the mbuf. */
+ *om = attr.om;
+
/* The read operation only has a single request / response exchange. */
return BLE_HS_EDONE;
}
@@ -2453,7 +2572,10 @@ ble_gattc_read_rx_read_rsp(struct ble_gattc_proc *proc, int status,
* @param attr_handle The handle of the characteristic value to read.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
@@ -2516,9 +2638,10 @@ ble_gattc_read_uuid_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(attr != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, read_uuid_fail);
}
@@ -2565,10 +2688,18 @@ ble_gattc_read_uuid_rx_adata(struct ble_gattc_proc *proc,
attr.handle = adata->att_handle;
attr.offset = 0;
- attr.value_len = adata->value_len;
- attr.value = adata->value;
+ attr.om = ble_hs_mbuf_from_flat(adata->value, adata->value_len);
+ if (attr.om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ } else {
+ rc = 0;
+ }
+
+ rc = ble_gattc_read_uuid_cb(proc, rc, 0, &attr);
+
+ /* Free the attribute mbuf if the application has not consumed it. */
+ os_mbuf_free_chain(attr.om);
- rc = ble_gattc_read_uuid_cb(proc, 0, 0, &attr);
if (rc != 0) {
return BLE_HS_EDONE;
}
@@ -2584,7 +2715,16 @@ static int
ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
{
ble_gattc_dbg_assert_proc_not_inserted(proc);
- ble_gattc_read_uuid_cb(proc, status, 0, NULL);
+
+ if (status != 0) {
+ ble_gattc_read_uuid_cb(proc, status, 0, NULL);
+ return BLE_HS_EDONE;
+ }
+
+ /* XXX: We may need to send a follow-up request to address the possibility
+ * of multiple characteristics with identical UUIDs.
+ */
+ ble_gattc_read_uuid_cb(proc, BLE_HS_EDONE, 0, NULL);
return BLE_HS_EDONE;
}
@@ -2599,11 +2739,14 @@ ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc, int status)
* last handle in the service definition).
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
- uint16_t end_handle, void *uuid128,
+ uint16_t end_handle, const void *uuid128,
ble_gatt_attr_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_READ_UUID)
@@ -2663,9 +2806,10 @@ ble_gattc_read_long_cb(struct ble_gattc_proc *proc, int status,
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(attr != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, read_long_fail);
}
@@ -2729,21 +2873,27 @@ ble_gattc_read_long_err(struct ble_gattc_proc *proc, int status,
*/
static int
ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status,
- void *value, int value_len)
+ struct os_mbuf **om)
{
struct ble_gatt_attr attr;
+ uint16_t data_len;
uint16_t mtu;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ data_len = OS_MBUF_PKTLEN(*om);
+
attr.handle = proc->read_long.handle;
attr.offset = proc->read_long.offset;
- attr.value_len = value_len;
- attr.value = value;
+ attr.om = *om;
/* Report partial payload to application. */
rc = ble_gattc_read_long_cb(proc, status, 0, &attr);
+
+ /* Indicate to the caller whether the application consumed the mbuf. */
+ *om = attr.om;
+
if (rc != 0 || status != 0) {
return BLE_HS_EDONE;
}
@@ -2755,13 +2905,14 @@ ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status,
return BLE_HS_EDONE;
}
- if (value_len < mtu - 1) {
- ble_gattc_read_long_cb(proc, 0, 0, NULL);
+ if (data_len < mtu - 1) {
+ /* Response shorter than maximum allowed; read complete. */
+ ble_gattc_read_long_cb(proc, BLE_HS_EDONE, 0, NULL);
return BLE_HS_EDONE;
}
/* Send follow-up request. */
- proc->read_long.offset += value_len;
+ proc->read_long.offset += data_len;
rc = ble_gattc_read_long_go(proc, 1);
if (rc != 0) {
return BLE_HS_EDONE;
@@ -2778,7 +2929,10 @@ ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status,
* @param handle The handle of the characteristic value to read.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_read_long(uint16_t conn_handle, uint16_t handle,
@@ -2835,38 +2989,40 @@ done:
*/
static int
ble_gattc_read_mult_cb(struct ble_gattc_proc *proc, int status,
- uint16_t att_handle, uint8_t *attr_data,
- uint16_t attr_data_len)
+ uint16_t att_handle, struct os_mbuf **om)
{
- struct ble_gatt_attr *attrp;
struct ble_gatt_attr attr;
int rc;
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
+ BLE_HS_DBG_ASSERT(om != NULL || status != 0);
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, read_mult_fail);
}
+ attr.handle = 0;
+ attr.offset = 0;
+ if (om == NULL) {
+ attr.om = NULL;
+ } else {
+ attr.om = *om;
+ }
+
if (proc->read_mult.cb == NULL) {
rc = 0;
} else {
- if (status != 0) {
- attrp = NULL;
- } else {
- attrp = &attr;
- attr.handle = 0;
- attr.offset = 0;
- attr.value_len = attr_data_len;
- attr.value = attr_data;
- }
-
rc = proc->read_mult.cb(proc->conn_handle,
- ble_gattc_error(status, att_handle), attrp,
+ ble_gattc_error(status, att_handle), &attr,
proc->read_mult.cb_arg);
}
+ /* Indicate to the caller whether the application consumed the mbuf. */
+ if (om != NULL) {
+ *om = attr.om;
+ }
+
return rc;
}
@@ -2879,7 +3035,7 @@ ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status,
uint16_t att_handle)
{
ble_gattc_dbg_assert_proc_not_inserted(proc);
- ble_gattc_read_mult_cb(proc, status, att_handle, NULL, 0);
+ ble_gattc_read_mult_cb(proc, status, att_handle, NULL);
}
/**
@@ -2891,10 +3047,13 @@ ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status,
* @param num_handles The number of entries in the "handles" array.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_read_mult(uint16_t conn_handle, uint16_t *handles,
+ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_fn *cb,
void *cb_arg)
{
@@ -2939,21 +3098,20 @@ done:
*****************************************************************************/
/**
- * Initiates GATT procedure: Write Without Response.
+ * Initiates GATT procedure: Write Without Response. This function consumes
+ * the supplied mbuf regardless of the outcome.
*
* @param conn_handle The connection over which to execute the
* procedure.
* @param attr_handle The handle of the characteristic value to write
* to.
- * @param value The value to write to the characteristic.
- * @param value_len The number of bytes to write.
- * @param cb The function to call to report procedure status
- * updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param txom The value to write to the characteristic.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, void *value,
- uint16_t value_len)
+ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(GATT_WRITE_NO_RSP)
return BLE_HS_ENOTSUP;
@@ -2964,10 +3122,10 @@ ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, void *value,
STATS_INC(ble_gattc_stats, write_no_rsp);
- ble_gattc_log_write(attr_handle, value_len, 0);
+ ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 0);
req.bawq_handle = attr_handle;
- rc = ble_att_clt_tx_write_cmd(conn_handle, &req, value, value_len);
+ rc = ble_att_clt_tx_write_cmd(conn_handle, &req, txom);
if (rc != 0) {
STATS_INC(ble_gattc_stats, write);
}
@@ -2975,6 +3133,39 @@ ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, void *value,
return rc;
}
+/**
+ * Initiates GATT procedure: Write Without Response. This function consumes
+ * the supplied mbuf regardless of the outcome.
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param attr_handle The handle of the characteristic value to write
+ * to.
+ * @param value The value to write to the characteristic.
+ * @param value_len The number of bytes to write.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_gattc_write_no_rsp_flat(uint16_t conn_handle, uint16_t attr_handle,
+ const void *data, uint16_t data_len)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_mbuf_from_flat(data, data_len);
+ if (om == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ rc = ble_gattc_write_no_rsp(conn_handle, attr_handle, om);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
/*****************************************************************************
* $write *
*****************************************************************************/
@@ -2996,7 +3187,7 @@ ble_gattc_write_cb(struct ble_gattc_proc *proc, int status,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, write_fail);
}
@@ -3026,21 +3217,24 @@ ble_gattc_write_err(struct ble_gattc_proc *proc, int status,
}
/**
- * Initiates GATT procedure: Write Characteristic Value.
+ * Initiates GATT procedure: Write Characteristic Value. This function
+ * consumes the supplied mbuf regardless of the outcome.
*
* @param conn_handle The connection over which to execute the
* procedure.
* @param attr_handle The handle of the characteristic value to write
* to.
- * @param value The value to write to the characteristic.
- * @param value_len The number of bytes to write.
+ * @param txom The value to write to the characteristic.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
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)
+ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle,
+ struct os_mbuf *txom, ble_gatt_attr_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_WRITE)
return BLE_HS_ENOTSUP;
@@ -3064,10 +3258,11 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, void *value,
proc->write.cb = cb;
proc->write.cb_arg = cb_arg;
- ble_gattc_log_write(attr_handle, value_len, 1);
+ ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 1);
req.bawq_handle = attr_handle;
- rc = ble_att_clt_tx_write_req(conn_handle, &req, value, value_len);
+ rc = ble_att_clt_tx_write_req(conn_handle, &req, txom);
+ txom = NULL;
if (rc != 0) {
goto done;
}
@@ -3077,10 +3272,50 @@ done:
STATS_INC(ble_gattc_stats, write_fail);
}
+ /* Free the mbuf in case the send failed. */
+ os_mbuf_free_chain(txom);
+
ble_gattc_process_status(proc, rc);
return rc;
}
+/**
+ * Initiates GATT procedure: Write Characteristic Value (flat buffer version).
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param attr_handle The handle of the characteristic value to write
+ * to.
+ * @param value The value to write to the characteristic.
+ * @param value_len The number of bytes to write.
+ * @param cb The function to call to report procedure status
+ * updates; null for no callback.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_gattc_write_flat(uint16_t conn_handle, uint16_t attr_handle,
+ const void *data, uint16_t data_len,
+ ble_gatt_attr_fn *cb, void *cb_arg)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_mbuf_from_flat(data, data_len);
+ if (om == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ rc = ble_gattc_write(conn_handle, attr_handle, om, cb, cb_arg);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
/*****************************************************************************
* $write long *
*****************************************************************************/
@@ -3101,7 +3336,7 @@ ble_gattc_write_long_cb(struct ble_gattc_proc *proc, int status,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, write_long_fail);
}
@@ -3126,48 +3361,65 @@ ble_gattc_write_long_go(struct ble_gattc_proc *proc, int cb_on_err)
{
struct ble_att_prep_write_cmd prep_req;
struct ble_att_exec_write_req exec_req;
- void *value;
+ struct os_mbuf *om;
+ int write_len;
int max_sz;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (proc->write_long.attr.offset < proc->write_long.attr.value_len) {
- max_sz = ble_att_mtu(proc->conn_handle) -
- BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
- if (max_sz == 0) {
- /* Not connected. */
- rc = BLE_HS_ENOTCONN;
- } else {
- if (proc->write_long.attr.offset + max_sz >
- proc->write_long.attr.value_len) {
+ om = NULL;
- proc->write_long.length = proc->write_long.attr.value_len -
- proc->write_long.attr.offset;
- } else {
- proc->write_long.length = max_sz;
- }
+ max_sz = ble_att_mtu(proc->conn_handle) -
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ if (max_sz <= 0) {
+ /* Not connected. */
+ rc = BLE_HS_ENOTCONN;
+ goto done;
+ }
- prep_req.bapc_handle = proc->write_long.attr.handle;
- prep_req.bapc_offset = proc->write_long.attr.offset;
- value = proc->write_long.attr.value + proc->write_long.attr.offset;
- rc = ble_att_clt_tx_prep_write(proc->conn_handle,
- &prep_req, value,
- proc->write_long.length);
- }
- } else {
+ write_len = min(max_sz,
+ OS_MBUF_PKTLEN(proc->write_long.attr.om) -
+ proc->write_long.attr.offset);
+
+ if (write_len <= 0) {
exec_req.baeq_flags = BLE_ATT_EXEC_WRITE_F_CONFIRM;
rc = ble_att_clt_tx_exec_write(proc->conn_handle, &exec_req);
+ goto done;
+ }
+
+ proc->write_long.length = write_len;
+ om = ble_hs_mbuf_att_pkt();
+ if (om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
}
+ rc = os_mbuf_appendfrom(om, proc->write_long.attr.om,
+ proc->write_long.attr.offset,
+ proc->write_long.length);
if (rc != 0) {
- if (cb_on_err) {
- ble_gattc_write_long_cb(proc, rc, 0);
- }
- return rc;
+ rc = BLE_HS_ENOMEM;
+ goto done;
}
- return 0;
+ prep_req.bapc_handle = proc->write_long.attr.handle;
+ prep_req.bapc_offset = proc->write_long.attr.offset;
+
+ rc = ble_att_clt_tx_prep_write(proc->conn_handle, &prep_req, om);
+ om = NULL;
+ if (rc != 0) {
+ goto done;
+ }
+
+done:
+ os_mbuf_free_chain(om);
+
+ if (rc != 0 && cb_on_err) {
+ ble_gattc_write_long_cb(proc, rc, 0);
+ }
+
+ return rc;
}
/**
@@ -3181,17 +3433,20 @@ ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status,
struct ble_att_exec_write_req exec_req;
ble_gattc_dbg_assert_proc_not_inserted(proc);
- ble_gattc_write_long_cb(proc, status, att_handle);
/* If we have successfully queued any data, and the failure occurred before
* we could send the execute write command, then erase all queued data.
*/
if (proc->write_long.attr.offset > 0 &&
- proc->write_long.attr.offset < proc->write_long.attr.value_len) {
+ proc->write_long.attr.offset <
+ OS_MBUF_PKTLEN(proc->write_long.attr.om)) {
exec_req.baeq_flags = 0;
ble_att_clt_tx_exec_write(proc->conn_handle, &exec_req);
}
+
+ /* Report failure. */
+ ble_gattc_write_long_cb(proc, status, att_handle);
}
/**
@@ -3201,18 +3456,31 @@ ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status,
static int
ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc,
int status, struct ble_att_prep_write_cmd *rsp,
- void *attr_data, uint16_t attr_len)
+ struct os_mbuf **rxom)
{
+ struct os_mbuf *om;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ /* Let the caller free the mbuf. */
+ om = *rxom;
+
if (status != 0) {
rc = status;
goto err;
}
/* Verify the response. */
+ if (proc->write_long.attr.offset >=
+ OS_MBUF_PKTLEN(proc->write_long.attr.om)) {
+
+ /* Expecting a prepare write response, not an execute write
+ * response.
+ */
+ rc = BLE_HS_EBADDATA;
+ goto err;
+ }
if (rsp->bapc_handle != proc->write_long.attr.handle) {
rc = BLE_HS_EBADDATA;
goto err;
@@ -3221,22 +3489,26 @@ ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc,
rc = BLE_HS_EBADDATA;
goto err;
}
- if (rsp->bapc_offset + attr_len > proc->write_long.attr.value_len) {
+ if (rsp->bapc_offset + OS_MBUF_PKTLEN(om) >
+ OS_MBUF_PKTLEN(proc->write_long.attr.om)) {
+
rc = BLE_HS_EBADDATA;
goto err;
}
- if (attr_len != proc->write_long.length) {
+ if (OS_MBUF_PKTLEN(om) != proc->write_long.length) {
rc = BLE_HS_EBADDATA;
goto err;
}
- if (memcmp(attr_data, proc->write_long.attr.value + rsp->bapc_offset,
- attr_len) != 0) {
+ if (os_mbuf_cmpm(om, 0,
+ proc->write_long.attr.om, rsp->bapc_offset,
+ proc->write_long.length) != 0) {
+
rc = BLE_HS_EBADDATA;
goto err;
}
/* Send follow-up request. */
- proc->write_long.attr.offset += attr_len;
+ proc->write_long.attr.offset += OS_MBUF_PKTLEN(om);
rc = ble_gattc_write_long_go(proc, 1);
if (rc != 0) {
goto err;
@@ -3258,26 +3530,39 @@ static int
ble_gattc_write_long_rx_exec(struct ble_gattc_proc *proc, int status)
{
ble_gattc_dbg_assert_proc_not_inserted(proc);
+
+ if (proc->write_long.attr.offset <
+ OS_MBUF_PKTLEN(proc->write_long.attr.om)) {
+
+ /* Expecting an execute write response, not a prepare write
+ * response.
+ */
+ return BLE_HS_EBADDATA;
+ }
+
ble_gattc_write_long_cb(proc, status, 0);
return BLE_HS_EDONE;
}
/**
- * Initiates GATT procedure: Write Long Characteristic Values.
+ * Initiates GATT procedure: Write Long Characteristic Values. This function
+ * consumes the supplied mbuf regardless of the outcome.
*
* @param conn_handle The connection over which to execute the
* procedure.
* @param attr_handle The handle of the characteristic value to write
* to.
- * @param value The value to write to the characteristic.
- * @param value_len The number of bytes to write.
+ * @param txom The value to write to the characteristic.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success; nonzero on failure.
*/
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)
+ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle,
+ struct os_mbuf *txom, ble_gatt_attr_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_WRITE_LONG)
return BLE_HS_ENOTSUP;
@@ -3298,11 +3583,13 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, void *value,
proc->conn_handle = conn_handle;
proc->write_long.attr.handle = attr_handle;
proc->write_long.attr.offset = 0;
- proc->write_long.attr.value = value;
- proc->write_long.attr.value_len = value_len;
+ proc->write_long.attr.om = txom;
proc->write_long.cb = cb;
proc->write_long.cb_arg = cb_arg;
+ /* The mbuf is consumed by the procedure. */
+ txom = NULL;
+
ble_gattc_log_write_long(proc);
rc = ble_gattc_write_long_go(proc, 0);
@@ -3315,6 +3602,9 @@ done:
STATS_INC(ble_gattc_stats, write_long_fail);
}
+ /* Free the mbuf in case of failure. */
+ os_mbuf_free_chain(txom);
+
ble_gattc_process_status(proc, rc);
return rc;
}
@@ -3339,7 +3629,7 @@ ble_gattc_write_reliable_cb(struct ble_gattc_proc *proc, int status,
BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
+ if (status != 0 && status != BLE_HS_EDONE) {
STATS_INC(ble_gattc_stats, write_reliable_fail);
}
@@ -3366,31 +3656,65 @@ ble_gattc_write_reliable_go(struct ble_gattc_proc *proc, int cb_on_err)
struct ble_att_prep_write_cmd prep_req;
struct ble_att_exec_write_req exec_req;
struct ble_gatt_attr *attr;
+ struct os_mbuf *om;
+ uint16_t max_sz;
int attr_idx;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ om = NULL;
+
attr_idx = proc->write_reliable.cur_attr;
- if (attr_idx < proc->write_reliable.num_attrs) {
- attr = proc->write_reliable.attrs + attr_idx;
- prep_req.bapc_handle = attr->handle;
- prep_req.bapc_offset = 0;
- rc = ble_att_clt_tx_prep_write(proc->conn_handle, &prep_req,
- attr->value, attr->value_len);
- } else {
+
+ if (attr_idx >= proc->write_reliable.num_attrs) {
exec_req.baeq_flags = BLE_ATT_EXEC_WRITE_F_CONFIRM;
rc = ble_att_clt_tx_exec_write(proc->conn_handle, &exec_req);
+ goto done;
+ }
+
+ attr = proc->write_reliable.attrs + attr_idx;
+
+ max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ if (max_sz <= 0) {
+ /* Not connected. */
+ rc = BLE_HS_ENOTCONN;
+ goto done;
+ }
+
+ proc->write_reliable.length =
+ min(max_sz, OS_MBUF_PKTLEN(attr->om) - attr->offset);
+
+ om = ble_hs_mbuf_att_pkt();
+ if (om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
}
+ rc = os_mbuf_appendfrom(om, attr->om, attr->offset,
+ proc->write_reliable.length);
if (rc != 0) {
- if (cb_on_err) {
- ble_gattc_write_reliable_cb(proc, rc, 0);
- }
- return rc;
+ rc = BLE_HS_ENOMEM;
+ goto done;
}
- return 0;
+ prep_req.bapc_handle = attr->handle;
+ prep_req.bapc_offset = attr->offset;
+
+ rc = ble_att_clt_tx_prep_write(proc->conn_handle, &prep_req, om);
+ om = NULL;
+ if (rc != 0) {
+ goto done;
+ }
+
+done:
+ os_mbuf_free_chain(om);
+
+ if (rc != 0 && cb_on_err) {
+ ble_gattc_write_reliable_cb(proc, rc, 0);
+ }
+
+ return rc;
}
/**
@@ -3425,19 +3749,26 @@ static int
ble_gattc_write_reliable_rx_prep(struct ble_gattc_proc *proc,
int status,
struct ble_att_prep_write_cmd *rsp,
- void *attr_data, uint16_t attr_len)
+ struct os_mbuf **rxom)
{
struct ble_gatt_attr *attr;
+ struct os_mbuf *om;
int rc;
ble_gattc_dbg_assert_proc_not_inserted(proc);
+ /* Let the caller free the mbuf. */
+ om = *rxom;
+
if (status != 0) {
rc = status;
goto err;
}
if (proc->write_reliable.cur_attr >= proc->write_reliable.num_attrs) {
+ /* Expecting an execute write response, not a prepare write
+ * response.
+ */
rc = BLE_HS_EBADDATA;
goto err;
}
@@ -3448,21 +3779,23 @@ ble_gattc_write_reliable_rx_prep(struct ble_gattc_proc *proc,
rc = BLE_HS_EBADDATA;
goto err;
}
- if (rsp->bapc_offset != 0) {
+ if (rsp->bapc_offset != attr->offset) {
rc = BLE_HS_EBADDATA;
goto err;
}
- if (attr_len != attr->value_len) {
- rc = BLE_HS_EBADDATA;
- goto err;
- }
- if (memcmp(attr_data, attr->value, attr_len) != 0) {
+ if (os_mbuf_cmpm(attr->om, rsp->bapc_offset, om, 0,
+ proc->write_reliable.length) != 0) {
+
rc = BLE_HS_EBADDATA;
goto err;
}
/* Send follow-up request. */
- proc->write_reliable.cur_attr++;
+ attr->offset += proc->write_reliable.length;
+ if (attr->offset >= OS_MBUF_PKTLEN(attr->om)) {
+ attr->offset = 0;
+ proc->write_reliable.cur_attr++;
+ }
rc = ble_gattc_write_reliable_go(proc, 1);
if (rc != 0) {
goto err;
@@ -3489,22 +3822,29 @@ ble_gattc_write_reliable_rx_exec(struct ble_gattc_proc *proc, int status)
}
/**
- * Initiates GATT procedure: Write Long Characteristic Values.
+ * Initiates GATT procedure: Reliable Writes. This function consumes the
+ * supplied mbufs regardless of the outcome.
*
* @param conn_handle The connection over which to execute the
* procedure.
- * @param attr_handle The handle of the characteristic value to write
- * to.
- * @param value The value to write to the characteristic.
- * @param value_len The number of bytes to write.
+ * @param attrs An array of attribute descriptors; specifies
+ * which characteristics to write to and what
+ * data to write to them. The mbuf pointer in
+ * each attribute is set to NULL by this
+ * function.
+ * @param num_attrs The number of characteristics to write; equal
+ * to the number of elements in the 'attrs'
+ * array.
* @param cb The function to call to report procedure status
* updates; null for no callback.
- * @param cb_arg The argument to pass to the callback function.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
*/
int
-ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs,
- int num_attrs, ble_gatt_reliable_attr_fn *cb,
- void *cb_arg)
+ble_gattc_write_reliable(uint16_t conn_handle,
+ struct ble_gatt_attr *attrs,
+ int num_attrs,
+ ble_gatt_reliable_attr_fn *cb, void *cb_arg)
{
#if !NIMBLE_OPT(GATT_WRITE_RELIABLE)
return BLE_HS_ENOTSUP;
@@ -3512,9 +3852,17 @@ ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs,
struct ble_gattc_proc *proc;
int rc;
+ int i;
+
+ proc = NULL;
STATS_INC(ble_gattc_stats, write_reliable);
+ if (num_attrs > NIMBLE_OPT(GATT_WRITE_MAX_ATTRS)) {
+ rc = BLE_HS_EINVAL;
+ goto done;
+ }
+
proc = ble_gattc_proc_alloc();
if (proc == NULL) {
rc = BLE_HS_ENOMEM;
@@ -3523,12 +3871,19 @@ ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs,
proc->op = BLE_GATT_OP_WRITE_RELIABLE;
proc->conn_handle = conn_handle;
- proc->write_reliable.attrs = attrs;
proc->write_reliable.num_attrs = num_attrs;
proc->write_reliable.cur_attr = 0;
proc->write_reliable.cb = cb;
proc->write_reliable.cb_arg = cb_arg;
+ for (i = 0; i < num_attrs; i++) {
+ proc->write_reliable.attrs[i] = attrs[i];
+ proc->write_reliable.attrs[i].offset = 0;
+
+ /* Consume mbuf from caller. */
+ attrs[i].om = NULL;
+ }
+
ble_gattc_log_write_reliable(proc);
rc = ble_gattc_write_reliable_go(proc, 1);
@@ -3541,6 +3896,12 @@ done:
STATS_INC(ble_gattc_stats, write_reliable_fail);
}
+ /* Free supplied mbufs in case something failed. */
+ for (i = 0; i < num_attrs; i++) {
+ os_mbuf_free_chain(attrs[i].om);
+ attrs[i].om = NULL;
+ }
+
ble_gattc_process_status(proc, rc);
return rc;
}
@@ -3550,45 +3911,53 @@ done:
*****************************************************************************/
/**
- * Sends an attribute notification. The content of the message is specified
- * in the attr parameter.
+ * Sends a "free-form" characteristic notification. This function consumes the
+ * supplied mbuf regardless of the outcome.
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param chr_val_handle The attribute handle to indicate in the
+ * outgoing notification.
+ * @param txom The value to write to the characteristic.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle,
- void *attr_data, uint16_t attr_data_len)
+ble_gattc_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle,
+ struct os_mbuf *txom)
{
#if !NIMBLE_OPT(GATT_NOTIFY)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_notify_req req;
int rc;
STATS_INC(ble_gattc_stats, notify);
- ble_gattc_log_notify(att_handle);
+ ble_gattc_log_notify(chr_val_handle);
- if (attr_data == NULL) {
+ if (txom == NULL) {
/* No custom attribute data; read the value from the specified
* attribute.
*/
+ txom = ble_hs_mbuf_att_pkt();
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE,
- att_handle, &ctxt, NULL);
+ chr_val_handle, 0, txom, NULL);
if (rc != 0) {
/* Fatal error; application disallowed attribute read. */
rc = BLE_HS_EAPP;
goto err;
}
- } else {
- ctxt.attr_data = attr_data;
- ctxt.data_len = attr_data_len;
- ctxt.offset = 0;
}
- req.banq_handle = att_handle;
- rc = ble_att_clt_tx_notify(conn_handle, &req,
- ctxt.attr_data, ctxt.data_len);
+ req.banq_handle = chr_val_handle;
+ rc = ble_att_clt_tx_notify(conn_handle, &req, txom);
+ txom = NULL;
if (rc != 0) {
goto err;
}
@@ -3596,13 +3965,26 @@ ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle,
return 0;
err:
- STATS_INC(ble_gattc_stats, notify_fail);
+ if (rc != 0) {
+ STATS_INC(ble_gattc_stats, notify_fail);
+ }
+
+ os_mbuf_free_chain(txom);
+
return rc;
}
/**
- * Sends an attribute notification. The content of the message is read from
- * the specified characteristic.
+ * Sends a characteristic notification. The content of the message is read
+ * from the specified characteristic.
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param chr_val_handle The value attribute handle of the
+ * characteristic to include in the outgoing
+ * notification.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle)
@@ -3613,12 +3995,12 @@ ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle)
int rc;
- rc = ble_gattc_notify_custom(conn_handle, chr_val_handle, NULL, 0);
- if (rc != 0) {
- return rc;
- }
+ rc = ble_gattc_notify_custom(conn_handle, chr_val_handle, NULL);
- return 0;
+ /* Tell the application that a notification transmission was attempted. */
+ ble_gap_notify_tx_event(rc, conn_handle, chr_val_handle, 0);
+
+ return rc;
}
/*****************************************************************************
@@ -3626,48 +4008,33 @@ ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle)
*****************************************************************************/
/**
- * Calls an indication proc's callback with the specified parameters. If the
- * proc has no callback, this function is a no-op.
- *
- * @return The return code of the callback (or 0 if there
- * is no callback).
+ * Handles an incoming ATT error response for the specified indication proc.
+ * A device should never send an error in response to an indication. If this
+ * happens, we treat it like a confirmation (indication ack), but report the
+ * error status to the application.
*/
-static int
-ble_gattc_indicate_cb(struct ble_gattc_proc *proc, int status,
- uint16_t att_handle)
+static void
+ble_gattc_indicate_err(struct ble_gattc_proc *proc, int status,
+ uint16_t att_handle)
{
- struct ble_gatt_attr attr;
int rc;
- BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
ble_gattc_dbg_assert_proc_not_inserted(proc);
- if (status != 0) {
- STATS_INC(ble_gattc_stats, indicate_fail);
- }
-
- if (proc->indicate.cb == NULL) {
- rc = 0;
- } else {
- memset(&attr, 0, sizeof attr);
- attr.handle = proc->indicate.chr_val_handle;
- rc = proc->indicate.cb(proc->conn_handle,
- ble_gattc_error(status, att_handle),
- &attr, proc->indicate.cb_arg);
+ if (status != BLE_HS_ENOTCONN) {
+ rc = ble_gatts_rx_indicate_ack(proc->conn_handle,
+ proc->indicate.chr_val_handle);
+ if (rc != 0) {
+ return;
+ }
}
- return rc;
-}
+ /* Tell the application about the received acknowledgment. */
+ ble_gap_notify_tx_event(status, proc->conn_handle,
+ proc->indicate.chr_val_handle, 1);
-/**
- * Handles an incoming ATT error response for the specified indication proc.
- */
-static void
-ble_gattc_indicate_err(struct ble_gattc_proc *proc, int status,
- uint16_t att_handle)
-{
- ble_gattc_dbg_assert_proc_not_inserted(proc);
- ble_gattc_indicate_cb(proc, status, att_handle);
+ /* Send the next indication if one is pending. */
+ ble_gatts_send_next_indicate(proc->conn_handle);
}
/**
@@ -3683,33 +4050,57 @@ ble_gattc_indicate_rx_rsp(struct ble_gattc_proc *proc)
rc = ble_gatts_rx_indicate_ack(proc->conn_handle,
proc->indicate.chr_val_handle);
- if (rc != BLE_HS_ENOTCONN && rc != BLE_HS_ENOENT) {
- ble_gattc_indicate_cb(proc, rc, 0);
+ if (rc != 0) {
+ return;
}
+ /* Tell the application about the received acknowledgment. */
+ ble_gap_notify_tx_event(BLE_HS_EDONE, proc->conn_handle,
+ proc->indicate.chr_val_handle, 1);
+
/* Send the next indication if one is pending. */
ble_gatts_send_next_indicate(proc->conn_handle);
}
/**
- * Sends an attribute indication.
+ * Causes the indication in progress for the specified connection (if any) to
+ * fail with a status code of BLE_HS_ENOTCONN;
+ */
+void
+ble_gatts_indicate_fail_notconn(uint16_t conn_handle)
+{
+ ble_gattc_fail_procs(conn_handle, BLE_GATT_OP_INDICATE, BLE_HS_ENOTCONN);
+}
+
+/**
+ * Sends a characteristic indication. The content of the message is read from
+ * the specified characteristic.
+ *
+ * @param conn_handle The connection over which to execute the
+ * procedure.
+ * @param chr_val_handle The value attribute handle of the
+ * characteristic to include in the outgoing
+ * indication.
+ *
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
- ble_gatt_attr_fn *cb, void *cb_arg)
+ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle)
{
#if !NIMBLE_OPT(GATT_INDICATE)
return BLE_HS_ENOTSUP;
#endif
- struct ble_att_svr_access_ctxt ctxt;
struct ble_att_indicate_req req;
struct ble_gattc_proc *proc;
struct ble_hs_conn *conn;
+ struct os_mbuf *om;
int rc;
STATS_INC(ble_gattc_stats, indicate);
+ om = NULL;
+
proc = ble_gattc_proc_alloc();
if (proc == NULL) {
rc = BLE_HS_ENOMEM;
@@ -3719,13 +4110,17 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
proc->op = BLE_GATT_OP_INDICATE;
proc->conn_handle = conn_handle;
proc->indicate.chr_val_handle = chr_val_handle;
- proc->indicate.cb = cb;
- proc->indicate.cb_arg = cb_arg;
ble_gattc_log_indicate(chr_val_handle);
- rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, chr_val_handle,
- &ctxt, NULL);
+ om = ble_hs_mbuf_att_pkt();
+ if (om == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, chr_val_handle, 0,
+ om, NULL);
if (rc != 0) {
/* Fatal error; application disallowed attribute read. */
BLE_HS_DBG_ASSERT(0);
@@ -3734,9 +4129,8 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle,
}
req.baiq_handle = chr_val_handle;
- rc = ble_att_clt_tx_indicate(conn_handle, &req,
- ctxt.attr_data, ctxt.data_len);
-
+ rc = ble_att_clt_tx_indicate(conn_handle, &req, om);
+ om = NULL;
if (rc != 0) {
goto done;
}
@@ -3755,7 +4149,11 @@ done:
STATS_INC(ble_gattc_stats, indicate_fail);
}
+ /* Tell the application that an indication transmission was attempted. */
+ ble_gap_notify_tx_event(rc, conn_handle, chr_val_handle, 1);
+
ble_gattc_process_status(proc, rc);
+ os_mbuf_free_chain(om);
return rc;
}
@@ -3983,8 +4381,7 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status)
* procedure.
*/
void
-ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, void *value,
- int value_len)
+ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om)
{
#if !NIMBLE_OPT(ATT_CLT_READ)
return;
@@ -3998,7 +4395,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, void *value,
ble_gattc_rx_read_rsp_entries,
&rx_entry);
if (proc != NULL) {
- rc = rx_entry->cb(proc, status, value, value_len);
+ rc = rx_entry->cb(proc, status, om);
ble_gattc_process_status(proc, rc);
}
}
@@ -4009,7 +4406,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, void *value,
*/
void
ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
- void *value, int value_len)
+ struct os_mbuf **om)
{
#if !NIMBLE_OPT(ATT_CLT_READ_BLOB)
return;
@@ -4020,7 +4417,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
proc = ble_gattc_extract(conn_handle, BLE_GATT_OP_READ_LONG);
if (proc != NULL) {
- rc = ble_gattc_read_long_rx_read_rsp(proc, status, value, value_len);
+ rc = ble_gattc_read_long_rx_read_rsp(proc, status, om);
ble_gattc_process_status(proc, rc);
}
}
@@ -4031,7 +4428,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
*/
void
ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status,
- void *value, int value_len)
+ struct os_mbuf **om)
{
#if !NIMBLE_OPT(ATT_CLT_READ_MULT)
return;
@@ -4041,7 +4438,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status,
proc = ble_gattc_extract(conn_handle, BLE_GATT_OP_READ_MULT);
if (proc != NULL) {
- ble_gattc_read_mult_cb(proc, status, 0, value, value_len);
+ ble_gattc_read_mult_cb(proc, status, 0, om);
ble_gattc_process_status(proc, BLE_HS_EDONE);
}
}
@@ -4073,7 +4470,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle)
void
ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status,
struct ble_att_prep_write_cmd *rsp,
- void *attr_data, uint16_t attr_data_len)
+ struct os_mbuf **om)
{
#if !NIMBLE_OPT(ATT_CLT_PREP_WRITE)
return;
@@ -4087,7 +4484,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status,
ble_gattc_rx_prep_entries,
&rx_entry);
if (proc != NULL) {
- rc = rx_entry->cb(proc, status, rsp, attr_data, attr_data_len);
+ rc = rx_entry->cb(proc, status, rsp, om);
ble_gattc_process_status(proc, rc);
}
}
@@ -4150,25 +4547,7 @@ ble_gattc_rx_indicate_rsp(uint16_t conn_handle)
void
ble_gattc_connection_broken(uint16_t conn_handle)
{
- struct ble_gattc_proc_list temp_list;
- struct ble_gattc_proc *proc;
- ble_gattc_err_fn *err_cb;
-
- /* Remove all procs with the specified conn handle and insert them into the
- * temporary list.
- */
- ble_gattc_extract_by_conn(conn_handle, &temp_list);
-
- /* Notify application of failed procedures and free the corresponding proc
- * entries.
- */
- while ((proc = STAILQ_FIRST(&temp_list)) != NULL) {
- err_cb = ble_gattc_err_dispatch_get(proc->op);
- err_cb(proc, BLE_HS_ENOTCONN, 0);
-
- STAILQ_REMOVE_HEAD(&temp_list, next);
- ble_gattc_proc_free(proc);
- }
+ ble_gattc_fail_procs(conn_handle, BLE_GATT_OP_NONE, BLE_HS_ENOTCONN);
}
/**
diff --git a/net/nimble/host/src/ble_gatts.c b/net/nimble/host/src/ble_gatts.c
index 3f73e015..e6ff2031 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -28,6 +28,9 @@
#define BLE_GATTS_INCLUDE_SZ 6
#define BLE_GATTS_CHR_MAX_SZ 19
+static const struct ble_gatt_svc_def **ble_gatts_svc_defs;
+static int ble_gatts_num_svc_defs;
+
struct ble_gatts_svc_entry {
const struct ble_gatt_svc_def *svc;
uint16_t handle; /* 0 means unregistered. */
@@ -35,7 +38,7 @@ struct ble_gatts_svc_entry {
};
static struct ble_gatts_svc_entry *ble_gatts_svc_entries;
-static int ble_gatts_num_svc_entries;
+static uint16_t ble_gatts_num_svc_entries;
static os_membuf_t *ble_gatts_clt_cfg_mem;
static struct os_mempool ble_gatts_clt_cfg_pool;
@@ -66,11 +69,13 @@ STATS_NAME_END(ble_gatts_stats)
static int
ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt, void *arg)
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
+ void *arg)
{
const struct ble_gatt_svc_def *svc;
- static uint16_t uuid16;
+ uint16_t uuid16;
+ uint8_t *buf;
+ int rc;
STATS_INC(ble_gatts_stats, svc_def_reads);
@@ -80,12 +85,16 @@ ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
uuid16 = ble_uuid_128_to_16(svc->uuid128);
if (uuid16 != 0) {
- htole16(&uuid16, uuid16);
- ctxt->attr_data = &uuid16;
- ctxt->data_len = 2;
+ buf = os_mbuf_extend(*om, 2);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ htole16(buf, uuid16);
} else {
- ctxt->attr_data = svc->uuid128;
- ctxt->data_len = 16;
+ rc = os_mbuf_append(*om, svc->uuid128, 16);
+ if (rc != 0) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
}
return 0;
@@ -93,13 +102,12 @@ ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
static int
ble_gatts_inc_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt, void *arg)
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
+ void *arg)
{
- static uint8_t buf[BLE_GATTS_INCLUDE_SZ];
-
const struct ble_gatts_svc_entry *entry;
uint16_t uuid16;
+ uint8_t *buf;
STATS_INC(ble_gatts_stats, svc_inc_reads);
@@ -107,18 +115,22 @@ ble_gatts_inc_access(uint16_t conn_handle, uint16_t attr_handle,
entry = arg;
+ buf = os_mbuf_extend(*om, 4);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
htole16(buf + 0, entry->handle);
htole16(buf + 2, entry->end_group_handle);
/* Only include the service UUID if it has a 16-bit representation. */
uuid16 = ble_uuid_128_to_16(entry->svc->uuid128);
if (uuid16 != 0) {
- htole16(buf + 4, uuid16);
- ctxt->data_len = 6;
- } else {
- ctxt->data_len = 4;
+ buf = os_mbuf_extend(*om, 2);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ htole16(buf, uuid16);
}
- ctxt->attr_data = buf;
return 0;
}
@@ -212,12 +224,12 @@ ble_gatts_chr_properties(const struct ble_gatt_chr_def *chr)
static int
ble_gatts_chr_def_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt, void *arg)
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
+ void *arg)
{
- static uint8_t buf[BLE_GATTS_CHR_MAX_SZ];
const struct ble_gatt_chr_def *chr;
uint16_t uuid16;
+ uint8_t *buf;
STATS_INC(ble_gatts_stats, chr_def_reads);
@@ -225,6 +237,11 @@ ble_gatts_chr_def_access(uint16_t conn_handle, uint16_t attr_handle,
chr = arg;
+ buf = os_mbuf_extend(*om, 3);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+
buf[0] = ble_gatts_chr_properties(chr);
/* The value attribute is always immediately after the declaration. */
@@ -232,13 +249,18 @@ ble_gatts_chr_def_access(uint16_t conn_handle, uint16_t attr_handle,
uuid16 = ble_uuid_128_to_16(chr->uuid128);
if (uuid16 != 0) {
- htole16(buf + 3, uuid16);
- ctxt->data_len = 5;
+ buf = os_mbuf_extend(*om, 2);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ htole16(buf, uuid16);
} else {
- memcpy(buf + 3, chr->uuid128, 16);
- ctxt->data_len = 19;
+ buf = os_mbuf_extend(*om, 16);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ memcpy(buf, chr->uuid128, 16);
}
- ctxt->attr_data = buf;
return 0;
}
@@ -293,45 +315,70 @@ ble_gatts_chr_inc_val_stat(uint8_t gatt_op)
}
static int
-ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t att_op,
- struct ble_att_svr_access_ctxt *att_ctxt, void *arg)
+ble_gatts_val_access(uint16_t conn_handle, uint16_t attr_handle,
+ uint16_t offset, struct ble_gatt_access_ctxt *gatt_ctxt,
+ struct os_mbuf **om, ble_gatt_access_fn *access_cb,
+ void *cb_arg)
{
- const struct ble_gatt_chr_def *chr;
- union ble_gatt_access_ctxt gatt_ctxt;
- uint8_t gatt_op;
+ int attr_len;
int rc;
- chr = arg;
- BLE_HS_DBG_ASSERT(chr != NULL && chr->access_cb != NULL);
+ switch (gatt_ctxt->op) {
+ case BLE_GATT_ACCESS_OP_READ_CHR:
+ case BLE_GATT_ACCESS_OP_READ_DSC:
+ gatt_ctxt->om = os_msys_get_pkthdr(0, 0);
+ if (gatt_ctxt->om == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
- gatt_op = ble_gatts_chr_op(att_op);
- gatt_ctxt.chr_access.chr = chr;
- gatt_ctxt.chr_access.data = att_ctxt->attr_data;
- gatt_ctxt.chr_access.len = att_ctxt->data_len;
+ rc = access_cb(conn_handle, attr_handle, gatt_ctxt, cb_arg);
+ if (rc == 0) {
+ attr_len = OS_MBUF_PKTLEN(gatt_ctxt->om) - offset;
+ if (attr_len > 0) {
+ os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len);
+ }
+ }
- ble_gatts_chr_inc_val_stat(gatt_op);
+ os_mbuf_free_chain(gatt_ctxt->om);
+ return rc;
- rc = chr->access_cb(conn_handle, attr_handle, gatt_op, &gatt_ctxt,
- chr->arg);
- if (rc != 0) {
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ case BLE_GATT_ACCESS_OP_WRITE_DSC:
+ gatt_ctxt->om = *om;
+ rc = access_cb(conn_handle, attr_handle, gatt_ctxt, cb_arg);
+ *om = gatt_ctxt->om;
return rc;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_ATT_ERR_UNLIKELY;
}
+}
+
+static int
+ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t att_op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ const struct ble_gatt_chr_def *chr_def;
+ struct ble_gatt_access_ctxt gatt_ctxt;
+ int rc;
- if (att_op == BLE_ATT_ACCESS_OP_WRITE &&
- ble_gatts_chr_clt_cfg_allowed(chr)) {
+ chr_def = arg;
+ BLE_HS_DBG_ASSERT(chr_def != NULL && chr_def->access_cb != NULL);
- ble_gatts_chr_updated(attr_handle - 1);
- }
+ gatt_ctxt.op = ble_gatts_chr_op(att_op);
+ gatt_ctxt.chr = chr_def;
- att_ctxt->attr_data = gatt_ctxt.chr_access.data;
- att_ctxt->data_len = gatt_ctxt.chr_access.len;
+ ble_gatts_chr_inc_val_stat(gatt_ctxt.op);
+ rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om,
+ chr_def->access_cb, chr_def->arg);
- return 0;
+ return rc;
}
static int
-ble_gatts_find_svc(const struct ble_gatt_svc_def *svc)
+ble_gatts_find_svc_entry_idx(const struct ble_gatt_svc_def *svc)
{
int i;
@@ -356,7 +403,7 @@ ble_gatts_svc_incs_satisfied(const struct ble_gatt_svc_def *svc)
}
for (i = 0; svc->includes[i] != NULL; i++) {
- idx = ble_gatts_find_svc(svc->includes[i]);
+ idx = ble_gatts_find_svc_entry_idx(svc->includes[i]);
if (idx == -1 || ble_gatts_svc_entries[idx].handle == 0) {
return 0;
}
@@ -418,34 +465,24 @@ ble_gatts_dsc_inc_stat(uint8_t gatt_op)
static int
ble_gatts_dsc_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t att_op,
- struct ble_att_svr_access_ctxt *att_ctxt, void *arg)
+ uint8_t att_op, uint16_t offset, struct os_mbuf **om,
+ void *arg)
{
- const struct ble_gatt_dsc_def *dsc;
- union ble_gatt_access_ctxt gatt_ctxt;
- uint8_t gatt_op;
+ const struct ble_gatt_dsc_def *dsc_def;
+ struct ble_gatt_access_ctxt gatt_ctxt;
int rc;
- dsc = arg;
- BLE_HS_DBG_ASSERT(dsc != NULL && dsc->access_cb != NULL);
+ dsc_def = arg;
+ BLE_HS_DBG_ASSERT(dsc_def != NULL && dsc_def->access_cb != NULL);
- gatt_op = ble_gatts_dsc_op(att_op);
- gatt_ctxt.dsc_access.dsc = dsc;
- gatt_ctxt.dsc_access.data = att_ctxt->attr_data;
- gatt_ctxt.dsc_access.len = att_ctxt->data_len;
-
- ble_gatts_dsc_inc_stat(gatt_op);
-
- rc = dsc->access_cb(conn_handle, attr_handle, gatt_op, &gatt_ctxt,
- dsc->arg);
- if (rc != 0) {
- return rc;
- }
+ gatt_ctxt.op = ble_gatts_dsc_op(att_op);
+ gatt_ctxt.dsc = dsc_def;
- att_ctxt->attr_data = gatt_ctxt.dsc_access.data;
- att_ctxt->data_len = gatt_ctxt.dsc_access.len;
+ ble_gatts_dsc_inc_stat(gatt_ctxt.op);
+ rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om,
+ dsc_def->access_cb, dsc_def->arg);
- return 0;
+ return rc;
}
static int
@@ -463,12 +500,13 @@ ble_gatts_dsc_is_sane(const struct ble_gatt_dsc_def *dsc)
}
static int
-ble_gatts_register_dsc(const struct ble_gatt_dsc_def *dsc,
+ble_gatts_register_dsc(const struct ble_gatt_svc_def *svc,
const struct ble_gatt_chr_def *chr,
+ const struct ble_gatt_dsc_def *dsc,
uint16_t chr_def_handle,
ble_gatt_register_fn *register_cb, void *cb_arg)
{
- union ble_gatt_register_ctxt register_ctxt;
+ struct ble_gatt_register_ctxt register_ctxt;
uint16_t dsc_handle;
int rc;
@@ -483,11 +521,12 @@ ble_gatts_register_dsc(const struct ble_gatt_dsc_def *dsc,
}
if (register_cb != NULL) {
- register_ctxt.dsc_reg.dsc_handle = dsc_handle;
- register_ctxt.dsc_reg.dsc = dsc;
- register_ctxt.dsc_reg.chr_def_handle = chr_def_handle;
- register_ctxt.dsc_reg.chr = chr;
- register_cb(BLE_GATT_REGISTER_OP_DSC, &register_ctxt, cb_arg);
+ register_ctxt.op = BLE_GATT_REGISTER_OP_DSC;
+ register_ctxt.dsc.handle = dsc_handle;
+ register_ctxt.dsc.svc_def = svc;
+ register_ctxt.dsc.chr_def = chr;
+ register_ctxt.dsc.dsc_def = dsc;
+ register_cb(&register_ctxt, cb_arg);
}
STATS_INC(ble_gatts_stats, dscs);
@@ -527,6 +566,22 @@ ble_gatts_clt_cfg_find(struct ble_gatts_clt_cfg *cfgs,
}
}
+static void
+ble_gatts_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t reason,
+ uint8_t prev_flags, uint8_t cur_flags)
+{
+ if (prev_flags != cur_flags) {
+ ble_gap_subscribe_event(conn_handle,
+ attr_handle,
+ reason,
+ prev_flags & BLE_GATTS_CLT_CFG_F_NOTIFY,
+ cur_flags & BLE_GATTS_CLT_CFG_F_NOTIFY,
+ prev_flags & BLE_GATTS_CLT_CFG_F_INDICATE,
+ cur_flags & BLE_GATTS_CLT_CFG_F_INDICATE);
+ }
+}
+
/**
* Performs a read or write access on a client characteritic configuration
* descriptor (CCCD).
@@ -549,16 +604,17 @@ ble_gatts_clt_cfg_find(struct ble_gatts_clt_cfg *cfgs,
*/
static int
ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
- uint8_t att_op,
- struct ble_att_svr_access_ctxt *ctxt,
- struct ble_store_value_cccd *out_cccd)
+ uint8_t att_op, uint16_t offset,
+ struct os_mbuf *om,
+ struct ble_store_value_cccd *out_cccd,
+ uint8_t *out_prev_clt_cfg_flags,
+ uint8_t *out_cur_clt_cfg_flags)
{
struct ble_gatts_clt_cfg *clt_cfg;
uint16_t chr_val_handle;
uint16_t flags;
uint8_t gatt_op;
-
- static uint8_t buf[2];
+ uint8_t *buf;
/* Assume nothing needs to be persisted. */
out_cccd->chr_val_handle = 0;
@@ -578,37 +634,49 @@ ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
return BLE_ATT_ERR_UNLIKELY;
}
+ /* Assume no change in flags. */
+ *out_prev_clt_cfg_flags = clt_cfg->flags;
+ *out_cur_clt_cfg_flags = clt_cfg->flags;
+
gatt_op = ble_gatts_dsc_op(att_op);
ble_gatts_dsc_inc_stat(gatt_op);
switch (gatt_op) {
case BLE_GATT_ACCESS_OP_READ_DSC:
STATS_INC(ble_gatts_stats, dsc_reads);
+ buf = os_mbuf_extend(om, 2);
+ if (buf == NULL) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
htole16(buf, clt_cfg->flags & ~BLE_GATTS_CLT_CFG_F_RESERVED);
- ctxt->attr_data = buf;
- ctxt->data_len = sizeof buf;
break;
case BLE_GATT_ACCESS_OP_WRITE_DSC:
STATS_INC(ble_gatts_stats, dsc_writes);
- if (ctxt->data_len != 2) {
+ if (OS_MBUF_PKTLEN(om) != 2) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
- flags = le16toh(ctxt->attr_data);
+ om = os_mbuf_pullup(om, 2);
+ BLE_HS_DBG_ASSERT(om != NULL);
+
+ flags = le16toh(om->om_data);
if ((flags & ~clt_cfg->allowed) != 0) {
- return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
+ return BLE_ATT_ERR_REQ_NOT_SUPPORTED;
}
- clt_cfg->flags = flags;
-
- /* Successful writes get persisted for bonded connections. */
- if (conn->bhc_sec_state.bonded) {
- out_cccd->peer_addr_type = conn->bhc_addr_type;
- memcpy(out_cccd->peer_addr, conn->bhc_addr, 6);
- out_cccd->chr_val_handle = chr_val_handle;
- out_cccd->flags = clt_cfg->flags;
- out_cccd->value_changed = 0;
+ if (clt_cfg->flags != flags) {
+ clt_cfg->flags = flags;
+ *out_cur_clt_cfg_flags = flags;
+
+ /* Successful writes get persisted for bonded connections. */
+ if (conn->bhc_sec_state.bonded) {
+ out_cccd->peer_addr_type = conn->bhc_peer_addr_type;
+ memcpy(out_cccd->peer_addr, conn->bhc_peer_addr, 6);
+ out_cccd->chr_val_handle = chr_val_handle;
+ out_cccd->flags = clt_cfg->flags;
+ out_cccd->value_changed = 0;
+ }
}
break;
@@ -622,13 +690,15 @@ ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
static int
ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
void *arg)
{
struct ble_store_value_cccd cccd_value;
struct ble_store_key_cccd cccd_key;
struct ble_hs_conn *conn;
+ uint16_t chr_val_handle;
+ uint8_t prev_flags;
+ uint8_t cur_flags;
int rc;
ble_hs_lock();
@@ -637,14 +707,27 @@ ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
if (conn == NULL) {
rc = BLE_ATT_ERR_UNLIKELY;
} else {
- rc = ble_gatts_clt_cfg_access_locked(conn, attr_handle, op, ctxt,
- &cccd_value);
+ rc = ble_gatts_clt_cfg_access_locked(conn, attr_handle, op, offset,
+ *om, &cccd_value, &prev_flags,
+ &cur_flags);
}
ble_hs_unlock();
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* The value attribute is always immediately after the declaration. */
+ chr_val_handle = attr_handle - 1;
+
+ /* Tell the application if the peer changed its subscription state. */
+ ble_gatts_subscribe_event(conn_handle, chr_val_handle,
+ BLE_GAP_SUBSCRIBE_REASON_WRITE,
+ prev_flags, cur_flags);
+
/* Persist the CCCD if required. */
- if (rc == 0 && cccd_value.chr_val_handle != 0) {
+ if (cccd_value.chr_val_handle != 0) {
if (cccd_value.flags == 0) {
ble_store_key_from_value_cccd(&cccd_key, &cccd_value);
rc = ble_store_delete_cccd(&cccd_key);
@@ -679,10 +762,11 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
}
static int
-ble_gatts_register_chr(const struct ble_gatt_chr_def *chr,
+ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
+ const struct ble_gatt_chr_def *chr,
ble_gatt_register_fn *register_cb, void *cb_arg)
{
- union ble_gatt_register_ctxt register_ctxt;
+ struct ble_gatt_register_ctxt register_ctxt;
struct ble_gatt_dsc_def *dsc;
uint16_t def_handle;
uint16_t val_handle;
@@ -694,7 +778,14 @@ ble_gatts_register_chr(const struct ble_gatt_chr_def *chr,
return BLE_HS_EINVAL;
}
- /* Register characteristic declaration attribute (cast away const on
+ if (ble_gatts_chr_clt_cfg_allowed(chr) != 0) {
+ if (ble_gatts_num_cfgable_chrs > ble_hs_cfg.max_client_configs) {
+ return BLE_HS_ENOMEM;
+ }
+ ble_gatts_num_cfgable_chrs++;
+ }
+
+ /* Register characteristic definition attribute (cast away const on
* callback arg).
*/
rc = ble_att_svr_register_uuid16(BLE_ATT_UUID_CHARACTERISTIC,
@@ -715,11 +806,17 @@ ble_gatts_register_chr(const struct ble_gatt_chr_def *chr,
}
BLE_HS_DBG_ASSERT(val_handle == def_handle + 1);
+ if (chr->val_handle != NULL) {
+ *chr->val_handle = val_handle;
+ }
+
if (register_cb != NULL) {
- register_ctxt.chr_reg.def_handle = def_handle;
- register_ctxt.chr_reg.val_handle = val_handle;
- register_ctxt.chr_reg.chr = chr;
- register_cb(BLE_GATT_REGISTER_OP_CHR, &register_ctxt, cb_arg);
+ register_ctxt.op = BLE_GATT_REGISTER_OP_CHR;
+ register_ctxt.chr.def_handle = def_handle;
+ register_ctxt.chr.val_handle = val_handle;
+ register_ctxt.chr.svc_def = svc;
+ register_ctxt.chr.chr_def = chr;
+ register_cb(&register_ctxt, cb_arg);
}
if (ble_gatts_chr_clt_cfg_allowed(chr) != 0) {
@@ -733,7 +830,7 @@ ble_gatts_register_chr(const struct ble_gatt_chr_def *chr,
/* Register each descriptor. */
if (chr->descriptors != NULL) {
for (dsc = chr->descriptors; dsc->uuid128 != NULL; dsc++) {
- rc = ble_gatts_register_dsc(dsc, chr, def_handle, register_cb,
+ rc = ble_gatts_register_dsc(svc, chr, dsc, def_handle, register_cb,
cb_arg);
if (rc != 0) {
return rc;
@@ -785,7 +882,7 @@ ble_gatts_register_svc(const struct ble_gatt_svc_def *svc,
ble_gatt_register_fn *register_cb, void *cb_arg)
{
const struct ble_gatt_chr_def *chr;
- union ble_gatt_register_ctxt register_ctxt;
+ struct ble_gatt_register_ctxt register_ctxt;
uint16_t uuid16;
int idx;
int rc;
@@ -815,15 +912,16 @@ ble_gatts_register_svc(const struct ble_gatt_svc_def *svc,
}
if (register_cb != NULL) {
- register_ctxt.svc_reg.handle = *out_handle;
- register_ctxt.svc_reg.svc = svc;
- register_cb(BLE_GATT_REGISTER_OP_SVC, &register_ctxt, cb_arg);
+ register_ctxt.op = BLE_GATT_REGISTER_OP_SVC;
+ register_ctxt.svc.handle = *out_handle;
+ register_ctxt.svc.svc_def = svc;
+ register_cb(&register_ctxt, cb_arg);
}
/* Register each include. */
if (svc->includes != NULL) {
for (i = 0; svc->includes[i] != NULL; i++) {
- idx = ble_gatts_find_svc(svc->includes[i]);
+ idx = ble_gatts_find_svc_entry_idx(svc->includes[i]);
BLE_HS_DBG_ASSERT_EVAL(idx != -1);
rc = ble_gatts_register_inc(ble_gatts_svc_entries + idx);
@@ -836,7 +934,7 @@ ble_gatts_register_svc(const struct ble_gatt_svc_def *svc,
/* Register each characteristic. */
if (svc->characteristics != NULL) {
for (chr = svc->characteristics; chr->uuid128 != NULL; chr++) {
- rc = ble_gatts_register_chr(chr, register_cb, cb_arg);
+ rc = ble_gatts_register_chr(svc, chr, register_cb, cb_arg);
if (rc != 0) {
return rc;
}
@@ -873,7 +971,7 @@ ble_gatts_register_round(int *out_num_registered, ble_gatt_register_fn *cb,
case BLE_HS_EAGAIN:
/* Service could not be registered due to unsatisfied includes.
- * Try again on the next itereation.
+ * Try again on the next iteration.
*/
break;
@@ -891,28 +989,50 @@ ble_gatts_register_round(int *out_num_registered, ble_gatt_register_fn *cb,
return 0;
}
+/**
+ * Registers a set of services, characteristics, and descriptors to be accessed
+ * by GATT clients.
+ *
+ * @param svcs A table of the service definitions to be
+ * registered.
+ * @param cb The function to call for each service,
+ * characteristic, and descriptor that gets
+ * registered.
+ * @param cb_arg The optional argument to pass to the callback
+ * function.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOMEM if registration failed due to
+ * resource exhaustion;
+ * BLE_HS_EINVAL if the service definition table
+ * contains an invalid element.
+ */
int
ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs,
ble_gatt_register_fn *cb, void *cb_arg)
{
int total_registered;
int cur_registered;
+ int num_svcs;
+ int idx;
int rc;
int i;
for (i = 0; svcs[i].type != BLE_GATT_SVC_TYPE_END; i++) {
- ble_gatts_svc_entries[i].svc = svcs + i;
- ble_gatts_svc_entries[i].handle = 0;
- ble_gatts_svc_entries[i].end_group_handle = 0xffff;
- }
- if (i > ble_hs_cfg.max_services) {
- return BLE_HS_ENOMEM;
- }
+ idx = ble_gatts_num_svc_entries + i;
+ if (idx >= ble_hs_cfg.max_services) {
+ return BLE_HS_ENOMEM;
+ }
- ble_gatts_num_svc_entries = i;
+ ble_gatts_svc_entries[idx].svc = svcs + i;
+ ble_gatts_svc_entries[idx].handle = 0;
+ ble_gatts_svc_entries[idx].end_group_handle = 0xffff;
+ }
+ num_svcs = i;
+ ble_gatts_num_svc_entries += num_svcs;
total_registered = 0;
- while (total_registered < ble_gatts_num_svc_entries) {
+ while (total_registered < num_svcs) {
rc = ble_gatts_register_round(&cur_registered, cb, cb_arg);
if (rc != 0) {
return rc;
@@ -923,23 +1043,71 @@ ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs,
return 0;
}
+static int
+ble_gatts_clt_cfg_size(void)
+{
+ return ble_gatts_num_cfgable_chrs * sizeof (struct ble_gatts_clt_cfg);
+}
+
+/**
+ * Handles GATT server clean up for a terminated connection:
+ * o Informs the application that the peer is no longer subscribed to any
+ * characteristic updates.
+ * o Frees GATT server resources consumed by the connection (CCCDs).
+ */
void
-ble_gatts_conn_deinit(struct ble_gatts_conn *gatts_conn)
+ble_gatts_connection_broken(uint16_t conn_handle)
{
+ struct ble_gatts_clt_cfg *clt_cfgs;
+ struct ble_hs_conn *conn;
+ int num_clt_cfgs;
int rc;
+ int i;
- if (gatts_conn->clt_cfgs != NULL) {
- rc = os_memblock_put(&ble_gatts_clt_cfg_pool, gatts_conn->clt_cfgs);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+ /* Find the specified connection and extract its CCCD entries. Extracting
+ * the clt_cfg pointer and setting the original to null is done for two
+ * reasons:
+ * 1. So that the CCCD entries can be safely processed after unlocking
+ * the mutex.
+ * 2. To ensure a subsequent indicate procedure for this peer is not
+ * attempted, as the connection is about to be terminated. This
+ * avoids a spurious notify-tx GAP event callback to the
+ * application. By setting the clt_cfg pointer to null, it is
+ * assured that the connection has no pending indications to send.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ if (conn != NULL) {
+ clt_cfgs = conn->bhc_gatt_svr.clt_cfgs;
+ num_clt_cfgs = conn->bhc_gatt_svr.num_clt_cfgs;
- gatts_conn->clt_cfgs = NULL;
+ conn->bhc_gatt_svr.clt_cfgs = NULL;
+ conn->bhc_gatt_svr.num_clt_cfgs = 0;
}
-}
+ ble_hs_unlock();
-static int
-ble_gatts_clt_cfg_size(void)
-{
- return ble_gatts_num_cfgable_chrs * sizeof (struct ble_gatts_clt_cfg);
+ if (conn == NULL) {
+ return;
+ }
+
+ /* If there is an indicate procedure in progress for this connection,
+ * inform the application that it has failed.
+ */
+ ble_gatts_indicate_fail_notconn(conn_handle);
+
+ /* Now that the mutex is unlocked, inform the application that the peer is
+ * no longer subscribed to any characteristic updates.
+ */
+ if (clt_cfgs != NULL) {
+ for (i = 0; i < num_clt_cfgs; i++) {
+ ble_gatts_subscribe_event(conn_handle, clt_cfgs[i].chr_val_handle,
+ BLE_GAP_SUBSCRIBE_REASON_TERM,
+ clt_cfgs[i].flags, 0);
+ }
+
+ rc = os_memblock_put(&ble_gatts_clt_cfg_pool, clt_cfgs);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+ }
}
int
@@ -953,26 +1121,10 @@ ble_gatts_start(void)
int idx;
int rc;
- rc = ble_uuid_16_to_128(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
-
- /* Count the number of client-configurable characteristics. */
- ble_gatts_num_cfgable_chrs = 0;
- ha = NULL;
- while ((ha = ble_att_svr_find_by_uuid(ha, uuid128)) != NULL) {
- chr = ha->ha_cb_arg;
- if (ble_gatts_chr_clt_cfg_allowed(chr) != 0) {
- ble_gatts_num_cfgable_chrs++;
- }
- }
if (ble_gatts_num_cfgable_chrs == 0) {
return 0;
}
- if (ble_gatts_num_cfgable_chrs > ble_hs_cfg.max_client_configs) {
- return BLE_HS_ENOMEM;
- }
-
/* Initialize client-configuration memory pool. */
num_elems = ble_hs_cfg.max_client_configs / ble_gatts_num_cfgable_chrs;
rc = os_mempool_init(&ble_gatts_clt_cfg_pool, num_elems,
@@ -991,9 +1143,11 @@ ble_gatts_start(void)
}
/* Fill the cache. */
+ rc = ble_uuid_16_to_128(BLE_ATT_UUID_CHARACTERISTIC, uuid128);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
idx = 0;
ha = NULL;
- while ((ha = ble_att_svr_find_by_uuid(ha, uuid128)) != NULL) {
+ while ((ha = ble_att_svr_find_by_uuid(ha, uuid128, 0xffff)) != NULL) {
chr = ha->ha_cb_arg;
allowed_flags = ble_gatts_chr_clt_cfg_allowed(chr);
if (allowed_flags != 0) {
@@ -1020,16 +1174,19 @@ int
ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn)
{
if (ble_gatts_num_cfgable_chrs > 0) {
- ble_gatts_conn_deinit(gatts_conn);
gatts_conn->clt_cfgs = os_memblock_get(&ble_gatts_clt_cfg_pool);
if (gatts_conn->clt_cfgs == NULL) {
return BLE_HS_ENOMEM;
}
- }
- /* Initialize the client configuration with a copy of the cache. */
- memcpy(gatts_conn->clt_cfgs, ble_gatts_clt_cfgs, ble_gatts_clt_cfg_size());
- gatts_conn->num_clt_cfgs = ble_gatts_num_cfgable_chrs;
+ /* Initialize the client configuration with a copy of the cache. */
+ memcpy(gatts_conn->clt_cfgs, ble_gatts_clt_cfgs,
+ ble_gatts_clt_cfg_size());
+ gatts_conn->num_clt_cfgs = ble_gatts_num_cfgable_chrs;
+ } else {
+ gatts_conn->clt_cfgs = NULL;
+ gatts_conn->num_clt_cfgs = 0;
+ }
return 0;
}
@@ -1037,9 +1194,7 @@ ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn)
/**
* Schedules a notification or indication for the specified peer-CCCD pair. If
- * the udpate should be sent immediately, it is indicated in the return code.
- * If the update can only be sent in the future, the appropriate flags are set
- * to ensure this happens.
+ * the update should be sent immediately, it is indicated in the return code.
*
* @param conn The connection to schedule the update for.
* @param clt_cfg The client config entry corresponding to the
@@ -1054,7 +1209,10 @@ ble_gatts_schedule_update(struct ble_hs_conn *conn,
{
uint8_t att_op;
- if (clt_cfg->flags & BLE_GATTS_CLT_CFG_F_NOTIFY) {
+ if (!(clt_cfg->flags & BLE_GATTS_CLT_CFG_F_MODIFIED)) {
+ /* Characteristic not modified. Nothing to send. */
+ att_op = 0;
+ } else if (clt_cfg->flags & BLE_GATTS_CLT_CFG_F_NOTIFY) {
/* Notifications always get sent immediately. */
att_op = BLE_ATT_OP_NOTIFY_REQ;
} else if (clt_cfg->flags & BLE_GATTS_CLT_CFG_F_INDICATE) {
@@ -1064,16 +1222,24 @@ ble_gatts_schedule_update(struct ble_hs_conn *conn,
* If there isn't an outstanding indication, send this one now.
*/
if (conn->bhc_gatt_svr.indicate_val_handle != 0) {
- clt_cfg->flags |= BLE_GATTS_CLT_CFG_F_INDICATE_PENDING;
att_op = 0;
} else {
att_op = BLE_ATT_OP_INDICATE_REQ;
}
} else {
- BLE_HS_DBG_ASSERT(0);
+ /* Peer isn't subscribed to notifications or indications. Nothing to
+ * send.
+ */
att_op = 0;
}
+ /* If we will be sending an update, clear the modified flag so that we
+ * don't double-send.
+ */
+ if (att_op != 0) {
+ clt_cfg->flags &= ~BLE_GATTS_CLT_CFG_F_MODIFIED;
+ }
+
return att_op;
}
@@ -1095,14 +1261,14 @@ ble_gatts_send_next_indicate(uint16_t conn_handle)
if (conn != NULL) {
for (i = 0; i < conn->bhc_gatt_svr.num_clt_cfgs; i++) {
clt_cfg = conn->bhc_gatt_svr.clt_cfgs + i;
- if (clt_cfg->flags & BLE_GATTS_CLT_CFG_F_INDICATE_PENDING) {
+ if (clt_cfg->flags & BLE_GATTS_CLT_CFG_F_MODIFIED) {
BLE_HS_DBG_ASSERT(clt_cfg->flags &
BLE_GATTS_CLT_CFG_F_INDICATE);
chr_val_handle = clt_cfg->chr_val_handle;
/* Clear pending flag in anticipation of indication tx. */
- clt_cfg->flags &= ~BLE_GATTS_CLT_CFG_F_INDICATE_PENDING;
+ clt_cfg->flags &= ~BLE_GATTS_CLT_CFG_F_MODIFIED;
break;
}
}
@@ -1118,7 +1284,7 @@ ble_gatts_send_next_indicate(uint16_t conn_handle)
return BLE_HS_ENOENT;
}
- rc = ble_gattc_indicate(conn_handle, chr_val_handle, NULL, NULL);
+ rc = ble_gattc_indicate(conn_handle, chr_val_handle);
if (rc != 0) {
return rc;
}
@@ -1170,16 +1336,16 @@ ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle)
BLE_HS_DBG_ASSERT(clt_cfg->chr_val_handle == chr_val_handle);
persist = conn->bhc_sec_state.bonded &&
- !(clt_cfg->flags & BLE_GATTS_CLT_CFG_F_INDICATE_PENDING);
+ !(clt_cfg->flags & BLE_GATTS_CLT_CFG_F_MODIFIED);
if (persist) {
- cccd_value.peer_addr_type = conn->bhc_addr_type;
- memcpy(cccd_value.peer_addr, conn->bhc_addr, 6);
+ cccd_value.peer_addr_type = conn->bhc_peer_addr_type;
+ memcpy(cccd_value.peer_addr, conn->bhc_peer_addr, 6);
cccd_value.chr_val_handle = chr_val_handle;
cccd_value.flags = clt_cfg->flags;
cccd_value.value_changed = 0;
}
} else {
- /* This acknowledgement doesn't correspnod to the outstanding
+ /* This acknowledgement doesn't correspond to the outstanding
* indication; ignore it.
*/
rc = BLE_HS_ENOENT;
@@ -1194,7 +1360,7 @@ ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle)
if (persist) {
rc = ble_store_write_cccd(&cccd_value);
if (rc != 0) {
- return rc;
+ /* XXX: How should this error get reported? */
}
}
@@ -1208,15 +1374,14 @@ ble_gatts_chr_updated(uint16_t chr_val_handle)
struct ble_store_key_cccd cccd_key;
struct ble_gatts_clt_cfg *clt_cfg;
struct ble_hs_conn *conn;
- uint16_t conn_handle;
- uint8_t att_op;
+ int new_notifications;
int clt_cfg_idx;
int persist;
int rc;
int i;
- /* Determine if notifications / indications are enabled for this
- * characteristic.
+ /* Determine if notifications or indications are allowed for this
+ * characteristic. If not, return immediately.
*/
clt_cfg_idx = ble_gatts_clt_cfg_find_idx(ble_gatts_clt_cfgs,
chr_val_handle);
@@ -1224,47 +1389,31 @@ ble_gatts_chr_updated(uint16_t chr_val_handle)
return;
}
- /* Handle the connected devices. */
- for (i = 0; ; i++) {
- ble_hs_lock();
+ /*** Send notifications and indications to connected devices. */
+ ble_hs_lock();
+ for (i = 0; ; i++) {
+ /* XXX: This is inefficient when there are a lot of connections.
+ * Consider using a "foreach" function to walk the connection list.
+ */
conn = ble_hs_conn_find_by_idx(i);
- if (conn != NULL) {
- BLE_HS_DBG_ASSERT_EVAL(conn->bhc_gatt_svr.num_clt_cfgs >
- clt_cfg_idx);
- clt_cfg = conn->bhc_gatt_svr.clt_cfgs + clt_cfg_idx;
- BLE_HS_DBG_ASSERT_EVAL(clt_cfg->chr_val_handle == chr_val_handle);
-
- /* Determine what kind of update should get sent immediately (if
- * any).
- */
- att_op = ble_gatts_schedule_update(conn, clt_cfg);
- conn_handle = conn->bhc_handle;
- } else {
- /* Silence some spurious gcc warnings. */
- att_op = 0;
- conn_handle = BLE_HS_CONN_HANDLE_NONE;
- }
- ble_hs_unlock();
-
if (conn == NULL) {
- /* No more connected devices. */
break;
}
- switch (att_op) {
- case 0:
- break;
- case BLE_ATT_OP_NOTIFY_REQ:
- ble_gattc_notify(conn_handle, chr_val_handle);
- break;
- case BLE_ATT_OP_INDICATE_REQ:
- ble_gattc_indicate(conn_handle, chr_val_handle, NULL, NULL);
- break;
- default:
- BLE_HS_DBG_ASSERT(0);
- break;
- }
+ BLE_HS_DBG_ASSERT_EVAL(conn->bhc_gatt_svr.num_clt_cfgs >
+ clt_cfg_idx);
+ clt_cfg = conn->bhc_gatt_svr.clt_cfgs + clt_cfg_idx;
+ BLE_HS_DBG_ASSERT_EVAL(clt_cfg->chr_val_handle == chr_val_handle);
+
+ /* Mark the CCCD entry as modified. */
+ clt_cfg->flags |= BLE_GATTS_CLT_CFG_F_MODIFIED;
+ new_notifications = 1;
+ }
+ ble_hs_unlock();
+
+ if (new_notifications) {
+ ble_hs_notifications_sched();
}
/*** Persist updated flag for unconnected and not-yet-bonded devices. */
@@ -1319,6 +1468,92 @@ ble_gatts_chr_updated(uint16_t chr_val_handle)
}
/**
+ * Sends notifications or indications for the specified characteristic to all
+ * connected devices. The bluetooth spec does not allow more than one
+ * concurrent indication for a single peer, so this function will hold off on
+ * sending such indications.
+ */
+static void
+ble_gatts_tx_notifications_one_chr(uint16_t chr_val_handle)
+{
+ struct ble_gatts_clt_cfg *clt_cfg;
+ struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+ uint8_t att_op;
+ int clt_cfg_idx;
+ int i;
+
+ /* Determine if notifications / indications are enabled for this
+ * characteristic.
+ */
+ clt_cfg_idx = ble_gatts_clt_cfg_find_idx(ble_gatts_clt_cfgs,
+ chr_val_handle);
+ if (clt_cfg_idx == -1) {
+ return;
+ }
+
+ for (i = 0; ; i++) {
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find_by_idx(i);
+ if (conn != NULL) {
+ BLE_HS_DBG_ASSERT_EVAL(conn->bhc_gatt_svr.num_clt_cfgs >
+ clt_cfg_idx);
+ clt_cfg = conn->bhc_gatt_svr.clt_cfgs + clt_cfg_idx;
+ BLE_HS_DBG_ASSERT_EVAL(clt_cfg->chr_val_handle == chr_val_handle);
+
+ /* Determine what type of command should get sent, if any. */
+ att_op = ble_gatts_schedule_update(conn, clt_cfg);
+ conn_handle = conn->bhc_handle;
+ } else {
+ /* Silence some spurious gcc warnings. */
+ att_op = 0;
+ conn_handle = BLE_HS_CONN_HANDLE_NONE;
+ }
+ ble_hs_unlock();
+
+ if (conn == NULL) {
+ /* No more connected devices. */
+ break;
+ }
+
+ switch (att_op) {
+ case 0:
+ break;
+
+ case BLE_ATT_OP_NOTIFY_REQ:
+ ble_gattc_notify(conn_handle, chr_val_handle);
+ break;
+
+ case BLE_ATT_OP_INDICATE_REQ:
+ ble_gattc_indicate(conn_handle, chr_val_handle);
+ break;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ break;
+ }
+ }
+}
+
+/**
+ * Sends all pending notifications and indications. The bluetooth spec does
+ * not allow more than one concurrent indication for a single peer, so this
+ * function will hold off on sending such indications.
+ */
+void
+ble_gatts_tx_notifications(void)
+{
+ uint16_t chr_val_handle;
+ int i;
+
+ for (i = 0; i < ble_gatts_num_cfgable_chrs; i++) {
+ chr_val_handle = ble_gatts_clt_cfgs[i].chr_val_handle;
+ ble_gatts_tx_notifications_one_chr(chr_val_handle);
+ }
+}
+
+/**
* Called when bonding has been restored via the encryption procedure. This
* function:
* o Restores persisted CCCD entries for the connected peer.
@@ -1342,8 +1577,8 @@ ble_gatts_bonding_restored(uint16_t conn_handle)
BLE_HS_DBG_ASSERT(conn != NULL);
BLE_HS_DBG_ASSERT(conn->bhc_sec_state.bonded);
- cccd_key.peer_addr_type = conn->bhc_addr_type;
- memcpy(cccd_key.peer_addr, conn->bhc_addr, 6);
+ cccd_key.peer_addr_type = conn->bhc_peer_addr_type;
+ memcpy(cccd_key.peer_addr, conn->bhc_peer_addr, 6);
cccd_key.chr_val_handle = 0;
cccd_key.idx = 0;
@@ -1355,7 +1590,7 @@ ble_gatts_bonding_restored(uint16_t conn_handle)
break;
}
- /* Assume no immediate send for this characteristic. */
+ /* Assume no notification or indication will get sent. */
att_op = 0;
ble_hs_lock();
@@ -1367,16 +1602,30 @@ ble_gatts_bonding_restored(uint16_t conn_handle)
cccd_value.chr_val_handle);
if (clt_cfg != NULL) {
clt_cfg->flags = cccd_value.flags;
+
if (cccd_value.value_changed) {
+ /* The characteristic's value changed while the device was
+ * disconnected or unbonded. Schedule the notification or
+ * indication now.
+ */
+ clt_cfg->flags |= BLE_GATTS_CLT_CFG_F_MODIFIED;
att_op = ble_gatts_schedule_update(conn, clt_cfg);
}
}
ble_hs_unlock();
+ /* Tell the application if the peer changed its subscription state
+ * when it was restored from persistence.
+ */
+ ble_gatts_subscribe_event(conn_handle, cccd_value.chr_val_handle,
+ BLE_GAP_SUBSCRIBE_REASON_RESTORE,
+ 0, cccd_value.flags);
+
switch (att_op) {
case 0:
break;
+
case BLE_ATT_OP_NOTIFY_REQ:
rc = ble_gattc_notify(conn_handle, cccd_value.chr_val_handle);
if (rc == 0) {
@@ -1384,10 +1633,11 @@ ble_gatts_bonding_restored(uint16_t conn_handle)
ble_store_write_cccd(&cccd_value);
}
break;
+
case BLE_ATT_OP_INDICATE_REQ:
- ble_gattc_indicate(conn_handle, cccd_value.chr_val_handle,
- NULL, NULL);
+ ble_gattc_indicate(conn_handle, cccd_value.chr_val_handle);
break;
+
default:
BLE_HS_DBG_ASSERT(0);
break;
@@ -1397,6 +1647,384 @@ ble_gatts_bonding_restored(uint16_t conn_handle)
}
}
+static struct ble_gatts_svc_entry *
+ble_gatts_find_svc_entry(const void *uuid128)
+{
+ struct ble_gatts_svc_entry *entry;
+ int i;
+
+ for (i = 0; i < ble_gatts_num_svc_entries; i++) {
+ entry = ble_gatts_svc_entries + i;
+ if (memcmp(uuid128, entry->svc->uuid128, 16) == 0) {
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+ble_gatts_find_svc_chr_attr(const void *svc_uuid128, const void *chr_uuid128,
+ struct ble_gatts_svc_entry **out_svc_entry,
+ struct ble_att_svr_entry **out_att_chr)
+{
+ struct ble_gatts_svc_entry *svc_entry;
+ struct ble_att_svr_entry *att_svc;
+ struct ble_att_svr_entry *next;
+ struct ble_att_svr_entry *cur;
+ uint16_t uuid16;
+
+ svc_entry = ble_gatts_find_svc_entry(svc_uuid128);
+ if (svc_entry == NULL) {
+ return BLE_HS_ENOENT;
+ }
+
+ att_svc = ble_att_svr_find_by_handle(svc_entry->handle);
+ if (att_svc == NULL) {
+ return BLE_HS_EUNKNOWN;
+ }
+
+ cur = STAILQ_NEXT(att_svc, ha_next);
+ while (1) {
+ if (cur == NULL) {
+ /* Reached end of attribute list without a match. */
+ return BLE_HS_ENOENT;
+ }
+ next = STAILQ_NEXT(cur, ha_next);
+
+ if (cur->ha_handle_id == svc_entry->end_group_handle) {
+ /* Reached end of service without a match. */
+ return BLE_HS_ENOENT;
+ }
+
+ uuid16 = ble_uuid_128_to_16(cur->ha_uuid);
+ if (uuid16 == BLE_ATT_UUID_CHARACTERISTIC &&
+ next != NULL &&
+ memcmp(next->ha_uuid, chr_uuid128, 16) == 0) {
+
+ if (out_svc_entry != NULL) {
+ *out_svc_entry = svc_entry;
+ }
+ if (out_att_chr != NULL) {
+ *out_att_chr = next;
+ }
+ return 0;
+ }
+
+ cur = next;
+ }
+}
+
+/**
+ * Retrieves the attribute handle associated with a local GATT service.
+ *
+ * @param uuid128 The UUID of the service to look up.
+ * @param out_handle On success, populated with the handle of the
+ * service attribute. Pass null if you don't
+ * need this value.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOENT if the specified service could
+ * not be found.
+ */
+int
+ble_gatts_find_svc(const void *uuid128, uint16_t *out_handle)
+{
+ struct ble_gatts_svc_entry *entry;
+
+ entry = ble_gatts_find_svc_entry(uuid128);
+ if (entry == NULL) {
+ return BLE_HS_ENOENT;
+ }
+
+ if (out_handle != NULL) {
+ *out_handle = entry->handle;
+ }
+ return 0;
+}
+
+/**
+ * Retrieves the pair of attribute handles associated with a local GATT
+ * characteristic.
+ *
+ * @param svc_uuid128 The UUID of the parent service.
+ * @param chr_uuid128 The UUID of the characteristic to look up.
+ * @param out_def_handle On success, populated with the handle
+ * of the characteristic definition attribute.
+ * Pass null if you don't need this value.
+ * @param out_val_handle On success, populated with the handle
+ * of the characteristic value attribute.
+ * Pass null if you don't need this value.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOENT if the specified service or
+ * characteristic could not be found.
+ */
+int
+ble_gatts_find_chr(const void *svc_uuid128, const void *chr_uuid128,
+ uint16_t *out_def_handle, uint16_t *out_val_handle)
+{
+ struct ble_att_svr_entry *att_chr;
+ int rc;
+
+ rc = ble_gatts_find_svc_chr_attr(svc_uuid128, chr_uuid128, NULL, &att_chr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ if (out_def_handle) {
+ *out_def_handle = att_chr->ha_handle_id - 1;
+ }
+ if (out_val_handle) {
+ *out_val_handle = att_chr->ha_handle_id;
+ }
+ return 0;
+}
+
+/**
+ * Retrieves the attribute handle associated with a local GATT descriptor.
+ *
+ * @param svc_uuid128 The UUID of the grandparent service.
+ * @param chr_uuid128 The UUID of the parent characteristic.
+ * @param dsc_uuid128 The UUID of the descriptor ro look up.
+ * @param out_handle On success, populated with the handle
+ * of the descripytor attribute. Pass null if
+ * you don't need this value.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOENT if the specified service,
+ * characteristic, or descriptor could not be
+ * found.
+ */
+int
+ble_gatts_find_dsc(const void *svc_uuid128, const void *chr_uuid128,
+ const void *dsc_uuid128, uint16_t *out_handle)
+{
+ struct ble_gatts_svc_entry *svc_entry;
+ struct ble_att_svr_entry *att_chr;
+ struct ble_att_svr_entry *cur;
+ uint16_t uuid16;
+ int rc;
+
+ rc = ble_gatts_find_svc_chr_attr(svc_uuid128, chr_uuid128, &svc_entry,
+ &att_chr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ cur = STAILQ_NEXT(att_chr, ha_next);
+ while (1) {
+ if (cur == NULL) {
+ /* Reached end of attribute list without a match. */
+ return BLE_HS_ENOENT;
+ }
+
+ if (cur->ha_handle_id == svc_entry->end_group_handle) {
+ /* Reached end of service without a match. */
+ return BLE_HS_ENOENT;
+ }
+
+ uuid16 = ble_uuid_128_to_16(cur->ha_uuid);
+ if (uuid16 == BLE_ATT_UUID_CHARACTERISTIC) {
+ /* Reached end of characteristic without a match. */
+ return BLE_HS_ENOENT;
+ }
+
+ if (memcmp(cur->ha_uuid, dsc_uuid128, 16) == 0) {
+ if (out_handle != NULL) {
+ *out_handle = cur->ha_handle_id;
+ return 0;
+ }
+ }
+ cur = STAILQ_NEXT(cur, ha_next);
+ }
+}
+
+/**
+ * Queues a set of service definitions for registration. All services queued
+ * in this manner get registered when ble_hs_init() is called.
+ *
+ * @param svcs An array of service definitions to queue for
+ * registration. This array must be
+ * terminated with an entry whose 'type'
+ * equals 0.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOMEM on heap exhaustion.
+ */
+int
+ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs)
+{
+ void *p;
+
+ p = realloc(ble_gatts_svc_defs,
+ (ble_gatts_num_svc_defs + 1) * sizeof *ble_gatts_svc_defs);
+ if (p == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ ble_gatts_svc_defs = p;
+ ble_gatts_svc_defs[ble_gatts_num_svc_defs] = svcs;
+ ble_gatts_num_svc_defs++;
+
+ return 0;
+}
+
+/**
+ * Accumulates counts of each resource type required by the specified service
+ * definition array. This function is generally used to calculate some host
+ * configuration values prior to initialization. This function adds the counts
+ * to the appropriate fields in the supplied ble_gatt_resources object without
+ * clearing them first, so it can be called repeatedly with different inputs to
+ * calculate totals. Be sure to zero the resource struct prior to the first
+ * call to this function.
+ *
+ * @param svcs The service array containing the resource
+ * definitions to be counted.
+ * @param res The resource counts are accumulated in this
+ * struct.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if the svcs array contains an
+ * invalid resource definition.
+ */
+int
+ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs,
+ struct ble_gatt_resources *res)
+{
+ const struct ble_gatt_svc_def *svc;
+ const struct ble_gatt_chr_def *chr;
+ int s;
+ int i;
+ int c;
+ int d;
+
+ for (s = 0; svcs[s].type != BLE_GATT_SVC_TYPE_END; s++) {
+ svc = svcs + s;
+
+ if (!ble_gatts_svc_is_sane(svc)) {
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_HS_EINVAL;
+ }
+
+ /* Each service requires:
+ * o 1 service
+ * o 1 attribute
+ */
+ res->svcs++;
+ res->attrs++;
+
+ if (svc->includes != NULL) {
+ for (i = 0; svc->includes[i] != NULL; i++) {
+ /* Each include requires:
+ * o 1 include
+ * o 1 attribute
+ */
+ res->incs++;
+ res->attrs++;
+ }
+ }
+
+ if (svc->characteristics != NULL) {
+ for (c = 0; svc->characteristics[c].uuid128 != NULL; c++) {
+ chr = svc->characteristics + c;
+
+ if (!ble_gatts_chr_is_sane(chr)) {
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_HS_EINVAL;
+ }
+
+ /* Each characteristic requires:
+ * o 1 characteristic
+ * o 2 attributes
+ */
+ res->chrs++;
+ res->attrs += 2;
+
+ /* If the characteristic permits notifications or indications,
+ * it has a CCCD.
+ */
+ if (chr->flags & BLE_GATT_CHR_F_NOTIFY ||
+ chr->flags & BLE_GATT_CHR_F_INDICATE) {
+
+ /* Each CCCD requires:
+ * o 1 descriptor
+ * o 1 CCCD
+ * o 1 attribute
+ */
+ res->dscs++;
+ res->cccds++;
+ res->attrs++;
+ }
+
+ if (chr->descriptors != NULL) {
+ for (d = 0; chr->descriptors[d].uuid128 != NULL; d++) {
+ if (!ble_gatts_dsc_is_sane(chr->descriptors + d)) {
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_HS_EINVAL;
+ }
+
+ /* Each descriptor requires:
+ * o 1 descriptor
+ * o 1 attribute
+ */
+ res->dscs++;
+ res->attrs++;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Adjusts a host configuration object's settings to accommodate the specified
+ * service definition array. This function adds the counts to the appropriate
+ * fields in the supplied configuration object without clearing them first, so
+ * it can be called repeatedly with different inputs to calculate totals. Be
+ * sure to zero the GATT server settings prior to the first call to this
+ * function.
+ *
+ * @param defs The service array containing the resource
+ * definitions to be counted.
+ * @param cfg The resource counts are accumulated in this
+ * configuration object.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if the svcs array contains an
+ * invalid resource definition.
+ */
+int
+ble_gatts_count_cfg(const struct ble_gatt_svc_def *defs,
+ struct ble_hs_cfg *cfg)
+{
+ struct ble_gatt_resources res = { 0 };
+ int rc;
+
+ rc = ble_gatts_count_resources(defs, &res);
+ if (rc != 0) {
+ return rc;
+ }
+
+ cfg->max_services += res.svcs;
+ cfg->max_attrs += res.attrs;
+
+ /* Reserve an extra CCCD for the cache. */
+ cfg->max_client_configs += res.cccds * (cfg->max_connections + 1);
+
+ return 0;
+}
+
+static void
+ble_gatts_free_svc_defs(void)
+{
+ free(ble_gatts_svc_defs);
+ ble_gatts_svc_defs = NULL;
+ ble_gatts_num_svc_defs = 0;
+}
+
static void
ble_gatts_free_mem(void)
{
@@ -1411,6 +2039,7 @@ int
ble_gatts_init(void)
{
int rc;
+ int i;
ble_gatts_free_mem();
ble_gatts_num_cfgable_chrs = 0;
@@ -1435,6 +2064,17 @@ ble_gatts_init(void)
}
}
+ ble_gatts_num_svc_entries = 0;
+ for (i = 0; i < ble_gatts_num_svc_defs; i++) {
+ rc = ble_gatts_register_svcs(ble_gatts_svc_defs[i],
+ ble_hs_cfg.gatts_register_cb,
+ ble_hs_cfg.gatts_register_arg);
+ if (rc != 0) {
+ goto err;
+ }
+ }
+ ble_gatts_free_svc_defs();
+
rc = stats_init_and_reg(
STATS_HDR(ble_gatts_stats), STATS_SIZE_INIT_PARMS(ble_gatts_stats,
STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_gatts_stats), "ble_gatts");
@@ -1447,5 +2087,6 @@ ble_gatts_init(void)
err:
ble_gatts_free_mem();
+ ble_gatts_free_svc_defs();
return rc;
}
diff --git a/net/nimble/host/src/ble_hci_cmd.c b/net/nimble/host/src/ble_hci_cmd.c
deleted file mode 100644
index 23eaba37..00000000
--- a/net/nimble/host/src/ble_hci_cmd.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include "os/os.h"
-#include "ble_hs_priv.h"
-#include "host_dbg_priv.h"
-
-#define BLE_HCI_CMD_TIMEOUT (OS_TICKS_PER_SEC)
-
-static struct os_mutex ble_hci_cmd_mutex;
-static struct os_sem ble_hci_cmd_sem;
-
-#if PHONY_HCI_ACKS
-static ble_hci_cmd_phony_ack_fn *ble_hci_cmd_phony_ack_cb;
-#endif
-
-#if PHONY_HCI_ACKS
-void
-ble_hci_set_phony_ack_cb(ble_hci_cmd_phony_ack_fn *cb)
-{
- ble_hci_cmd_phony_ack_cb = cb;
-}
-#endif
-
-static void
-ble_hci_cmd_lock(void)
-{
- int rc;
-
- rc = os_mutex_pend(&ble_hci_cmd_mutex, 0xffffffff);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
-}
-
-static void
-ble_hci_cmd_unlock(void)
-{
- int rc;
-
- rc = os_mutex_release(&ble_hci_cmd_mutex);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
-}
-
-static int
-ble_hci_cmd_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len,
- struct ble_hci_ack *out_ack)
-{
- uint16_t opcode;
- uint8_t *params;
- uint8_t params_len;
- uint8_t num_pkts;
-
- if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
- /* XXX: Increment stat. */
- return BLE_HS_ECONTROLLER;
- }
-
- num_pkts = data[2];
- opcode = le16toh(data + 3);
- params = data + 5;
-
- /* XXX: Process num_pkts field. */
- (void)num_pkts;
-
- out_ack->bha_opcode = opcode;
-
- params_len = len - BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN;
- if (params_len > 0) {
- out_ack->bha_status = BLE_HS_HCI_ERR(params[0]);
- } else if (opcode == BLE_HCI_OPCODE_NOP) {
- out_ack->bha_status = 0;
- } else {
- out_ack->bha_status = BLE_HS_ECONTROLLER;
- }
-
- /* Don't include the status byte in the parameters blob. */
- if (params_len > 1) {
- out_ack->bha_params = params + 1;
- out_ack->bha_params_len = params_len - 1;
- } else {
- out_ack->bha_params = NULL;
- out_ack->bha_params_len = 0;
- }
-
- return 0;
-}
-
-static int
-ble_hci_cmd_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
- struct ble_hci_ack *out_ack)
-{
- uint16_t opcode;
- uint8_t num_pkts;
- uint8_t status;
-
- if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
- /* XXX: Increment stat. */
- return BLE_HS_ECONTROLLER;
- }
-
- status = data[2];
- num_pkts = data[3];
- opcode = le16toh(data + 4);
-
- /* XXX: Process num_pkts field. */
- (void)num_pkts;
-
- out_ack->bha_opcode = opcode;
- out_ack->bha_params = NULL;
- out_ack->bha_params_len = 0;
- out_ack->bha_status = BLE_HS_HCI_ERR(status);
-
- return 0;
-}
-
-static int
-ble_hci_cmd_process_ack(uint8_t *params_buf, uint8_t params_buf_len,
- struct ble_hci_ack *out_ack)
-{
- uint8_t event_code;
- uint8_t param_len;
- uint8_t event_len;
- int rc;
-
- /***
- * The controller always reuses the command buffer for its acknowledgement
- * events. This function processes the acknowledgement event contained in
- * the command buffer.
- */
-
- /* Count events received */
- STATS_INC(ble_hs_stats, hci_event);
-
- /* Display to console */
- host_hci_dbg_event_disp(host_hci_cmd_buf);
-
- event_code = host_hci_cmd_buf[0];
- param_len = host_hci_cmd_buf[1];
- event_len = param_len + 2;
-
- /* Clear ack fields up front to silence spurious gcc warnings. */
- memset(out_ack, 0, sizeof *out_ack);
-
- switch (event_code) {
- case BLE_HCI_EVCODE_COMMAND_COMPLETE:
- rc = ble_hci_cmd_rx_cmd_complete(event_code, host_hci_cmd_buf,
- event_len, out_ack);
- break;
-
- case BLE_HCI_EVCODE_COMMAND_STATUS:
- rc = ble_hci_cmd_rx_cmd_status(event_code, host_hci_cmd_buf,
- event_len, out_ack);
- break;
-
- default:
- BLE_HS_DBG_ASSERT(0);
- rc = BLE_HS_EUNKNOWN;
- break;
- }
-
- if (rc == 0) {
- if (params_buf == NULL) {
- out_ack->bha_params_len = 0;
- } else {
- if (out_ack->bha_params_len > params_buf_len) {
- out_ack->bha_params_len = params_buf_len;
- rc = BLE_HS_ECONTROLLER;
- }
- memcpy(params_buf, out_ack->bha_params, out_ack->bha_params_len);
- }
- out_ack->bha_params = params_buf;
- }
-
- return rc;
-}
-
-static int
-ble_hci_cmd_wait_for_ack(void)
-{
- int rc;
-
-#if PHONY_HCI_ACKS
- if (ble_hci_cmd_phony_ack_cb == NULL) {
- rc = BLE_HS_ETIMEOUT_HCI;
- } else {
- rc = ble_hci_cmd_phony_ack_cb(host_hci_cmd_buf, 260);
- }
-#else
- rc = os_sem_pend(&ble_hci_cmd_sem, BLE_HCI_CMD_TIMEOUT);
- switch (rc) {
- case 0:
- break;
- case OS_TIMEOUT:
- rc = BLE_HS_ETIMEOUT_HCI;
- break;
- default:
- rc = BLE_HS_EOS;
- break;
- }
-#endif
-
- return rc;
-}
-
-int
-ble_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
- uint8_t *out_evt_buf_len)
-{
- struct ble_hci_ack ack;
- int rc;
-
- ble_hci_cmd_lock();
-
- rc = host_hci_cmd_send_buf(cmd);
- if (rc != 0) {
- goto done;
- }
-
- rc = ble_hci_cmd_wait_for_ack();
- if (rc != 0) {
- goto done;
- }
-
- rc = ble_hci_cmd_process_ack(evt_buf, evt_buf_len, &ack);
- if (rc != 0) {
- goto done;
- }
-
- if (out_evt_buf_len != NULL) {
- *out_evt_buf_len = ack.bha_params_len;
- }
-
- rc = ack.bha_status;
-
-done:
- ble_hci_cmd_unlock();
- return rc;
-}
-
-int
-ble_hci_cmd_tx_empty_ack(void *cmd)
-{
- int rc;
-
- rc = ble_hci_cmd_tx(cmd, NULL, 0, NULL);
- if (rc != 0) {
- return rc;
- }
-
- return 0;
-}
-
-void
-ble_hci_cmd_rx_ack(uint8_t *ack_ev)
-{
- /* The controller should always reuse the command buffer for its acks. */
- BLE_HS_DBG_ASSERT(ack_ev == host_hci_cmd_buf);
-
- if (ble_hci_cmd_sem.sem_tokens != 0) {
- /* This ack is unexpected; ignore it. */
- return;
- }
-
- /* Unblock the application now that the HCI command buffer is populated
- * with the acknowledgement.
- */
- os_sem_release(&ble_hci_cmd_sem);
-}
-
-void
-ble_hci_cmd_init(void)
-{
- int rc;
-
- rc = os_sem_init(&ble_hci_cmd_sem, 0);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
-
- rc = os_mutex_init(&ble_hci_cmd_mutex);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
-}
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index bd092173..8d4b0473 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -23,38 +23,44 @@
#include "stats/stats.h"
#include "util/tpq.h"
#include "os/os.h"
-#include "nimble/hci_transport.h"
-#include "host/host_hci.h"
+#include "nimble/ble_hci_trans.h"
#include "ble_hs_priv.h"
-#ifdef PHONY_TRANSPORT
-#include "host/ble_hs_test.h"
-#endif
-#ifdef ARCH_sim
-#define BLE_HS_STACK_SIZE (1024)
-#else
-#define BLE_HS_STACK_SIZE (512)//(250)
-#endif
+/**
+ * The maximum number of events the host will process in a row before returning
+ * control to the parent task.
+ */
+#define BLE_HS_MAX_EVS_IN_A_ROW 2
static struct log_handler ble_hs_log_console_handler;
-struct log ble_hs_log;
-struct os_mempool g_hci_cmd_pool;
-static void *ble_hs_hci_cmd_buf;
+struct os_mempool ble_hs_hci_ev_pool;
+static void *ble_hs_hci_os_event_buf;
-/* XXX: this might be transport layer */
-#define HCI_OS_EVENT_BUF_SIZE (sizeof(struct os_event))
+/** OS event - triggers tx of pending notifications and indications. */
+static struct os_event ble_hs_event_tx_notifications = {
+ .ev_type = BLE_HS_EVENT_TX_NOTIFICATIONS,
+ .ev_arg = NULL,
+};
-struct os_mempool g_hci_os_event_pool;
-static void *ble_hs_hci_os_event_buf;
+/** OS event - triggers a full reset. */
+static struct os_event ble_hs_event_reset = {
+ .ev_type = BLE_HS_EVENT_RESET,
+ .ev_arg = NULL,
+};
+
+uint8_t ble_hs_sync_state;
+static int ble_hs_reset_reason;
#if MYNEWT_SELFTEST
/** Use a higher frequency timer to allow tests to run faster. */
-#define BLE_HS_HEARTBEAT_OS_TICKS (OS_TICKS_PER_SEC / 10)
+#define BLE_HS_HEARTBEAT_OS_TICKS (OS_TICKS_PER_SEC / 10)
#else
-#define BLE_HS_HEARTBEAT_OS_TICKS OS_TICKS_PER_SEC
+#define BLE_HS_HEARTBEAT_OS_TICKS OS_TICKS_PER_SEC
#endif
+#define BLE_HS_SYNC_RETRY_RATE (OS_TICKS_PER_SEC / 10)
+
/**
* Handles unresponsive timeouts and periodic retries in case of resource
* shortage.
@@ -86,6 +92,9 @@ STATS_NAME_START(ble_hs_stats)
STATS_NAME(ble_hs_stats, hci_event)
STATS_NAME(ble_hs_stats, hci_invalid_ack)
STATS_NAME(ble_hs_stats, hci_unknown_event)
+ STATS_NAME(ble_hs_stats, hci_timeout)
+ STATS_NAME(ble_hs_stats, reset)
+ STATS_NAME(ble_hs_stats, sync)
STATS_NAME_END(ble_hs_stats)
int
@@ -153,24 +162,31 @@ ble_hs_process_tx_data_queue(void)
struct os_mbuf *om;
while ((om = os_mqueue_get(&ble_hs_tx_q)) != NULL) {
-#ifdef PHONY_TRANSPORT
- ble_hs_test_pkt_txed(om);
-#else
- ble_hci_transport_host_acl_data_send(om);
-#endif
+ ble_hci_trans_hs_acl_tx(om);
}
}
-static void
+void
ble_hs_process_rx_data_queue(void)
{
struct os_mbuf *om;
while ((om = os_mqueue_get(&ble_hs_rx_q)) != NULL) {
- host_hci_data_rx(om);
+ ble_hs_hci_evt_acl_process(om);
+ }
+}
+
+static void
+ble_hs_clear_data_queue(struct os_mqueue *mqueue)
+{
+ struct os_mbuf *om;
+
+ while ((om = os_mqueue_get(mqueue)) != NULL) {
+ os_mbuf_free_chain(om);
}
}
+
static void
ble_hs_heartbeat_timer_reset(uint32_t ticks)
{
@@ -180,6 +196,102 @@ ble_hs_heartbeat_timer_reset(uint32_t ticks)
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
+void
+ble_hs_heartbeat_sched(int32_t ticks_from_now)
+{
+ if (ticks_from_now == BLE_HS_FOREVER) {
+ return;
+ }
+
+ /* Reset heartbeat timer if it is not currently scheduled or if the
+ * specified time is sooner than the current expiration time.
+ */
+ if (!os_callout_queued(&ble_hs_heartbeat_timer.cf_c) ||
+ OS_TIME_TICK_LT(ticks_from_now, ble_hs_heartbeat_timer.cf_c.c_ticks)) {
+
+ ble_hs_heartbeat_timer_reset(ticks_from_now);
+ }
+}
+
+/**
+ * Indicates whether the host has synchronized with the controller.
+ * Synchronization must occur before any host procedures can be performed.
+ *
+ * @return 1 if the host and controller are in sync;
+ * 0 if the host and controller our out of sync.
+ */
+int
+ble_hs_synced(void)
+{
+ return ble_hs_sync_state == BLE_HS_SYNC_STATE_GOOD;
+}
+
+static int
+ble_hs_sync(void)
+{
+ int rc;
+
+ /* Set the sync state to "bringup." This allows the parent task to send
+ * the startup sequence to the controller. No other tasks are allowed to
+ * send any commands.
+ */
+ ble_hs_sync_state = BLE_HS_SYNC_STATE_BRINGUP;
+
+ rc = ble_hs_startup_go();
+ if (rc == 0) {
+ ble_hs_sync_state = BLE_HS_SYNC_STATE_GOOD;
+ if (ble_hs_cfg.sync_cb != NULL) {
+ ble_hs_cfg.sync_cb();
+ }
+ } else {
+ ble_hs_sync_state = BLE_HS_SYNC_STATE_BAD;
+ }
+
+ ble_hs_heartbeat_sched(BLE_HS_SYNC_RETRY_RATE);
+
+ if (rc == 0) {
+ STATS_INC(ble_hs_stats, sync);
+ }
+
+ return rc;
+}
+
+static int
+ble_hs_reset(void)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ STATS_INC(ble_hs_stats, reset);
+
+ ble_hs_sync_state = 0;
+
+ rc = ble_hci_trans_reset();
+ if (rc != 0) {
+ return rc;
+ }
+
+ ble_hs_clear_data_queue(&ble_hs_tx_q);
+ ble_hs_clear_data_queue(&ble_hs_rx_q);
+
+ while (1) {
+ conn_handle = ble_hs_atomic_first_conn_handle();
+ if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
+ break;
+ }
+
+ ble_gap_conn_broken(conn_handle, ble_hs_reset_reason);
+ }
+
+ if (ble_hs_cfg.reset_cb != NULL && ble_hs_reset_reason != 0) {
+ ble_hs_cfg.reset_cb(ble_hs_reset_reason);
+ }
+ ble_hs_reset_reason = 0;
+
+ rc = ble_hs_sync();
+ return rc;
+}
+
/**
* Called once a second by the ble_hs heartbeat timer. Handles unresponsive
* timeouts and periodic retries in case of resource shortage.
@@ -187,43 +299,62 @@ ble_hs_heartbeat_timer_reset(uint32_t ticks)
static void
ble_hs_heartbeat(void *unused)
{
- uint32_t lcl_ticks_until_next;
- uint32_t ticks_until_next;
+ int32_t ticks_until_next;
- ticks_until_next = BLE_HS_HEARTBEAT_OS_TICKS;
+ if (!ble_hs_sync_state) {
+ ble_hs_reset();
+ return;
+ }
- lcl_ticks_until_next = ble_gattc_heartbeat();
- ticks_until_next = min(ticks_until_next, lcl_ticks_until_next);
+ /* Ensure the timer expires at least once in the next second.
+ * XXX: This is not very power efficient. We will need separate timers for
+ * each module.
+ */
+ ticks_until_next = BLE_HS_HEARTBEAT_OS_TICKS;
+ ble_hs_heartbeat_sched(ticks_until_next);
- lcl_ticks_until_next = ble_gap_heartbeat();
- ticks_until_next = min(ticks_until_next, lcl_ticks_until_next);
+ ticks_until_next = ble_gattc_heartbeat();
+ ble_hs_heartbeat_sched(ticks_until_next);
- lcl_ticks_until_next = ble_l2cap_sig_heartbeat();
- ticks_until_next = min(ticks_until_next, lcl_ticks_until_next);
+ ticks_until_next = ble_gap_heartbeat();
+ ble_hs_heartbeat_sched(ticks_until_next);
- lcl_ticks_until_next = ble_sm_heartbeat();
- ticks_until_next = min(ticks_until_next, lcl_ticks_until_next);
+ ticks_until_next = ble_l2cap_sig_heartbeat();
+ ble_hs_heartbeat_sched(ticks_until_next);
- ble_hs_heartbeat_timer_reset(ticks_until_next);
+ ticks_until_next = ble_sm_heartbeat();
+ ble_hs_heartbeat_sched(ticks_until_next);
}
static void
ble_hs_event_handle(void *unused)
{
struct os_callout_func *cf;
+ struct os_eventq *evqp;
struct os_event *ev;
- os_sr_t sr;
+ uint8_t *hci_evt;
+ int rc;
+ int i;
+ evqp = &ble_hs_evq;
+
+ i = 0;
while (1) {
- OS_ENTER_CRITICAL(sr);
- ev = STAILQ_FIRST(&ble_hs_evq.evq_list);
- OS_EXIT_CRITICAL(sr);
+ /* If the host has already processed several consecutive events, stop
+ * and return control to the parent task. Put an event on the parent
+ * task's eventq to indicate that more host events are enqueued.
+ */
+ if (i >= BLE_HS_MAX_EVS_IN_A_ROW) {
+ os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
+ break;
+ }
+ i++;
+ ev = os_eventq_poll(&evqp, 1, 0);
if (ev == NULL) {
break;
}
- ev = os_eventq_get(&ble_hs_evq);
switch (ev->ev_type) {
case OS_EVENT_T_TIMER:
cf = (struct os_callout_func *)ev;
@@ -232,8 +363,16 @@ ble_hs_event_handle(void *unused)
break;
case BLE_HOST_HCI_EVENT_CTLR_EVENT:
- /* Process HCI event from controller */
- host_hci_os_event_proc(ev);
+ hci_evt = ev->ev_arg;
+ rc = os_memblock_put(&ble_hs_hci_ev_pool, ev);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+
+ ble_hs_hci_evt_process(hci_evt);
+ break;
+
+ case BLE_HS_EVENT_TX_NOTIFICATIONS:
+ BLE_HS_DBG_ASSERT(ev == &ble_hs_event_tx_notifications);
+ ble_gatts_tx_notifications();
break;
case OS_EVENT_T_MQUEUE_DATA:
@@ -241,6 +380,11 @@ ble_hs_event_handle(void *unused)
ble_hs_process_rx_data_queue();
break;
+ case BLE_HS_EVENT_RESET:
+ BLE_HS_DBG_ASSERT(ev == &ble_hs_event_reset);
+ ble_hs_reset();
+ break;
+
default:
BLE_HS_DBG_ASSERT(0);
break;
@@ -255,6 +399,67 @@ ble_hs_event_enqueue(struct os_event *ev)
os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
}
+void
+ble_hs_enqueue_hci_event(uint8_t *hci_evt)
+{
+ struct os_event *ev;
+
+ ev = os_memblock_get(&ble_hs_hci_ev_pool);
+ if (ev == NULL) {
+ ble_hci_trans_buf_free(hci_evt);
+ } else {
+ ev->ev_queued = 0;
+ ev->ev_type = BLE_HOST_HCI_EVENT_CTLR_EVENT;
+ ev->ev_arg = hci_evt;
+ ble_hs_event_enqueue(ev);
+ }
+}
+
+/**
+ * Schedules for all pending notifications and indications to be sent in the
+ * host parent task.
+ */
+void
+ble_hs_notifications_sched(void)
+{
+#if MYNEWT_SELFTEST
+ if (!os_started()) {
+ ble_gatts_tx_notifications();
+ return;
+ }
+#endif
+
+ ble_hs_event_enqueue(&ble_hs_event_tx_notifications);
+}
+
+void
+ble_hs_sched_reset(int reason)
+{
+ BLE_HS_DBG_ASSERT(ble_hs_reset_reason == 0);
+
+ ble_hs_reset_reason = reason;
+ ble_hs_event_enqueue(&ble_hs_event_reset);
+}
+
+void
+ble_hs_hw_error(uint8_t hw_code)
+{
+ ble_hs_sched_reset(BLE_HS_HW_ERR(hw_code));
+}
+
+/**
+ * Synchronizes the host with the controller by sending a sequence of HCI
+ * commands. This function must be called before any other host functionality
+ * is used, but it must be called after both the host and controller are
+ * initialized. Typically, the host-parent-task calls this function at the top
+ * of its task routine.
+ *
+ * If the host fails to synchronize with the controller (if the controller is
+ * not fully booted, for example), the host will attempt to resynchronize every
+ * 100 ms. For this reason, an error return code is not necessarily fatal.
+ *
+ * @return 0 on success; nonzero on error.
+ */
int
ble_hs_start(void)
{
@@ -262,11 +467,9 @@ ble_hs_start(void)
ble_hs_parent_task = os_sched_get_current_task();
- ble_hs_heartbeat_timer_reset(BLE_HS_HEARTBEAT_OS_TICKS);
-
ble_gatts_start();
- rc = ble_hs_startup_go();
+ rc = ble_hs_sync();
return rc;
}
@@ -280,19 +483,29 @@ ble_hs_start(void)
* @return 0 on success; nonzero on failure.
*/
int
-ble_hs_rx_data(struct os_mbuf *om)
+ble_hs_rx_data(struct os_mbuf *om, void *arg)
{
int rc;
rc = os_mqueue_put(&ble_hs_rx_q, &ble_hs_evq, om);
- if (rc != 0) {
- return BLE_HS_EOS;
+ if (rc == 0) {
+ os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
+ } else {
+ os_mbuf_free_chain(om);
+ rc = BLE_HS_EOS;
}
- os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
-
- return 0;
+ return rc;
}
+/**
+ * Enqueues an ACL data packet for transmission. This function consumes the
+ * supplied mbuf, regardless of the outcome.
+ *
+ * @param om The outgoing data packet, beginning with the
+ * HCI ACL data header.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
int
ble_hs_tx_data(struct os_mbuf *om)
{
@@ -300,6 +513,7 @@ ble_hs_tx_data(struct os_mbuf *om)
rc = os_mqueue_put(&ble_hs_tx_q, &ble_hs_evq, om);
if (rc != 0) {
+ os_mbuf_free_chain(om);
return BLE_HS_EOS;
}
os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
@@ -310,15 +524,26 @@ ble_hs_tx_data(struct os_mbuf *om)
static void
ble_hs_free_mem(void)
{
- free(ble_hs_hci_cmd_buf);
- ble_hs_hci_cmd_buf = NULL;
-
free(ble_hs_hci_os_event_buf);
ble_hs_hci_os_event_buf = NULL;
}
/**
- * Initializes the host portion of the BLE stack.
+ * Initializes the NimBLE host. This function must be called before the OS is
+ * started. The NimBLE stack requires an application task to function. One
+ * application task in particular is designated as the "host parent task". In
+ * addition to application-specific work, the host parent task does work for
+ * NimBLE by processing events generated by the host.
+ *
+ * @param app_evq The event queue associated with the host parent
+ * task.
+ * @param cfg The set of configuration settings to initialize
+ * the host with. Specify null for defaults.
+ *
+ * @return 0 on success;
+ * BLE_HS_ENOMEM if initialization failed due to
+ * resource exhaustion.
+ * Other nonzero on error.
*/
int
ble_hs_init(struct os_eventq *app_evq, struct ble_hs_cfg *cfg)
@@ -339,30 +564,17 @@ ble_hs_init(struct os_eventq *app_evq, struct ble_hs_cfg *cfg)
log_console_handler_init(&ble_hs_log_console_handler);
log_register("ble_hs", &ble_hs_log, &ble_hs_log_console_handler);
- ble_hs_hci_cmd_buf = malloc(OS_MEMPOOL_BYTES(ble_hs_cfg.max_hci_bufs,
- HCI_CMD_BUF_SIZE));
- if (ble_hs_hci_cmd_buf == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
- }
-
- /* Create memory pool of command buffers */
- rc = os_mempool_init(&g_hci_cmd_pool, ble_hs_cfg.max_hci_bufs,
- HCI_CMD_BUF_SIZE, ble_hs_hci_cmd_buf,
- "HCICmdPool");
- assert(rc == 0);
-
- ble_hs_hci_os_event_buf = malloc(OS_MEMPOOL_BYTES(ble_hs_cfg.max_hci_bufs,
- HCI_OS_EVENT_BUF_SIZE));
+ ble_hs_hci_os_event_buf = malloc(
+ OS_MEMPOOL_BYTES(ble_hs_cfg.max_hci_bufs, sizeof (struct os_event)));
if (ble_hs_hci_os_event_buf == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
}
/* Create memory pool of OS events */
- rc = os_mempool_init(&g_hci_os_event_pool, ble_hs_cfg.max_hci_bufs,
- HCI_OS_EVENT_BUF_SIZE, ble_hs_hci_os_event_buf,
- "HCIOsEventPool");
+ rc = os_mempool_init(&ble_hs_hci_ev_pool, ble_hs_cfg.max_hci_bufs,
+ sizeof (struct os_event), ble_hs_hci_os_event_buf,
+ "ble_hs_hci_ev_pool");
assert(rc == 0);
/* Initialize eventq */
@@ -375,7 +587,7 @@ ble_hs_init(struct os_eventq *app_evq, struct ble_hs_cfg *cfg)
goto err;
}
- ble_hci_cmd_init();
+ ble_hs_hci_init();
rc = ble_hs_conn_init();
if (rc != 0) {
@@ -437,6 +649,9 @@ ble_hs_init(struct os_eventq *app_evq, struct ble_hs_cfg *cfg)
ble_hs_dbg_mutex_locked = 0;
#endif
+ /* Configure the HCI transport to communicate with a host. */
+ ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
+
return 0;
err:
diff --git a/net/nimble/host/src/ble_hs_adv.c b/net/nimble/host/src/ble_hs_adv.c
index c56bb194..fd7bfafb 100644
--- a/net/nimble/host/src/ble_hs_adv.c
+++ b/net/nimble/host/src/ble_hs_adv.c
@@ -20,8 +20,12 @@
#include <string.h>
#include <errno.h>
#include "nimble/ble.h"
+#include "host/ble_hs_adv.h"
#include "ble_hs_priv.h"
+static uint16_t ble_hs_adv_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2];
+static uint32_t ble_hs_adv_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4];
+
static int
ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len,
uint8_t *dst, uint8_t *dst_len)
@@ -39,7 +43,7 @@ ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len,
}
int
-ble_hs_adv_set_flat(uint8_t type, int data_len, void *data,
+ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
{
#if !NIMBLE_OPT(ADVERTISE)
@@ -62,7 +66,7 @@ ble_hs_adv_set_flat(uint8_t type, int data_len, void *data,
}
static int
-ble_hs_adv_set_array16(uint8_t type, uint8_t num_elems, uint16_t *elems,
+ble_hs_adv_set_array16(uint8_t type, uint8_t num_elems, const uint16_t *elems,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
{
int rc;
@@ -83,7 +87,7 @@ ble_hs_adv_set_array16(uint8_t type, uint8_t num_elems, uint16_t *elems,
}
static int
-ble_hs_adv_set_array32(uint8_t type, uint8_t num_elems, uint32_t *elems,
+ble_hs_adv_set_array32(uint8_t type, uint8_t num_elems, const uint32_t *elems,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
{
int rc;
@@ -106,10 +110,10 @@ ble_hs_adv_set_array32(uint8_t type, uint8_t num_elems, uint32_t *elems,
/**
* Sets the significant part of the data in outgoing advertisements.
*
- * @return 0 on success; on failure.
+ * @return 0 on success; nonzero on failure.
*/
int
-ble_hs_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
+ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
uint8_t *dst, uint8_t *dst_len, uint8_t max_len)
{
#if !NIMBLE_OPT(ADVERTISE)
@@ -117,11 +121,28 @@ ble_hs_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
#endif
uint8_t type;
+ int8_t tx_pwr_lvl;
int rc;
*dst_len = 0;
- /*** 0x01 - Flags (written automatically by GAP). */
+ /*** 0x01 - Flags. */
+ /* The application has three options concerning the flags field:
+ * 1. Don't include it in advertisements (!flags_is_present).
+ * 2. Explicitly specify the value (flags_is_present && flags != 0).
+ * 3. Let stack calculate the value (flags_is_present && flags == 0).
+ *
+ * For option 3, the calculation is delayed until advertising is enabled.
+ * The delay is necessary because the flags value depends on the type of
+ * advertising being performed which is not known at this time.
+ *
+ * Note: The CSS prohibits advertising a flags value of 0, so this method
+ * of specifying option 2 vs. 3 is sound.
+ */
+ if (adv_fields->flags_is_present && adv_fields->flags != 0) {
+ rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &adv_fields->flags,
+ dst, dst_len, max_len);
+ }
/*** 0x02,0x03 - 16-bit service class UUIDs. */
if (adv_fields->uuids16 != NULL && adv_fields->num_uuids16) {
@@ -185,7 +206,26 @@ ble_hs_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
}
}
- /*** 0x0a - Tx power level (written automatically by GAP). */
+ /*** 0x0a - Tx power level. */
+ if (adv_fields->tx_pwr_lvl_is_present) {
+ /* Read the power level from the controller if requested; otherwise use
+ * the explicitly specified value.
+ */
+ if (adv_fields->tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO) {
+ rc = ble_hs_hci_util_read_adv_tx_pwr(&tx_pwr_lvl);
+ if (rc != 0) {
+ return rc;
+ }
+ } else {
+ tx_pwr_lvl = adv_fields->tx_pwr_lvl;
+ }
+
+ rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1, &tx_pwr_lvl,
+ dst, dst_len, max_len);
+ if (rc != 0) {
+ return rc;
+ }
+ }
/*** 0x0d - Class of device. */
if (adv_fields->device_class != NULL) {
@@ -321,12 +361,53 @@ ble_hs_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
}
static int
+ble_hs_adv_parse_uuids16(struct ble_hs_adv_fields *adv_fields,
+ const uint8_t *data, uint8_t data_len)
+{
+ int i;
+
+ if (data_len % 2 != 0) {
+ return BLE_HS_EBADDATA;
+ }
+
+ adv_fields->uuids16 = ble_hs_adv_uuids16;
+ adv_fields->num_uuids16 = data_len / 2;
+
+ for (i = 0; i < adv_fields->num_uuids16; i++) {
+ adv_fields->uuids16[i] = le16toh(data + i * 2);
+ }
+
+ return 0;
+}
+
+static int
+ble_hs_adv_parse_uuids32(struct ble_hs_adv_fields *adv_fields,
+ const uint8_t *data, uint8_t data_len)
+{
+ int i;
+
+ if (data_len % 4 != 0) {
+ return BLE_HS_EBADDATA;
+ }
+
+ adv_fields->uuids32 = ble_hs_adv_uuids32;
+ adv_fields->num_uuids32 = data_len / 4;
+
+ for (i = 0; i < adv_fields->num_uuids32; i++) {
+ adv_fields->uuids32[i] = le32toh(data + i * 4);
+ }
+
+ return 0;
+}
+
+static int
ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
uint8_t *total_len, uint8_t *src, uint8_t src_len)
{
uint8_t data_len;
uint8_t type;
uint8_t *data;
+ int rc;
if (src_len < 1) {
return BLE_HS_EMSGSIZE;
@@ -341,6 +422,10 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
data = src + 2;
data_len = *total_len - 2;
+ if (data_len > BLE_HS_ADV_MAX_FIELD_SZ) {
+ return BLE_HS_EBADDATA;
+ }
+
switch (type) {
case BLE_HS_ADV_TYPE_FLAGS:
if (data_len != BLE_HS_ADV_FLAGS_LEN) {
@@ -351,39 +436,35 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
break;
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
- if (data_len % 2 != 0) {
- return BLE_HS_EBADDATA;
+ rc = ble_hs_adv_parse_uuids16(adv_fields, data, data_len);
+ if (rc != 0) {
+ return rc;
}
- adv_fields->uuids16 = data;
- adv_fields->num_uuids16 = data_len / 2;
adv_fields->uuids16_is_complete = 0;
break;
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
- if (data_len % 2 != 0) {
- return BLE_HS_EBADDATA;
+ rc = ble_hs_adv_parse_uuids16(adv_fields, data, data_len);
+ if (rc != 0) {
+ return rc;
}
- adv_fields->uuids16 = data;
- adv_fields->num_uuids16 = data_len / 2;
adv_fields->uuids16_is_complete = 1;
break;
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
- if (data_len % 4 != 0) {
- return BLE_HS_EBADDATA;
+ rc = ble_hs_adv_parse_uuids32(adv_fields, data, data_len);
+ if (rc != 0) {
+ return rc;
}
- adv_fields->uuids32 = data;
- adv_fields->num_uuids32 = data_len / 4;
- adv_fields->uuids32_is_complete = 0;
+ adv_fields->uuids16_is_complete = 0;
break;
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
- if (data_len % 4 != 0) {
- return BLE_HS_EBADDATA;
+ rc = ble_hs_adv_parse_uuids32(adv_fields, data, data_len);
+ if (rc != 0) {
+ return rc;
}
- adv_fields->uuids32 = data;
- adv_fields->num_uuids32 = data_len / 4;
- adv_fields->uuids32_is_complete = 1;
+ adv_fields->uuids16_is_complete = 1;
break;
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
@@ -443,6 +524,7 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
return BLE_HS_EBADDATA;
}
adv_fields->svc_data_uuid16 = data;
+ adv_fields->svc_data_uuid16_len = data_len;
break;
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
@@ -490,6 +572,7 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
return BLE_HS_EBADDATA;
}
adv_fields->svc_data_uuid32 = data;
+ adv_fields->svc_data_uuid32_len = data_len;
break;
case BLE_HS_ADV_TYPE_SVC_DATA_UUID128:
@@ -497,6 +580,7 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields,
return BLE_HS_EBADDATA;
}
adv_fields->svc_data_uuid128 = data;
+ adv_fields->svc_data_uuid128_len = data_len;
break;
case BLE_HS_ADV_TYPE_URI:
diff --git a/net/nimble/host/src/ble_hs_adv_priv.h b/net/nimble/host/src/ble_hs_adv_priv.h
index 5b853740..3ad4f49c 100644
--- a/net/nimble/host/src/ble_hs_adv_priv.h
+++ b/net/nimble/host/src/ble_hs_adv_priv.h
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -20,16 +20,11 @@
#ifndef H_BLE_HS_ADV_PRIV_
#define H_BLE_HS_ADV_PRIV_
-#include "host/ble_hs_adv.h"
-
-struct ble_hs_adv {
- uint8_t event_type;
- uint8_t addr_type;
- uint8_t length_data;
- int8_t rssi;
- uint8_t addr[6];
- uint8_t *data;
- struct ble_hs_adv_fields *fields;
-};
+int ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data,
+ uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
+int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
+ uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
+int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src,
+ uint8_t src_len);
#endif
diff --git a/net/nimble/host/src/ble_hs_atomic.c b/net/nimble/host/src/ble_hs_atomic.c
index 36a603dd..9c933fce 100644
--- a/net/nimble/host/src/ble_hs_atomic.c
+++ b/net/nimble/host/src/ble_hs_atomic.c
@@ -93,3 +93,23 @@ ble_hs_atomic_conn_set_flags(uint16_t conn_handle, ble_hs_conn_flags_t flags,
return rc;
}
+
+uint16_t
+ble_hs_atomic_first_conn_handle(void)
+{
+ const struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_first();
+ if (conn != NULL) {
+ conn_handle = conn->bhc_handle;
+ } else {
+ conn_handle = BLE_HS_CONN_HANDLE_NONE;
+ }
+
+ ble_hs_unlock();
+
+ return conn_handle;
+}
diff --git a/net/nimble/host/src/ble_hs_atomic_priv.h b/net/nimble/host/src/ble_hs_atomic_priv.h
index a08b7ca7..d82eeabc 100644
--- a/net/nimble/host/src/ble_hs_atomic_priv.h
+++ b/net/nimble/host/src/ble_hs_atomic_priv.h
@@ -28,5 +28,6 @@ int ble_hs_atomic_conn_flags(uint16_t conn_handle,
ble_hs_conn_flags_t *out_flags);
int ble_hs_atomic_conn_set_flags(uint16_t conn_handle,
ble_hs_conn_flags_t flags, int on);
+uint16_t ble_hs_atomic_first_conn_handle(void);
#endif
diff --git a/net/nimble/host/src/ble_hs_cfg.c b/net/nimble/host/src/ble_hs_cfg.c
index 6fe02365..eca8407e 100644
--- a/net/nimble/host/src/ble_hs_cfg.c
+++ b/net/nimble/host/src/ble_hs_cfg.c
@@ -19,31 +19,38 @@
#include "ble_hs_priv.h"
+#if NIMBLE_OPT(CONNECT)
+#define BLE_HS_CFG_MAX_CONNECTIONS NIMBLE_OPT(MAX_CONNECTIONS)
+#else
+#define BLE_HS_CFG_MAX_CONNECTIONS 0
+#endif
+
const struct ble_hs_cfg ble_hs_cfg_dflt = {
/** HCI settings. */
- .max_hci_bufs = 8,
+ .max_hci_bufs = 14,
/** Connection settings. */
-#if NIMBLE_OPT(CONNECT)
- .max_connections = NIMBLE_OPT(MAX_CONNECTIONS),
-#else
- .max_connections = 0,
-#endif
+ .max_connections = BLE_HS_CFG_MAX_CONNECTIONS,
/** GATT server settings. */
- .max_services = 16,
- .max_client_configs = 32,
+ /* These get set to zero with the expectation that they will be increased
+ * as needed when each supported GATT service is initialized.
+ */
+ .max_services = 0,
+ .max_client_configs = 0,
/** GATT client settings. */
- .max_gattc_procs = 16,
+ .max_gattc_procs = 4,
/** ATT server settings. */
- .max_attrs = 64,
+ /* This is set to 0; see note above re: GATT server settings. */
+ .max_attrs = 0,
.max_prep_entries = 6,
/** L2CAP settings. */
- .max_l2cap_chans = 16,
- .max_l2cap_sig_procs = 8,
+ /* Three channels per connection (sig, att, and sm). */
+ .max_l2cap_chans = 3 * BLE_HS_CFG_MAX_CONNECTIONS,
+ .max_l2cap_sig_procs = 1,
.max_l2cap_sm_procs = 1,
/** Security manager settings. */
@@ -55,7 +62,8 @@ const struct ble_hs_cfg ble_hs_cfg_dflt = {
.sm_keypress = 0,
.sm_our_key_dist = 0,
.sm_their_key_dist = 0,
- /** privacy info */
+
+ /** Privacy settings. */
.rpa_timeout = 300,
};
diff --git a/net/nimble/host/src/ble_hs_conn.c b/net/nimble/host/src/ble_hs_conn.c
index a4b0f16b..34d95903 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -20,7 +20,7 @@
#include <string.h>
#include <errno.h>
#include "os/os.h"
-#include "host/host_hci.h"
+#include "host/ble_hs_id.h"
#include "ble_hs_priv.h"
/** At least three channels required per connection (sig, att, sm). */
@@ -187,8 +187,6 @@ ble_hs_conn_free(struct ble_hs_conn *conn)
return;
}
- ble_gatts_conn_deinit(&conn->bhc_gatt_svr);
-
ble_att_svr_prep_clear(&conn->bhc_att_svr.basc_prep_list);
while ((chan = SLIST_FIRST(&conn->bhc_channels)) != NULL) {
@@ -247,6 +245,17 @@ ble_hs_conn_find(uint16_t conn_handle)
}
struct ble_hs_conn *
+ble_hs_conn_find_assert(uint16_t conn_handle)
+{
+ struct ble_hs_conn *conn;
+
+ conn = ble_hs_conn_find(conn_handle);
+ BLE_HS_DBG_ASSERT(conn != NULL);
+
+ return conn;
+}
+
+struct ble_hs_conn *
ble_hs_conn_find_by_addr(uint8_t addr_type, uint8_t *addr)
{
#if !NIMBLE_OPT(CONNECT)
@@ -258,8 +267,8 @@ ble_hs_conn_find_by_addr(uint8_t addr_type, uint8_t *addr)
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
- if (conn->bhc_addr_type == addr_type &&
- memcmp(conn->bhc_addr, addr, 6) == 0) {
+ if (conn->bhc_peer_addr_type == addr_type &&
+ memcmp(conn->bhc_peer_addr, addr, 6) == 0) {
return conn;
}
@@ -316,59 +325,52 @@ ble_hs_conn_first(void)
}
void
-ble_hs_conn_addrs(struct ble_hs_conn *conn,
+ble_hs_conn_addrs(const struct ble_hs_conn *conn,
struct ble_hs_conn_addrs *addrs)
{
+ int rc;
+
/* Determine our address information. */
- addrs->our_id_addr =
- ble_hs_pvcy_our_id_addr(&addrs->our_id_addr_type);
- if (memcmp(conn->our_rpa_addr, ble_hs_conn_null_addr, 6) == 0) {
+ addrs->our_id_addr_type =
+ ble_hs_misc_addr_type_to_id(conn->bhc_our_addr_type);
+ rc = ble_hs_id_addr(addrs->our_id_addr_type, &addrs->our_id_addr, NULL);
+ assert(rc == 0);
+
+ if (memcmp(conn->bhc_our_rpa_addr, ble_hs_conn_null_addr, 6) == 0) {
addrs->our_ota_addr_type = addrs->our_id_addr_type;
addrs->our_ota_addr = addrs->our_id_addr;
} else {
- switch (addrs->our_id_addr_type) {
- case BLE_ADDR_TYPE_PUBLIC:
- addrs->our_ota_addr_type = BLE_ADDR_TYPE_RPA_PUB_DEFAULT;
- break;
-
- case BLE_ADDR_TYPE_RANDOM:
- addrs->our_ota_addr_type = BLE_ADDR_TYPE_RPA_RND_DEFAULT;
- break;
-
- default:
- BLE_HS_DBG_ASSERT(0);
- }
-
- addrs->our_ota_addr = conn->our_rpa_addr;
+ addrs->our_ota_addr_type = conn->bhc_our_addr_type;
+ addrs->our_ota_addr = conn->bhc_our_rpa_addr;
}
/* Determine peer address information. */
- addrs->peer_ota_addr_type = conn->bhc_addr_type;
- addrs->peer_id_addr = conn->bhc_addr;
- switch (conn->bhc_addr_type) {
+ addrs->peer_ota_addr_type = conn->bhc_peer_addr_type;
+ addrs->peer_id_addr = conn->bhc_peer_addr;
+ switch (conn->bhc_peer_addr_type) {
case BLE_ADDR_TYPE_PUBLIC:
addrs->peer_id_addr_type = BLE_ADDR_TYPE_PUBLIC;
- addrs->peer_ota_addr = conn->bhc_addr;
+ addrs->peer_ota_addr = conn->bhc_peer_addr;
break;
case BLE_ADDR_TYPE_RANDOM:
addrs->peer_id_addr_type = BLE_ADDR_TYPE_RANDOM;
- addrs->peer_ota_addr = conn->bhc_addr;
+ addrs->peer_ota_addr = conn->bhc_peer_addr;
break;
case BLE_ADDR_TYPE_RPA_PUB_DEFAULT:
addrs->peer_id_addr_type = BLE_ADDR_TYPE_PUBLIC;
- addrs->peer_ota_addr = conn->peer_rpa_addr;
+ addrs->peer_ota_addr = conn->bhc_peer_rpa_addr;
break;
case BLE_ADDR_TYPE_RPA_RND_DEFAULT:
addrs->peer_id_addr_type = BLE_ADDR_TYPE_RANDOM;
- addrs->peer_ota_addr = conn->peer_rpa_addr;
+ addrs->peer_ota_addr = conn->bhc_peer_rpa_addr;
break;
default:
BLE_HS_DBG_ASSERT(0);
- return;
+ break;
}
}
diff --git a/net/nimble/host/src/ble_hs_conn_priv.h b/net/nimble/host/src/ble_hs_conn_priv.h
index 36b483dc..da8d2fc4 100644
--- a/net/nimble/host/src/ble_hs_conn_priv.h
+++ b/net/nimble/host/src/ble_hs_conn_priv.h
@@ -36,15 +36,16 @@ typedef uint8_t ble_hs_conn_flags_t;
struct ble_hs_conn {
SLIST_ENTRY(ble_hs_conn) bhc_next;
uint16_t bhc_handle;
- uint8_t bhc_addr_type;
- uint8_t our_addr_type;
- uint8_t bhc_addr[6];
- uint8_t our_rpa_addr[6];
- uint8_t peer_rpa_addr[6];
+ uint8_t bhc_peer_addr_type;
+ uint8_t bhc_our_addr_type;
+ uint8_t bhc_peer_addr[6];
+ uint8_t bhc_our_rpa_addr[6];
+ uint8_t bhc_peer_rpa_addr[6];
uint16_t bhc_itvl;
uint16_t bhc_latency;
uint16_t bhc_supervision_timeout;
+ uint8_t bhc_master_clock_accuracy;
ble_hs_conn_flags_t bhc_flags;
@@ -66,10 +67,10 @@ struct ble_hs_conn_addrs {
uint8_t our_id_addr_type;
uint8_t peer_ota_addr_type;
uint8_t peer_id_addr_type;
- uint8_t *our_ota_addr;
- uint8_t *our_id_addr;
- uint8_t *peer_ota_addr;
- uint8_t *peer_id_addr;
+ const uint8_t *our_ota_addr;
+ const uint8_t *our_id_addr;
+ const uint8_t *peer_ota_addr;
+ const uint8_t *peer_id_addr;
};
int ble_hs_conn_can_alloc(void);
@@ -78,6 +79,7 @@ void ble_hs_conn_free(struct ble_hs_conn *conn);
void ble_hs_conn_insert(struct ble_hs_conn *conn);
void ble_hs_conn_remove(struct ble_hs_conn *conn);
struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle);
+struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle);
struct ble_hs_conn *ble_hs_conn_find_by_addr(uint8_t addr_type, uint8_t *addr);
struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx);
int ble_hs_conn_exists(uint16_t conn_handle);
@@ -86,7 +88,7 @@ struct ble_l2cap_chan *ble_hs_conn_chan_find(struct ble_hs_conn *conn,
uint16_t cid);
int ble_hs_conn_chan_insert(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan);
-void ble_hs_conn_addrs(struct ble_hs_conn *conn,
+void ble_hs_conn_addrs(const struct ble_hs_conn *conn,
struct ble_hs_conn_addrs *addrs);
int ble_hs_conn_init(void);
diff --git a/net/nimble/host/src/host_dbg.c b/net/nimble/host/src/ble_hs_dbg.c
index 6b58624d..bb6ebdf9 100644
--- a/net/nimble/host/src/host_dbg.c
+++ b/net/nimble/host/src/ble_hs_dbg.c
@@ -23,11 +23,11 @@
#include "os/os.h"
#include "console/console.h"
#include "nimble/hci_common.h"
-#include "nimble/hci_transport.h"
+#include "nimble/ble_hci_trans.h"
#include "ble_hs_priv.h"
static void
-host_hci_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
+ble_hs_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
{
int8_t rssi;
uint8_t advlen;
@@ -158,7 +158,7 @@ host_hci_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
* @param len
*/
static void
-host_hci_dbg_disconn_comp_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_disconn_comp_disp(uint8_t *evdata, uint8_t len)
{
uint8_t status;
uint8_t reason;
@@ -183,7 +183,7 @@ host_hci_dbg_disconn_comp_disp(uint8_t *evdata, uint8_t len)
* @param len
*/
static void
-host_hci_dbg_encrypt_chg_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_encrypt_chg_disp(uint8_t *evdata, uint8_t len)
{
uint8_t status;
uint8_t enabled;
@@ -209,7 +209,7 @@ host_hci_dbg_encrypt_chg_disp(uint8_t *evdata, uint8_t len)
* @param len
*/
static void
-host_hci_dbg_encrypt_refresh_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_encrypt_refresh_disp(uint8_t *evdata, uint8_t len)
{
uint8_t status;
uint16_t handle;
@@ -228,7 +228,7 @@ host_hci_dbg_encrypt_refresh_disp(uint8_t *evdata, uint8_t len)
* @param len
*/
static void
-host_hci_dbg_rd_rem_ver_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_rd_rem_ver_disp(uint8_t *evdata, uint8_t len)
{
BLE_HS_LOG(DEBUG, "Remote Version Info: status=%u handle=%u vers_nr=%u "
"compid=%u subver=%u\n",
@@ -243,7 +243,7 @@ host_hci_dbg_rd_rem_ver_disp(uint8_t *evdata, uint8_t len)
* @param len
*/
static void
-host_hci_dbg_num_comp_pkts_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_num_comp_pkts_disp(uint8_t *evdata, uint8_t len)
{
uint8_t handles;
uint8_t *handle_ptr;
@@ -282,7 +282,7 @@ host_hci_dbg_num_comp_pkts_disp(uint8_t *evdata, uint8_t len)
* @param len
*/
static void
-host_hci_dbg_auth_pyld_tmo_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_auth_pyld_tmo_disp(uint8_t *evdata, uint8_t len)
{
uint16_t handle;
@@ -298,7 +298,7 @@ host_hci_dbg_auth_pyld_tmo_disp(uint8_t *evdata, uint8_t len)
static void
-host_hci_dbg_cmd_comp_info_params(uint8_t status, uint8_t ocf, uint8_t *evdata)
+ble_hs_dbg_cmd_comp_info_params(uint8_t status, uint8_t ocf, uint8_t *evdata)
{
int i;
uint8_t *dptr;
@@ -339,7 +339,7 @@ host_hci_dbg_cmd_comp_info_params(uint8_t status, uint8_t ocf, uint8_t *evdata)
}
static void
-host_hci_dbg_cmd_complete_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_cmd_complete_disp(uint8_t *evdata, uint8_t len)
{
uint8_t cmd_pkts;
uint8_t ogf;
@@ -374,7 +374,7 @@ host_hci_dbg_cmd_complete_disp(uint8_t *evdata, uint8_t len)
/* Display parameters based on command. */
switch (ogf) {
case BLE_HCI_OGF_INFO_PARAMS:
- host_hci_dbg_cmd_comp_info_params(status, ocf, evdata);
+ ble_hs_dbg_cmd_comp_info_params(status, ocf, evdata);
break;
case BLE_HCI_OGF_STATUS_PARAMS:
switch (ocf) {
@@ -438,7 +438,7 @@ done:
}
static void
-host_hci_dbg_cmd_status_disp(uint8_t *evdata, uint8_t len)
+ble_hs_dbg_cmd_status_disp(uint8_t *evdata, uint8_t len)
{
uint8_t ogf;
uint8_t ocf;
@@ -453,7 +453,7 @@ host_hci_dbg_cmd_status_disp(uint8_t *evdata, uint8_t len)
}
void
-host_hci_dbg_event_disp(uint8_t *evbuf)
+ble_hs_dbg_event_disp(uint8_t *evbuf)
{
#if LOG_LEVEL > LOG_LEVEL_DEBUG
return;
@@ -470,34 +470,40 @@ host_hci_dbg_event_disp(uint8_t *evbuf)
switch (evcode) {
case BLE_HCI_EVCODE_DISCONN_CMP:
- host_hci_dbg_disconn_comp_disp(evdata, len);
+ ble_hs_dbg_disconn_comp_disp(evdata, len);
break;
case BLE_HCI_EVCODE_ENC_KEY_REFRESH:
- host_hci_dbg_encrypt_refresh_disp(evdata, len);
+ ble_hs_dbg_encrypt_refresh_disp(evdata, len);
break;
case BLE_HCI_EVCODE_ENCRYPT_CHG:
- host_hci_dbg_encrypt_chg_disp(evdata, len);
+ ble_hs_dbg_encrypt_chg_disp(evdata, len);
break;
case BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP:
- host_hci_dbg_rd_rem_ver_disp(evdata, len);
+ ble_hs_dbg_rd_rem_ver_disp(evdata, len);
break;
case BLE_HCI_EVCODE_COMMAND_COMPLETE:
- host_hci_dbg_cmd_complete_disp(evdata, len);
+ ble_hs_dbg_cmd_complete_disp(evdata, len);
break;
case BLE_HCI_EVCODE_COMMAND_STATUS:
- host_hci_dbg_cmd_status_disp(evdata, len);
+ ble_hs_dbg_cmd_status_disp(evdata, len);
break;
case BLE_HCI_EVCODE_NUM_COMP_PKTS:
- host_hci_dbg_num_comp_pkts_disp(evdata, len);
+ ble_hs_dbg_num_comp_pkts_disp(evdata, len);
break;
case BLE_HCI_EVCODE_LE_META:
- host_hci_dbg_le_event_disp(evdata[0], len, evdata + 1);
+ ble_hs_dbg_le_event_disp(evdata[0], len, evdata + 1);
break;
case BLE_HCI_EVCODE_AUTH_PYLD_TMO:
- host_hci_dbg_auth_pyld_tmo_disp(evdata, len);
+ ble_hs_dbg_auth_pyld_tmo_disp(evdata, len);
break;
default:
BLE_HS_LOG(DEBUG, "Unknown event 0x%x len=%u\n", evcode, len);
break;
}
}
+
+void
+ble_hs_dbg_set_sync_state(uint8_t sync_state)
+{
+ ble_hs_sync_state = sync_state;
+}
diff --git a/net/nimble/host/src/host_dbg_priv.h b/net/nimble/host/src/ble_hs_dbg_priv.h
index 8d548cab..cf8d2039 100644
--- a/net/nimble/host/src/host_dbg_priv.h
+++ b/net/nimble/host/src/ble_hs_dbg_priv.h
@@ -17,9 +17,10 @@
* under the License.
*/
-#ifndef H_HOST_DBG_
-#define H_HOST_DBG_
+#ifndef H_BLE_HS_DBG_PRIV_
+#define H_BLE_HS_DBG_PRIV_
-void host_hci_dbg_event_disp(uint8_t *evbuf);
+void ble_hs_dbg_event_disp(uint8_t *evbuf);
+void ble_hs_dbg_set_sync_state(uint8_t sync_state);
#endif /* H_HOST_DBG_ */
diff --git a/net/nimble/host/src/ble_hs_hci.c b/net/nimble/host/src/ble_hs_hci.c
new file mode 100644
index 00000000..433c2e09
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_hci.c
@@ -0,0 +1,518 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "os/os.h"
+#include "nimble/ble_hci_trans.h"
+#include "ble_hs_priv.h"
+#include "ble_hs_dbg_priv.h"
+
+#define BLE_HCI_CMD_TIMEOUT (OS_TICKS_PER_SEC)
+
+static struct os_mutex ble_hs_hci_mutex;
+static struct os_sem ble_hs_hci_sem;
+
+static uint8_t *ble_hs_hci_ack;
+static uint16_t ble_hs_hci_buf_sz;
+static uint8_t ble_hs_hci_max_pkts;
+
+#if PHONY_HCI_ACKS
+static ble_hs_hci_phony_ack_fn *ble_hs_hci_phony_ack_cb;
+#endif
+
+#if PHONY_HCI_ACKS
+void
+ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb)
+{
+ ble_hs_hci_phony_ack_cb = cb;
+}
+#endif
+
+static void
+ble_hs_hci_lock(void)
+{
+ int rc;
+
+ rc = os_mutex_pend(&ble_hs_hci_mutex, 0xffffffff);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
+}
+
+static void
+ble_hs_hci_unlock(void)
+{
+ int rc;
+
+ rc = os_mutex_release(&ble_hs_hci_mutex);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
+}
+
+int
+ble_hs_hci_set_buf_sz(uint16_t pktlen, uint8_t max_pkts)
+{
+ if (pktlen == 0 || max_pkts == 0) {
+ return BLE_HS_EINVAL;
+ }
+
+ ble_hs_hci_buf_sz = pktlen;
+ ble_hs_hci_max_pkts = max_pkts;
+
+ return 0;
+}
+
+static int
+ble_hs_hci_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len,
+ struct ble_hs_hci_ack *out_ack)
+{
+ uint16_t opcode;
+ uint8_t *params;
+ uint8_t params_len;
+ uint8_t num_pkts;
+
+ if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ num_pkts = data[2];
+ opcode = le16toh(data + 3);
+ params = data + 5;
+
+ /* XXX: Process num_pkts field. */
+ (void)num_pkts;
+
+ out_ack->bha_opcode = opcode;
+
+ params_len = len - BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN;
+ if (params_len > 0) {
+ out_ack->bha_status = BLE_HS_HCI_ERR(params[0]);
+ } else if (opcode == BLE_HCI_OPCODE_NOP) {
+ out_ack->bha_status = 0;
+ } else {
+ out_ack->bha_status = BLE_HS_ECONTROLLER;
+ }
+
+ /* Don't include the status byte in the parameters blob. */
+ if (params_len > 1) {
+ out_ack->bha_params = params + 1;
+ out_ack->bha_params_len = params_len - 1;
+ } else {
+ out_ack->bha_params = NULL;
+ out_ack->bha_params_len = 0;
+ }
+
+ return 0;
+}
+
+static int
+ble_hs_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
+ struct ble_hs_hci_ack *out_ack)
+{
+ uint16_t opcode;
+ uint8_t num_pkts;
+ uint8_t status;
+
+ if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ status = data[2];
+ num_pkts = data[3];
+ opcode = le16toh(data + 4);
+
+ /* XXX: Process num_pkts field. */
+ (void)num_pkts;
+
+ out_ack->bha_opcode = opcode;
+ out_ack->bha_params = NULL;
+ out_ack->bha_params_len = 0;
+ out_ack->bha_status = BLE_HS_HCI_ERR(status);
+
+ return 0;
+}
+
+static int
+ble_hs_hci_process_ack(uint16_t expected_opcode,
+ uint8_t *params_buf, uint8_t params_buf_len,
+ struct ble_hs_hci_ack *out_ack)
+{
+ uint8_t event_code;
+ uint8_t param_len;
+ uint8_t event_len;
+ int rc;
+
+ BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
+
+ /* Count events received */
+ STATS_INC(ble_hs_stats, hci_event);
+
+ /* Display to console */
+ ble_hs_dbg_event_disp(ble_hs_hci_ack);
+
+ event_code = ble_hs_hci_ack[0];
+ param_len = ble_hs_hci_ack[1];
+ event_len = param_len + 2;
+
+ /* Clear ack fields up front to silence spurious gcc warnings. */
+ memset(out_ack, 0, sizeof *out_ack);
+
+ switch (event_code) {
+ case BLE_HCI_EVCODE_COMMAND_COMPLETE:
+ rc = ble_hs_hci_rx_cmd_complete(event_code, ble_hs_hci_ack,
+ event_len, out_ack);
+ break;
+
+ case BLE_HCI_EVCODE_COMMAND_STATUS:
+ rc = ble_hs_hci_rx_cmd_status(event_code, ble_hs_hci_ack,
+ event_len, out_ack);
+ break;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ rc = BLE_HS_EUNKNOWN;
+ break;
+ }
+
+ if (rc == 0) {
+ if (params_buf == NULL) {
+ out_ack->bha_params_len = 0;
+ } else {
+ if (out_ack->bha_params_len > params_buf_len) {
+ out_ack->bha_params_len = params_buf_len;
+ rc = BLE_HS_ECONTROLLER;
+ }
+ memcpy(params_buf, out_ack->bha_params, out_ack->bha_params_len);
+ }
+ out_ack->bha_params = params_buf;
+
+ if (out_ack->bha_opcode != expected_opcode) {
+ rc = BLE_HS_ECONTROLLER;
+ }
+ }
+
+ if (rc != 0) {
+ STATS_INC(ble_hs_stats, hci_invalid_ack);
+ }
+
+ return rc;
+}
+
+static int
+ble_hs_hci_wait_for_ack(void)
+{
+ int rc;
+
+#if PHONY_HCI_ACKS
+ if (ble_hs_hci_phony_ack_cb == NULL) {
+ rc = BLE_HS_ETIMEOUT_HCI;
+ } else {
+ ble_hs_hci_ack =
+ ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
+ rc = ble_hs_hci_phony_ack_cb(ble_hs_hci_ack, 260);
+ }
+#else
+ rc = os_sem_pend(&ble_hs_hci_sem, BLE_HCI_CMD_TIMEOUT);
+ switch (rc) {
+ case 0:
+ BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
+ break;
+ case OS_TIMEOUT:
+ rc = BLE_HS_ETIMEOUT_HCI;
+ STATS_INC(ble_hs_stats, hci_timeout);
+ break;
+ default:
+ rc = BLE_HS_EOS;
+ break;
+ }
+#endif
+
+ return rc;
+}
+
+int
+ble_hs_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
+ uint8_t *out_evt_buf_len)
+{
+ struct ble_hs_hci_ack ack;
+ uint16_t opcode;
+ int rc;
+
+ opcode = le16toh(cmd);
+
+ BLE_HS_DBG_ASSERT(ble_hs_hci_ack == NULL);
+ ble_hs_hci_lock();
+
+ rc = ble_hs_hci_cmd_send_buf(cmd);
+ if (rc != 0) {
+ goto done;
+ }
+
+ rc = ble_hs_hci_wait_for_ack();
+ if (rc != 0) {
+ ble_hs_sched_reset(rc);
+ goto done;
+ }
+
+ rc = ble_hs_hci_process_ack(opcode, evt_buf, evt_buf_len, &ack);
+ if (rc != 0) {
+ ble_hs_sched_reset(rc);
+ goto done;
+ }
+
+ if (out_evt_buf_len != NULL) {
+ *out_evt_buf_len = ack.bha_params_len;
+ }
+
+ rc = ack.bha_status;
+
+done:
+ if (ble_hs_hci_ack != NULL) {
+ ble_hci_trans_buf_free(ble_hs_hci_ack);
+ ble_hs_hci_ack = NULL;
+ }
+
+ ble_hs_hci_unlock();
+ return rc;
+}
+
+int
+ble_hs_hci_cmd_tx_empty_ack(void *cmd)
+{
+ int rc;
+
+ rc = ble_hs_hci_cmd_tx(cmd, NULL, 0, NULL);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+void
+ble_hs_hci_rx_ack(uint8_t *ack_ev)
+{
+ if (ble_hs_hci_sem.sem_tokens != 0) {
+ /* This ack is unexpected; ignore it. */
+ ble_hci_trans_buf_free(ack_ev);
+ return;
+ }
+ BLE_HS_DBG_ASSERT(ble_hs_hci_ack == NULL);
+
+ /* Unblock the application now that the HCI command buffer is populated
+ * with the acknowledgement.
+ */
+ ble_hs_hci_ack = ack_ev;
+ os_sem_release(&ble_hs_hci_sem);
+}
+
+int
+ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg)
+{
+ int enqueue;
+
+ BLE_HS_DBG_ASSERT(hci_ev != NULL);
+
+ switch (hci_ev[0]) {
+ case BLE_HCI_EVCODE_COMMAND_COMPLETE:
+ case BLE_HCI_EVCODE_COMMAND_STATUS:
+ if (hci_ev[3] == 0 && hci_ev[4] == 0) {
+ enqueue = 1;
+ } else {
+ ble_hs_hci_rx_ack(hci_ev);
+ enqueue = 0;
+ }
+ break;
+
+ default:
+ enqueue = 1;
+ break;
+ }
+
+ if (enqueue) {
+ ble_hs_enqueue_hci_event(hci_ev);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Splits an appropriately-sized fragment from the front of an outgoing ACL
+ * data packet, if necessary. If the packet size is within the controller's
+ * buffer size requirements, no splitting is performed. The fragment data is
+ * removed from the data packet mbuf.
+ *
+ * @param om The ACL data packet. If this constitutes a
+ * single fragment, it gets set to NULL on
+ * success.
+ * @param out_frag On success, this points to the fragment to
+ * send. If the entire packet can fit within
+ * a single fragment, this will point to the
+ * ACL data packet itself ('om').
+ *
+ * @return 0 on success;
+ * BLE host core return code on error.
+ */
+static int
+ble_hs_hci_split_frag(struct os_mbuf **om, struct os_mbuf **out_frag)
+{
+ struct os_mbuf *frag;
+ int rc;
+
+ /* Assume failure. */
+ *out_frag = NULL;
+
+ if (OS_MBUF_PKTLEN(*om) <= ble_hs_hci_buf_sz) {
+ /* Final fragment. */
+ *out_frag = *om;
+ *om = NULL;
+ return 0;
+ }
+
+ frag = ble_hs_mbuf_acm_pkt();
+ if (frag == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ /* Move data from the front of the packet into the fragment mbuf. */
+ rc = os_mbuf_appendfrom(frag, *om, 0, ble_hs_hci_buf_sz);
+ if (rc != 0) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+ os_mbuf_adj(*om, ble_hs_hci_buf_sz);
+
+ /* More fragments to follow. */
+ *out_frag = frag;
+ return 0;
+
+err:
+ os_mbuf_free_chain(frag);
+ return rc;
+}
+
+static struct os_mbuf *
+ble_hs_hci_acl_hdr_prepend(struct os_mbuf *om, uint16_t handle,
+ uint8_t pb_flag)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om2;
+
+ hci_hdr.hdh_handle_pb_bc =
+ ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0);
+ htole16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
+
+ om2 = os_mbuf_prepend(om, sizeof hci_hdr);
+ if (om2 == NULL) {
+ return NULL;
+ }
+
+ om = om2;
+ om = os_mbuf_pullup(om, sizeof hci_hdr);
+ if (om == NULL) {
+ return NULL;
+ }
+
+ memcpy(om->om_data, &hci_hdr, sizeof hci_hdr);
+
+ BLE_HS_LOG(DEBUG, "host tx hci data; handle=%d length=%d\n", handle,
+ le16toh(&hci_hdr.hdh_len));
+
+ return om;
+}
+
+/**
+ * Transmits an HCI ACL data packet. This function consumes the supplied mbuf,
+ * regardless of the outcome.
+ *
+ * XXX: Ensure the controller has sufficient buffer capacity for the outgoing
+ * fragments.
+ */
+int
+ble_hs_hci_acl_tx(struct ble_hs_conn *connection, struct os_mbuf *txom)
+{
+ struct os_mbuf *frag;
+ uint8_t pb;
+ int rc;
+
+ /* The first fragment uses the first-non-flush packet boundary value.
+ * After sending the first fragment, pb gets set appropriately for all
+ * subsequent fragments in this packet.
+ */
+ pb = BLE_HCI_PB_FIRST_NON_FLUSH;
+
+ /* Send fragments until the entire packet has been sent. */
+ while (txom != NULL) {
+ rc = ble_hs_hci_split_frag(&txom, &frag);
+ if (rc != 0) {
+ goto err;
+ }
+
+ frag = ble_hs_hci_acl_hdr_prepend(frag, connection->bhc_handle, pb);
+ if (frag == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+ pb = BLE_HCI_PB_MIDDLE;
+
+ BLE_HS_LOG(DEBUG, "ble_hs_hci_acl_tx(): ");
+ ble_hs_log_mbuf(frag);
+ BLE_HS_LOG(DEBUG, "\n");
+
+ /* XXX: Try to pullup the entire fragment. The controller currently
+ * requires the entire fragment to fit in a single buffer. When this
+ * restriction is removed from the controller, this operation can be
+ * removed.
+ */
+ frag = os_mbuf_pullup(frag, OS_MBUF_PKTLEN(frag));
+ if (frag == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ rc = ble_hs_tx_data(frag);
+ if (rc != 0) {
+ goto err;
+ }
+
+ connection->bhc_outstanding_pkts++;
+ }
+
+ return 0;
+
+err:
+ BLE_HS_DBG_ASSERT(rc != 0);
+
+ os_mbuf_free_chain(txom);
+ return rc;
+}
+
+void
+ble_hs_hci_init(void)
+{
+ int rc;
+
+ rc = os_sem_init(&ble_hs_hci_sem, 0);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+
+ rc = os_mutex_init(&ble_hs_hci_mutex);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+}
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/ble_hs_hci_cmd.c
index baebed3e..82b442dd 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/ble_hs_hci_cmd.c
@@ -24,26 +24,16 @@
#include "os/os.h"
#include "console/console.h"
#include "nimble/hci_common.h"
-#include "nimble/hci_transport.h"
-#include "host/host_hci.h"
-#include "host_dbg_priv.h"
+#include "nimble/ble_hci_trans.h"
+#include "ble_hs_dbg_priv.h"
#include "ble_hs_priv.h"
-#ifdef PHONY_TRANSPORT
-#include "host/ble_hs_test.h"
-#endif
-
-uint8_t host_hci_cmd_buf[HCI_CMD_BUF_SIZE];
static int
-host_hci_cmd_transport(uint8_t *cmdbuf)
+ble_hs_hci_cmd_transport(uint8_t *cmdbuf)
{
-#ifdef PHONY_TRANSPORT
- ble_hs_test_hci_txed(cmdbuf);
- return 0;
-#else
int rc;
- rc = ble_hci_transport_host_cmd_send(cmdbuf);
+ rc = ble_hci_trans_hs_cmd_tx(cmdbuf);
switch (rc) {
case 0:
return 0;
@@ -54,11 +44,10 @@ host_hci_cmd_transport(uint8_t *cmdbuf)
default:
return BLE_HS_EUNKNOWN;
}
-#endif
}
void
-host_hci_write_hdr(uint8_t ogf, uint8_t ocf, uint8_t len, void *buf)
+ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint8_t ocf, uint8_t len, void *buf)
{
uint16_t opcode;
uint8_t *u8ptr;
@@ -71,44 +60,68 @@ host_hci_write_hdr(uint8_t ogf, uint8_t ocf, uint8_t len, void *buf)
}
int
-host_hci_cmd_send(uint8_t ogf, uint8_t ocf, uint8_t len, void *cmddata)
+ble_hs_hci_cmd_send(uint8_t ogf, uint8_t ocf, uint8_t len, const void *cmddata)
{
+ uint8_t *buf;
int rc;
- htole16(host_hci_cmd_buf, ogf << 10 | ocf);
- host_hci_cmd_buf[2] = len;
+ buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ BLE_HS_DBG_ASSERT(buf != NULL);
+
+ htole16(buf, ogf << 10 | ocf);
+ buf[2] = len;
if (len != 0) {
- memcpy(host_hci_cmd_buf + BLE_HCI_CMD_HDR_LEN, cmddata, len);
+ memcpy(buf + BLE_HCI_CMD_HDR_LEN, cmddata, len);
}
- rc = host_hci_cmd_transport(host_hci_cmd_buf);
- BLE_HS_LOG(DEBUG, "host_hci_cmd_send: ogf=0x%02x ocf=0x%02x len=%d "
- "rc=%d\n", ogf, ocf, len, rc);
- ble_hs_misc_log_flat_buf(host_hci_cmd_buf, len + BLE_HCI_CMD_HDR_LEN);
+ BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send: ogf=0x%02x ocf=0x%02x len=%d\n",
+ ogf, ocf, len);
+ ble_hs_log_flat_buf(buf, len + BLE_HCI_CMD_HDR_LEN);
BLE_HS_LOG(DEBUG, "\n");
+ rc = ble_hs_hci_cmd_transport(buf);
if (rc == 0) {
STATS_INC(ble_hs_stats, hci_cmd);
+ } else {
+ BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send failure; rc=%d\n", rc);
}
return rc;
}
int
-host_hci_cmd_send_buf(void *buf)
+ble_hs_hci_cmd_send_buf(void *buf)
{
uint16_t opcode;
uint8_t *u8ptr;
uint8_t len;
int rc;
+ switch (ble_hs_sync_state) {
+ case BLE_HS_SYNC_STATE_BAD:
+ return BLE_HS_ENOTSYNCED;
+
+ case BLE_HS_SYNC_STATE_BRINGUP:
+ if (!ble_hs_is_parent_task()) {
+ return BLE_HS_ENOTSYNCED;
+ }
+ break;
+
+ case BLE_HS_SYNC_STATE_GOOD:
+ break;
+
+ default:
+ BLE_HS_DBG_ASSERT(0);
+ return BLE_HS_EUNKNOWN;
+ }
+
u8ptr = buf;
opcode = le16toh(u8ptr + 0);
len = u8ptr[2];
- rc = host_hci_cmd_send(BLE_HCI_OGF(opcode), BLE_HCI_OCF(opcode), len,
- u8ptr + BLE_HCI_CMD_HDR_LEN);
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF(opcode), BLE_HCI_OCF(opcode), len,
+ u8ptr + BLE_HCI_CMD_HDR_LEN);
return rc;
}
@@ -123,16 +136,31 @@ host_hci_cmd_send_buf(void *buf)
* @return int
*/
static int
-host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
+ble_hs_hci_cmd_le_send(uint16_t ocf, uint8_t len, void *cmddata)
{
int rc;
- rc = host_hci_cmd_send(BLE_HCI_OGF_LE, ocf, len, cmddata);
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF_LE, ocf, len, cmddata);
return rc;
}
+/**
+ * Read BD_ADDR
+ *
+ * OGF = 0x04 (Informational parameters)
+ * OCF = 0x0009
+ */
+void
+ble_hs_hci_cmd_build_read_bd_addr(uint8_t *dst, int dst_len)
+{
+ BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS,
+ BLE_HCI_OCF_IP_RD_BD_ADDR,
+ 0, dst);
+}
+
static int
-host_hci_cmd_body_le_whitelist_chg(uint8_t *addr, uint8_t addr_type,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_whitelist_chg(const uint8_t *addr, uint8_t addr_type,
+ uint8_t *dst)
{
if (addr_type > BLE_ADDR_TYPE_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -145,7 +173,8 @@ host_hci_cmd_body_le_whitelist_chg(uint8_t *addr, uint8_t addr_type,
}
static int
-host_hci_cmd_body_le_set_adv_params(struct hci_adv_params *adv, uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_adv_params(const struct hci_adv_params *adv,
+ uint8_t *dst)
{
uint16_t itvl;
@@ -192,19 +221,19 @@ host_hci_cmd_body_le_set_adv_params(struct hci_adv_params *adv, uint8_t *dst)
}
int
-host_hci_cmd_build_le_set_adv_params(struct hci_adv_params *adv, uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_PARAMS,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_PARAMS,
BLE_HCI_SET_ADV_PARAM_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_set_adv_params(adv, dst);
+ rc = ble_hs_hci_cmd_body_le_set_adv_params(adv, dst);
if (rc != 0) {
return rc;
}
@@ -225,7 +254,8 @@ host_hci_cmd_build_le_set_adv_params(struct hci_adv_params *adv, uint8_t *dst,
* @return int
*/
static int
-host_hci_cmd_body_le_set_adv_data(uint8_t *data, uint8_t len, uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_adv_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst)
{
/* Check for valid parameters */
if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) {
@@ -252,19 +282,19 @@ host_hci_cmd_body_le_set_adv_data(uint8_t *data, uint8_t len, uint8_t *dst)
* @return int
*/
int
-host_hci_cmd_build_le_set_adv_data(uint8_t *data, uint8_t len, uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_DATA_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA,
BLE_HCI_SET_ADV_DATA_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_set_adv_data(data, len, dst);
+ rc = ble_hs_hci_cmd_body_le_set_adv_data(data, len, dst);
if (rc != 0) {
return rc;
}
@@ -273,8 +303,8 @@ host_hci_cmd_build_le_set_adv_data(uint8_t *data, uint8_t len, uint8_t *dst,
}
static int
-host_hci_cmd_body_le_set_scan_rsp_data(uint8_t *data, uint8_t len,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst)
{
/* Check for valid parameters */
if (((data == NULL) && (len != 0)) ||
@@ -290,19 +320,19 @@ host_hci_cmd_body_le_set_scan_rsp_data(uint8_t *data, uint8_t len,
}
int
-host_hci_cmd_build_le_set_scan_rsp_data(uint8_t *data, uint8_t len,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_RSP_DATA_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA,
BLE_HCI_SET_SCAN_RSP_DATA_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_set_scan_rsp_data(data, len, dst);
+ rc = ble_hs_hci_cmd_body_le_set_scan_rsp_data(data, len, dst);
if (rc != 0) {
return rc;
}
@@ -311,70 +341,70 @@ host_hci_cmd_build_le_set_scan_rsp_data(uint8_t *data, uint8_t len,
}
static void
-host_hci_cmd_body_set_event_mask(uint64_t event_mask, uint8_t *dst)
+ble_hs_hci_cmd_body_set_event_mask(uint64_t event_mask, uint8_t *dst)
{
htole64(dst, event_mask);
}
void
-host_hci_cmd_build_set_event_mask(uint64_t event_mask,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_EVENT_MASK_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK,
BLE_HCI_SET_EVENT_MASK_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_set_event_mask(event_mask, dst);
+ ble_hs_hci_cmd_body_set_event_mask(event_mask, dst);
}
void
-host_hci_cmd_build_set_event_mask2(uint64_t event_mask,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_EVENT_MASK_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_SET_EVENT_MASK2,
BLE_HCI_SET_EVENT_MASK_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_set_event_mask(event_mask, dst);
+ ble_hs_hci_cmd_body_set_event_mask(event_mask, dst);
}
static void
-host_hci_cmd_body_disconnect(uint16_t handle, uint8_t reason, uint8_t *dst)
+ble_hs_hci_cmd_body_disconnect(uint16_t handle, uint8_t reason, uint8_t *dst)
{
htole16(dst + 0, handle);
dst[2] = reason;
}
void
-host_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_DISCONNECT_CMD_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_DISCONNECT_CMD,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_DISCONNECT_CMD,
BLE_HCI_DISCONNECT_CMD_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_disconnect(handle, reason, dst);
+ ble_hs_hci_cmd_body_disconnect(handle, reason, dst);
}
int
-host_hci_cmd_disconnect(uint16_t handle, uint8_t reason)
+ble_hs_hci_cmd_disconnect(uint16_t handle, uint8_t reason)
{
uint8_t cmd[BLE_HCI_DISCONNECT_CMD_LEN];
int rc;
- host_hci_cmd_body_disconnect(handle, reason, cmd);
- rc = host_hci_cmd_send(BLE_HCI_OGF_LINK_CTRL,
+ ble_hs_hci_cmd_body_disconnect(handle, reason, cmd);
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF_LINK_CTRL,
BLE_HCI_OCF_DISCONNECT_CMD,
BLE_HCI_DISCONNECT_CMD_LEN,
cmd);
@@ -382,24 +412,24 @@ host_hci_cmd_disconnect(uint16_t handle, uint8_t reason)
}
static void
-host_hci_cmd_body_le_set_event_mask(uint64_t event_mask, uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_event_mask(uint64_t event_mask, uint8_t *dst)
{
htole64(dst, event_mask);
}
void
-host_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_LE_EVENT_MASK_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_EVENT_MASK,
BLE_HCI_SET_LE_EVENT_MASK_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_set_event_mask(event_mask, dst);
+ ble_hs_hci_cmd_body_le_set_event_mask(event_mask, dst);
}
/**
@@ -411,10 +441,11 @@ host_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
* @return int
*/
void
-host_hci_cmd_build_le_read_buffer_size(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_read_buffer_size(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE, 0, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE,
+ 0, dst);
}
/**
@@ -426,11 +457,11 @@ host_hci_cmd_build_le_read_buffer_size(uint8_t *dst, int dst_len)
* @return int
*/
int
-host_hci_cmd_le_read_buffer_size(void)
+ble_hs_hci_cmd_le_read_buffer_size(void)
{
int rc;
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_RD_BUF_SIZE, 0, NULL);
+ rc = ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_RD_BUF_SIZE, 0, NULL);
return rc;
}
@@ -438,35 +469,35 @@ host_hci_cmd_le_read_buffer_size(void)
* OGF=LE, OCF=0x0003
*/
void
-host_hci_cmd_build_le_read_loc_supp_feat(uint8_t *dst, uint8_t dst_len)
+ble_hs_hci_cmd_build_le_read_loc_supp_feat(uint8_t *dst, uint8_t dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT,
0, dst);
}
static void
-host_hci_cmd_body_le_set_adv_enable(uint8_t enable, uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_adv_enable(uint8_t enable, uint8_t *dst)
{
dst[0] = enable;
}
void
-host_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
+ int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_ENABLE_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE,
BLE_HCI_SET_ADV_ENABLE_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_set_adv_enable(enable, dst);
+ ble_hs_hci_cmd_body_le_set_adv_enable(enable, dst);
}
static int
-host_hci_cmd_body_le_set_scan_params(
+ble_hs_hci_cmd_body_le_set_scan_params(
uint8_t scan_type, uint16_t scan_itvl, uint16_t scan_window,
uint8_t own_addr_type, uint8_t filter_policy, uint8_t *dst) {
@@ -505,24 +536,25 @@ host_hci_cmd_body_le_set_scan_params(
}
int
-host_hci_cmd_build_le_set_scan_params(uint8_t scan_type, uint16_t scan_itvl,
- uint16_t scan_window,
- uint8_t own_addr_type,
- uint8_t filter_policy,
- uint8_t *cmd, int cmd_len)
+ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,
+ uint16_t scan_itvl,
+ uint16_t scan_window,
+ uint8_t own_addr_type,
+ uint8_t filter_policy,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
- cmd_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN);
+ dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
- BLE_HCI_SET_SCAN_PARAM_LEN, cmd);
- cmd += BLE_HCI_CMD_HDR_LEN;
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
+ BLE_HCI_SET_SCAN_PARAM_LEN, dst);
+ dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_set_scan_params(scan_type, scan_itvl,
+ rc = ble_hs_hci_cmd_body_le_set_scan_params(scan_type, scan_itvl,
scan_window, own_addr_type,
- filter_policy, cmd);
+ filter_policy, dst);
if (rc != 0) {
return rc;
}
@@ -531,30 +563,30 @@ host_hci_cmd_build_le_set_scan_params(uint8_t scan_type, uint16_t scan_itvl,
}
static void
-host_hci_cmd_body_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
+ uint8_t *dst)
{
dst[0] = enable;
dst[1] = filter_dups;
}
void
-host_hci_cmd_build_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
- uint8_t *dst, uint8_t dst_len)
+ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
+ uint8_t *dst, uint8_t dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
BLE_HCI_SET_SCAN_ENABLE_LEN, dst);
- host_hci_cmd_body_le_set_scan_enable(enable, filter_dups,
+ ble_hs_hci_cmd_body_le_set_scan_enable(enable, filter_dups,
dst + BLE_HCI_CMD_HDR_LEN);
}
static int
-host_hci_cmd_body_le_create_connection(struct hci_create_conn *hcc,
- uint8_t *cmd)
+ble_hs_hci_cmd_body_le_create_connection(const struct hci_create_conn *hcc,
+ uint8_t *cmd)
{
/* Check scan interval and scan window */
if ((hcc->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
@@ -627,18 +659,18 @@ host_hci_cmd_body_le_create_connection(struct hci_create_conn *hcc,
}
int
-host_hci_cmd_build_le_create_connection(struct hci_create_conn *hcc,
- uint8_t *cmd, int cmd_len)
+ble_hs_hci_cmd_build_le_create_connection(const struct hci_create_conn *hcc,
+ uint8_t *cmd, int cmd_len)
{
int rc;
BLE_HS_DBG_ASSERT(
cmd_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CREATE_CONN_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN,
BLE_HCI_CREATE_CONN_LEN, cmd);
- rc = host_hci_cmd_body_le_create_connection(hcc,
+ rc = ble_hs_hci_cmd_body_le_create_connection(hcc,
cmd + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
@@ -648,27 +680,28 @@ host_hci_cmd_build_le_create_connection(struct hci_create_conn *hcc,
}
void
-host_hci_cmd_build_le_clear_whitelist(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_clear_whitelist(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_WHITE_LIST,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_WHITE_LIST,
0, dst);
}
int
-host_hci_cmd_build_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr,
+ uint8_t addr_type,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CHG_WHITE_LIST_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_WHITE_LIST,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_WHITE_LIST,
BLE_HCI_CHG_WHITE_LIST_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_whitelist_chg(addr, addr_type, dst);
+ rc = ble_hs_hci_cmd_body_le_whitelist_chg(addr, addr_type, dst);
if (rc != 0) {
return rc;
}
@@ -677,10 +710,10 @@ host_hci_cmd_build_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type,
}
void
-host_hci_cmd_build_reset(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_reset(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
0, dst);
}
@@ -690,21 +723,21 @@ host_hci_cmd_build_reset(uint8_t *dst, int dst_len)
* @return int
*/
int
-host_hci_cmd_reset(void)
+ble_hs_hci_cmd_reset(void)
{
int rc;
- rc = host_hci_cmd_send(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET, 0,
- NULL);
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
+ 0, NULL);
return rc;
}
void
-host_hci_cmd_build_read_adv_pwr(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_read_adv_pwr(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR,
- 0, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR,
+ 0, dst);
}
/**
@@ -713,35 +746,36 @@ host_hci_cmd_build_read_adv_pwr(uint8_t *dst, int dst_len)
* @return int
*/
int
-host_hci_cmd_read_adv_pwr(void)
+ble_hs_hci_cmd_read_adv_pwr(void)
{
int rc;
- rc = host_hci_cmd_send(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR, 0,
- NULL);
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR,
+ 0, NULL);
return rc;
}
void
-host_hci_cmd_build_le_create_conn_cancel(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_create_conn_cancel(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
0, dst);
}
int
-host_hci_cmd_le_create_conn_cancel(void)
+ble_hs_hci_cmd_le_create_conn_cancel(void)
{
int rc;
- rc = host_hci_cmd_send(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
+ rc = ble_hs_hci_cmd_send(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
0, NULL);
return rc;
}
static int
-host_hci_cmd_body_le_conn_update(struct hci_conn_update *hcu, uint8_t *dst)
+ble_hs_hci_cmd_body_le_conn_update(const struct hci_conn_update *hcu,
+ uint8_t *dst)
{
/* XXX: add parameter checking later */
htole16(dst + 0, hcu->handle);
@@ -756,19 +790,19 @@ host_hci_cmd_body_le_conn_update(struct hci_conn_update *hcu, uint8_t *dst)
}
int
-host_hci_cmd_build_le_conn_update(struct hci_conn_update *hcu, uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_UPDATE_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CONN_UPDATE,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CONN_UPDATE,
BLE_HCI_CONN_UPDATE_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_le_conn_update(hcu, dst);
+ rc = ble_hs_hci_cmd_body_le_conn_update(hcu, dst);
if (rc != 0) {
return rc;
}
@@ -777,17 +811,17 @@ host_hci_cmd_build_le_conn_update(struct hci_conn_update *hcu, uint8_t *dst,
}
int
-host_hci_cmd_le_conn_update(struct hci_conn_update *hcu)
+ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu)
{
uint8_t cmd[BLE_HCI_CONN_UPDATE_LEN];
int rc;
- rc = host_hci_cmd_body_le_conn_update(hcu, cmd);
+ rc = ble_hs_hci_cmd_body_le_conn_update(hcu, cmd);
if (rc != 0) {
return rc;
}
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_CONN_UPDATE,
+ rc = ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_CONN_UPDATE,
BLE_HCI_CONN_UPDATE_LEN, cmd);
if (rc != 0) {
return rc;
@@ -797,8 +831,8 @@ host_hci_cmd_le_conn_update(struct hci_conn_update *hcu)
}
static void
-host_hci_cmd_body_le_lt_key_req_reply(struct hci_lt_key_req_reply *hkr,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_lt_key_req_reply(const struct hci_lt_key_req_reply *hkr,
+ uint8_t *dst)
{
htole16(dst + 0, hkr->conn_handle);
memcpy(dst + 2, hkr->long_term_key, sizeof hkr->long_term_key);
@@ -819,36 +853,37 @@ host_hci_cmd_body_le_lt_key_req_reply(struct hci_lt_key_req_reply *hkr,
* @return int
*/
void
-host_hci_cmd_build_le_lt_key_req_reply(struct hci_lt_key_req_reply *hkr,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_lt_key_req_reply(
+ const struct hci_lt_key_req_reply *hkr, uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_LT_KEY_REQ_REPLY_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY,
BLE_HCI_LT_KEY_REQ_REPLY_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_lt_key_req_reply(hkr, dst);
+ ble_hs_hci_cmd_body_le_lt_key_req_reply(hkr, dst);
}
void
-host_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY,
- BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY,
+ BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
htole16(dst + 0, conn_handle);
}
static void
-host_hci_cmd_body_le_conn_param_reply(struct hci_conn_param_reply *hcr,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_conn_param_reply(const struct hci_conn_param_reply *hcr,
+ uint8_t *dst)
{
htole16(dst + 0, hcr->handle);
htole16(dst + 2, hcr->conn_itvl_min);
@@ -860,21 +895,21 @@ host_hci_cmd_body_le_conn_param_reply(struct hci_conn_param_reply *hcr,
}
void
-host_hci_cmd_build_le_conn_param_reply(struct hci_conn_param_reply *hcr,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_conn_param_reply(
+ const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_PARAM_REPLY_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
BLE_HCI_CONN_PARAM_REPLY_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_conn_param_reply(hcr, dst);
+ ble_hs_hci_cmd_body_le_conn_param_reply(hcr, dst);
}
int
-host_hci_cmd_le_conn_param_reply(struct hci_conn_param_reply *hcr)
+ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr)
{
uint8_t cmd[BLE_HCI_CONN_PARAM_REPLY_LEN];
int rc;
@@ -887,14 +922,14 @@ host_hci_cmd_le_conn_param_reply(struct hci_conn_param_reply *hcr)
htole16(cmd + 10, hcr->min_ce_len);
htole16(cmd + 12, hcr->max_ce_len);
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
+ rc = ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
BLE_HCI_CONN_PARAM_REPLY_LEN, cmd);
return rc;
}
static void
-host_hci_cmd_body_le_conn_param_neg_reply(struct hci_conn_param_neg_reply *hcn,
- uint8_t *dst)
+ble_hs_hci_cmd_body_le_conn_param_neg_reply(
+ const struct hci_conn_param_neg_reply *hcn, uint8_t *dst)
{
htole16(dst + 0, hcn->handle);
dst[2] = hcn->reason;
@@ -902,28 +937,29 @@ host_hci_cmd_body_le_conn_param_neg_reply(struct hci_conn_param_neg_reply *hcn,
void
-host_hci_cmd_build_le_conn_param_neg_reply(
- struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_conn_param_neg_reply(
+ const struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_PARAM_NEG_REPLY_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
BLE_HCI_CONN_PARAM_NEG_REPLY_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_conn_param_neg_reply(hcn, dst);
+ ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, dst);
}
int
-host_hci_cmd_le_conn_param_neg_reply(struct hci_conn_param_neg_reply *hcn)
+ble_hs_hci_cmd_le_conn_param_neg_reply(
+ const struct hci_conn_param_neg_reply *hcn)
{
uint8_t cmd[BLE_HCI_CONN_PARAM_NEG_REPLY_LEN];
int rc;
- host_hci_cmd_body_le_conn_param_neg_reply(hcn, cmd);
+ ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, cmd);
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
+ rc = ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
BLE_HCI_CONN_PARAM_NEG_REPLY_LEN, cmd);
return rc;
}
@@ -937,14 +973,15 @@ host_hci_cmd_le_conn_param_neg_reply(struct hci_conn_param_neg_reply *hcn)
* @return int
*/
void
-host_hci_cmd_build_le_rand(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_rand(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND, 0, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND, 0, dst);
}
static void
-host_hci_cmd_body_le_start_encrypt(struct hci_start_encrypt *cmd, uint8_t *dst)
+ble_hs_hci_cmd_body_le_start_encrypt(const struct hci_start_encrypt *cmd,
+ uint8_t *dst)
{
htole16(dst + 0, cmd->connection_handle);
htole64(dst + 2, cmd->random_number);
@@ -956,17 +993,17 @@ host_hci_cmd_body_le_start_encrypt(struct hci_start_encrypt *cmd, uint8_t *dst)
* OGF=0x08 OCF=0x0019
*/
void
-host_hci_cmd_build_le_start_encrypt(struct hci_start_encrypt *cmd,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd,
+ uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_START_ENCRYPT_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT,
BLE_HCI_LE_START_ENCRYPT_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_le_start_encrypt(cmd, dst);
+ ble_hs_hci_cmd_body_le_start_encrypt(cmd, dst);
}
/**
@@ -979,27 +1016,28 @@ host_hci_cmd_build_le_start_encrypt(struct hci_start_encrypt *cmd,
* @return int
*/
static void
-host_hci_cmd_body_read_rssi(uint16_t handle, uint8_t *dst)
+ble_hs_hci_cmd_body_read_rssi(uint16_t handle, uint8_t *dst)
{
htole16(dst, handle);
}
void
-host_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_READ_RSSI_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_STATUS_PARAMS, BLE_HCI_OCF_RD_RSSI,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_STATUS_PARAMS, BLE_HCI_OCF_RD_RSSI,
BLE_HCI_READ_RSSI_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- host_hci_cmd_body_read_rssi(handle, dst);
+ ble_hs_hci_cmd_body_read_rssi(handle, dst);
}
static int
-host_hci_cmd_body_set_data_len(uint16_t connection_handle, uint16_t tx_octets,
- uint16_t tx_time, uint8_t *dst)
+ble_hs_hci_cmd_body_set_data_len(uint16_t connection_handle,
+ uint16_t tx_octets,
+ uint16_t tx_time, uint8_t *dst)
{
if (tx_octets < BLE_HCI_SET_DATALEN_TX_OCTETS_MIN ||
@@ -1025,21 +1063,21 @@ host_hci_cmd_body_set_data_len(uint16_t connection_handle, uint16_t tx_octets,
* OGF=0x08 OCF=0x0022
*/
int
-host_hci_cmd_build_set_data_len(uint16_t connection_handle,
- uint16_t tx_octets, uint16_t tx_time,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,
+ uint16_t tx_octets, uint16_t tx_time,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_DATALEN_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DATA_LEN,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DATA_LEN,
BLE_HCI_SET_DATALEN_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
- rc = host_hci_cmd_body_set_data_len(connection_handle, tx_octets, tx_time,
- dst);
+ rc = ble_hs_hci_cmd_body_set_data_len(connection_handle, tx_octets,
+ tx_time, dst);
if (rc != 0) {
return rc;
}
@@ -1051,9 +1089,10 @@ host_hci_cmd_build_set_data_len(uint16_t connection_handle,
* IRKs are in little endian.
*/
static int
-host_hci_cmd_body_add_to_resolv_list(uint8_t addr_type, uint8_t *addr,
- uint8_t *peer_irk, uint8_t *local_irk,
- uint8_t *dst)
+ble_hs_hci_cmd_body_add_to_resolv_list(uint8_t addr_type, const uint8_t *addr,
+ const uint8_t *peer_irk,
+ const uint8_t *local_irk,
+ uint8_t *dst)
{
if (addr_type > BLE_ADDR_TYPE_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -1073,8 +1112,8 @@ host_hci_cmd_body_add_to_resolv_list(uint8_t addr_type, uint8_t *addr,
* IRKs are in little endian.
*/
int
-host_hci_cmd_build_add_to_resolv_list(
- struct hci_add_dev_to_resolving_list *padd,
+ble_hs_hci_cmd_build_add_to_resolv_list(
+ const struct hci_add_dev_to_resolving_list *padd,
uint8_t *dst,
int dst_len)
{
@@ -1083,10 +1122,10 @@ host_hci_cmd_build_add_to_resolv_list(
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_ADD_TO_RESOLV_LIST_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST,
BLE_HCI_ADD_TO_RESOLV_LIST_LEN, dst);
- rc = host_hci_cmd_body_add_to_resolv_list(
+ rc = ble_hs_hci_cmd_body_add_to_resolv_list(
padd->addr_type, padd->addr, padd->peer_irk, padd->local_irk,
dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
@@ -1097,8 +1136,9 @@ host_hci_cmd_build_add_to_resolv_list(
}
static int
-host_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type, uint8_t *addr,
- uint8_t *dst)
+ble_hs_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type,
+ const uint8_t *addr,
+ uint8_t *dst)
{
if (addr_type > BLE_ADDR_TYPE_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -1111,18 +1151,19 @@ host_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type, uint8_t *addr,
int
-host_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type, uint8_t *addr,
- uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type,
+ const uint8_t *addr,
+ uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_RMV_FROM_RESOLV_LIST_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RMV_RESOLV_LIST,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RMV_RESOLV_LIST,
BLE_HCI_RMV_FROM_RESOLV_LIST_LEN, dst);
- rc = host_hci_cmd_body_remove_from_resolv_list(addr_type, addr,
+ rc = ble_hs_hci_cmd_body_remove_from_resolv_list(addr_type, addr,
dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
@@ -1131,31 +1172,32 @@ host_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type, uint8_t *addr,
}
int
-host_hci_cmd_build_clear_resolv_list(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_clear_resolv_list(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST,
0, dst);
return 0;
}
int
-host_hci_cmd_build_read_resolv_list_size(uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_read_resolv_list_size(uint8_t *dst, int dst_len)
{
BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CMD_HDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE,
- 0, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE,
+ 0, dst);
return 0;
}
static int
-host_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
- uint8_t *peer_identity_addr,
- uint8_t *dst)
+ble_hs_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
+ const uint8_t *peer_identity_addr,
+ uint8_t *dst)
{
if (peer_identity_addr_type > BLE_ADDR_TYPE_RANDOM) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -1167,22 +1209,23 @@ host_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
}
int
-host_hci_cmd_build_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
- uint8_t *peer_identity_addr,
- uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
+ const uint8_t *peer_identity_addr,
+ uint8_t *dst,
+ int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_RD_PEER_RESOLV_ADDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR,
- BLE_HCI_RD_PEER_RESOLV_ADDR_LEN, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR,
+ BLE_HCI_RD_PEER_RESOLV_ADDR_LEN, dst);
- rc = host_hci_cmd_body_read_peer_resolv_addr(peer_identity_addr_type,
- peer_identity_addr,
- dst + BLE_HCI_CMD_HDR_LEN);
+ rc = ble_hs_hci_cmd_body_read_peer_resolv_addr(peer_identity_addr_type,
+ peer_identity_addr,
+ dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
}
@@ -1190,9 +1233,9 @@ host_hci_cmd_build_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
}
static int
-host_hci_cmd_body_read_lcl_resolv_addr(
+ble_hs_hci_cmd_body_read_lcl_resolv_addr(
uint8_t local_identity_addr_type,
- uint8_t *local_identity_addr,
+ const uint8_t *local_identity_addr,
uint8_t *dst)
{
if (local_identity_addr_type > BLE_ADDR_TYPE_RANDOM) {
@@ -1208,22 +1251,23 @@ host_hci_cmd_body_read_lcl_resolv_addr(
* OGF=0x08 OCF=0x002c
*/
int
-host_hci_cmd_build_read_lcl_resolv_addr(uint8_t local_identity_addr_type,
- uint8_t *local_identity_addr,
- uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_read_lcl_resolv_addr(uint8_t local_identity_addr_type,
+ const uint8_t *local_identity_addr,
+ uint8_t *dst,
+ int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_RD_LOC_RESOLV_ADDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR,
- BLE_HCI_RD_LOC_RESOLV_ADDR_LEN, dst);
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR,
+ BLE_HCI_RD_LOC_RESOLV_ADDR_LEN, dst);
- rc = host_hci_cmd_body_read_lcl_resolv_addr(local_identity_addr_type,
- local_identity_addr,
- dst + BLE_HCI_CMD_HDR_LEN);
+ rc = ble_hs_hci_cmd_body_read_lcl_resolv_addr(local_identity_addr_type,
+ local_identity_addr,
+ dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
}
@@ -1231,7 +1275,7 @@ host_hci_cmd_build_read_lcl_resolv_addr(uint8_t local_identity_addr_type,
}
static int
-host_hci_cmd_body_set_addr_res_en(uint8_t enable, uint8_t *dst)
+ble_hs_hci_cmd_body_set_addr_res_en(uint8_t enable, uint8_t *dst)
{
if (enable > 1) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -1245,17 +1289,18 @@ host_hci_cmd_body_set_addr_res_en(uint8_t enable, uint8_t *dst)
* OGF=0x08 OCF=0x002d
*/
int
-host_hci_cmd_build_set_addr_res_en(uint8_t enable, uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_set_addr_res_en(uint8_t enable, uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADDR_RESOL_ENA_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN,
BLE_HCI_SET_ADDR_RESOL_ENA_LEN, dst);
- rc = host_hci_cmd_body_set_addr_res_en(enable, dst + BLE_HCI_CMD_HDR_LEN);
+ rc = ble_hs_hci_cmd_body_set_addr_res_en(enable,
+ dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
}
@@ -1263,7 +1308,8 @@ host_hci_cmd_build_set_addr_res_en(uint8_t enable, uint8_t *dst, int dst_len)
}
static int
-host_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout, uint8_t *dst)
+ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout,
+ uint8_t *dst)
{
if (timeout == 0 || timeout > 0xA1B8) {
return BLE_ERR_INV_HCI_CMD_PARMS;
@@ -1277,18 +1323,18 @@ host_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout, uint8_t *dst)
* OGF=0x08 OCF=0x002e
*/
int
-host_hci_cmd_build_set_resolv_priv_addr_timeout(uint16_t timeout, uint8_t *dst,
- int dst_len)
+ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
+ uint16_t timeout, uint8_t *dst, int dst_len)
{
int rc;
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RPA_TMO,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RPA_TMO,
BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN, dst);
- rc = host_hci_cmd_body_set_resolv_priv_addr_timeout(
+ rc = ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(
timeout, dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
@@ -1297,14 +1343,16 @@ host_hci_cmd_build_set_resolv_priv_addr_timeout(uint16_t timeout, uint8_t *dst,
}
static int
-host_hci_cmd_body_set_random_addr(struct hci_rand_addr *paddr, uint8_t *dst)
+ble_hs_hci_cmd_body_set_random_addr(const struct hci_rand_addr *paddr,
+ uint8_t *dst)
{
memcpy(dst, paddr->addr, BLE_DEV_ADDR_LEN);
return 0;
}
int
-host_hci_cmd_build_set_random_addr(uint8_t *addr, uint8_t *dst, int dst_len)
+ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
+ uint8_t *dst, int dst_len)
{
struct hci_rand_addr r_addr;
int rc;
@@ -1314,10 +1362,11 @@ host_hci_cmd_build_set_random_addr(uint8_t *addr, uint8_t *dst, int dst_len)
BLE_HS_DBG_ASSERT(
dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RAND_ADDR_LEN);
- host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RAND_ADDR,
+ ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RAND_ADDR,
BLE_HCI_SET_RAND_ADDR_LEN, dst);
- rc = host_hci_cmd_body_set_random_addr(&r_addr, dst + BLE_HCI_CMD_HDR_LEN);
+ rc = ble_hs_hci_cmd_body_set_random_addr(&r_addr,
+ dst + BLE_HCI_CMD_HDR_LEN);
if (rc != 0) {
return rc;
}
diff --git a/net/nimble/host/src/host_hci.c b/net/nimble/host/src/ble_hs_hci_evt.c
index 4452dcc3..3d382dc1 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/ble_hs_hci_evt.c
@@ -23,30 +23,29 @@
#include "os/os.h"
#include "console/console.h"
#include "nimble/hci_common.h"
-#include "nimble/hci_transport.h"
-#include "host/host_hci.h"
+#include "nimble/ble_hci_trans.h"
+#include "host/ble_gap.h"
#include "ble_hs_priv.h"
-#include "host_dbg_priv.h"
+#include "ble_hs_dbg_priv.h"
_Static_assert(sizeof (struct hci_data_hdr) == BLE_HCI_DATA_HDR_SZ,
"struct hci_data_hdr must be 4 bytes");
-typedef int host_hci_event_fn(uint8_t event_code, uint8_t *data, int len);
-static host_hci_event_fn host_hci_rx_disconn_complete;
-static host_hci_event_fn host_hci_rx_encrypt_change;
-static host_hci_event_fn host_hci_rx_num_completed_pkts;
-static host_hci_event_fn host_hci_rx_enc_key_refresh;
-static host_hci_event_fn host_hci_rx_le_meta;
-
-typedef int host_hci_le_event_fn(uint8_t subevent, uint8_t *data, int len);
-static host_hci_le_event_fn host_hci_rx_le_conn_complete;
-static host_hci_le_event_fn host_hci_rx_le_adv_rpt;
-static host_hci_le_event_fn host_hci_rx_le_conn_upd_complete;
-static host_hci_le_event_fn host_hci_rx_le_lt_key_req;
-static host_hci_le_event_fn host_hci_rx_le_conn_parm_req;
-
-static uint16_t host_hci_buffer_sz;
-static uint8_t host_hci_max_pkts;
+typedef int ble_hs_hci_evt_fn(uint8_t event_code, uint8_t *data, int len);
+static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_hw_error;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_num_completed_pkts;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_enc_key_refresh;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_le_meta;
+
+typedef int ble_hs_hci_evt_le_fn(uint8_t subevent, uint8_t *data, int len);
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_complete;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_rpt;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_upd_complete;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_lt_key_req;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
/* Statistics */
struct host_hci_stats
@@ -57,71 +56,56 @@ struct host_hci_stats
uint32_t unknown_events_rxd;
};
-#define HOST_HCI_TIMEOUT 50 /* Milliseconds. */
+#define BLE_HS_HCI_EVT_TIMEOUT 50 /* Milliseconds. */
/** Dispatch table for incoming HCI events. Sorted by event code field. */
-struct host_hci_event_dispatch_entry {
- uint8_t hed_event_code;
- host_hci_event_fn *hed_fn;
+struct ble_hs_hci_evt_dispatch_entry {
+ uint8_t event_code;
+ ble_hs_hci_evt_fn *cb;
};
-static const struct host_hci_event_dispatch_entry host_hci_event_dispatch[] = {
- { BLE_HCI_EVCODE_DISCONN_CMP, host_hci_rx_disconn_complete },
- { BLE_HCI_EVCODE_ENCRYPT_CHG, host_hci_rx_encrypt_change },
- { BLE_HCI_EVCODE_NUM_COMP_PKTS, host_hci_rx_num_completed_pkts },
- { BLE_HCI_EVCODE_ENC_KEY_REFRESH, host_hci_rx_enc_key_refresh },
- { BLE_HCI_EVCODE_LE_META, host_hci_rx_le_meta },
+static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = {
+ { BLE_HCI_EVCODE_DISCONN_CMP, ble_hs_hci_evt_disconn_complete },
+ { BLE_HCI_EVCODE_ENCRYPT_CHG, ble_hs_hci_evt_encrypt_change },
+ { BLE_HCI_EVCODE_HW_ERROR, ble_hs_hci_evt_hw_error },
+ { BLE_HCI_EVCODE_NUM_COMP_PKTS, ble_hs_hci_evt_num_completed_pkts },
+ { BLE_HCI_EVCODE_ENC_KEY_REFRESH, ble_hs_hci_evt_enc_key_refresh },
+ { BLE_HCI_EVCODE_LE_META, ble_hs_hci_evt_le_meta },
};
-#define HOST_HCI_EVENT_DISPATCH_SZ \
- (sizeof host_hci_event_dispatch / sizeof host_hci_event_dispatch[0])
+#define BLE_HS_HCI_EVT_DISPATCH_SZ \
+ (sizeof ble_hs_hci_evt_dispatch / sizeof ble_hs_hci_evt_dispatch[0])
/** Dispatch table for incoming LE meta events. Sorted by subevent field. */
-struct host_hci_le_event_dispatch_entry {
- uint8_t hmd_subevent;
- host_hci_le_event_fn *hmd_fn;
+struct ble_hs_hci_evt_le_dispatch_entry {
+ uint8_t subevent;
+ ble_hs_hci_evt_le_fn *cb;
};
-static const struct host_hci_le_event_dispatch_entry
- host_hci_le_event_dispatch[] = {
- { BLE_HCI_LE_SUBEV_CONN_COMPLETE, host_hci_rx_le_conn_complete },
- { BLE_HCI_LE_SUBEV_ADV_RPT, host_hci_rx_le_adv_rpt },
- { BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE, host_hci_rx_le_conn_upd_complete },
- { BLE_HCI_LE_SUBEV_LT_KEY_REQ, host_hci_rx_le_lt_key_req },
- { BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ, host_hci_rx_le_conn_parm_req },
- { BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE, host_hci_rx_le_conn_complete },
+static const struct ble_hs_hci_evt_le_dispatch_entry
+ ble_hs_hci_evt_le_dispatch[] = {
+ { BLE_HCI_LE_SUBEV_CONN_COMPLETE, ble_hs_hci_evt_le_conn_complete },
+ { BLE_HCI_LE_SUBEV_ADV_RPT, ble_hs_hci_evt_le_adv_rpt },
+ { BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE,
+ ble_hs_hci_evt_le_conn_upd_complete },
+ { BLE_HCI_LE_SUBEV_LT_KEY_REQ, ble_hs_hci_evt_le_lt_key_req },
+ { BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ, ble_hs_hci_evt_le_conn_parm_req },
+ { BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE, ble_hs_hci_evt_le_conn_complete },
+ { BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT, ble_hs_hci_evt_le_dir_adv_rpt },
};
-#define HOST_HCI_LE_EVENT_DISPATCH_SZ \
- (sizeof host_hci_le_event_dispatch / sizeof host_hci_le_event_dispatch[0])
-
-uint16_t
-host_hci_opcode_join(uint8_t ogf, uint16_t ocf)
-{
- return (ogf << 10) | ocf;
-}
-
-uint16_t
-host_hci_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
-{
- BLE_HS_DBG_ASSERT(handle <= 0x0fff);
- BLE_HS_DBG_ASSERT(pb <= 0x03);
- BLE_HS_DBG_ASSERT(bc <= 0x03);
-
- return (handle << 0) |
- (pb << 12) |
- (bc << 14);
-}
+#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
+ (sizeof ble_hs_hci_evt_le_dispatch / sizeof ble_hs_hci_evt_le_dispatch[0])
-static const struct host_hci_event_dispatch_entry *
-host_hci_dispatch_entry_find(uint8_t event_code)
+static const struct ble_hs_hci_evt_dispatch_entry *
+ble_hs_hci_evt_dispatch_find(uint8_t event_code)
{
- const struct host_hci_event_dispatch_entry *entry;
+ const struct ble_hs_hci_evt_dispatch_entry *entry;
int i;
- for (i = 0; i < HOST_HCI_EVENT_DISPATCH_SZ; i++) {
- entry = host_hci_event_dispatch + i;
- if (entry->hed_event_code == event_code) {
+ for (i = 0; i < BLE_HS_HCI_EVT_DISPATCH_SZ; i++) {
+ entry = ble_hs_hci_evt_dispatch + i;
+ if (entry->event_code == event_code) {
return entry;
}
}
@@ -129,15 +113,15 @@ host_hci_dispatch_entry_find(uint8_t event_code)
return NULL;
}
-static const struct host_hci_le_event_dispatch_entry *
-host_hci_le_dispatch_entry_find(uint8_t event_code)
+static const struct ble_hs_hci_evt_le_dispatch_entry *
+ble_hs_hci_evt_le_dispatch_find(uint8_t event_code)
{
- const struct host_hci_le_event_dispatch_entry *entry;
+ const struct ble_hs_hci_evt_le_dispatch_entry *entry;
int i;
- for (i = 0; i < HOST_HCI_LE_EVENT_DISPATCH_SZ; i++) {
- entry = host_hci_le_event_dispatch + i;
- if (entry->hmd_subevent == event_code) {
+ for (i = 0; i < BLE_HS_HCI_EVT_LE_DISPATCH_SZ; i++) {
+ entry = ble_hs_hci_evt_le_dispatch + i;
+ if (entry->subevent == event_code) {
return entry;
}
}
@@ -146,7 +130,7 @@ host_hci_le_dispatch_entry_find(uint8_t event_code)
}
static int
-host_hci_rx_disconn_complete(uint8_t event_code, uint8_t *data, int len)
+ble_hs_hci_evt_disconn_complete(uint8_t event_code, uint8_t *data, int len)
{
struct hci_disconn_complete evt;
@@ -164,7 +148,7 @@ host_hci_rx_disconn_complete(uint8_t event_code, uint8_t *data, int len)
}
static int
-host_hci_rx_encrypt_change(uint8_t event_code, uint8_t *data, int len)
+ble_hs_hci_evt_encrypt_change(uint8_t event_code, uint8_t *data, int len)
{
struct hci_encrypt_change evt;
@@ -182,7 +166,22 @@ host_hci_rx_encrypt_change(uint8_t event_code, uint8_t *data, int len)
}
static int
-host_hci_rx_enc_key_refresh(uint8_t event_code, uint8_t *data, int len)
+ble_hs_hci_evt_hw_error(uint8_t event_code, uint8_t *data, int len)
+{
+ uint8_t hw_code;
+
+ if (len < BLE_HCI_EVENT_HW_ERROR_LEN) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ hw_code = data[0];
+ ble_hs_hw_error(hw_code);
+
+ return 0;
+}
+
+static int
+ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, uint8_t *data, int len)
{
struct hci_encrypt_key_refresh evt;
@@ -199,7 +198,7 @@ host_hci_rx_enc_key_refresh(uint8_t event_code, uint8_t *data, int len)
}
static int
-host_hci_rx_num_completed_pkts(uint8_t event_code, uint8_t *data, int len)
+ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, uint8_t *data, int len)
{
uint16_t num_pkts;
uint16_t handle;
@@ -232,21 +231,20 @@ host_hci_rx_num_completed_pkts(uint8_t event_code, uint8_t *data, int len)
}
static int
-host_hci_rx_le_meta(uint8_t event_code, uint8_t *data, int len)
+ble_hs_hci_evt_le_meta(uint8_t event_code, uint8_t *data, int len)
{
- const struct host_hci_le_event_dispatch_entry *entry;
+ const struct ble_hs_hci_evt_le_dispatch_entry *entry;
uint8_t subevent;
int rc;
if (len < BLE_HCI_EVENT_HDR_LEN + BLE_HCI_LE_MIN_LEN) {
- /* XXX: Increment stat. */
return BLE_HS_ECONTROLLER;
}
subevent = data[2];
- entry = host_hci_le_dispatch_entry_find(subevent);
+ entry = ble_hs_hci_evt_le_dispatch_find(subevent);
if (entry != NULL) {
- rc = entry->hmd_fn(subevent, data + BLE_HCI_EVENT_HDR_LEN,
+ rc = entry->cb(subevent, data + BLE_HCI_EVENT_HDR_LEN,
len - BLE_HCI_EVENT_HDR_LEN);
if (rc != 0) {
return rc;
@@ -257,7 +255,7 @@ host_hci_rx_le_meta(uint8_t event_code, uint8_t *data, int len)
}
static int
-host_hci_rx_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
+ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
{
struct hci_le_conn_complete evt;
int extended_offset = 0;
@@ -313,8 +311,9 @@ host_hci_rx_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
}
static int
-host_hci_le_adv_rpt_first_pass(uint8_t *data, int len,
- uint8_t *out_num_reports, int *out_rssi_off)
+ble_hs_hci_evt_le_adv_rpt_first_pass(uint8_t *data, int len,
+ uint8_t *out_num_reports,
+ int *out_rssi_off)
{
uint8_t num_reports;
int data_len;
@@ -361,50 +360,117 @@ host_hci_le_adv_rpt_first_pass(uint8_t *data, int len,
}
static int
-host_hci_rx_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
+ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
{
- struct ble_hs_adv adv;
+ struct ble_gap_disc_desc desc;
uint8_t num_reports;
int rssi_off;
int data_off;
+ int suboff;
int off;
int rc;
int i;
- rc = host_hci_le_adv_rpt_first_pass(data, len, &num_reports, &rssi_off);
+ rc = ble_hs_hci_evt_le_adv_rpt_first_pass(data, len, &num_reports,
+ &rssi_off);
if (rc != 0) {
return rc;
}
+ /* Direct address fields not present in a standard advertising report. */
+ desc.direct_addr_type = BLE_GAP_ADDR_TYPE_NONE;
+ memset(desc.direct_addr, 0, sizeof desc.direct_addr);
+
data_off = 0;
for (i = 0; i < num_reports; i++) {
- off = 2 + 0 * num_reports + i;
- adv.event_type = data[2 + 0 * num_reports + i];
+ suboff = 0;
+
+ off = 2 + suboff * num_reports + i;
+ desc.event_type = data[off];
+ suboff++;
- off = 2 + 1 * num_reports + i;
- adv.addr_type = data[2 + 1 * num_reports + i];
+ off = 2 + suboff * num_reports + i;
+ desc.addr_type = data[off];
+ suboff++;
- off = 2 + 2 * num_reports + i * 6;
- memcpy(adv.addr, data + off, 6);
+ off = 2 + suboff * num_reports + i * 6;
+ memcpy(desc.addr, data + off, 6);
+ suboff += 6;
- off = 2 + 8 * num_reports + i;
- adv.length_data = data[off];
+ off = 2 + suboff * num_reports + i;
+ desc.length_data = data[off];
+ suboff++;
- off = 2 + 9 * num_reports + data_off;
- adv.data = data + off;
- data_off += adv.length_data;
+ off = 2 + suboff * num_reports + data_off;
+ desc.data = data + off;
+ data_off += desc.length_data;
off = rssi_off + 1 * i;
- adv.rssi = data[off];
+ desc.rssi = data[off];
- ble_gap_rx_adv_report(&adv);
+ ble_gap_rx_adv_report(&desc);
}
return 0;
}
static int
-host_hci_rx_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
+ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len)
+{
+ struct ble_gap_disc_desc desc;
+ uint8_t num_reports;
+ int suboff;
+ int off;
+ int i;
+
+ if (len < BLE_HCI_LE_ADV_DIRECT_RPT_LEN) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ num_reports = data[1];
+ if (len != 2 + num_reports * BLE_HCI_LE_ADV_DIRECT_RPT_SUB_LEN) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ /* Data fields not present in a direct advertising report. */
+ desc.data = NULL;
+ desc.fields = NULL;
+
+ for (i = 0; i < num_reports; i++) {
+ suboff = 0;
+
+ off = 2 + suboff * num_reports + i;
+ desc.event_type = data[off];
+ suboff++;
+
+ off = 2 + suboff * num_reports + i;
+ desc.addr_type = data[off];
+ suboff++;
+
+ off = 2 + suboff * num_reports + i * 6;
+ memcpy(desc.addr, data + off, 6);
+ suboff += 6;
+
+ off = 2 + suboff * num_reports + i;
+ desc.direct_addr_type = data[off];
+ suboff++;
+
+ off = 2 + suboff * num_reports + i * 6;
+ memcpy(desc.direct_addr, data + off, 6);
+ suboff += 6;
+
+ off = 2 + suboff * num_reports + i;
+ desc.rssi = data[off];
+ suboff++;
+
+ ble_gap_rx_adv_report(&desc);
+ }
+
+ return 0;
+}
+
+static int
+ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
{
struct hci_le_conn_upd_complete evt;
@@ -443,7 +509,7 @@ host_hci_rx_le_conn_upd_complete(uint8_t subevent, uint8_t *data, int len)
}
static int
-host_hci_rx_le_lt_key_req(uint8_t subevent, uint8_t *data, int len)
+ble_hs_hci_evt_le_lt_key_req(uint8_t subevent, uint8_t *data, int len)
{
struct hci_le_lt_key_req evt;
@@ -462,7 +528,7 @@ host_hci_rx_le_lt_key_req(uint8_t subevent, uint8_t *data, int len)
}
static int
-host_hci_rx_le_conn_parm_req(uint8_t subevent, uint8_t *data, int len)
+ble_hs_hci_evt_le_conn_parm_req(uint8_t subevent, uint8_t *data, int len)
{
struct hci_le_conn_param_req evt;
@@ -500,22 +566,9 @@ host_hci_rx_le_conn_parm_req(uint8_t subevent, uint8_t *data, int len)
}
int
-host_hci_set_buf_size(uint16_t pktlen, uint8_t max_pkts)
-{
- if (pktlen == 0 || max_pkts == 0) {
- return BLE_HS_EINVAL;
- }
-
- host_hci_buffer_sz = pktlen;
- host_hci_max_pkts = max_pkts;
-
- return 0;
-}
-
-int
-host_hci_event_rx(uint8_t *data)
+ble_hs_hci_evt_process(uint8_t *data)
{
- const struct host_hci_event_dispatch_entry *entry;
+ const struct ble_hs_hci_evt_dispatch_entry *entry;
uint8_t event_code;
uint8_t param_len;
int event_len;
@@ -525,7 +578,7 @@ host_hci_event_rx(uint8_t *data)
STATS_INC(ble_hs_stats, hci_event);
/* Display to console */
- host_hci_dbg_event_disp(data);
+ ble_hs_dbg_event_disp(data);
/* Process the event */
event_code = data[0];
@@ -533,100 +586,19 @@ host_hci_event_rx(uint8_t *data)
event_len = param_len + 2;
- entry = host_hci_dispatch_entry_find(event_code);
+ entry = ble_hs_hci_evt_dispatch_find(event_code);
if (entry == NULL) {
- STATS_INC(ble_hs_stats, hci_invalid_ack);
+ STATS_INC(ble_hs_stats, hci_unknown_event);
rc = BLE_HS_ENOTSUP;
} else {
- rc = entry->hed_fn(event_code, data, event_len);
+ rc = entry->cb(event_code, data, event_len);
}
- return rc;
-}
-
-int
-host_hci_os_event_proc(struct os_event *ev)
-{
- os_error_t err;
- int rc;
-
- rc = host_hci_event_rx(ev->ev_arg);
-
- /* Free the command buffer */
- err = os_memblock_put(&g_hci_cmd_pool, ev->ev_arg);
- BLE_HS_DBG_ASSERT_EVAL(err == OS_OK);
-
- /* Free the event */
- err = os_memblock_put(&g_hci_os_event_pool, ev);
- BLE_HS_DBG_ASSERT_EVAL(err == OS_OK);
+ ble_hci_trans_buf_free(data);
return rc;
}
-/* XXX: For now, put this here */
-int
-ble_hci_transport_ctlr_event_send(uint8_t *hci_ev)
-{
- struct os_event *ev;
- os_error_t err;
- int enqueue;
-
- BLE_HS_DBG_ASSERT(hci_ev != NULL);
-
- switch (hci_ev[0]) {
- case BLE_HCI_EVCODE_COMMAND_COMPLETE:
- case BLE_HCI_EVCODE_COMMAND_STATUS:
- if (hci_ev[3] == 0 && hci_ev[4] == 0) {
- enqueue = 1;
- } else {
- ble_hci_cmd_rx_ack(hci_ev);
- enqueue = 0;
- }
- break;
-
- default:
- enqueue = 1;
- break;
- }
-
- if (enqueue) {
- /* Get an event structure off the queue */
- ev = (struct os_event *)os_memblock_get(&g_hci_os_event_pool);
- if (!ev) {
- err = os_memblock_put(&g_hci_cmd_pool, hci_ev);
- BLE_HS_DBG_ASSERT_EVAL(err == OS_OK);
- return -1;
- }
-
- /* Fill out the event and post to host task. */
- ev->ev_queued = 0;
- ev->ev_type = BLE_HOST_HCI_EVENT_CTLR_EVENT;
- ev->ev_arg = hci_ev;
- ble_hs_event_enqueue(ev);
- }
-
- return 0;
-}
-
-static int
-host_hci_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *hdr)
-{
- int rc;
-
- rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, hdr);
- if (rc != 0) {
- return BLE_HS_ECONTROLLER;
- }
-
- /* Strip HCI ACL data header from the front of the packet. */
- os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
-
- hdr->hdh_handle_pb_bc = le16toh(&hdr->hdh_handle_pb_bc);
- hdr->hdh_len = le16toh(&hdr->hdh_len);
-
- return 0;
-}
-
/**
* Called when a data packet is received from the controller. This function
* consumes the supplied mbuf, regardless of the outcome.
@@ -637,7 +609,7 @@ host_hci_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *hdr)
* @return 0 on success; nonzero on failure.
*/
int
-host_hci_data_rx(struct os_mbuf *om)
+ble_hs_hci_evt_acl_process(struct os_mbuf *om)
{
struct hci_data_hdr hci_hdr;
struct ble_hs_conn *conn;
@@ -646,100 +618,60 @@ host_hci_data_rx(struct os_mbuf *om)
uint16_t handle;
int rc;
- rc = host_hci_data_hdr_strip(om, &hci_hdr);
- if (rc == 0) {
+ rc = ble_hs_hci_util_data_hdr_strip(om, &hci_hdr);
+ if (rc != 0) {
+ goto err;
+ }
+
#if (BLETEST_THROUGHPUT_TEST == 0)
- BLE_HS_LOG(DEBUG, "host_hci_data_rx(): handle=%u pb=%x len=%u data=",
- BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
- BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
- hci_hdr.hdh_len);
- ble_hs_misc_log_mbuf(om);
- BLE_HS_LOG(DEBUG, "\n");
+ BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): handle=%u pb=%x len=%u "
+ "data=",
+ BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
+ BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
+ hci_hdr.hdh_len);
+ ble_hs_log_mbuf(om);
+ BLE_HS_LOG(DEBUG, "\n");
#endif
- if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
- rc = BLE_HS_EBADDATA;
- } else {
- handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);
+ if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
+ rc = BLE_HS_EBADDATA;
+ goto err;
+ }
- ble_hs_lock();
+ handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);
- conn = ble_hs_conn_find(handle);
- if (conn == NULL) {
- rc = BLE_HS_ENOTCONN;
- } else {
- rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf);
- om = NULL;
- }
+ ble_hs_lock();
- ble_hs_unlock();
- }
+ conn = ble_hs_conn_find(handle);
+ if (conn == NULL) {
+ rc = BLE_HS_ENOTCONN;
+ } else {
+ rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf);
+ om = NULL;
}
- os_mbuf_free_chain(om);
+ ble_hs_unlock();
- if (rc == 0) {
+ switch (rc) {
+ case 0:
+ /* Final fragment received. */
BLE_HS_DBG_ASSERT(rx_cb != NULL);
BLE_HS_DBG_ASSERT(rx_buf != NULL);
rc = rx_cb(handle, &rx_buf);
os_mbuf_free_chain(rx_buf);
- } else if (rc == BLE_HS_EAGAIN) {
- /* More fragments on the way. */
- rc = 0;
- }
-
- return rc;
-}
-
-static struct os_mbuf *
-host_hci_data_hdr_prepend(struct os_mbuf *om, uint16_t handle, uint8_t pb_flag)
-{
- struct hci_data_hdr hci_hdr;
-
- hci_hdr.hdh_handle_pb_bc = host_hci_handle_pb_bc_join(handle, pb_flag, 0);
- htole16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
-
- om = os_mbuf_prepend(om, sizeof hci_hdr);
- if (om == NULL) {
- return NULL;
- }
-
- memcpy(om->om_data, &hci_hdr, sizeof hci_hdr);
-
- BLE_HS_LOG(DEBUG, "host tx hci data; handle=%d length=%d\n", handle,
- le16toh(&hci_hdr.hdh_len));
-
- return om;
-}
-
-/**
- * Transmits an HCI ACL data packet. This function consumes the supplied mbuf,
- * regardless of the outcome.
- */
-int
-host_hci_data_tx(struct ble_hs_conn *connection, struct os_mbuf *om)
-{
- int rc;
-
- /* XXX: Different transport mechanisms have different fragmentation
- * requirements. For now, never fragment.
- */
- om = host_hci_data_hdr_prepend(om, connection->bhc_handle,
- BLE_HCI_PB_FIRST_NON_FLUSH);
- if (om == NULL) {
- return BLE_HS_ENOMEM;
- }
+ break;
- BLE_HS_LOG(DEBUG, "host_hci_data_tx(): ");
- ble_hs_misc_log_mbuf(om);
- BLE_HS_LOG(DEBUG, "\n");
+ case BLE_HS_EAGAIN:
+ /* More fragments on the way. */
+ break;
- rc = ble_hs_tx_data(om);
- if (rc != 0) {
- return rc;
+ default:
+ goto err;
}
- connection->bhc_outstanding_pkts++;
-
return 0;
+
+err:
+ os_mbuf_free_chain(om);
+ return rc;
}
diff --git a/net/nimble/host/src/ble_hs_hci_priv.h b/net/nimble/host/src/ble_hs_hci_priv.h
new file mode 100644
index 00000000..7d2fb120
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_hci_priv.h
@@ -0,0 +1,158 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_HS_HCI_PRIV_
+#define H_BLE_HS_HCI_PRIV_
+
+#include "nimble/hci_common.h"
+struct ble_hs_conn;
+struct os_mbuf;
+
+struct ble_hs_hci_ack {
+ int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */
+ uint8_t *bha_params;
+ int bha_params_len;
+ uint16_t bha_opcode;
+ uint8_t bha_hci_handle;
+};
+
+int ble_hs_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
+ uint8_t *out_evt_buf_len);
+int ble_hs_hci_cmd_tx_empty_ack(void *cmd);
+void ble_hs_hci_rx_ack(uint8_t *ack_ev);
+void ble_hs_hci_init(void);
+
+#if PHONY_HCI_ACKS
+typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len);
+void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb);
+#endif
+
+int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr);
+int ble_hs_hci_util_rand(void *dst, int len);
+int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi);
+int ble_hs_hci_util_set_random_addr(const uint8_t *addr);
+int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
+ uint16_t tx_time);
+int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
+ struct hci_data_hdr *out_hdr);
+
+int ble_hs_hci_evt_process(uint8_t *data);
+uint16_t ble_hs_hci_util_opcode_join(uint8_t ogf, uint16_t ocf);
+void ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint8_t ocf, uint8_t len,
+ void *buf);
+int ble_hs_hci_cmd_send(uint8_t ogf, uint8_t ocf, uint8_t len,
+ const void *cmddata);
+int ble_hs_hci_cmd_send_buf(void *cmddata);
+void ble_hs_hci_cmd_build_read_bd_addr(uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask, uint8_t *dst,
+ int dst_len);
+void ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_disconnect(uint16_t handle, uint8_t reason);
+void ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst,
+ int dst_len);
+int ble_hs_hci_cmd_read_rssi(uint16_t handle);
+int ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_read_buffer_size(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_le_read_buffer_size(void);
+void ble_hs_hci_cmd_build_le_read_loc_supp_feat(uint8_t *dst, uint8_t dst_len);
+void ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
+ int dst_len);
+int ble_hs_hci_cmd_le_set_adv_enable(uint8_t enable);
+int ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,
+ uint16_t scan_itvl,
+ uint16_t scan_window,
+ uint8_t own_addr_type,
+ uint8_t filter_policy,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable,
+ uint8_t filter_dups,
+ uint8_t *dst, uint8_t dst_len);
+int ble_hs_hci_cmd_le_set_scan_enable(uint8_t enable, uint8_t filter_dups);
+int ble_hs_hci_cmd_build_le_create_connection(
+ const struct hci_create_conn *hcc, uint8_t *cmd, int cmd_len);
+int ble_hs_hci_cmd_le_create_connection(const struct hci_create_conn *hcc);
+void ble_hs_hci_cmd_build_le_clear_whitelist(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr,
+ uint8_t addr_type,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_reset(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_reset(void);
+void ble_hs_hci_cmd_build_read_adv_pwr(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_read_adv_pwr(void);
+void ble_hs_hci_cmd_build_le_create_conn_cancel(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_le_create_conn_cancel(void);
+int ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu);
+void ble_hs_hci_cmd_build_le_lt_key_req_reply(
+ const struct hci_lt_key_req_reply *hkr, uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
+ uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_conn_param_reply(
+ const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr);
+void ble_hs_hci_cmd_build_le_conn_param_neg_reply(
+ const struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_le_conn_param_neg_reply(
+ const struct hci_conn_param_neg_reply *hcn);
+void ble_hs_hci_cmd_build_le_rand(uint8_t *dst, int dst_len);
+void ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint8_t max_pkts);
+
+uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb,
+ uint8_t bc);
+
+int ble_hs_hci_acl_tx(struct ble_hs_conn *connection, struct os_mbuf *txom);
+
+int ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,
+ uint16_t tx_octets, uint16_t tx_time,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_add_to_resolv_list(
+ const struct hci_add_dev_to_resolving_list *padd,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_remove_from_resolv_list(
+ uint8_t addr_type, const uint8_t *addr, uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_read_resolv_list_size(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_clear_resolv_list(uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_read_peer_resolv_addr(
+ uint8_t peer_identity_addr_type, const uint8_t *peer_identity_addr,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_read_lcl_resolv_addr(
+ uint8_t local_identity_addr_type, const uint8_t *local_identity_addr,
+ uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_set_addr_res_en(
+ uint8_t enable, uint8_t *dst, int dst_len);
+int ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
+ uint16_t timeout, uint8_t *dst, int dst_len);
+
+int ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
+ uint8_t *dst, int dst_len);
+
+#endif
diff --git a/net/nimble/host/src/ble_hci_util.c b/net/nimble/host/src/ble_hs_hci_util.c
index f9ed2c52..0d9f625e 100644
--- a/net/nimble/host/src/ble_hci_util.c
+++ b/net/nimble/host/src/ble_hs_hci_util.c
@@ -19,18 +19,35 @@
#include <string.h>
#include "nimble/hci_common.h"
-#include "host/host_hci.h"
#include "ble_hs_priv.h"
+uint16_t
+ble_hs_hci_util_opcode_join(uint8_t ogf, uint16_t ocf)
+{
+ return (ogf << 10) | ocf;
+}
+
+uint16_t
+ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
+{
+ BLE_HS_DBG_ASSERT(handle <= 0x0fff);
+ BLE_HS_DBG_ASSERT(pb <= 0x03);
+ BLE_HS_DBG_ASSERT(bc <= 0x03);
+
+ return (handle << 0) |
+ (pb << 12) |
+ (bc << 14);
+}
+
int
-ble_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
+ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t params_len;
int rc;
- host_hci_cmd_build_read_adv_pwr(buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, out_tx_pwr, 1, &params_len);
+ ble_hs_hci_cmd_build_read_adv_pwr(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, out_tx_pwr, 1, &params_len);
if (rc != 0) {
return rc;
}
@@ -46,7 +63,7 @@ ble_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
}
int
-ble_hci_util_rand(void *dst, int len)
+ble_hs_hci_util_rand(void *dst, int len)
{
uint8_t rsp_buf[BLE_HCI_LE_RAND_LEN];
uint8_t req_buf[BLE_HCI_CMD_HDR_LEN];
@@ -55,11 +72,11 @@ ble_hci_util_rand(void *dst, int len)
int chunk_sz;
int rc;
- host_hci_cmd_build_le_rand(req_buf, sizeof req_buf);
+ ble_hs_hci_cmd_build_le_rand(req_buf, sizeof req_buf);
u8ptr = dst;
while (len > 0) {
- rc = ble_hci_cmd_tx(req_buf, rsp_buf, sizeof rsp_buf, &params_len);
+ rc = ble_hs_hci_cmd_tx(req_buf, rsp_buf, sizeof rsp_buf, &params_len);
if (rc != 0) {
return rc;
}
@@ -78,7 +95,7 @@ ble_hci_util_rand(void *dst, int len)
}
int
-ble_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
+ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_READ_RSSI_LEN];
uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
@@ -86,8 +103,8 @@ ble_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
uint8_t params_len;
int rc;
- host_hci_cmd_build_read_rssi(conn_handle, buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, params, sizeof params, &params_len);
+ ble_hs_hci_cmd_build_read_rssi(conn_handle, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, params, sizeof params, &params_len);
if (rc != 0) {
return rc;
}
@@ -107,25 +124,25 @@ ble_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
}
int
-ble_hs_util_set_random_addr(uint8_t *addr)
+ble_hs_hci_util_set_random_addr(const uint8_t *addr)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RAND_ADDR_LEN];
int rc;
/* set the address in the controller */
- rc = host_hci_cmd_build_set_random_addr(addr, buf, sizeof(buf));
+ rc = ble_hs_hci_cmd_build_set_random_addr(addr, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
return rc;
}
int
-ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
- uint16_t tx_time)
+ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
+ uint16_t tx_time)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_DATALEN_LEN];
@@ -134,14 +151,14 @@ ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
uint8_t params_len;
int rc;
- rc = host_hci_cmd_build_set_data_len(conn_handle, tx_octets, tx_time, buf,
- sizeof buf);
+ rc = ble_hs_hci_cmd_build_set_data_len(conn_handle, tx_octets, tx_time,
+ buf, sizeof buf);
if (rc != 0) {
return BLE_HS_HCI_ERR(rc);
}
- rc = ble_hci_cmd_tx(buf, params, BLE_HCI_SET_DATALEN_ACK_PARAM_LEN,
- &params_len);
+ rc = ble_hs_hci_cmd_tx(buf, params, BLE_HCI_SET_DATALEN_ACK_PARAM_LEN,
+ &params_len);
if (rc != 0) {
return rc;
}
@@ -157,3 +174,23 @@ ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
return 0;
}
+
+int
+ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
+ struct hci_data_hdr *out_hdr)
+{
+ int rc;
+
+ rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
+ if (rc != 0) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ /* Strip HCI ACL data header from the front of the packet. */
+ os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
+
+ out_hdr->hdh_handle_pb_bc = le16toh(&out_hdr->hdh_handle_pb_bc);
+ out_hdr->hdh_len = le16toh(&out_hdr->hdh_len);
+
+ return 0;
+}
diff --git a/net/nimble/host/src/ble_hs_id.c b/net/nimble/host/src/ble_hs_id.c
new file mode 100644
index 00000000..9ef384b9
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_id.c
@@ -0,0 +1,248 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include "host/ble_hs_id.h"
+#include "ble_hs_priv.h"
+
+static uint8_t ble_hs_id_pub[6];
+static uint8_t ble_hs_id_rnd[6];
+
+void
+ble_hs_id_set_pub(const uint8_t *pub_addr)
+{
+ ble_hs_lock();
+ memcpy(ble_hs_id_pub, pub_addr, 6);
+ ble_hs_unlock();
+}
+
+/**
+ * Generates a new random address. This function does not configure the device
+ * with the new address; the caller can use the address in subsequent
+ * operations.
+ *
+ * @param nrpa The type of random address to generate:
+ * 0: static
+ * 1: non-resolvable private
+ * @param out_addr On success, the generated address gets written
+ * here.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_hs_id_gen_rnd(int nrpa, uint8_t *out_addr)
+{
+ int rc;
+
+ rc = ble_hs_hci_util_rand(out_addr, 6);
+ if (rc != 0) {
+ return rc;
+ }
+
+ if (nrpa) {
+ out_addr[5] &= ~0xc0;
+ } else {
+ out_addr[5] |= 0xc0;
+ }
+
+ return 0;
+}
+
+/**
+ * Sets the device's random address. The address type (static vs.
+ * non-resolvable private) is inferred from the most-significant byte of the
+ * address. The address is specified in host byte order (little-endian!).
+ *
+ * @param rnd_addr The random address to set.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if the specified address is not a
+ * valid static random or non-resolvable
+ * private address.
+ * Other nonzero on error.
+ */
+int
+ble_hs_id_set_rnd(const uint8_t *rnd_addr)
+{
+ uint8_t addr_type_byte;
+ int rc;
+
+ ble_hs_lock();
+
+ addr_type_byte = rnd_addr[5] & 0xc0;
+ if (addr_type_byte != 0x00 && addr_type_byte != 0xc0) {
+ rc = BLE_HS_EINVAL;
+ goto done;
+ }
+
+ rc = ble_hs_hci_util_set_random_addr(rnd_addr);
+ if (rc != 0) {
+ goto done;
+ }
+
+ memcpy(ble_hs_id_rnd, rnd_addr, 6);
+
+ rc = 0;
+
+done:
+ ble_hs_unlock();
+ return rc;
+}
+
+/**
+ * Retrieves one of the device's identity addresses. The device can have two
+ * identity addresses: one public and one random. The id_addr_type argument
+ * specifies which of these two addresses to retrieve.
+ *
+ * @param id_addr_type The type of identity address to retrieve.
+ * Valid values are:
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * @param out_id_addr On success, this is reseated to point to the
+ * retrieved 6-byte identity address.
+ * @param out_is_nrpa On success, the pointed-to value indicates
+ * whether the retrieved address is a
+ * non-resolvable private address.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if an invalid address type was
+ * specified;
+ * BLE_HS_ENOADDR if the device does not have an
+ * identity address of the requested type;
+ * Other BLE host core code on error.
+ */
+int
+ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr,
+ int *out_is_nrpa)
+{
+ const uint8_t *id_addr;
+ int nrpa;
+
+ BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
+
+ switch (id_addr_type) {
+ case BLE_ADDR_TYPE_PUBLIC:
+ id_addr = ble_hs_id_pub;
+ nrpa = 0;
+ break;
+
+ case BLE_ADDR_TYPE_RANDOM:
+ id_addr = ble_hs_id_rnd;
+ nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0;
+ break;
+
+ default:
+ return BLE_HS_EINVAL;
+ }
+
+ if (memcmp(id_addr, ble_hs_misc_null_addr, 6) == 0) {
+ return BLE_HS_ENOADDR;
+ }
+
+ if (out_id_addr != NULL) {
+ *out_id_addr = id_addr;
+ }
+ if (out_is_nrpa != NULL) {
+ *out_is_nrpa = nrpa;
+ }
+
+ return 0;
+}
+
+/**
+ * Retrieves one of the device's identity addresses. The device can have two
+ * identity addresses: one public and one random. The id_addr_type argument
+ * specifies which of these two addresses to retrieve.
+ *
+ * @param id_addr_type The type of identity address to retrieve.
+ * Valid values are:
+ * o BLE_ADDR_TYPE_PUBLIC
+ * o BLE_ADDR_TYPE_RANDOM
+ * @param out_id_addr On success, the requested identity address is
+ * copied into this buffer. The buffer must
+ * be at least six bytes in size.
+ * @param out_is_nrpa On success, the pointed-to value indicates
+ * whether the retrieved address is a
+ * non-resolvable private address.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if an invalid address type was
+ * specified;
+ * BLE_HS_ENOADDR if the device does not have an
+ * identity address of the requested type;
+ * Other BLE host core code on error.
+ */
+int
+ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr,
+ int *out_is_nrpa)
+{
+ const uint8_t *addr;
+ int rc;
+
+ ble_hs_lock();
+
+ rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa);
+ if (rc == 0) {
+ memcpy(out_id_addr, addr, 6);
+ }
+
+ ble_hs_unlock();
+
+ return rc;
+}
+
+int
+ble_hs_id_use_addr(uint8_t addr_type)
+{
+ uint8_t id_addr_type;
+ int nrpa;
+ int rc;
+
+ switch (addr_type) {
+ case BLE_ADDR_TYPE_PUBLIC:
+ case BLE_ADDR_TYPE_RANDOM:
+ rc = ble_hs_id_addr(addr_type, NULL, NULL);
+ if (rc != 0) {
+ return rc;
+ }
+ break;
+
+ case BLE_ADDR_TYPE_RPA_PUB_DEFAULT:
+ case BLE_ADDR_TYPE_RPA_RND_DEFAULT:
+ id_addr_type = ble_hs_misc_addr_type_to_id(addr_type);
+ rc = ble_hs_id_addr(id_addr_type, NULL, &nrpa);
+ if (rc != 0) {
+ return rc;
+ }
+ if (nrpa) {
+ return BLE_HS_ENOADDR;
+ }
+
+ rc = ble_hs_pvcy_ensure_started();
+ if (rc != 0) {
+ return rc;
+ }
+ break;
+
+ default:
+ return BLE_HS_EINVAL;
+ }
+
+ return 0;
+}
diff --git a/net/nimble/host/src/ble_hci_util_priv.h b/net/nimble/host/src/ble_hs_id_priv.h
index f4455147..5c0728c5 100644
--- a/net/nimble/host/src/ble_hci_util_priv.h
+++ b/net/nimble/host/src/ble_hs_id_priv.h
@@ -17,14 +17,14 @@
* under the License.
*/
-#ifndef H_BLE_HCI_UTIL_
-#define H_BLE_HCI_UTIL_
+#ifndef H_BLE_HS_ID_PRIV_
+#define H_BLE_HS_ID_PRIV_
-int ble_hci_util_read_adv_tx_pwr(int8_t *out_pwr);
-int ble_hci_util_rand(void *dst, int len);
-int ble_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi);
-int ble_hs_util_set_random_addr(uint8_t *addr);
-int ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
- uint16_t tx_time);
+#include <inttypes.h>
+
+void ble_hs_id_set_pub(const uint8_t *pub_addr);
+int ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr,
+ int *out_is_nrpa);
+int ble_hs_id_use_addr(uint8_t addr_type);
#endif
diff --git a/net/nimble/host/src/ble_hs_log.c b/net/nimble/host/src/ble_hs_log.c
new file mode 100644
index 00000000..39294830
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_log.c
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "host/ble_hs.h"
+
+struct log ble_hs_log;
+
+void
+ble_hs_log_mbuf(const struct os_mbuf *om)
+{
+ uint8_t u8;
+ int i;
+
+ for (i = 0; i < OS_MBUF_PKTLEN(om); i++) {
+ os_mbuf_copydata(om, i, 1, &u8);
+ BLE_HS_LOG(DEBUG, "0x%02x ", u8);
+ }
+}
+
+void
+ble_hs_log_flat_buf(const void *data, int len)
+{
+ const uint8_t *u8ptr;
+ int i;
+
+ u8ptr = data;
+ for (i = 0; i < len; i++) {
+ BLE_HS_LOG(DEBUG, "0x%02x ", u8ptr[i]);
+ }
+}
diff --git a/net/nimble/host/src/ble_hs_mbuf.c b/net/nimble/host/src/ble_hs_mbuf.c
new file mode 100644
index 00000000..870c88bd
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_mbuf.c
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "host/ble_hs.h"
+#include "ble_hs_priv.h"
+
+/**
+ * Allocates an mbuf for use by the nimble host.
+ */
+static struct os_mbuf *
+ble_hs_mbuf_gen_pkt(uint16_t leading_space)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = os_msys_get_pkthdr(0, 0);
+ if (om == NULL) {
+ return NULL;
+ }
+
+ if (om->om_omp->omp_databuf_len < leading_space) {
+ rc = os_mbuf_free_chain(om);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+ return NULL;
+ }
+
+ om->om_data += leading_space;
+
+ return om;
+}
+
+/**
+ * Allocates an mbuf with no leading space.
+ *
+ * @return An empty mbuf on success; null on memory
+ * exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_bare_pkt(void)
+{
+ return ble_hs_mbuf_gen_pkt(0);
+}
+
+/**
+ * Allocates an mbuf suitable for an HCI ACM data packet.
+ *
+ * @return An empty mbuf on success; null on memory
+ * exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_acm_pkt(void)
+{
+ return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ);
+}
+
+/**
+ * Allocates an mbuf suitable for an L2CAP data packet. The resulting packet
+ * has sufficient leading space for:
+ * o ACM data header
+ * o L2CAP B-frame header
+ *
+ * @return An empty mbuf on success; null on memory
+ * exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_l2cap_pkt(void)
+{
+ return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ + BLE_L2CAP_HDR_SZ);
+}
+
+/**
+ * Allocates an mbuf suitable for an ATT command packet. The resulting packet
+ * has sufficient leading space for:
+ * o ACM data header
+ * o L2CAP B-frame header
+ * o Largest ATT command base (prepare write request / response).
+ *
+ * @return An empty mbuf on success; null on memory
+ * exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_att_pkt(void)
+{
+ /* Prepare write request and response are the larget ATT commands which
+ * contain attribute data.
+ */
+ return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ +
+ BLE_L2CAP_HDR_SZ +
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+}
+
+/**
+ * Allocates a an mbuf and fills it with the contents of the specified flat
+ * buffer.
+ *
+ * @param buf The flat buffer to copy from.
+ * @param len The length of the flat buffer.
+ *
+ * @return A newly-allocated mbuf on success;
+ * NULL on memory exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_from_flat(const void *buf, uint16_t len)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_mbuf_att_pkt();
+ if (om == NULL) {
+ return NULL;
+ }
+
+ rc = os_mbuf_copyinto(om, 0, buf, len);
+ if (rc != 0) {
+ os_mbuf_free_chain(om);
+ return NULL;
+ }
+
+ return om;
+}
+
+/**
+ * Copies the contents of an mbuf into the specified flat buffer. If the flat
+ * buffer is too small to contain the mbuf's contents, it is filled to capacity
+ * and BLE_HS_EMSGSIZE is returned.
+ *
+ * @param om The mbuf to copy from.
+ * @param flat The destination flat buffer.
+ * @param max_len The size of the flat buffer.
+ * @param out_copy_len The number of bytes actually copied gets
+ * written here.
+ *
+ * @return 0 on success;
+ * BLE_HS_EMSGSIZE if the flat buffer is too small
+ * to contain the mbuf's contents;
+ * A BLE host core return code on unexpected
+ * error.
+ */
+int
+ble_hs_mbuf_to_flat(const struct os_mbuf *om, void *flat, uint16_t max_len,
+ uint16_t *out_copy_len)
+{
+ uint16_t copy_len;
+ int rc;
+
+ if (OS_MBUF_PKTLEN(om) <= max_len) {
+ copy_len = OS_MBUF_PKTLEN(om);
+ } else {
+ copy_len = max_len;
+ }
+
+ rc = os_mbuf_copydata(om, 0, copy_len, flat);
+ if (rc != 0) {
+ return BLE_HS_EUNKNOWN;
+ }
+
+ if (copy_len > max_len) {
+ rc = BLE_HS_EMSGSIZE;
+ } else {
+ rc = 0;
+ }
+
+ if (out_copy_len != NULL) {
+ *out_copy_len = copy_len;
+ }
+ return rc;
+}
+
+int
+ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len)
+{
+ if (OS_MBUF_PKTLEN(*om) < base_len) {
+ return BLE_HS_EBADDATA;
+ }
+
+ *om = os_mbuf_pullup(*om, base_len);
+ if (*om == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/net/nimble/host/src/ble_hs_mbuf_priv.h b/net/nimble/host/src/ble_hs_mbuf_priv.h
new file mode 100644
index 00000000..f0ea9b52
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_mbuf_priv.h
@@ -0,0 +1,11 @@
+#ifndef H_BLE_HS_MBUF_PRIV_
+#define H_BLE_HS_MBUF_PRIV_
+
+struct os_mbuf;
+
+struct os_mbuf *ble_hs_mbuf_bare_pkt(void);
+struct os_mbuf *ble_hs_mbuf_acm_pkt(void);
+struct os_mbuf *ble_hs_mbuf_l2cap_pkt(void);
+int ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len);
+
+#endif
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
index 9575ae39..649fc05e 100644
--- a/net/nimble/host/src/ble_hs_misc.c
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -23,6 +23,8 @@
#include "console/console.h"
#include "ble_hs_priv.h"
+const uint8_t ble_hs_misc_null_addr[6];
+
int
ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
int num_entries, int entry_size, char *name)
@@ -43,71 +45,6 @@ ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
return 0;
}
-void
-ble_hs_misc_log_mbuf(struct os_mbuf *om)
-{
- uint8_t u8;
- int i;
-
- for (i = 0; i < OS_MBUF_PKTLEN(om); i++) {
- os_mbuf_copydata(om, i, 1, &u8);
- BLE_HS_LOG(DEBUG, "0x%02x ", u8);
- }
-}
-
-void
-ble_hs_misc_log_flat_buf(void *data, int len)
-{
- uint8_t *u8ptr;
- int i;
-
- u8ptr = data;
- for (i = 0; i < len; i++) {
- BLE_HS_LOG(DEBUG, "0x%02x ", u8ptr[i]);
- }
-}
-
-/**
- * Allocates an mbuf for use by the nimble host.
- */
-struct os_mbuf *
-ble_hs_misc_pkthdr(void)
-{
- struct os_mbuf *om;
- int rc;
-
- om = os_msys_get_pkthdr(0, 0);
- if (om == NULL) {
- return NULL;
- }
-
- /* Make room in the buffer for various headers. XXX Check this number. */
- if (om->om_omp->omp_databuf_len < 8) {
- rc = os_mbuf_free_chain(om);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
- return NULL;
- }
-
- om->om_data += 8;
-
- return om;
-}
-
-int
-ble_hs_misc_pullup_base(struct os_mbuf **om, int base_len)
-{
- if (OS_MBUF_PKTLEN(*om) < base_len) {
- return BLE_HS_EBADDATA;
- }
-
- *om = os_mbuf_pullup(*om, base_len);
- if (*om == NULL) {
- return BLE_HS_ENOMEM;
- }
-
- return 0;
-}
-
int
ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
struct ble_hs_conn **out_conn,
@@ -140,7 +77,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
return rc;
}
-int
+void
ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan)
@@ -150,7 +87,7 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
int rc;
rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
- BLE_HS_DBG_ASSERT(conn == NULL || chan != NULL);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
if (out_conn != NULL) {
*out_conn = conn;
@@ -158,8 +95,6 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
if (out_chan != NULL) {
*out_chan = chan;
}
-
- return rc;
}
uint8_t
diff --git a/net/nimble/host/src/ble_hs_priv.h b/net/nimble/host/src/ble_hs_priv.h
index 1be119a1..6bebec9c 100644
--- a/net/nimble/host/src/ble_hs_priv.h
+++ b/net/nimble/host/src/ble_hs_priv.h
@@ -26,25 +26,37 @@
#include "ble_att_priv.h"
#include "ble_gap_priv.h"
#include "ble_gatt_priv.h"
-#include "ble_hci_util_priv.h"
-#include "ble_hs_adv_priv.h"
+#include "ble_hs_dbg_priv.h"
+#include "ble_hs_hci_priv.h"
#include "ble_hs_atomic_priv.h"
#include "ble_hs_conn_priv.h"
+#include "ble_hs_atomic_priv.h"
#include "ble_hs_endian_priv.h"
+#include "ble_hs_mbuf_priv.h"
#include "ble_hs_startup_priv.h"
#include "ble_l2cap_priv.h"
#include "ble_l2cap_sig_priv.h"
#include "ble_sm_priv.h"
+#include "ble_hs_adv_priv.h"
+#include "ble_hs_pvcy_priv.h"
+#include "ble_hs_id_priv.h"
+#include "ble_uuid_priv.h"
#include "host/ble_hs.h"
-#include "log/log.h"
#include "nimble/nimble_opt.h"
#include "stats/stats.h"
struct ble_hs_conn;
struct ble_l2cap_chan;
struct os_mbuf;
struct os_mempool;
+struct os_event;
#define BLE_HOST_HCI_EVENT_CTLR_EVENT (OS_EVENT_T_PERUSER + 0)
+#define BLE_HS_EVENT_TX_NOTIFICATIONS (OS_EVENT_T_PERUSER + 1)
+#define BLE_HS_EVENT_RESET (OS_EVENT_T_PERUSER + 2)
+
+#define BLE_HS_SYNC_STATE_BAD 0
+#define BLE_HS_SYNC_STATE_BRINGUP 1
+#define BLE_HS_SYNC_STATE_GOOD 2
STATS_SECT_START(ble_hs_stats)
STATS_SECT_ENTRY(conn_create)
@@ -53,38 +65,35 @@ STATS_SECT_START(ble_hs_stats)
STATS_SECT_ENTRY(hci_event)
STATS_SECT_ENTRY(hci_invalid_ack)
STATS_SECT_ENTRY(hci_unknown_event)
+ STATS_SECT_ENTRY(hci_timeout)
+ STATS_SECT_ENTRY(reset)
+ STATS_SECT_ENTRY(sync)
STATS_SECT_END
extern STATS_SECT_DECL(ble_hs_stats) ble_hs_stats;
-struct ble_hci_ack {
- int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */
- uint8_t *bha_params;
- int bha_params_len;
- uint16_t bha_opcode;
- uint8_t bha_hci_handle;
-};
-
-extern struct ble_hs_dev ble_hs_our_dev;
extern struct ble_hs_cfg ble_hs_cfg;
-
extern struct os_mbuf_pool ble_hs_mbuf_pool;
+extern uint8_t ble_hs_sync_state;
-extern struct log ble_hs_log;
+extern const uint8_t ble_hs_misc_null_addr[6];
void ble_hs_process_tx_data_queue(void);
-int ble_hs_rx_data(struct os_mbuf *om);
+void ble_hs_process_rx_data_queue(void);
int ble_hs_tx_data(struct os_mbuf *om);
+void ble_hs_enqueue_hci_event(uint8_t *hci_evt);
+void ble_hs_event_enqueue(struct os_event *ev);
+
+int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg);
+int ble_hs_hci_evt_acl_process(struct os_mbuf *om);
int ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
int num_entries, int entry_size, char *name);
-void ble_hs_misc_log_mbuf(struct os_mbuf *om);
-void ble_hs_misc_log_flat_buf(void *data, int len);
int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan);
-int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
- struct ble_hs_conn **out_conn,
- struct ble_l2cap_chan **out_chan);
+void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
+ struct ble_hs_conn **out_conn,
+ struct ble_l2cap_chan **out_chan);
uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type);
void ble_hs_cfg_init(struct ble_hs_cfg *cfg);
@@ -93,37 +102,10 @@ int ble_hs_locked_by_cur_task(void);
int ble_hs_is_parent_task(void);
void ble_hs_lock(void);
void ble_hs_unlock(void);
-
-struct os_mbuf *ble_hs_misc_pkthdr(void);
-
-int ble_hs_misc_pullup_base(struct os_mbuf **om, int base_len);
-
-int ble_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
- uint8_t *out_evt_buf_len);
-int ble_hci_cmd_tx_empty_ack(void *cmd);
-void ble_hci_cmd_rx_ack(uint8_t *ack_ev);
-void ble_hci_cmd_init(void);
-int ble_hs_pvcy_set_our_nrpa(void);
-void ble_hs_pvcy_our_nrpa(uint8_t *addr);
-void ble_hs_pvcy_set_our_id_addr(uint8_t *addr);
-void ble_hs_pvcy_set_our_irk(uint8_t *irk);
-uint8_t *ble_hs_pvcy_our_id_addr(uint8_t *type);
-uint8_t *ble_hs_pvcy_our_irk(void);
-int ble_hs_pvcy_remove_entry(uint8_t addr_type, uint8_t *addr);
-int ble_hs_pvcy_add_entry(uint8_t *addr, uint8_t addrtype, uint8_t *irk);
-#if PHONY_HCI_ACKS
-typedef int ble_hci_cmd_phony_ack_fn(uint8_t *ack, int ack_buf_len);
-
-void ble_hci_set_phony_ack_cb(ble_hci_cmd_phony_ack_fn *cb);
-#endif
-
-#define BLE_HS_LOG(lvl, ...) \
- LOG_ ## lvl(&ble_hs_log, LOG_MODULE_NIMBLE_HOST, __VA_ARGS__)
-
-#define BLE_HS_LOG_ADDR(lvl, addr) \
- BLE_HS_LOG(lvl, "%02x:%02x:%02x:%02x:%02x:%02x", \
- (addr)[5], (addr)[4], (addr)[3], \
- (addr)[2], (addr)[1], (addr)[0])
+void ble_hs_sched_reset(int reason);
+void ble_hs_hw_error(uint8_t hw_code);
+void ble_hs_heartbeat_sched(int32_t ticks);
+void ble_hs_notifications_sched(void);
#if LOG_LEVEL <= LOG_LEVEL_DEBUG
diff --git a/net/nimble/host/src/ble_hs_pvcy.c b/net/nimble/host/src/ble_hs_pvcy.c
index 1ea2f918..ad3fa0c3 100644
--- a/net/nimble/host/src/ble_hs_pvcy.c
+++ b/net/nimble/host/src/ble_hs_pvcy.c
@@ -21,13 +21,9 @@
#include <string.h>
#include "ble_hs_priv.h"
-static int ble_hs_pvcy_initialized;
-static uint8_t ble_hs_pvcy_id_addr[6];
-static uint8_t ble_hs_pvcy_id_addr_type;
-static uint8_t ble_hs_pvcy_nrpa[6];
+static uint8_t ble_hs_pvcy_started;
uint8_t ble_hs_pvcy_irk[16];
-
/** Use this as a default IRK if none gets set. */
const uint8_t default_irk[16] = {
0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
@@ -35,24 +31,12 @@ const uint8_t default_irk[16] = {
};
static int
-ble_hs_pvcy_gen_static_random_addr(uint8_t *addr)
-{
- int rc;
-
- rc = ble_hci_util_rand(addr, 6);
- /* TODO -- set bits properly */
- addr[5] |= 0xc0;
-
- return rc;
-}
-
-static int
ble_hs_pvcy_set_addr_timeout(uint16_t timeout)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN];
int rc;
- rc = host_hci_cmd_build_set_resolv_priv_addr_timeout(
+ rc = ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
timeout, buf, sizeof(buf));
return rc;
@@ -64,12 +48,12 @@ ble_hs_pvcy_set_resolve_enabled(int enable)
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
int rc;
- rc = host_hci_cmd_build_set_addr_res_en(enable, buf, sizeof(buf));
+ rc = ble_hs_hci_cmd_build_set_addr_res_en(enable, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx(buf, NULL, 0, NULL);
+ rc = ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
@@ -83,13 +67,13 @@ ble_hs_pvcy_remove_entry(uint8_t addr_type, uint8_t *addr)
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_RMV_FROM_RESOLV_LIST_LEN];
int rc;
- rc = host_hci_cmd_build_remove_from_resolv_list(
+ rc = ble_hs_hci_cmd_build_remove_from_resolv_list(
addr_type, addr, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx(buf, NULL, 0, NULL);
+ rc = ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
@@ -103,12 +87,12 @@ ble_hs_pvcy_clear_entries(void)
uint8_t buf[BLE_HCI_CMD_HDR_LEN ];
int rc;
- rc = host_hci_cmd_build_clear_resolv_list(buf, sizeof(buf));
+ rc = ble_hs_hci_cmd_build_clear_resolv_list(buf, sizeof(buf));
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx(buf, NULL, 0, NULL);
+ rc = ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
@@ -125,15 +109,15 @@ ble_hs_pvcy_add_entry(uint8_t *addr, uint8_t addr_type, uint8_t *irk)
add.addr_type = addr_type;
memcpy(add.addr, addr, 6);
- memcpy(add.local_irk, ble_hs_pvcy_our_irk(), 16);
+ memcpy(add.local_irk, ble_hs_pvcy_irk, 16);
memcpy(add.peer_irk, irk, 16);
- rc = host_hci_cmd_build_add_to_resolv_list(&add, buf, sizeof(buf));
+ rc = ble_hs_hci_cmd_build_add_to_resolv_list(&add, buf, sizeof(buf));
if (rc != 0) {
return rc;
}
- rc = ble_hci_cmd_tx(buf, NULL, 0, NULL);
+ rc = ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
if (rc != 0) {
return rc;
}
@@ -141,73 +125,32 @@ ble_hs_pvcy_add_entry(uint8_t *addr, uint8_t addr_type, uint8_t *irk)
return 0;
}
-void
-ble_hs_pvcy_our_nrpa(uint8_t *addr)
-{
- memcpy(addr, ble_hs_pvcy_nrpa, 6);
-}
-
-int
-ble_hs_pvcy_set_our_nrpa(void)
+int
+ble_hs_pvcy_ensure_started(void)
{
int rc;
- uint8_t addr[6];
-
- rc = ble_hci_util_rand(addr, 6);
- assert(rc == 0);
- addr[5] &= ~(0xc0);
- memcpy(ble_hs_pvcy_nrpa, addr, 6);
-
- return ble_hs_util_set_random_addr(addr);
-}
-uint8_t *
-ble_hs_pvcy_our_id_addr(uint8_t *type)
-{
- if (!ble_hs_pvcy_initialized) {
- ble_hs_pvcy_set_our_id_addr(NULL);
+ if (ble_hs_pvcy_started) {
+ return 0;
}
- if (type != NULL) {
- *type = ble_hs_pvcy_id_addr_type;
- }
-
- return ble_hs_pvcy_id_addr;
-}
-
-void
-ble_hs_pvcy_set_our_id_addr(uint8_t *addr)
-{
- uint8_t random_addr[6];
- int rc;
-
- if (!ble_hs_pvcy_initialized) {
- /* Set up the periodic change of our RPA. */
- rc = ble_hs_pvcy_set_addr_timeout(ble_hs_cfg.rpa_timeout);
- assert(rc == 0);
+ /* Set up the periodic change of our RPA. */
+ rc = ble_hs_pvcy_set_addr_timeout(ble_hs_cfg.rpa_timeout);
+ if (rc != 0) {
+ return rc;
}
- if (addr != NULL) {
- memcpy(ble_hs_pvcy_id_addr, addr, 6);
- ble_hs_pvcy_id_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
- } else {
- /* Generate a new static random address. */
- ble_hs_pvcy_gen_static_random_addr(random_addr);
- rc = ble_hs_util_set_random_addr(random_addr);
- assert(rc == 0);
+ ble_hs_pvcy_started = 1;
- ble_hs_pvcy_id_addr_type = BLE_HCI_ADV_OWN_ADDR_RANDOM;
- memcpy(ble_hs_pvcy_id_addr, random_addr, 6);
- }
-
- ble_hs_pvcy_initialized = 1;
+ return 0;
}
-void
-ble_hs_pvcy_set_our_irk(uint8_t *irk)
+int
+ble_hs_pvcy_set_our_irk(const uint8_t *irk)
{
uint8_t tmp_addr[6];
uint8_t new_irk[16];
+ int rc;
memset(new_irk, 0, sizeof(new_irk));
@@ -221,25 +164,40 @@ ble_hs_pvcy_set_our_irk(uint8_t *irk)
if (memcmp(ble_hs_pvcy_irk, new_irk, 16) != 0) {
memcpy(ble_hs_pvcy_irk, new_irk, 16);
- ble_hs_pvcy_set_resolve_enabled(0);
- ble_hs_pvcy_clear_entries();
- ble_hs_pvcy_set_resolve_enabled(1);
+ rc = ble_hs_pvcy_set_resolve_enabled(0);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_hs_pvcy_clear_entries();
+ if (rc != 0) {
+ return rc;
+ }
- /* Push our identity to the controller as a keycache entry with a null
- * MAC address. The controller uses this entry to generate an RPA when
- * we do advertising with own-addr-type = rpa.
+ rc = ble_hs_pvcy_set_resolve_enabled(1);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* Push a null address identity to the controller. The controller uses
+ * this entry to generate an RPA when we do advertising with
+ * own-addr-type = rpa.
*/
memset(tmp_addr, 0, 6);
- ble_hs_pvcy_add_entry(tmp_addr, 0, ble_hs_pvcy_irk);
+ rc = ble_hs_pvcy_add_entry(tmp_addr, 0, ble_hs_pvcy_irk);
+ if (rc != 0) {
+ return rc;
+ }
}
+
+ return 0;
}
-uint8_t *
-ble_hs_pvcy_our_irk(void)
+int
+ble_hs_pvcy_our_irk(const uint8_t **out_irk)
{
- if (!ble_hs_pvcy_initialized) {
- ble_hs_pvcy_set_our_id_addr(NULL);
- }
+ /* XXX: Return error if privacy not supported. */
- return ble_hs_pvcy_irk;
+ *out_irk = ble_hs_pvcy_irk;
+ return 0;
}
diff --git a/net/nimble/host/src/ble_hs_pvcy_priv.h b/net/nimble/host/src/ble_hs_pvcy_priv.h
new file mode 100644
index 00000000..16ded359
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_pvcy_priv.h
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_HS_PVCY_PRIV_
+#define H_BLE_HS_PVCY_PRIV_
+
+#include <inttypes.h>
+
+int ble_hs_pvcy_set_our_irk(const uint8_t *irk);
+int ble_hs_pvcy_our_irk(const uint8_t **out_irk);
+int ble_hs_pvcy_remove_entry(uint8_t addr_type, uint8_t *addr);
+int ble_hs_pvcy_add_entry(uint8_t *addr, uint8_t addrtype, uint8_t *irk);
+int ble_hs_pvcy_ensure_started(void);
+
+#endif
diff --git a/net/nimble/host/src/ble_hs_startup.c b/net/nimble/host/src/ble_hs_startup.c
index 1973cf9a..89cbd700 100644
--- a/net/nimble/host/src/ble_hs_startup.c
+++ b/net/nimble/host/src/ble_hs_startup.c
@@ -19,7 +19,6 @@
#include <stddef.h>
#include <string.h>
-#include "host/host_hci.h"
#include "host/ble_hs.h"
#include "ble_hs_priv.h"
@@ -31,8 +30,9 @@ ble_hs_startup_le_read_sup_f_tx(void)
uint8_t ack_params_len;
int rc;
- host_hci_cmd_build_le_read_loc_supp_feat(buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, ack_params, sizeof ack_params, &ack_params_len);
+ ble_hs_hci_cmd_build_le_read_loc_supp_feat(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, ack_params, sizeof ack_params,
+ &ack_params_len);
if (rc != 0) {
return rc;
}
@@ -56,8 +56,9 @@ ble_hs_startup_le_read_buf_sz_tx(void)
uint8_t max_pkts;
int rc;
- host_hci_cmd_build_le_read_buffer_size(buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, ack_params, sizeof ack_params, &ack_params_len);
+ ble_hs_hci_cmd_build_le_read_buffer_size(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, ack_params, sizeof ack_params,
+ &ack_params_len);
if (rc != 0) {
return rc;
}
@@ -69,7 +70,7 @@ ble_hs_startup_le_read_buf_sz_tx(void)
pktlen = le16toh(ack_params + 0);
max_pkts = ack_params[2];
- rc = host_hci_set_buf_size(pktlen, max_pkts);
+ rc = ble_hs_hci_set_buf_sz(pktlen, max_pkts);
if (rc != 0) {
return rc;
}
@@ -78,6 +79,29 @@ ble_hs_startup_le_read_buf_sz_tx(void)
}
static int
+ble_hs_startup_read_bd_addr(void)
+{
+ uint8_t ack_params[BLE_HCI_IP_RD_BD_ADDR_ACK_PARAM_LEN];
+ uint8_t buf[BLE_HCI_CMD_HDR_LEN];
+ uint8_t ack_params_len;
+ int rc;
+
+ ble_hs_hci_cmd_build_read_bd_addr(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, ack_params, sizeof ack_params,
+ &ack_params_len);
+ if (rc != 0) {
+ return rc;
+ }
+
+ if (ack_params_len != sizeof ack_params) {
+ return BLE_HS_ECONTROLLER;
+ }
+
+ ble_hs_id_set_pub(ack_params);
+ return 0;
+}
+
+static int
ble_hs_startup_le_set_evmask_tx(void)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_LE_EVENT_MASK_LEN];
@@ -94,8 +118,9 @@ ble_hs_startup_le_set_evmask_tx(void)
* 0x0000000000000040 LE Data Length Change Event
* 0x0000000000000200 LE Enhanced Connection Complete Event
*/
- host_hci_cmd_build_le_set_event_mask(0x000000000000027f, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_set_event_mask(0x000000000000027f,
+ buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -151,8 +176,8 @@ ble_hs_startup_set_evmask_tx(void)
* 0x0000800000000000 Encryption Key Refresh Complete Event
* 0x2000000000000000 LE Meta-Event
*/
- host_hci_cmd_build_set_event_mask(0x20009fffffffffff, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_set_event_mask(0x20009fffffffffff, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -161,8 +186,8 @@ ble_hs_startup_set_evmask_tx(void)
* Enable the following events:
* 0x0000000000800000 Authenticated Payload Timeout Event
*/
- host_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -176,8 +201,8 @@ ble_hs_startup_reset_tx(void)
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
int rc;
- host_hci_cmd_build_reset(buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_reset(buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -200,19 +225,16 @@ ble_hs_startup_go(void)
rc = ble_hs_startup_set_evmask_tx();
if (rc != 0) {
- assert(0);
return rc;
}
rc = ble_hs_startup_le_set_evmask_tx();
if (rc != 0) {
- assert(0);
return rc;
}
rc = ble_hs_startup_le_read_buf_sz_tx();
if (rc != 0) {
- assert(0);
return rc;
}
@@ -220,13 +242,15 @@ ble_hs_startup_go(void)
rc = ble_hs_startup_le_read_sup_f_tx();
if (rc != 0) {
- assert(0);
return rc;
}
- /* XXX: Read BD_ADDR. */
- ble_hs_pvcy_set_our_id_addr(g_dev_addr);
+ rc = ble_hs_startup_read_bd_addr();
+ if (rc != 0) {
+ return rc;
+ }
+
ble_hs_pvcy_set_our_irk(NULL);
- return rc;
+ return 0;
}
diff --git a/net/nimble/host/src/ble_ibeacon.c b/net/nimble/host/src/ble_ibeacon.c
index db34dfbd..5bdb99d7 100644
--- a/net/nimble/host/src/ble_ibeacon.c
+++ b/net/nimble/host/src/ble_ibeacon.c
@@ -18,10 +18,24 @@
*/
#include <string.h>
+#include "host/ble_hs_adv.h"
#include "ble_hs_priv.h"
#define BLE_IBEACON_MFG_DATA_SIZE 25
+/**
+ * Configures the device to advertise iBeacons.
+ *
+ * @param uuid The 128-bit UUID to advertise.
+ * @param major The major version number to include in
+ * iBeacons.
+ * @param minor The minor version number to include in
+ * iBeacons.
+ *
+ * @return 0 on success;
+ * BLE_HS_EBUSY if advertising is in progress;
+ * Other nonzero on failure.
+ */
int
ble_ibeacon_set_adv_data(void *uuid128, uint16_t major, uint16_t minor)
{
@@ -47,7 +61,7 @@ ble_ibeacon_set_adv_data(void *uuid128, uint16_t major, uint16_t minor)
/** Last byte (tx power level) filled in after HCI exchange. */
- rc = ble_hci_util_read_adv_tx_pwr(&tx_pwr);
+ rc = ble_hs_hci_util_read_adv_tx_pwr(&tx_pwr);
if (rc != 0) {
return rc;
}
diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_l2cap.c
index da66bf1b..43ccd6f7 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -22,7 +22,6 @@
#include "os/os.h"
#include "nimble/ble.h"
#include "nimble/hci_common.h"
-#include "host/host_hci.h"
#include "ble_hs_priv.h"
_Static_assert(sizeof (struct ble_l2cap_hdr) == BLE_L2CAP_HDR_SZ,
@@ -79,7 +78,7 @@ ble_l2cap_chan_free(struct ble_l2cap_chan *chan)
}
uint16_t
-ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan)
+ble_l2cap_chan_mtu(const struct ble_l2cap_chan *chan)
{
uint16_t mtu;
@@ -124,7 +123,7 @@ ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, uint16_t len)
htole16(&hdr.blh_len, len);
htole16(&hdr.blh_cid, cid);
- om = os_mbuf_prepend(om, sizeof hdr);
+ om = os_mbuf_prepend_pullup(om, sizeof hdr);
if (om == NULL) {
return NULL;
}
@@ -270,33 +269,27 @@ err:
* mbuf is consumed, regardless of the outcome of the function call.
*
* @param chan The L2CAP channel to transmit over.
- * @param om The data to transmit.
+ * @param txom The data to transmit.
*
* @return 0 on success; nonzero on error.
*/
int
ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- struct os_mbuf *om)
+ struct os_mbuf *txom)
{
int rc;
- om = ble_l2cap_prepend_hdr(om, chan->blc_cid, OS_MBUF_PKTLEN(om));
- if (om == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
+ txom = ble_l2cap_prepend_hdr(txom, chan->blc_cid, OS_MBUF_PKTLEN(txom));
+ if (txom == NULL) {
+ return BLE_HS_ENOMEM;
}
- rc = host_hci_data_tx(conn, om);
- om = NULL;
+ rc = ble_hs_hci_acl_tx(conn, txom);
if (rc != 0) {
- goto err;
+ return rc;
}
return 0;
-
-err:
- os_mbuf_free_chain(om);
- return rc;
}
static void
diff --git a/net/nimble/host/src/ble_l2cap_priv.h b/net/nimble/host/src/ble_l2cap_priv.h
index 9cbf8791..ce19218e 100644
--- a/net/nimble/host/src/ble_l2cap_priv.h
+++ b/net/nimble/host/src/ble_l2cap_priv.h
@@ -57,8 +57,7 @@ extern struct os_mempool ble_l2cap_chan_pool;
typedef uint8_t ble_l2cap_chan_flags;
-typedef int ble_l2cap_rx_fn(uint16_t conn_handle,
- struct os_mbuf **om);
+typedef int ble_l2cap_rx_fn(uint16_t conn_handle, struct os_mbuf **rxom);
struct ble_l2cap_chan {
SLIST_ENTRY(ble_l2cap_chan) blc_next;
@@ -94,7 +93,7 @@ struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
struct ble_l2cap_chan *ble_l2cap_chan_alloc(void);
void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
-uint16_t ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan);
+uint16_t ble_l2cap_chan_mtu(const struct ble_l2cap_chan *chan);
int ble_l2cap_rx(struct ble_hs_conn *conn,
@@ -103,7 +102,7 @@ int ble_l2cap_rx(struct ble_hs_conn *conn,
ble_l2cap_rx_fn **out_rx_cb,
struct os_mbuf **out_rx_buf);
int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- struct os_mbuf *om);
+ struct os_mbuf *txom);
int ble_l2cap_init(void);
diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c
index 93ba2e23..a382b097 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -300,7 +300,7 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle,
l2cap_result = 0; /* Silence spurious gcc warning. */
- rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_UPDATE_REQ_SZ);
if (rc != 0) {
return rc;
}
@@ -338,18 +338,16 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle,
/* Send L2CAP response. */
ble_hs_lock();
- rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
- &conn, &chan);
- if (rc == 0) {
- if (!sig_err) {
- rc = ble_l2cap_sig_update_rsp_tx(conn, chan, hdr->identifier,
- l2cap_result);
- } else {
- ble_l2cap_sig_reject_tx(conn, chan, hdr->identifier,
- BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
- NULL, 0);
- rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
- }
+ ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+ &conn, &chan);
+ if (!sig_err) {
+ rc = ble_l2cap_sig_update_rsp_tx(conn, chan, hdr->identifier,
+ l2cap_result);
+ } else {
+ ble_l2cap_sig_reject_tx(conn, chan, hdr->identifier,
+ BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
+ NULL, 0);
+ rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
}
ble_hs_unlock();
@@ -373,7 +371,7 @@ ble_l2cap_sig_update_rsp_rx(uint16_t conn_handle,
return BLE_HS_ENOENT;
}
- rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_UPDATE_RSP_SZ);
if (rc != 0) {
cb_status = rc;
goto done;
@@ -421,11 +419,8 @@ ble_l2cap_sig_update(uint16_t conn_handle,
ble_hs_lock();
- rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
- &conn, &chan);
- if (rc != 0) {
- goto done;
- }
+ ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+ &conn, &chan);
if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
/* Only the slave can initiate the L2CAP connection update
* procedure.
@@ -479,10 +474,10 @@ ble_l2cap_sig_rx(uint16_t conn_handle, struct os_mbuf **om)
STATS_INC(ble_l2cap_stats, sig_rx);
BLE_HS_LOG(DEBUG, "L2CAP - rxed signalling msg: ");
- ble_hs_misc_log_mbuf(*om);
+ ble_hs_log_mbuf(*om);
BLE_HS_LOG(DEBUG, "\n");
- rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_HDR_SZ);
+ rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_HDR_SZ);
if (rc != 0) {
return rc;
}
@@ -499,16 +494,12 @@ ble_l2cap_sig_rx(uint16_t conn_handle, struct os_mbuf **om)
rx_cb = ble_l2cap_sig_dispatch_get(hdr.op);
if (rx_cb == NULL) {
ble_hs_lock();
- rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
- &conn, &chan);
- if (rc == 0) {
- ble_l2cap_sig_reject_tx(conn, chan, hdr.identifier,
- BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
- NULL, 0);
- rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
- } else {
- rc = BLE_HS_ENOTCONN;
- }
+ ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+ &conn, &chan);
+ ble_l2cap_sig_reject_tx(conn, chan, hdr.identifier,
+ BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
+ NULL, 0);
+ rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
ble_hs_unlock();
} else {
rc = rx_cb(conn_handle, &hdr, om);
@@ -582,7 +573,7 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list)
* be called again; currently always
* UINT32_MAX.
*/
-uint32_t
+int32_t
ble_l2cap_sig_heartbeat(void)
{
struct ble_l2cap_sig_proc_list temp_list;
@@ -596,10 +587,10 @@ ble_l2cap_sig_heartbeat(void)
/* Terminate the connection associated with each timed-out procedure. */
STAILQ_FOREACH(proc, &temp_list, next) {
STATS_INC(ble_l2cap_stats, proc_timeout);
- ble_gap_terminate(proc->conn_handle);
+ ble_gap_terminate(proc->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
- return UINT32_MAX;
+ return BLE_HS_FOREVER;
}
int
diff --git a/net/nimble/host/src/ble_l2cap_sig_cmd.c b/net/nimble/host/src/ble_l2cap_sig_cmd.c
index a93833c6..d8220322 100644
--- a/net/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/net/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -27,18 +27,21 @@ ble_l2cap_sig_init_cmd(uint8_t op, uint8_t id, uint8_t payload_len,
struct ble_l2cap_sig_hdr hdr;
struct os_mbuf *txom;
void *v;
+ int rc;
*out_om = NULL;
*out_payload_buf = NULL;
- txom = ble_hs_misc_pkthdr();
+ txom = ble_hs_mbuf_l2cap_pkt();
if (txom == NULL) {
- return BLE_HS_ENOMEM;
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
v = os_mbuf_extend(txom, BLE_L2CAP_SIG_HDR_SZ + payload_len);
if (v == NULL) {
- return BLE_HS_ENOMEM;
+ rc = BLE_HS_ENOMEM;
+ goto err;
}
hdr.op = op;
@@ -51,6 +54,10 @@ ble_l2cap_sig_init_cmd(uint8_t op, uint8_t id, uint8_t payload_len,
*out_payload_buf = (uint8_t *)v + BLE_L2CAP_SIG_HDR_SZ;
return 0;
+
+err:
+ os_mbuf_free(txom);
+ return rc;
}
static void
@@ -113,6 +120,9 @@ ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_REJECT, id,
BLE_L2CAP_SIG_REJECT_MIN_SZ + data_len, &txom,
&payload_buf);
+ if (rc != 0) {
+ return rc;
+ }
cmd.reason = reason;
ble_l2cap_sig_reject_write(payload_buf, txom->om_len, &cmd,
@@ -120,7 +130,11 @@ ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
STATS_INC(ble_l2cap_stats, sig_rx);
rc = ble_l2cap_tx(conn, chan, txom);
- return rc;
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
}
int
diff --git a/net/nimble/host/src/ble_l2cap_sig_priv.h b/net/nimble/host/src/ble_l2cap_sig_priv.h
index a561a82a..3477ee13 100644
--- a/net/nimble/host/src/ble_l2cap_sig_priv.h
+++ b/net/nimble/host/src/ble_l2cap_sig_priv.h
@@ -80,7 +80,7 @@ int ble_l2cap_sig_reject_invalid_cid_tx(struct ble_hs_conn *conn,
uint8_t id,
uint16_t src_cid, uint16_t dst_cid);
-uint32_t ble_l2cap_sig_heartbeat(void);
+int32_t ble_l2cap_sig_heartbeat(void);
struct ble_l2cap_chan *ble_l2cap_sig_create_chan(void);
int ble_l2cap_sig_init(void);
diff --git a/net/nimble/host/src/ble_sm.c b/net/nimble/host/src/ble_sm.c
index ab411731..8e07cdb0 100644
--- a/net/nimble/host/src/ble_sm.c
+++ b/net/nimble/host/src/ble_sm.c
@@ -259,7 +259,7 @@ ble_sm_gen_pair_rand(uint8_t *pair_rand)
}
#endif
- rc = ble_hci_util_rand(pair_rand, 16);
+ rc = ble_hs_hci_util_rand(pair_rand, 16);
if (rc != 0) {
return rc;
}
@@ -280,7 +280,7 @@ ble_sm_gen_ediv(uint16_t *ediv)
}
#endif
- rc = ble_hci_util_rand(ediv, sizeof *ediv);
+ rc = ble_hs_hci_util_rand(ediv, sizeof *ediv);
if (rc != 0) {
return rc;
}
@@ -301,7 +301,7 @@ ble_sm_gen_master_id_rand(uint64_t *master_id_rand)
}
#endif
- rc = ble_hci_util_rand(master_id_rand, sizeof *master_id_rand);
+ rc = ble_hs_hci_util_rand(master_id_rand, sizeof *master_id_rand);
if (rc != 0) {
return rc;
}
@@ -323,7 +323,7 @@ ble_sm_gen_ltk(struct ble_sm_proc *proc, uint8_t *ltk)
}
#endif
- rc = ble_hci_util_rand(ltk, 16);
+ rc = ble_hs_hci_util_rand(ltk, 16);
if (rc != 0) {
return rc;
}
@@ -345,7 +345,7 @@ ble_sm_gen_csrk(struct ble_sm_proc *proc, uint8_t *csrk)
}
#endif
- rc = ble_hci_util_rand(csrk, 16);
+ rc = ble_hs_hci_util_rand(csrk, 16);
if (rc != 0) {
return rc;
}
@@ -494,24 +494,7 @@ ble_sm_fill_store_value(uint8_t peer_addr_type, uint8_t *peer_addr,
}
}
-int
-ble_sm_peer_addr(struct ble_sm_proc *proc,
- uint8_t *out_type, uint8_t **out_addr)
-{
- struct ble_hs_conn *conn;
-
- conn = ble_hs_conn_find(proc->conn_handle);
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
- }
-
- *out_type = conn->bhc_addr_type;
- *out_addr = conn->bhc_addr;
-
- return 0;
-}
-
-int
+void
ble_sm_ia_ra(struct ble_sm_proc *proc,
uint8_t *out_iat, uint8_t *out_ia,
uint8_t *out_rat, uint8_t *out_ra)
@@ -519,10 +502,7 @@ ble_sm_ia_ra(struct ble_sm_proc *proc,
struct ble_hs_conn_addrs addrs;
struct ble_hs_conn *conn;
- conn = ble_hs_conn_find(proc->conn_handle);
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
- }
+ conn = ble_hs_conn_find_assert(proc->conn_handle);
ble_hs_conn_addrs(conn, &addrs);
@@ -539,8 +519,6 @@ ble_sm_ia_ra(struct ble_sm_proc *proc,
*out_rat = addrs.our_id_addr_type;
memcpy(out_ra, addrs.our_ota_addr, 6);
}
-
- return 0;
}
static void
@@ -562,8 +540,8 @@ ble_sm_persist_keys(struct ble_sm_proc *proc)
peer_addr_type = proc->peer_keys.addr_type;
memcpy(peer_addr, proc->peer_keys.addr, sizeof peer_addr);
} else {
- peer_addr_type = ble_hs_misc_addr_type_to_id(conn->bhc_addr_type);
- memcpy(peer_addr, conn->bhc_addr, sizeof peer_addr);
+ peer_addr_type = ble_hs_misc_addr_type_to_id(conn->bhc_peer_addr_type);
+ memcpy(peer_addr, conn->bhc_peer_addr, sizeof peer_addr);
}
ble_hs_unlock();
@@ -765,13 +743,16 @@ ble_sm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, void *arg)
{
ble_sm_state_fn *cb;
- BLE_HS_DBG_ASSERT(proc->state < BLE_SM_PROC_STATE_CNT);
- cb = ble_sm_state_dispatch[proc->state];
- BLE_HS_DBG_ASSERT(cb != NULL);
-
memset(res, 0, sizeof *res);
- cb(proc, res, arg);
+ if (!ble_hs_conn_exists(proc->conn_handle)) {
+ res->app_status = BLE_HS_ENOTCONN;
+ } else {
+ BLE_HS_DBG_ASSERT(proc->state < BLE_SM_PROC_STATE_CNT);
+ cb = ble_sm_state_dispatch[proc->state];
+ BLE_HS_DBG_ASSERT(cb != NULL);
+ cb(proc, res, arg);
+ }
}
void
@@ -824,9 +805,9 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
}
if (res->app_status == 0 &&
- res->passkey_action.action != BLE_SM_IOACT_NONE) {
+ res->passkey_params.action != BLE_SM_IOACT_NONE) {
- ble_gap_passkey_event(conn_handle, &res->passkey_action);
+ ble_gap_passkey_event(conn_handle, &res->passkey_params);
}
/* Persist keys if bonding has successfully completed. */
@@ -875,8 +856,8 @@ ble_sm_start_encrypt_tx(struct hci_start_encrypt *cmd)
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_START_ENCRYPT_LEN];
int rc;
- host_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
- rc = ble_hci_cmd_tx_empty_ack(buf);
+ ble_hs_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx_empty_ack(buf);
if (rc != 0) {
return rc;
}
@@ -1059,9 +1040,9 @@ ble_sm_ltk_req_reply_tx(uint16_t conn_handle, uint8_t *ltk)
cmd.conn_handle = conn_handle;
memcpy(cmd.long_term_key, ltk, 16);
- host_hci_cmd_build_le_lt_key_req_reply(&cmd, buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
- &ack_params_len);
+ ble_hs_hci_cmd_build_le_lt_key_req_reply(&cmd, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
+ &ack_params_len);
if (rc != 0) {
return rc;
}
@@ -1085,9 +1066,9 @@ ble_sm_ltk_req_neg_reply_tx(uint16_t conn_handle)
uint8_t ack_params_len;
int rc;
- host_hci_cmd_build_le_lt_key_req_neg_reply(conn_handle, buf, sizeof buf);
- rc = ble_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
- &ack_params_len);
+ ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(conn_handle, buf, sizeof buf);
+ rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
+ &ack_params_len);
if (rc != 0) {
return rc;
}
@@ -1208,13 +1189,9 @@ ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
}
if (restore) {
- conn = ble_hs_conn_find(evt->connection_handle);
- if (conn == NULL) {
- res.app_status = BLE_HS_ENOTCONN;
- } else {
- ble_hs_conn_addrs(conn, &addrs);
- memcpy(peer_id_addr, addrs.peer_id_addr, 6);
- }
+ conn = ble_hs_conn_find_assert(evt->connection_handle);
+ ble_hs_conn_addrs(conn, &addrs);
+ memcpy(peer_id_addr, addrs.peer_id_addr, 6);
}
ble_hs_unlock();
@@ -1285,7 +1262,7 @@ ble_sm_random_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_RANDOM_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_RANDOM_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1335,7 +1312,7 @@ ble_sm_confirm_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *prev;
uint8_t ioact;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CONFIRM_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CONFIRM_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1466,7 +1443,7 @@ ble_sm_pair_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
ioact = ble_sm_io_action(proc);
if (ble_sm_ioact_state(ioact) == proc->state) {
- res->passkey_action.action = ioact;
+ res->passkey_params.action = ioact;
}
}
@@ -1496,7 +1473,7 @@ ble_sm_pair_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *prev;
struct ble_hs_conn *conn;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
if (res->app_status != 0) {
return;
}
@@ -1526,11 +1503,8 @@ ble_sm_pair_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
proc->pair_req = req;
- conn = ble_hs_conn_find(proc->conn_handle);
- if (conn == NULL) {
- res->sm_err = BLE_SM_ERR_UNSPECIFIED;
- res->app_status = BLE_HS_ENOTCONN;
- } else if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
+ conn = ble_hs_conn_find_assert(proc->conn_handle);
+ if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
} else if (!ble_sm_pair_cmd_is_valid(&req)) {
@@ -1553,7 +1527,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *prev;
uint8_t ioact;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
if (res->app_status != 0) {
res->enc_cb = 1;
return;
@@ -1575,7 +1549,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
proc->state = ble_sm_state_after_pair(proc);
ioact = ble_sm_io_action(proc);
if (ble_sm_ioact_state(ioact) == proc->state) {
- res->passkey_action.action = ioact;
+ res->passkey_params.action = ioact;
}
if (ble_sm_proc_can_advance(proc)) {
res->execute = 1;
@@ -1616,7 +1590,7 @@ ble_sm_sec_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_hs_conn *conn;
int authreq_mitm;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_SEC_REQ_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_SEC_REQ_SZ);
if (res->app_status != 0) {
return;
}
@@ -1630,10 +1604,8 @@ ble_sm_sec_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
ble_hs_lock();
- conn = ble_hs_conn_find(conn_handle);
- if (conn == NULL) {
- res->app_status = BLE_HS_ENOTCONN;
- } else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
+ conn = ble_hs_conn_find_assert(conn_handle);
+ if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
} else {
@@ -1703,15 +1675,16 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
void *arg)
{
struct ble_sm_id_addr_info addr_info;
+ struct ble_hs_conn_addrs addrs;
struct ble_sm_sign_info sign_info;
struct ble_sm_master_id master_id;
struct ble_sm_enc_info enc_info;
struct ble_sm_id_info id_info;
+ struct ble_hs_conn *conn;
uint8_t init_key_dist;
uint8_t resp_key_dist;
uint8_t our_key_dist;
- uint8_t *our_id_addr;
- uint8_t *irk;
+ const uint8_t *irk;
int rc;
ble_sm_key_dist(proc, &init_key_dist, &resp_key_dist);
@@ -1754,7 +1727,10 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
if (our_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
/* Send identity information. */
- irk = ble_hs_pvcy_our_irk();
+ rc = ble_hs_pvcy_our_irk(&irk);
+ if (rc != 0) {
+ goto err;
+ }
memcpy(id_info.irk, irk, 16);
@@ -1765,8 +1741,11 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
proc->our_keys.irk_valid = 1;
/* Send identity address information. */
- our_id_addr = ble_hs_pvcy_our_id_addr(&addr_info.addr_type);
- memcpy(addr_info.bd_addr, our_id_addr, 6);
+ conn = ble_hs_conn_find_assert(proc->conn_handle);
+
+ ble_hs_conn_addrs(conn, &addrs);
+ addr_info.addr_type = addrs.our_id_addr_type;
+ memcpy(addr_info.bd_addr, addrs.our_id_addr, 6);
rc = ble_sm_id_addr_info_tx(proc->conn_handle, &addr_info);
if (rc != 0) {
goto err;
@@ -1830,7 +1809,7 @@ ble_sm_enc_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ENC_INFO_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ENC_INFO_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1866,7 +1845,7 @@ ble_sm_master_id_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_MASTER_ID_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_MASTER_ID_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1903,7 +1882,7 @@ ble_sm_id_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ID_INFO_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ID_INFO_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1940,7 +1919,7 @@ ble_sm_id_addr_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ID_ADDR_INFO_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ID_ADDR_INFO_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -1978,7 +1957,7 @@ ble_sm_sign_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_SIGN_INFO_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_SIGN_INFO_SZ);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -2019,12 +1998,12 @@ ble_sm_fail_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
res->enc_cb = 1;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_FAIL_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_FAIL_SZ);
if (res->app_status == 0) {
ble_sm_pair_fail_parse((*om)->om_data, (*om)->om_len, &cmd);
BLE_SM_LOG_CMD(0, "fail", conn_handle, ble_sm_pair_fail_log, &cmd);
- res->app_status = BLE_HS_SM_THEM_ERR(cmd.reason);
+ res->app_status = BLE_HS_SM_PEER_ERR(cmd.reason);
}
}
@@ -2044,7 +2023,7 @@ ble_sm_fail_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
* be called again; currently always
* UINT32_MAX.
*/
-uint32_t
+int32_t
ble_sm_heartbeat(void)
{
struct ble_sm_proc_list exp_list;
@@ -2067,7 +2046,7 @@ ble_sm_heartbeat(void)
ble_sm_proc_free(proc);
}
- return UINT32_MAX;
+ return BLE_HS_FOREVER;
}
/**
@@ -2153,7 +2132,7 @@ ble_sm_slave_initiate(uint16_t conn_handle)
* Initiates the encryption procedure for the specified connection.
*/
int
-ble_sm_enc_initiate(uint16_t conn_handle, uint8_t *ltk, uint16_t ediv,
+ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, uint16_t ediv,
uint64_t rand_val, int auth)
{
struct ble_sm_result res;
@@ -2281,17 +2260,12 @@ ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey)
switch (pkey->action) {
case BLE_SM_IOACT_OOB:
- if (pkey->oob == NULL) {
- res.app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_OOB);
- res.sm_err = BLE_SM_ERR_OOB;
- } else {
- proc->flags |= BLE_SM_PROC_F_IO_INJECTED;
- memcpy(proc->tk, pkey->oob, 16);
- if ((proc->flags & BLE_SM_PROC_F_INITIATOR) ||
- (proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO)) {
+ proc->flags |= BLE_SM_PROC_F_IO_INJECTED;
+ memcpy(proc->tk, pkey->oob, 16);
+ if ((proc->flags & BLE_SM_PROC_F_INITIATOR) ||
+ (proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO)) {
- res.execute = 1;
- }
+ res.execute = 1;
}
break;
diff --git a/net/nimble/host/src/ble_sm_alg.c b/net/nimble/host/src/ble_sm_alg.c
index 1885d098..66f86dc6 100644
--- a/net/nimble/host/src/ble_sm_alg.c
+++ b/net/nimble/host/src/ble_sm_alg.c
@@ -40,39 +40,11 @@ static const uint32_t ble_sm_alg_dbg_priv_key[8] = {
0xa3c55f38, 0x3f49f6d4
};
-static const uint8_t ble_sm_alg_dbg_pub_key[64] = {
- 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
- 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
- 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
- 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
- 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
- 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
- 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
- 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
-};
-
-static const uint8_t ble_sm_alg_dbg_f4[16] = {
- 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1,
- 0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2,
-};
-
-static const uint8_t ble_sm_alg_dbg_f5[32] = {
- 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd,
- 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29,
- 0x38, 0x0a, 0x75, 0x94, 0xb5, 0x22, 0x05, 0x98,
- 0x23, 0xcd, 0xd7, 0x69, 0x11, 0x79, 0x86, 0x69,
-};
-
-static const uint8_t ble_sm_alg_dbg_f6[16] = {
- 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2,
- 0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3,
-};
-
static void
-ble_sm_alg_log_buf(char *name, uint8_t *buf, int len)
+ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len)
{
BLE_HS_LOG(DEBUG, " %s=", name);
- ble_hs_misc_log_flat_buf(buf, len);
+ ble_hs_log_flat_buf(buf, len);
BLE_HS_LOG(DEBUG, "\n");
}
@@ -166,13 +138,13 @@ ble_sm_alg_s1(uint8_t *k, uint8_t *r1, uint8_t *r2, uint8_t *out)
}
BLE_HS_LOG(DEBUG, "ble_sm_alg_s1()\n k=");
- ble_hs_misc_log_flat_buf(k, 16);
+ ble_hs_log_flat_buf(k, 16);
BLE_HS_LOG(DEBUG, "\n r1=");
- ble_hs_misc_log_flat_buf(r1, 16);
+ ble_hs_log_flat_buf(r1, 16);
BLE_HS_LOG(DEBUG, "\n r2=");
- ble_hs_misc_log_flat_buf(r2, 16);
+ ble_hs_log_flat_buf(r2, 16);
BLE_HS_LOG(DEBUG, "\n out=");
- ble_hs_misc_log_flat_buf(out, 16);
+ ble_hs_log_flat_buf(out, 16);
BLE_HS_LOG(DEBUG, "\n");
return 0;
@@ -189,18 +161,18 @@ ble_sm_alg_c1(uint8_t *k, uint8_t *r,
int rc;
BLE_HS_LOG(DEBUG, "ble_sm_alg_c1()\n k=");
- ble_hs_misc_log_flat_buf(k, 16);
+ ble_hs_log_flat_buf(k, 16);
BLE_HS_LOG(DEBUG, "\n r=");
- ble_hs_misc_log_flat_buf(r, 16);
+ ble_hs_log_flat_buf(r, 16);
BLE_HS_LOG(DEBUG, "\n iat=%d rat=%d", iat, rat);
BLE_HS_LOG(DEBUG, "\n ia=");
- ble_hs_misc_log_flat_buf(ia, 6);
+ ble_hs_log_flat_buf(ia, 6);
BLE_HS_LOG(DEBUG, "\n ra=");
- ble_hs_misc_log_flat_buf(ra, 6);
+ ble_hs_log_flat_buf(ra, 6);
BLE_HS_LOG(DEBUG, "\n preq=");
- ble_hs_misc_log_flat_buf(preq, 7);
+ ble_hs_log_flat_buf(preq, 7);
BLE_HS_LOG(DEBUG, "\n pres=");
- ble_hs_misc_log_flat_buf(pres, 7);
+ ble_hs_log_flat_buf(pres, 7);
/* pres, preq, rat and iat are concatenated to generate p1 */
p1[0] = iat;
@@ -209,7 +181,7 @@ ble_sm_alg_c1(uint8_t *k, uint8_t *r,
memcpy(p1 + 9, pres, 7);
BLE_HS_LOG(DEBUG, "\n p1=");
- ble_hs_misc_log_flat_buf(p1, sizeof p1);
+ ble_hs_log_flat_buf(p1, sizeof p1);
/* c1 = e(k, e(k, r XOR p1) XOR p2) */
@@ -228,7 +200,7 @@ ble_sm_alg_c1(uint8_t *k, uint8_t *r,
memset(p2 + 12, 0, 4);
BLE_HS_LOG(DEBUG, "\n p2=");
- ble_hs_misc_log_flat_buf(p2, sizeof p2);
+ ble_hs_log_flat_buf(p2, sizeof p2);
ble_sm_alg_xor_128(out_enc_data, p2, out_enc_data);
@@ -239,7 +211,7 @@ ble_sm_alg_c1(uint8_t *k, uint8_t *r,
}
BLE_HS_LOG(DEBUG, "\n out_enc_data=");
- ble_hs_misc_log_flat_buf(out_enc_data, 16);
+ ble_hs_log_flat_buf(out_enc_data, 16);
rc = 0;
@@ -257,11 +229,11 @@ ble_sm_alg_f4(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t z,
int rc;
BLE_HS_LOG(DEBUG, "ble_sm_alg_f4()\n u=");
- ble_hs_misc_log_flat_buf(u, 32);
+ ble_hs_log_flat_buf(u, 32);
BLE_HS_LOG(DEBUG, "\n v=");
- ble_hs_misc_log_flat_buf(v, 32);
+ ble_hs_log_flat_buf(v, 32);
BLE_HS_LOG(DEBUG, "\n x=");
- ble_hs_misc_log_flat_buf(x, 16);
+ ble_hs_log_flat_buf(x, 16);
BLE_HS_LOG(DEBUG, "\n z=0x%02x\n", z);
/*
@@ -287,7 +259,7 @@ ble_sm_alg_f4(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t z,
swap_in_place(out_enc_data, 16);
BLE_HS_LOG(DEBUG, " out_enc_data=");
- ble_hs_misc_log_flat_buf(out_enc_data, 16);
+ ble_hs_log_flat_buf(out_enc_data, 16);
BLE_HS_LOG(DEBUG, "\n");
return 0;
@@ -362,9 +334,10 @@ ble_sm_alg_f5(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t a1t,
}
int
-ble_sm_alg_f6(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t *r,
- uint8_t *iocap, uint8_t a1t, uint8_t *a1,
- uint8_t a2t, uint8_t *a2, uint8_t *check)
+ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2,
+ const uint8_t *r, const uint8_t *iocap, uint8_t a1t,
+ const uint8_t *a1, uint8_t a2t, const uint8_t *a2,
+ uint8_t *check)
{
uint8_t ws[16];
uint8_t m[65];
@@ -409,7 +382,8 @@ ble_sm_alg_f6(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t *r,
}
int
-ble_sm_alg_g2(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t *y, uint32_t *passkey)
+ble_sm_alg_g2(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t *y,
+ uint32_t *passkey)
{
uint8_t m[80], xs[16];
int rc;
@@ -475,7 +449,7 @@ ble_sm_alg_gen_key_pair(void *pub, uint32_t *priv)
int rc;
do {
- rc = ble_hci_util_rand(random, sizeof random);
+ rc = ble_hs_hci_util_rand(random, sizeof random);
if (rc != 0) {
return rc;
}
diff --git a/net/nimble/host/src/ble_sm_cmd.c b/net/nimble/host/src/ble_sm_cmd.c
index 3d506b24..02831374 100644
--- a/net/nimble/host/src/ble_sm_cmd.c
+++ b/net/nimble/host/src/ble_sm_cmd.c
@@ -38,13 +38,14 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
STATS_INC(ble_l2cap_stats, sm_tx);
- rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
- &conn, &chan);
- if (rc == 0) {
- rc = ble_l2cap_tx(conn, chan, txom);
+ ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
+ &conn, &chan);
+ rc = ble_l2cap_tx(conn, chan, txom);
+ if (rc != 0) {
+ return rc;
}
- return rc;
+ return 0;
}
static int
@@ -53,7 +54,7 @@ ble_sm_init_req(uint16_t initial_sz, struct os_mbuf **out_txom)
void *buf;
int rc;
- *out_txom = ble_hs_misc_pkthdr();
+ *out_txom = ble_hs_mbuf_l2cap_pkt();
if (*out_txom == NULL) {
rc = BLE_HS_ENOMEM;
goto err;
@@ -148,8 +149,7 @@ ble_sm_pair_cmd_tx(uint16_t conn_handle, int is_req,
rc = ble_sm_init_req(BLE_SM_PAIR_CMD_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_pair_cmd_write(txom->om_data, txom->om_len, is_req, cmd);
@@ -158,11 +158,11 @@ ble_sm_pair_cmd_tx(uint16_t conn_handle, int is_req,
BLE_HS_DBG_ASSERT(ble_sm_pair_cmd_is_valid(cmd));
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
@@ -204,29 +204,27 @@ ble_sm_pair_confirm_tx(uint16_t conn_handle, struct ble_sm_pair_confirm *cmd)
struct os_mbuf *txom;
int rc;
-
rc = ble_sm_init_req(BLE_SM_PAIR_CONFIRM_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_pair_confirm_write(txom->om_data, txom->om_len, cmd);
BLE_SM_LOG_CMD(1, "confirm", conn_handle, ble_sm_pair_confirm_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_pair_confirm_log(struct ble_sm_pair_confirm *cmd)
{
BLE_HS_LOG(DEBUG, "value=");
- ble_hs_misc_log_flat_buf(cmd->value, sizeof cmd->value);
+ ble_hs_log_flat_buf(cmd->value, sizeof cmd->value);
}
void
@@ -260,26 +258,25 @@ ble_sm_pair_random_tx(uint16_t conn_handle, struct ble_sm_pair_random *cmd)
rc = ble_sm_init_req(BLE_SM_PAIR_RANDOM_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_pair_random_write(txom->om_data, txom->om_len, cmd);
BLE_SM_LOG_CMD(1, "random", conn_handle, ble_sm_pair_random_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_pair_random_log(struct ble_sm_pair_random *cmd)
{
BLE_HS_LOG(DEBUG, "value=");
- ble_hs_misc_log_flat_buf(cmd->value, sizeof cmd->value);
+ ble_hs_log_flat_buf(cmd->value, sizeof cmd->value);
}
void
@@ -318,8 +315,7 @@ ble_sm_pair_fail_tx(uint16_t conn_handle, uint8_t reason)
rc = ble_sm_init_req(BLE_SM_PAIR_FAIL_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
cmd.reason = reason;
@@ -328,11 +324,11 @@ ble_sm_pair_fail_tx(uint16_t conn_handle, uint8_t reason)
BLE_SM_LOG_CMD(1, "fail", conn_handle, ble_sm_pair_fail_log, &cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
@@ -368,8 +364,7 @@ ble_sm_enc_info_tx(uint16_t conn_handle, struct ble_sm_enc_info *cmd)
rc = ble_sm_init_req(BLE_SM_ENC_INFO_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_enc_info_write(txom->om_data, txom->om_len, cmd);
@@ -377,18 +372,18 @@ ble_sm_enc_info_tx(uint16_t conn_handle, struct ble_sm_enc_info *cmd)
BLE_SM_LOG_CMD(1, "enc info", conn_handle, ble_sm_enc_info_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_enc_info_log(struct ble_sm_enc_info *cmd)
{
BLE_HS_LOG(DEBUG, "ltk=");
- ble_hs_misc_log_flat_buf(cmd->ltk, sizeof cmd->ltk);
+ ble_hs_log_flat_buf(cmd->ltk, sizeof cmd->ltk);
}
void
@@ -424,8 +419,7 @@ ble_sm_master_id_tx(uint16_t conn_handle, struct ble_sm_master_id *cmd)
rc = ble_sm_init_req(BLE_SM_MASTER_ID_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
txom->om_data[0] = BLE_SM_OP_MASTER_ID;
@@ -435,11 +429,11 @@ ble_sm_master_id_tx(uint16_t conn_handle, struct ble_sm_master_id *cmd)
BLE_SM_LOG_CMD(1, "master id", conn_handle, ble_sm_master_id_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
@@ -481,25 +475,24 @@ ble_sm_id_info_tx(uint16_t conn_handle, struct ble_sm_id_info *cmd)
rc = ble_sm_init_req(BLE_SM_ID_INFO_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_id_info_write(txom->om_data, txom->om_len, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_id_info_log(struct ble_sm_id_info *cmd)
{
BLE_HS_LOG(DEBUG, "irk=");
- ble_hs_misc_log_flat_buf(cmd->irk, sizeof cmd->irk);
+ ble_hs_log_flat_buf(cmd->irk, sizeof cmd->irk);
}
void
@@ -537,18 +530,17 @@ ble_sm_id_addr_info_tx(uint16_t conn_handle, struct ble_sm_id_addr_info *cmd)
rc = ble_sm_init_req(BLE_SM_ID_ADDR_INFO_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_id_addr_info_write(txom->om_data, txom->om_len, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
@@ -587,25 +579,24 @@ ble_sm_sign_info_tx(uint16_t conn_handle, struct ble_sm_sign_info *cmd)
rc = ble_sm_init_req(BLE_SM_SIGN_INFO_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_sign_info_write(txom->om_data, txom->om_len, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_sign_info_log(struct ble_sm_sign_info *cmd)
{
BLE_HS_LOG(DEBUG, "sig_key=");
- ble_hs_misc_log_flat_buf(cmd->sig_key, sizeof cmd->sig_key);
+ ble_hs_log_flat_buf(cmd->sig_key, sizeof cmd->sig_key);
}
void
@@ -640,8 +631,7 @@ ble_sm_sec_req_tx(uint16_t conn_handle, struct ble_sm_sec_req *cmd)
rc = ble_sm_init_req(BLE_SM_SEC_REQ_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
ble_sm_sec_req_write(txom->om_data, txom->om_len, cmd);
@@ -649,11 +639,11 @@ ble_sm_sec_req_tx(uint16_t conn_handle, struct ble_sm_sec_req *cmd)
BLE_SM_LOG_CMD(1, "sec req", conn_handle, ble_sm_sec_req_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
@@ -704,8 +694,7 @@ ble_sm_public_key_tx(uint16_t conn_handle, struct ble_sm_public_key *cmd)
rc = ble_sm_init_req(BLE_SM_PUBLIC_KEY_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
rc = ble_sm_public_key_write(txom->om_data, txom->om_len, cmd);
@@ -714,20 +703,20 @@ ble_sm_public_key_tx(uint16_t conn_handle, struct ble_sm_public_key *cmd)
BLE_SM_LOG_CMD(1, "public key", conn_handle, ble_sm_public_key_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_public_key_log(struct ble_sm_public_key *cmd)
{
BLE_HS_LOG(DEBUG, "x=");
- ble_hs_misc_log_flat_buf(cmd->x, sizeof cmd->x);
+ ble_hs_log_flat_buf(cmd->x, sizeof cmd->x);
BLE_HS_LOG(DEBUG, "y=");
- ble_hs_misc_log_flat_buf(cmd->y, sizeof cmd->y);
+ ble_hs_log_flat_buf(cmd->y, sizeof cmd->y);
}
void
@@ -765,8 +754,7 @@ ble_sm_dhkey_check_tx(uint16_t conn_handle, struct ble_sm_dhkey_check *cmd)
rc = ble_sm_init_req(BLE_SM_DHKEY_CHECK_SZ, &txom);
if (rc != 0) {
- rc = BLE_HS_ENOMEM;
- goto done;
+ return BLE_HS_ENOMEM;
}
rc = ble_sm_dhkey_check_write(txom->om_data, txom->om_len, cmd);
@@ -775,18 +763,18 @@ ble_sm_dhkey_check_tx(uint16_t conn_handle, struct ble_sm_dhkey_check *cmd)
BLE_SM_LOG_CMD(1, "dhkey check", conn_handle, ble_sm_dhkey_check_log, cmd);
rc = ble_sm_tx(conn_handle, txom);
- txom = NULL;
+ if (rc != 0) {
+ return rc;
+ }
-done:
- os_mbuf_free_chain(txom);
- return rc;
+ return 0;
}
void
ble_sm_dhkey_check_log(struct ble_sm_dhkey_check *cmd)
{
BLE_HS_LOG(DEBUG, "value=");
- ble_hs_misc_log_flat_buf(cmd->value, sizeof cmd->value);
+ ble_hs_log_flat_buf(cmd->value, sizeof cmd->value);
}
#endif
diff --git a/net/nimble/host/src/ble_sm_lgcy.c b/net/nimble/host/src/ble_sm_lgcy.c
index d844a6f1..7b1673c7 100644
--- a/net/nimble/host/src/ble_sm_lgcy.c
+++ b/net/nimble/host/src/ble_sm_lgcy.c
@@ -109,12 +109,7 @@ ble_sm_lgcy_confirm_prepare_args(struct ble_sm_proc *proc,
uint8_t *iat, uint8_t *rat,
uint8_t *ia, uint8_t *ra)
{
- int rc;
-
- rc = ble_sm_ia_ra(proc, iat, ia, rat, ra);
- if (rc != 0) {
- return rc;
- }
+ ble_sm_ia_ra(proc, iat, ia, rat, ra);
memcpy(k, proc->tk, sizeof proc->tk);
diff --git a/net/nimble/host/src/ble_sm_priv.h b/net/nimble/host/src/ble_sm_priv.h
index 2543514f..d15afbc2 100644
--- a/net/nimble/host/src/ble_sm_priv.h
+++ b/net/nimble/host/src/ble_sm_priv.h
@@ -276,7 +276,7 @@ struct ble_sm_proc {
struct ble_sm_result {
int app_status;
uint8_t sm_err;
- struct ble_gap_passkey_action passkey_action;
+ struct ble_gap_passkey_params passkey_params;
void *state_arg;
unsigned execute:1;
unsigned enc_cb:1;
@@ -386,9 +386,10 @@ int ble_sm_alg_g2(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t *y,
int ble_sm_alg_f5(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t a1t,
uint8_t *a1, uint8_t a2t, uint8_t *a2,
uint8_t *mackey, uint8_t *ltk);
-int ble_sm_alg_f6(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t *r,
- uint8_t *iocap, uint8_t a1t, uint8_t *a1,
- uint8_t a2t, uint8_t *a2, uint8_t *check);
+int ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2,
+ const uint8_t *r, const uint8_t *iocap, uint8_t a1t,
+ const uint8_t *a1, uint8_t a2t, const uint8_t *a2,
+ uint8_t *check);
int ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y,
uint32_t *our_priv_key, void *out_dhkey);
int ble_sm_alg_gen_key_pair(void *pub, uint32_t *priv);
@@ -416,11 +417,12 @@ void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc,
struct ble_sm_result *res,
void *arg);
void ble_sm_sc_public_key_rx(uint16_t conn_handle, uint8_t op,
- struct os_mbuf **om, struct ble_sm_result *res);
+ struct os_mbuf **rxom, struct ble_sm_result *res);
void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc,
struct ble_sm_result *res, void *arg);
void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, uint8_t op,
- struct os_mbuf **om, struct ble_sm_result *res);
+ struct os_mbuf **rxom,
+ struct ble_sm_result *res);
void ble_sm_sc_init(void);
#else
#define ble_sm_sc_io_action(proc) (BLE_SM_IOACT_NONE)
@@ -446,17 +448,15 @@ int ble_sm_ioact_state(uint8_t action);
int ble_sm_proc_can_advance(struct ble_sm_proc *proc);
void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res);
void ble_sm_confirm_advance(struct ble_sm_proc *proc);
-int ble_sm_peer_addr(struct ble_sm_proc *proc,
- uint8_t *out_type, uint8_t **out_addr);
-int ble_sm_ia_ra(struct ble_sm_proc *proc,
- uint8_t *out_iat, uint8_t *out_ia,
- uint8_t *out_rat, uint8_t *out_ra);
+void ble_sm_ia_ra(struct ble_sm_proc *proc,
+ uint8_t *out_iat, uint8_t *out_ia,
+ uint8_t *out_rat, uint8_t *out_ra);
-uint32_t ble_sm_heartbeat(void);
+int32_t ble_sm_heartbeat(void);
void ble_sm_connection_broken(uint16_t conn_handle);
int ble_sm_pair_initiate(uint16_t conn_handle);
int ble_sm_slave_initiate(uint16_t conn_handle);
-int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t *ltk,
+int ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk,
uint16_t ediv, uint64_t rand_val, int auth);
int ble_sm_init(void);
@@ -471,7 +471,7 @@ int ble_sm_init(void);
#define ble_sm_ltk_req_rx(evt) ((void)(evt))
#define ble_sm_enc_key_refresh_rx(evt) ((void)(evt))
-#define ble_sm_heartbeat() UINT32_MAX
+#define ble_sm_heartbeat() BLE_HS_FOREVER
#define ble_sm_connection_broken(conn_handle)
#define ble_sm_pair_initiate(conn_handle) BLE_HS_ENOTSUP
#define ble_sm_slave_initiate(conn_handle) BLE_HS_ENOTSUP
diff --git a/net/nimble/host/src/ble_sm_sc.c b/net/nimble/host/src/ble_sm_sc.c
index fc568044..e82ba72f 100644
--- a/net/nimble/host/src/ble_sm_sc.c
+++ b/net/nimble/host/src/ble_sm_sc.c
@@ -153,10 +153,10 @@ ble_sm_sc_ensure_keys_generated(void)
}
BLE_HS_LOG(DEBUG, "our pubkey=");
- ble_hs_misc_log_flat_buf(&ble_sm_sc_pub_key, 64);
+ ble_hs_log_flat_buf(&ble_sm_sc_pub_key, 64);
BLE_HS_LOG(DEBUG, "\n");
BLE_HS_LOG(DEBUG, "our privkey=");
- ble_hs_misc_log_flat_buf(&ble_sm_sc_priv_key, 32);
+ ble_hs_log_flat_buf(&ble_sm_sc_priv_key, 32);
BLE_HS_LOG(DEBUG, "\n");
return 0;
@@ -221,7 +221,7 @@ ble_sm_sc_gen_ri(struct ble_sm_proc *proc)
return 0;
case BLE_SM_PAIR_ALG_OOB:
- rc = ble_hci_util_rand(&proc->ri, 1);
+ rc = ble_hs_hci_util_rand(&proc->ri, 1);
return rc;
default:
@@ -280,7 +280,7 @@ ble_sm_sc_gen_numcmp(struct ble_sm_proc *proc, struct ble_sm_result *res)
pkb = ble_sm_sc_pub_key.u8;
}
res->app_status = ble_sm_alg_g2(pka, pkb, proc->randm, proc->rands,
- &res->passkey_action.numcmp);
+ &res->passkey_params.numcmp);
if (res->app_status != 0) {
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->enc_cb = 1;
@@ -341,7 +341,7 @@ ble_sm_sc_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
if (ble_sm_ioact_state(ioact) == proc->state &&
!(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
- res->passkey_action.action = ioact;
+ res->passkey_params.action = ioact;
BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
ble_sm_sc_gen_numcmp(proc, res);
}
@@ -363,7 +363,7 @@ ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
ble_sm_sc_responder_verifies_random(proc)) {
BLE_HS_LOG(DEBUG, "tk=");
- ble_hs_misc_log_flat_buf(proc->tk, 32);
+ ble_hs_log_flat_buf(proc->tk, 32);
BLE_HS_LOG(DEBUG, "\n");
rc = ble_sm_alg_f4(proc->pub_key_peer.x, ble_sm_sc_pub_key.u8,
@@ -386,14 +386,7 @@ ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
}
/* Calculate the mac key and ltk. */
- rc = ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
- if (rc != 0) {
- res->app_status = rc;
- res->sm_err = BLE_SM_ERR_UNSPECIFIED;
- res->enc_cb = 1;
- return;
- }
-
+ ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
rc = ble_sm_alg_f5(proc->dhkey, proc->randm, proc->rands,
iat, ia, rat, ra, proc->mackey, proc->ltk);
if (rc != 0) {
@@ -423,7 +416,7 @@ ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
if (ble_sm_ioact_state(ioact) == proc->state &&
!(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
- res->passkey_action.action = ioact;
+ res->passkey_params.action = ioact;
BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
ble_sm_sc_gen_numcmp(proc, res);
} else {
@@ -457,14 +450,14 @@ ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
return;
}
- ioact = ble_sm_sc_io_action(proc);
- if (ble_sm_ioact_state(ioact) == BLE_SM_PROC_STATE_CONFIRM) {
- res->passkey_action.action = ioact;
- }
-
if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
proc->state = BLE_SM_PROC_STATE_CONFIRM;
+ ioact = ble_sm_sc_io_action(proc);
+ if (ble_sm_ioact_state(ioact) == proc->state) {
+ res->passkey_params.action = ioact;
+ }
+
if (ble_sm_proc_can_advance(proc) &&
!ble_sm_sc_initiator_txes_confirm(proc)) {
@@ -480,9 +473,10 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_public_key cmd;
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
+ uint8_t ioact;
int rc;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PUBLIC_KEY_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PUBLIC_KEY_SZ);
if (res->app_status != 0) {
res->enc_cb = 1;
return;
@@ -518,6 +512,11 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
proc->state = BLE_SM_PROC_STATE_CONFIRM;
+ ioact = ble_sm_sc_io_action(proc);
+ if (ble_sm_ioact_state(ioact) == proc->state) {
+ res->passkey_params.action = ioact;
+ }
+
if (ble_sm_proc_can_advance(proc) &&
ble_sm_sc_initiator_txes_confirm(proc)) {
@@ -531,28 +530,23 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
ble_hs_unlock();
}
-static int
+static void
ble_sm_sc_dhkey_addrs(struct ble_sm_proc *proc,
uint8_t *out_our_id_addr_type,
- uint8_t **out_our_ota_addr,
+ const uint8_t **out_our_ota_addr,
uint8_t *out_peer_id_addr_type,
- uint8_t **out_peer_ota_addr)
+ const uint8_t **out_peer_ota_addr)
{
struct ble_hs_conn_addrs addrs;
struct ble_hs_conn *conn;
- conn = ble_hs_conn_find(proc->conn_handle);
- if (conn == NULL) {
- return BLE_HS_ENOTCONN;
- }
+ conn = ble_hs_conn_find_assert(proc->conn_handle);
ble_hs_conn_addrs(conn, &addrs);
*out_our_id_addr_type = addrs.our_id_addr_type;
*out_our_ota_addr = addrs.our_ota_addr;
*out_peer_id_addr_type = addrs.peer_id_addr_type;
*out_peer_ota_addr = addrs.peer_ota_addr;
-
- return 0;
}
static void
@@ -569,8 +563,8 @@ ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
void *arg)
{
struct ble_sm_dhkey_check cmd;
- uint8_t *our_ota_addr;
- uint8_t *peer_ota_addr;
+ const uint8_t *our_ota_addr;
+ const uint8_t *peer_ota_addr;
uint8_t peer_id_addr_type;
uint8_t our_id_addr_type;
uint8_t iocap[3];
@@ -582,12 +576,9 @@ ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
ble_sm_sc_dhkey_check_iocap(&proc->pair_rsp, iocap);
}
- rc = ble_sm_sc_dhkey_addrs(proc,
- &our_id_addr_type, &our_ota_addr,
- &peer_id_addr_type, &peer_ota_addr);
- if (rc != 0) {
- goto err;
- }
+ ble_sm_sc_dhkey_addrs(proc,
+ &our_id_addr_type, &our_ota_addr,
+ &peer_id_addr_type, &peer_ota_addr);
rc = ble_sm_alg_f6(proc->mackey, ble_sm_our_pair_rand(proc),
ble_sm_peer_pair_rand(proc), proc->tk, iocap,
@@ -621,8 +612,8 @@ ble_sm_dhkey_check_process(struct ble_sm_proc *proc,
struct ble_sm_result *res)
{
uint8_t exp_value[16];
- uint8_t *peer_ota_addr;
- uint8_t *our_ota_addr;
+ const uint8_t *peer_ota_addr;
+ const uint8_t *our_ota_addr;
uint8_t peer_id_addr_type;
uint8_t our_id_addr_type;
uint8_t iocap[3];
@@ -634,19 +625,13 @@ ble_sm_dhkey_check_process(struct ble_sm_proc *proc,
ble_sm_sc_dhkey_check_iocap(&proc->pair_req, iocap);
}
- res->app_status = ble_sm_sc_dhkey_addrs(proc,
- &our_id_addr_type,
- &our_ota_addr,
- &peer_id_addr_type,
- &peer_ota_addr);
- if (res->app_status != 0) {
- res->sm_err = BLE_SM_ERR_UNSPECIFIED;
- res->enc_cb = 1;
- return;
- }
-
+ ble_sm_sc_dhkey_addrs(proc,
+ &our_id_addr_type,
+ &our_ota_addr,
+ &peer_id_addr_type,
+ &peer_ota_addr);
BLE_HS_LOG(DEBUG, "tk=");
- ble_hs_misc_log_flat_buf(proc->tk, 32);
+ ble_hs_log_flat_buf(proc->tk, 32);
BLE_HS_LOG(DEBUG, "\n");
res->app_status = ble_sm_alg_f6(proc->mackey,
@@ -693,7 +678,7 @@ ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
struct ble_sm_proc *proc;
struct ble_sm_proc *prev;
- res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_DHKEY_CHECK_SZ);
+ res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_DHKEY_CHECK_SZ);
if (res->app_status != 0) {
res->enc_cb = 1;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
diff --git a/net/nimble/host/src/ble_uuid.c b/net/nimble/host/src/ble_uuid.c
index ec015286..805cf497 100644
--- a/net/nimble/host/src/ble_uuid.c
+++ b/net/nimble/host/src/ble_uuid.c
@@ -34,15 +34,19 @@ static uint8_t ble_uuid_base[16] = {
* Attempts to convert the supplied 128-bit UUID into its shortened 16-bit
* form.
*
- * @return Positive 16-bit unsigned integer on
+ * @param uuid128 The 128-bit UUID to attempt to convert.
+ * This must point to 16 contiguous bytes.
+ *
+ * @return A positive 16-bit unsigned integer on
* success;
- * 0 if the UUID could not be converted.
+ * 0 if the UUID cannot be represented in 16
+ * bits.
*/
uint16_t
-ble_uuid_128_to_16(void *uuid128)
+ble_uuid_128_to_16(const void *uuid128)
{
+ const uint8_t *u8ptr;
uint16_t uuid16;
- uint8_t *u8ptr;
int rc;
u8ptr = uuid128;
@@ -68,8 +72,19 @@ ble_uuid_128_to_16(void *uuid128)
return uuid16;
}
+/**
+ * Expands a 16-bit UUID into its 128-bit form.
+ *
+ * @param uuid16 The 16-bit UUID to convert.
+ * @param out_uuid128 On success, the resulting 128-bit UUID gets
+ * written here.
+ *
+ * @return 0 on success;
+ * BLE_HS_EINVAL if uuid16 is not a valid 16-bit
+ * UUID.
+ */
int
-ble_uuid_16_to_128(uint16_t uuid16, void *uuid128)
+ble_uuid_16_to_128(uint16_t uuid16, void *out_uuid128)
{
uint8_t *u8ptr;
@@ -77,7 +92,7 @@ ble_uuid_16_to_128(uint16_t uuid16, void *uuid128)
return BLE_HS_EINVAL;
}
- u8ptr = uuid128;
+ u8ptr = out_uuid128;
memcpy(u8ptr, ble_uuid_base, 16);
htole16(u8ptr + 12, uuid16);
@@ -86,7 +101,7 @@ ble_uuid_16_to_128(uint16_t uuid16, void *uuid128)
}
int
-ble_uuid_append(struct os_mbuf *om, void *uuid128)
+ble_uuid_append(struct os_mbuf *om, const void *uuid128)
{
uint16_t uuid16;
void *buf;
diff --git a/net/nimble/host/src/ble_uuid_priv.h b/net/nimble/host/src/ble_uuid_priv.h
new file mode 100644
index 00000000..a1f1bd49
--- /dev/null
+++ b/net/nimble/host/src/ble_uuid_priv.h
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_UUID_PRIV_
+#define H_BLE_UUID_PRIV_
+
+struct os_mbuf;
+
+int ble_uuid_append(struct os_mbuf *om, const void *uuid128);
+int ble_uuid_extract(struct os_mbuf *om, int off, void *uuid128);
+
+#endif
diff --git a/net/nimble/host/src/test/ble_att_clt_test.c b/net/nimble/host/src/test/ble_att_clt_test.c
index dcb402e6..14d66f62 100644
--- a/net/nimble/host/src/test/ble_att_clt_test.c
+++ b/net/nimble/host/src/test/ble_att_clt_test.c
@@ -63,12 +63,14 @@ ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle,
struct ble_att_write_req *req,
void *value, int value_len, int is_req)
{
+ struct os_mbuf *om;
int rc;
+ om = ble_hs_test_util_om_from_flat(value, value_len);
if (is_req) {
- rc = ble_att_clt_tx_write_req(conn_handle, req, value, value_len);
+ rc = ble_att_clt_tx_write_req(conn_handle, req, om);
} else {
- rc = ble_att_clt_tx_write_cmd(conn_handle, req, value, value_len);
+ rc = ble_att_clt_tx_write_cmd(conn_handle, req, om);
}
TEST_ASSERT(rc == 0);
}
@@ -212,8 +214,8 @@ ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
req.bapc_handle = handle;
req.bapc_offset = offset;
- rc = ble_att_clt_tx_prep_write(conn_handle, &req, attr_data,
- attr_data_len);
+ om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+ rc = ble_att_clt_tx_prep_write(conn_handle, &req, om);
TEST_ASSERT(rc == 0);
ble_hs_test_util_tx_all();
@@ -259,18 +261,36 @@ ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
int status)
{
struct ble_att_prep_write_cmd req;
+ struct os_mbuf *om;
uint16_t conn_handle;
int rc;
conn_handle = ble_att_clt_test_misc_init();
+ om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+
req.bapc_handle = handle;
req.bapc_offset = offset;
- rc = ble_att_clt_tx_prep_write(conn_handle, &req, attr_data,
- attr_data_len);
+ rc = ble_att_clt_tx_prep_write(conn_handle, &req, om);
TEST_ASSERT(rc == status);
}
+static void
+ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle, uint16_t mtu, int status)
+{
+ struct ble_att_mtu_cmd req;
+ int rc;
+
+ req.bamc_mtu = mtu;
+ rc = ble_att_clt_tx_mtu(conn_handle, &req);
+ TEST_ASSERT(rc == status);
+
+ if (rc == 0) {
+ ble_hs_test_util_verify_tx_mtu_cmd(1, mtu);
+ }
+}
+
+
TEST_CASE(ble_att_clt_test_tx_write)
{
ble_att_clt_test_case_tx_write_req_or_cmd(0);
@@ -408,7 +428,8 @@ TEST_CASE(ble_att_clt_test_rx_read_mult)
htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
rc = ble_hs_test_util_l2cap_rx_payload_flat(
- conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_READ_MULT_RSP_BASE_SZ + 2);
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_READ_MULT_RSP_BASE_SZ + 2);
TEST_ASSERT(rc == 0);
/*** Larger response. */
@@ -416,12 +437,14 @@ TEST_CASE(ble_att_clt_test_rx_read_mult)
htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2, 43);
htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 4, 91);
rc = ble_hs_test_util_l2cap_rx_payload_flat(
- conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_READ_MULT_RSP_BASE_SZ + 6);
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_READ_MULT_RSP_BASE_SZ + 6);
TEST_ASSERT(rc == 0);
/*** Zero-length response. */
rc = ble_hs_test_util_l2cap_rx_payload_flat(
- conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_READ_MULT_RSP_BASE_SZ + 0);
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_READ_MULT_RSP_BASE_SZ + 0);
TEST_ASSERT(rc == 0);
}
@@ -502,8 +525,24 @@ TEST_CASE(ble_att_clt_test_tx_exec_write)
TEST_ASSERT(rc == BLE_HS_EINVAL);
}
+TEST_CASE(ble_att_clt_test_tx_mtu)
+{
+ uint16_t conn_handle;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ ble_att_clt_test_misc_tx_mtu(conn_handle, 50, 0);
+
+ /*** Error: repeated sends. */
+ ble_att_clt_test_misc_tx_mtu(conn_handle, 50, BLE_HS_EALREADY);
+ ble_att_clt_test_misc_tx_mtu(conn_handle, 60, BLE_HS_EALREADY);
+}
+
TEST_SUITE(ble_att_clt_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_att_clt_test_tx_find_info();
ble_att_clt_test_rx_find_info();
ble_att_clt_test_tx_read();
@@ -516,6 +555,7 @@ TEST_SUITE(ble_att_clt_suite)
ble_att_clt_test_tx_prep_write();
ble_att_clt_test_rx_prep_write();
ble_att_clt_test_tx_exec_write();
+ ble_att_clt_test_tx_mtu();
}
int
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 e6f8bdbd..52a56694 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -27,33 +27,32 @@
#include "ble_hs_test_util.h"
static uint8_t *ble_att_svr_test_attr_r_1;
-static int ble_att_svr_test_attr_r_1_len;
+static uint16_t ble_att_svr_test_attr_r_1_len;
static uint8_t *ble_att_svr_test_attr_r_2;
-static int ble_att_svr_test_attr_r_2_len;
+static uint16_t ble_att_svr_test_attr_r_2_len;
static uint8_t ble_att_svr_test_attr_w_1[1024];
-static int ble_att_svr_test_attr_w_1_len;
+static uint16_t 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_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 uint16_t ble_att_svr_test_attr_n_len;
static int
-ble_att_svr_test_misc_gap_cb(int event,
- struct ble_gap_conn_ctxt *ctxt, void *arg)
+ble_att_svr_test_misc_gap_cb(struct ble_gap_event *event, void *arg)
{
- switch (event) {
- case BLE_GAP_EVENT_NOTIFY:
- ble_att_svr_test_n_conn_handle = ctxt->desc->conn_handle;
- ble_att_svr_test_n_attr_handle = ctxt->notify.attr_handle;
- TEST_ASSERT_FATAL(ctxt->notify.attr_len <=
+ switch (event->type) {
+ case BLE_GAP_EVENT_NOTIFY_RX:
+ ble_att_svr_test_n_conn_handle = event->notify_rx.conn_handle;
+ ble_att_svr_test_n_attr_handle = event->notify_rx.attr_handle;
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(event->notify_rx.om) <=
sizeof ble_att_svr_test_attr_n);
- ble_att_svr_test_attr_n_len = ctxt->notify.attr_len;
- memcpy(ble_att_svr_test_attr_n, ctxt->notify.attr_data,
- ctxt->notify.attr_len);
+ ble_att_svr_test_attr_n_len = OS_MBUF_PKTLEN(event->notify_rx.om);
+ os_mbuf_copydata(event->notify_rx.om, 0, ble_att_svr_test_attr_n_len,
+ ble_att_svr_test_attr_n);
break;
default:
@@ -100,18 +99,17 @@ ble_att_svr_test_misc_init(uint16_t mtu)
static int
ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
- void *arg)
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
{
- if (ctxt->offset > ble_att_svr_test_attr_r_1_len) {
- return BLE_ATT_ERR_INVALID_OFFSET;
- }
-
switch (op) {
case BLE_ATT_ACCESS_OP_READ:
- ctxt->attr_data = ble_att_svr_test_attr_r_1 + ctxt->offset;
- ctxt->data_len = ble_att_svr_test_attr_r_1_len - ctxt->offset;
+ if (offset > ble_att_svr_test_attr_r_1_len) {
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+
+ os_mbuf_append(*om, ble_att_svr_test_attr_r_1 + offset,
+ ble_att_svr_test_attr_r_1_len - offset);
return 0;
default:
@@ -121,18 +119,18 @@ ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
static int
ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
- void *arg)
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
{
- if (ctxt->offset > ble_att_svr_test_attr_r_2_len) {
- return BLE_ATT_ERR_INVALID_OFFSET;
- }
switch (op) {
case BLE_ATT_ACCESS_OP_READ:
- ctxt->attr_data = ble_att_svr_test_attr_r_2 + ctxt->offset;
- ctxt->data_len = ble_att_svr_test_attr_r_2_len - ctxt->offset;
+ if (offset > ble_att_svr_test_attr_r_2_len) {
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+
+ os_mbuf_append(*om, ble_att_svr_test_attr_r_2 + offset,
+ ble_att_svr_test_attr_r_2_len - offset);
return 0;
default:
@@ -145,11 +143,15 @@ ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
static int
ble_att_svr_test_misc_attr_fn_r_group(uint16_t conn_handle,
- uint16_t attr_handle, uint8_t *uuid128,
+ uint16_t attr_handle,
uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint16_t offset,
+ struct os_mbuf **om,
void *arg)
{
+ uint8_t *src;
+ int rc;
+
/* Service 0x1122 from 1 to 5 */
/* Service 0x2233 from 6 to 10 */
/* Service 010203...0f from 11 to 24 */
@@ -190,11 +192,14 @@ ble_att_svr_test_misc_attr_fn_r_group(uint16_t conn_handle,
TEST_ASSERT_FATAL(attr_handle >= 1 &&
attr_handle <= BLE_ATT_SVR_TEST_LAST_ATTR);
- ctxt->attr_data = vals + attr_handle;
- if (memcmp(ctxt->attr_data + 2, zeros, 14) == 0) {
- ctxt->data_len = 2;
+ src = &vals[attr_handle][0];
+ if (memcmp(src + 2, zeros, 14) == 0) {
+ rc = os_mbuf_append(*om, src, 2);
} else {
- ctxt->data_len = 16;
+ rc = os_mbuf_append(*om, src, 16);
+ }
+ if (rc != 0) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
}
return 0;
@@ -282,14 +287,14 @@ ble_att_svr_test_misc_register_group_attrs(void)
static int
ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
- void *arg)
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
{
switch (op) {
case BLE_ATT_ACCESS_OP_WRITE:
- memcpy(ble_att_svr_test_attr_w_1, ctxt->attr_data, ctxt->data_len);
- ble_att_svr_test_attr_w_1_len = ctxt->data_len;
+ os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+ ble_att_svr_test_attr_w_1);
+ ble_att_svr_test_attr_w_1_len = OS_MBUF_PKTLEN(*om);
return 0;
default:
@@ -299,14 +304,14 @@ ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
static int
ble_att_svr_test_misc_attr_fn_w_2(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
- void *arg)
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
{
switch (op) {
case BLE_ATT_ACCESS_OP_WRITE:
- memcpy(ble_att_svr_test_attr_w_2, ctxt->attr_data, ctxt->data_len);
- ble_att_svr_test_attr_w_2_len = ctxt->data_len;
+ os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+ ble_att_svr_test_attr_w_2);
+ ble_att_svr_test_attr_w_2_len = OS_MBUF_PKTLEN(*om);
return 0;
default:
@@ -314,6 +319,15 @@ ble_att_svr_test_misc_attr_fn_w_2(uint16_t conn_handle, uint16_t attr_handle,
}
}
+static int
+ble_att_svr_test_misc_attr_fn_w_fail(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+}
+
static void
ble_att_svr_test_misc_verify_w_1(void *data, int data_len)
{
@@ -329,55 +343,6 @@ ble_att_svr_test_misc_verify_w_2(void *data, int data_len)
}
static void
-ble_att_svr_test_misc_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
- uint8_t error_code)
-{
- struct ble_att_error_rsp rsp;
- struct os_mbuf *om;
- uint8_t buf[BLE_ATT_ERROR_RSP_SZ];
- int rc;
-
- ble_hs_test_util_tx_all();
-
- om = ble_hs_test_util_prev_tx_dequeue();
-
- rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
- TEST_ASSERT(rc == 0);
-
- ble_att_error_rsp_parse(buf, sizeof buf, &rsp);
-
- TEST_ASSERT(rsp.baep_req_op == req_op);
- TEST_ASSERT(rsp.baep_handle == handle);
- TEST_ASSERT(rsp.baep_error_code == error_code);
-}
-
-static void
-ble_att_svr_test_misc_verify_tx_read_rsp(uint8_t *attr_data, int attr_len)
-{
- struct os_mbuf *om;
- uint8_t u8;
- int rc;
- int i;
-
- ble_hs_test_util_tx_all();
-
- om = ble_hs_test_util_prev_tx_dequeue();
-
- rc = os_mbuf_copydata(om, 0, 1, &u8);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(u8 == BLE_ATT_OP_READ_RSP);
-
- for (i = 0; i < attr_len; i++) {
- rc = os_mbuf_copydata(om, i + 1, 1, &u8);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(u8 == attr_data[i]);
- }
-
- rc = os_mbuf_copydata(om, i + 1, 1, &u8);
- TEST_ASSERT(rc != 0);
-}
-
-static void
ble_att_svr_test_misc_verify_tx_read_blob_rsp(uint8_t *attr_data, int attr_len)
{
struct os_mbuf *om;
@@ -431,18 +396,17 @@ ble_att_svr_test_misc_rx_read_mult_req(uint16_t conn_handle,
}
static void
-ble_att_svr_test_misc_verify_tx_read_mult_rsp(uint16_t conn_handle,
- struct ble_gatt_attr *attrs,
- int num_attrs)
+ble_att_svr_test_misc_verify_tx_read_mult_rsp(
+ uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs,
+ int num_attrs)
{
struct ble_l2cap_chan *chan;
struct os_mbuf *om;
+ uint16_t attr_len;
uint16_t mtu;
- uint8_t *attr_value;
uint8_t u8;
int rc;
int off;
- int ii;
int i;
ble_hs_test_util_tx_all();
@@ -464,25 +428,21 @@ ble_att_svr_test_misc_verify_tx_read_mult_rsp(uint16_t conn_handle,
off = 1;
for (i = 0; i < num_attrs; i++) {
- attr_value = attrs[i].value;
+ attr_len = min(attrs[i].value_len, mtu - off);
- for (ii = 0; ii < attrs[i].value_len && off < mtu; ii++) {
- rc = os_mbuf_copydata(om, off, 1, &u8);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(u8 == attr_value[ii]);
+ rc = os_mbuf_cmpf(om, off, attrs[i].value, attr_len);
+ TEST_ASSERT(rc == 0);
- off++;
- }
+ off += attr_len;
}
- rc = os_mbuf_copydata(om, off, 1, &u8);
- TEST_ASSERT(rc != 0);
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == off);
}
static void
-ble_att_svr_test_misc_verify_all_read_mult(uint16_t conn_handle,
- struct ble_gatt_attr *attrs,
- int num_attrs)
+ble_att_svr_test_misc_verify_all_read_mult(
+ uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs,
+ int num_attrs)
{
uint16_t handles[256];
int i;
@@ -498,23 +458,6 @@ ble_att_svr_test_misc_verify_all_read_mult(uint16_t conn_handle,
attrs, num_attrs);
}
-
-static void
-ble_att_svr_test_misc_verify_tx_write_rsp(void)
-{
- struct os_mbuf *om;
- uint8_t u8;
- int rc;
-
- ble_hs_test_util_tx_all();
-
- om = ble_hs_test_util_prev_tx_dequeue();
-
- rc = os_mbuf_copydata(om, 0, 1, &u8);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(u8 == BLE_ATT_OP_WRITE_RSP);
-}
-
static void
ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle)
{
@@ -532,7 +475,7 @@ ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle)
rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
TEST_ASSERT(rc == 0);
- ble_att_mtu_cmd_parse(buf, sizeof buf, &rsp);
+ ble_att_mtu_rsp_parse(buf, sizeof buf, &rsp);
ble_hs_lock();
rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
@@ -836,6 +779,7 @@ ble_att_svr_test_misc_mtu_exchange(uint16_t my_mtu, uint16_t peer_sent,
TEST_ASSERT(chan->blc_peer_mtu == peer_actual);
TEST_ASSERT(ble_l2cap_chan_mtu(chan) == chan_mtu);
ble_hs_unlock();
+
}
static void
@@ -861,7 +805,7 @@ ble_att_svr_test_misc_prep_write(uint16_t conn_handle, uint16_t attr_handle,
data, data_len);
} else {
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_PREP_WRITE_REQ,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_PREP_WRITE_REQ,
attr_handle, error_code);
}
}
@@ -885,7 +829,7 @@ ble_att_svr_test_misc_exec_write(uint16_t conn_handle, uint8_t flags,
ble_att_svr_test_misc_verify_tx_exec_write_rsp();
} else {
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_EXEC_WRITE_REQ,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_EXEC_WRITE_REQ,
error_handle, error_code);
}
}
@@ -1022,12 +966,11 @@ TEST_CASE(ble_att_svr_test_read)
{
struct ble_att_read_req req;
struct ble_hs_conn *conn;
+ struct os_mbuf *om;
uint16_t conn_handle;
- uint16_t attr_len;
uint8_t buf[BLE_ATT_READ_REQ_SZ];
uint8_t uuid_sec[16] = {1};
uint8_t uuid[16] = {0};
- void *attr_data;
int rc;
conn_handle = ble_att_svr_test_misc_init(0);
@@ -1039,7 +982,7 @@ TEST_CASE(ble_att_svr_test_read)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ, 0,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ, 0,
BLE_ATT_ERR_INVALID_HANDLE);
/*** Successful read. */
@@ -1054,7 +997,7 @@ TEST_CASE(ble_att_svr_test_read)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
- ble_att_svr_test_misc_verify_tx_read_rsp(
+ ble_hs_test_util_verify_tx_read_rsp(
ble_att_svr_test_attr_r_1, ble_att_svr_test_attr_r_1_len);
/*** Partial read. */
@@ -1068,8 +1011,8 @@ TEST_CASE(ble_att_svr_test_read)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
- ble_att_svr_test_misc_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
- BLE_ATT_MTU_DFLT - 1);
+ ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
+ BLE_ATT_MTU_DFLT - 1);
/*** Read requires encryption. */
/* Insufficient authentication. */
@@ -1082,16 +1025,18 @@ TEST_CASE(ble_att_svr_test_read)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
- TEST_ASSERT(rc == BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHENT));
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ,
+ TEST_ASSERT(rc == BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN));
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ,
req.barq_handle,
- BLE_ATT_ERR_INSUFFICIENT_AUTHENT);
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
/* Security check bypassed for local reads. */
- rc = ble_att_svr_read_local(req.barq_handle, &attr_data, &attr_len);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(attr_len == ble_att_svr_test_attr_r_1_len);
- TEST_ASSERT(attr_data == ble_att_svr_test_attr_r_1);
+ rc = ble_att_svr_read_local(req.barq_handle, &om);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(os_mbuf_cmpf(om, 0, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len) == 0);
+ os_mbuf_free_chain(om);
/* Ensure no response got sent. */
ble_hs_test_util_tx_all();
@@ -1106,8 +1051,9 @@ TEST_CASE(ble_att_svr_test_read)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
- ble_att_svr_test_misc_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
- BLE_ATT_MTU_DFLT - 1);
+ ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
+ BLE_ATT_MTU_DFLT - 1);
+
}
TEST_CASE(ble_att_svr_test_read_blob)
@@ -1128,14 +1074,15 @@ TEST_CASE(ble_att_svr_test_read_blob)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ, 0,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ, 0,
BLE_ATT_ERR_INVALID_HANDLE);
- /*** Short read failure. */
+
+ /*** Successful partial read. */
ble_att_svr_test_attr_r_1 =
(uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,
22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39};
- ble_att_svr_test_attr_r_1_len = BLE_ATT_MTU_DFLT - 3;
+ ble_att_svr_test_attr_r_1_len = 40;
rc = ble_att_svr_register(uuid, HA_FLAG_PERM_RW, &req.babq_handle,
ble_att_svr_test_misc_attr_fn_r_1, NULL);
TEST_ASSERT(rc == 0);
@@ -1144,18 +1091,6 @@ TEST_CASE(ble_att_svr_test_read_blob)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
- TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ,
- req.babq_handle,
- BLE_ATT_ERR_ATTR_NOT_LONG);
-
- /*** Successful partial read. */
- ble_att_svr_test_attr_r_1_len = 40;
-
- ble_att_read_blob_req_write(buf, sizeof buf, &req);
-
- rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
- buf, sizeof buf);
TEST_ASSERT(rc == 0);
ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
BLE_ATT_MTU_DFLT - 1);
@@ -1180,73 +1115,84 @@ TEST_CASE(ble_att_svr_test_read_blob)
TEST_ASSERT(rc == 0);
ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
0);
+
}
TEST_CASE(ble_att_svr_test_read_mult)
{
- struct ble_gatt_attr attr1;
- struct ble_gatt_attr attr2;
uint16_t conn_handle;
int rc;
conn_handle = ble_att_svr_test_misc_init(0);
- attr1.value = (uint8_t[]){ 1, 2, 3, 4 };
- attr1.value_len = 4;
- ble_att_svr_test_attr_r_1 = attr1.value;
- ble_att_svr_test_attr_r_1_len = attr1.value_len;
+ struct ble_hs_test_util_flat_attr attrs[2] = {
+ {
+ .handle = 0,
+ .offset = 0,
+ .value = { 1, 2, 3, 4 },
+ .value_len = 4,
+ },
+ {
+ .handle = 0,
+ .offset = 0,
+ .value = { 2, 3, 4, 5, 6 },
+ .value_len = 5,
+ },
+ };
+
+ ble_att_svr_test_attr_r_1 = attrs[0].value;
+ ble_att_svr_test_attr_r_1_len = attrs[0].value_len;
+ ble_att_svr_test_attr_r_2 = attrs[1].value;
+ ble_att_svr_test_attr_r_2_len = attrs[1].value_len;
+
rc = ble_att_svr_register(BLE_UUID16(0x1111), HA_FLAG_PERM_RW,
- &attr1.handle,
+ &attrs[0].handle,
ble_att_svr_test_misc_attr_fn_r_1, NULL);
TEST_ASSERT(rc == 0);
- attr2.value = (uint8_t[]){ 2, 3, 4, 5, 6 };
- attr2.value_len = 5;
- ble_att_svr_test_attr_r_2 = attr2.value;
- ble_att_svr_test_attr_r_2_len = attr2.value_len;
rc = ble_att_svr_register(BLE_UUID16(0x2222), HA_FLAG_PERM_RW,
- &attr2.handle,
+ &attrs[1].handle,
ble_att_svr_test_misc_attr_fn_r_2, NULL);
TEST_ASSERT(rc == 0);
/*** Single nonexistent attribute. */
ble_att_svr_test_misc_rx_read_mult_req(
conn_handle, ((uint16_t[]){ 100 }), 1, 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ,
100, BLE_ATT_ERR_INVALID_HANDLE);
/*** Single attribute. */
- ble_att_svr_test_misc_verify_all_read_mult(conn_handle, &attr1, 1);
+ ble_att_svr_test_misc_verify_all_read_mult(conn_handle, &attrs[0], 1);
/*** Two attributes. */
- ble_att_svr_test_misc_verify_all_read_mult(
- conn_handle, ((struct ble_gatt_attr[]) { attr1, attr2 }), 2);
+ ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
/*** Reverse order. */
- ble_att_svr_test_misc_verify_all_read_mult(
- conn_handle, ((struct ble_gatt_attr[]) { attr2, attr1 }), 2);
+ ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
/*** Second attribute nonexistent; verify only error txed. */
ble_att_svr_test_misc_rx_read_mult_req(
- conn_handle, ((uint16_t[]){ attr1.handle, 100 }), 2, 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ,
+ conn_handle, ((uint16_t[]){ attrs[0].handle, 100 }), 2, 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ,
100, BLE_ATT_ERR_INVALID_HANDLE);
/*** Response too long; verify only MTU bytes sent. */
- attr1.value =
- (uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
- attr1.value_len = 20;
- ble_att_svr_test_attr_r_1 = attr1.value;
- ble_att_svr_test_attr_r_1_len = attr1.value_len;
-
- attr2.value =
- (uint8_t[]){22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39};
- attr2.value_len = 20;
- ble_att_svr_test_attr_r_2 = attr2.value;
- ble_att_svr_test_attr_r_2_len = attr2.value_len;
-
- ble_att_svr_test_misc_verify_all_read_mult(
- conn_handle, ((struct ble_gatt_attr[]) { attr1, attr2 }), 2);
+ attrs[0].value_len = 20;
+ memcpy(attrs[0].value,
+ ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}),
+ attrs[0].value_len);
+ ble_att_svr_test_attr_r_1_len = attrs[0].value_len;
+
+ attrs[1].value_len = 20;
+ memcpy(attrs[1].value,
+ ((uint8_t[]){
+ 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
+ }),
+ attrs[1].value_len);
+ ble_att_svr_test_attr_r_2_len = attrs[1].value_len;
+
+ ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
+
}
TEST_CASE(ble_att_svr_test_write)
@@ -1270,7 +1216,7 @@ TEST_CASE(ble_att_svr_test_write)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_WRITE_REQ, 0, BLE_ATT_ERR_INVALID_HANDLE);
/*** Write not permitted if non-local. */
@@ -1286,12 +1232,12 @@ TEST_CASE(ble_att_svr_test_write)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == BLE_HS_ENOTSUP);
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
req.bawq_handle,
BLE_ATT_ERR_WRITE_NOT_PERMITTED);
/* Local write (success). */
- rc = ble_att_svr_write_local(req.bawq_handle, buf, sizeof buf);
+ rc = ble_hs_test_util_write_local_flat(req.bawq_handle, buf, sizeof buf);
TEST_ASSERT(rc == 0);
/* Ensure no response got sent. */
@@ -1310,7 +1256,7 @@ TEST_CASE(ble_att_svr_test_write)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
- ble_att_svr_test_misc_verify_tx_write_rsp();
+ ble_hs_test_util_verify_tx_write_rsp();
/*** Write requires encryption. */
/* Insufficient authentication. */
@@ -1325,13 +1271,13 @@ TEST_CASE(ble_att_svr_test_write)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
- TEST_ASSERT(rc == BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHENT));
- ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
+ TEST_ASSERT(rc == BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN));
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
req.bawq_handle,
- BLE_ATT_ERR_INSUFFICIENT_AUTHENT);
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
/* Security check bypassed for local writes. */
- rc = ble_att_svr_write_local(req.bawq_handle, buf, sizeof buf);
+ rc = ble_hs_test_util_write_local_flat(req.bawq_handle, buf, sizeof buf);
TEST_ASSERT(rc == 0);
/* Ensure no response got sent. */
@@ -1347,7 +1293,7 @@ TEST_CASE(ble_att_svr_test_write)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
- ble_att_svr_test_misc_verify_tx_write_rsp();
+ ble_hs_test_util_verify_tx_write_rsp();
}
TEST_CASE(ble_att_svr_test_find_info)
@@ -1377,7 +1323,7 @@ TEST_CASE(ble_att_svr_test_find_info)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_INFO_REQ, 0, BLE_ATT_ERR_INVALID_HANDLE);
/*** Start handle > end handle. */
@@ -1389,7 +1335,7 @@ TEST_CASE(ble_att_svr_test_find_info)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_INFO_REQ, 101, BLE_ATT_ERR_INVALID_HANDLE);
/*** No attributes. */
@@ -1401,7 +1347,7 @@ TEST_CASE(ble_att_svr_test_find_info)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND);
/*** Range too late. */
@@ -1417,7 +1363,7 @@ TEST_CASE(ble_att_svr_test_find_info)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND);
/*** One 128-bit entry. */
@@ -1501,6 +1447,7 @@ TEST_CASE(ble_att_svr_test_find_info)
}, {
.handle = 0,
} }));
+
}
TEST_CASE(ble_att_svr_test_find_type_value)
@@ -1543,7 +1490,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 0,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1556,7 +1503,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 101,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1569,7 +1516,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 200,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -1586,7 +1533,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 200,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -1701,6 +1648,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
}, {
.first = 0,
} }));
+
}
static void
@@ -1724,7 +1672,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_TYPE_REQ, 0,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1739,7 +1687,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_TYPE_REQ, 101,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1754,7 +1702,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_TYPE_REQ, 1,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -1770,7 +1718,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_TYPE_REQ, 200,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -1907,6 +1855,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
}, {
.handle = 0,
} }));
+
}
TEST_CASE(ble_att_svr_test_read_type)
@@ -1935,7 +1884,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_GROUP_TYPE_REQ, 0,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1950,7 +1899,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_GROUP_TYPE_REQ, 101,
BLE_ATT_ERR_INVALID_HANDLE);
@@ -1964,7 +1913,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_GROUP_TYPE_REQ, 110,
BLE_ATT_ERR_UNSUPPORTED_GROUP);
@@ -1979,7 +1928,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_GROUP_TYPE_REQ, 1,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -1995,7 +1944,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc != 0);
- ble_att_svr_test_misc_verify_tx_err_rsp(
+ ble_hs_test_util_verify_tx_err_rsp(
BLE_ATT_OP_READ_GROUP_TYPE_REQ, 200,
BLE_ATT_ERR_ATTR_NOT_FOUND);
@@ -2086,28 +2035,47 @@ TEST_CASE(ble_att_svr_test_read_group_type)
}, {
.start_handle = 0,
} }));
+
}
TEST_CASE(ble_att_svr_test_prep_write)
{
+ struct ble_hs_conn *conn;
uint16_t conn_handle;
int i;
static uint8_t data[1024];
- conn_handle = ble_att_svr_test_misc_init(200);
+ conn_handle = ble_att_svr_test_misc_init(205);
/* Initialize some attribute data. */
for (i = 0; i < sizeof data; i++) {
data[i] = i;
}
- /* Register two attributes. */
+ /* Register two writable attributes. */
ble_att_svr_test_misc_register_uuid16(0x1234, HA_FLAG_PERM_RW, 1,
ble_att_svr_test_misc_attr_fn_w_1);
ble_att_svr_test_misc_register_uuid16(0x8989, HA_FLAG_PERM_RW, 2,
ble_att_svr_test_misc_attr_fn_w_2);
+ /* 3: not writable. */
+ ble_att_svr_test_misc_register_uuid16(0xabab, BLE_ATT_F_READ, 3,
+ ble_att_svr_test_misc_attr_fn_r_1);
+ /* 4: Encryption required. */
+ ble_att_svr_test_misc_register_uuid16(
+ 0xabac, BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_ENC, 4,
+ ble_att_svr_test_misc_attr_fn_w_1);
+
+ /* 5: Encryption+authentication required. */
+ ble_att_svr_test_misc_register_uuid16(
+ 0xabad, BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_ENC | BLE_ATT_F_WRITE_AUTHEN,
+ 5, ble_att_svr_test_misc_attr_fn_w_1);
+
+ /* 6: Write callback always fails. */
+ ble_att_svr_test_misc_register_uuid16(
+ 0xabae, BLE_ATT_F_WRITE, 6, ble_att_svr_test_misc_attr_fn_w_fail);
+
/*** Empty write succeeds. */
ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_CONFIRM,
0, 0);
@@ -2119,6 +2087,28 @@ TEST_CASE(ble_att_svr_test_prep_write)
ble_att_svr_test_misc_prep_write(conn_handle, 53525, 0, data, 10,
BLE_ATT_ERR_INVALID_HANDLE);
+ /*** Failure due to write-not-permitted. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 3, 0, data, 35,
+ BLE_ATT_ERR_WRITE_NOT_PERMITTED);
+
+ /*** Failure due to insufficient authentication (encryption required). */
+ ble_att_svr_test_misc_prep_write(conn_handle, 4, 0, data, 1,
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
+
+ /*** Encrypt connection; ensure previous prep write now succeeds. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.encrypted = 1;
+ ble_hs_unlock();
+
+ ble_att_svr_test_misc_prep_write(conn_handle, 4, 0, data, 1, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, 0, 0, 0);
+
+ /*** Failure due to insufficient authentication (not authenticated). */
+ ble_att_svr_test_misc_prep_write(conn_handle, 5, 0, data, 35,
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
+
/*** Failure for write starting at nonzero offset. */
ble_att_svr_test_misc_prep_write(conn_handle, 1, 1, data, 10, 0);
ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_CONFIRM,
@@ -2195,6 +2185,13 @@ TEST_CASE(ble_att_svr_test_prep_write)
0, 0);
ble_att_svr_test_misc_verify_w_1(data, 12);
ble_att_svr_test_misc_verify_w_2(data, 61);
+
+ /*** Fail due to attribute callback error. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 6, 0, data, 35, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 6, 35, data + 35, 43, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 6, 78, data + 78, 1, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_CONFIRM,
+ BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN, 6);
}
TEST_CASE(ble_att_svr_test_notify)
@@ -2217,6 +2214,7 @@ TEST_CASE(ble_att_svr_test_notify)
/* Attribute handle of 0. */
ble_att_svr_test_misc_verify_notify(conn_handle, 0,
(uint8_t[]) { 1, 2, 3 }, 3, 0);
+
}
TEST_CASE(ble_att_svr_test_indicate)
@@ -2239,10 +2237,20 @@ TEST_CASE(ble_att_svr_test_indicate)
/* Attribute handle of 0. */
ble_att_svr_test_misc_verify_indicate(conn_handle, 0,
(uint8_t[]) { 1, 2, 3 }, 3, 0);
+
}
TEST_SUITE(ble_att_svr_suite)
{
+ /* When checking for mbuf leaks, ensure no stale prep entries. */
+ static struct ble_hs_test_util_mbuf_params mbuf_params = {
+ .prev_tx = 1,
+ .rx_queue = 1,
+ .prep_list = 0,
+ };
+
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, &mbuf_params);
+
ble_att_svr_test_mtu();
ble_att_svr_test_read();
ble_att_svr_test_read_blob();
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
index fcaba400..5dd6532b 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -22,18 +22,18 @@
#include "testutil/testutil.h"
#include "nimble/ble.h"
#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
-static int ble_gap_test_conn_event;
+static struct ble_gap_event ble_gap_test_event;
static int ble_gap_test_conn_status;
static struct ble_gap_conn_desc ble_gap_test_conn_desc;
static void *ble_gap_test_conn_arg;
static struct ble_gap_upd_params ble_gap_test_conn_peer_params;
static struct ble_gap_upd_params ble_gap_test_conn_self_params;
-static int ble_gap_test_disc_event;
-static int ble_gap_test_disc_status;
+static int ble_gap_test_disc_event_type;
static struct ble_gap_disc_desc ble_gap_test_disc_desc;
static void *ble_gap_test_disc_arg;
@@ -54,13 +54,12 @@ ble_gap_test_util_update_in_progress(uint16_t conn_handle)
static void
ble_gap_test_util_reset_cb_info(void)
{
- ble_gap_test_conn_event = -1;
+ memset(&ble_gap_test_event, 0xff, sizeof ble_gap_test_event);
ble_gap_test_conn_status = -1;
memset(&ble_gap_test_conn_desc, 0xff, sizeof ble_gap_test_conn_desc);
ble_gap_test_conn_arg = (void *)-1;
- ble_gap_test_disc_event = -1;
- ble_gap_test_disc_status = -1;
+ ble_gap_test_disc_event_type = -1;
memset(&ble_gap_test_disc_desc, 0xff, sizeof ble_gap_test_disc_desc);
ble_gap_test_disc_arg = (void *)-1;
}
@@ -69,47 +68,55 @@ static void
ble_gap_test_util_init(void)
{
ble_hs_test_util_init();
+ ble_hs_test_util_set_static_rnd_addr();
ble_gap_test_util_reset_cb_info();
}
-static void
-ble_gap_test_util_disc_cb(int event, int status,
- struct ble_gap_disc_desc *desc, void *arg)
+static int
+ble_gap_test_util_disc_cb(struct ble_gap_event *event, void *arg)
{
- ble_gap_test_disc_event = event;
- ble_gap_test_disc_status = status;
- ble_gap_test_disc_desc = *desc;
+ ble_gap_test_disc_event_type = event->type;
ble_gap_test_disc_arg = arg;
+
+ if (event->type == BLE_GAP_EVENT_DISC) {
+ ble_gap_test_disc_desc = event->disc;
+ }
+
+ return 0;
}
static int
-ble_gap_test_util_connect_cb(int event, struct ble_gap_conn_ctxt *ctxt,
- void *arg)
+ble_gap_test_util_connect_cb(struct ble_gap_event *event, void *arg)
{
int *fail_reason;
- ble_gap_test_conn_event = event;
- ble_gap_test_conn_desc = *ctxt->desc;
+ ble_gap_test_event = *event;
ble_gap_test_conn_arg = arg;
- switch (event) {
+ switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
- ble_gap_test_conn_status = ctxt->connect.status;
+ ble_gap_test_conn_status = event->connect.status;
+ ble_gap_conn_find(event->connect.conn_handle, &ble_gap_test_conn_desc);
break;
case BLE_GAP_EVENT_DISCONNECT:
- ble_gap_test_conn_status = ctxt->disconnect.reason;
+ ble_gap_test_conn_status = event->disconnect.reason;
+ ble_gap_test_conn_desc = event->disconnect.conn;
break;
case BLE_GAP_EVENT_CONN_UPDATE:
- ble_gap_test_conn_status = ctxt->conn_update.status;
+ ble_gap_test_conn_status = event->conn_update.status;
+ ble_gap_conn_find(event->conn_update.conn_handle,
+ &ble_gap_test_conn_desc);
break;
case BLE_GAP_EVENT_CONN_CANCEL:
break;
case BLE_GAP_EVENT_TERM_FAILURE:
- ble_gap_test_conn_status = ctxt->term_failure.status;
+ ble_gap_test_conn_status = event->term_failure.status;
+ ble_gap_conn_find(event->term_failure.conn_handle,
+ &ble_gap_test_conn_desc);
break;
case BLE_GAP_EVENT_ADV_COMPLETE:
@@ -117,8 +124,10 @@ ble_gap_test_util_connect_cb(int event, struct ble_gap_conn_ctxt *ctxt,
break;
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
- ble_gap_test_conn_peer_params = *ctxt->conn_update_req.peer_params;
- *ctxt->conn_update_req.self_params = ble_gap_test_conn_self_params;
+ ble_gap_test_conn_peer_params = *event->conn_update_req.peer_params;
+ *event->conn_update_req.self_params = ble_gap_test_conn_self_params;
+ ble_gap_conn_find(event->conn_update_req.conn_handle,
+ &ble_gap_test_conn_desc);
fail_reason = arg;
if (fail_reason == NULL) {
@@ -128,6 +137,9 @@ ble_gap_test_util_connect_cb(int event, struct ble_gap_conn_ctxt *ctxt,
}
break;
+ case BLE_GAP_EVENT_MTU:
+ break;
+
default:
TEST_ASSERT_FATAL(0);
break;
@@ -165,7 +177,9 @@ ble_gap_test_util_verify_tx_add_wl(struct ble_gap_white_entry *entry)
}
static void
-ble_gap_test_util_verify_tx_set_scan_params(uint16_t itvl,
+ble_gap_test_util_verify_tx_set_scan_params(uint8_t own_addr_type,
+ uint8_t scan_type,
+ uint16_t itvl,
uint16_t scan_window,
uint8_t filter_policy)
{
@@ -176,15 +190,16 @@ ble_gap_test_util_verify_tx_set_scan_params(uint16_t itvl,
BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
&param_len);
TEST_ASSERT(param_len == BLE_HCI_SET_SCAN_PARAM_LEN);
- TEST_ASSERT(param[0] == BLE_HCI_SCAN_TYPE_ACTIVE);
+ TEST_ASSERT(param[0] == scan_type);
TEST_ASSERT(le16toh(param + 1) == itvl);
TEST_ASSERT(le16toh(param + 3) == scan_window);
- TEST_ASSERT(param[5] == BLE_HCI_ADV_OWN_ADDR_PUBLIC);
+ TEST_ASSERT(param[5] == own_addr_type);
TEST_ASSERT(param[6] == filter_policy);
}
static void
-ble_gap_test_util_verify_tx_scan_enable(uint8_t enable)
+ble_gap_test_util_verify_tx_scan_enable(uint8_t enable,
+ uint8_t filter_duplicates)
{
uint8_t param_len;
uint8_t *param;
@@ -194,26 +209,11 @@ ble_gap_test_util_verify_tx_scan_enable(uint8_t enable)
&param_len);
TEST_ASSERT(param_len == BLE_HCI_SET_SCAN_ENABLE_LEN);
TEST_ASSERT(param[0] == enable);
+ TEST_ASSERT(param[1] == filter_duplicates);
}
static void
-ble_gap_test_util_verify_tx_create_conn(uint8_t filter_policy)
-{
- uint8_t param_len;
- uint8_t *param;
-
- param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_CREATE_CONN,
- &param_len);
- TEST_ASSERT(param_len == BLE_HCI_CREATE_CONN_LEN);
-
- TEST_ASSERT(param[4] == filter_policy);
-
- /* XXX: Verify other fields. */
-}
-
-static void
-ble_gap_test_util_verify_tx_create_conn_cancel(void)
+ble_hs_test_util_verify_tx_create_conn_cancel(void)
{
uint8_t param_len;
@@ -251,17 +251,6 @@ ble_gap_test_util_verify_tx_adv_params(void)
}
static void
-ble_gap_test_util_verify_tx_rd_pwr(void)
-{
- uint8_t param_len;
-
- ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR,
- &param_len);
- TEST_ASSERT(param_len == 0);
-}
-
-static void
ble_gap_test_util_verify_tx_adv_data(void)
{
uint8_t param_len;
@@ -384,13 +373,13 @@ ble_gap_test_util_rx_param_req(struct ble_gap_upd_params *params, int pos,
evt.itvl_max = params->itvl_max;
evt.latency = params->latency;
evt.timeout = params->supervision_timeout;
-
+
if (pos) {
- opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_REM_CONN_PARAM_RR);
+ opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR);
} else {
- opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR);
+ opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR);
}
if (*cmd_idx == cmd_fail_idx) {
hci_status = fail_status;
@@ -442,7 +431,7 @@ ble_gap_test_util_wl_set(struct ble_gap_white_entry *white_list,
}
}
-TEST_CASE(ble_gap_test_case_conn_wl_bad_args)
+TEST_CASE(ble_gap_test_case_wl_bad_args)
{
int rc;
@@ -461,8 +450,9 @@ TEST_CASE(ble_gap_test_case_conn_wl_bad_args)
TEST_ASSERT(rc == BLE_HS_EINVAL);
/*** White-list-using connection in progress. */
- rc = ble_hs_test_util_conn_initiate(BLE_GAP_ADDR_TYPE_WL, NULL, NULL,
- ble_gap_test_util_connect_cb, NULL, 0);
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_GAP_ADDR_TYPE_WL, NULL, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
TEST_ASSERT(rc == 0);
rc = ble_hs_test_util_wl_set(
@@ -473,7 +463,7 @@ TEST_CASE(ble_gap_test_case_conn_wl_bad_args)
TEST_ASSERT(rc == BLE_HS_EBUSY);
}
-TEST_CASE(ble_gap_test_case_conn_wl_ctlr_fail)
+TEST_CASE(ble_gap_test_case_wl_ctlr_fail)
{
int i;
@@ -491,7 +481,7 @@ TEST_CASE(ble_gap_test_case_conn_wl_ctlr_fail)
}
}
-TEST_CASE(ble_gap_test_case_conn_wl_good)
+TEST_CASE(ble_gap_test_case_wl_good)
{
struct ble_gap_white_entry white_list[] = {
{ BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
@@ -504,11 +494,13 @@ TEST_CASE(ble_gap_test_case_conn_wl_good)
ble_gap_test_util_wl_set(white_list, white_list_count, 0, 0);
}
-TEST_SUITE(ble_gap_test_suite_conn_wl)
+TEST_SUITE(ble_gap_test_suite_wl)
{
- ble_gap_test_case_conn_wl_good();
- ble_gap_test_case_conn_wl_bad_args();
- ble_gap_test_case_conn_wl_ctlr_fail();
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_wl_good();
+ ble_gap_test_case_wl_bad_args();
+ ble_gap_test_case_wl_ctlr_fail();
}
/*****************************************************************************
@@ -516,73 +508,85 @@ TEST_SUITE(ble_gap_test_suite_conn_wl)
*****************************************************************************/
static int
-ble_gap_test_util_disc(uint8_t disc_mode, uint8_t *peer_addr,
- struct ble_hs_adv *adv, int cmd_fail_idx,
+ble_gap_test_util_disc(uint8_t own_addr_type,
+ const struct ble_gap_disc_params *disc_params,
+ struct ble_gap_disc_desc *desc, int cmd_fail_idx,
uint8_t fail_status)
{
int rc;
ble_gap_test_util_init();
+ TEST_ASSERT(!ble_gap_disc_active());
+
/* Begin the discovery procedure. */
- rc = ble_hs_test_util_disc(0, disc_mode, BLE_HCI_SCAN_TYPE_ACTIVE,
- BLE_HCI_SCAN_FILT_NO_WL,
+ rc = ble_hs_test_util_disc(own_addr_type, BLE_HS_FOREVER, disc_params,
ble_gap_test_util_disc_cb, NULL, cmd_fail_idx,
fail_status);
TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
if (rc == 0) {
TEST_ASSERT(ble_gap_master_in_progress());
- ble_gap_rx_adv_report(adv);
+ ble_gap_rx_adv_report(desc);
} else {
- TEST_ASSERT(ble_gap_test_disc_status == -1);
+ TEST_ASSERT(ble_gap_test_disc_event_type == -1);
}
if (cmd_fail_idx > 0) {
/* Verify tx of set scan parameters command. */
ble_gap_test_util_verify_tx_set_scan_params(
- 30 * 1000 / BLE_HCI_ADV_ITVL,
- 30 * 1000 / BLE_HCI_SCAN_ITVL,
- BLE_HCI_SCAN_FILT_NO_WL);
+ own_addr_type,
+ disc_params->passive ?
+ BLE_HCI_SCAN_TYPE_PASSIVE :
+ BLE_HCI_SCAN_TYPE_ACTIVE,
+ disc_params->itvl,
+ disc_params->window,
+ disc_params->filter_policy);
}
if (cmd_fail_idx > 1) {
/* Verify tx of scan enable command. */
- ble_gap_test_util_verify_tx_scan_enable(1);
+ ble_gap_test_util_verify_tx_scan_enable(
+ 1, disc_params->filter_duplicates);
+ }
+
+ if (rc == 0) {
+ TEST_ASSERT(ble_gap_disc_active());
}
return rc;
}
-TEST_CASE(ble_gap_test_case_conn_disc_bad_args)
+TEST_CASE(ble_gap_test_case_disc_bad_args)
{
+ struct ble_gap_disc_params params;
int rc;
+ params.itvl = 0;
+ params.window = 0;
+ params.filter_policy = BLE_HCI_SCAN_FILT_NO_WL;
+ params.limited = 0;
+ params.passive = 0;
+ params.filter_duplicates = 0;
+
ble_gap_test_util_init();
- /*** Invalid discovery mode. */
- rc = ble_gap_disc(0, BLE_GAP_DISC_MODE_NON, BLE_HCI_SCAN_TYPE_ACTIVE,
- BLE_HCI_SCAN_FILT_NO_WL, BLE_ADDR_TYPE_PUBLIC, ble_gap_test_util_disc_cb,
- NULL);
+ /*** Invalid filter policy. */
+ params.filter_policy = 6;
+ rc = ble_gap_disc(BLE_ADDR_TYPE_PUBLIC, 0, &params,
+ ble_gap_test_util_disc_cb, NULL);
TEST_ASSERT(rc == BLE_HS_EINVAL);
-
- /*** Master operation already in progress. */
- rc = ble_hs_test_util_conn_initiate(BLE_GAP_ADDR_TYPE_WL, NULL, NULL,
- ble_gap_test_util_connect_cb, NULL, 0);
- rc = ble_gap_disc(0, BLE_GAP_DISC_MODE_GEN, BLE_HCI_SCAN_TYPE_ACTIVE,
- BLE_HCI_SCAN_FILT_NO_WL, BLE_ADDR_TYPE_PUBLIC, ble_gap_test_util_disc_cb,
- NULL);
- TEST_ASSERT(rc == BLE_HS_EALREADY);
}
-TEST_CASE(ble_gap_test_case_conn_disc_good)
+TEST_CASE(ble_gap_test_case_disc_good)
{
uint8_t adv_data[32];
uint8_t flags;
+ uint8_t own_addr_type;
+ int passive;
+ int limited;
int rc;
- int d;
- uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
- struct ble_hs_adv adv = {
+ struct ble_gap_disc_desc desc = {
.event_type = BLE_HCI_ADV_TYPE_ADV_IND,
.addr_type = BLE_ADDR_TYPE_PUBLIC,
.length_data = 0,
@@ -590,56 +594,101 @@ TEST_CASE(ble_gap_test_case_conn_disc_good)
.addr = { 1, 2, 3, 4, 5, 6 },
.data = adv_data,
};
+ struct ble_gap_disc_params disc_params = {
+ .itvl = BLE_GAP_SCAN_SLOW_INTERVAL1,
+ .window = BLE_GAP_SCAN_SLOW_WINDOW1,
+ .filter_policy = BLE_HCI_CONN_FILT_NO_WL,
+ .limited = 0,
+ .passive = 0,
+ .filter_duplicates = 0,
+ };
flags = BLE_HS_ADV_F_DISC_LTD;
rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &flags,
- adv.data, &adv.length_data,
+ desc.data, &desc.length_data,
sizeof adv_data);
TEST_ASSERT_FATAL(rc == 0);
- for (d = BLE_GAP_DISC_MODE_LTD; d < BLE_GAP_DISC_MODE_MAX; d++) {
- ble_gap_test_util_disc(d, peer_addr, &adv, -1, 0);
+ for (own_addr_type = 0;
+ own_addr_type <= BLE_ADDR_TYPE_RPA_RND_DEFAULT;
+ own_addr_type++)
+ for (passive = 0; passive <= 1; passive++)
+ for (limited = 0; limited <= 1; limited++) {
+ disc_params.passive = passive;
+ disc_params.limited = limited;
+ ble_gap_test_util_disc(own_addr_type, &disc_params, &desc, -1, 0);
TEST_ASSERT(ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_test_disc_event == BLE_GAP_EVENT_DISC_SUCCESS);
- TEST_ASSERT(ble_gap_test_disc_status == 0);
+ TEST_ASSERT(ble_gap_test_disc_event_type == BLE_GAP_EVENT_DISC);
TEST_ASSERT(ble_gap_test_disc_desc.event_type ==
BLE_HCI_ADV_TYPE_ADV_IND);
- TEST_ASSERT(ble_gap_test_disc_desc.addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(ble_gap_test_disc_desc.addr_type ==
+ BLE_ADDR_TYPE_PUBLIC);
TEST_ASSERT(ble_gap_test_disc_desc.length_data == 3);
TEST_ASSERT(ble_gap_test_disc_desc.rssi == 0);
- TEST_ASSERT(memcmp(ble_gap_test_disc_desc.addr, adv.addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_disc_desc.addr, desc.addr, 6) == 0);
TEST_ASSERT(ble_gap_test_disc_arg == NULL);
+
}
}
-TEST_CASE(ble_gap_test_case_conn_disc_bad_flags)
+TEST_CASE(ble_gap_test_case_disc_ltd_mismatch)
{
- uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
- struct ble_hs_adv adv = {
+ int rc;
+ struct ble_gap_disc_desc desc = {
.event_type = BLE_HCI_ADV_TYPE_ADV_IND,
.addr_type = BLE_ADDR_TYPE_PUBLIC,
.length_data = 0,
.rssi = 0,
.addr = { 1, 2, 3, 4, 5, 6 },
- .data = NULL,
+ .data = (uint8_t[BLE_HCI_MAX_ADV_DATA_LEN]){
+ 2,
+ BLE_HS_ADV_TYPE_FLAGS,
+ BLE_HS_ADV_F_DISC_GEN,
+ },
+ };
+ struct ble_gap_disc_params disc_params = {
+ .itvl = BLE_GAP_SCAN_SLOW_INTERVAL1,
+ .window = BLE_GAP_SCAN_SLOW_WINDOW1,
+ .filter_policy = BLE_HCI_CONN_FILT_NO_WL,
+ .limited = 1,
+ .passive = 0,
+ .filter_duplicates = 0,
};
- ble_gap_test_util_disc(BLE_GAP_DISC_MODE_LTD, peer_addr, &adv, -1, 0);
+ rc = ble_gap_test_util_disc(BLE_ADDR_TYPE_PUBLIC, &disc_params, &desc,
+ -1, 0);
+ TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
- /* Verify that the report was ignored becuase of a mismatched LTD flag. */
- TEST_ASSERT(ble_gap_test_disc_event == -1);
+ /* Verify that the report was ignored because of a mismatched LTD flag. */
+ TEST_ASSERT(ble_gap_test_disc_event_type == -1);
+
+ /* Stop the scan and swap the flags. */
+ rc = ble_hs_test_util_disc_cancel(0);
+ TEST_ASSERT(rc == 0);
+
+ desc.data[2] = BLE_HS_ADV_F_DISC_LTD;
+ disc_params.limited = 0;
+ rc = ble_gap_test_util_disc(BLE_ADDR_TYPE_PUBLIC, &disc_params, &desc,
+ -1, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(ble_gap_master_in_progress());
+
+ /* This time we should have reported the advertisement; general discovery
+ * hears everything.
+ */
+ TEST_ASSERT(ble_gap_test_disc_event_type == BLE_GAP_EVENT_DISC);
+
}
-TEST_CASE(ble_gap_test_case_conn_disc_hci_fail)
+TEST_CASE(ble_gap_test_case_disc_hci_fail)
{
int fail_idx;
+ int limited;
int rc;
- int d;
- uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
- struct ble_hs_adv adv = {
+ struct ble_gap_disc_desc desc = {
.event_type = BLE_HCI_ADV_TYPE_ADV_IND,
.addr_type = BLE_ADDR_TYPE_PUBLIC,
.length_data = 0,
@@ -647,32 +696,127 @@ TEST_CASE(ble_gap_test_case_conn_disc_hci_fail)
.addr = { 1, 2, 3, 4, 5, 6 },
.data = NULL,
};
+ struct ble_gap_disc_params disc_params = {
+ .itvl = BLE_GAP_SCAN_SLOW_INTERVAL1,
+ .window = BLE_GAP_SCAN_SLOW_WINDOW1,
+ .filter_policy = BLE_HCI_CONN_FILT_NO_WL,
+ .limited = 0,
+ .passive = 0,
+ .filter_duplicates = 0,
+ };
+
+ for (limited = 0; limited <= 1; limited++) {
+ disc_params.limited = limited;
- for (d = BLE_GAP_DISC_MODE_LTD; d < BLE_GAP_DISC_MODE_MAX; d++) {
for (fail_idx = 0; fail_idx < 2; fail_idx++) {
- rc = ble_gap_test_util_disc(d, peer_addr, &adv, fail_idx,
- BLE_ERR_UNSUPPORTED);
+ rc = ble_gap_test_util_disc(BLE_ADDR_TYPE_PUBLIC, &disc_params,
+ &desc, fail_idx, BLE_ERR_UNSUPPORTED);
TEST_ASSERT(rc == BLE_HS_HCI_ERR(BLE_ERR_UNSUPPORTED));
TEST_ASSERT(!ble_gap_master_in_progress());
}
}
}
-TEST_SUITE(ble_gap_test_suite_conn_disc)
+static void
+ble_gap_test_util_disc_dflts_once(int limited)
+{
+ struct ble_gap_disc_params params;
+ uint16_t exp_window;
+ uint16_t exp_itvl;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ memset(&params, 0, sizeof params);
+ params.limited = limited;
+
+ rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC, 0, &params,
+ ble_gap_test_util_disc_cb, NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ if (limited) {
+ exp_itvl = BLE_GAP_LIM_DISC_SCAN_INT;
+ exp_window = BLE_GAP_LIM_DISC_SCAN_WINDOW;
+ } else {
+ exp_itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN;
+ exp_window = BLE_GAP_SCAN_FAST_WINDOW;
+ }
+ ble_gap_test_util_verify_tx_set_scan_params(
+ BLE_ADDR_TYPE_PUBLIC,
+ BLE_HCI_SCAN_TYPE_ACTIVE,
+ exp_itvl,
+ exp_window,
+ BLE_HCI_SCAN_FILT_NO_WL);
+
+ ble_gap_test_util_verify_tx_scan_enable(1, 0);
+}
+
+TEST_CASE(ble_gap_test_case_disc_dflts)
+{
+ ble_gap_test_util_disc_dflts_once(0);
+ ble_gap_test_util_disc_dflts_once(1);
+}
+
+TEST_CASE(ble_gap_test_case_disc_already)
{
- ble_gap_test_case_conn_disc_bad_args();
- ble_gap_test_case_conn_disc_good();
- ble_gap_test_case_conn_disc_bad_flags();
- ble_gap_test_case_conn_disc_hci_fail();
+ static const struct ble_gap_disc_params disc_params = { 0 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a discovery procedure. */
+ rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, ble_gap_test_util_disc_cb,
+ NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure host indicates BLE_HS_EALREADY if we try to discover. */
+ rc = ble_gap_disc(BLE_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER, &disc_params,
+ ble_gap_test_util_disc_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+}
+
+TEST_CASE(ble_gap_test_case_disc_busy)
+{
+ static const struct ble_gap_disc_params disc_params = { 0 };
+ static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a connect procedure. */
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure host indicates BLE_HS_EBUSY if we try to discover. */
+ rc = ble_gap_disc(BLE_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER, &disc_params,
+ ble_gap_test_util_disc_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EBUSY);
+}
+
+TEST_SUITE(ble_gap_test_suite_disc)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_disc_bad_args();
+ ble_gap_test_case_disc_good();
+ ble_gap_test_case_disc_ltd_mismatch();
+ ble_gap_test_case_disc_hci_fail();
+ ble_gap_test_case_disc_dflts();
+ ble_gap_test_case_disc_already();
+ ble_gap_test_case_disc_busy();
}
/*****************************************************************************
* $direct connect *
*****************************************************************************/
-TEST_CASE(ble_gap_test_case_conn_dir_good)
+TEST_CASE(ble_gap_test_case_conn_gen_good)
{
struct hci_le_conn_complete evt;
+ struct ble_gap_conn_params params;
int rc;
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -680,15 +824,25 @@ TEST_CASE(ble_gap_test_case_conn_dir_good)
ble_gap_test_util_init();
TEST_ASSERT(!ble_gap_master_in_progress());
-
- rc = ble_hs_test_util_conn_initiate(BLE_ADDR_TYPE_PUBLIC, peer_addr, NULL,
- ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT(!ble_gap_conn_active());
+
+ params.scan_itvl = 0x12;
+ params.scan_window = 0x11;
+ params.itvl_min = 25;
+ params.itvl_max = 26;
+ params.latency = 1;
+ params.supervision_timeout = 20;
+ params.min_ce_len = 3;
+ params.max_ce_len = 4;
+
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC, peer_addr, 0, &params,
+ ble_gap_test_util_connect_cb, NULL, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_conn_active());
- /* Verify tx of create connection command. */
- ble_gap_test_util_verify_tx_create_conn(BLE_HCI_CONN_FILT_NO_WL);
TEST_ASSERT(ble_gap_master_in_progress());
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
@@ -704,14 +858,15 @@ TEST_CASE(ble_gap_test_case_conn_dir_good)
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
}
-TEST_CASE(ble_gap_test_case_conn_dir_bad_args)
+TEST_CASE(ble_gap_test_case_conn_gen_bad_args)
{
int rc;
@@ -720,29 +875,92 @@ TEST_CASE(ble_gap_test_case_conn_dir_bad_args)
TEST_ASSERT(!ble_gap_master_in_progress());
/*** Invalid address type. */
- rc = ble_gap_conn_initiate(5, ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), NULL,
- ble_gap_test_util_connect_cb, NULL);
+ rc = ble_gap_connect(BLE_ADDR_TYPE_PUBLIC, 5,
+ ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), 0, NULL,
+ ble_gap_test_util_connect_cb, NULL);
TEST_ASSERT(rc == BLE_HS_EINVAL);
TEST_ASSERT(!ble_gap_master_in_progress());
/*** Connection already in progress. */
- rc = ble_hs_test_util_conn_initiate(BLE_ADDR_TYPE_PUBLIC,
- ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }),
- NULL, ble_gap_test_util_connect_cb,
- NULL, 0);
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), 0,
+ NULL, ble_gap_test_util_connect_cb,
+ NULL, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
- rc = ble_gap_conn_initiate(BLE_ADDR_TYPE_PUBLIC,
- ((uint8_t[]){ 2, 3, 4, 5, 6, 7 }), NULL,
- ble_gap_test_util_connect_cb, NULL);
+ rc = ble_gap_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), 0, NULL,
+ ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+}
+
+TEST_CASE(ble_gap_test_case_conn_gen_dflt_params)
+{
+ static const uint8_t peer_addr[6] = { 2, 3, 8, 6, 6, 1 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC, peer_addr, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_gap_test_case_conn_gen_already)
+{
+ static const struct ble_gap_conn_params conn_params = { 0 };
+ static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a connect procedure. */
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure host indicates BLE_HS_EALREADY if we try to connect. */
+ rc = ble_gap_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, BLE_HS_FOREVER, &conn_params,
+ ble_gap_test_util_connect_cb, NULL);
TEST_ASSERT(rc == BLE_HS_EALREADY);
}
-TEST_SUITE(ble_gap_test_suite_conn_dir)
+TEST_CASE(ble_gap_test_case_conn_gen_busy)
{
- ble_gap_test_case_conn_dir_good();
- ble_gap_test_case_conn_dir_bad_args();
+ static const struct ble_gap_disc_params disc_params = { 0 };
+ static const struct ble_gap_conn_params conn_params = { 0 };
+ static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a discovery procedure. */
+ rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, ble_gap_test_util_disc_cb,
+ NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure host indicates BLE_HS_EBUSY if we try to connect. */
+ rc = ble_gap_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, BLE_HS_FOREVER, &conn_params,
+ ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EBUSY);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_gen)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_conn_gen_good();
+ ble_gap_test_case_conn_gen_bad_args();
+ ble_gap_test_case_conn_gen_dflt_params();
+ ble_gap_test_case_conn_gen_already();
+ ble_gap_test_case_conn_gen_busy();
}
/*****************************************************************************
@@ -750,26 +968,17 @@ TEST_SUITE(ble_gap_test_suite_conn_dir)
*****************************************************************************/
static void
-ble_gap_test_util_conn_cancel(uint8_t *peer_addr, uint8_t hci_status)
+ble_gap_test_util_conn_cancel(uint8_t hci_status)
{
struct hci_le_conn_complete evt;
int rc;
- ble_gap_test_util_init();
-
- /* Begin creating a connection. */
- rc = ble_hs_test_util_conn_initiate(BLE_ADDR_TYPE_PUBLIC, peer_addr, NULL,
- ble_gap_test_util_connect_cb, NULL, 0);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(ble_gap_master_in_progress());
- ble_gap_test_util_verify_tx_create_conn(BLE_HCI_CONN_FILT_NO_WL);
-
/* Initiate cancel procedure. */
rc = ble_hs_test_util_conn_cancel(hci_status);
TEST_ASSERT(rc == BLE_HS_HCI_ERR(hci_status));
/* Verify tx of cancel create connection command. */
- ble_gap_test_util_verify_tx_create_conn_cancel();
+ ble_hs_test_util_verify_tx_create_conn_cancel();
if (rc != 0) {
return;
}
@@ -779,12 +988,29 @@ ble_gap_test_util_conn_cancel(uint8_t *peer_addr, uint8_t hci_status)
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
evt.status = BLE_ERR_UNK_CONN_ID;
- evt.connection_handle = 2;
- evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
- memcpy(evt.peer_addr, peer_addr, 6);
rc = ble_gap_rx_conn_complete(&evt);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
+}
+
+static void
+ble_gap_test_util_conn_and_cancel(uint8_t *peer_addr, uint8_t hci_status)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Begin creating a connection. */
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC, peer_addr, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(ble_gap_master_in_progress());
+
+ /* Initiate cancel procedure. */
+ ble_gap_test_util_conn_cancel(hci_status);
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
}
@@ -797,16 +1023,16 @@ TEST_CASE(ble_gap_test_case_conn_cancel_bad_args)
/* Initiate cancel procedure with no connection in progress. */
TEST_ASSERT(!ble_gap_master_in_progress());
rc = ble_hs_test_util_conn_cancel(0);
- TEST_ASSERT(rc == BLE_HS_ENOENT);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
}
TEST_CASE(ble_gap_test_case_conn_cancel_good)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
- ble_gap_test_util_conn_cancel(peer_addr, 0);
+ ble_gap_test_util_conn_and_cancel(peer_addr, 0);
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_CANCEL);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == BLE_HS_CONN_HANDLE_NONE);
}
@@ -817,12 +1043,12 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
- ble_gap_test_util_conn_cancel(peer_addr, BLE_ERR_REPEATED_ATTEMPTS);
+ ble_gap_test_util_conn_and_cancel(peer_addr, BLE_ERR_REPEATED_ATTEMPTS);
/* Make sure the host didn't invoke the application callback. The cancel
* failure was indicated via the return code from the gap call.
*/
- TEST_ASSERT(ble_gap_test_conn_event == -1);
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
/* Allow connection complete to succeed. */
memset(&evt, 0, sizeof evt);
@@ -836,7 +1062,7 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
peer_addr, 6) == 0);
@@ -846,6 +1072,8 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
TEST_SUITE(ble_gap_test_suite_conn_cancel)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gap_test_case_conn_cancel_good();
ble_gap_test_case_conn_cancel_bad_args();
ble_gap_test_case_conn_cancel_ctlr_fail();
@@ -870,7 +1098,7 @@ ble_gap_test_util_terminate(uint8_t *peer_addr, uint8_t hci_status)
/* Reset the callback event code; we don't care about the successful
* connection in this test.
*/
- ble_gap_test_conn_event = -1;
+ ble_gap_test_event.type = -1;
/* Terminate the connection. */
rc = ble_hs_test_util_conn_terminate(2, hci_status);
@@ -906,12 +1134,14 @@ TEST_CASE(ble_gap_test_case_conn_terminate_good)
ble_gap_test_util_terminate(peer_addr, 0);
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_DISCONNECT);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(ble_gap_test_conn_status ==
BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_LOCAL));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(ble_gap_test_conn_desc.peer_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(ble_gap_test_conn_desc.peer_id_addr_type ==
+ BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_arg == NULL);
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
@@ -945,12 +1175,14 @@ TEST_CASE(ble_gap_test_case_conn_terminate_ctlr_fail)
evt.reason = 0;
ble_gap_rx_disconn_complete(&evt);
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_TERM_FAILURE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_TERM_FAILURE);
TEST_ASSERT(ble_gap_test_conn_status ==
BLE_HS_HCI_ERR(BLE_ERR_UNSUPPORTED));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(ble_gap_test_conn_desc.peer_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(ble_gap_test_conn_desc.peer_id_addr_type ==
+ BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_arg == NULL);
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
@@ -963,13 +1195,15 @@ TEST_CASE(ble_gap_test_case_conn_terminate_hci_fail)
ble_gap_test_util_terminate(peer_addr, BLE_ERR_REPEATED_ATTEMPTS);
- TEST_ASSERT(ble_gap_test_conn_event == -1);
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
}
TEST_SUITE(ble_gap_test_suite_conn_terminate)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gap_test_case_conn_terminate_bad_args();
ble_gap_test_case_conn_terminate_good();
ble_gap_test_case_conn_terminate_ctlr_fail();
@@ -977,38 +1211,170 @@ TEST_SUITE(ble_gap_test_suite_conn_terminate)
}
/*****************************************************************************
+ * $conn find *
+ *****************************************************************************/
+
+TEST_CASE(ble_gap_test_case_conn_find)
+{
+
+ struct ble_gap_conn_desc desc;
+ struct ble_hs_conn *conn;
+ uint8_t pub_addr[6];
+ int rc;
+
+ /*** We are master; public addresses. */
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_rpa_conn(8,
+ BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[6]){0,0,0,0,0,0}),
+ BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[6]){2,3,4,5,6,7}),
+ ((uint8_t[6]){0,0,0,0,0,0}),
+ ble_gap_test_util_connect_cb,
+ NULL);
+
+
+ rc = ble_hs_id_copy_addr(BLE_ADDR_TYPE_PUBLIC, pub_addr, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_gap_conn_find(8, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(desc.conn_handle == 8);
+ TEST_ASSERT(desc.our_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(desc.our_ota_addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(desc.peer_ota_addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
+ TEST_ASSERT(memcmp(desc.our_ota_addr, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.our_id_addr, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_ota_addr,
+ ((uint8_t[6]){2,3,4,5,6,7}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_id_addr,
+ ((uint8_t[6]){2,3,4,5,6,7}), 6) == 0);
+ TEST_ASSERT(desc.conn_itvl == BLE_GAP_INITIAL_CONN_ITVL_MAX);
+ TEST_ASSERT(desc.conn_latency == BLE_GAP_INITIAL_CONN_LATENCY);
+ TEST_ASSERT(desc.supervision_timeout ==
+ BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
+ TEST_ASSERT(desc.master_clock_accuracy == 0);
+ TEST_ASSERT(!desc.sec_state.encrypted);
+ TEST_ASSERT(!desc.sec_state.authenticated);
+ TEST_ASSERT(!desc.sec_state.bonded);
+
+ /*** Swap roles. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(8);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ rc = ble_gap_conn_find(8, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_SLAVE);
+
+ /*** We are master; RPAs. */
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_rpa_conn(54,
+ BLE_ADDR_TYPE_RPA_PUB_DEFAULT,
+ ((uint8_t[6]){0x40,1,2,3,4,5}),
+ BLE_ADDR_TYPE_RPA_RND_DEFAULT,
+ ((uint8_t[6]){3,4,5,6,7,8}),
+ ((uint8_t[6]){0x50,1,2,3,4,5}),
+ ble_gap_test_util_connect_cb,
+ NULL);
+
+ rc = ble_gap_conn_find(54, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(desc.conn_handle == 54);
+ TEST_ASSERT(desc.our_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(desc.our_ota_addr_type == BLE_ADDR_TYPE_RPA_PUB_DEFAULT);
+ TEST_ASSERT(desc.peer_ota_addr_type == BLE_ADDR_TYPE_RPA_RND_DEFAULT);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
+ TEST_ASSERT(memcmp(desc.our_ota_addr,
+ ((uint8_t[6]){0x40,1,2,3,4,5}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.our_id_addr, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_ota_addr,
+ ((uint8_t[6]){0x50,1,2,3,4,5}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_id_addr,
+ ((uint8_t[6]){3,4,5,6,7,8}), 6) == 0);
+ TEST_ASSERT(desc.conn_itvl == BLE_GAP_INITIAL_CONN_ITVL_MAX);
+ TEST_ASSERT(desc.conn_latency == BLE_GAP_INITIAL_CONN_LATENCY);
+ TEST_ASSERT(desc.supervision_timeout ==
+ BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
+ TEST_ASSERT(desc.master_clock_accuracy == 0);
+ TEST_ASSERT(!desc.sec_state.encrypted);
+ TEST_ASSERT(!desc.sec_state.authenticated);
+ TEST_ASSERT(!desc.sec_state.bonded);
+
+ /*** Swap roles. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(54);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ rc = ble_gap_conn_find(54, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_SLAVE);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_find)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_conn_find();
+}
+
+/*****************************************************************************
* $advertise *
*****************************************************************************/
static void
-ble_gap_test_util_adv(uint8_t disc_mode, uint8_t conn_mode,
- uint8_t *peer_addr, uint8_t peer_addr_type,
- int connect_status,
+ble_gap_test_util_adv(uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr, uint8_t conn_mode,
+ uint8_t disc_mode, int connect_status,
int cmd_fail_idx, uint8_t fail_status)
{
struct hci_le_conn_complete evt;
+ struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields adv_fields;
+ uint8_t hci_status;
int cmd_idx;
int rc;
ble_gap_test_util_init();
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = conn_mode;
+ adv_params.disc_mode = disc_mode;
+
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ cmd_idx = 0;
if (conn_mode != BLE_GAP_CONN_MODE_DIR) {
memset(&adv_fields, 0, sizeof adv_fields);
adv_fields.tx_pwr_lvl_is_present = 1;
- rc = ble_gap_adv_set_fields(&adv_fields);
- TEST_ASSERT_FATAL(rc == 0);
+ adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+ hci_status = ble_hs_test_util_exp_hci_status(cmd_idx, cmd_fail_idx,
+ fail_status);
+ rc = ble_hs_test_util_adv_set_fields(&adv_fields, hci_status);
+
+ if (adv_fields.tx_pwr_lvl_is_present &&
+ adv_fields.tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO) {
+
+ TEST_ASSERT_FATAL(rc == BLE_HS_HCI_ERR(hci_status));
+ cmd_idx++;
+ }
}
- rc = ble_hs_test_util_adv_start(disc_mode, conn_mode, peer_addr,
- peer_addr_type, NULL,
- ble_gap_test_util_connect_cb, NULL,
- cmd_fail_idx, fail_status);
- TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
+ if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
+ rc = ble_hs_test_util_adv_start(own_addr_type, peer_addr_type,
+ peer_addr, &adv_params,
+ ble_gap_test_util_connect_cb, NULL,
+ cmd_fail_idx - cmd_idx, fail_status);
- cmd_idx = 0;
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
+ }
if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
/* Verify tx of set advertising params command. */
@@ -1018,12 +1384,6 @@ ble_gap_test_util_adv(uint8_t disc_mode, uint8_t conn_mode,
if (conn_mode != BLE_GAP_CONN_MODE_DIR) {
if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
- /* Verify tx of read tx power command. */
- ble_gap_test_util_verify_tx_rd_pwr();
- }
- cmd_idx++;
-
- if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
/* Verify tx of set advertise data command. */
ble_gap_test_util_verify_tx_adv_data();
}
@@ -1042,8 +1402,10 @@ ble_gap_test_util_adv(uint8_t disc_mode, uint8_t conn_mode,
}
cmd_idx++;
- if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
- TEST_ASSERT(ble_gap_slave_in_progress());
+ if (connect_status != -1 &&
+ (fail_status == 0 || cmd_fail_idx >= cmd_idx)) {
+
+ TEST_ASSERT(ble_gap_adv_active());
/* Receive a connection complete event. */
if (conn_mode != BLE_GAP_CONN_MODE_NON) {
@@ -1059,74 +1421,164 @@ ble_gap_test_util_adv(uint8_t disc_mode, uint8_t conn_mode,
if (connect_status == 0 ||
connect_status == BLE_ERR_DIR_ADV_TMO) {
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
} else {
- TEST_ASSERT(ble_gap_slave_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
}
}
}
}
-TEST_CASE(ble_gap_test_case_conn_adv_bad_args)
+TEST_CASE(ble_gap_test_case_adv_bad_args)
{
+ struct ble_gap_adv_params adv_params;
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
int rc;
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
/*** Invalid discoverable mode. */
- rc = ble_hs_test_util_adv_start(-1, BLE_GAP_CONN_MODE_DIR, peer_addr,
- BLE_ADDR_TYPE_PUBLIC, NULL,
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.disc_mode = 43;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, &adv_params,
ble_gap_test_util_connect_cb, NULL, 0, 0);
TEST_ASSERT(rc == BLE_HS_EINVAL);
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
/*** Invalid connectable mode. */
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_GEN, -1, peer_addr,
- BLE_ADDR_TYPE_PUBLIC, NULL,
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = 27;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, &adv_params,
ble_gap_test_util_connect_cb, NULL, 0, 0);
TEST_ASSERT(rc == BLE_HS_EINVAL);
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
/*** Invalid peer address type with directed advertisable mode. */
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_GEN,
- BLE_GAP_CONN_MODE_DIR, peer_addr, -1,
- NULL, ble_gap_test_util_connect_cb, NULL,
- 0, 0);
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = BLE_GAP_CONN_MODE_DIR;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, 12,
+ peer_addr, &adv_params,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
TEST_ASSERT(rc == BLE_HS_EINVAL);
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
/*** Advertising already in progress. */
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_GEN,
- BLE_GAP_CONN_MODE_DIR,
- peer_addr, BLE_ADDR_TYPE_PUBLIC, NULL,
+ adv_params = ble_hs_test_util_adv_params;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, &adv_params,
ble_gap_test_util_connect_cb, NULL, 0, 0);
TEST_ASSERT(rc == 0);
- TEST_ASSERT(ble_gap_slave_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_GEN,
- BLE_GAP_CONN_MODE_DIR,
- peer_addr, BLE_ADDR_TYPE_PUBLIC, NULL,
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, &adv_params,
ble_gap_test_util_connect_cb, NULL, 0, 0);
TEST_ASSERT(rc == BLE_HS_EALREADY);
- TEST_ASSERT(ble_gap_slave_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
+}
+
+static void
+ble_gap_test_util_adv_verify_dflt_params(uint8_t own_addr_type,
+ uint8_t peer_addr_type,
+ const uint8_t *peer_addr,
+ uint8_t conn_mode,
+ uint8_t disc_mode)
+{
+ struct ble_gap_adv_params adv_params;
+ struct hci_adv_params hci_cmd;
+ uint8_t *hci_buf;
+ uint8_t hci_param_len;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = conn_mode;
+ adv_params.disc_mode = disc_mode;
+
+ /* Let stack calculate all default parameters. */
+ adv_params.itvl_min = 0;
+ adv_params.itvl_max = 0;
+ adv_params.channel_map = 0;
+ adv_params.filter_policy = 0;
+ adv_params.high_duty_cycle = 0;
+
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, &adv_params,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure default parameters properly filled in. */
+ hci_buf = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_PARAMS,
+ &hci_param_len);
+ TEST_ASSERT_FATAL(hci_buf != NULL);
+ TEST_ASSERT_FATAL(hci_param_len == BLE_HCI_SET_ADV_PARAM_LEN);
+
+ hci_cmd.adv_itvl_min = le16toh(hci_buf + 0);
+ hci_cmd.adv_itvl_max = le16toh(hci_buf + 2);
+ hci_cmd.adv_type = hci_buf[4];
+ hci_cmd.own_addr_type = hci_buf[5];
+ hci_cmd.peer_addr_type = hci_buf[6];
+ memcpy(hci_cmd.peer_addr, hci_buf + 7, 6);
+ hci_cmd.adv_channel_map = hci_buf[13];
+ hci_cmd.adv_filter_policy = hci_buf[14];
+
+ if (conn_mode == BLE_GAP_CONN_MODE_NON) {
+ TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL2_MIN);
+ TEST_ASSERT(hci_cmd.adv_itvl_max == BLE_GAP_ADV_FAST_INTERVAL2_MAX);
+ } else {
+ TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL1_MIN);
+ TEST_ASSERT(hci_cmd.adv_itvl_max == BLE_GAP_ADV_FAST_INTERVAL1_MAX);
+ }
+
+ if (conn_mode == BLE_GAP_CONN_MODE_NON) {
+ if (disc_mode == BLE_GAP_DISC_MODE_NON) {
+ TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND);
+ } else {
+ TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
+ }
+ } else if (conn_mode == BLE_GAP_CONN_MODE_UND) {
+ TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_IND);
+ } else {
+ TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD);
+ }
}
-TEST_CASE(ble_gap_test_case_conn_adv_good)
+TEST_CASE(ble_gap_test_case_adv_dflt_params)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
int d;
int c;
for (c = BLE_GAP_CONN_MODE_NON; c < BLE_GAP_CONN_MODE_MAX; c++) {
for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
- ble_gap_test_util_adv(d, c, peer_addr, BLE_ADDR_TYPE_PUBLIC,
- BLE_ERR_SUCCESS, -1, 0);
+ ble_gap_test_util_adv_verify_dflt_params(
+ BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d);
+ }
+ }
+}
+
+TEST_CASE(ble_gap_test_case_adv_good)
+{
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+ int d;
+ int c;
+
+ for (c = BLE_GAP_CONN_MODE_NON; c < BLE_GAP_CONN_MODE_MAX; c++) {
+ for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
+ ble_gap_test_util_adv(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, c, d, BLE_ERR_SUCCESS, -1, 0);
if (c != BLE_GAP_CONN_MODE_NON) {
- TEST_ASSERT(!ble_gap_slave_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event ==
- BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(!ble_gap_adv_active());
+ TEST_ASSERT(ble_gap_test_event.type ==
+ BLE_GAP_EVENT_CONNECT);
TEST_ASSERT(ble_gap_test_conn_status == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1137,19 +1589,19 @@ TEST_CASE(ble_gap_test_case_conn_adv_good)
}
}
-TEST_CASE(ble_gap_test_case_conn_adv_ctlr_fail)
+TEST_CASE(ble_gap_test_case_adv_ctlr_fail)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
int d;
int c;
- for (c = BLE_GAP_CONN_MODE_DIR; c < BLE_GAP_CONN_MODE_MAX; c++) {
+ for (c = BLE_GAP_CONN_MODE_NON + 1; c < BLE_GAP_CONN_MODE_MAX; c++) {
for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
- ble_gap_test_util_adv(d, c, peer_addr, BLE_ADDR_TYPE_PUBLIC,
- BLE_ERR_DIR_ADV_TMO, -1, 0);
+ ble_gap_test_util_adv(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ peer_addr, c, d, BLE_ERR_DIR_ADV_TMO, -1, 0);
- TEST_ASSERT(!ble_gap_slave_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event ==
+ TEST_ASSERT(!ble_gap_adv_active());
+ TEST_ASSERT(ble_gap_test_event.type ==
BLE_GAP_EVENT_ADV_COMPLETE);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle ==
BLE_HS_CONN_HANDLE_NONE);
@@ -1158,7 +1610,7 @@ TEST_CASE(ble_gap_test_case_conn_adv_ctlr_fail)
}
}
-TEST_CASE(ble_gap_test_case_conn_adv_hci_fail)
+TEST_CASE(ble_gap_test_case_adv_hci_fail)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
int num_hci_cmds;
@@ -1175,21 +1627,26 @@ TEST_CASE(ble_gap_test_case_conn_adv_hci_fail)
for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
for (fail_idx = 0; fail_idx < num_hci_cmds; fail_idx++) {
- ble_gap_test_util_adv(d, c, peer_addr, BLE_ADDR_TYPE_PUBLIC,
- 0, fail_idx, BLE_ERR_UNSUPPORTED);
- TEST_ASSERT(!ble_gap_slave_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == -1);
+ ble_gap_test_util_adv(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC, peer_addr,
+ c, d, 0, fail_idx, BLE_ERR_UNSUPPORTED);
+
+ TEST_ASSERT(!ble_gap_adv_active());
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
}
}
}
}
-TEST_SUITE(ble_gap_test_suite_conn_adv)
+TEST_SUITE(ble_gap_test_suite_adv)
{
- ble_gap_test_case_conn_adv_bad_args();
- ble_gap_test_case_conn_adv_good();
- ble_gap_test_case_conn_adv_ctlr_fail();
- ble_gap_test_case_conn_adv_hci_fail();
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_adv_bad_args();
+ ble_gap_test_case_adv_dflt_params();
+ ble_gap_test_case_adv_good();
+ ble_gap_test_case_adv_ctlr_fail();
+ ble_gap_test_case_adv_hci_fail();
}
/*****************************************************************************
@@ -1197,8 +1654,8 @@ TEST_SUITE(ble_gap_test_suite_conn_adv)
*****************************************************************************/
static void
-ble_gap_test_util_stop_adv(uint8_t disc_mode, uint8_t conn_mode,
- uint8_t *peer_addr, uint8_t peer_addr_type,
+ble_gap_test_util_stop_adv(uint8_t peer_addr_type, const uint8_t *peer_addr,
+ uint8_t conn_mode, uint8_t disc_mode,
int cmd_fail_idx, uint8_t fail_status)
{
uint8_t hci_status;
@@ -1207,15 +1664,10 @@ ble_gap_test_util_stop_adv(uint8_t disc_mode, uint8_t conn_mode,
ble_gap_test_util_init();
/* Start advertising; don't rx a successful connection event. */
- ble_gap_test_util_adv(disc_mode, conn_mode, peer_addr,
- BLE_ADDR_TYPE_PUBLIC, BLE_ERR_UNSUPPORTED, 0, 0);
+ ble_gap_test_util_adv(BLE_ADDR_TYPE_PUBLIC, peer_addr_type, peer_addr,
+ conn_mode, disc_mode, -1, -1, 0);
- TEST_ASSERT(ble_gap_slave_in_progress());
-
- /* Clear the advertising event that the host sent; we only care about what
- * happens after advertising is stopped.
- */
- ble_gap_test_util_reset_cb_info();
+ TEST_ASSERT(ble_gap_adv_active());
/* Stop advertising. */
hci_status = cmd_fail_idx == 0 ? fail_status : 0;
@@ -1227,7 +1679,7 @@ ble_gap_test_util_stop_adv(uint8_t disc_mode, uint8_t conn_mode,
ble_gap_test_util_verify_tx_adv_enable(0);
}
-TEST_CASE(ble_gap_test_case_conn_stop_adv_good)
+TEST_CASE(ble_gap_test_case_stop_adv_good)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
int d;
@@ -1235,10 +1687,10 @@ TEST_CASE(ble_gap_test_case_conn_stop_adv_good)
for (c = BLE_GAP_CONN_MODE_NON; c < BLE_GAP_CONN_MODE_MAX; c++) {
for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
- ble_gap_test_util_stop_adv(d, c, peer_addr, BLE_ADDR_TYPE_PUBLIC,
+ ble_gap_test_util_stop_adv(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
-1, 0);
- TEST_ASSERT(!ble_gap_slave_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == -1);
+ TEST_ASSERT(!ble_gap_adv_active());
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
TEST_ASSERT(ble_gap_test_conn_status == -1);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == (uint16_t)-1);
TEST_ASSERT(ble_gap_test_conn_arg == (void *)-1);
@@ -1246,7 +1698,7 @@ TEST_CASE(ble_gap_test_case_conn_stop_adv_good)
}
}
-TEST_CASE(ble_gap_test_case_conn_stop_adv_hci_fail)
+TEST_CASE(ble_gap_test_case_stop_adv_hci_fail)
{
uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
int d;
@@ -1254,10 +1706,10 @@ TEST_CASE(ble_gap_test_case_conn_stop_adv_hci_fail)
for (c = BLE_GAP_CONN_MODE_NON; c < BLE_GAP_CONN_MODE_MAX; c++) {
for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
- ble_gap_test_util_stop_adv(d, c, peer_addr, BLE_ADDR_TYPE_PUBLIC,
+ ble_gap_test_util_stop_adv(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
0, BLE_ERR_UNSUPPORTED);
- TEST_ASSERT(ble_gap_slave_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == -1);
+ TEST_ASSERT(ble_gap_adv_active());
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
TEST_ASSERT(ble_gap_test_conn_status == -1);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == (uint16_t)-1);
TEST_ASSERT(ble_gap_test_conn_arg == (void *)-1);
@@ -1265,10 +1717,12 @@ TEST_CASE(ble_gap_test_case_conn_stop_adv_hci_fail)
}
}
-TEST_SUITE(ble_gap_test_suite_conn_stop_adv)
+TEST_SUITE(ble_gap_test_suite_stop_adv)
{
- ble_gap_test_case_conn_stop_adv_good();
- ble_gap_test_case_conn_stop_adv_hci_fail();
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_stop_adv_good();
+ ble_gap_test_case_stop_adv_hci_fail();
}
/*****************************************************************************
@@ -1316,10 +1770,11 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == params->itvl_max);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency == params->latency);
TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
@@ -1330,10 +1785,11 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
return;
fail:
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == status);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl ==
BLE_GAP_INITIAL_CONN_ITVL_MAX);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
@@ -1361,7 +1817,7 @@ ble_gap_test_util_update_peer(uint8_t status,
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(status));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1416,10 +1872,11 @@ ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
TEST_ASSERT(!ble_gap_master_in_progress());
TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == self_params->itvl_max);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency == self_params->latency);
TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
@@ -1428,10 +1885,11 @@ ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
return;
hci_fail:
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(hci_status));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl ==
BLE_GAP_INITIAL_CONN_ITVL_MAX);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
@@ -1477,10 +1935,11 @@ ble_gap_test_util_update_req_neg(struct ble_gap_upd_params *peer_params,
return;
hci_fail:
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(hci_status));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl ==
BLE_GAP_INITIAL_CONN_ITVL_MAX);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
@@ -1552,10 +2011,11 @@ ble_gap_test_util_update_req_concurrent(
TEST_ASSERT(!ble_gap_master_in_progress());
TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == self_params->itvl_max);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency == self_params->latency);
TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
@@ -1564,10 +2024,11 @@ ble_gap_test_util_update_req_concurrent(
return;
hci_fail:
- TEST_ASSERT(ble_gap_test_conn_event == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(fail_status));
TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr, peer_addr, 6) == 0);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+ peer_addr, 6) == 0);
TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl ==
BLE_GAP_INITIAL_CONN_ITVL_MAX);
TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
@@ -1831,6 +2292,8 @@ TEST_CASE(ble_gap_test_case_update_concurrent_hci_fail)
TEST_SUITE(ble_gap_test_suite_update_conn)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gap_test_case_update_conn_good();
ble_gap_test_case_update_conn_bad();
ble_gap_test_case_update_conn_hci_fail();
@@ -1843,20 +2306,328 @@ TEST_SUITE(ble_gap_test_suite_update_conn)
}
/*****************************************************************************
+ * $timeout *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_conn_forever(void)
+{
+ int32_t ticks_from_now;
+
+ /* Initiate a connect procedure with no timeout. */
+ ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), BLE_HS_FOREVER,
+ NULL, ble_gap_test_util_connect_cb,
+ NULL, 0);
+
+ /* Ensure no pending GAP event. */
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Advance 100 seconds; ensure no timeout reported. */
+ os_time_advance(100 * OS_TICKS_PER_SEC);
+ ble_gap_heartbeat();
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+ TEST_ASSERT(ble_gap_conn_active());
+}
+
+static void
+ble_gap_test_util_conn_timeout(int32_t duration_ms)
+{
+ struct hci_le_conn_complete evt;
+ uint32_t duration_ticks;
+ int32_t ticks_from_now;
+ int rc;
+
+ TEST_ASSERT_FATAL(duration_ms != BLE_HS_FOREVER);
+
+ /* Initiate a connect procedure with the specified timeout. */
+ ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC,
+ ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), duration_ms,
+ NULL, ble_gap_test_util_connect_cb,
+ NULL, 0);
+
+ /* Ensure next GAP event is at the expected time. */
+ rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
+ TEST_ASSERT_FATAL(rc == 0);
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == duration_ticks);
+
+ /* Advance duration ms; ensure timeout event does not get reported before
+ * connection complete event rxed.
+ */
+ os_time_advance(duration_ms);
+
+ ble_hs_test_util_set_ack(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
+ 0);
+
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Ensure cancel create connection command was sent. */
+ ble_hs_test_util_verify_tx_create_conn_cancel();
+
+ /* Ensure timer has been stopped. */
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Receive the connection complete event indicating a successful cancel. */
+ memset(&evt, 0, sizeof evt);
+ evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+ evt.status = BLE_ERR_UNK_CONN_ID;
+ rc = ble_gap_rx_conn_complete(&evt);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure the GAP event was triggered. */
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
+
+ /* Clear GAP event for remainder of test. */
+ ble_gap_test_util_reset_cb_info();
+}
+
+static void
+ble_gap_test_util_disc_forever(void)
+{
+ struct ble_gap_disc_params params;
+ int32_t ticks_from_now;
+
+ memset(&params, 0, sizeof params);
+
+ /* Initiate a discovery procedure with no timeout. */
+ ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC,
+ BLE_HS_FOREVER, &params, ble_gap_test_util_disc_cb,
+ NULL, -1, 0);
+
+ /* Ensure no pending GAP event. */
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Advance 100 seconds; ensure no timeout reported. */
+ os_time_advance(100 * OS_TICKS_PER_SEC);
+ TEST_ASSERT(ble_gap_test_disc_event_type == -1);
+ TEST_ASSERT(ble_gap_disc_active());
+}
+
+static void
+ble_gap_test_util_disc_timeout(int32_t duration_ms)
+{
+ struct ble_gap_disc_params params;
+ uint32_t duration_ticks;
+ int32_t ticks_from_now;
+ int rc;
+
+ TEST_ASSERT_FATAL(duration_ms != BLE_HS_FOREVER);
+
+ memset(&params, 0, sizeof params);
+
+ /* Initiate a discovery procedure with the specified timeout. */
+ ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC,
+ duration_ms, &params, ble_gap_test_util_disc_cb,
+ NULL, -1, 0);
+
+ /* Ensure next GAP event is at the expected time. */
+ rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
+ TEST_ASSERT_FATAL(rc == 0);
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == duration_ticks);
+
+ /* Advance duration ms; ensure timeout event was reported. */
+ os_time_advance(duration_ms);
+
+ ble_hs_test_util_set_ack(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ 0);
+ ticks_from_now = ble_gap_heartbeat();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ TEST_ASSERT(ble_gap_test_disc_event_type == BLE_GAP_EVENT_DISC_COMPLETE);
+
+ /* Clear GAP event for remainder of test. */
+ ble_gap_test_util_reset_cb_info();
+}
+
+TEST_CASE(ble_gap_test_case_conn_timeout_conn_forever)
+{
+ ble_gap_test_util_init();
+
+ /* 3 ms. */
+ ble_gap_test_util_conn_timeout(3);
+
+ /* No timeout. */
+ ble_gap_test_util_conn_forever();
+
+}
+
+TEST_CASE(ble_gap_test_case_conn_timeout_conn_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_conn_timeout(30);
+
+ /* 5 ms. */
+ ble_gap_test_util_conn_timeout(5);
+
+}
+
+TEST_CASE(ble_gap_test_case_conn_forever_conn_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* No timeout. */
+ ble_gap_test_util_conn_forever();
+
+ /* Cancel connect procedure manually. */
+ ble_gap_test_util_conn_cancel(0);
+
+ /* Clear GAP event for remainder of test. */
+ ble_gap_test_util_reset_cb_info();
+
+ /* 3 ms. */
+ ble_gap_test_util_conn_timeout(3);
+}
+
+TEST_CASE(ble_gap_test_case_disc_timeout_disc_forever)
+{
+ ble_gap_test_util_init();
+
+ /* 3 ms. */
+ ble_gap_test_util_disc_timeout(3);
+
+ /* No timeout. */
+ ble_gap_test_util_disc_forever();
+
+}
+
+TEST_CASE(ble_gap_test_case_disc_timeout_disc_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_disc_timeout(30);
+
+ /* 5 ms. */
+ ble_gap_test_util_disc_timeout(5);
+
+}
+
+TEST_CASE(ble_gap_test_case_disc_forever_disc_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* No timeout. */
+ ble_gap_test_util_disc_forever();
+
+ /* Cancel discovery procedure manually. */
+ ble_hs_test_util_disc_cancel(0);
+
+ /* 3 ms. */
+ ble_gap_test_util_disc_timeout(3);
+}
+
+TEST_CASE(ble_gap_test_case_conn_timeout_disc_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 15 seconds. */
+ ble_gap_test_util_conn_timeout(15000);
+
+ /* 1285 ms. */
+ ble_gap_test_util_disc_timeout(1285);
+}
+
+TEST_SUITE(ble_gap_test_suite_timeout)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_conn_timeout_conn_forever();
+ ble_gap_test_case_conn_timeout_conn_timeout();
+ ble_gap_test_case_conn_forever_conn_timeout();
+
+ ble_gap_test_case_disc_timeout_disc_forever();
+ ble_gap_test_case_disc_timeout_disc_timeout();
+ ble_gap_test_case_disc_forever_disc_timeout();
+
+ ble_gap_test_case_conn_timeout_disc_timeout();
+}
+
+TEST_CASE(ble_gap_test_case_mtu_us)
+{
+ const uint8_t peer_addr[6] = { 1,2,3,4,5,6 };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ ble_att_set_preferred_mtu(200);
+
+ rc = ble_gattc_exchange_mtu(2, NULL, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_test_util_verify_tx_mtu_cmd(1, 200);
+
+ ble_hs_test_util_rx_att_mtu_cmd(2, 0, 123);
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_MTU);
+ TEST_ASSERT(ble_gap_test_event.mtu.conn_handle == 2);
+ TEST_ASSERT(ble_gap_test_event.mtu.channel_id == BLE_L2CAP_CID_ATT);
+ TEST_ASSERT(ble_gap_test_event.mtu.value == 123);
+}
+
+TEST_CASE(ble_gap_test_case_mtu_peer)
+{
+ const uint8_t peer_addr[6] = { 1,2,3,4,5,6 };
+
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ ble_att_set_preferred_mtu(200);
+
+ ble_hs_test_util_rx_att_mtu_cmd(2, 1, 123);
+ ble_hs_test_util_verify_tx_mtu_cmd(0, 200);
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_MTU);
+ TEST_ASSERT(ble_gap_test_event.mtu.conn_handle == 2);
+ TEST_ASSERT(ble_gap_test_event.mtu.channel_id == BLE_L2CAP_CID_ATT);
+ TEST_ASSERT(ble_gap_test_event.mtu.value == 123);
+}
+
+TEST_SUITE(ble_gap_test_suite_mtu)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gap_test_case_mtu_us();
+ ble_gap_test_case_mtu_peer();
+}
+
+/*****************************************************************************
* $all *
*****************************************************************************/
int
ble_gap_test_all(void)
{
- ble_gap_test_suite_conn_wl();
- ble_gap_test_suite_conn_disc();
- ble_gap_test_suite_conn_dir();
+ ble_gap_test_suite_wl();
+ ble_gap_test_suite_disc();
+ ble_gap_test_suite_conn_gen();
ble_gap_test_suite_conn_cancel();
ble_gap_test_suite_conn_terminate();
- ble_gap_test_suite_conn_adv();
- ble_gap_test_suite_conn_stop_adv();
+ ble_gap_test_suite_conn_find();
+ ble_gap_test_suite_adv();
+ ble_gap_test_suite_stop_adv();
ble_gap_test_suite_update_conn();
+ ble_gap_test_suite_timeout();
+ ble_gap_test_suite_mtu();
return tu_any_failed;
}
diff --git a/net/nimble/host/src/test/ble_gatt_conn_test.c b/net/nimble/host/src/test/ble_gatt_conn_test.c
index 6f3a4a59..be4a46d3 100644
--- a/net/nimble/host/src/test/ble_gatt_conn_test.c
+++ b/net/nimble/host/src/test/ble_gatt_conn_test.c
@@ -36,16 +36,16 @@ struct ble_gatt_conn_test_cb_arg {
static int
ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
- uint8_t *uuid128, uint8_t op,
- struct ble_att_svr_access_ctxt *ctxt,
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
void *arg)
{
- static uint8_t data = 1;
+ uint8_t *buf;
switch (op) {
case BLE_ATT_ACCESS_OP_READ:
- ctxt->attr_data = &data;
- ctxt->data_len = 1;
+ buf = os_mbuf_extend(*om, 1);
+ TEST_ASSERT_FATAL(buf != NULL);
+ *buf = 1;
return 0;
default:
@@ -54,7 +54,8 @@ ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
}
static int
-ble_gatt_conn_test_mtu_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+ble_gatt_conn_test_mtu_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
uint16_t mtu, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -74,9 +75,9 @@ ble_gatt_conn_test_mtu_cb(uint16_t conn_handle, struct ble_gatt_error *error,
static int
ble_gatt_conn_test_disc_all_svcs_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_svc *service,
- void *arg)
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -95,8 +96,8 @@ ble_gatt_conn_test_disc_all_svcs_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_disc_svc_uuid_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_svc *service,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -116,8 +117,8 @@ ble_gatt_conn_test_disc_svc_uuid_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_find_inc_svcs_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_svc *service,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -137,8 +138,8 @@ ble_gatt_conn_test_find_inc_svcs_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_disc_all_chrs_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_chr *chr, void *arg)
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -157,8 +158,8 @@ ble_gatt_conn_test_disc_all_chrs_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_disc_chr_uuid_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_chr *chr, void *arg)
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -177,9 +178,9 @@ ble_gatt_conn_test_disc_chr_uuid_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_disc_all_dscs_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
uint16_t chr_def_handle,
- struct ble_gatt_dsc *dsc,
+ const struct ble_gatt_dsc *dsc,
void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -198,7 +199,8 @@ ble_gatt_conn_test_disc_all_dscs_cb(uint16_t conn_handle,
}
static int
-ble_gatt_conn_test_read_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+ble_gatt_conn_test_read_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -218,7 +220,7 @@ ble_gatt_conn_test_read_cb(uint16_t conn_handle, struct ble_gatt_error *error,
static int
ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -238,7 +240,7 @@ ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -257,7 +259,7 @@ ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
}
static int
ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -268,7 +270,7 @@ ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
TEST_ASSERT(!cb_arg->called);
TEST_ASSERT_FATAL(error != NULL);
TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
- TEST_ASSERT(attr == NULL);
+ TEST_ASSERT(attr->om == NULL);
cb_arg->called++;
@@ -276,8 +278,10 @@ ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
}
static int
-ble_gatt_conn_test_write_cb(uint16_t conn_handle, struct ble_gatt_error *error,
- struct ble_gatt_attr *attr, void *arg)
+ble_gatt_conn_test_write_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr,
+ void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -297,7 +301,7 @@ ble_gatt_conn_test_write_cb(uint16_t conn_handle, struct ble_gatt_error *error,
static int
ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -318,8 +322,9 @@ ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
static int
ble_gatt_conn_test_write_rel_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_attr *attrs, uint8_t num_attrs,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attrs,
+ uint8_t num_attrs,
void *arg)
{
struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -337,26 +342,6 @@ ble_gatt_conn_test_write_rel_cb(uint16_t conn_handle,
return 0;
}
-static int
-ble_gatt_conn_test_indicate_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_attr *attr, void *arg)
-{
- struct ble_gatt_conn_test_cb_arg *cb_arg;
-
- cb_arg = arg;
-
- TEST_ASSERT(cb_arg->exp_conn_handle == conn_handle);
- TEST_ASSERT(!cb_arg->called);
- TEST_ASSERT_FATAL(error != NULL);
- TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
- TEST_ASSERT(attr != NULL);
-
- cb_arg->called++;
-
- return 0;
-}
-
TEST_CASE(ble_gatt_conn_test_disconnect)
{
struct ble_gatt_conn_test_cb_arg mtu_arg = { 0 };
@@ -373,7 +358,7 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
struct ble_gatt_conn_test_cb_arg write_arg = { 0 };
struct ble_gatt_conn_test_cb_arg write_long_arg = { 0 };
struct ble_gatt_conn_test_cb_arg write_rel_arg = { 0 };
- struct ble_gatt_conn_test_cb_arg indicate_arg = { 0 };
+ struct ble_gatt_attr attr;
uint16_t attr_handle;
int rc;
@@ -423,12 +408,12 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
/* Connection 2. */
disc_all_dscs_arg.exp_conn_handle = 2;
- rc = ble_gattc_disc_all_dscs(2, 1, 0xffff,
+ rc = ble_gattc_disc_all_dscs(2, 3, 0xffff,
ble_gatt_conn_test_disc_all_dscs_cb,
&disc_all_dscs_arg);
disc_chr_uuid_arg.exp_conn_handle = 2;
- rc = ble_gattc_disc_chrs_by_uuid(2, 1, 0xffff, BLE_UUID16(0x2222),
+ rc = ble_gattc_disc_chrs_by_uuid(2, 2, 0xffff, BLE_UUID16(0x2222),
ble_gatt_conn_test_disc_chr_uuid_cb,
&disc_chr_uuid_arg);
@@ -455,31 +440,25 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
TEST_ASSERT_FATAL(rc == 0);
write_arg.exp_conn_handle = 3;
- rc = ble_gattc_write(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
- ble_gatt_conn_test_write_value,
- sizeof ble_gatt_conn_test_write_value,
- ble_gatt_conn_test_write_cb, &write_arg);
+ rc = ble_hs_test_util_gatt_write_flat(
+ 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+ ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+ ble_gatt_conn_test_write_cb, &write_arg);
TEST_ASSERT_FATAL(rc == 0);
write_long_arg.exp_conn_handle = 3;
- rc = ble_gattc_write_long(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
- ble_gatt_conn_test_write_value,
- sizeof ble_gatt_conn_test_write_value,
- ble_gatt_conn_test_write_long_cb,
- &write_long_arg);
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+ ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+ ble_gatt_conn_test_write_long_cb, &write_long_arg);
TEST_ASSERT_FATAL(rc == 0);
+ attr.handle = 8;
+ attr.offset = 0;
+ attr.om = os_msys_get_pkthdr(0, 0);
write_rel_arg.exp_conn_handle = 3;
- rc = ble_gattc_write_reliable(3,
- ((struct ble_gatt_attr[]){{8, 0, 0, NULL}}),
- 1, ble_gatt_conn_test_write_rel_cb,
- &write_rel_arg);
- TEST_ASSERT_FATAL(rc == 0);
-
- indicate_arg.exp_conn_handle = 3;
- rc = ble_gattc_indicate(3, attr_handle,
- ble_gatt_conn_test_indicate_cb,
- &indicate_arg);
+ rc = ble_gattc_write_reliable(
+ 3, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg);
TEST_ASSERT_FATAL(rc == 0);
/*** Start the procedures. */
@@ -502,7 +481,6 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
TEST_ASSERT(write_arg.called == 0);
TEST_ASSERT(write_long_arg.called == 0);
TEST_ASSERT(write_rel_arg.called == 0);
- TEST_ASSERT(indicate_arg.called == 0);
/* Connection 2. */
ble_gattc_connection_broken(2);
@@ -520,7 +498,6 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
TEST_ASSERT(write_arg.called == 0);
TEST_ASSERT(write_long_arg.called == 0);
TEST_ASSERT(write_rel_arg.called == 0);
- TEST_ASSERT(indicate_arg.called == 0);
/* Connection 3. */
ble_gattc_connection_broken(3);
@@ -538,11 +515,12 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
TEST_ASSERT(write_arg.called == 1);
TEST_ASSERT(write_long_arg.called == 1);
TEST_ASSERT(write_rel_arg.called == 1);
- TEST_ASSERT(indicate_arg.called == 1);
}
TEST_SUITE(ble_gatt_break_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_conn_test_disconnect();
}
diff --git a/net/nimble/host/src/test/ble_gatt_disc_c_test.c b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
index 6325926f..a4eb67bf 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_c_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
@@ -169,25 +169,33 @@ ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char *chars,
static int
ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_chr *chr, void *arg)
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
{
struct ble_gatt_chr *dst;
int *stop_after;
- TEST_ASSERT(error == NULL);
+ TEST_ASSERT(error != NULL);
TEST_ASSERT(!ble_gatt_disc_c_test_rx_complete);
stop_after = arg;
- if (chr == NULL) {
- ble_gatt_disc_c_test_rx_complete = 1;
- } else {
+ switch (error->status) {
+ case 0:
TEST_ASSERT_FATAL(ble_gatt_disc_c_test_num_chars <
BLE_GATT_DISC_C_TEST_MAX_CHARS);
dst = ble_gatt_disc_c_test_chars + ble_gatt_disc_c_test_num_chars++;
*dst = *chr;
+ break;
+
+ case BLE_HS_EDONE:
+ ble_gatt_disc_c_test_rx_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
}
if (*stop_after > 0) {
@@ -524,6 +532,8 @@ TEST_CASE(ble_gatt_disc_c_test_disc_uuid)
TEST_SUITE(ble_gatt_disc_c_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_disc_c_test_disc_all();
ble_gatt_disc_c_test_disc_uuid();
}
diff --git a/net/nimble/host/src/test/ble_gatt_disc_d_test.c b/net/nimble/host/src/test/ble_gatt_disc_d_test.c
index 6b0a8077..7e021e2e 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_d_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_d_test.c
@@ -28,7 +28,7 @@
#include "ble_hs_test_util.h"
struct ble_gatt_disc_d_test_dsc {
- uint16_t chr_def_handle; /* 0 if last entry. */
+ uint16_t chr_val_handle; /* 0 if last entry. */
uint16_t dsc_handle;
uint8_t dsc_uuid128[16];
};
@@ -74,7 +74,7 @@ ble_gatt_disc_d_test_misc_rx_rsp_once(
off = BLE_ATT_FIND_INFO_RSP_BASE_SZ;
for (i = 0; ; i++) {
- if (dscs[i].chr_def_handle == 0) {
+ if (dscs[i].chr_val_handle == 0) {
/* No more descriptors. */
break;
}
@@ -113,7 +113,7 @@ ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle,
int idx;
idx = 0;
- while (dscs[idx].chr_def_handle != 0) {
+ while (dscs[idx].chr_val_handle != 0) {
count = ble_gatt_disc_d_test_misc_rx_rsp_once(conn_handle, dscs + idx);
if (count == 0) {
break;
@@ -140,9 +140,9 @@ ble_gatt_disc_d_test_misc_verify_dscs(struct ble_gatt_disc_d_test_dsc *dscs,
stop_after = INT_MAX;
}
- for (i = 0; i < stop_after && dscs[i].chr_def_handle != 0; i++) {
- TEST_ASSERT(dscs[i].chr_def_handle ==
- ble_gatt_disc_d_test_dscs[i].chr_def_handle);
+ for (i = 0; i < stop_after && dscs[i].chr_val_handle != 0; i++) {
+ TEST_ASSERT(dscs[i].chr_val_handle ==
+ ble_gatt_disc_d_test_dscs[i].chr_val_handle);
TEST_ASSERT(dscs[i].dsc_handle ==
ble_gatt_disc_d_test_dscs[i].dsc_handle);
TEST_ASSERT(memcmp(dscs[i].dsc_uuid128,
@@ -156,28 +156,37 @@ ble_gatt_disc_d_test_misc_verify_dscs(struct ble_gatt_disc_d_test_dsc *dscs,
static int
ble_gatt_disc_d_test_misc_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- uint16_t chr_def_handle, struct ble_gatt_dsc *dsc,
+ const struct ble_gatt_error *error,
+ uint16_t chr_val_handle,
+ const struct ble_gatt_dsc *dsc,
void *arg)
{
struct ble_gatt_disc_d_test_dsc *dst;
int *stop_after;
- TEST_ASSERT(error == NULL);
+ TEST_ASSERT(error != NULL);
TEST_ASSERT(!ble_gatt_disc_d_test_rx_complete);
stop_after = arg;
- if (dsc == NULL) {
- ble_gatt_disc_d_test_rx_complete = 1;
- } else {
+ switch (error->status) {
+ case 0:
TEST_ASSERT_FATAL(ble_gatt_disc_d_test_num_dscs <
BLE_GATT_DISC_D_TEST_MAX_DSCS);
dst = ble_gatt_disc_d_test_dscs + ble_gatt_disc_d_test_num_dscs++;
- dst->chr_def_handle = chr_def_handle;
+ dst->chr_val_handle = chr_val_handle;
dst->dsc_handle = dsc->handle;
memcpy(dst->dsc_uuid128, dsc->uuid128, 16);
+ break;
+
+ case BLE_HS_EDONE:
+ ble_gatt_disc_d_test_rx_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
}
if (*stop_after > 0) {
@@ -192,7 +201,7 @@ ble_gatt_disc_d_test_misc_cb(uint16_t conn_handle,
}
static void
-ble_gatt_disc_d_test_misc_all(uint16_t chr_def_handle, uint16_t end_handle,
+ble_gatt_disc_d_test_misc_all(uint16_t chr_val_handle, uint16_t end_handle,
int stop_after,
struct ble_gatt_disc_d_test_dsc *dscs)
{
@@ -205,7 +214,7 @@ ble_gatt_disc_d_test_misc_all(uint16_t chr_def_handle, uint16_t end_handle,
NULL, NULL);
num_left = stop_after;
- rc = ble_gattc_disc_all_dscs(2, chr_def_handle, end_handle,
+ rc = ble_gattc_disc_all_dscs(2, chr_val_handle, end_handle,
ble_gatt_disc_d_test_misc_cb, &num_left);
TEST_ASSERT(rc == 0);
@@ -216,9 +225,9 @@ ble_gatt_disc_d_test_misc_all(uint16_t chr_def_handle, uint16_t end_handle,
TEST_CASE(ble_gatt_disc_d_test_1)
{
/*** One 16-bit descriptor. */
- ble_gatt_disc_d_test_misc_all(4, 10, 0,
+ ble_gatt_disc_d_test_misc_all(5, 10, 0,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 4,
+ .chr_val_handle = 5,
.dsc_handle = 6,
.dsc_uuid128 = BLE_UUID16_ARR(0x1234),
}, {
@@ -227,13 +236,13 @@ TEST_CASE(ble_gatt_disc_d_test_1)
);
/*** Two 16-bit descriptors. */
- ble_gatt_disc_d_test_misc_all(49, 100, 0,
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 51,
.dsc_uuid128 = BLE_UUID16_ARR(0x1111),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 52,
.dsc_uuid128 = BLE_UUID16_ARR(0x2222),
}, {
@@ -242,25 +251,25 @@ TEST_CASE(ble_gatt_disc_d_test_1)
);
/*** Five 16-bit descriptors. */
- ble_gatt_disc_d_test_misc_all(49, 100, 0,
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 51,
.dsc_uuid128 = BLE_UUID16_ARR(0x1111),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 52,
.dsc_uuid128 = BLE_UUID16_ARR(0x2222),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 53,
.dsc_uuid128 = BLE_UUID16_ARR(0x3333),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 54,
.dsc_uuid128 = BLE_UUID16_ARR(0x4444),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 55,
.dsc_uuid128 = BLE_UUID16_ARR(0x5555),
}, {
@@ -269,25 +278,25 @@ TEST_CASE(ble_gatt_disc_d_test_1)
);
/*** Interleaved 16-bit and 128-bit descriptors. */
- ble_gatt_disc_d_test_misc_all(49, 100, 0,
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 51,
.dsc_uuid128 = BLE_UUID16_ARR(0x1111),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 52,
.dsc_uuid128 = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 53,
.dsc_uuid128 = BLE_UUID16_ARR(0x3333),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 54,
.dsc_uuid128 = { 1,0,4,0,6,9,17,7,8,43,7,4,12,43,19,35 },
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 55,
.dsc_uuid128 = BLE_UUID16_ARR(0x5555),
}, {
@@ -296,13 +305,13 @@ TEST_CASE(ble_gatt_disc_d_test_1)
);
/*** Ends with final handle ID. */
- ble_gatt_disc_d_test_misc_all(49, 52, 0,
+ ble_gatt_disc_d_test_misc_all(50, 52, 0,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 51,
.dsc_uuid128 = BLE_UUID16_ARR(0x1111),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 52,
.dsc_uuid128 = BLE_UUID16_ARR(0x2222),
}, {
@@ -311,25 +320,25 @@ TEST_CASE(ble_gatt_disc_d_test_1)
);
/*** Stop after two descriptors. */
- ble_gatt_disc_d_test_misc_all(49, 100, 2,
+ ble_gatt_disc_d_test_misc_all(50, 100, 2,
((struct ble_gatt_disc_d_test_dsc[]) { {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 51,
.dsc_uuid128 = BLE_UUID16_ARR(0x1111),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 52,
.dsc_uuid128 = BLE_UUID16_ARR(0x2222),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 53,
.dsc_uuid128 = BLE_UUID16_ARR(0x3333),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 54,
.dsc_uuid128 = BLE_UUID16_ARR(0x4444),
}, {
- .chr_def_handle = 49,
+ .chr_val_handle = 50,
.dsc_handle = 55,
.dsc_uuid128 = BLE_UUID16_ARR(0x5555),
}, {
@@ -340,6 +349,8 @@ TEST_CASE(ble_gatt_disc_d_test_1)
TEST_SUITE(ble_gatt_disc_d_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_disc_d_test_1();
}
diff --git a/net/nimble/host/src/test/ble_gatt_disc_s_test.c b/net/nimble/host/src/test/ble_gatt_disc_s_test.c
index d7572b2c..2e278d6e 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_s_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_s_test.c
@@ -219,18 +219,28 @@ ble_gatt_disc_s_test_misc_verify_services(
static int
ble_gatt_disc_s_test_misc_disc_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_svc *service, void *arg)
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
{
- TEST_ASSERT(error == NULL);
+ TEST_ASSERT(error != NULL);
TEST_ASSERT(!ble_gatt_disc_s_test_rx_complete);
- if (service == NULL) {
- ble_gatt_disc_s_test_rx_complete = 1;
- } else {
+ switch (error->status) {
+ case 0:
+ TEST_ASSERT(service != NULL);
TEST_ASSERT_FATAL(ble_gatt_disc_s_test_num_svcs <
BLE_GATT_DISC_S_TEST_MAX_SERVICES);
ble_gatt_disc_s_test_svcs[ble_gatt_disc_s_test_num_svcs++] = *service;
+ break;
+
+ case BLE_HS_EDONE:
+ TEST_ASSERT(service == NULL);
+ ble_gatt_disc_s_test_rx_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
}
return 0;
@@ -381,6 +391,8 @@ TEST_CASE(ble_gatt_disc_s_test_disc_service_uuid)
TEST_SUITE(ble_gatt_disc_s_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_disc_s_test_disc_all();
ble_gatt_disc_s_test_disc_service_uuid();
}
diff --git a/net/nimble/host/src/test/ble_gatt_find_s_test.c b/net/nimble/host/src/test/ble_gatt_find_s_test.c
index dca1f367..c3ab93df 100644
--- a/net/nimble/host/src/test/ble_gatt_find_s_test.c
+++ b/net/nimble/host/src/test/ble_gatt_find_s_test.c
@@ -46,17 +46,25 @@ ble_gatt_find_s_test_misc_init(void)
static int
ble_gatt_find_s_test_misc_cb(uint16_t conn_handle,
- struct ble_gatt_error *error,
- struct ble_gatt_svc *service,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
void *arg)
{
TEST_ASSERT(!ble_gatt_find_s_test_proc_complete);
- TEST_ASSERT(error == NULL);
+ TEST_ASSERT(error != NULL);
- if (service == NULL) {
- ble_gatt_find_s_test_proc_complete = 1;
- } else {
+ switch (error->status) {
+ case 0:
ble_gatt_find_s_test_svcs[ble_gatt_find_s_test_num_svcs++] = *service;
+ break;
+
+ case BLE_HS_EDONE:
+ ble_gatt_find_s_test_proc_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
}
return 0;
@@ -320,6 +328,8 @@ TEST_CASE(ble_gatt_find_s_test_1)
TEST_SUITE(ble_gatt_find_s_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_find_s_test_1();
}
diff --git a/net/nimble/host/src/test/ble_gatt_read_test.c b/net/nimble/host/src/test/ble_gatt_read_test.c
index 03df56ec..822de5c7 100644
--- a/net/nimble/host/src/test/ble_gatt_read_test.c
+++ b/net/nimble/host/src/test/ble_gatt_read_test.c
@@ -57,7 +57,7 @@ ble_gatt_read_test_misc_init(void)
}
static int
-ble_gatt_read_test_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+ble_gatt_read_test_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_read_test_attr *dst;
@@ -65,7 +65,9 @@ ble_gatt_read_test_cb(uint16_t conn_handle, struct ble_gatt_error *error,
stop_after = arg;
- if (error != NULL) {
+ TEST_ASSERT_FATAL(error != NULL);
+
+ if (error->status != 0) {
ble_gatt_read_test_bad_conn_handle = conn_handle;
ble_gatt_read_test_bad_status = error->status;
ble_gatt_read_test_complete = 1;
@@ -81,12 +83,12 @@ ble_gatt_read_test_cb(uint16_t conn_handle, struct ble_gatt_error *error,
BLE_GATT_READ_TEST_MAX_ATTRS);
dst = ble_gatt_read_test_attrs + ble_gatt_read_test_num_attrs++;
- TEST_ASSERT_FATAL(attr->value_len <= sizeof dst->value);
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <= sizeof dst->value);
dst->conn_handle = conn_handle;
dst->handle = attr->handle;
- dst->value_len = attr->value_len;
- memcpy(dst->value, attr->value, attr->value_len);
+ dst->value_len = OS_MBUF_PKTLEN(attr->om);
+ os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), dst->value);
if (stop_after != NULL && *stop_after > 0) {
(*stop_after)--;
@@ -102,7 +104,8 @@ ble_gatt_read_test_cb(uint16_t conn_handle, struct ble_gatt_error *error,
}
static int
-ble_gatt_read_test_long_cb(uint16_t conn_handle, struct ble_gatt_error *error,
+ble_gatt_read_test_long_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
struct ble_gatt_read_test_attr *dst;
@@ -110,7 +113,9 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, struct ble_gatt_error *error,
reads_left = arg;
- if (error != NULL) {
+ TEST_ASSERT_FATAL(error != NULL);
+
+ if (error->status != 0) {
ble_gatt_read_test_bad_conn_handle = conn_handle;
ble_gatt_read_test_bad_status = error->status;
ble_gatt_read_test_complete = 1;
@@ -124,7 +129,8 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, struct ble_gatt_error *error,
dst = ble_gatt_read_test_attrs + 0;
- TEST_ASSERT_FATAL(attr->value_len <= dst->value_len + sizeof dst->value);
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <=
+ dst->value_len + sizeof dst->value);
TEST_ASSERT(attr->offset == dst->value_len);
if (attr->offset == 0) {
@@ -134,8 +140,9 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, struct ble_gatt_error *error,
TEST_ASSERT(conn_handle == dst->conn_handle);
TEST_ASSERT(attr->handle == dst->handle);
}
- memcpy(dst->value + dst->value_len, attr->value, attr->value_len);
- dst->value_len += attr->value_len;
+ os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om),
+ dst->value + dst->value_len);
+ dst->value_len += OS_MBUF_PKTLEN(attr->om);
if (reads_left != NULL && *reads_left > 0) {
(*reads_left)--;
@@ -151,7 +158,7 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, struct ble_gatt_error *error,
static void
ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,
uint8_t att_op,
- void *data, int data_len)
+ const void *data, int data_len)
{
uint8_t buf[1024];
int rc;
@@ -171,7 +178,7 @@ ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,
static void
ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle,
- struct ble_gatt_attr *attr)
+ struct ble_hs_test_util_flat_attr *attr)
{
ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, BLE_ATT_OP_READ_RSP,
attr->value,
@@ -190,8 +197,8 @@ ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle,
}
static int
-ble_gatt_read_test_misc_uuid_rx_rsp_good(uint16_t conn_handle,
- struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_uuid_rx_rsp_good(
+ uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs)
{
struct ble_att_read_type_rsp rsp;
uint8_t buf[1024];
@@ -233,7 +240,7 @@ ble_gatt_read_test_misc_uuid_rx_rsp_good(uint16_t conn_handle,
}
static void
-ble_gatt_read_test_misc_verify_good(struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr)
{
int rc;
@@ -256,7 +263,7 @@ ble_gatt_read_test_misc_verify_good(struct ble_gatt_attr *attr)
static void
ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
- struct ble_gatt_attr *attr)
+ struct ble_hs_test_util_flat_attr *attr)
{
int rc;
@@ -277,10 +284,9 @@ ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
}
static void
-ble_gatt_read_test_misc_uuid_verify_good(uint16_t start_handle,
- uint16_t end_handle, void *uuid128,
- int stop_after,
- struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_uuid_verify_good(
+ uint16_t start_handle, uint16_t end_handle, void *uuid128,
+ int stop_after, struct ble_hs_test_util_flat_attr *attrs)
{
int num_read;
int idx;
@@ -324,8 +330,8 @@ ble_gatt_read_test_misc_uuid_verify_good(uint16_t start_handle,
}
static void
-ble_gatt_read_test_misc_long_verify_good(int max_reads,
- struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_long_verify_good(
+ int max_reads, struct ble_hs_test_util_flat_attr *attr)
{
int reads_left;
int chunk_sz;
@@ -377,8 +383,8 @@ ble_gatt_read_test_misc_long_verify_good(int max_reads,
}
static void
-ble_gatt_read_test_misc_long_verify_bad(uint8_t att_status,
- struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_long_verify_bad(
+ uint8_t att_status, struct ble_hs_test_util_flat_attr *attr)
{
int rc;
@@ -400,8 +406,8 @@ ble_gatt_read_test_misc_long_verify_bad(uint8_t att_status,
}
static int
-ble_gatt_read_test_misc_extract_handles(struct ble_gatt_attr *attrs,
- uint16_t *handles)
+ble_gatt_read_test_misc_extract_handles(
+ struct ble_hs_test_util_flat_attr *attrs, uint16_t *handles)
{
int i;
@@ -412,7 +418,8 @@ ble_gatt_read_test_misc_extract_handles(struct ble_gatt_attr *attrs,
}
static void
-ble_gatt_read_test_misc_mult_verify_good(struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_mult_verify_good(
+ struct ble_hs_test_util_flat_attr *attrs)
{
uint8_t expected_value[512];
uint16_t handles[256];
@@ -458,9 +465,9 @@ ble_gatt_read_test_misc_mult_verify_good(struct ble_gatt_attr *attrs)
}
static void
-ble_gatt_read_test_misc_mult_verify_bad(uint8_t att_status,
- uint16_t err_handle,
- struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_mult_verify_bad(
+ uint8_t att_status, uint16_t err_handle,
+ struct ble_hs_test_util_flat_attr *attrs)
{
uint16_t handles[256];
int num_attrs;
@@ -488,39 +495,42 @@ ble_gatt_read_test_misc_mult_verify_bad(uint8_t att_status,
TEST_CASE(ble_gatt_read_test_by_handle)
{
/* Read a seven-byte attribute. */
- ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
} });
/* Read a one-byte attribute. */
- ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 0x5432,
- .value = (uint8_t[]){ 0xff },
+ .value = { 0xff },
.value_len = 1
} });
/* Read a 200-byte attribute. */
- ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 815,
- .value = (uint8_t[200]){ 0 },
+ .value = { 0 },
.value_len = 200,
} });
/* Fail due to attribute not found. */
ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 719,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
} });
/* Fail due to invalid PDU. */
ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_INVALID_PDU,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 65,
- .value = (uint8_t[]){ 0xfa, 0x4c },
+ .value = { 0xfa, 0x4c },
.value_len = 2
} });
}
@@ -529,9 +539,9 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
{
/* Read a single seven-byte attribute. */
ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
}, {
0,
@@ -539,13 +549,13 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
/* Read two seven-byte attributes; one response. */
ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
}, {
.handle = 44,
- .value = (uint8_t[]){ 2,3,4,5,6,7,8 },
+ .value = { 2,3,4,5,6,7,8 },
.value_len = 7
}, {
0,
@@ -553,13 +563,13 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
/* Read two attributes; two responses. */
ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
}, {
.handle = 44,
- .value = (uint8_t[]){ 2,3,4 },
+ .value = { 2,3,4 },
.value_len = 3
}, {
0,
@@ -567,25 +577,25 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
/* Stop after three reads. */
ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 3,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
}, {
.handle = 44,
- .value = (uint8_t[]){ 2,3,4 },
+ .value = { 2,3,4 },
.value_len = 3
}, {
.handle = 45,
- .value = (uint8_t[]){ 2,3,4 },
+ .value = { 2,3,4 },
.value_len = 3
}, {
.handle = 46,
- .value = (uint8_t[]){ 3,4,5,6 },
+ .value = { 3,4,5,6 },
.value_len = 4
}, {
.handle = 47,
- .value = (uint8_t[]){ 2,3,4 },
+ .value = { 2,3,4 },
.value_len = 3
}, {
0,
@@ -602,38 +612,52 @@ TEST_CASE(ble_gatt_read_test_long)
}
/* Read a seven-byte attribute. */
- ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_long_verify_good(0,
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = data512,
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
} });
/* Read a zero-byte attribute. */
- ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_long_verify_good(0,
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = NULL,
+ .value = { 0 },
.value_len = 0
} });
/* Read a 60-byte attribute; three requests. */
- ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_long_verify_good(0,
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 34,
- .value = data512,
+ .value = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
+ },
.value_len = 60
} });
/* Stop after two reads. */
- ble_gatt_read_test_misc_long_verify_good(2, (struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_long_verify_good(2,
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 34,
- .value = data512,
+ .value = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
+ },
.value_len = 60
} });
/* Fail due to attribute not found. */
ble_gatt_read_test_misc_long_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 719,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1, 2, 3, 4, 5, 6, 7 },
.value_len = 7
} });
}
@@ -648,60 +672,64 @@ TEST_CASE(ble_gatt_read_test_mult)
}
/* Read one attribute. */
- ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = data512,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
.value_len = 7
}, {
0
} });
/* Read two attributes. */
- ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = data512,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
.value_len = 7,
}, {
.handle = 44,
- .value = data512 + 7,
+ .value = { 8, 9, 10, 11 },
.value_len = 4,
}, {
0
} });
/* Read two attributes (swap order). */
- ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 44,
- .value = data512 + 7,
+ .value = { 8, 9, 10, 11 },
.value_len = 4,
}, {
.handle = 43,
- .value = data512,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
.value_len = 7,
}, {
0
} });
/* Read five attributes. */
- ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 43,
- .value = data512,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
.value_len = 7,
}, {
.handle = 44,
- .value = data512 + 7,
+ .value = { 8, 9, 10, 11 },
.value_len = 4,
}, {
.handle = 145,
- .value = data512 + 11,
+ .value = { 12, 13 },
.value_len = 2,
}, {
.handle = 191,
- .value = data512 + 13,
+ .value = { 14, 15, 16 },
.value_len = 3,
}, {
.handle = 352,
- .value = data512 + 16,
+ .value = { 17, 18, 19, 20 },
.value_len = 4,
}, {
0
@@ -709,21 +737,81 @@ TEST_CASE(ble_gatt_read_test_mult)
/* Fail due to attribute not found. */
ble_gatt_read_test_misc_mult_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND, 719,
- (struct ble_gatt_attr[]) { {
+ (struct ble_hs_test_util_flat_attr[]) { {
.handle = 719,
- .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+ .value = { 1,2,3,4,5,6,7 },
.value_len = 7
}, {
0
} });
}
+TEST_CASE(ble_gatt_read_test_concurrent)
+{
+ int rc;
+ int i;
+
+ ble_gatt_read_test_misc_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /***
+ * Perform three concurrent reads. Assert that each response is correctly
+ * matched up with its corresponding GATT procedure.
+ */
+
+ struct ble_hs_test_util_flat_attr attrs[3] = {
+ {
+ .handle = 1,
+ .offset = 0,
+ .value_len = 3,
+ .value = { 1, 2, 3 },
+ },
+ {
+ .handle = 2,
+ .offset = 0,
+ .value_len = 4,
+ .value = { 2, 3, 4, 5 },
+ },
+ {
+ .handle = 3,
+ .offset = 0,
+ .value_len = 5,
+ .value = { 3, 4, 5, 6, 7 },
+ },
+ };
+
+ rc = ble_gattc_read(2, attrs[0].handle, ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_gattc_read(2, attrs[1].handle, ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_gattc_read(2, attrs[2].handle, ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 0);
+ ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 1);
+ ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 2);
+
+ TEST_ASSERT(ble_gatt_read_test_num_attrs == 3);
+
+ for (i = 0; i < 3; i++) {
+ TEST_ASSERT(ble_gatt_read_test_attrs[i].handle == attrs[i].handle);
+ TEST_ASSERT(ble_gatt_read_test_attrs[i].value_len ==
+ attrs[i].value_len);
+ TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[i].value, attrs[i].value,
+ attrs[i].value_len) == 0);
+ }
+}
+
TEST_SUITE(ble_gatt_read_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_read_test_by_handle();
ble_gatt_read_test_by_uuid();
ble_gatt_read_test_long();
ble_gatt_read_test_mult();
+ ble_gatt_read_test_concurrent();
}
int
diff --git a/net/nimble/host/src/test/ble_gatt_write_test.c b/net/nimble/host/src/test/ble_gatt_write_test.c
index 56e88d36..f5481980 100644
--- a/net/nimble/host/src/test/ble_gatt_write_test.c
+++ b/net/nimble/host/src/test/ble_gatt_write_test.c
@@ -33,7 +33,7 @@ static int ble_gatt_write_test_cb_called;
static uint8_t ble_gatt_write_test_attr_value[BLE_ATT_ATTR_MAX_LEN];
static struct ble_gatt_error ble_gatt_write_test_error;
-static struct ble_gatt_attr *
+static struct ble_hs_test_util_flat_attr
ble_gatt_write_test_attrs[BLE_GATT_WRITE_TEST_MAX_ATTRS];
static int ble_gatt_write_test_num_attrs;
@@ -52,20 +52,22 @@ ble_gatt_write_test_init(void)
}
static int
-ble_gatt_write_test_cb_good(uint16_t conn_handle, struct ble_gatt_error *error,
+ble_gatt_write_test_cb_good(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg)
{
int *attr_len;
attr_len = arg;
+ TEST_ASSERT(error != NULL);
TEST_ASSERT(conn_handle == 2);
+
+ ble_gatt_write_test_error = *error;
+
if (attr_len != NULL) {
- TEST_ASSERT(error == NULL);
+ TEST_ASSERT(error->status == 0);
TEST_ASSERT(attr->handle == 100);
- } else {
- TEST_ASSERT(error != NULL);
- ble_gatt_write_test_error = *error;
}
ble_gatt_write_test_cb_called = 1;
@@ -88,7 +90,7 @@ ble_gatt_write_test_rx_rsp(uint16_t conn_handle)
static void
ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle,
uint16_t offset,
- void *attr_data, uint16_t attr_data_len)
+ const void *attr_data, uint16_t attr_data_len)
{
struct ble_att_prep_write_cmd rsp;
uint8_t buf[512];
@@ -121,6 +123,7 @@ ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle)
static void
ble_gatt_write_test_misc_long_good(int attr_len)
{
+ uint16_t mtu;
int off;
int len;
int rc;
@@ -130,24 +133,27 @@ ble_gatt_write_test_misc_long_good(int attr_len)
ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
NULL, NULL);
- rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
- attr_len, ble_gatt_write_test_cb_good,
- &attr_len);
+ mtu = ble_att_mtu(2);
+
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 2, 100, ble_gatt_write_test_attr_value, attr_len,
+ ble_gatt_write_test_cb_good, &attr_len);
TEST_ASSERT(rc == 0);
off = 0;
while (off < attr_len) {
- /* Send the pending ATT Prep Write Command. */
- ble_hs_test_util_tx_all();
-
- /* Receive Prep Write response. */
- len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
if (off + len > attr_len) {
len = attr_len - off;
}
- ble_gatt_write_test_rx_prep_rsp(2, 100, off,
- ble_gatt_write_test_attr_value + off,
- len);
+
+ /* Send the pending ATT Prep Write Command. */
+ ble_hs_test_util_verify_tx_prep_write(
+ 100, off, ble_gatt_write_test_attr_value + off, len);
+
+ /* Receive Prep Write response. */
+ ble_gatt_write_test_rx_prep_rsp(
+ 2, 100, off, ble_gatt_write_test_attr_value + off, len);
/* Verify callback hasn't gotten called. */
TEST_ASSERT(!ble_gatt_write_test_cb_called);
@@ -155,6 +161,9 @@ ble_gatt_write_test_misc_long_good(int attr_len)
off += len;
}
+ /* Verify execute write request sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_CONFIRM);
+
/* Receive Exec Write response. */
ble_hs_test_util_tx_all();
ble_gatt_write_test_rx_exec_rsp(2);
@@ -170,6 +179,7 @@ static void
ble_gatt_write_test_misc_long_bad(int attr_len,
ble_gatt_write_test_long_fail_fn *cb)
{
+ uint16_t mtu;
int fail_now;
int off;
int len;
@@ -179,17 +189,24 @@ ble_gatt_write_test_misc_long_bad(int attr_len,
ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
NULL, NULL);
+ mtu = ble_att_mtu(2);
- rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
- attr_len, ble_gatt_write_test_cb_good, NULL);
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 2, 100, ble_gatt_write_test_attr_value, attr_len,
+ ble_gatt_write_test_cb_good, NULL);
TEST_ASSERT(rc == 0);
fail_now = 0;
off = 0;
while (off < attr_len) {
+ len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ if (off + len > attr_len) {
+ len = attr_len - off;
+ }
+
/* Send the pending ATT Prep Write Command. */
- ble_hs_test_util_tx_all();
- TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL);
+ ble_hs_test_util_verify_tx_prep_write(
+ 100, off, ble_gatt_write_test_attr_value + off, len);
/* Receive Prep Write response. */
len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
@@ -255,7 +272,7 @@ ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle,
static int
ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
- struct ble_gatt_error *error,
+ const struct ble_gatt_error *error,
struct ble_gatt_attr *attrs,
uint8_t num_attrs, void *arg)
{
@@ -267,7 +284,8 @@ ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
ble_gatt_write_test_num_attrs = num_attrs;
for (i = 0; i < num_attrs; i++) {
- ble_gatt_write_test_attrs[i] = attrs + i;
+ ble_hs_test_util_attr_to_flat(ble_gatt_write_test_attrs + i,
+ attrs + i);
}
ble_gatt_write_test_cb_called = 1;
@@ -276,38 +294,66 @@ ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
}
static void
-ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
+ble_gatt_write_test_misc_reliable_good(
+ struct ble_hs_test_util_flat_attr *flat_attrs)
{
+ const struct ble_hs_test_util_flat_attr *attr;
+ struct ble_gatt_attr attrs[16];
+ uint16_t mtu;
int num_attrs;
int attr_idx;
+ int len;
+ int off;
int rc;
int i;
ble_gatt_write_test_init();
- for (num_attrs = 0; attrs[num_attrs].handle != 0; num_attrs++)
- ;
+ for (num_attrs = 0; flat_attrs[num_attrs].handle != 0; num_attrs++) {
+ TEST_ASSERT_FATAL(num_attrs < sizeof attrs / sizeof attrs[0]);
+ ble_hs_test_util_attr_from_flat(attrs + num_attrs,
+ flat_attrs + num_attrs);
+ }
ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
NULL, NULL);
+ mtu = ble_att_mtu(2);
rc = ble_gattc_write_reliable(2, attrs, num_attrs,
ble_gatt_write_test_reliable_cb_good, NULL);
TEST_ASSERT(rc == 0);
- for (attr_idx = 0; attr_idx < num_attrs; attr_idx++) {
+ attr_idx = 0;
+ off = 0;
+ while (attr_idx < num_attrs) {
+ attr = flat_attrs + attr_idx;
+
+ len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ if (off + len > attr->value_len) {
+ len = attr->value_len - off;
+ }
+
/* Send the pending ATT Prep Write Command. */
- ble_hs_test_util_tx_all();
+ ble_hs_test_util_verify_tx_prep_write(attr->handle, off,
+ attr->value + off, len);
/* Receive Prep Write response. */
- ble_gatt_write_test_rx_prep_rsp(2, attrs[attr_idx].handle, 0,
- attrs[attr_idx].value,
- attrs[attr_idx].value_len);
+ ble_gatt_write_test_rx_prep_rsp(2, attr->handle, off,
+ attr->value + off, len);
/* Verify callback hasn't gotten called. */
TEST_ASSERT(!ble_gatt_write_test_cb_called);
+
+ off += len;
+ if (off >= attr->value_len) {
+ attr_idx++;
+ off = 0;
+ }
}
+ /* Verify execute write request sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_CONFIRM);
+
/* Receive Exec Write response. */
ble_hs_test_util_tx_all();
ble_gatt_write_test_rx_exec_rsp(2);
@@ -316,7 +362,9 @@ ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
TEST_ASSERT(ble_gatt_write_test_cb_called);
TEST_ASSERT(ble_gatt_write_test_num_attrs == num_attrs);
for (i = 0; i < num_attrs; i++) {
- TEST_ASSERT(ble_gatt_write_test_attrs[i] == attrs + i);
+ rc = ble_hs_test_util_flat_attr_cmp(
+ ble_gatt_write_test_attrs + i, flat_attrs + i);
+ TEST_ASSERT(rc == 0);
}
}
@@ -331,8 +379,8 @@ TEST_CASE(ble_gatt_write_test_no_rsp)
NULL, NULL);
attr_len = 4;
- rc = ble_gattc_write_no_rsp(2, 100, ble_gatt_write_test_attr_value,
- attr_len);
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(
+ 2, 100, ble_gatt_write_test_attr_value, attr_len);
TEST_ASSERT(rc == 0);
/* Send the pending ATT Write Command. */
@@ -352,8 +400,9 @@ TEST_CASE(ble_gatt_write_test_rsp)
NULL, NULL);
attr_len = 4;
- ble_gattc_write(2, 100, ble_gatt_write_test_attr_value, attr_len,
- ble_gatt_write_test_cb_good, &attr_len);
+ ble_hs_test_util_gatt_write_flat(2, 100, ble_gatt_write_test_attr_value,
+ attr_len, ble_gatt_write_test_cb_good,
+ &attr_len);
/* Send the pending ATT Write Command. */
ble_hs_test_util_tx_all();
@@ -458,42 +507,57 @@ TEST_CASE(ble_gatt_write_test_reliable_good)
{
/*** 1 attribute. */
ble_gatt_write_test_misc_reliable_good(
- ((struct ble_gatt_attr[]) { {
+ ((struct ble_hs_test_util_flat_attr[]) { {
.handle = 100,
.value_len = 2,
- .value = (uint8_t[]){ 1, 2 },
+ .value = { 1, 2 },
}, {
0
} }));
/*** 2 attributes. */
ble_gatt_write_test_misc_reliable_good(
- ((struct ble_gatt_attr[]) { {
+ ((struct ble_hs_test_util_flat_attr[]) { {
.handle = 100,
.value_len = 2,
- .value = (uint8_t[]){ 1,2 },
+ .value = { 1,2 },
}, {
.handle = 113,
.value_len = 6,
- .value = (uint8_t[]){ 5,6,7,8,9,10 },
+ .value = { 5,6,7,8,9,10 },
}, {
0
} }));
/*** 3 attributes. */
ble_gatt_write_test_misc_reliable_good(
- ((struct ble_gatt_attr[]) { {
+ ((struct ble_hs_test_util_flat_attr[]) { {
.handle = 100,
.value_len = 2,
- .value = (uint8_t[]){ 1,2 },
+ .value = { 1,2 },
}, {
.handle = 113,
.value_len = 6,
- .value = (uint8_t[]){ 5,6,7,8,9,10 },
+ .value = { 5,6,7,8,9,10 },
}, {
.handle = 144,
.value_len = 1,
- .value = (uint8_t[]){ 0xff },
+ .value = { 0xff },
+ }, {
+ 0
+ } }));
+
+ /*** Long attributes. */
+ ble_gatt_write_test_misc_reliable_good(
+ ((struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 100,
+ .value_len = 20,
+ .value = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 },
+ }, {
+ .handle = 144,
+ .value_len = 20,
+ .value = { 11,12,13,14,15,16,17,18,19,110,
+ 111,112,113,114,115,116,117,118,119,120 },
}, {
0
} }));
@@ -511,8 +575,9 @@ TEST_CASE(ble_gatt_write_test_long_queue_full)
ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
NULL, NULL);
- rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
- 128, ble_gatt_write_test_cb_good, NULL);
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 2, 100, ble_gatt_write_test_attr_value, 128,
+ ble_gatt_write_test_cb_good, NULL);
TEST_ASSERT(rc == 0);
off = 0;
@@ -552,6 +617,8 @@ TEST_CASE(ble_gatt_write_test_long_queue_full)
TEST_SUITE(ble_gatt_write_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatt_write_test_no_rsp();
ble_gatt_write_test_rsp();
ble_gatt_write_test_long_good();
diff --git a/net/nimble/host/src/test/ble_gatts_notify_test.c b/net/nimble/host/src/test/ble_gatts_notify_test.c
index 6a0f2188..4e2d587c 100644
--- a/net/nimble/host/src/test/ble_gatts_notify_test.c
+++ b/net/nimble/host/src/test/ble_gatts_notify_test.c
@@ -29,16 +29,17 @@
#define BLE_GATTS_NOTIFY_TEST_CHR_1_UUID 0x1111
#define BLE_GATTS_NOTIFY_TEST_CHR_2_UUID 0x2222
-static uint8_t ble_gatts_peer_addr[6] = {2,3,4,5,6,7};
+#define BLE_GATTS_NOTIFY_TEST_MAX_EVENTS 16
+
+static uint8_t ble_gatts_notify_test_peer_addr[6] = {2,3,4,5,6,7};
static int
ble_gatts_notify_test_misc_access(uint16_t conn_handle,
- uint16_t attr_handle, uint8_t op,
- union ble_gatt_access_ctxt *ctxt,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
void *arg);
static void
-ble_gatts_notify_test_misc_reg_cb(uint8_t op,
- union ble_gatt_register_ctxt *ctxt,
+ble_gatts_notify_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
void *arg);
static const struct ble_gatt_svc_def ble_gatts_notify_test_svcs[] = { {
@@ -69,10 +70,34 @@ static uint16_t ble_gatts_notify_test_chr_2_def_handle;
static uint8_t ble_gatts_notify_test_chr_2_val[1024];
static int ble_gatts_notify_test_chr_2_len;
+static struct ble_gap_event
+ble_gatts_notify_test_events[BLE_GATTS_NOTIFY_TEST_MAX_EVENTS];
+
+static int ble_gatts_notify_test_num_events;
+
typedef int ble_store_write_fn(int obj_type, union ble_store_value *val);
typedef int ble_store_delete_fn(int obj_type, union ble_store_key *key);
+static int
+ble_gatts_notify_test_util_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_NOTIFY_TX:
+ case BLE_GAP_EVENT_SUBSCRIBE:
+ TEST_ASSERT_FATAL(ble_gatts_notify_test_num_events <
+ BLE_GATTS_NOTIFY_TEST_MAX_EVENTS);
+
+ ble_gatts_notify_test_events[ble_gatts_notify_test_num_events++] =
+ *event;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static uint16_t
ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,
uint16_t chr_def_handle)
@@ -102,9 +127,9 @@ ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,
}
static void
-ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,
- uint16_t chr_def_handle,
- uint16_t flags)
+ble_gatts_notify_test_misc_try_enable_notify(uint16_t conn_handle,
+ uint16_t chr_def_handle,
+ uint16_t flags, int fail)
{
struct ble_att_write_req req;
uint8_t buf[BLE_ATT_WRITE_REQ_BASE_SZ + 2];
@@ -116,7 +141,86 @@ ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,
htole16(buf + BLE_ATT_WRITE_REQ_BASE_SZ, flags);
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
- TEST_ASSERT(rc == 0);
+ if (fail) {
+ TEST_ASSERT_FATAL(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
+ req.bawq_handle,
+ BLE_ATT_ERR_REQ_NOT_SUPPORTED);
+ } else {
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_test_util_verify_tx_write_rsp();
+ }
+}
+
+static void
+ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,
+ uint16_t chr_def_handle,
+ uint16_t flags)
+{
+ ble_gatts_notify_test_misc_try_enable_notify(conn_handle,
+ chr_def_handle,
+ flags, 0);
+}
+
+static void
+ble_gatts_notify_test_util_next_event(struct ble_gap_event *event)
+{
+ TEST_ASSERT_FATAL(ble_gatts_notify_test_num_events > 0);
+
+ *event = *ble_gatts_notify_test_events;
+
+ ble_gatts_notify_test_num_events--;
+ if (ble_gatts_notify_test_num_events > 0) {
+ memmove(ble_gatts_notify_test_events + 0,
+ ble_gatts_notify_test_events + 1,
+ ble_gatts_notify_test_num_events * sizeof *event);
+ }
+}
+
+static void
+ble_gatts_notify_test_util_verify_sub_event(uint16_t conn_handle,
+ uint8_t attr_handle,
+ uint8_t reason,
+ uint8_t prevn, uint8_t curn,
+ uint8_t previ, uint8_t curi)
+{
+ struct ble_gap_event event;
+
+ ble_gatts_notify_test_util_next_event(&event);
+
+ TEST_ASSERT(event.type == BLE_GAP_EVENT_SUBSCRIBE);
+ TEST_ASSERT(event.subscribe.conn_handle == conn_handle);
+ TEST_ASSERT(event.subscribe.attr_handle == attr_handle);
+ TEST_ASSERT(event.subscribe.reason == reason);
+ TEST_ASSERT(event.subscribe.prev_notify == prevn);
+ TEST_ASSERT(event.subscribe.cur_notify == curn);
+ TEST_ASSERT(event.subscribe.prev_indicate == previ);
+ TEST_ASSERT(event.subscribe.cur_indicate == curi);
+}
+
+static void
+ble_gatts_notify_test_util_verify_tx_event(uint16_t conn_handle,
+ uint8_t attr_handle,
+ int status,
+ int indication)
+{
+ struct ble_gap_event event;
+
+ ble_gatts_notify_test_util_next_event(&event);
+
+ TEST_ASSERT(event.type == BLE_GAP_EVENT_NOTIFY_TX);
+ TEST_ASSERT(event.notify_tx.status == status);
+ TEST_ASSERT(event.notify_tx.conn_handle == conn_handle);
+ TEST_ASSERT(event.notify_tx.attr_handle == attr_handle);
+ TEST_ASSERT(event.notify_tx.indication == indication);
+}
+
+static void
+ble_gatts_notify_test_util_verify_ack_event(uint16_t conn_handle,
+ uint8_t attr_handle)
+{
+ ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle,
+ BLE_HS_EDONE, 1);
}
static void
@@ -130,6 +234,8 @@ ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
ble_hs_test_util_init();
+ ble_gatts_notify_test_num_events = 0;
+
ble_hs_test_util_store_init(10, 10, 10);
ble_hs_cfg.store_read_cb = ble_hs_test_util_store_read;
ble_hs_cfg.store_write_cb = ble_hs_test_util_store_write;
@@ -142,7 +248,8 @@ ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
ble_gatts_start();
- ble_hs_test_util_create_conn(2, ble_gatts_peer_addr, NULL, NULL);
+ ble_hs_test_util_create_conn(2, ble_gatts_notify_test_peer_addr,
+ ble_gatts_notify_test_util_gap_event, NULL);
*out_conn_handle = 2;
if (bonding) {
@@ -163,16 +270,35 @@ ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
2, ble_gatts_notify_test_chr_2_def_handle);
TEST_ASSERT(flags == 0);
- /* Set initial notification / indication state. */
+ /* Set initial notification / indication state and verify that subscription
+ * callback gets executed.
+ */
if (chr1_flags != 0) {
ble_gatts_notify_test_misc_enable_notify(
2, ble_gatts_notify_test_chr_1_def_handle, chr1_flags);
+
+ ble_gatts_notify_test_util_verify_sub_event(
+ *out_conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_WRITE,
+ 0, chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
+ 0, chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
}
if (chr2_flags != 0) {
ble_gatts_notify_test_misc_enable_notify(
2, ble_gatts_notify_test_chr_2_def_handle, chr2_flags);
+
+ ble_gatts_notify_test_util_verify_sub_event(
+ *out_conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_WRITE,
+ 0, chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
+ 0, chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
}
+ /* Ensure no extraneous subscription callbacks were executed. */
+ TEST_ASSERT(ble_gatts_notify_test_num_events == 0);
+
/* Toss both write responses. */
ble_hs_test_util_prev_tx_queue_clear();
@@ -185,42 +311,76 @@ ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
TEST_ASSERT(flags == chr2_flags);
/* Ensure both CCCDs still persisted. */
- exp_num_cccds = (chr1_flags != 0) + (chr2_flags != 0);
+ if (bonding) {
+ exp_num_cccds = (chr1_flags != 0) + (chr2_flags != 0);
+ } else {
+ exp_num_cccds = 0;
+ }
TEST_ASSERT(ble_hs_test_util_store_num_cccds == exp_num_cccds);
}
static void
-ble_gatts_restore_bonding(uint16_t conn_handle)
+ble_gatts_notify_test_disconnect(uint16_t conn_handle,
+ uint8_t chr1_flags,
+ uint8_t chr1_indicate_in_progress,
+ uint8_t chr2_flags,
+ uint8_t chr2_indicate_in_progress)
{
- struct ble_hs_conn *conn;
+ ble_hs_test_util_conn_disconnect(conn_handle);
- ble_hs_lock();
- conn = ble_hs_conn_find(conn_handle);
- TEST_ASSERT_FATAL(conn != NULL);
- conn->bhc_sec_state.encrypted = 1;
- conn->bhc_sec_state.authenticated = 1;
- conn->bhc_sec_state.bonded = 1;
- ble_hs_unlock();
+ if (chr1_indicate_in_progress) {
+ ble_gatts_notify_test_util_verify_tx_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ BLE_HS_ENOTCONN,
+ 1);
+ }
- ble_gatts_bonding_restored(conn_handle);
+ /* Verify subscription callback executed for each subscribed
+ * characteristic.
+ */
+ if (chr1_flags != 0) {
+ ble_gatts_notify_test_util_verify_sub_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_TERM,
+ chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
+ chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE, 0);
+ }
+
+ if (chr2_indicate_in_progress) {
+ ble_gatts_notify_test_util_verify_tx_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ BLE_HS_ENOTCONN,
+ 1);
+ }
+
+ if (chr2_flags != 0) {
+ ble_gatts_notify_test_util_verify_sub_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_TERM,
+ chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
+ chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE, 0);
+ }
}
static void
-ble_gatts_notify_test_misc_reg_cb(uint8_t op,
- union ble_gatt_register_ctxt *ctxt,
+ble_gatts_notify_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
void *arg)
{
uint16_t uuid16;
- if (op == BLE_GATT_REGISTER_OP_CHR) {
- uuid16 = ble_uuid_128_to_16(ctxt->chr_reg.chr->uuid128);
+ if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) {
+ uuid16 = ble_uuid_128_to_16(ctxt->chr.chr_def->uuid128);
switch (uuid16) {
case BLE_GATTS_NOTIFY_TEST_CHR_1_UUID:
- ble_gatts_notify_test_chr_1_def_handle = ctxt->chr_reg.def_handle;
+ ble_gatts_notify_test_chr_1_def_handle = ctxt->chr.def_handle;
break;
case BLE_GATTS_NOTIFY_TEST_CHR_2_UUID:
- ble_gatts_notify_test_chr_2_def_handle = ctxt->chr_reg.def_handle;
+ ble_gatts_notify_test_chr_2_def_handle = ctxt->chr.def_handle;
break;
default:
@@ -232,32 +392,37 @@ ble_gatts_notify_test_misc_reg_cb(uint8_t op,
static int
ble_gatts_notify_test_misc_access(uint16_t conn_handle,
- uint16_t attr_handle, uint8_t op,
- union ble_gatt_access_ctxt *ctxt,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
void *arg)
{
- TEST_ASSERT_FATAL(op == BLE_GATT_ACCESS_OP_READ_CHR);
+ int rc;
+
+ TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
TEST_ASSERT(conn_handle == 0xffff);
if (attr_handle == ble_gatts_notify_test_chr_1_def_handle + 1) {
- TEST_ASSERT(ctxt->chr_access.chr ==
+ TEST_ASSERT(ctxt->chr ==
&ble_gatts_notify_test_svcs[0].characteristics[0]);
- ctxt->chr_access.data = ble_gatts_notify_test_chr_1_val;
- ctxt->chr_access.len = ble_gatts_notify_test_chr_1_len;
+ rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
+ TEST_ASSERT_FATAL(rc == 0);
} else if (attr_handle == ble_gatts_notify_test_chr_2_def_handle + 1) {
- TEST_ASSERT(ctxt->chr_access.chr ==
+ TEST_ASSERT(ctxt->chr ==
&ble_gatts_notify_test_svcs[0].characteristics[1]);
- ctxt->chr_access.data = ble_gatts_notify_test_chr_2_val;
- ctxt->chr_access.len = ble_gatts_notify_test_chr_2_len;
+ rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
+ TEST_ASSERT_FATAL(rc == 0);
} else {
- TEST_ASSERT(0);
+ TEST_ASSERT_FATAL(0);
}
return 0;
}
static void
-ble_gatts_notify_test_misc_rx_indicate_rsp(uint16_t conn_handle)
+ble_gatts_notify_test_misc_rx_indicate_rsp(uint16_t conn_handle,
+ uint16_t attr_handle)
{
uint8_t buf[BLE_ATT_INDICATE_RSP_SZ];
int rc;
@@ -267,11 +432,15 @@ ble_gatts_notify_test_misc_rx_indicate_rsp(uint16_t conn_handle)
rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
buf, sizeof buf);
TEST_ASSERT(rc == 0);
+
+ ble_gatts_notify_test_util_verify_ack_event(conn_handle, attr_handle);
}
static void
-ble_gatts_notify_test_misc_verify_tx_n(uint8_t *attr_data, int attr_len)
+ble_gatts_notify_test_misc_verify_tx_n(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint8_t *attr_data, int attr_len)
{
struct ble_att_notify_req req;
struct os_mbuf *om;
@@ -283,15 +452,20 @@ ble_gatts_notify_test_misc_verify_tx_n(uint8_t *attr_data, int attr_len)
TEST_ASSERT_FATAL(om != NULL);
ble_att_notify_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.banq_handle == attr_handle);
for (i = 0; i < attr_len; i++) {
TEST_ASSERT(om->om_data[BLE_ATT_NOTIFY_REQ_BASE_SZ + i] ==
attr_data[i]);
}
+
+ ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle, 0, 0);
}
static void
-ble_gatts_notify_test_misc_verify_tx_i(uint8_t *attr_data, int attr_len)
+ble_gatts_notify_test_misc_verify_tx_i(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint8_t *attr_data, int attr_len)
{
struct ble_att_indicate_req req;
struct os_mbuf *om;
@@ -303,33 +477,117 @@ ble_gatts_notify_test_misc_verify_tx_i(uint8_t *attr_data, int attr_len)
TEST_ASSERT_FATAL(om != NULL);
ble_att_indicate_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.baiq_handle == attr_handle);
for (i = 0; i < attr_len; i++) {
TEST_ASSERT(om->om_data[BLE_ATT_INDICATE_REQ_BASE_SZ + i] ==
attr_data[i]);
}
+
+ ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle, 0, 1);
}
-TEST_CASE(ble_gatts_notify_test_n)
+static void
+ble_gatts_notify_test_misc_verify_tx_gen(uint16_t conn_handle, int attr_idx,
+ uint8_t chr_flags)
{
- uint16_t conn_handle;
- uint16_t flags;
+ uint16_t attr_handle;
+ uint16_t attr_len;
+ void *attr_val;
+
+ switch (attr_idx) {
+ case 1:
+ attr_handle = ble_gatts_notify_test_chr_1_def_handle + 1;
+ attr_len = ble_gatts_notify_test_chr_1_len;
+ attr_val = ble_gatts_notify_test_chr_1_val;
+ break;
+
+ case 2:
+ attr_handle = ble_gatts_notify_test_chr_2_def_handle + 1;
+ attr_len = ble_gatts_notify_test_chr_2_len;
+ attr_val = ble_gatts_notify_test_chr_2_val;
+ break;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ break;
+ }
- ble_gatts_notify_test_misc_init(&conn_handle, 0, 0, 0);
+ switch (chr_flags) {
+ case 0:
+ break;
- /* Enable notifications on both characteristics. */
- ble_gatts_notify_test_misc_enable_notify(
- conn_handle, ble_gatts_notify_test_chr_1_def_handle,
- BLE_GATTS_CLT_CFG_F_NOTIFY);
- ble_gatts_notify_test_misc_enable_notify(
- conn_handle, ble_gatts_notify_test_chr_2_def_handle,
- BLE_GATTS_CLT_CFG_F_NOTIFY);
+ case BLE_GATTS_CLT_CFG_F_NOTIFY:
+ ble_gatts_notify_test_misc_verify_tx_n(conn_handle, attr_handle,
+ attr_val, attr_len);
+ break;
- /* Toss both write responses. */
- ble_hs_test_util_prev_tx_queue_clear();
+ case BLE_GATTS_CLT_CFG_F_INDICATE:
+ ble_gatts_notify_test_misc_verify_tx_i(conn_handle, attr_handle,
+ attr_val, attr_len);
+ break;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ break;
+ }
+}
+
+static void
+ble_gatts_notify_test_restore_bonding(uint16_t conn_handle,
+ uint8_t chr1_flags, uint8_t chr1_tx,
+ uint8_t chr2_flags, uint8_t chr2_tx)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.encrypted = 1;
+ conn->bhc_sec_state.authenticated = 1;
+ conn->bhc_sec_state.bonded = 1;
+ ble_hs_unlock();
+
+ ble_gatts_bonding_restored(conn_handle);
+
+ /* Verify subscription callback executed for each subscribed
+ * characteristic.
+ */
+ if (chr1_flags != 0) {
+ ble_gatts_notify_test_util_verify_sub_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_RESTORE,
+ 0, chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
+ 0, chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ }
+ if (chr1_tx) {
+ ble_gatts_notify_test_misc_verify_tx_gen(conn_handle, 1, chr1_flags);
+ }
- /* Ensure nothing got persisted since peer is not bonded. */
- TEST_ASSERT(ble_hs_test_util_store_num_cccds == 0);
+
+ if (chr2_flags != 0) {
+ ble_gatts_notify_test_util_verify_sub_event(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ BLE_GAP_SUBSCRIBE_REASON_RESTORE,
+ 0, chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
+ 0, chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+ }
+ if (chr2_tx) {
+ ble_gatts_notify_test_misc_verify_tx_gen(conn_handle, 2, chr2_flags);
+ }
+}
+
+TEST_CASE(ble_gatts_notify_test_n)
+{
+ uint16_t conn_handle;
+ uint16_t flags;
+
+ ble_gatts_notify_test_misc_init(&conn_handle, 0,
+ BLE_GATTS_CLT_CFG_F_NOTIFY,
+ BLE_GATTS_CLT_CFG_F_NOTIFY);
/* Ensure notifications read back as enabled. */
flags = ble_gatts_notify_test_misc_read_notify(
@@ -345,8 +603,11 @@ TEST_CASE(ble_gatts_notify_test_n)
ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
/* Verify notification sent properly. */
- ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_misc_verify_tx_n(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
/* Update characteristic 2's value. */
ble_gatts_notify_test_chr_2_len = 16;
@@ -355,15 +616,20 @@ TEST_CASE(ble_gatts_notify_test_n)
ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
/* Verify notification sent properly. */
- ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_2_val,
- ble_gatts_notify_test_chr_2_len);
+ ble_gatts_notify_test_misc_verify_tx_n(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
/***
* Disconnect, modify characteristic values, and reconnect. Ensure
* notifications are not sent and are no longer enabled.
*/
- ble_hs_test_util_conn_disconnect(conn_handle);
+ ble_gatts_notify_test_disconnect(conn_handle,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
/* Update characteristic 1's value. */
ble_gatts_notify_test_chr_1_len = 1;
@@ -377,7 +643,7 @@ TEST_CASE(ble_gatts_notify_test_n)
ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
- NULL, NULL);
+ ble_gatts_notify_test_util_gap_event, NULL);
/* Ensure no notifications sent. */
TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
@@ -396,29 +662,9 @@ TEST_CASE(ble_gatts_notify_test_i)
uint16_t conn_handle;
uint16_t flags;
- ble_gatts_notify_test_misc_init(&conn_handle, 0, 0, 0);
-
- /* Enable indications on both characteristics. */
- ble_gatts_notify_test_misc_enable_notify(
- conn_handle, ble_gatts_notify_test_chr_1_def_handle,
- BLE_GATTS_CLT_CFG_F_INDICATE);
- ble_gatts_notify_test_misc_enable_notify(
- conn_handle, ble_gatts_notify_test_chr_2_def_handle,
- BLE_GATTS_CLT_CFG_F_INDICATE);
-
- /* Toss both write responses. */
- ble_hs_test_util_prev_tx_queue_clear();
-
- /* Ensure nothing got persisted since peer is not bonded. */
- TEST_ASSERT(ble_hs_test_util_store_num_cccds == 0);
-
- /* Ensure indications read back as enabled. */
- flags = ble_gatts_notify_test_misc_read_notify(
- conn_handle, ble_gatts_notify_test_chr_1_def_handle);
- TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
- flags = ble_gatts_notify_test_misc_read_notify(
- conn_handle, ble_gatts_notify_test_chr_2_def_handle);
- TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+ ble_gatts_notify_test_misc_init(&conn_handle, 0,
+ BLE_GATTS_CLT_CFG_F_INDICATE,
+ BLE_GATTS_CLT_CFG_F_INDICATE);
/* Update characteristic 1's value. */
ble_gatts_notify_test_chr_1_len = 1;
@@ -426,8 +672,11 @@ TEST_CASE(ble_gatts_notify_test_i)
ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
/* Verify indication sent properly. */
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_misc_verify_tx_i(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
/* Update characteristic 2's value. */
ble_gatts_notify_test_chr_2_len = 16;
@@ -442,15 +691,22 @@ TEST_CASE(ble_gatts_notify_test_i)
TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
/* Receive the confirmation for the first indication. */
- ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1);
/* Verify indication sent properly. */
ble_hs_test_util_tx_all();
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_2_val,
- ble_gatts_notify_test_chr_2_len);
+ ble_gatts_notify_test_misc_verify_tx_i(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
/* Receive the confirmation for the second indication. */
- ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1);
/* Verify no pending GATT jobs. */
TEST_ASSERT(!ble_gattc_any_jobs());
@@ -460,7 +716,9 @@ TEST_CASE(ble_gatts_notify_test_i)
* indications are not sent and are no longer enabled.
*/
- ble_hs_test_util_conn_disconnect(conn_handle);
+ ble_gatts_notify_test_disconnect(conn_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0);
/* Update characteristic 1's value. */
ble_gatts_notify_test_chr_1_len = 1;
@@ -474,7 +732,7 @@ TEST_CASE(ble_gatts_notify_test_i)
ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
- NULL, NULL);
+ ble_gatts_notify_test_util_gap_event, NULL);
/* Ensure no indications sent. */
TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
@@ -498,7 +756,9 @@ TEST_CASE(ble_gatts_notify_test_bonded_n)
BLE_GATTS_CLT_CFG_F_NOTIFY);
/* Disconnect. */
- ble_hs_test_util_conn_disconnect(conn_handle);
+ ble_gatts_notify_test_disconnect(conn_handle,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
/* Ensure both CCCDs still persisted. */
TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
@@ -519,8 +779,9 @@ TEST_CASE(ble_gatts_notify_test_bonded_n)
*/
ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
- NULL, NULL);
+ ble_gatts_notify_test_util_gap_event, NULL);
+ ble_gatts_notify_test_num_events = 0;
/* Ensure no notifications sent. */
TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
@@ -533,13 +794,9 @@ TEST_CASE(ble_gatts_notify_test_bonded_n)
TEST_ASSERT(flags == 0);
/* Simulate a successful encryption procedure (bonding restoration). */
- ble_gatts_restore_bonding(conn_handle);
-
- /* Verify notifications sent properly. */
- ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
- ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_2_val,
- ble_gatts_notify_test_chr_2_len);
+ ble_gatts_notify_test_restore_bonding(conn_handle,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 1,
+ BLE_GATTS_CLT_CFG_F_NOTIFY, 1);
/* Ensure notifications enabled. */
flags = ble_gatts_notify_test_misc_read_notify(
@@ -563,7 +820,9 @@ TEST_CASE(ble_gatts_notify_test_bonded_i)
BLE_GATTS_CLT_CFG_F_INDICATE);
/* Disconnect. */
- ble_hs_test_util_conn_disconnect(conn_handle);
+ ble_gatts_notify_test_disconnect(conn_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0);
/* Ensure both CCCDs still persisted. */
TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
@@ -584,7 +843,7 @@ TEST_CASE(ble_gatts_notify_test_bonded_i)
*/
ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
- NULL, NULL);
+ ble_gatts_notify_test_util_gap_event, NULL);
/* Ensure no indications sent. */
TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
@@ -598,11 +857,9 @@ TEST_CASE(ble_gatts_notify_test_bonded_i)
TEST_ASSERT(flags == 0);
/* Simulate a successful encryption procedure (bonding restoration). */
- ble_gatts_restore_bonding(conn_handle);
-
- /* Verify first indication sent properly. */
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_restore_bonding(conn_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 1,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0);
/* Verify the second indication doesn't get sent until the first is
* confirmed.
@@ -611,15 +868,22 @@ TEST_CASE(ble_gatts_notify_test_bonded_i)
TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
/* Receive the confirmation for the first indication. */
- ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1);
/* Verify indication sent properly. */
ble_hs_test_util_tx_all();
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_2_val,
- ble_gatts_notify_test_chr_2_len);
+ ble_gatts_notify_test_misc_verify_tx_i(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1,
+ ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
/* Receive the confirmation for the second indication. */
- ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_2_def_handle + 1);
/* Verify no pending GATT jobs. */
TEST_ASSERT(!ble_gattc_any_jobs());
@@ -654,8 +918,11 @@ TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)
/* Verify indication sent properly. */
ble_hs_test_util_tx_all();
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_misc_verify_tx_i(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
/* Verify 'updated' state is still persisted. */
key_cccd.peer_addr_type = BLE_STORE_ADDR_TYPE_NONE;
@@ -667,24 +934,25 @@ TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)
TEST_ASSERT(value_cccd.value_changed);
/* Disconnect. */
- ble_hs_test_util_conn_disconnect(conn_handle);
+ ble_gatts_notify_test_disconnect(conn_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 1, 0, 0);
/* Ensure CCCD still persisted. */
TEST_ASSERT(ble_hs_test_util_store_num_cccds == 1);
/* Reconnect. */
ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
- NULL, NULL);
+ ble_gatts_notify_test_util_gap_event, NULL);
/* Simulate a successful encryption procedure (bonding restoration). */
- ble_gatts_restore_bonding(conn_handle);
-
- /* Verify indication sent properly. */
- ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_1_val,
- ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_restore_bonding(conn_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 1,
+ 0, 0);
/* Receive the confirmation for the indication. */
- ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1);
/* Verify no pending GATT jobs. */
TEST_ASSERT(!ble_gattc_any_jobs());
@@ -706,8 +974,81 @@ TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)
TEST_ASSERT(!value_cccd.value_changed);
}
+TEST_CASE(ble_gatts_notify_test_disallowed)
+{
+ uint16_t chr1_val_handle;
+ uint16_t chr2_val_handle;
+ uint16_t chr3_val_handle;
+ int rc;
+
+ const struct ble_gatt_svc_def svcs[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid128 = BLE_UUID16(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid128 = BLE_UUID16(1),
+ .access_cb = ble_gatts_notify_test_misc_access,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
+ .val_handle = &chr1_val_handle,
+ }, {
+ .uuid128 = BLE_UUID16(2),
+ .access_cb = ble_gatts_notify_test_misc_access,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_INDICATE,
+ .val_handle = &chr2_val_handle,
+ }, {
+ .uuid128 = BLE_UUID16(3),
+ .access_cb = ble_gatts_notify_test_misc_access,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
+ BLE_GATT_CHR_F_INDICATE,
+ .val_handle = &chr3_val_handle,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } };
+
+ ble_hs_test_util_init();
+
+ rc = ble_gatts_register_svcs(svcs, NULL, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(chr1_val_handle != 0);
+ TEST_ASSERT_FATAL(chr2_val_handle != 0);
+ TEST_ASSERT_FATAL(chr3_val_handle != 0);
+
+ ble_gatts_start();
+
+ ble_hs_test_util_create_conn(2, ble_gatts_notify_test_peer_addr,
+ ble_gatts_notify_test_util_gap_event, NULL);
+
+ /* Attempt to enable notifications on chr1 should succeed. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr1_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
+
+ /* Attempt to enable indications on chr1 should fail. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr1_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 1);
+
+ /* Attempt to enable notifications on chr2 should fail. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr2_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 1);
+
+ /* Attempt to enable indications on chr2 should succeed. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr2_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 0);
+
+ /* Attempt to enable notifications on chr3 should succeed. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr3_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
+
+ /* Attempt to enable indications on chr3 should succeed. */
+ ble_gatts_notify_test_misc_try_enable_notify(
+ 2, chr3_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 0);
+}
+
TEST_SUITE(ble_gatts_notify_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatts_notify_test_n();
ble_gatts_notify_test_i();
@@ -716,6 +1057,8 @@ TEST_SUITE(ble_gatts_notify_suite)
ble_gatts_notify_test_bonded_i_no_ack();
+ ble_gatts_notify_test_disallowed();
+
/* XXX: Test corner cases:
* o Bonding after CCCD configuration.
* o Disconnect prior to rx of indicate ack.
diff --git a/net/nimble/host/src/test/ble_gatts_read_test.c b/net/nimble/host/src/test/ble_gatts_read_test.c
new file mode 100644
index 00000000..cef9f927
--- /dev/null
+++ b/net/nimble/host/src/test/ble_gatts_read_test.c
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "host/ble_uuid.h"
+#include "host/ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_GATTS_READ_TEST_CHR_1_UUID 0x1111
+#define BLE_GATTS_READ_TEST_CHR_2_UUID 0x2222
+
+static uint8_t ble_gatts_read_test_peer_addr[6] = {2,3,4,5,6,7};
+
+static int
+ble_gatts_read_test_util_access_1(uint16_t conn_handle,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg);
+
+static int
+ble_gatts_read_test_util_access_2(uint16_t conn_handle,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg);
+static void
+ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
+ void *arg);
+
+static const struct ble_gatt_svc_def ble_gatts_read_test_svcs[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid128 = BLE_UUID16(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid128 = BLE_UUID16(BLE_GATTS_READ_TEST_CHR_1_UUID),
+ .access_cb = ble_gatts_read_test_util_access_1,
+ .flags = BLE_GATT_CHR_F_READ
+ }, {
+ .uuid128 = BLE_UUID16(BLE_GATTS_READ_TEST_CHR_2_UUID),
+ .access_cb = ble_gatts_read_test_util_access_2,
+ .flags = BLE_GATT_CHR_F_READ
+ }, {
+ 0
+ } },
+}, {
+ 0
+} };
+
+
+static uint16_t ble_gatts_read_test_chr_1_def_handle;
+static uint16_t ble_gatts_read_test_chr_1_val_handle;
+static uint8_t ble_gatts_read_test_chr_1_val[1024];
+static int ble_gatts_read_test_chr_1_len;
+static uint16_t ble_gatts_read_test_chr_2_def_handle;
+static uint16_t ble_gatts_read_test_chr_2_val_handle;
+
+static void
+ble_gatts_read_test_misc_init(uint16_t *out_conn_handle)
+{
+ int rc;
+
+ ble_hs_test_util_init();
+
+ rc = ble_gatts_register_svcs(ble_gatts_read_test_svcs,
+ ble_gatts_read_test_misc_reg_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_def_handle != 0);
+ TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_val_handle ==
+ ble_gatts_read_test_chr_1_def_handle + 1);
+ TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_def_handle != 0);
+ TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_val_handle ==
+ ble_gatts_read_test_chr_2_def_handle + 1);
+
+ ble_gatts_start();
+
+ ble_hs_test_util_create_conn(2, ble_gatts_read_test_peer_addr, NULL, NULL);
+
+ if (out_conn_handle != NULL) {
+ *out_conn_handle = 2;
+ }
+}
+
+static void
+ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
+ void *arg)
+{
+ uint16_t uuid16;
+
+ if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) {
+ uuid16 = ble_uuid_128_to_16(ctxt->chr.chr_def->uuid128);
+ switch (uuid16) {
+ case BLE_GATTS_READ_TEST_CHR_1_UUID:
+ ble_gatts_read_test_chr_1_def_handle = ctxt->chr.def_handle;
+ ble_gatts_read_test_chr_1_val_handle = ctxt->chr.val_handle;
+ break;
+
+ case BLE_GATTS_READ_TEST_CHR_2_UUID:
+ ble_gatts_read_test_chr_2_def_handle = ctxt->chr.def_handle;
+ ble_gatts_read_test_chr_2_val_handle = ctxt->chr.val_handle;
+ break;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ break;
+ }
+ }
+}
+
+static int
+ble_gatts_read_test_util_access_1(uint16_t conn_handle,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg)
+{
+ int rc;
+
+ TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+ TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_1_val_handle);
+
+ TEST_ASSERT(ctxt->chr ==
+ &ble_gatts_read_test_svcs[0].characteristics[0]);
+
+ rc = os_mbuf_append(ctxt->om, ble_gatts_read_test_chr_1_val,
+ ble_gatts_read_test_chr_1_len);
+ TEST_ASSERT(rc == 0);
+
+ return 0;
+}
+
+static int
+ble_gatts_read_test_util_access_2(uint16_t conn_handle,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg)
+{
+ uint8_t *buf;
+
+ TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+ TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_2_def_handle + 1);
+
+ TEST_ASSERT(ctxt->chr ==
+ &ble_gatts_read_test_svcs[0].characteristics[1]);
+
+ buf = os_mbuf_extend(ctxt->om, 6);
+ TEST_ASSERT_FATAL(buf != NULL);
+
+ buf[0] = 0;
+ buf[1] = 10;
+ buf[2] = 20;
+ buf[3] = 30;
+ buf[4] = 40;
+ buf[5] = 50;
+
+ return 0;
+}
+
+static void
+ble_gatts_read_test_once(uint16_t conn_handle, uint16_t attr_id,
+ void *expected_value, uint16_t expected_len)
+{
+ struct ble_att_read_req read_req;
+ uint8_t buf[BLE_ATT_READ_REQ_SZ];
+ int rc;
+
+ read_req.barq_handle = attr_id;
+ ble_att_read_req_write(buf, sizeof buf, &read_req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_verify_tx_read_rsp(expected_value, expected_len);
+}
+
+TEST_CASE(ble_gatts_read_test_case_basic)
+{
+ uint16_t conn_handle;
+
+ ble_gatts_read_test_misc_init(&conn_handle);
+
+ /*** Application points attribute at static data. */
+ ble_gatts_read_test_chr_1_val[0] = 1;
+ ble_gatts_read_test_chr_1_val[1] = 2;
+ ble_gatts_read_test_chr_1_val[2] = 3;
+ ble_gatts_read_test_chr_1_len = 3;
+ ble_gatts_read_test_once(conn_handle,
+ ble_gatts_read_test_chr_1_val_handle,
+ ble_gatts_read_test_chr_1_val,
+ ble_gatts_read_test_chr_1_len);
+
+ /*** Application uses stack-provided buffer for dynamic attribute. */
+ ble_gatts_read_test_once(conn_handle,
+ ble_gatts_read_test_chr_2_def_handle + 1,
+ ((uint8_t[6]){0,10,20,30,40,50}), 6);
+
+}
+
+TEST_CASE(ble_gatts_read_test_case_long)
+{
+ struct ble_att_read_blob_req read_blob_req;
+ struct ble_att_read_req read_req;
+ uint8_t buf[max(BLE_ATT_READ_REQ_SZ, BLE_ATT_READ_BLOB_REQ_SZ)];
+ uint16_t conn_handle;
+ int rc;
+ int i;
+
+ ble_gatts_read_test_misc_init(&conn_handle);
+
+ /*** Prepare characteristic value. */
+ ble_gatts_read_test_chr_1_len = 40;
+ for (i = 0; i < ble_gatts_read_test_chr_1_len; i++) {
+ ble_gatts_read_test_chr_1_val[i] = i;
+ }
+
+ /* Receive first read request. */
+ read_req.barq_handle = ble_gatts_read_test_chr_1_val_handle;
+ ble_att_read_req_write(buf, sizeof buf, &read_req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_verify_tx_read_rsp(ble_gatts_read_test_chr_1_val, 22);
+
+ /* Receive follow-up read blob request. */
+ read_blob_req.babq_handle = ble_gatts_read_test_chr_1_val_handle;
+ read_blob_req.babq_offset = 22;
+ ble_att_read_blob_req_write(buf, sizeof buf, &read_blob_req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure response starts at appropriate offset (22). */
+ ble_hs_test_util_verify_tx_read_blob_rsp(
+ ble_gatts_read_test_chr_1_val + 22, 18);
+}
+
+TEST_SUITE(ble_gatts_read_test_suite)
+{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_gatts_read_test_case_basic();
+ ble_gatts_read_test_case_long();
+}
diff --git a/net/nimble/host/src/test/ble_gatts_reg_test.c b/net/nimble/host/src/test/ble_gatts_reg_test.c
index a198d997..ad5f18fa 100644
--- a/net/nimble/host/src/test/ble_gatts_reg_test.c
+++ b/net/nimble/host/src/test/ble_gatts_reg_test.c
@@ -30,6 +30,12 @@
struct ble_gatts_reg_test_entry {
uint8_t op;
uint8_t uuid128[16];
+ uint16_t handle;
+ uint16_t val_handle; /* If a characteristic. */
+
+ const struct ble_gatt_svc_def *svc;
+ const struct ble_gatt_chr_def *chr;
+ const struct ble_gatt_dsc_def *dsc;
};
static struct ble_gatts_reg_test_entry
@@ -45,8 +51,7 @@ ble_gatts_reg_test_init(void)
}
static void
-ble_gatts_reg_test_misc_reg_cb(uint8_t op, union ble_gatt_register_ctxt *ctxt,
- void *arg)
+ble_gatts_reg_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
struct ble_gatts_reg_test_entry *entry;
@@ -54,19 +59,65 @@ ble_gatts_reg_test_misc_reg_cb(uint8_t op, union ble_gatt_register_ctxt *ctxt,
BLE_GATTS_REG_TEST_MAX_ENTRIES);
entry = ble_gatts_reg_test_entries + ble_gatts_reg_test_num_entries++;
+ memset(entry, 0, sizeof *entry);
+
+ entry->op = ctxt->op;
+ switch (ctxt->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ memcpy(entry->uuid128, ctxt->svc.svc_def->uuid128, 16);
+ entry->handle = ctxt->svc.handle;
+ entry->svc = ctxt->svc.svc_def;
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ memcpy(entry->uuid128, ctxt->chr.chr_def->uuid128, 16);
+ entry->handle = ctxt->chr.def_handle;
+ entry->val_handle = ctxt->chr.val_handle;
+ entry->svc = ctxt->chr.svc_def;
+ entry->chr = ctxt->chr.chr_def;
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ memcpy(entry->uuid128, ctxt->dsc.dsc_def->uuid128, 16);
+ entry->handle = ctxt->dsc.handle;
+ entry->svc = ctxt->dsc.svc_def;
+ entry->chr = ctxt->dsc.chr_def;
+ entry->dsc = ctxt->dsc.dsc_def;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+}
- entry->op = op;
- switch (op) {
+static void
+ble_gatts_reg_test_misc_lookup_good(struct ble_gatts_reg_test_entry *entry)
+{
+ uint16_t chr_def_handle;
+ uint16_t chr_val_handle;
+ uint16_t svc_handle;
+ uint16_t dsc_handle;
+ int rc;
+
+ switch (entry->op) {
case BLE_GATT_REGISTER_OP_SVC:
- memcpy(entry->uuid128, ctxt->svc_reg.svc->uuid128, 16);
+ rc = ble_gatts_find_svc(entry->uuid128, &svc_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(svc_handle == entry->handle);
break;
case BLE_GATT_REGISTER_OP_CHR:
- memcpy(entry->uuid128, ctxt->chr_reg.chr->uuid128, 16);
+ rc = ble_gatts_find_chr(entry->svc->uuid128, entry->chr->uuid128,
+ &chr_def_handle, &chr_val_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(chr_def_handle == entry->handle);
+ TEST_ASSERT(chr_val_handle == entry->val_handle);
break;
case BLE_GATT_REGISTER_OP_DSC:
- memcpy(entry->uuid128, ctxt->dsc_reg.dsc->uuid128, 16);
+ rc = ble_gatts_find_dsc(entry->svc->uuid128, entry->chr->uuid128,
+ entry->dsc->uuid128, &dsc_handle);
break;
default:
@@ -76,7 +127,139 @@ ble_gatts_reg_test_misc_reg_cb(uint8_t op, union ble_gatt_register_ctxt *ctxt,
}
static void
-ble_gatts_reg_test_misc_verify_entry(uint8_t op, uint8_t *uuid128)
+ble_gatts_reg_test_misc_lookup_bad(struct ble_gatts_reg_test_entry *entry)
+{
+ struct ble_gatts_reg_test_entry *cur;
+ uint8_t wrong_uuid[16];
+ int rc;
+ int i;
+
+ switch (entry->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ /* Wrong service UUID. */
+ memcpy(wrong_uuid, entry->svc->uuid128, 16);
+ wrong_uuid[15]++;
+ rc = ble_gatts_find_svc(wrong_uuid, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ /* Correct service UUID, wrong characteristic UUID. */
+ memcpy(wrong_uuid, entry->chr->uuid128, 16);
+ wrong_uuid[15]++;
+ rc = ble_gatts_find_chr(entry->svc->uuid128, wrong_uuid, NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Incorrect service UUID, correct characteristic UUID. */
+ memcpy(wrong_uuid, entry->svc->uuid128, 16);
+ wrong_uuid[15]++;
+ rc = ble_gatts_find_chr(wrong_uuid, entry->chr->uuid128, NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Existing (but wrong) service, correct characteristic UUID. */
+ for (i = 0; i < ble_gatts_reg_test_num_entries; i++) {
+ cur = ble_gatts_reg_test_entries + i;
+ switch (cur->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ if (cur->svc != entry->svc) {
+ rc = ble_gatts_find_chr(cur->svc->uuid128,
+ entry->chr->uuid128,
+ NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ }
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ /* Characteristic that isn't in this service. */
+ if (cur->svc != entry->svc) {
+ rc = ble_gatts_find_chr(entry->svc->uuid128,
+ cur->chr->uuid128,
+ NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ }
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ /* Use descriptor UUID instead of characteristic UUID. */
+ rc = ble_gatts_find_chr(entry->svc->uuid128,
+ cur->dsc->uuid128,
+ NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+ }
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ /* Correct svc/chr UUID, wrong dsc UUID. */
+ memcpy(wrong_uuid, entry->dsc->uuid128, 16);
+ wrong_uuid[15]++;
+ rc = ble_gatts_find_dsc(entry->svc->uuid128, entry->chr->uuid128,
+ wrong_uuid, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Incorrect svc UUID, correct chr/dsc UUID. */
+ memcpy(wrong_uuid, entry->svc->uuid128, 16);
+ wrong_uuid[15]++;
+ rc = ble_gatts_find_dsc(wrong_uuid, entry->chr->uuid128,
+ entry->dsc->uuid128, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ for (i = 0; i < ble_gatts_reg_test_num_entries; i++) {
+ cur = ble_gatts_reg_test_entries + i;
+ switch (cur->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ /* Existing (but wrong) svc, correct chr/dsc UUID. */
+ if (cur->svc != entry->svc) {
+ rc = ble_gatts_find_dsc(cur->svc->uuid128,
+ entry->chr->uuid128,
+ entry->dsc->uuid128,
+ NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ }
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ /* Existing (but wrong) svc/chr, correct dsc UUID. */
+ if (cur->chr != entry->chr) {
+ rc = ble_gatts_find_dsc(cur->svc->uuid128,
+ cur->chr->uuid128,
+ entry->dsc->uuid128,
+ NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ }
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ /* Descriptor that isn't in this characteristic. */
+ if (cur->chr != entry->chr) {
+ rc = ble_gatts_find_dsc(cur->svc->uuid128,
+ cur->chr->uuid128,
+ entry->dsc->uuid128,
+ NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ }
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+ }
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+}
+
+static void
+ble_gatts_reg_test_misc_verify_entry(uint8_t op, const uint8_t *uuid128)
{
struct ble_gatts_reg_test_entry *entry;
int i;
@@ -84,17 +267,31 @@ ble_gatts_reg_test_misc_verify_entry(uint8_t op, uint8_t *uuid128)
for (i = 0; i < ble_gatts_reg_test_num_entries; i++) {
entry = ble_gatts_reg_test_entries + i;
if (entry->op == op && memcmp(entry->uuid128, uuid128, 16) == 0) {
- return;
+ break;
}
}
+ TEST_ASSERT_FATAL(entry != NULL);
- TEST_ASSERT(0);
+ /* Verify that characteristic value handle was properly assigned at
+ * registration.
+ */
+ if (op == BLE_GATT_REGISTER_OP_CHR) {
+ TEST_ASSERT(*entry->chr->val_handle == entry->val_handle);
+ }
+
+ /* Verify that the entry can be looked up. */
+ ble_gatts_reg_test_misc_lookup_good(entry);
+
+ /* Verify that "barely incorrect" UUID information doesn't retrieve any
+ * handles.
+ */
+ ble_gatts_reg_test_misc_lookup_bad(entry);
}
static int
ble_gatts_reg_test_misc_dummy_access(uint16_t conn_handle,
- uint16_t attr_handle, uint8_t op,
- union ble_gatt_access_ctxt *ctxt,
+ uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
void *arg)
{
return 0;
@@ -104,9 +301,8 @@ TEST_CASE(ble_gatts_reg_test_svc_return)
{
int rc;
- ble_gatts_reg_test_init();
-
/*** Missing UUID. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_no_uuid[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
}, {
@@ -117,6 +313,7 @@ TEST_CASE(ble_gatts_reg_test_svc_return)
TEST_ASSERT(rc == BLE_HS_EINVAL);
/*** Circular dependency. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_circ[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -133,6 +330,7 @@ TEST_CASE(ble_gatts_reg_test_svc_return)
TEST_ASSERT(rc == BLE_HS_EINVAL);
/*** Success. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_good[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -152,9 +350,8 @@ TEST_CASE(ble_gatts_reg_test_chr_return)
{
int rc;
- ble_gatts_reg_test_init();
-
/*** Missing callback. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_no_chr_cb[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -172,6 +369,7 @@ TEST_CASE(ble_gatts_reg_test_chr_return)
TEST_ASSERT(rc == BLE_HS_EINVAL);
/*** Success. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_good[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -194,9 +392,8 @@ TEST_CASE(ble_gatts_reg_test_dsc_return)
{
int rc;
- ble_gatts_reg_test_init();
-
/*** Missing callback. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_no_dsc_cb[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -221,6 +418,7 @@ TEST_CASE(ble_gatts_reg_test_dsc_return)
TEST_ASSERT(rc == BLE_HS_EINVAL);
/*** Success. */
+ ble_gatts_reg_test_init();
struct ble_gatt_svc_def svcs_good[] = { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -249,9 +447,9 @@ TEST_CASE(ble_gatts_reg_test_dsc_return)
static void
ble_gatts_reg_test_misc_svcs(struct ble_gatt_svc_def *svcs)
{
- struct ble_gatt_svc_def *svc;
- struct ble_gatt_chr_def *chr;
- struct ble_gatt_dsc_def *dsc;
+ const struct ble_gatt_svc_def *svc;
+ const struct ble_gatt_chr_def *chr;
+ const struct ble_gatt_dsc_def *dsc;
int rc;
ble_gatts_reg_test_init();
@@ -337,6 +535,8 @@ TEST_CASE(ble_gatts_reg_test_svc_cb)
TEST_CASE(ble_gatts_reg_test_chr_cb)
{
+ uint16_t val_handles[16];
+
/*** 1 characteristic. */
ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
@@ -345,6 +545,7 @@ TEST_CASE(ble_gatts_reg_test_chr_cb)
.uuid128 = BLE_UUID16(0x1111),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
}, {
0
} },
@@ -360,10 +561,12 @@ TEST_CASE(ble_gatts_reg_test_chr_cb)
.uuid128 = BLE_UUID16(0x1111),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
}, {
.uuid128 = BLE_UUID16(0x2222),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_WRITE,
+ .val_handle = val_handles + 1,
}, {
0
} },
@@ -374,6 +577,7 @@ TEST_CASE(ble_gatts_reg_test_chr_cb)
.uuid128 = BLE_UUID16(0x3333),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 2,
}, {
0
} },
@@ -384,6 +588,8 @@ TEST_CASE(ble_gatts_reg_test_chr_cb)
TEST_CASE(ble_gatts_reg_test_dsc_cb)
{
+ uint16_t val_handles[16];
+
/*** 1 descriptor. */
ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
@@ -392,8 +598,9 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
.uuid128 = BLE_UUID16(0x1111),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
.descriptors = (struct ble_gatt_dsc_def[]) { {
- .uuid128 = BLE_UUID16(0xaaaa),
+ .uuid128 = BLE_UUID16(0x111a),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
@@ -406,7 +613,7 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
0
} });
- /*** 5 descriptors. */
+ /*** 5+ descriptors. */
ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid128 = BLE_UUID16(0x1234),
@@ -414,8 +621,9 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
.uuid128 = BLE_UUID16(0x1111),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
.descriptors = (struct ble_gatt_dsc_def[]) { {
- .uuid128 = BLE_UUID16(0xaaaa),
+ .uuid128 = BLE_UUID16(0x111a),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
@@ -425,6 +633,7 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
.uuid128 = BLE_UUID16(0x2222),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_WRITE,
+ .val_handle = val_handles + 1,
}, {
0
} },
@@ -435,20 +644,45 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
.uuid128 = BLE_UUID16(0x3333),
.access_cb = ble_gatts_reg_test_misc_dummy_access,
.flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 2,
.descriptors = (struct ble_gatt_dsc_def[]) { {
- .uuid128 = BLE_UUID16(0xaaab),
+ .uuid128 = BLE_UUID16(0x333a),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
- .uuid128 = BLE_UUID16(0xaaac),
+ .uuid128 = BLE_UUID16(0x333b),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
- .uuid128 = BLE_UUID16(0xaaad),
+ .uuid128 = BLE_UUID16(0x333c),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
- .uuid128 = BLE_UUID16(0xaaae),
+ .uuid128 = BLE_UUID16(0x333e),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ 0
+ } },
+ }, {
+ .uuid128 = BLE_UUID16(0x4444),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 3,
+ .descriptors = (struct ble_gatt_dsc_def[]) { {
+ .uuid128 = BLE_UUID16(0x444a),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid128 = BLE_UUID16(0x444b),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid128 = BLE_UUID16(0x444c),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid128 = BLE_UUID16(0x444e),
.att_flags = 5,
.access_cb = ble_gatts_reg_test_misc_dummy_access,
}, {
@@ -464,6 +698,8 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
TEST_SUITE(ble_gatts_reg_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_gatts_reg_test_svc_return();
ble_gatts_reg_test_chr_return();
ble_gatts_reg_test_dsc_return();
diff --git a/net/nimble/host/src/test/ble_hs_adv_test.c b/net/nimble/host/src/test/ble_hs_adv_test.c
index 9673cc10..e99fd5b4 100644
--- a/net/nimble/host/src/test/ble_hs_adv_test.c
+++ b/net/nimble/host/src/test/ble_hs_adv_test.c
@@ -22,8 +22,8 @@
#include <string.h>
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
#include "host/ble_hs_test.h"
-#include "host/host_hci.h"
#include "ble_hs_test_util.h"
#define BLE_ADV_TEST_DATA_OFF 4
@@ -140,18 +140,36 @@ ble_hs_adv_test_misc_tx_and_verify_data(
struct ble_hs_adv_fields *rsp_fields,
struct ble_hs_adv_test_field *test_rsp_fields)
{
+ struct ble_gap_adv_params adv_params;
int rc;
ble_hs_test_util_init();
- rc = ble_gap_adv_set_fields(adv_fields);
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.disc_mode = disc_mode;
+
+ rc = ble_hs_test_util_adv_set_fields(adv_fields, 0);
TEST_ASSERT_FATAL(rc == 0);
rc = ble_gap_adv_rsp_set_fields(rsp_fields);
TEST_ASSERT_FATAL(rc == 0);
- rc = ble_hs_test_util_adv_start(disc_mode, BLE_GAP_CONN_MODE_UND, NULL, 0,
- NULL, NULL, NULL, 0, 0);
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, 0, NULL, &adv_params,
+ NULL, NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Discard the adv-enable command. */
+ ble_hs_test_util_get_last_hci_tx();
+
+ ble_hs_adv_test_misc_verify_tx_rsp_data(test_rsp_fields);
+ ble_hs_adv_test_misc_verify_tx_adv_data(test_adv_fields);
+
+ /* Ensure the same data gets sent on repeated advertise procedures. */
+ rc = ble_hs_test_util_adv_stop(0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, 0, NULL, &adv_params,
+ NULL, NULL, 0, 0);
TEST_ASSERT_FATAL(rc == 0);
/* Discard the adv-enable command. */
@@ -170,18 +188,20 @@ TEST_CASE(ble_hs_adv_test_case_flags)
memset(&rsp_fields, 0, sizeof rsp_fields);
/* Default flags. */
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON,
&adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -191,15 +211,16 @@ TEST_CASE(ble_hs_adv_test_case_flags)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_LTD, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_FLAGS,
.val = (uint8_t[]) {
BLE_HS_ADV_F_DISC_LTD | BLE_HS_ADV_F_BREDR_UNSUP
},
.val_len = 1,
- }, {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
},
{ 0 },
}, &rsp_fields, NULL);
@@ -208,15 +229,16 @@ TEST_CASE(ble_hs_adv_test_case_flags)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_GEN, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_FLAGS,
.val = (uint8_t[]) {
BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP
},
.val_len = 1,
- }, {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
},
{ 0 },
}, &rsp_fields, NULL);
@@ -231,7 +253,9 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Complete 16-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
adv_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab };
adv_fields.num_uuids16 = 3;
adv_fields.uuids16_is_complete = 1;
@@ -244,13 +268,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 6,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -258,6 +282,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Incomplete 16-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab };
adv_fields.num_uuids16 = 3;
@@ -271,13 +296,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 6,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -285,6 +310,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Complete 32-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae };
adv_fields.num_uuids32 = 2;
@@ -298,13 +324,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 8,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -312,6 +338,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Incomplete 32-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae };
adv_fields.num_uuids32 = 2;
@@ -325,13 +352,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 8,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -339,6 +366,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Complete 128-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uuids128 = (uint8_t[]) {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -358,13 +386,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 16,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -372,6 +400,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Incomplete 128-bit service class UUIDs. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uuids128 = (uint8_t[]) {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -391,13 +420,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 16,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -405,6 +434,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Complete name. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.name = (uint8_t *)"myname";
adv_fields.name_len = 6;
@@ -418,13 +448,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 6,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -432,6 +462,7 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Incomplete name. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.name = (uint8_t *)"myname";
adv_fields.name_len = 6;
@@ -445,13 +476,13 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val_len = 6,
},
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -459,12 +490,18 @@ TEST_CASE(ble_hs_adv_test_case_user)
/*** Class of device. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.device_class = (uint8_t[]){ 1,2,3 };
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_DEVICE_CLASS,
.val = (uint8_t[]) { 1,2,3 },
.val_len = BLE_HS_ADV_DEVICE_CLASS_LEN,
@@ -474,22 +511,23 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** Slave interval range. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.slave_itvl_range = (uint8_t[]){ 1,2,3,4 };
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE,
.val = (uint8_t[]) { 1,2,3,4 },
.val_len = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN,
@@ -499,16 +537,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x16 - Service data - 16-bit UUID. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.svc_data_uuid16 = (uint8_t[]){ 1,2,3,4 };
adv_fields.svc_data_uuid16_len = 4;
@@ -516,6 +550,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16,
.val = (uint8_t[]) { 1,2,3,4 },
.val_len = 4,
@@ -525,16 +564,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x17 - Public target address. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.public_tgt_addr = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 };
adv_fields.num_public_tgt_addrs = 2;
@@ -542,6 +577,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR,
.val = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 },
.val_len = 2 * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN,
@@ -551,16 +591,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x19 - Appearance. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.appearance = 0x1234;
adv_fields.appearance_is_present = 1;
@@ -568,6 +604,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_APPEARANCE,
.val = (uint8_t[]){ 0x34, 0x12 },
.val_len = BLE_HS_ADV_APPEARANCE_LEN,
@@ -577,16 +618,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x1a - Advertising interval. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.adv_itvl = 0x1234;
adv_fields.adv_itvl_is_present = 1;
@@ -594,6 +631,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_ADV_ITVL,
.val = (uint8_t[]){ 0x34, 0x12 },
.val_len = BLE_HS_ADV_ADV_ITVL_LEN,
@@ -603,22 +645,23 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x1b - LE bluetooth device address. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.le_addr = (uint8_t[]){ 1,2,3,4,5,6,7 };
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_LE_ADDR,
.val = (uint8_t[]) { 1,2,3,4,5,6,7 },
.val_len = BLE_HS_ADV_LE_ADDR_LEN,
@@ -628,16 +671,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x1c - LE role. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.le_role = BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF;
adv_fields.le_role_is_present = 1;
@@ -645,6 +684,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_LE_ROLE,
.val = (uint8_t[]) { BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF },
.val_len = 1,
@@ -654,16 +698,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x20 - Service data - 32-bit UUID. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.svc_data_uuid32 = (uint8_t[]){ 1,2,3,4,5 };
adv_fields.svc_data_uuid32_len = 5;
@@ -671,6 +711,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32,
.val = (uint8_t[]) { 1,2,3,4,5 },
.val_len = 5,
@@ -680,16 +725,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x21 - Service data - 128-bit UUID. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.svc_data_uuid128 =
(uint8_t[]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };
@@ -698,6 +739,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128,
.val = (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18 },
@@ -708,16 +754,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0x24 - URI. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.uri = (uint8_t[]){ 1,2,3,4 };
adv_fields.uri_len = 4;
@@ -725,6 +767,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_URI,
.val = (uint8_t[]) { 1,2,3,4 },
.val_len = 4,
@@ -734,16 +781,12 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
/*** 0xff - Manufacturer specific data. */
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
adv_fields.mfg_data = (uint8_t[]){ 1,2,3,4 };
adv_fields.mfg_data_len = 4;
@@ -751,6 +794,11 @@ TEST_CASE(ble_hs_adv_test_case_user)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ {
.type = BLE_HS_ADV_TYPE_MFG_DATA,
.val = (uint8_t[]) { 1,2,3,4 },
.val_len = 4,
@@ -760,11 +808,6 @@ TEST_CASE(ble_hs_adv_test_case_user)
.val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
- {
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
- .val_len = 1,
- },
{ 0 },
}, &rsp_fields, NULL);
}
@@ -775,6 +818,7 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
struct ble_hs_adv_fields adv_fields;
memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags_is_present = 1;
adv_fields.tx_pwr_lvl_is_present = 1;
/*** Complete 16-bit service class UUIDs. */
@@ -786,13 +830,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -816,13 +860,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -846,13 +890,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -876,13 +920,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -909,13 +953,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -945,13 +989,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -978,13 +1022,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1008,13 +1052,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1036,13 +1080,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1064,13 +1108,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1093,13 +1137,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1122,13 +1166,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1151,13 +1195,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1180,13 +1224,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1208,13 +1252,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1237,13 +1281,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1266,13 +1310,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1296,13 +1340,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1326,13 +1370,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1355,13 +1399,13 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
(struct ble_hs_adv_test_field[]) {
{
- .type = BLE_HS_ADV_TYPE_FLAGS,
- .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
.val_len = 1,
},
{
- .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
- .val = (uint8_t[]){ 0x00 },
+ .type = BLE_HS_ADV_TYPE_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
.val_len = 1,
},
{ 0 },
@@ -1377,11 +1421,59 @@ TEST_CASE(ble_hs_adv_test_case_user_rsp)
});
}
+TEST_CASE(ble_hs_adv_test_case_user_full_payload)
+{
+ /* Intentionally allocate an extra byte. */
+ static const uint8_t mfg_data[30] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+ };
+
+ struct ble_hs_adv_fields adv_fields;
+ struct ble_hs_adv_fields rsp_fields;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+
+ /***
+ * An advertisement should allow 31 bytes of user data. Each field has a
+ * two-byte header, leaving 29 bytes of payload.
+ */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.mfg_data = (void *)mfg_data;
+ adv_fields.mfg_data_len = 29;
+
+ ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_MFG_DATA,
+ .val = (void *)mfg_data,
+ .val_len = 29,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Fail with 30 bytes. */
+ rc = ble_hs_test_util_adv_stop(0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ adv_fields.mfg_data_len = 30;
+ rc = ble_gap_adv_set_fields(&adv_fields);
+ TEST_ASSERT(rc == BLE_HS_EMSGSIZE);
+}
+
TEST_SUITE(ble_hs_adv_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_hs_adv_test_case_flags();
ble_hs_adv_test_case_user();
ble_hs_adv_test_case_user_rsp();
+ ble_hs_adv_test_case_user_full_payload();
}
int
diff --git a/net/nimble/host/src/test/ble_hs_conn_test.c b/net/nimble/host/src/test/ble_hs_conn_test.c
index 5f86ad1b..c9574460 100644
--- a/net/nimble/host/src/test/ble_hs_conn_test.c
+++ b/net/nimble/host/src/test/ble_hs_conn_test.c
@@ -22,8 +22,8 @@
#include <string.h>
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
#include "host/ble_hs_test.h"
-#include "host/host_hci.h"
#include "ble_hs_test_util.h"
static int
@@ -53,7 +53,9 @@ TEST_CASE(ble_hs_conn_test_direct_connect_success)
TEST_ASSERT(!ble_hs_conn_test_util_any());
/* Initiate connection. */
- rc = ble_hs_test_util_conn_initiate(0, addr, NULL, NULL, NULL, 0);
+ rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
+ BLE_ADDR_TYPE_PUBLIC,
+ addr, 0, NULL, NULL, NULL, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(ble_gap_master_in_progress());
@@ -74,7 +76,7 @@ TEST_CASE(ble_hs_conn_test_direct_connect_success)
conn = ble_hs_conn_first();
TEST_ASSERT_FATAL(conn != NULL);
TEST_ASSERT(conn->bhc_handle == 2);
- TEST_ASSERT(memcmp(conn->bhc_addr, addr, 6) == 0);
+ TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0);
chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
TEST_ASSERT_FATAL(chan != NULL);
@@ -85,28 +87,10 @@ TEST_CASE(ble_hs_conn_test_direct_connect_success)
ble_hs_unlock();
}
-TEST_CASE(ble_hs_conn_test_direct_connect_hci_errors)
-{
- uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
- int rc;
-
- ble_hs_test_util_init();
-
- /* Ensure no current or pending connections. */
- TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_hs_conn_test_util_any());
-
- /* Initiate connection; receive no HCI ack. */
- rc = ble_gap_conn_initiate(0, addr, NULL, NULL, NULL);
- TEST_ASSERT(rc == BLE_HS_ETIMEOUT_HCI);
-
- TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_hs_conn_test_util_any());
-}
-
TEST_CASE(ble_hs_conn_test_direct_connectable_success)
{
struct hci_le_conn_complete evt;
+ struct ble_gap_adv_params adv_params;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -116,18 +100,18 @@ TEST_CASE(ble_hs_conn_test_direct_connectable_success)
/* Ensure no current or pending connections. */
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
TEST_ASSERT(!ble_hs_conn_test_util_any());
/* Initiate advertising. */
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_NON,
- BLE_GAP_CONN_MODE_DIR, addr,
- BLE_HCI_ADV_PEER_ADDR_PUBLIC, NULL, NULL,
- NULL, 0, 0);
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = BLE_GAP_CONN_MODE_DIR;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ addr, &adv_params, NULL, NULL, 0, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_slave_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
/* Receive successful connection complete event. */
memset(&evt, 0, sizeof evt);
@@ -139,14 +123,14 @@ TEST_CASE(ble_hs_conn_test_direct_connectable_success)
rc = ble_gap_rx_conn_complete(&evt);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
ble_hs_lock();
conn = ble_hs_conn_first();
TEST_ASSERT_FATAL(conn != NULL);
TEST_ASSERT(conn->bhc_handle == 2);
- TEST_ASSERT(memcmp(conn->bhc_addr, addr, 6) == 0);
+ TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0);
chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
TEST_ASSERT_FATAL(chan != NULL);
@@ -157,38 +141,11 @@ TEST_CASE(ble_hs_conn_test_direct_connectable_success)
ble_hs_unlock();
}
-TEST_CASE(ble_hs_conn_test_direct_connectable_hci_errors)
-{
- struct hci_le_conn_complete evt;
- uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
- int rc;
-
- ble_hs_test_util_init();
-
- /* Ensure no current or pending connections. */
- TEST_ASSERT(!ble_gap_slave_in_progress());
- TEST_ASSERT(!ble_hs_conn_test_util_any());
-
- /* Initiate connection. */
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_NON,
- BLE_GAP_CONN_MODE_DIR, addr,
- BLE_HCI_ADV_PEER_ADDR_PUBLIC, NULL, NULL,
- NULL, 0, 0);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(ble_gap_slave_in_progress());
-
- /* Receive failure connection complete event. */
- evt.status = BLE_ERR_UNSPECIFIED;
- rc = ble_gap_rx_conn_complete(&evt);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(ble_gap_slave_in_progress());
- TEST_ASSERT(!ble_hs_conn_test_util_any());
-}
-
TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
{
struct ble_hs_adv_fields adv_fields;
struct hci_le_conn_complete evt;
+ struct ble_gap_adv_params adv_params;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -198,7 +155,7 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
/* Ensure no current or pending connections. */
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
TEST_ASSERT(!ble_hs_conn_test_util_any());
/* Initiate advertising. */
@@ -207,13 +164,14 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
rc = ble_gap_adv_set_fields(&adv_fields);
TEST_ASSERT_FATAL(rc == 0);
- rc = ble_hs_test_util_adv_start(BLE_GAP_DISC_MODE_NON,
- BLE_GAP_CONN_MODE_UND, NULL, 0, NULL,
- NULL, NULL, 0, 0);
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+ rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ addr, &adv_params, NULL, NULL, 0, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(ble_gap_slave_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
/* Receive successful connection complete event. */
memset(&evt, 0, sizeof evt);
@@ -225,14 +183,14 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
rc = ble_gap_rx_conn_complete(&evt);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_gap_master_in_progress());
- TEST_ASSERT(!ble_gap_slave_in_progress());
+ TEST_ASSERT(!ble_gap_adv_active());
ble_hs_lock();
conn = ble_hs_conn_first();
TEST_ASSERT_FATAL(conn != NULL);
TEST_ASSERT(conn->bhc_handle == 2);
- TEST_ASSERT(memcmp(conn->bhc_addr, addr, 6) == 0);
+ TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0);
chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
TEST_ASSERT_FATAL(chan != NULL);
@@ -245,10 +203,10 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
TEST_SUITE(conn_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_hs_conn_test_direct_connect_success();
- ble_hs_conn_test_direct_connect_hci_errors();
ble_hs_conn_test_direct_connectable_success();
- ble_hs_conn_test_direct_connectable_hci_errors();
ble_hs_conn_test_undirect_connectable_success();
}
diff --git a/net/nimble/host/src/test/ble_host_hci_test.c b/net/nimble/host/src/test/ble_hs_hci_test.c
index 52837bd3..21184b8a 100644
--- a/net/nimble/host/src/test/ble_host_hci_test.c
+++ b/net/nimble/host/src/test/ble_hs_hci_test.c
@@ -21,31 +21,34 @@
#include <errno.h>
#include <string.h>
#include "nimble/hci_common.h"
-#include "host/host_hci.h"
+#include "nimble/ble_hci_trans.h"
#include "host/ble_hs_test.h"
#include "testutil/testutil.h"
#include "ble_hs_test_util.h"
-TEST_CASE(ble_host_hci_test_event_bad)
+TEST_CASE(ble_hs_hci_test_event_bad)
{
- uint8_t buf[2];
+ uint8_t *buf;
int rc;
/*** Invalid event code. */
+ buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+ TEST_ASSERT_FATAL(buf != NULL);
+
buf[0] = 0xff;
buf[1] = 0;
- rc = host_hci_event_rx(buf);
+ rc = ble_hs_hci_evt_process(buf);
TEST_ASSERT(rc == BLE_HS_ENOTSUP);
}
-TEST_CASE(ble_host_hci_test_rssi)
+TEST_CASE(ble_hs_hci_test_rssi)
{
uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
uint16_t opcode;
int8_t rssi;
int rc;
- opcode = host_hci_opcode_join(BLE_HCI_OGF_STATUS_PARAMS,
+ opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_STATUS_PARAMS,
BLE_HCI_OCF_RD_RSSI);
/*** Success. */
@@ -57,7 +60,7 @@ TEST_CASE(ble_host_hci_test_rssi)
ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params);
- rc = ble_hci_util_read_rssi(1, &rssi);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(rssi == -8);
@@ -66,29 +69,31 @@ TEST_CASE(ble_host_hci_test_rssi)
ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params);
- rc = ble_hci_util_read_rssi(1, &rssi);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
/*** Failure: params too short. */
ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params - 1);
- rc = ble_hci_util_read_rssi(1, &rssi);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
/*** Failure: params too long. */
ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params + 1);
- rc = ble_hci_util_read_rssi(1, &rssi);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
}
-TEST_SUITE(ble_host_hci_suite)
+TEST_SUITE(ble_hs_hci_suite)
{
- ble_host_hci_test_event_bad();
- ble_host_hci_test_rssi();
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_hs_hci_test_event_bad();
+ ble_hs_hci_test_rssi();
}
int
-ble_host_hci_test_all(void)
+ble_hs_hci_test_all(void)
{
- ble_host_hci_suite();
+ ble_hs_hci_suite();
return tu_any_failed;
}
diff --git a/net/nimble/host/src/test/ble_hs_test.c b/net/nimble/host/src/test/ble_hs_test.c
index 88a2c0cd..3bc468ec 100644
--- a/net/nimble/host/src/test/ble_hs_test.c
+++ b/net/nimble/host/src/test/ble_hs_test.c
@@ -23,24 +23,6 @@
#include "testutil/testutil.h"
#include "ble_hs_test_util.h"
-/* Our global device address. */
-uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
-
-void
-ble_hs_test_pkt_txed(struct os_mbuf *om)
-{
- /* XXX: For now, just strip the HCI ACL data and L2CAP headers. */
- os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ + BLE_L2CAP_HDR_SZ);
- ble_hs_test_util_prev_tx_enqueue(om);
-}
-
-void
-ble_hs_test_hci_txed(uint8_t *cmdbuf)
-{
- ble_hs_test_util_enqueue_hci_tx(cmdbuf);
- os_memblock_put(&g_hci_cmd_pool, cmdbuf);
-}
-
#ifdef MYNEWT_SELFTEST
int
@@ -62,8 +44,9 @@ main(int argc, char **argv)
ble_gatt_read_test_all();
ble_gatt_write_test_all();
ble_gatts_notify_test_all();
+ ble_gatts_read_test_suite();
ble_gatts_reg_test_all();
- ble_host_hci_test_all();
+ ble_hs_hci_test_all();
ble_hs_adv_test_all();
ble_hs_conn_test_all();
ble_l2cap_test_all();
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index 90448da9..e1acb81c 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -23,10 +23,17 @@
#include "testutil/testutil.h"
#include "nimble/ble.h"
#include "nimble/hci_common.h"
-#include "nimble/hci_transport.h"
-#include "host/host_hci.h"
+#include "nimble/ble_hci_trans.h"
+#include "host/ble_hs_adv.h"
+#include "host/ble_hs_id.h"
+#include "transport/ram/ble_hci_ram.h"
#include "ble_hs_test_util.h"
+/* Our global device address. */
+uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
+
+#define BLE_HS_TEST_UTIL_PUB_ADDR_VAL { 0x0a, 0x54, 0xab, 0x49, 0x7f, 0x06 }
+
/** Use lots of small mbufs to ensure correct mbuf usage. */
#define BLE_HS_TEST_UTIL_NUM_MBUFS (100)
#define BLE_HS_TEST_UTIL_BUF_SIZE OS_ALIGN(100, 4)
@@ -36,7 +43,7 @@
OS_MEMPOOL_SIZE(BLE_HS_TEST_UTIL_NUM_MBUFS, BLE_HS_TEST_UTIL_MEMBLOCK_SIZE)
#define BLE_HS_TEST_UTIL_LE_OPCODE(ocf) \
- host_hci_opcode_join(BLE_HCI_OGF_LE, (ocf))
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE, (ocf))
struct os_eventq ble_hs_test_util_evq;
@@ -54,6 +61,17 @@ int ble_hs_test_util_num_prev_hci_txes;
uint8_t ble_hs_test_util_cur_hci_tx[260];
+const struct ble_gap_adv_params ble_hs_test_util_adv_params = {
+ .conn_mode = BLE_GAP_CONN_MODE_UND,
+ .disc_mode = BLE_GAP_DISC_MODE_GEN,
+
+ .itvl_min = 0,
+ .itvl_max = 0,
+ .channel_map = 0,
+ .filter_policy = 0,
+ .high_duty_cycle = 0,
+};
+
void
ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om)
{
@@ -69,20 +87,65 @@ ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om)
}
}
+static struct os_mbuf *
+ble_hs_test_util_prev_tx_dequeue_once(struct hci_data_hdr *out_hci_hdr)
+{
+ struct os_mbuf_pkthdr *omp;
+ struct os_mbuf *om;
+ int rc;
+
+ omp = STAILQ_FIRST(&ble_hs_test_util_prev_tx_queue);
+ if (omp == NULL) {
+ return NULL;
+ }
+ STAILQ_REMOVE_HEAD(&ble_hs_test_util_prev_tx_queue, omp_next);
+
+ om = OS_MBUF_PKTHDR_TO_MBUF(omp);
+
+ rc = ble_hs_hci_util_data_hdr_strip(om, out_hci_hdr);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(out_hci_hdr->hdh_len == OS_MBUF_PKTLEN(om));
+
+ return om;
+}
+
struct os_mbuf *
ble_hs_test_util_prev_tx_dequeue(void)
{
- struct os_mbuf_pkthdr *omp;
+ struct ble_l2cap_hdr l2cap_hdr;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ uint8_t pb;
+ int rc;
os_mbuf_free_chain(ble_hs_test_util_prev_tx_cur);
- omp = STAILQ_FIRST(&ble_hs_test_util_prev_tx_queue);
- if (omp != NULL) {
- STAILQ_REMOVE_HEAD(&ble_hs_test_util_prev_tx_queue, omp_next);
- ble_hs_test_util_prev_tx_cur = OS_MBUF_PKTHDR_TO_MBUF(omp);
+ om = ble_hs_test_util_prev_tx_dequeue_once(&hci_hdr);
+ if (om != NULL) {
+ pb = BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc);
+ TEST_ASSERT_FATAL(pb == BLE_HCI_PB_FIRST_NON_FLUSH);
+
+ rc = ble_l2cap_parse_hdr(om, 0, &l2cap_hdr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ os_mbuf_adj(om, BLE_L2CAP_HDR_SZ);
+
+ ble_hs_test_util_prev_tx_cur = om;
+ while (OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx_cur) <
+ l2cap_hdr.blh_len) {
+
+ om = ble_hs_test_util_prev_tx_dequeue_once(&hci_hdr);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ pb = BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc);
+ TEST_ASSERT_FATAL(pb == BLE_HCI_PB_MIDDLE);
+
+ os_mbuf_concat(ble_hs_test_util_prev_tx_cur, om);
+ }
} else {
ble_hs_test_util_prev_tx_cur = NULL;
}
+
return ble_hs_test_util_prev_tx_cur;
}
@@ -188,13 +251,14 @@ ble_hs_test_util_rx_hci_evt(uint8_t *evt)
TEST_ASSERT_FATAL(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
if (os_started()) {
- evbuf = os_memblock_get(&g_hci_cmd_pool);
+ evbuf = ble_hci_trans_buf_alloc(
+ BLE_HCI_TRANS_BUF_EVT_LO);
TEST_ASSERT_FATAL(evbuf != NULL);
memcpy(evbuf, evt, totlen);
- rc = ble_hci_transport_ctlr_event_send(evbuf);
+ rc = ble_hci_trans_ll_evt_tx(evbuf);
} else {
- rc = host_hci_event_rx(evt);
+ rc = ble_hs_hci_evt_process(evt);
}
TEST_ASSERT_FATAL(rc == 0);
@@ -284,7 +348,7 @@ ble_hs_test_util_set_ack_params(uint16_t opcode, uint8_t status, void *params,
}
ble_hs_test_util_num_phony_acks = 1;
- ble_hci_set_phony_ack_cb(ble_hs_test_util_phony_ack_cb);
+ ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_phony_ack_cb);
}
void
@@ -303,22 +367,22 @@ ble_hs_test_util_set_ack_seq(struct ble_hs_test_util_phony_ack *acks)
}
ble_hs_test_util_num_phony_acks = i;
- ble_hci_set_phony_ack_cb(ble_hs_test_util_phony_ack_cb);
+ ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_phony_ack_cb);
}
void
-ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t *our_rpa,
- uint8_t peer_addr_type, uint8_t *peer_id_addr,
- uint8_t *peer_rpa,
+ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
+ const uint8_t *our_rpa,
+ uint8_t peer_addr_type,
+ const uint8_t *peer_id_addr,
+ const uint8_t *peer_rpa,
ble_gap_event_fn *cb, void *cb_arg)
{
struct hci_le_conn_complete evt;
int rc;
- ble_hs_test_util_set_ack(
- BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CREATE_CONN), 0);
- rc = ble_gap_conn_initiate(peer_addr_type, peer_id_addr, NULL, cb, cb_arg);
- TEST_ASSERT(rc == 0);
+ ble_hs_test_util_connect(own_addr_type, peer_addr_type,
+ peer_id_addr, 0, NULL, cb, cb_arg, 0);
memset(&evt, 0, sizeof evt);
evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
@@ -340,28 +404,116 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t *our_rpa,
}
void
-ble_hs_test_util_create_conn(uint16_t handle, uint8_t *peer_id_addr,
+ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *peer_id_addr,
ble_gap_event_fn *cb, void *cb_arg)
{
static uint8_t null_addr[6];
- ble_hs_test_util_create_rpa_conn(handle, null_addr, BLE_ADDR_TYPE_PUBLIC,
- peer_id_addr, null_addr, cb, cb_arg);
+ ble_hs_test_util_create_rpa_conn(handle, BLE_ADDR_TYPE_PUBLIC, null_addr,
+ BLE_ADDR_TYPE_PUBLIC, peer_id_addr,
+ null_addr, cb, cb_arg);
+}
+
+static void
+ble_hs_test_util_conn_params_dflt(struct ble_gap_conn_params *conn_params)
+{
+ conn_params->scan_itvl = 0x0010;
+ conn_params->scan_window = 0x0010;
+ conn_params->itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN;
+ conn_params->itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX;
+ conn_params->latency = BLE_GAP_INITIAL_CONN_LATENCY;
+ conn_params->supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT;
+ conn_params->min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
+ conn_params->max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
+}
+
+static void
+ble_hs_test_util_hcc_from_conn_params(
+ struct hci_create_conn *hcc, uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr, const struct ble_gap_conn_params *conn_params)
+{
+ hcc->scan_itvl = conn_params->scan_itvl;
+ hcc->scan_window = conn_params->scan_window;
+
+ if (peer_addr_type == BLE_GAP_ADDR_TYPE_WL) {
+ hcc->filter_policy = BLE_HCI_CONN_FILT_USE_WL;
+ hcc->peer_addr_type = 0;
+ memset(hcc->peer_addr, 0, 6);
+ } else {
+ hcc->filter_policy = BLE_HCI_CONN_FILT_NO_WL;
+ hcc->peer_addr_type = peer_addr_type;
+ memcpy(hcc->peer_addr, peer_addr, 6);
+ }
+ hcc->own_addr_type = own_addr_type;
+ hcc->conn_itvl_min = conn_params->itvl_min;
+ hcc->conn_itvl_max = conn_params->itvl_max;
+ hcc->conn_latency = conn_params->latency;
+ hcc->supervision_timeout = conn_params->supervision_timeout;
+ hcc->min_ce_len = conn_params->min_ce_len;
+ hcc->max_ce_len = conn_params->max_ce_len;
+}
+
+void
+ble_hs_test_util_verify_tx_create_conn(const struct hci_create_conn *exp)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CREATE_CONN_LEN);
+
+ TEST_ASSERT(le16toh(param + 0) == exp->scan_itvl);
+ TEST_ASSERT(le16toh(param + 2) == exp->scan_window);
+ TEST_ASSERT(param[4] == exp->filter_policy);
+ TEST_ASSERT(param[5] == exp->peer_addr_type);
+ TEST_ASSERT(memcmp(param + 6, exp->peer_addr, 6) == 0);
+ TEST_ASSERT(param[12] == exp->own_addr_type);
+ TEST_ASSERT(le16toh(param + 13) == exp->conn_itvl_min);
+ TEST_ASSERT(le16toh(param + 15) == exp->conn_itvl_max);
+ TEST_ASSERT(le16toh(param + 17) == exp->conn_latency);
+ TEST_ASSERT(le16toh(param + 19) == exp->supervision_timeout);
+ TEST_ASSERT(le16toh(param + 21) == exp->min_ce_len);
+ TEST_ASSERT(le16toh(param + 23) == exp->max_ce_len);
}
int
-ble_hs_test_util_conn_initiate(int addr_type, uint8_t *addr,
- struct ble_gap_crt_params *params,
- ble_gap_event_fn *cb, void *cb_arg,
- uint8_t ack_status)
+ble_hs_test_util_connect(uint8_t own_addr_type, uint8_t peer_addr_type,
+ const uint8_t *peer_addr, int32_t duration_ms,
+ const struct ble_gap_conn_params *params,
+ ble_gap_event_fn *cb, void *cb_arg,
+ uint8_t ack_status)
{
+ struct ble_gap_conn_params dflt_params;
+ struct hci_create_conn hcc;
int rc;
+ /* This function ensures the most recently sent HCI command is the expected
+ * create connection command. If the current test case has unverified HCI
+ * commands, assume we are not interested in them and clear the queue.
+ */
+ ble_hs_test_util_prev_hci_tx_clear();
+
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN),
ack_status);
- rc = ble_gap_conn_initiate(addr_type, addr, params, cb, cb_arg);
+ rc = ble_gap_connect(own_addr_type, peer_addr_type, peer_addr, duration_ms,
+ params, cb, cb_arg);
+
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(ack_status));
+
+ if (params == NULL) {
+ ble_hs_test_util_conn_params_dflt(&dflt_params);
+ params = &dflt_params;
+ }
+
+ ble_hs_test_util_hcc_from_conn_params(&hcc, own_addr_type,
+ peer_addr_type, peer_addr, params);
+ ble_hs_test_util_verify_tx_create_conn(&hcc);
+
return rc;
}
@@ -371,25 +523,42 @@ ble_hs_test_util_conn_cancel(uint8_t ack_status)
int rc;
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
ack_status);
- rc = ble_gap_cancel();
+ rc = ble_gap_conn_cancel();
return rc;
}
+void
+ble_hs_test_util_conn_cancel_full(void)
+{
+ struct hci_le_conn_complete evt;
+ int rc;
+
+ ble_hs_test_util_conn_cancel(0);
+
+ memset(&evt, 0, sizeof evt);
+ evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+ evt.status = BLE_ERR_UNK_CONN_ID;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
+
+ rc = ble_gap_rx_conn_complete(&evt);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
int
ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status)
{
int rc;
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LINK_CTRL,
- BLE_HCI_OCF_DISCONNECT_CMD),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LINK_CTRL,
+ BLE_HCI_OCF_DISCONNECT_CMD),
hci_status);
- rc = ble_gap_terminate(conn_handle);
+ rc = ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
return rc;
}
@@ -410,9 +579,19 @@ ble_hs_test_util_conn_disconnect(uint16_t conn_handle)
}
int
-ble_hs_test_util_disc(uint32_t duration_ms, uint8_t discovery_mode,
- uint8_t scan_type, uint8_t filter_policy,
- ble_gap_disc_fn *cb, void *cb_arg, int fail_idx,
+ble_hs_test_util_exp_hci_status(int cmd_idx, int fail_idx, uint8_t fail_status)
+{
+ if (cmd_idx == fail_idx) {
+ return BLE_HS_HCI_ERR(fail_status);
+ } else {
+ return 0;
+ }
+}
+
+int
+ble_hs_test_util_disc(uint8_t own_addr_type, int32_t duration_ms,
+ const struct ble_gap_disc_params *disc_params,
+ ble_gap_event_fn *cb, void *cb_arg, int fail_idx,
uint8_t fail_status)
{
int rc;
@@ -420,27 +599,77 @@ ble_hs_test_util_disc(uint32_t duration_ms, uint8_t discovery_mode,
ble_hs_test_util_set_ack_seq(((struct ble_hs_test_util_phony_ack[]) {
{
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
- fail_idx == 0 ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(0, fail_idx, fail_status),
},
{
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
- fail_idx == 1 ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(1, fail_idx, fail_status),
},
{ 0 }
}));
- rc = ble_gap_disc(duration_ms, discovery_mode, scan_type, filter_policy,
- BLE_ADDR_TYPE_PUBLIC,
+ rc = ble_gap_disc(own_addr_type, duration_ms, disc_params,
cb, cb_arg);
return rc;
}
int
-ble_hs_test_util_adv_start(uint8_t discoverable_mode,
- uint8_t connectable_mode,
- uint8_t *peer_addr, uint8_t peer_addr_type,
- struct ble_gap_adv_params *adv_params,
+ble_hs_test_util_disc_cancel(uint8_t ack_status)
+{
+ int rc;
+
+ ble_hs_test_util_set_ack(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ ack_status);
+
+ rc = ble_gap_disc_cancel();
+ return rc;
+}
+
+static void
+ble_hs_test_util_verify_tx_rd_pwr(void)
+{
+ uint8_t param_len;
+
+ ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR,
+ &param_len);
+ TEST_ASSERT(param_len == 0);
+}
+
+int
+ble_hs_test_util_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
+ uint8_t hci_status)
+{
+ int auto_pwr;
+ int rc;
+
+ auto_pwr = adv_fields->tx_pwr_lvl_is_present &&
+ adv_fields->tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+ if (auto_pwr) {
+ ble_hs_test_util_set_ack_params(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
+ hci_status,
+ ((uint8_t[1]){0}), 1);
+ }
+
+ rc = ble_gap_adv_set_fields(adv_fields);
+ if (rc == 0 && auto_pwr) {
+ /* Verify tx of set advertising params command. */
+ ble_hs_test_util_verify_tx_rd_pwr();
+ }
+
+ return rc;
+}
+
+int
+ble_hs_test_util_adv_start(uint8_t own_addr_type,
+ uint8_t peer_addr_type, const uint8_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params,
ble_gap_event_fn *cb, void *cb_arg,
int fail_idx, uint8_t fail_status)
{
@@ -456,31 +685,23 @@ ble_hs_test_util_adv_start(uint8_t discoverable_mode,
};
i++;
- if (connectable_mode != BLE_GAP_CONN_MODE_DIR) {
- acks[i] = (struct ble_hs_test_util_phony_ack) {
- BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
- fail_idx == i ? fail_status : 0,
- { 0 },
- 1,
- };
- i++;
-
+ if (adv_params->conn_mode != BLE_GAP_CONN_MODE_DIR) {
acks[i] = (struct ble_hs_test_util_phony_ack) {
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_DATA),
- fail_idx == i ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(i, fail_idx, fail_status),
};
i++;
acks[i] = (struct ble_hs_test_util_phony_ack) {
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA),
- fail_idx == i ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(i, fail_idx, fail_status),
};
i++;
}
acks[i] = (struct ble_hs_test_util_phony_ack) {
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
- fail_idx == i ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(i, fail_idx, fail_status),
};
i++;
@@ -488,9 +709,8 @@ ble_hs_test_util_adv_start(uint8_t discoverable_mode,
ble_hs_test_util_set_ack_seq(acks);
- rc = ble_gap_adv_start(discoverable_mode, connectable_mode,
- peer_addr, peer_addr_type,
- adv_params, cb, cb_arg);
+ rc = ble_gap_adv_start(own_addr_type, peer_addr_type, peer_addr,
+ BLE_HS_FOREVER, adv_params, cb, cb_arg);
return rc;
}
@@ -523,14 +743,14 @@ ble_hs_test_util_wl_set(struct ble_gap_white_entry *white_list,
cmd_idx = 0;
acks[cmd_idx] = (struct ble_hs_test_util_phony_ack) {
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST),
- fail_idx == cmd_idx ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(cmd_idx, fail_idx, fail_status),
};
cmd_idx++;
for (i = 0; i < white_list_count; i++) {
acks[cmd_idx] = (struct ble_hs_test_util_phony_ack) {
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_ADD_WHITE_LIST),
- fail_idx == cmd_idx ? fail_status : 0,
+ ble_hs_test_util_exp_hci_status(cmd_idx, fail_idx, fail_status),
};
cmd_idx++;
@@ -557,6 +777,38 @@ ble_hs_test_util_conn_update(uint16_t conn_handle,
}
int
+ble_hs_test_util_set_our_irk(const uint8_t *irk, int fail_idx,
+ uint8_t hci_status)
+{
+ int rc;
+
+ ble_hs_test_util_set_ack_seq(((struct ble_hs_test_util_phony_ack[]) {
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ ble_hs_test_util_exp_hci_status(0, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
+ ble_hs_test_util_exp_hci_status(1, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ ble_hs_test_util_exp_hci_status(2, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
+ ble_hs_test_util_exp_hci_status(3, fail_idx, hci_status),
+ },
+ {
+ 0
+ }
+ }));
+
+ rc = ble_hs_pvcy_set_our_irk(irk);
+ return rc;
+}
+
+int
ble_hs_test_util_security_initiate(uint16_t conn_handle, uint8_t hci_status)
{
int rc;
@@ -597,6 +849,8 @@ ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
conn = ble_hs_conn_find(conn_handle);
if (conn != NULL) {
rc = ble_l2cap_rx(conn, hci_hdr, om, &rx_cb, &rx_buf);
+ } else {
+ os_mbuf_free_chain(om);
}
ble_hs_unlock();
@@ -624,15 +878,15 @@ ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
struct os_mbuf *om;
int rc;
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
rc = os_mbuf_append(om, data, len);
TEST_ASSERT_FATAL(rc == 0);
hci_hdr.hdh_handle_pb_bc =
- host_hci_handle_pb_bc_join(conn_handle,
- BLE_HCI_PB_FIRST_FLUSH, 0);
+ ble_hs_hci_util_handle_pb_bc_join(conn_handle,
+ BLE_HCI_PB_FIRST_FLUSH, 0);
hci_hdr.hdh_len = OS_MBUF_PKTHDR(om)->omp_len;
rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, cid, &hci_hdr, om);
@@ -640,6 +894,26 @@ ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
}
void
+ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu)
+{
+ struct ble_att_mtu_cmd cmd;
+ uint8_t buf[BLE_ATT_MTU_CMD_SZ];
+ int rc;
+
+ cmd.bamc_mtu = mtu;
+
+ if (is_req) {
+ ble_att_mtu_req_write(buf, sizeof buf, &cmd);
+ } else {
+ ble_att_mtu_rsp_write(buf, sizeof buf, &cmd);
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+}
+
+void
ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op,
uint8_t error_code, uint16_t err_handle)
{
@@ -666,48 +940,55 @@ ble_hs_test_util_set_startup_acks(void)
*/
ble_hs_test_util_set_ack_seq(((struct ble_hs_test_util_phony_ack[]) {
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
- BLE_HCI_OCF_CB_RESET),
+ .opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
+ BLE_HCI_OCF_CB_RESET),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
- BLE_HCI_OCF_CB_SET_EVENT_MASK),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
- BLE_HCI_OCF_CB_SET_EVENT_MASK2),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK2),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_SET_EVENT_MASK),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EVENT_MASK),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_RD_BUF_SIZE),
- .evt_params = { 0xff, 0xff, 1 },
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE),
+ /* Use a very low buffer size (16) to test fragmentation. */
+ .evt_params = { 0x10, 0x00, 0x20 },
.evt_params_len = 3,
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
.evt_params = { 0 },
.evt_params_len = 8,
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR),
+ .evt_params = BLE_HS_TEST_UTIL_PUB_ADDR_VAL,
+ .evt_params_len = 6,
+ },
+ {
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
},
{
- .opcode = host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
},
{ 0 }
}));
@@ -790,9 +1071,26 @@ ble_hs_test_util_tx_all(void)
}
void
-ble_hs_test_util_set_public_addr(uint8_t *addr)
+ble_hs_test_util_verify_tx_prep_write(uint16_t attr_handle, uint16_t offset,
+ const void *data, int data_len)
{
- ble_hs_pvcy_set_our_id_addr(addr);
+ struct ble_att_prep_write_cmd req;
+ struct os_mbuf *om;
+
+ ble_hs_test_util_tx_all();
+ om = ble_hs_test_util_prev_tx_dequeue();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) ==
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + data_len);
+
+ om = os_mbuf_pullup(om, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ ble_att_prep_write_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.bapc_handle == attr_handle);
+ TEST_ASSERT(req.bapc_offset == offset);
+ TEST_ASSERT(os_mbuf_cmpf(om, BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ data, data_len) == 0);
}
void
@@ -811,8 +1109,354 @@ ble_hs_test_util_verify_tx_exec_write(uint8_t expected_flags)
}
void
+ble_hs_test_util_verify_tx_read_rsp_gen(uint8_t att_op,
+ uint8_t *attr_data, int attr_len)
+{
+ struct os_mbuf *om;
+ uint8_t u8;
+ int rc;
+ int i;
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+
+ rc = os_mbuf_copydata(om, 0, 1, &u8);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(u8 == att_op);
+
+ for (i = 0; i < attr_len; i++) {
+ rc = os_mbuf_copydata(om, i + 1, 1, &u8);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(u8 == attr_data[i]);
+ }
+
+ rc = os_mbuf_copydata(om, i + 1, 1, &u8);
+ TEST_ASSERT(rc != 0);
+}
+
+void
+ble_hs_test_util_verify_tx_read_rsp(uint8_t *attr_data, int attr_len)
+{
+ ble_hs_test_util_verify_tx_read_rsp_gen(BLE_ATT_OP_READ_RSP,
+ attr_data, attr_len);
+}
+
+void
+ble_hs_test_util_verify_tx_read_blob_rsp(uint8_t *attr_data, int attr_len)
+{
+ ble_hs_test_util_verify_tx_read_rsp_gen(BLE_ATT_OP_READ_BLOB_RSP,
+ attr_data, attr_len);
+}
+
+void
+ble_hs_test_util_verify_tx_write_rsp(void)
+{
+ struct os_mbuf *om;
+ uint8_t u8;
+ int rc;
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+
+ rc = os_mbuf_copydata(om, 0, 1, &u8);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(u8 == BLE_ATT_OP_WRITE_RSP);
+}
+
+void
+ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu)
+{
+ struct ble_att_mtu_cmd cmd;
+ struct os_mbuf *om;
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ if (is_req) {
+ ble_att_mtu_req_parse(om->om_data, om->om_len, &cmd);
+ } else {
+ ble_att_mtu_rsp_parse(om->om_data, om->om_len, &cmd);
+ }
+
+ TEST_ASSERT(cmd.bamc_mtu == mtu);
+}
+
+void
+ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
+ uint8_t error_code)
+{
+ struct ble_att_error_rsp rsp;
+ struct os_mbuf *om;
+ uint8_t buf[BLE_ATT_ERROR_RSP_SZ];
+ int rc;
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+
+ rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
+ TEST_ASSERT(rc == 0);
+
+ ble_att_error_rsp_parse(buf, sizeof buf, &rsp);
+
+ TEST_ASSERT(rsp.baep_req_op == req_op);
+ TEST_ASSERT(rsp.baep_handle == handle);
+ TEST_ASSERT(rsp.baep_error_code == error_code);
+}
+
+void
+ble_hs_test_util_set_static_rnd_addr(void)
+{
+ uint8_t addr[6] = { 1, 2, 3, 4, 5, 0xc1 };
+ int rc;
+
+ ble_hs_test_util_set_ack(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_RAND_ADDR), 0);
+
+ rc = ble_hs_id_set_rnd(addr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_get_first_hci_tx();
+}
+
+struct os_mbuf *
+ble_hs_test_util_om_from_flat(const void *buf, uint16_t len)
+{
+ struct os_mbuf *om;
+
+ om = ble_hs_mbuf_from_flat(buf, len);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ return om;
+}
+
+int
+ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a,
+ const struct ble_hs_test_util_flat_attr *b)
+{
+ if (a->handle != b->handle) {
+ return -1;
+ }
+ if (a->offset != b->offset) {
+ return -1;
+ }
+ if (a->value_len != b->value_len) {
+ return -1;
+ }
+ return memcmp(a->value, b->value, a->value_len);
+}
+
+void
+ble_hs_test_util_attr_to_flat(struct ble_hs_test_util_flat_attr *flat,
+ const struct ble_gatt_attr *attr)
+{
+ int rc;
+
+ flat->handle = attr->handle;
+ flat->offset = attr->offset;
+ rc = ble_hs_mbuf_to_flat(attr->om, flat->value, sizeof flat->value,
+ &flat->value_len);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+void
+ble_hs_test_util_attr_from_flat(struct ble_gatt_attr *attr,
+ const struct ble_hs_test_util_flat_attr *flat)
+{
+ attr->handle = flat->handle;
+ attr->offset = flat->offset;
+ attr->om = ble_hs_test_util_om_from_flat(flat->value, flat->value_len);
+}
+
+int
+ble_hs_test_util_read_local_flat(uint16_t attr_handle, uint16_t max_len,
+ void *buf, uint16_t *out_len)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ rc = ble_att_svr_read_local(attr_handle, &om);
+ if (rc != 0) {
+ return rc;
+ }
+
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(om) <= max_len);
+
+ rc = os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), buf);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ *out_len = OS_MBUF_PKTLEN(om);
+
+ os_mbuf_free_chain(om);
+ return 0;
+}
+
+int
+ble_hs_test_util_write_local_flat(uint16_t attr_handle,
+ const void *buf, uint16_t buf_len)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_test_util_om_from_flat(buf, buf_len);
+ rc = ble_att_svr_write_local(attr_handle, om);
+ return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_flat(uint16_t conn_handle, uint16_t attr_handle,
+ const void *data, uint16_t data_len,
+ ble_gatt_attr_fn *cb, void *cb_arg)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_test_util_om_from_flat(data, data_len);
+ rc = ble_gattc_write(conn_handle, attr_handle, om, cb, cb_arg);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_no_rsp_flat(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *data, uint16_t data_len)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_test_util_om_from_flat(data, data_len);
+ rc = ble_gattc_write_no_rsp(conn_handle, attr_handle, om);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_long_flat(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *data, uint16_t data_len,
+ ble_gatt_attr_fn *cb, void *cb_arg)
+{
+ struct os_mbuf *om;
+ int rc;
+
+ om = ble_hs_test_util_om_from_flat(data, data_len);
+ rc = ble_gattc_write_long(conn_handle, attr_handle, om, cb, cb_arg);
+
+ return rc;
+}
+
+static int
+ble_hs_test_util_mbuf_chain_len(const struct os_mbuf *om)
+{
+ int count;
+
+ count = 0;
+ while (om != NULL) {
+ count++;
+ om = SLIST_NEXT(om, om_next);
+ }
+
+ return count;
+}
+
+int
+ble_hs_test_util_mbuf_count(const struct ble_hs_test_util_mbuf_params *params)
+{
+ const struct ble_att_prep_entry *prep;
+ const struct os_mbuf_pkthdr *omp;
+ const struct ble_l2cap_chan *chan;
+ const struct ble_hs_conn *conn;
+ const struct os_mbuf *om;
+ int count;
+ int i;
+
+ ble_hs_process_tx_data_queue();
+ ble_hs_process_rx_data_queue();
+
+ count = ble_hs_test_util_mbuf_mpool.mp_num_free;
+
+ if (params->prev_tx) {
+ count += ble_hs_test_util_mbuf_chain_len(ble_hs_test_util_prev_tx_cur);
+ STAILQ_FOREACH(omp, &ble_hs_test_util_prev_tx_queue, omp_next) {
+ om = OS_MBUF_PKTHDR_TO_MBUF(omp);
+ count += ble_hs_test_util_mbuf_chain_len(om);
+ }
+ }
+
+ ble_hs_lock();
+ for (i = 0; ; i++) {
+ conn = ble_hs_conn_find_by_idx(i);
+ if (conn == NULL) {
+ break;
+ }
+
+ if (params->rx_queue) {
+ SLIST_FOREACH(chan, &conn->bhc_channels, blc_next) {
+ count += ble_hs_test_util_mbuf_chain_len(chan->blc_rx_buf);
+ }
+ }
+
+ if (params->prep_list) {
+ SLIST_FOREACH(prep, &conn->bhc_att_svr.basc_prep_list, bape_next) {
+ count += ble_hs_test_util_mbuf_chain_len(prep->bape_value);
+ }
+ }
+ }
+ ble_hs_unlock();
+
+ return count;
+}
+
+void
+ble_hs_test_util_assert_mbufs_freed(
+ const struct ble_hs_test_util_mbuf_params *params)
+{
+ static const struct ble_hs_test_util_mbuf_params dflt = {
+ .prev_tx = 1,
+ .rx_queue = 1,
+ .prep_list = 1,
+ };
+
+ int count;
+
+ if (params == NULL) {
+ params = &dflt;
+ }
+
+ count = ble_hs_test_util_mbuf_count(params);
+ TEST_ASSERT(count == ble_hs_test_util_mbuf_mpool.mp_num_blocks);
+}
+
+void
+ble_hs_test_util_post_test(void *arg)
+{
+ ble_hs_test_util_assert_mbufs_freed(arg);
+}
+
+static int
+ble_hs_test_util_pkt_txed(struct os_mbuf *om, void *arg)
+{
+ ble_hs_test_util_prev_tx_enqueue(om);
+ return 0;
+}
+
+static int
+ble_hs_test_util_hci_txed(uint8_t *cmdbuf, void *arg)
+{
+ ble_hs_test_util_enqueue_hci_tx(cmdbuf);
+ ble_hci_trans_buf_free(cmdbuf);
+ return 0;
+}
+
+void
ble_hs_test_util_init(void)
{
+ struct ble_hci_ram_cfg hci_cfg;
struct ble_hs_cfg cfg;
int rc;
@@ -827,6 +1471,12 @@ ble_hs_test_util_init(void)
cfg = ble_hs_cfg_dflt;
cfg.max_connections = 8;
+ cfg.max_l2cap_chans = 3 * cfg.max_connections;
+ cfg.max_services = 16;
+ cfg.max_client_configs = 32;
+ cfg.max_attrs = 64;
+ cfg.max_gattc_procs = 16;
+
rc = ble_hs_init(&ble_hs_test_util_evq, &cfg);
TEST_ASSERT_FATAL(rc == 0);
@@ -846,9 +1496,19 @@ ble_hs_test_util_init(void)
rc = os_msys_register(&ble_hs_test_util_mbuf_pool);
TEST_ASSERT_FATAL(rc == 0);
- ble_hci_set_phony_ack_cb(NULL);
+ ble_hs_hci_set_phony_ack_cb(NULL);
- ble_hs_test_util_prev_hci_tx_clear();
+ ble_hci_trans_cfg_ll(ble_hs_test_util_hci_txed, NULL,
+ ble_hs_test_util_pkt_txed, NULL);
- ble_hs_test_util_set_public_addr(g_dev_addr);
+ hci_cfg = ble_hci_ram_cfg_dflt;
+ rc = ble_hci_ram_init(&hci_cfg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_set_startup_acks();
+
+ rc = ble_hs_start();
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_prev_hci_tx_clear();
}
diff --git a/net/nimble/host/src/test/ble_hs_test_util.h b/net/nimble/host/src/test/ble_hs_test_util.h
index 92032526..7780d4ee 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -27,14 +27,29 @@
struct ble_hs_conn;
struct ble_l2cap_chan;
struct hci_disconn_complete;
+struct hci_create_conn;
-struct os_eventq ble_hs_test_util_evq;
+extern struct os_eventq ble_hs_test_util_evq;
+extern const struct ble_gap_adv_params ble_hs_test_util_adv_params;
struct ble_hs_test_util_num_completed_pkts_entry {
uint16_t handle_id; /* 0 for terminating entry in array. */
uint16_t num_pkts;
};
+struct ble_hs_test_util_flat_attr {
+ uint16_t handle;
+ uint16_t offset;
+ uint8_t value[BLE_ATT_ATTR_MAX_LEN];
+ uint16_t value_len;
+};
+
+struct ble_hs_test_util_mbuf_params {
+ unsigned prev_tx:1;
+ unsigned rx_queue:1;
+ unsigned prep_list:1;
+};
+
void ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om);
struct os_mbuf *ble_hs_test_util_prev_tx_dequeue(void);
struct os_mbuf *ble_hs_test_util_prev_tx_dequeue_pullup(void);
@@ -54,28 +69,40 @@ void ble_hs_test_util_build_cmd_complete(uint8_t *dst, int len,
void ble_hs_test_util_build_cmd_status(uint8_t *dst, int len,
uint8_t status, uint8_t num_pkts,
uint16_t opcode);
-void ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t *our_rpa,
+void ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
+ const uint8_t *our_rpa,
uint8_t peer_addr_type,
- uint8_t *peer_id_addr,
- uint8_t *peer_rpa,
+ const uint8_t *peer_id_addr,
+ const uint8_t *peer_rpa,
ble_gap_event_fn *cb, void *cb_arg);
-void ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr,
+void ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *addr,
ble_gap_event_fn *cb, void *cb_arg);
-int ble_hs_test_util_conn_initiate(int addr_type, uint8_t *addr,
- struct ble_gap_crt_params *params,
- ble_gap_event_fn *cb, void *cb_arg,
+int ble_hs_test_util_connect(uint8_t own_addr_type,
+ uint8_t peer_addr_type,
+ const uint8_t *peer_addr,
+ int32_t duration_ms,
+ const struct ble_gap_conn_params *params,
+ ble_gap_event_fn *cb,
+ void *cb_arg,
uint8_t ack_status);
int ble_hs_test_util_conn_cancel(uint8_t ack_status);
+void ble_hs_test_util_conn_cancel_full(void);
int ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status);
void ble_hs_test_util_conn_disconnect(uint16_t conn_handle);
-int ble_hs_test_util_disc(uint32_t duration_ms, uint8_t discovery_mode,
- uint8_t scan_type, uint8_t filter_policy,
- ble_gap_disc_fn *cb, void *cb_arg, int fail_idx,
+int ble_hs_test_util_exp_hci_status(int cmd_idx, int fail_idx,
+ uint8_t fail_status);
+int ble_hs_test_util_disc(uint8_t own_addr_type, int32_t duration_ms,
+ const struct ble_gap_disc_params *disc_params,
+ ble_gap_event_fn *cb, void *cb_arg, int fail_idx,
uint8_t fail_status);
-int ble_hs_test_util_adv_start(uint8_t discoverable_mode,
- uint8_t connectable_mode,
- uint8_t *peer_addr, uint8_t peer_addr_type,
- struct ble_gap_adv_params *adv_params,
+int ble_hs_test_util_disc_cancel(uint8_t ack_status);
+void ble_hs_test_util_verify_tx_create_conn(const struct hci_create_conn *exp);
+int ble_hs_test_util_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
+ uint8_t hci_status);
+int ble_hs_test_util_adv_start(uint8_t own_addr_type,
+ uint8_t peer_addr_type,
+ const uint8_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params,
ble_gap_event_fn *cb, void *cb_arg,
int fail_idx, uint8_t fail_status);
int ble_hs_test_util_adv_stop(uint8_t hci_status);
@@ -85,6 +112,8 @@ int ble_hs_test_util_wl_set(struct ble_gap_white_entry *white_list,
int ble_hs_test_util_conn_update(uint16_t conn_handle,
struct ble_gap_upd_params *params,
uint8_t hci_status);
+int ble_hs_test_util_set_our_irk(const uint8_t *irk, int fail_idx,
+ uint8_t hci_status);
int ble_hs_test_util_security_initiate(uint16_t conn_handle,
uint8_t hci_status);
int ble_hs_test_util_l2cap_rx_first_frag(uint16_t conn_handle, uint16_t cid,
@@ -96,6 +125,8 @@ int ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
int ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
const void *data, int len);
void ble_hs_test_util_rx_hci_buf_size_ack(uint16_t buf_size);
+void ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req,
+ uint16_t mtu);
void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op,
uint8_t error_code, uint16_t err_handle);
void ble_hs_test_util_set_startup_acks(void);
@@ -106,8 +137,46 @@ void ble_hs_test_util_rx_disconn_complete_event(
uint8_t *ble_hs_test_util_verify_tx_hci(uint8_t ogf, uint16_t ocf,
uint8_t *out_param_len);
void ble_hs_test_util_tx_all(void);
-void ble_hs_test_util_set_public_addr(uint8_t *addr);
+void ble_hs_test_util_verify_tx_prep_write(uint16_t attr_handle,
+ uint16_t offset,
+ const void *data, int data_len);
void ble_hs_test_util_verify_tx_exec_write(uint8_t expected_flags);
+void ble_hs_test_util_verify_tx_read_rsp(uint8_t *attr_data, int attr_len);
+void ble_hs_test_util_verify_tx_read_blob_rsp(uint8_t *attr_data,
+ int attr_len);
+void ble_hs_test_util_verify_tx_write_rsp(void);
+void ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu);
+void ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
+ uint8_t error_code);
+void ble_hs_test_util_set_static_rnd_addr(void);
+struct os_mbuf *ble_hs_test_util_om_from_flat(const void *buf, uint16_t len);
+int ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a,
+ const struct ble_hs_test_util_flat_attr *b);
+void ble_hs_test_util_attr_to_flat(struct ble_hs_test_util_flat_attr *flat,
+ const struct ble_gatt_attr *attr);
+void ble_hs_test_util_attr_from_flat(
+ struct ble_gatt_attr *attr, const struct ble_hs_test_util_flat_attr *flat);
+int ble_hs_test_util_read_local_flat(uint16_t attr_handle, uint16_t max_len,
+ void *buf, uint16_t *out_len);
+int ble_hs_test_util_write_local_flat(uint16_t attr_handle,
+ const void *buf, uint16_t buf_len);
+int ble_hs_test_util_gatt_write_flat(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *data, uint16_t data_len,
+ ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_hs_test_util_gatt_write_no_rsp_flat(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *data,
+ uint16_t data_len);
+int ble_hs_test_util_gatt_write_long_flat(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *data, uint16_t data_len,
+ ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_hs_test_util_mbuf_count(
+ const struct ble_hs_test_util_mbuf_params *params);
+void ble_hs_test_util_assert_mbufs_freed(
+ const struct ble_hs_test_util_mbuf_params *params);
+void ble_hs_test_util_post_test(void *arg);
void ble_hs_test_util_init(void);
#endif
diff --git a/net/nimble/host/src/test/ble_l2cap_test.c b/net/nimble/host/src/test/ble_l2cap_test.c
index 161bd55c..69db2f87 100644
--- a/net/nimble/host/src/test/ble_l2cap_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_test.c
@@ -21,7 +21,6 @@
#include <errno.h>
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
-#include "host/host_hci.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
@@ -74,7 +73,8 @@ ble_l2cap_test_util_rx_update_req(uint16_t conn_handle, uint8_t id,
ble_l2cap_sig_update_req_write(v, BLE_L2CAP_SIG_UPDATE_REQ_SZ, &req);
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CONN_UPDATE), 0);
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CONN_UPDATE), 0);
rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG,
&hci_hdr, om);
TEST_ASSERT_FATAL(rc == 0);
@@ -242,7 +242,7 @@ ble_l2cap_test_util_rx_first_frag(uint16_t conn_handle,
void *v;
int rc;
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
v = os_mbuf_extend(om, l2cap_frag_len);
@@ -266,7 +266,7 @@ ble_l2cap_test_util_rx_next_frag(uint16_t conn_handle, uint16_t hci_len)
void *v;
int rc;
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
v = os_mbuf_extend(om, hci_len);
@@ -374,7 +374,7 @@ TEST_CASE(ble_l2cap_test_case_frag_single)
/*** HCI header specifies middle fragment without start. */
hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
om = ble_l2cap_prepend_hdr(om, 0, 5);
@@ -480,12 +480,11 @@ TEST_CASE(ble_l2cap_test_case_sig_unsol_rsp)
*****************************************************************************/
static int
-ble_l2cap_test_util_conn_cb(int event, struct ble_gap_conn_ctxt *ctxt,
- void *arg)
+ble_l2cap_test_util_conn_cb(struct ble_gap_event *event, void *arg)
{
int *accept;
- switch (event) {
+ switch (event->type) {
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ:
accept = arg;
return !*accept;
@@ -667,6 +666,8 @@ TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_bad_id)
TEST_SUITE(ble_l2cap_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_l2cap_test_case_bad_header();
ble_l2cap_test_case_frag_single();
ble_l2cap_test_case_frag_multiple();
diff --git a/net/nimble/host/src/test/ble_os_test.c b/net/nimble/host/src/test/ble_os_test.c
index ee7ffd65..a9c28ea9 100644
--- a/net/nimble/host/src/test/ble_os_test.c
+++ b/net/nimble/host/src/test/ble_os_test.c
@@ -21,18 +21,13 @@
#include "os/os.h"
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
-#include "nimble/hci_transport.h"
+#include "nimble/ble_hci_trans.h"
#include "host/ble_hs_test.h"
#include "host/ble_gap.h"
#include "ble_hs_test_util.h"
-#ifdef ARCH_sim
-#define BLE_OS_TEST_STACK_SIZE 1024
-#define BLE_OS_TEST_APP_STACK_SIZE 1024
-#else
#define BLE_OS_TEST_STACK_SIZE 256
#define BLE_OS_TEST_APP_STACK_SIZE 256
-#endif
#define BLE_OS_TEST_APP_PRIO 9
#define BLE_OS_TEST_TASK_PRIO 10
@@ -48,7 +43,7 @@ static uint8_t ble_os_test_peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
static void ble_os_test_app_task_handler(void *arg);
-static int ble_os_test_gap_event;
+static int ble_os_test_gap_event_type;
static void
ble_os_test_init_app_task(void)
@@ -96,20 +91,23 @@ ble_os_test_misc_conn_exists(uint16_t conn_handle)
}
static int
-ble_gap_direct_connect_test_connect_cb(int event,
- struct ble_gap_conn_ctxt *ctxt,
- void *arg)
+ble_gap_direct_connect_test_connect_cb(struct ble_gap_event *event, void *arg)
{
+ struct ble_gap_conn_desc desc;
int *cb_called;
+ int rc;
cb_called = arg;
*cb_called = 1;
- TEST_ASSERT(event == BLE_GAP_EVENT_CONNECT);
- TEST_ASSERT(ctxt->connect.status == 0);
- TEST_ASSERT(ctxt->desc->conn_handle == 2);
- TEST_ASSERT(ctxt->desc->peer_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
- TEST_ASSERT(memcmp(ctxt->desc->peer_id_addr, ble_os_test_peer_addr, 6) == 0);
+ TEST_ASSERT(event->type == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(event->connect.status == 0);
+ TEST_ASSERT(event->connect.conn_handle == 2);
+
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(desc.peer_id_addr_type == BLE_ADDR_TYPE_PUBLIC);
+ TEST_ASSERT(memcmp(desc.peer_id_addr, ble_os_test_peer_addr, 6) == 0);
return 0;
}
@@ -133,9 +131,10 @@ ble_gap_direct_connect_test_task_handler(void *arg)
TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
/* Initiate a direct connection. */
- ble_hs_test_util_conn_initiate(0, addr, NULL,
- ble_gap_direct_connect_test_connect_cb,
- &cb_called, 0);
+ ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ addr, 0, NULL,
+ ble_gap_direct_connect_test_connect_cb,
+ &cb_called, 0);
TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
TEST_ASSERT(!cb_called);
@@ -168,22 +167,23 @@ TEST_CASE(ble_gap_direct_connect_test_case)
os_start();
}
-static void
-ble_gap_gen_disc_test_connect_cb(int event, int status,
- struct ble_gap_disc_desc *desc, void *arg)
+static int
+ble_os_disc_test_cb(struct ble_gap_event *event, void *arg)
{
int *cb_called;
cb_called = arg;
*cb_called = 1;
- TEST_ASSERT(event == BLE_GAP_EVENT_DISC_COMPLETE);
- TEST_ASSERT(status == 0);
+ TEST_ASSERT(event->type == BLE_GAP_EVENT_DISC_COMPLETE);
+
+ return 0;
}
static void
-ble_gap_gen_disc_test_task_handler(void *arg)
+ble_os_disc_test_task_handler(void *arg)
{
+ struct ble_gap_disc_params disc_params;
int cb_called;
int rc;
@@ -203,11 +203,10 @@ ble_gap_gen_disc_test_task_handler(void *arg)
TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
TEST_ASSERT(!ble_gap_master_in_progress());
- /* Initiate the general discovery procedure with a 200 ms timeout. */
- rc = ble_hs_test_util_disc(300, BLE_GAP_DISC_MODE_GEN,
- BLE_HCI_SCAN_TYPE_ACTIVE,
- BLE_HCI_SCAN_FILT_NO_WL,
- ble_gap_gen_disc_test_connect_cb,
+ /* Initiate the general discovery procedure with a 300 ms timeout. */
+ memset(&disc_params, 0, sizeof disc_params);
+ rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC, 300, &disc_params,
+ ble_os_disc_test_cb,
&cb_called, 0, 0);
TEST_ASSERT(rc == 0);
TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
@@ -226,7 +225,8 @@ ble_gap_gen_disc_test_task_handler(void *arg)
TEST_ASSERT(!cb_called);
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
0);
/* Wait 250 more ms; verify scan completed. */
@@ -238,13 +238,13 @@ ble_gap_gen_disc_test_task_handler(void *arg)
tu_restart();
}
-TEST_CASE(ble_gap_gen_disc_test_case)
+TEST_CASE(ble_os_disc_test_case)
{
ble_os_test_misc_init();
os_task_init(&ble_os_test_task,
- "ble_gap_gen_disc_test_task",
- ble_gap_gen_disc_test_task_handler, NULL,
+ "ble_os_disc_test_task",
+ ble_os_disc_test_task_handler, NULL,
BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
@@ -252,15 +252,15 @@ TEST_CASE(ble_gap_gen_disc_test_case)
}
static int
-ble_gap_terminate_cb(int event, struct ble_gap_conn_ctxt *ctxt, void *arg)
+ble_gap_terminate_cb(struct ble_gap_event *event, void *arg)
{
int *disconn_handle;
- ble_os_test_gap_event = event;
+ ble_os_test_gap_event_type = event->type;
- if (event == BLE_GAP_EVENT_DISCONNECT) {
+ if (event->type == BLE_GAP_EVENT_DISCONNECT) {
disconn_handle = arg;
- *disconn_handle = ctxt->desc->conn_handle;
+ *disconn_handle = event->disconnect.conn.conn_handle;
}
return 0;
@@ -294,8 +294,9 @@ ble_gap_terminate_test_task_handler(void *arg)
TEST_ASSERT(!ble_gap_master_in_progress());
/* Create two direct connections. */
- ble_hs_test_util_conn_initiate(0, addr1, NULL, ble_gap_terminate_cb,
- &disconn_handle, 0);
+ ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ addr1, 0, NULL, ble_gap_terminate_cb,
+ &disconn_handle, 0);
memset(&conn_evt, 0, sizeof conn_evt);
conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
conn_evt.status = BLE_ERR_SUCCESS;
@@ -304,8 +305,9 @@ ble_gap_terminate_test_task_handler(void *arg)
rc = ble_gap_rx_conn_complete(&conn_evt);
TEST_ASSERT(rc == 0);
- ble_hs_test_util_conn_initiate(0, addr2, NULL, ble_gap_terminate_cb,
- &disconn_handle, 0);
+ ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
+ addr2, 0, NULL, ble_gap_terminate_cb,
+ &disconn_handle, 0);
memset(&conn_evt, 0, sizeof conn_evt);
conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
conn_evt.status = BLE_ERR_SUCCESS;
@@ -324,7 +326,7 @@ ble_gap_terminate_test_task_handler(void *arg)
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_rx_disconn_complete_event(&disconn_evt);
- TEST_ASSERT(ble_os_test_gap_event == BLE_GAP_EVENT_DISCONNECT);
+ TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(disconn_handle == 1);
TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
@@ -336,7 +338,7 @@ ble_gap_terminate_test_task_handler(void *arg)
disconn_evt.status = 0;
disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
ble_hs_test_util_rx_disconn_complete_event(&disconn_evt);
- TEST_ASSERT(ble_os_test_gap_event == BLE_GAP_EVENT_DISCONNECT);
+ TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
TEST_ASSERT(disconn_handle == 2);
TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(2));
@@ -384,7 +386,9 @@ TEST_CASE(ble_gap_terminate_test_case)
TEST_SUITE(ble_os_test_suite)
{
- ble_gap_gen_disc_test_case();
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+ ble_os_disc_test_case();
ble_gap_direct_connect_test_case();
ble_gap_terminate_test_case();
}
diff --git a/net/nimble/host/src/test/ble_sm_lgcy_test.c b/net/nimble/host/src/test/ble_sm_lgcy_test.c
index 59dceab4..6e451ca9 100644
--- a/net/nimble/host/src/test/ble_sm_lgcy_test.c
+++ b/net/nimble/host/src/test/ble_sm_lgcy_test.c
@@ -23,7 +23,6 @@
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
#include "nimble/nimble_opt.h"
-#include "host/host_hci.h"
#include "host/ble_sm.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
@@ -822,6 +821,8 @@ TEST_CASE(ble_sm_lgcy_peer_pk_iio4_rio4_b1_iat0_rat0_ik7_rk7)
TEST_SUITE(ble_sm_lgcy_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
/*** No privacy. */
/* Peer as initiator. */
diff --git a/net/nimble/host/src/test/ble_sm_sc_test.c b/net/nimble/host/src/test/ble_sm_sc_test.c
index 4d60f0c5..518720c9 100644
--- a/net/nimble/host/src/test/ble_sm_sc_test.c
+++ b/net/nimble/host/src/test/ble_sm_sc_test.c
@@ -23,7 +23,6 @@
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
#include "nimble/nimble_opt.h"
-#include "host/host_hci.h"
#include "host/ble_sm.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
@@ -4879,6 +4878,8 @@ TEST_CASE(ble_sm_sc_us_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3)
TEST_SUITE(ble_sm_sc_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
/*** No privacy. */
/* Peer as initiator. */
diff --git a/net/nimble/host/src/test/ble_sm_test.c b/net/nimble/host/src/test/ble_sm_test.c
index d8909965..f139ddb7 100644
--- a/net/nimble/host/src/test/ble_sm_test.c
+++ b/net/nimble/host/src/test/ble_sm_test.c
@@ -23,7 +23,6 @@
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
#include "nimble/nimble_opt.h"
-#include "host/host_hci.h"
#include "host/ble_sm.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
@@ -648,6 +647,8 @@ TEST_CASE(ble_sm_test_case_us_fail_inval)
TEST_SUITE(ble_sm_gen_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_sm_test_case_f4();
ble_sm_test_case_f5();
ble_sm_test_case_f6();
diff --git a/net/nimble/host/src/test/ble_sm_test_util.c b/net/nimble/host/src/test/ble_sm_test_util.c
index 2225f30e..9edaa04c 100644
--- a/net/nimble/host/src/test/ble_sm_test_util.c
+++ b/net/nimble/host/src/test/ble_sm_test_util.c
@@ -23,15 +23,16 @@
#include "testutil/testutil.h"
#include "nimble/hci_common.h"
#include "nimble/nimble_opt.h"
-#include "host/host_hci.h"
#include "host/ble_sm.h"
#include "host/ble_hs_test.h"
+#include "host/ble_hs_id.h"
#include "ble_hs_test_util.h"
#include "ble_sm_test_util.h"
-int ble_sm_test_gap_event;
+int ble_sm_test_gap_event_type;
int ble_sm_test_gap_status;
struct ble_gap_sec_state ble_sm_test_sec_state;
+static struct ble_gap_passkey_params ble_sm_test_ioact;
int ble_sm_test_store_obj_type;
union ble_store_key ble_sm_test_store_key;
@@ -102,9 +103,10 @@ ble_sm_test_util_init(void)
ble_hs_cfg.store_write_cb = ble_sm_test_util_store_write;
ble_sm_test_store_obj_type = -1;
- ble_sm_test_gap_event = -1;
+ ble_sm_test_gap_event_type = -1;
ble_sm_test_gap_status = -1;
+ memset(&ble_sm_test_ioact, 0, sizeof ble_sm_test_ioact);
memset(&ble_sm_test_sec_state, 0xff, sizeof ble_sm_test_sec_state);
}
@@ -223,19 +225,19 @@ ble_sm_test_util_init_good(struct ble_sm_test_params *params,
ble_hs_cfg.sm_their_key_dist = out_us->pair_cmd->init_key_dist;
}
- ble_hs_test_util_set_public_addr(out_us->id_addr);
+ ble_hs_id_set_pub(out_us->id_addr);
ble_sm_dbg_set_next_pair_rand(out_us->randoms[0].value);
ble_sm_dbg_set_next_ediv(out_us->ediv);
ble_sm_dbg_set_next_master_id_rand(out_us->rand_num);
ble_sm_dbg_set_next_ltk(out_us->ltk);
- ble_hs_pvcy_set_our_irk(out_us->id_info->irk);
+ ble_hs_test_util_set_our_irk(out_us->id_info->irk, 0, 0);
ble_sm_dbg_set_next_csrk(out_us->sign_info->sig_key);
if (out_us->public_key != NULL) {
ble_sm_dbg_set_sc_keys(out_us->public_key->x, params->our_priv_key);
}
- ble_hs_test_util_create_rpa_conn(2, out_us->rpa,
+ ble_hs_test_util_create_rpa_conn(2, out_us->addr_type, out_us->rpa,
out_peer->addr_type,
out_peer->id_addr, out_peer->rpa,
ble_sm_test_util_conn_cb,
@@ -260,31 +262,32 @@ ble_sm_test_util_init_good(struct ble_sm_test_params *params,
}
}
-struct ble_gap_passkey_action ble_sm_test_ioact;
-
int
-ble_sm_test_util_conn_cb(int event, struct ble_gap_conn_ctxt *ctxt, void *arg)
+ble_sm_test_util_conn_cb(struct ble_gap_event *event, void *arg)
{
+ struct ble_gap_conn_desc desc;
int rc;
- switch (event) {
+ switch (event->type) {
case BLE_GAP_EVENT_ENC_CHANGE:
- ble_sm_test_gap_status = ctxt->enc_change.status;
- ble_sm_test_sec_state = ctxt->desc->sec_state;
- rc = 0;
+ ble_sm_test_gap_status = event->enc_change.status;
+
+ rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_sm_test_sec_state = desc.sec_state;
break;
case BLE_GAP_EVENT_PASSKEY_ACTION:
- ble_sm_test_ioact = ctxt->passkey_action;
+ ble_sm_test_ioact = event->passkey.params;
break;
default:
return 0;
}
- ble_sm_test_gap_event = event;
+ ble_sm_test_gap_event_type = event->type;
- return rc;
+ return 0;
}
static void
@@ -302,7 +305,7 @@ ble_sm_test_util_rx_pair_cmd(uint16_t conn_handle, uint8_t op,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_CMD_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_CMD_SZ;
@@ -349,7 +352,7 @@ ble_sm_test_util_rx_confirm(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_CONFIRM_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_CONFIRM_SZ;
@@ -379,7 +382,7 @@ ble_sm_test_util_rx_random(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_RANDOM_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_RANDOM_SZ;
@@ -408,7 +411,7 @@ ble_sm_test_util_rx_sec_req(uint16_t conn_handle, struct ble_sm_sec_req *cmd,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_SEC_REQ_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_SEC_REQ_SZ;
@@ -437,7 +440,7 @@ ble_sm_test_util_rx_public_key(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PUBLIC_KEY_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_PUBLIC_KEY_SZ;
@@ -467,7 +470,7 @@ ble_sm_test_util_rx_dhkey_check(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_DHKEY_CHECK_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_DHKEY_CHECK_SZ;
@@ -497,7 +500,7 @@ ble_sm_test_util_rx_enc_info(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ENC_INFO_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_ENC_INFO_SZ;
@@ -527,7 +530,7 @@ ble_sm_test_util_rx_master_id(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_MASTER_ID_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_MASTER_ID_SZ;
@@ -557,7 +560,7 @@ ble_sm_test_util_rx_id_info(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ID_INFO_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_ID_INFO_SZ;
@@ -587,7 +590,7 @@ ble_sm_test_util_rx_id_addr_info(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ID_ADDR_INFO_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_ID_ADDR_INFO_SZ;
@@ -617,7 +620,7 @@ ble_sm_test_util_rx_sign_info(uint16_t conn_handle,
2, BLE_HCI_PB_FIRST_FLUSH,
BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_SIGN_INFO_SZ);
- om = ble_hs_misc_pkthdr();
+ om = ble_hs_mbuf_l2cap_pkt();
TEST_ASSERT_FATAL(om != NULL);
payload_len = BLE_SM_HDR_SZ + BLE_SM_SIGN_INFO_SZ;
@@ -637,7 +640,7 @@ ble_sm_test_util_verify_tx_hdr(uint8_t sm_op, uint16_t payload_len)
{
struct os_mbuf *om;
- om = ble_hs_test_util_prev_tx_dequeue();
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
TEST_ASSERT_FATAL(om != NULL);
TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_SM_HDR_SZ + payload_len);
@@ -797,10 +800,14 @@ ble_sm_test_util_verify_tx_id_addr_info(struct ble_sm_id_addr_info *exp_cmd)
{
struct ble_sm_id_addr_info cmd;
struct os_mbuf *om;
- uint8_t *our_id_addr;
- uint8_t our_id_addr_type;
+ const uint8_t *our_id_addr;
+ int rc;
- our_id_addr = ble_hs_pvcy_our_id_addr(&our_id_addr_type);
+ ble_hs_lock();
+ rc = ble_hs_id_addr(exp_cmd->addr_type, &our_id_addr, NULL);
+ ble_hs_unlock();
+
+ TEST_ASSERT_FATAL(rc == 0);
ble_hs_test_util_tx_all();
om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_IDENTITY_ADDR_INFO,
@@ -809,8 +816,6 @@ ble_sm_test_util_verify_tx_id_addr_info(struct ble_sm_id_addr_info *exp_cmd)
TEST_ASSERT(cmd.addr_type == exp_cmd->addr_type);
TEST_ASSERT(memcmp(cmd.bd_addr, exp_cmd->bd_addr, 6) == 0);
-
- TEST_ASSERT(cmd.addr_type == our_id_addr_type);
TEST_ASSERT(memcmp(cmd.bd_addr, our_id_addr, 6) == 0);
}
@@ -902,14 +907,27 @@ ble_sm_test_util_verify_tx_lt_key_req_neg_reply(uint16_t conn_handle)
}
static void
-ble_sm_test_util_set_lt_key_req_reply_ack(uint8_t status,
- uint16_t conn_handle)
+ble_sm_test_util_set_lt_key_req_neg_reply_ack(uint8_t status,
+ uint16_t conn_handle)
+{
+ static uint8_t params[BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN];
+
+ htole16(params, conn_handle);
+ ble_hs_test_util_set_ack_params(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY),
+ status, params, sizeof params);
+}
+
+static void
+ble_sm_test_util_set_lt_key_req_reply_ack(uint8_t status, uint16_t conn_handle)
{
static uint8_t params[BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN];
htole16(params, conn_handle);
ble_hs_test_util_set_ack_params(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
status, params, sizeof params);
}
@@ -975,15 +993,20 @@ ble_sm_test_util_io_inject(struct ble_sm_test_passkey_info *passkey_info,
io_sm_state = ble_sm_ioact_state(passkey_info->passkey.action);
if (io_sm_state != cur_sm_state) {
+ TEST_ASSERT(ble_sm_test_ioact.action == BLE_SM_IOACT_NONE);
return;
}
+ TEST_ASSERT(ble_sm_test_ioact.action == passkey_info->passkey.action);
+
if (passkey_info->passkey.action == BLE_SM_IOACT_NUMCMP) {
TEST_ASSERT(ble_sm_test_ioact.numcmp == passkey_info->exp_numcmp);
}
rc = ble_sm_inject_io(2, &passkey_info->passkey);
TEST_ASSERT(rc == 0);
+
+ ble_sm_test_ioact.action = BLE_SM_IOACT_NONE;
}
void
@@ -1193,6 +1216,7 @@ ble_sm_test_util_verify_persist(struct ble_sm_test_params *params,
static void
ble_sm_test_util_peer_bonding_good(int send_enc_req,
+ uint8_t our_addr_type,
uint8_t *our_rpa,
uint8_t peer_addr_type,
uint8_t *peer_id_addr,
@@ -1203,8 +1227,9 @@ ble_sm_test_util_peer_bonding_good(int send_enc_req,
struct ble_hs_conn *conn;
int rc;
- ble_hs_test_util_create_rpa_conn(2, our_rpa, peer_addr_type, peer_id_addr,
- peer_rpa, ble_sm_test_util_conn_cb, NULL);
+ ble_hs_test_util_create_rpa_conn(2, our_addr_type, our_rpa, peer_addr_type,
+ peer_id_addr, peer_rpa,
+ ble_sm_test_util_conn_cb, NULL);
/* This test inspects and modifies the connection object after unlocking
* the host mutex. It is not OK for real code to do this, but this test
@@ -1255,7 +1280,7 @@ ble_sm_test_util_peer_bonding_good(int send_enc_req,
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
@@ -1294,7 +1319,7 @@ ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Receive a long term key request from the controller. */
- ble_sm_test_util_set_lt_key_req_reply_ack(0, 2);
+ ble_sm_test_util_set_lt_key_req_neg_reply_ack(0, 2);
ble_sm_test_util_rx_lt_key_req(2, rand_num, ediv);
TEST_ASSERT(!conn->bhc_sec_state.encrypted);
@@ -1323,7 +1348,8 @@ ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num)
* 0: No security request; we initiate.
*/
static void
-ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *our_rpa,
+ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t our_addr_type,
+ uint8_t *our_rpa,
uint8_t peer_addr_type,
uint8_t *peer_id_addr, uint8_t *peer_rpa,
uint8_t *ltk, int authenticated,
@@ -1332,7 +1358,8 @@ ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *our_rpa,
struct ble_sm_sec_req sec_req;
struct ble_hs_conn *conn;
- ble_hs_test_util_create_rpa_conn(2, our_rpa, peer_addr_type, peer_id_addr,
+ ble_hs_test_util_create_rpa_conn(2, our_addr_type, our_rpa,
+ peer_addr_type, peer_id_addr,
peer_rpa, ble_sm_test_util_conn_cb, NULL);
/* This test inspects and modifies the connection object after unlocking
@@ -1348,7 +1375,8 @@ ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *our_rpa,
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT),
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_START_ENCRYPT),
0);
if (send_enc_req) {
@@ -1376,7 +1404,7 @@ ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *our_rpa,
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
@@ -1401,7 +1429,7 @@ ble_sm_test_util_peer_fail_inval(
struct ble_hs_conn *conn;
ble_sm_test_util_init();
- ble_hs_test_util_set_public_addr(resp_addr);
+ ble_hs_id_set_pub(resp_addr);
ble_hs_test_util_create_conn(2, init_id_addr, ble_sm_test_util_conn_cb,
NULL);
@@ -1435,7 +1463,7 @@ ble_sm_test_util_peer_fail_inval(
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was not executed. */
- TEST_ASSERT(ble_sm_test_gap_event == -1);
+ TEST_ASSERT(ble_sm_test_gap_event_type == -1);
TEST_ASSERT(ble_sm_test_gap_status == -1);
/* Verify that connection has correct security state. */
@@ -1458,7 +1486,7 @@ ble_sm_test_util_peer_lgcy_fail_confirm(
struct ble_hs_conn *conn;
ble_sm_test_util_init();
- ble_hs_test_util_set_public_addr(resp_addr);
+ ble_hs_id_set_pub(resp_addr);
ble_sm_dbg_set_next_pair_rand(random_rsp->value);
ble_hs_test_util_create_conn(2, init_id_addr, ble_sm_test_util_conn_cb,
@@ -1512,7 +1540,7 @@ ble_sm_test_util_peer_lgcy_fail_confirm(
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status ==
BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH));
TEST_ASSERT(!ble_sm_test_sec_state.encrypted);
@@ -1548,7 +1576,8 @@ ble_sm_test_util_bonding_all(struct ble_sm_test_params *params,
if (sc || peer_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
/* We are master; we initiate procedure. */
- ble_sm_test_util_us_bonding_good(0, our_entity.rpa,
+ ble_sm_test_util_us_bonding_good(0, our_entity.addr_type,
+ our_entity.rpa,
peer_entity.addr_type,
peer_entity.id_addr,
peer_entity.rpa,
@@ -1558,7 +1587,8 @@ ble_sm_test_util_bonding_all(struct ble_sm_test_params *params,
peer_entity.rand_num);
/* We are master; peer initiates procedure via security request. */
- ble_sm_test_util_us_bonding_good(1, our_entity.rpa,
+ ble_sm_test_util_us_bonding_good(1, our_entity.addr_type,
+ our_entity.rpa,
peer_entity.addr_type,
peer_entity.id_addr,
peer_entity.rpa,
@@ -1570,7 +1600,8 @@ ble_sm_test_util_bonding_all(struct ble_sm_test_params *params,
if (sc || our_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
/* Peer is master; peer initiates procedure. */
- ble_sm_test_util_peer_bonding_good(0, our_entity.rpa,
+ ble_sm_test_util_peer_bonding_good(0, our_entity.addr_type,
+ our_entity.rpa,
peer_entity.addr_type,
peer_entity.id_addr,
peer_entity.rpa,
@@ -1580,7 +1611,8 @@ ble_sm_test_util_bonding_all(struct ble_sm_test_params *params,
our_entity.rand_num);
/* Peer is master; we initiate procedure via security request. */
- ble_sm_test_util_peer_bonding_good(1, our_entity.rpa,
+ ble_sm_test_util_peer_bonding_good(1, our_entity.addr_type,
+ our_entity.rpa,
peer_entity.addr_type,
peer_entity.id_addr,
peer_entity.rpa,
@@ -1629,8 +1661,8 @@ ble_sm_test_util_rx_keys(struct ble_sm_test_params *params,
}
if (peer_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_ADD_RESOLV_LIST), 0);
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_ADD_RESOLV_LIST), 0);
ble_sm_test_util_rx_id_info(2, peer_id_info, 0);
ble_sm_test_util_rx_id_addr_info(2, peer_id_addr_info, 0);
}
@@ -1697,7 +1729,8 @@ ble_sm_test_util_us_lgcy_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT), 0);
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_START_ENCRYPT), 0);
if (params->sec_req.authreq != 0) {
ble_sm_test_util_rx_sec_req(2, &params->sec_req, 0);
} else {
@@ -1768,7 +1801,7 @@ ble_sm_test_util_us_lgcy_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated == params->authenticated);
@@ -1894,7 +1927,7 @@ ble_sm_test_util_peer_lgcy_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
@@ -1957,7 +1990,8 @@ ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
ble_hs_test_util_set_ack(
- host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT), 0);
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_START_ENCRYPT), 0);
if (params->sec_req.authreq != 0) {
ble_sm_test_util_rx_sec_req(2, &params->sec_req, 0);
} else {
@@ -2079,7 +2113,7 @@ ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
@@ -2267,7 +2301,7 @@ ble_sm_test_util_peer_sc_good_once(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was executed. */
- TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+ TEST_ASSERT(ble_sm_test_gap_event_type == BLE_GAP_EVENT_ENC_CHANGE);
TEST_ASSERT(ble_sm_test_gap_status == 0);
TEST_ASSERT(ble_sm_test_sec_state.encrypted);
TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
@@ -2321,7 +2355,7 @@ ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params)
int rc;
ble_sm_test_util_init();
- ble_hs_test_util_set_public_addr(params->resp_id_addr);
+ ble_hs_id_set_pub(params->resp_id_addr);
ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
@@ -2365,7 +2399,7 @@ ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params)
TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
/* Verify that security callback was not executed. */
- TEST_ASSERT(ble_sm_test_gap_event == -1);
+ TEST_ASSERT(ble_sm_test_gap_event_type == -1);
TEST_ASSERT(ble_sm_test_gap_status == -1);
/* Verify that connection has correct security state. */
diff --git a/net/nimble/host/src/test/ble_sm_test_util.h b/net/nimble/host/src/test/ble_sm_test_util.h
index 3b0688b3..3323be69 100644
--- a/net/nimble/host/src/test/ble_sm_test_util.h
+++ b/net/nimble/host/src/test/ble_sm_test_util.h
@@ -78,8 +78,7 @@ extern union ble_store_key ble_sm_test_store_key;
extern union ble_store_value ble_sm_test_store_value;
void ble_sm_test_util_init(void);
-int ble_sm_test_util_conn_cb(int event, struct ble_gap_conn_ctxt *ctxt,
- void *arg);
+int ble_sm_test_util_conn_cb(struct ble_gap_event *ctxt, void *arg);
void ble_sm_test_util_io_inject(struct ble_sm_test_passkey_info *passkey_info,
uint8_t cur_sm_state);
void ble_sm_test_util_io_inject_bad(uint16_t conn_handle,
diff --git a/net/nimble/host/src/test/ble_uuid_test.c b/net/nimble/host/src/test/ble_uuid_test.c
index ecb3505f..10113034 100644
--- a/net/nimble/host/src/test/ble_uuid_test.c
+++ b/net/nimble/host/src/test/ble_uuid_test.c
@@ -19,9 +19,10 @@
#include <stddef.h>
#include <string.h>
-#include "host/ble_hs_test.h"
#include "testutil/testutil.h"
+#include "host/ble_hs_test.h"
#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
TEST_CASE(ble_uuid_test_128_to_16)
{
@@ -78,6 +79,8 @@ TEST_CASE(ble_uuid_test_128_to_16)
TEST_SUITE(ble_uuid_test_suite)
{
+ tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
ble_uuid_test_128_to_16();
}