summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/host/test
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
committerJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
commitbdc10744fb338ae197692713a0b48a7ccc36f566 (patch)
treeaf7a8f2f16ddd2e5483758effec15c7683f6c453 /src/libs/mynewt-nimble/nimble/host/test
parent032fad094c6411ad3ff4321ad61ceed95d7dc4ff (diff)
Add Nimble in libs directory
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/host/test')
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/pkg.yml34
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_att_clt_test.c548
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_att_svr_test.c2138
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c3168
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_conn_test.c746
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_c_test.c722
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_d_test.c446
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_s_test.c631
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_find_s_test.c433
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_read_test.c923
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_write_test.c832
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_notify_test.c1090
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_read_test.c257
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_reg_test.c719
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_adv_test.c1280
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_conn_test.c224
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_hci_test.c342
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_id_test.c124
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_pvcy_test.c509
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_stop_test.c203
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.c83
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.h62
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.c2048
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.h305
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.c616
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.h105
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_l2cap_test.c1500
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_os_test.c388
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_lgcy_test.c849
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_sc_test.c4938
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test.c414
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.c2967
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.h128
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_store_test.c435
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_uuid_test.c76
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/syscfg.yml31
36 files changed, 30314 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/nimble/host/test/pkg.yml b/src/libs/mynewt-nimble/nimble/host/test/pkg.yml
new file mode 100644
index 00000000..dd1ad18b
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/pkg.yml
@@ -0,0 +1,34 @@
+# 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.
+#
+pkg.name: nimble/host/test
+pkg.type: unittest
+pkg.description: "NimBLE host unit tests."
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/test/testutil"
+ - nimble/host
+ - nimble/host/store/config
+
+pkg.deps.SELFTEST:
+ - "@apache-mynewt-core/sys/console/stub"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/stats/stub"
+ - nimble/transport/ram
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_clt_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_clt_test.c
new file mode 100644
index 00000000..787d4bca
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_clt_test.c
@@ -0,0 +1,548 @@
+/*
+ * 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 "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+/**
+ * @return The handle of the new test connection.
+ */
+static uint16_t
+ble_att_clt_test_misc_init(void)
+{
+ ble_hs_test_util_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL,
+ NULL);
+ return 2;
+}
+
+static void
+ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value,
+ int value_len, int is_req)
+{
+ struct ble_att_write_req req;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ if (is_req) {
+ ble_att_write_req_parse(om->om_data, om->om_len, &req);
+ } else {
+ ble_att_write_cmd_parse(om->om_data, om->om_len, &req);
+ }
+
+ TEST_ASSERT(req.bawq_handle == handle_id);
+ TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len);
+ TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value,
+ value_len) == 0);
+}
+
+static void
+ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle, uint16_t handle,
+ 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, handle, om);
+ } else {
+ rc = ble_att_clt_tx_write_cmd(conn_handle, handle, om);
+ }
+ TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_find_info)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ rc = ble_att_clt_tx_find_info(conn_handle, 1, 0xffff);
+ TEST_ASSERT(rc == 0);
+
+ /*** Error: start handle of 0. */
+ rc = ble_att_clt_tx_find_info(conn_handle, 0, 0xffff);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ /*** Error: start handle greater than end handle. */
+ rc = ble_att_clt_tx_find_info(conn_handle, 500, 499);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ /*** Success; start and end handles equal. */
+ rc = ble_att_clt_tx_find_info(conn_handle, 500, 500);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_rx_find_info)
+{
+ struct ble_att_find_info_rsp rsp;
+ uint16_t conn_handle;
+ uint8_t buf[1024];
+ uint8_t uuid128_1[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
+ int off;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** One 128-bit UUID. */
+ /* Receive response with attribute mapping. */
+ off = 0;
+ rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT;
+ ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+ off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+ put_le16(buf + off, 1);
+ off += 2;
+ memcpy(buf + off, uuid128_1, 16);
+ off += 16;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ /*** One 16-bit UUID. */
+ /* Receive response with attribute mapping. */
+ off = 0;
+ rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+ ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+ off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+ put_le16(buf + off, 2);
+ off += 2;
+ put_le16(buf + off, 0x000f);
+ off += 2;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ /*** Two 16-bit UUIDs. */
+ /* Receive response with attribute mappings. */
+ off = 0;
+ rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+ ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+ off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+ put_le16(buf + off, 3);
+ off += 2;
+ put_le16(buf + off, 0x0010);
+ off += 2;
+
+ put_le16(buf + off, 4);
+ off += 2;
+ put_le16(buf + off, 0x0011);
+ off += 2;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+ble_att_clt_test_case_tx_write_req_or_cmd(int is_req)
+{
+ uint16_t conn_handle;
+ uint8_t value300[500] = { 0 };
+ uint8_t value5[5] = { 6, 7, 54, 34, 8 };
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** 5-byte write. */
+ ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0x1234, value5,
+ sizeof value5, is_req);
+ ble_att_clt_test_misc_verify_tx_write(0x1234, value5, sizeof value5,
+ is_req);
+
+ /*** Overlong write; verify command truncated to ATT MTU. */
+ ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0xab83, value300,
+ sizeof value300, is_req);
+ ble_att_clt_test_misc_verify_tx_write(0xab83, value300,
+ BLE_ATT_MTU_DFLT - 3, is_req);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
+ uint8_t *attr_data, uint16_t attr_data_len)
+{
+ struct ble_att_prep_write_cmd req;
+ struct os_mbuf *om;
+ uint16_t conn_handle;
+ int rc;
+ int i;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+ rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om);
+ TEST_ASSERT(rc == 0);
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
+
+ ble_att_prep_write_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.bapc_handle == handle);
+ TEST_ASSERT(req.bapc_offset == offset);
+ for (i = 0; i < attr_data_len; i++) {
+ TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] ==
+ attr_data[i]);
+ }
+}
+
+static void
+ble_att_clt_test_misc_exec_good(uint8_t flags)
+{
+ struct ble_att_exec_write_req req;
+ struct os_mbuf *om;
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ rc = ble_att_clt_tx_exec_write(conn_handle, flags);
+ TEST_ASSERT(rc == 0);
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ);
+
+ ble_att_exec_write_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.baeq_flags == flags);
+}
+
+static void
+ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
+ uint8_t *attr_data, uint16_t attr_data_len,
+ int status)
+{
+ 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);
+
+ rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om);
+ TEST_ASSERT(rc == status);
+}
+
+static void
+ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle, uint16_t mtu, int status)
+{
+ int rc;
+
+ rc = ble_att_clt_tx_mtu(conn_handle, mtu);
+ TEST_ASSERT(rc == status);
+
+ if (rc == 0) {
+ ble_hs_test_util_verify_tx_mtu_cmd(1, mtu);
+ }
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_write)
+{
+ ble_att_clt_test_case_tx_write_req_or_cmd(0);
+ ble_att_clt_test_case_tx_write_req_or_cmd(1);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_read)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ rc = ble_att_clt_tx_read(conn_handle, 1);
+ TEST_ASSERT(rc == 0);
+
+ /*** Error: handle of 0. */
+ rc = ble_att_clt_tx_read(conn_handle, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_rx_read)
+{
+ uint16_t conn_handle;
+ uint8_t buf[1024];
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Basic success. */
+ buf[0] = BLE_ATT_OP_READ_RSP;
+ buf[1] = 0;
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 2);
+ TEST_ASSERT(rc == 0);
+
+ /*** Larger response. */
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 20);
+ TEST_ASSERT(rc == 0);
+
+ /*** Zero-length response. */
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 1);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_read_blob)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ rc = ble_att_clt_tx_read_blob(conn_handle, 1, 0);
+ TEST_ASSERT(rc == 0);
+
+ /*** Error: handle of 0. */
+ rc = ble_att_clt_tx_read_blob(conn_handle, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_rx_read_blob)
+{
+ uint16_t conn_handle;
+ uint8_t buf[1024];
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Basic success. */
+ buf[0] = BLE_ATT_OP_READ_BLOB_RSP;
+ buf[1] = 0;
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 2);
+ TEST_ASSERT(rc == 0);
+
+ /*** Larger response. */
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 20);
+ TEST_ASSERT(rc == 0);
+
+ /*** Zero-length response. */
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 1);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_read_mult)
+{
+ struct os_mbuf *om;
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2);
+ TEST_ASSERT(rc == 0);
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(om->om_len == BLE_ATT_READ_MULT_REQ_BASE_SZ + 4);
+
+ ble_att_read_mult_req_parse(om->om_data, om->om_len);
+ TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ) == 1);
+ TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2);
+
+ /*** Error: no handles. */
+ rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_rx_read_mult)
+{
+ uint16_t conn_handle;
+ uint8_t buf[1024];
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Basic success. */
+ ble_att_read_mult_rsp_write(buf, sizeof buf);
+ put_le16(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);
+ TEST_ASSERT(rc == 0);
+
+ /*** Larger response. */
+ put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
+ put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2, 43);
+ put_le16(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);
+ 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);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_prep_write)
+{
+ uint8_t attr_data[512];
+ int i;
+
+ for (i = 0; i < sizeof attr_data; i++) {
+ attr_data[i] = i;
+ }
+
+ /*** Success. */
+ ble_att_clt_test_misc_prep_good(123, 0, attr_data, 16);
+ ble_att_clt_test_misc_prep_good(5432, 100, attr_data, 2);
+ ble_att_clt_test_misc_prep_good(0x1234, 400, attr_data, 0);
+ ble_att_clt_test_misc_prep_good(5432, 0, attr_data,
+ BLE_ATT_MTU_DFLT -
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ ble_att_clt_test_misc_prep_good(0x1234, 507, attr_data, 5);
+
+ /*** Error: handle of 0. */
+ ble_att_clt_test_misc_prep_bad(0, 0, attr_data, 16, BLE_HS_EINVAL);
+
+ /*** Error: offset + length greater than maximum attribute size. */
+ ble_att_clt_test_misc_prep_bad(1, 507, attr_data, 6, BLE_HS_EINVAL);
+
+ /*** Error: packet larger than MTU. */
+ ble_att_clt_test_misc_prep_bad(1, 0, attr_data,
+ BLE_ATT_MTU_DFLT -
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+ BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_rx_prep_write)
+{
+ struct ble_att_prep_write_cmd rsp;
+ uint16_t conn_handle;
+ uint8_t buf[1024];
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Basic success. */
+ rsp.bapc_handle = 0x1234;
+ rsp.bapc_offset = 0;
+ ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
+ memset(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, 1, 5);
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 5);
+ TEST_ASSERT(rc == 0);
+
+ /*** 0-length write. */
+ rsp.bapc_handle = 0x1234;
+ rsp.bapc_offset = 0;
+ ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_att_clt_test_tx_exec_write)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_clt_test_misc_init();
+
+ /*** Success. */
+ ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CANCEL);
+ ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_EXECUTE);
+
+ /*** Success: nonzero == execute. */
+ rc = ble_att_clt_tx_exec_write(conn_handle, 0x02);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_att_clt_suite)
+{
+ ble_att_clt_test_tx_find_info();
+ ble_att_clt_test_rx_find_info();
+ ble_att_clt_test_tx_read();
+ ble_att_clt_test_rx_read();
+ ble_att_clt_test_tx_read_blob();
+ ble_att_clt_test_rx_read_blob();
+ ble_att_clt_test_tx_read_mult();
+ ble_att_clt_test_rx_read_mult();
+ ble_att_clt_test_tx_write();
+ 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();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_svr_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_svr_test.c
new file mode 100644
index 00000000..60ab14b4
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_att_svr_test.c
@@ -0,0 +1,2138 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "ble_hs_test.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+static uint8_t *ble_att_svr_test_attr_r_1;
+static uint16_t ble_att_svr_test_attr_r_1_len;
+static uint8_t *ble_att_svr_test_attr_r_2;
+static uint16_t ble_att_svr_test_attr_r_2_len;
+
+static uint8_t ble_att_svr_test_attr_w_1[1024];
+static uint16_t ble_att_svr_test_attr_w_1_len;
+static uint8_t ble_att_svr_test_attr_w_2[1024];
+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 uint16_t ble_att_svr_test_attr_n_len;
+
+static void
+ble_att_svr_test_assert_mbufs_freed(void)
+{
+ /* When checking for mbuf leaks, ensure no stale prep entries. */
+ static const struct ble_hs_test_util_mbuf_params mbuf_params = {
+ .prev_tx = 1,
+ .rx_queue = 1,
+ .prep_list = 0,
+ };
+
+ ble_hs_test_util_assert_mbufs_freed(&mbuf_params);
+}
+
+static int
+ble_att_svr_test_misc_gap_cb(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+
+ 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 = OS_MBUF_PKTLEN(event->notify_rx.om);
+ rc = os_mbuf_copydata(event->notify_rx.om, 0,
+ ble_att_svr_test_attr_n_len,
+ ble_att_svr_test_attr_n);
+ TEST_ASSERT_FATAL(rc == 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * @return The handle of the new test connection.
+ */
+static uint16_t
+ble_att_svr_test_misc_init(uint16_t mtu)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ ble_att_svr_test_misc_gap_cb, NULL);
+
+ ble_hs_lock();
+
+ rc = ble_hs_misc_conn_chan_find(2, BLE_L2CAP_CID_ATT, &conn, &chan);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ if (mtu != 0) {
+ chan->my_mtu = mtu;
+ chan->peer_mtu = mtu;
+ chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
+ }
+
+ ble_hs_unlock();
+
+ ble_att_svr_test_attr_r_1_len = 0;
+ ble_att_svr_test_attr_r_2_len = 0;
+ ble_att_svr_test_attr_w_1_len = 0;
+
+ return 2;
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_READ:
+ if (offset > ble_att_svr_test_attr_r_1_len) {
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+
+ rc = os_mbuf_append(*om, ble_att_svr_test_attr_r_1 + offset,
+ ble_att_svr_test_attr_r_1_len - offset);
+ TEST_ASSERT_FATAL(rc == 0);
+ return 0;
+
+ default:
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_READ:
+ if (offset > ble_att_svr_test_attr_r_2_len) {
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+
+ rc = os_mbuf_append(*om, ble_att_svr_test_attr_r_2 + offset,
+ ble_att_svr_test_attr_r_2_len - offset);
+ TEST_ASSERT_FATAL(rc == 0);
+ return 0;
+
+ default:
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_r_err(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ rc = os_mbuf_append(*om, (uint8_t[4]){1,2,3,4}, 4);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ return BLE_ATT_ERR_UNLIKELY;
+}
+
+#define BLE_ATT_SVR_TEST_LAST_SVC 11
+#define BLE_ATT_SVR_TEST_LAST_ATTR 24
+
+static int
+ble_att_svr_test_misc_attr_fn_r_group(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint8_t op,
+ 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 */
+
+ static uint8_t vals[25][16] = {
+ [1] = { 0x22, 0x11 },
+ [2] = { 0x01, 0x11 },
+ [3] = { 0x02, 0x11 },
+ [4] = { 0x03, 0x11 },
+ [5] = { 0x04, 0x11 },
+ [6] = { 0x33, 0x22 },
+ [7] = { 0x01, 0x22 },
+ [8] = { 0x02, 0x22 },
+ [9] = { 0x03, 0x22 },
+ [10] = { 0x04, 0x22 },
+ [11] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
+ [12] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
+ [13] = { 0xdd, 0xdd },
+ [14] = { 0x55, 0x55 },
+ [15] = { 0xdd, 0xdd },
+ [16] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
+ [17] = { 0xdd, 0xdd },
+ [18] = { 0x66, 0x66 },
+ [19] = { 0xdd, 0xdd },
+ [20] = { 0x77, 0x77 },
+ [21] = { 0xdd, 0xdd },
+ [22] = { 0x88, 0x88 },
+ [23] = { 0xdd, 0xdd },
+ [24] = { 0x99, 0x99 },
+ };
+
+ static uint8_t zeros[14];
+
+ if (op != BLE_ATT_ACCESS_OP_READ) {
+ return -1;
+ }
+
+ TEST_ASSERT_FATAL(attr_handle >= 1 &&
+ attr_handle <= BLE_ATT_SVR_TEST_LAST_ATTR);
+
+ src = &vals[attr_handle][0];
+ if (memcmp(src + 2, zeros, 14) == 0) {
+ rc = os_mbuf_append(*om, src, 2);
+ } else {
+ rc = os_mbuf_append(*om, src, 16);
+ }
+ if (rc != 0) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+
+ return 0;
+}
+
+static void
+ble_att_svr_test_misc_register_uuid(const ble_uuid_t *uuid, uint8_t flags,
+ uint16_t expected_handle,
+ ble_att_svr_access_fn *fn)
+{
+ uint16_t handle;
+ int rc;
+
+ rc = ble_att_svr_register(uuid, flags, 0, &handle, fn, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(handle == expected_handle);
+}
+
+static void
+ble_att_svr_test_misc_register_group_attrs(void)
+{
+ /* Service 0x1122 from 1 to 5 */
+ /* Service 0x2233 from 6 to 10 */
+ /* Service 010203...0f from 11 to 24 */
+
+ static const ble_uuid16_t uuid_svc =
+ BLE_UUID16_INIT(BLE_ATT_UUID_PRIMARY_SERVICE);
+ static const ble_uuid16_t uuid_inc =
+ BLE_UUID16_INIT(BLE_ATT_UUID_INCLUDE);
+ static const ble_uuid16_t uuid_chr =
+ BLE_UUID16_INIT(BLE_ATT_UUID_CHARACTERISTIC);
+ static ble_uuid16_t uuids[24];
+
+ int i;
+
+ /* Service 0x1122 from 1 to 5 */
+ ble_att_svr_test_misc_register_uuid(&uuid_svc.u, HA_FLAG_PERM_RW, 1,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ for (i = 2; i <= 5; i++) {
+ if ((i - 2) % 2 == 0) {
+ ble_att_svr_test_misc_register_uuid(&uuid_chr.u, HA_FLAG_PERM_RW, i,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ } else {
+ uuids[i] = *BLE_UUID16(BLE_UUID16_DECLARE(i));
+ ble_att_svr_test_misc_register_uuid(&uuids[i].u, HA_FLAG_PERM_RW, i,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ }
+ }
+
+ /* Service 0x2233 from 6 to 10 */
+ ble_att_svr_test_misc_register_uuid(&uuid_svc.u, HA_FLAG_PERM_RW, 6,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ for (i = 7; i <= 10; i++) {
+ ble_att_svr_test_misc_register_uuid(&uuid_inc.u, HA_FLAG_PERM_RW, i,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ }
+
+ /* Service 010203...0f from 11 to 24 */
+ ble_att_svr_test_misc_register_uuid(&uuid_svc.u, HA_FLAG_PERM_RW, 11,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ for (i = 12; i <= 24; i++) {
+ if ((i - 12) % 2 == 0) {
+ ble_att_svr_test_misc_register_uuid(&uuid_chr.u, HA_FLAG_PERM_RW, i,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ } else {
+ uuids[i] = *BLE_UUID16(BLE_UUID16_DECLARE(i));
+ ble_att_svr_test_misc_register_uuid(&uuids[i].u, HA_FLAG_PERM_RW, i,
+ ble_att_svr_test_misc_attr_fn_r_group);
+ }
+ }
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_rw_1(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_READ:
+ if (offset > ble_att_svr_test_attr_w_1_len) {
+ return BLE_ATT_ERR_INVALID_OFFSET;
+ }
+
+ rc = os_mbuf_append(*om, ble_att_svr_test_attr_w_1 + offset,
+ ble_att_svr_test_attr_w_1_len - offset);
+ TEST_ASSERT_FATAL(rc == 0);
+ return 0;
+
+ case BLE_ATT_ACCESS_OP_WRITE:
+ rc = os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+ ble_att_svr_test_attr_w_1);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_att_svr_test_attr_w_1_len = OS_MBUF_PKTLEN(*om);
+ return 0;
+
+ default:
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_WRITE:
+ rc = os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+ ble_att_svr_test_attr_w_1);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_att_svr_test_attr_w_1_len = OS_MBUF_PKTLEN(*om);
+ return 0;
+
+ default:
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+static int
+ble_att_svr_test_misc_attr_fn_w_2(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset,
+ struct os_mbuf **om, void *arg)
+{
+ int rc;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_WRITE:
+ rc = os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+ ble_att_svr_test_attr_w_2);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_att_svr_test_attr_w_2_len = OS_MBUF_PKTLEN(*om);
+ return 0;
+
+ default:
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+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)
+{
+ TEST_ASSERT(ble_att_svr_test_attr_w_1_len == data_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_w_1, data, data_len) == 0);
+}
+
+static void
+ble_att_svr_test_misc_verify_w_2(void *data, int data_len)
+{
+ TEST_ASSERT(ble_att_svr_test_attr_w_2_len == data_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_w_2, data, data_len) == 0);
+}
+
+static void
+ble_att_svr_test_misc_rx_read_mult_req(uint16_t conn_handle,
+ uint16_t *handles, int num_handles,
+ int success)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_read_mult_req(conn_handle, handles,
+ num_handles);
+ if (success) {
+ TEST_ASSERT(rc == 0);
+ } else {
+ TEST_ASSERT(rc != 0);
+ }
+}
+
+static void
+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 u8;
+ int rc;
+ int off;
+ int i;
+
+ 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_MULT_RSP);
+
+ ble_hs_lock();
+
+ rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
+ NULL, &chan);
+ TEST_ASSERT_FATAL(rc == 0);
+ mtu = ble_att_chan_mtu(chan);
+
+ ble_hs_unlock();
+
+ off = 1;
+ for (i = 0; i < num_attrs; i++) {
+ attr_len = min(attrs[i].value_len, mtu - off);
+
+ rc = os_mbuf_cmpf(om, off, attrs[i].value, attr_len);
+ TEST_ASSERT(rc == 0);
+
+ off += attr_len;
+ }
+
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == off);
+}
+
+static void
+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;
+
+ TEST_ASSERT_FATAL(num_attrs <= sizeof handles / sizeof handles[0]);
+
+ for (i = 0; i < num_attrs; i++) {
+ handles[i] = attrs[i].handle;
+ }
+
+ ble_att_svr_test_misc_rx_read_mult_req(conn_handle, handles, num_attrs, 1);
+ ble_att_svr_test_misc_verify_tx_read_mult_rsp(conn_handle,
+ attrs, num_attrs);
+}
+
+static void
+ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ uint16_t my_mtu;
+ int rc;
+
+ ble_hs_lock();
+
+ rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
+ assert(rc == 0);
+ my_mtu = chan->my_mtu;
+
+ ble_hs_unlock();
+
+ ble_hs_test_util_verify_tx_mtu_cmd(0, my_mtu);
+}
+
+struct ble_att_svr_test_type_value_entry {
+ uint16_t first; /* 0 on last entry */
+ uint16_t last;
+};
+
+static void
+ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ struct ble_att_svr_test_type_value_entry *entries)
+{
+ struct ble_att_svr_test_type_value_entry *entry;
+ struct os_mbuf *om;
+ uint16_t u16;
+ uint8_t op;
+ int off;
+ int rc;
+
+ off = 0;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+
+ rc = os_mbuf_copydata(om, off, 1, &op);
+ TEST_ASSERT(rc == 0);
+ off += 1;
+
+ TEST_ASSERT(op == BLE_ATT_OP_FIND_TYPE_VALUE_RSP);
+
+ for (entry = entries; entry->first != 0; entry++) {
+ rc = os_mbuf_copydata(om, off, 2, &u16);
+ TEST_ASSERT(rc == 0);
+ put_le16(&u16, u16);
+ TEST_ASSERT(u16 == entry->first);
+ off += 2;
+
+ rc = os_mbuf_copydata(om, off, 2, &u16);
+ TEST_ASSERT(rc == 0);
+ put_le16(&u16, u16);
+ TEST_ASSERT(u16 == entry->last);
+ off += 2;
+ }
+
+ /* Ensure there is no extra data in the response. */
+ TEST_ASSERT(off == OS_MBUF_PKTHDR(om)->omp_len);
+}
+
+/** Returns the number of entries successfully verified. */
+
+struct ble_att_svr_test_type_entry {
+ uint16_t handle; /* 0 on last entry */
+ void *value;
+ int value_len;
+};
+
+/** Returns the number of entries successfully verified. */
+static void
+ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ struct ble_att_svr_test_type_entry *entries)
+{
+ struct ble_att_svr_test_type_entry *entry;
+ struct ble_att_read_type_rsp rsp;
+ struct os_mbuf *om;
+ uint16_t handle;
+ uint8_t buf[512];
+ int off;
+ int rc;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT(om);
+
+ ble_att_read_type_rsp_parse(om->om_data, om->om_len, &rsp);
+
+ off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
+ for (entry = entries; entry->handle != 0; entry++) {
+ TEST_ASSERT_FATAL(rsp.batp_length ==
+ BLE_ATT_READ_TYPE_ADATA_BASE_SZ + entry->value_len);
+
+ rc = os_mbuf_copydata(om, off, 2, &handle);
+ TEST_ASSERT(rc == 0);
+ handle = get_le16(&handle);
+ TEST_ASSERT(handle == entry->handle);
+ off += 2;
+
+ rc = os_mbuf_copydata(om, off, entry->value_len, buf);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(memcmp(entry->value, buf, entry->value_len) == 0);
+ off += entry->value_len;
+ }
+
+ /* Ensure there is no extra data in the response. */
+ TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
+}
+
+static void
+ble_att_svr_test_misc_verify_tx_prep_write_rsp(uint16_t attr_handle,
+ uint16_t offset,
+ void *data, int data_len)
+{
+ struct ble_att_prep_write_cmd rsp;
+ struct os_mbuf *om;
+ uint8_t buf[1024];
+ int rc;
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+
+ rc = os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), buf);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_att_prep_write_rsp_parse(buf, sizeof buf, &rsp);
+
+ TEST_ASSERT(rsp.bapc_handle == attr_handle);
+ TEST_ASSERT(rsp.bapc_offset == offset);
+ TEST_ASSERT(memcmp(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, data,
+ data_len) == 0);
+
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) ==
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + data_len);
+}
+
+static void
+ble_att_svr_test_misc_verify_tx_exec_write_rsp(void)
+{
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT(om);
+
+ ble_att_exec_write_rsp_parse(om->om_data, om->om_len);
+}
+
+static void
+ble_att_svr_test_misc_mtu_exchange(uint16_t my_mtu, uint16_t peer_sent,
+ uint16_t peer_actual, uint16_t chan_mtu)
+{
+ struct ble_att_mtu_cmd req;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+ uint8_t buf[BLE_ATT_MTU_CMD_SZ];
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(my_mtu);
+
+ req.bamc_mtu = peer_sent;
+ ble_att_mtu_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_mtu_rsp(conn_handle);
+
+ ble_hs_lock();
+ rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
+ &conn, &chan);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(chan->peer_mtu == peer_actual);
+ TEST_ASSERT(ble_att_chan_mtu(chan) == chan_mtu);
+ ble_hs_unlock();
+
+}
+
+static void
+ble_att_svr_test_misc_prep_write(uint16_t conn_handle, uint16_t attr_handle,
+ uint16_t offset, void *data,
+ int data_len, uint8_t error_code)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_prep_write_req(conn_handle, attr_handle,
+ offset, data, data_len);
+ if (error_code == 0) {
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_prep_write_rsp(attr_handle, offset,
+ data, data_len);
+ } else {
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_PREP_WRITE_REQ,
+ attr_handle, error_code);
+ }
+}
+
+static void
+ble_att_svr_test_misc_exec_write(uint16_t conn_handle, uint8_t flags,
+ uint8_t error_code, uint16_t error_handle)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_exec_write_req(conn_handle, flags);
+ if (error_code == 0) {
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_exec_write_rsp();
+ } else {
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_EXEC_WRITE_REQ,
+ error_handle, error_code);
+ }
+}
+
+static void
+ble_att_svr_test_misc_rx_notify(uint16_t conn_handle, uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ struct ble_att_notify_req req;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+
+ req.banq_handle = attr_handle;
+ ble_att_notify_req_write(buf, sizeof buf, &req);
+ off = BLE_ATT_NOTIFY_REQ_BASE_SZ;
+
+ memcpy(buf + off, attr_val, attr_len);
+ off += attr_len;
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ if (good) {
+ TEST_ASSERT(rc == 0);
+ } else {
+ TEST_ASSERT(rc == BLE_HS_EBADDATA);
+ }
+}
+
+static void
+ble_att_svr_test_misc_verify_notify(uint16_t conn_handle, uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ ble_att_svr_test_n_conn_handle = 0xffff;
+ ble_att_svr_test_n_attr_handle = 0;
+ ble_att_svr_test_attr_n_len = 0;
+
+ ble_att_svr_test_misc_rx_notify(conn_handle, attr_handle, attr_val,
+ attr_len, good);
+
+ if (good) {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == conn_handle);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == attr_handle);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == attr_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_n, attr_val, attr_len) == 0);
+ } else {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == 0xffff);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == 0);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == 0);
+ }
+}
+
+static void
+ble_att_svr_test_misc_verify_tx_indicate_rsp(void)
+{
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT(om);
+
+ ble_att_indicate_rsp_parse(om->om_data, om->om_len);
+}
+
+static void
+ble_att_svr_test_misc_rx_indicate(uint16_t conn_handle, uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_indicate_req(conn_handle, attr_handle,
+ attr_val, attr_len);
+ if (good) {
+ TEST_ASSERT(rc == 0);
+ } else {
+ TEST_ASSERT(rc == BLE_HS_EBADDATA);
+ }
+}
+
+static void
+ble_att_svr_test_misc_verify_indicate(uint16_t conn_handle,
+ uint16_t attr_handle,
+ void *attr_val, int attr_len, int good)
+{
+ ble_att_svr_test_n_conn_handle = 0xffff;
+ ble_att_svr_test_n_attr_handle = 0;
+ ble_att_svr_test_attr_n_len = 0;
+
+ ble_att_svr_test_misc_rx_indicate(conn_handle, attr_handle, attr_val,
+ attr_len, good);
+
+ if (good) {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == conn_handle);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == attr_handle);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == attr_len);
+ TEST_ASSERT(memcmp(ble_att_svr_test_attr_n, attr_val, attr_len) == 0);
+ ble_att_svr_test_misc_verify_tx_indicate_rsp();
+ } else {
+ TEST_ASSERT(ble_att_svr_test_n_conn_handle == 0xffff);
+ TEST_ASSERT(ble_att_svr_test_n_attr_handle == 0);
+ TEST_ASSERT(ble_att_svr_test_attr_n_len == 0);
+ TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
+ }
+}
+
+TEST_CASE_SELF(ble_att_svr_test_mtu)
+{
+ /*** MTU too low; should pretend peer sent default value instead. */
+ ble_att_svr_test_misc_mtu_exchange(BLE_ATT_MTU_DFLT, 5,
+ BLE_ATT_MTU_DFLT, BLE_ATT_MTU_DFLT);
+
+ /*** MTUs equal. */
+ ble_att_svr_test_misc_mtu_exchange(50, 50, 50, 50);
+
+ /*** Peer's higher than mine. */
+ ble_att_svr_test_misc_mtu_exchange(50, 100, 100, 50);
+
+ /*** Mine higher than peer's. */
+ ble_att_svr_test_misc_mtu_exchange(100, 50, 50, 50);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_read)
+{
+ struct ble_hs_conn *conn;
+ struct os_mbuf *om;
+ uint16_t attr_handle;
+ uint16_t conn_handle;
+ const ble_uuid_t *uuid_sec = BLE_UUID128_DECLARE( \
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const ble_uuid_t *uuid_bad = BLE_UUID128_DECLARE( \
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const ble_uuid_t *uuid = BLE_UUID128_DECLARE( \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, );
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /*** Nonexistent attribute. */
+ attr_handle = 0;
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ, 0,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Application error. */
+ rc = ble_att_svr_register(uuid_bad, HA_FLAG_PERM_RW, 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_r_err, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ TEST_ASSERT(rc == BLE_HS_EAPP);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ, attr_handle,
+ BLE_ATT_ERR_UNLIKELY);
+
+ /*** Successful read. */
+ ble_att_svr_test_attr_r_1 = (uint8_t[]){0,1,2,3,4,5,6,7};
+ ble_att_svr_test_attr_r_1_len = 8;
+ rc = ble_att_svr_register(uuid, HA_FLAG_PERM_RW, 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ TEST_ASSERT(rc == 0);
+ 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. */
+ 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 = 40;
+
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ TEST_ASSERT(rc == 0);
+ 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. */
+ rc = ble_att_svr_register(uuid_sec, BLE_ATT_F_READ | BLE_ATT_F_READ_ENC, 0,
+ &attr_handle,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ 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, attr_handle,
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
+
+ /* Security check bypassed for local reads. */
+ rc = ble_att_svr_read_local(attr_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);
+ rc = os_mbuf_free_chain(om);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure no response got sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Encrypt link; success. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ conn->bhc_sec_state.encrypted = 1;
+ ble_hs_unlock();
+
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, attr_handle);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
+ BLE_ATT_MTU_DFLT - 1);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_read_blob)
+{
+ uint16_t attr_handle;
+ uint16_t conn_handle;
+ const ble_uuid_t *uuid = BLE_UUID128_DECLARE( \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /*** Nonexistent attribute. */
+ rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, 0, 0);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ, 0,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** 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 = 40;
+ rc = ble_att_svr_register(uuid, HA_FLAG_PERM_RW, 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle, 0);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
+ BLE_ATT_MTU_DFLT - 1);
+
+ /*** Read remainder of attribute. */
+ rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle,
+ BLE_ATT_MTU_DFLT - 1);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_blob_rsp(
+ ble_att_svr_test_attr_r_1 + BLE_ATT_MTU_DFLT - 1,
+ 40 - (BLE_ATT_MTU_DFLT - 1));
+
+ /*** Zero-length read. */
+ rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
+ 0);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_read_mult)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ 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_DECLARE(0x1111), HA_FLAG_PERM_RW, 0,
+ &attrs[0].handle,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_att_svr_register(BLE_UUID16_DECLARE(0x2222), HA_FLAG_PERM_RW, 0,
+ &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_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, &attrs[0], 1);
+
+ /*** Two attributes. */
+ 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, attrs, 2);
+
+ /*** Second attribute nonexistent; verify only error txed. */
+ ble_att_svr_test_misc_rx_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. */
+ 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);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_write)
+{
+ struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+ uint16_t attr_handle;
+ const ble_uuid_t *uuid_sec = BLE_UUID128_DECLARE( \
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const ble_uuid_t *uuid_rw = BLE_UUID128_DECLARE( \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const ble_uuid_t *uuid_r = BLE_UUID128_DECLARE( \
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ int rc;
+
+ static const uint8_t attr_val[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /*** Nonexistent attribute. */
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, 0,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc != 0);
+ 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. */
+ /* Non-local write (fail). */
+ rc = ble_att_svr_register(uuid_r, BLE_ATT_F_READ, 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_w_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, attr_handle,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc == BLE_HS_EREJECT);
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
+ attr_handle,
+ BLE_ATT_ERR_WRITE_NOT_PERMITTED);
+
+ /* Local write (success). */
+ rc = ble_hs_test_util_write_local_flat(attr_handle,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure no response got sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /*** Successful write. */
+ rc = ble_att_svr_register(uuid_rw, HA_FLAG_PERM_RW, 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_w_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, attr_handle,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_write_rsp();
+
+ /*** Write requires encryption. */
+ /* Insufficient authentication. */
+ rc = ble_att_svr_register(uuid_sec, BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_ENC,
+ 0, &attr_handle,
+ ble_att_svr_test_misc_attr_fn_w_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, attr_handle,
+ attr_val, sizeof attr_val);
+ 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,
+ attr_handle,
+ BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
+
+ /* Security check bypassed for local writes. */
+ rc = ble_hs_test_util_write_local_flat(attr_handle,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure no response got sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Encrypt link; success. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ conn->bhc_sec_state.encrypted = 1;
+ ble_hs_unlock();
+
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, attr_handle,
+ attr_val, sizeof attr_val);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_write_rsp();
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_find_info)
+{
+ uint16_t conn_handle;
+ uint16_t handle1;
+ uint16_t handle2;
+ uint16_t handle3;
+ const ble_uuid_t *uuid1 =
+ BLE_UUID128_DECLARE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11, 12, 13, 14, 15);
+ const ble_uuid_t *uuid2 =
+ BLE_UUID128_DECLARE(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ const ble_uuid_t *uuid3 = BLE_UUID16_DECLARE(0x000f);
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(128);
+
+ /*** Start handle of 0. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 0, 0);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_INFO_REQ, 0, BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Start handle > end handle. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 101, 100);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_INFO_REQ, 101, BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** No attributes. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Range too late. */
+ rc = ble_att_svr_register(uuid1, HA_FLAG_PERM_RW, 0, &handle1,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300);
+ TEST_ASSERT(rc != 0);
+ 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. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle1);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_find_info_rsp(
+ ((struct ble_hs_test_util_att_info_entry[]) { {
+ .handle = handle1,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Two 128-bit entries. */
+ rc = ble_att_svr_register(uuid2, HA_FLAG_PERM_RW, 0, &handle2,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle2);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_find_info_rsp(
+ ((struct ble_hs_test_util_att_info_entry[]) { {
+ .handle = handle1,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .handle = handle2,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Two 128-bit entries; 16-bit entry doesn't get sent. */
+ rc = ble_att_svr_register(uuid3, HA_FLAG_PERM_RW, 0, &handle3,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle3);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_find_info_rsp(
+ ((struct ble_hs_test_util_att_info_entry[]) { {
+ .handle = handle1,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .handle = handle2,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Remaining 16-bit entry requested. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle3, handle3);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_find_info_rsp(
+ ((struct ble_hs_test_util_att_info_entry[]) { {
+ .handle = handle3,
+ .uuid = BLE_UUID16_DECLARE(0x000f),
+ }, {
+ .handle = 0,
+ } }));
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_find_type_value)
+{
+ uint16_t conn_handle;
+ uint16_t handle1;
+ uint16_t handle2;
+ uint16_t handle3;
+ uint16_t handle4;
+ uint16_t handle5;
+ uint16_t handle_desc;
+ const ble_uuid_t *uuid1 = BLE_UUID16_DECLARE(0x2800);
+ const ble_uuid_t *uuid2 = BLE_UUID16_DECLARE(0x2803);
+ const ble_uuid_t *uuid3 =
+ BLE_UUID128_DECLARE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(128);
+
+ ble_att_svr_test_attr_r_1 = (uint8_t[]){0x99, 0x99};
+ ble_att_svr_test_attr_r_1_len = 2;
+
+ /*** Start handle of 0. */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 0, 0, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 0,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Start handle > end handle. */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 101, 100, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 101,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** No attributes. */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 200, 300, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 200,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Range too late. */
+ rc = ble_att_svr_register(uuid1, HA_FLAG_PERM_RW, 0, &handle1,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 200, 300, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 200,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** One entry, one attribute. */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, handle1, handle1, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ ((struct ble_att_svr_test_type_value_entry[]) { {
+ .first = handle1,
+ .last = handle1,
+ }, {
+ .first = 0,
+ } }));
+
+ /*** One entry, two attributes. */
+ rc = ble_att_svr_register(uuid2, HA_FLAG_PERM_RW, 0, &handle2,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, handle1, handle2, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ ((struct ble_att_svr_test_type_value_entry[]) { {
+ .first = handle1,
+ .last = handle2,
+ }, {
+ .first = 0,
+ } }));
+
+ /*** Entry 1: four attributes; entry 2 (invalid value): one attribute;
+ * entry 3: one attribute; Check that invalid value is not returned. */
+ ble_att_svr_test_attr_r_2 = (uint8_t[]){0x00, 0x00};
+ ble_att_svr_test_attr_r_2_len = 2;
+
+ rc = ble_att_svr_register(uuid3, HA_FLAG_PERM_RW, 0, &handle_desc,
+ ble_att_svr_test_misc_attr_fn_r_2, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_att_svr_register(uuid2, HA_FLAG_PERM_RW, 0, &handle3,
+ ble_att_svr_test_misc_attr_fn_r_2, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_att_svr_register(uuid1, HA_FLAG_PERM_RW, 0, &handle4,
+ ble_att_svr_test_misc_attr_fn_r_2, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_att_svr_register(uuid1, HA_FLAG_PERM_RW, 0, &handle5,
+ ble_att_svr_test_misc_attr_fn_r_1, NULL);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 0x0001, 0xffff, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ ((struct ble_att_svr_test_type_value_entry[]) { {
+ .first = handle1,
+ .last = handle3,
+ }, {
+ .first = handle5,
+ .last = handle5,
+ }, {
+ .first = 0,
+ } }));
+
+ /*** As above, check proper range is returned with smaller search range */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 0x0001, 0x0001, 0x2800, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ ((struct ble_att_svr_test_type_value_entry[]) { {
+ .first = handle1,
+ .last = handle3,
+ }, {
+ .first = 0,
+ } }));
+
+ /*** As above, check grouping by Characteristic UUID */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, handle1, handle3, 0x2803, ble_att_svr_test_attr_r_1,
+ ble_att_svr_test_attr_r_1_len);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
+ ((struct ble_att_svr_test_type_value_entry[]) { {
+ .first = handle2,
+ .last = handle_desc,
+ }, {
+ .first = 0,
+ } }));
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+static void
+ble_att_svr_test_misc_read_type(uint16_t mtu)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(mtu);
+
+ /*** Start handle of 0. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 0, 0,
+ BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_TYPE_REQ, 0,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Start handle > end handle. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 101, 100,
+ BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_TYPE_REQ, 101,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** No attributes. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff,
+ BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_TYPE_REQ, 1,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Range too late. */
+ ble_att_svr_test_misc_register_group_attrs();
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 200, 300,
+ BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_TYPE_REQ, 200,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** One characteristic from one service. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 2,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 2,
+ .value = (uint8_t[]){ 0x01, 0x11 },
+ .value_len = 2,
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Both characteristics from one service. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 10,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 2,
+ .value = (uint8_t[]){ 0x01, 0x11 },
+ .value_len = 2,
+ }, {
+ .handle = 4,
+ .value = (uint8_t[]){ 0x03, 0x11 },
+ .value_len = 2,
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Ensure 16-bit and 128-bit values are retrieved separately. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 11, 0xffff,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 12,
+ .value = (uint8_t[]){ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
+ .value_len = 16,
+ }, {
+ .handle = 0,
+ } }));
+
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 13, 0xffff,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 14,
+ .value = (uint8_t[]){ 0x55, 0x55 },
+ .value_len = 2,
+ }, {
+ .handle = 0,
+ } }));
+
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 15, 0xffff,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 16,
+ .value = (uint8_t[]){ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
+ .value_len = 16,
+ }, {
+ .handle = 0,
+ } }));
+
+ /*** Read until the end of the attribute list. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 17, 0xffff,
+ BLE_ATT_UUID_CHARACTERISTIC);
+ TEST_ASSERT(rc == 0);
+ ble_att_svr_test_misc_verify_tx_read_type_rsp(
+ ((struct ble_att_svr_test_type_entry[]) { {
+ .handle = 18,
+ .value = (uint8_t[]){ 0x66, 0x66 },
+ .value_len = 2,
+ }, {
+ .handle = 20,
+ .value = (uint8_t[]){ 0x77, 0x77 },
+ .value_len = 2,
+ }, {
+ .handle = 22,
+ .value = (uint8_t[]){ 0x88, 0x88 },
+ .value_len = 2,
+ }, {
+ .handle = 24,
+ .value = (uint8_t[]){ 0x99, 0x99 },
+ .value_len = 2,
+ }, {
+ .handle = 0,
+ } }));
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_read_type)
+{
+ ble_att_svr_test_misc_read_type(0);
+ ble_att_svr_test_misc_read_type(128);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_read_group_type)
+{
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(128);
+
+ /*** Start handle of 0. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 0, 0, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ, 0,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Start handle > end handle. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 101, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ, 101,
+ BLE_ATT_ERR_INVALID_HANDLE);
+
+ /*** Invalid group UUID (0x1234). */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 110, 150, 0x1234);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ, 110,
+ BLE_ATT_ERR_UNSUPPORTED_GROUP);
+
+ /*** No attributes. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ, 1,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Range too late. */
+ ble_att_svr_test_misc_register_group_attrs();
+
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 200, 300, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc != 0);
+ ble_hs_test_util_verify_tx_err_rsp(
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ, 200,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** One 16-bit UUID service. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 1, 5, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_group_type_rsp(
+ ((struct ble_hs_test_util_att_group_type_entry[]) { {
+ .start_handle = 1,
+ .end_handle = 5,
+ .uuid = BLE_UUID16_DECLARE(0x1122),
+ }, {
+ .start_handle = 0,
+ } }));
+
+ /*** Two 16-bit UUID services. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 1, 10, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_group_type_rsp(
+ ((struct ble_hs_test_util_att_group_type_entry[]) { {
+ .start_handle = 1,
+ .end_handle = 5,
+ .uuid = BLE_UUID16_DECLARE(0x1122),
+ }, {
+ .start_handle = 6,
+ .end_handle = 10,
+ .uuid = BLE_UUID16_DECLARE(0x2233),
+ }, {
+ .start_handle = 0,
+ } }));
+
+ /*** Two 16-bit UUID services; ensure 128-bit service not returned. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 1, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_group_type_rsp(
+ ((struct ble_hs_test_util_att_group_type_entry[]) { {
+ .start_handle = 1,
+ .end_handle = 5,
+ .uuid = BLE_UUID16_DECLARE(0x1122),
+ }, {
+ .start_handle = 6,
+ .end_handle = 10,
+ .uuid = BLE_UUID16_DECLARE(0x2233),
+ }, {
+ .start_handle = 0,
+ } }));
+
+ /*** One 128-bit service. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 11, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_verify_tx_read_group_type_rsp(
+ ((struct ble_hs_test_util_att_group_type_entry[]) { {
+ .start_handle = 11,
+ .end_handle = 0xffff,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ .start_handle = 0,
+ } }));
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(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(205);
+
+ /* Initialize some attribute data. */
+ for (i = 0; i < sizeof data; i++) {
+ data[i] = i;
+ }
+
+ /* Register two writable attributes. */
+ ble_att_svr_test_misc_register_uuid(BLE_UUID16_DECLARE(0x1234),
+ HA_FLAG_PERM_RW, 1,
+ ble_att_svr_test_misc_attr_fn_w_1);
+ ble_att_svr_test_misc_register_uuid(BLE_UUID16_DECLARE(0x8989),
+ HA_FLAG_PERM_RW, 2,
+ ble_att_svr_test_misc_attr_fn_w_2);
+
+ /* 3: not writable. */
+ ble_att_svr_test_misc_register_uuid(BLE_UUID16_DECLARE(0xabab),
+ BLE_ATT_F_READ, 3,
+ ble_att_svr_test_misc_attr_fn_r_1);
+ /* 4: Encryption required. */
+ ble_att_svr_test_misc_register_uuid(
+ BLE_UUID16_DECLARE(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_uuid(
+ BLE_UUID16_DECLARE(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_uuid(
+ BLE_UUID16_DECLARE(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_EXECUTE,
+ 0, 0);
+
+ /*** Empty cancel succeeds. */
+ ble_att_svr_test_misc_exec_write(conn_handle, 0, 0, 0);
+
+ /*** Failure for prep write to nonexistent attribute. */
+ 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_EXECUTE,
+ BLE_ATT_ERR_INVALID_OFFSET, 1);
+ ble_att_svr_test_misc_verify_w_1(NULL, 0);
+
+ /*** Success for clear 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, 0, 0, 0);
+ ble_att_svr_test_misc_verify_w_1(NULL, 0);
+
+ /*** Failure for write with gap. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 10, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 11, data, 10, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ BLE_ATT_ERR_INVALID_OFFSET, 1);
+ ble_att_svr_test_misc_verify_w_1(NULL, 0);
+
+ /*** Success for clear with gap. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 10, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 11, data, 10, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, 0, 0, 0);
+ ble_att_svr_test_misc_verify_w_1(NULL, 0);
+
+ /*** Failure for overlong write. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 200, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 200, data + 200, 200, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 400, data + 400, 200, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN, 1);
+ ble_att_svr_test_misc_verify_w_1(NULL, 0);
+
+ /*** Successful two part write. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 20, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 20, data + 20, 20, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ 0, 0);
+ ble_att_svr_test_misc_verify_w_1(data, 40);
+
+ /*** Successful three part write. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 35, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 35, data + 35, 43, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 78, data + 78, 1, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ 0, 0);
+ ble_att_svr_test_misc_verify_w_1(data, 79);
+
+ /*** Successful two part write to two attributes. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 7, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 7, data + 7, 10, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 0, data, 20, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 20, data + 20, 10, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ 0, 0);
+ ble_att_svr_test_misc_verify_w_1(data, 17);
+ ble_att_svr_test_misc_verify_w_2(data, 30);
+
+ /*** Fail write to second attribute; ensure first write doesn't occur. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 5, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 5, data + 5, 2, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 0, data, 11, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 12, data + 11, 19, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ BLE_ATT_ERR_INVALID_OFFSET, 2);
+ ble_att_svr_test_misc_verify_w_1(data, 17);
+ ble_att_svr_test_misc_verify_w_2(data, 30);
+
+ /*** Successful out of order write to two attributes. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 9, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 0, data, 18, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 9, data + 9, 3, 0);
+ ble_att_svr_test_misc_prep_write(conn_handle, 2, 18, data + 18, 43, 0);
+ ble_att_svr_test_misc_exec_write(conn_handle, BLE_ATT_EXEC_WRITE_F_EXECUTE,
+ 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_EXECUTE,
+ BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN, 6);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_notify)
+{
+ uint16_t conn_handle;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /*** Successful notifies; verify callback is executed. */
+ /* 3-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn_handle, 10,
+ (uint8_t[]) { 1, 2, 3 }, 3, 1);
+ /* 1-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn_handle, 1,
+ (uint8_t[]) { 0xff }, 1, 1);
+ /* 0-length attribute. */
+ ble_att_svr_test_misc_verify_notify(conn_handle, 43, NULL, 0, 1);
+
+ /*** Bad notifies; verify callback is not executed. */
+ /* Attribute handle of 0. */
+ ble_att_svr_test_misc_verify_notify(conn_handle, 0,
+ (uint8_t[]) { 1, 2, 3 }, 3, 0);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_prep_write_tmo)
+{
+ int32_t ticks_from_now;
+ uint16_t conn_handle;
+ int rc;
+ int i;
+
+ static uint8_t data[1024];
+
+ conn_handle = ble_att_svr_test_misc_init(205);
+
+ /* Initialize some attribute data. */
+ for (i = 0; i < sizeof data; i++) {
+ data[i] = i;
+ }
+
+ /* Register a writable attribute. */
+ ble_att_svr_test_misc_register_uuid(BLE_UUID16_DECLARE(0x1234),
+ HA_FLAG_PERM_RW, 1,
+ ble_att_svr_test_misc_attr_fn_w_1);
+
+ /* Ensure timer is not set. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT_FATAL(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Receive a prepare write request. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 0, data, 7, 0);
+
+ /* Ensure timer will expire in 30 seconds. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_ATT_SVR_QUEUED_WRITE_TMO);
+
+ /* Almost let the timer expire. */
+ os_time_advance(BLE_HS_ATT_SVR_QUEUED_WRITE_TMO - 1);
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == 1);
+
+ /* Receive a second prepare write request. */
+ ble_att_svr_test_misc_prep_write(conn_handle, 1, 7, data + 7, 10, 0);
+
+ /* Ensure timer got reset. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_ATT_SVR_QUEUED_WRITE_TMO);
+
+ /* Allow the timer to expire. */
+ ble_hs_test_util_hci_ack_set_disconnect(0);
+ os_time_advance(BLE_HS_ATT_SVR_QUEUED_WRITE_TMO);
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Ensure connection was terminated. */
+ ble_hs_test_util_hci_verify_tx_disconnect(2, BLE_ERR_REM_USER_CONN_TERM);
+
+ /* Free connection. This is needed so that the prep write mbufs get
+ * freed and no mbuf leak gets reported.
+ */
+ rc = ble_hs_atomic_conn_delete(conn_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_indicate)
+{
+ uint16_t conn_handle;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /*** Successful indicates; verify callback is executed. */
+ /* 3-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn_handle, 10,
+ (uint8_t[]) { 1, 2, 3 }, 3, 1);
+ /* 1-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn_handle, 1,
+ (uint8_t[]) { 0xff }, 1, 1);
+ /* 0-length attribute. */
+ ble_att_svr_test_misc_verify_indicate(conn_handle, 43, NULL, 0, 1);
+
+ /*** Bad indicates; verify callback is not executed. */
+ /* Attribute handle of 0. */
+ ble_att_svr_test_misc_verify_indicate(conn_handle, 0,
+ (uint8_t[]) { 1, 2, 3 }, 3, 0);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_oom)
+{
+ struct os_mbuf *oms;
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /* Register an attribute (primary service) for incoming read commands. */
+ ble_att_svr_test_misc_register_uuid(
+ BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE),
+ HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_rw_1);
+ ble_att_svr_test_attr_w_1_len = 2;
+ ble_att_svr_test_attr_w_1[0] = 0x12;
+ ble_att_svr_test_attr_w_1[1] = 0x34;
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming request. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+
+ /*** MTU; always respond affirmatively, even when no mbufs. */
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_mtu_cmd(conn_handle, 1, 100);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure we were able to send a real response. */
+ ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle);
+
+ /*** Find information; always respond affirmatively, even when no mbufs. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 1, 100);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure we were able to send a real response. */
+ ble_hs_test_util_verify_tx_find_info_rsp(
+ (struct ble_hs_test_util_att_info_entry[]) {
+ { .handle = 1, .uuid = BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE) },
+ { 0 },
+ });
+
+ /*** Find by type value. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_find_type_value_req(
+ conn_handle, 1, 100, 0x0001, ((uint8_t[2]){0x99, 0x99}), 2);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+
+ /* Ensure we were able to send an error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1,
+ BLE_ATT_ERR_INSUFFICIENT_RES);
+
+ /*** Read by type; always respond affirmatively, even when no mbufs. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 100, 0xffff,
+ BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
+
+ /* Ensure we were able to send a non-OOM error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_TYPE_REQ, 100,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Read; always respond affirmatively, even when no mbufs. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_read_req(conn_handle, 1);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure we were able to send a real response. */
+ ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_w_1,
+ ble_att_svr_test_attr_w_1_len);
+
+ /*** Read blob; always respond affirmatively, even when no mbufs. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, 1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure we were able to send a real response. */
+ ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_w_1,
+ ble_att_svr_test_attr_w_1_len);
+
+ /*** Read multiple. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_read_mult_req(conn_handle,
+ ((uint16_t[2]){0x0001, 0x0002}),
+ 2);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+
+ /* Ensure we were able to send an error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ, 0,
+ BLE_ATT_ERR_INSUFFICIENT_RES);
+
+ /***
+ * Read by group type; always respond affirmatively, even when no
+ * mbufs.
+ */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_read_group_type_req16(
+ conn_handle, 11, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
+
+ /* Ensure we were able to send a non-OOM error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_GROUP_TYPE_REQ, 11,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+
+ /*** Write. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_write_req(conn_handle, 1,
+ ((uint8_t[1]){1}), 1);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+
+ /* Ensure we were able to send an error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ, 1,
+ BLE_ATT_ERR_INSUFFICIENT_RES);
+
+ /*** Write command; no response. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_write_cmd(conn_handle, 1,
+ ((uint8_t[1]){1}), 1);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure no response sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /*** Prepare write. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_prep_write_req(conn_handle, 1, 0,
+ ((uint8_t[1]){1}), 1);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+
+ /* Ensure we were able to send an error response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_PREP_WRITE_REQ, 1,
+ BLE_ATT_ERR_INSUFFICIENT_RES);
+
+ /*** Notify; no response. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_notify_req(conn_handle, 1,
+ ((uint8_t[1]){1}), 1);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure no response sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /*** Indicate. */
+ ble_hs_test_util_prev_tx_dequeue();
+
+ /* Receive a request. */
+ rc = ble_hs_test_util_rx_att_indicate_req(conn_handle, 1,
+ ((uint8_t[1]){1}), 1);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+
+ /* Ensure we were able to send a real response. */
+ ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_INDICATE_REQ, 1,
+ BLE_ATT_ERR_INSUFFICIENT_RES);
+
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_CASE_SELF(ble_att_svr_test_unsupported_req)
+{
+ uint16_t conn_handle;
+ int rc;
+ uint8_t buf[] = {0x3f, 0x00, 0x00, 0x01, 0x02, 0x03};
+
+ conn_handle = ble_att_svr_test_misc_init(0);
+
+ /* Put handle into buf */
+ (*(uint16_t *)&buf[1]) = htole16(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_hs_test_util_verify_tx_err_rsp(0x3f, 0,
+ BLE_ATT_ERR_REQ_NOT_SUPPORTED);
+
+ /* Check for no response when unknown command is sent */
+ buf[0] = 0x4f;
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc != 0);
+
+ /* Ensure no response sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ ble_att_svr_test_assert_mbufs_freed();
+}
+
+TEST_SUITE(ble_att_svr_suite)
+{
+ ble_att_svr_test_mtu();
+ ble_att_svr_test_read();
+ ble_att_svr_test_read_blob();
+ ble_att_svr_test_read_mult();
+ ble_att_svr_test_write();
+ ble_att_svr_test_find_info();
+ ble_att_svr_test_find_type_value();
+ ble_att_svr_test_read_type();
+ ble_att_svr_test_read_group_type();
+ ble_att_svr_test_prep_write();
+ ble_att_svr_test_prep_write_tmo();
+ ble_att_svr_test_notify();
+ ble_att_svr_test_indicate();
+ ble_att_svr_test_oom();
+ ble_att_svr_test_unsupported_req();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
new file mode 100644
index 00000000..7496e316
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
@@ -0,0 +1,3168 @@
+/*
+ * 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 "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_HCI_SET_SCAN_PARAM_LEN (7)
+#define BLE_HCI_SET_SCAN_ENABLE_LEN (2)
+#define BLE_HCI_DISCONNECT_CMD_LEN (3)
+#define BLE_HCI_SET_ADV_PARAM_LEN (15)
+#define BLE_HCI_SET_ADV_ENABLE_LEN (1)
+#define BLE_HCI_CONN_UPDATE_LEN (14)
+#define BLE_HCI_CONN_PARAM_REPLY_LEN (14)
+#define BLE_HCI_CONN_PARAM_NEG_REPLY_LEN (3)
+
+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_type;
+static struct ble_gap_disc_desc ble_gap_test_disc_desc;
+static void *ble_gap_test_disc_arg;
+
+/*****************************************************************************
+ * $misc *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_reset_cb_info(void)
+{
+ 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_type = -1;
+ memset(&ble_gap_test_disc_desc, 0xff, sizeof ble_gap_test_disc_desc);
+ ble_gap_test_disc_arg = (void *)-1;
+}
+
+static void
+ble_gap_test_util_init(void)
+{
+ ble_hs_test_util_init();
+ ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 });
+ ble_gap_test_util_reset_cb_info();
+}
+
+static int
+ble_gap_test_util_disc_cb(struct ble_gap_event *event, void *arg)
+{
+ 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(struct ble_gap_event *event, void *arg)
+{
+ int *fail_reason;
+ int ret;
+
+ ble_gap_test_event = *event;
+ ble_gap_test_conn_arg = arg;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ble_gap_test_conn_status = event->connect.status;
+ ret = ble_gap_conn_find(event->connect.conn_handle,
+ &ble_gap_test_conn_desc);
+ TEST_ASSERT_FATAL(ble_gap_test_conn_status || ret == 0);
+ break;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ 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 = event->conn_update.status;
+ ret = ble_gap_conn_find(event->conn_update.conn_handle,
+ &ble_gap_test_conn_desc);
+ TEST_ASSERT_FATAL(ret == 0);
+ break;
+
+ case BLE_GAP_EVENT_TERM_FAILURE:
+ ble_gap_test_conn_status = event->term_failure.status;
+ ret = ble_gap_conn_find(event->term_failure.conn_handle,
+ &ble_gap_test_conn_desc);
+ TEST_ASSERT_FATAL(ret == 0);
+ break;
+
+ case BLE_GAP_EVENT_ADV_COMPLETE:
+ ble_gap_test_conn_arg = arg;
+ break;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ ble_gap_test_conn_peer_params = *event->conn_update_req.peer_params;
+ *event->conn_update_req.self_params = ble_gap_test_conn_self_params;
+ ret = ble_gap_conn_find(event->conn_update_req.conn_handle,
+ &ble_gap_test_conn_desc);
+ TEST_ASSERT_FATAL(ret == 0);
+
+ fail_reason = arg;
+ if (fail_reason == NULL) {
+ return 0;
+ } else {
+ return *fail_reason;
+ }
+ break;
+
+ case BLE_GAP_EVENT_MTU:
+ break;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ break;
+ }
+
+ return 0;
+}
+
+static int
+ble_gap_test_util_copy_cb(struct ble_gap_event *event, void *arg)
+{
+ ble_gap_test_event = *event;
+ ble_gap_test_conn_arg = arg;
+
+ return 0;
+}
+
+static void
+ble_gap_test_util_verify_tx_clear_wl(void)
+{
+ uint8_t param_len;
+
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CLEAR_WHITE_LIST,
+ &param_len);
+ TEST_ASSERT(param_len == 0);
+}
+
+static void
+ble_gap_test_util_verify_tx_add_wl(ble_addr_t *addr)
+{
+ uint8_t param_len;
+ uint8_t *param;
+ int i;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_ADD_WHITE_LIST,
+ &param_len);
+ TEST_ASSERT(param_len == 7);
+ TEST_ASSERT(param[0] == addr->type);
+ for (i = 0; i < 6; i++) {
+ TEST_ASSERT(param[1 + i] == addr->val[i]);
+ }
+}
+
+static void
+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)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_SET_SCAN_PARAM_LEN);
+ TEST_ASSERT(param[0] == scan_type);
+ TEST_ASSERT(get_le16(param + 1) == itvl);
+ TEST_ASSERT(get_le16(param + 3) == scan_window);
+ 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,
+ uint8_t filter_duplicates)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_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_hs_test_util_hci_verify_tx_create_conn_cancel(void)
+{
+ uint8_t param_len;
+
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
+ &param_len);
+ TEST_ASSERT(param_len == 0);
+}
+
+static void
+ble_gap_test_util_verify_tx_disconnect(void)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LINK_CTRL,
+ BLE_HCI_OCF_DISCONNECT_CMD,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_DISCONNECT_CMD_LEN);
+ TEST_ASSERT(get_le16(param + 0) == 2);
+ TEST_ASSERT(param[2] == BLE_ERR_REM_USER_CONN_TERM);
+}
+
+static void
+ble_gap_test_util_verify_tx_adv_params(void)
+{
+ uint8_t param_len;
+
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_PARAMS,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_SET_ADV_PARAM_LEN);
+
+ /* Note: Content of message verified in ble_hs_adv_test.c. */
+}
+
+static void
+ble_gap_test_util_verify_tx_adv_data(void)
+{
+ uint8_t param_len;
+
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_DATA,
+ &param_len);
+ /* Note: Content of message verified in ble_hs_adv_test.c. */
+}
+
+#if 0
+static void
+ble_gap_test_util_verify_tx_rsp_data(void)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA,
+ &param_len);
+ (void)param; /* XXX: Verify other fields. */
+}
+#endif
+
+static void
+ble_gap_test_util_verify_tx_adv_enable(int enabled)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_ENABLE,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_SET_ADV_ENABLE_LEN);
+ TEST_ASSERT(param[0] == !!enabled);
+}
+
+static void
+ble_gap_test_util_verify_tx_update_conn(struct ble_gap_upd_params *params)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CONN_UPDATE,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN);
+ TEST_ASSERT(get_le16(param + 0) == 2);
+ TEST_ASSERT(get_le16(param + 2) == params->itvl_min);
+ TEST_ASSERT(get_le16(param + 4) == params->itvl_max);
+ TEST_ASSERT(get_le16(param + 6) == params->latency);
+ TEST_ASSERT(get_le16(param + 8) == params->supervision_timeout);
+ TEST_ASSERT(get_le16(param + 10) == params->min_ce_len);
+ TEST_ASSERT(get_le16(param + 12) == params->max_ce_len);
+}
+
+static void
+ble_gap_test_util_verify_tx_params_reply_pos(void)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CONN_PARAM_REPLY_LEN);
+ TEST_ASSERT(get_le16(param + 0) == 2);
+ TEST_ASSERT(get_le16(param + 2) == ble_gap_test_conn_self_params.itvl_min);
+ TEST_ASSERT(get_le16(param + 4) == ble_gap_test_conn_self_params.itvl_max);
+ TEST_ASSERT(get_le16(param + 6) == ble_gap_test_conn_self_params.latency);
+ TEST_ASSERT(get_le16(param + 8) ==
+ ble_gap_test_conn_self_params.supervision_timeout);
+ TEST_ASSERT(get_le16(param + 10) ==
+ ble_gap_test_conn_self_params.min_ce_len);
+ TEST_ASSERT(get_le16(param + 12) ==
+ ble_gap_test_conn_self_params.max_ce_len);
+}
+
+static void
+ble_gap_test_util_verify_tx_params_reply_neg(uint8_t reason)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CONN_PARAM_NEG_REPLY_LEN);
+ TEST_ASSERT(get_le16(param + 0) == 2);
+ TEST_ASSERT(param[2] == reason);
+}
+
+static void
+ble_gap_test_util_rx_update_complete(
+ uint8_t status,
+ const struct ble_gap_upd_params *params)
+{
+ struct ble_hci_ev_le_subev_conn_upd_complete evt;
+
+ evt.subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
+ evt.status = status;
+ evt.conn_handle = htole16(2);
+ evt.conn_itvl = htole16(params->itvl_max);
+ evt.conn_latency = htole16(params->latency);
+ evt.supervision_timeout = htole16(params->supervision_timeout);
+
+ ble_gap_rx_update_complete(&evt);
+}
+
+static int
+ble_gap_test_util_rx_param_req(struct ble_gap_upd_params *params, int pos,
+ int *cmd_idx, int cmd_fail_idx,
+ uint8_t fail_status)
+{
+ struct ble_hci_ev_le_subev_rem_conn_param_req evt;
+ uint16_t opcode;
+ uint8_t hci_status;
+
+ evt.subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
+ evt.conn_handle = htole16(2);
+ evt.min_interval = htole16(params->itvl_min);
+ evt.max_interval = htole16(params->itvl_max);
+ evt.latency = htole16(params->latency);
+ evt.timeout = params->supervision_timeout;
+
+ if (pos) {
+ opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR);
+ } else {
+ 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;
+ } else {
+ hci_status = 0;
+ }
+ (*cmd_idx)++;
+
+ ble_hs_test_util_hci_ack_set(opcode, hci_status);
+ ble_gap_rx_param_req(&evt);
+
+ return hci_status;
+}
+
+/*****************************************************************************
+ * $white list *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_wl_set(ble_addr_t *addrs, int addrs_count, int cmd_fail_idx,
+ uint8_t fail_status)
+{
+ int cmd_idx;
+ int rc;
+ int i;
+
+ ble_gap_test_util_init();
+ cmd_idx = 0;
+
+ rc = ble_hs_test_util_wl_set(addrs, addrs_count, cmd_fail_idx,
+ fail_status);
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
+
+ /* Verify tx of clear white list command. */
+ ble_gap_test_util_verify_tx_clear_wl();
+ if (cmd_idx >= cmd_fail_idx) {
+ return;
+ }
+ cmd_idx++;
+
+ /* Verify tx of add white list commands. */
+ for (i = 0; i < addrs_count; i++) {
+ ble_gap_test_util_verify_tx_add_wl(addrs + i);
+ if (cmd_idx >= cmd_fail_idx) {
+ return;
+ }
+ cmd_idx++;
+ }
+}
+
+TEST_CASE_SELF(ble_gap_test_case_wl_bad_args)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /*** 0 white list entries. */
+ rc = ble_hs_test_util_wl_set(NULL, 0, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ /*** Invalid address type. */
+ rc = ble_hs_test_util_wl_set(
+ ((ble_addr_t[]) { {
+ 5, { 1, 2, 3, 4, 5, 6 }
+ }, }),
+ 1, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ /*** White-list-using connection in progress. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, NULL, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_wl_set(
+ ((ble_addr_t[]) { {
+ BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }
+ }, }),
+ 1, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EBUSY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_wl_ctlr_fail)
+{
+ int i;
+
+ ble_addr_t addrs[] = {
+ { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
+ { BLE_ADDR_PUBLIC, { 3, 4, 5, 6, 7, 8 } },
+ { BLE_ADDR_PUBLIC, { 4, 5, 6, 7, 8, 9 } },
+ };
+ int addrs_count = sizeof addrs / sizeof addrs[0];
+
+ for (i = 0; i < 5; i++) {
+ ble_gap_test_util_wl_set(addrs, addrs_count, i,
+ BLE_ERR_UNSPECIFIED);
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_wl_good)
+{
+ ble_addr_t addrs[] = {
+ { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
+ { BLE_ADDR_PUBLIC, { 3, 4, 5, 6, 7, 8 } },
+ { BLE_ADDR_PUBLIC, { 4, 5, 6, 7, 8, 9 } },
+ };
+ int addrs_count = sizeof addrs / sizeof addrs[0];
+
+ ble_gap_test_util_wl_set(addrs, addrs_count, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_wl)
+{
+ ble_gap_test_case_wl_good();
+ ble_gap_test_case_wl_bad_args();
+ ble_gap_test_case_wl_ctlr_fail();
+}
+
+/*****************************************************************************
+ * $discovery *
+ *****************************************************************************/
+
+static int
+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(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(desc);
+ } else {
+ 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(
+ 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, disc_params->filter_duplicates);
+ }
+
+ if (rc == 0) {
+ TEST_ASSERT(ble_gap_disc_active());
+ }
+
+ return rc;
+}
+
+TEST_CASE_SELF(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 filter policy. */
+ params.filter_policy = 6;
+ rc = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, 0, &params,
+ ble_gap_test_util_disc_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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;
+
+ struct ble_gap_disc_desc desc = {
+ .event_type = BLE_HCI_ADV_TYPE_ADV_IND,
+ .addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .length_data = 0,
+ .rssi = 0,
+ .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, &desc.length_data,
+ sizeof adv_data);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ for (own_addr_type = 0;
+ own_addr_type <= BLE_OWN_ADDR_RPA_RANDOM_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_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_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.val, desc.addr.val,
+ 6) == 0);
+ TEST_ASSERT(ble_gap_test_disc_arg == NULL);
+
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_disc_ltd_mismatch)
+{
+ int rc;
+ struct ble_gap_disc_desc desc_gen = {
+ .event_type = BLE_HCI_ADV_TYPE_ADV_IND,
+ .length_data = 3,
+ .rssi = 0,
+ .addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .data = (uint8_t[BLE_HS_ADV_MAX_SZ]){
+ 2,
+ BLE_HS_ADV_TYPE_FLAGS,
+ BLE_HS_ADV_F_DISC_GEN,
+ },
+ };
+
+ struct ble_gap_disc_desc desc_lim = {
+ .event_type = BLE_HCI_ADV_TYPE_ADV_IND,
+ .length_data = 3,
+ .rssi = 0,
+ .addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .data = (uint8_t[BLE_HS_ADV_MAX_SZ]){
+ 2,
+ BLE_HS_ADV_TYPE_FLAGS,
+ BLE_HS_ADV_F_DISC_LTD,
+ },
+ };
+
+ 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,
+ };
+
+ rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc_gen,
+ -1, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(ble_gap_master_in_progress());
+
+ /* 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);
+
+ disc_params.limited = 0;
+ rc = ble_gap_test_util_disc(BLE_OWN_ADDR_PUBLIC, &disc_params, &desc_lim,
+ -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_SELF(ble_gap_test_case_disc_hci_fail)
+{
+ int fail_idx;
+ int limited;
+ int rc;
+
+ struct ble_gap_disc_desc desc = {
+ .event_type = BLE_HCI_ADV_TYPE_ADV_IND,
+ .length_data = 0,
+ .rssi = 0,
+ .addr = { BLE_ADDR_PUBLIC, { 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 (fail_idx = 0; fail_idx < 2; fail_idx++) {
+ rc = ble_gap_test_util_disc(BLE_OWN_ADDR_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());
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+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_OWN_ADDR_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_OWN_ADDR_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_SELF(ble_gap_test_case_disc_dflts)
+{
+ ble_gap_test_util_disc_dflts_once(0);
+ ble_gap_test_util_disc_dflts_once(1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_disc_already)
+{
+ 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_OWN_ADDR_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_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &disc_params,
+ ble_gap_test_util_disc_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_disc_busy)
+{
+ static const struct ble_gap_disc_params disc_params = { 0 };
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 1, 2, 3, 4, 5, 6 }
+ };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a connect procedure. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_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_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &disc_params,
+ ble_gap_test_util_disc_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EBUSY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_disc)
+{
+ 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_SELF(ble_gap_test_case_conn_gen_good)
+{
+ struct ble_gap_conn_complete evt;
+ struct ble_gap_conn_params params;
+ int rc;
+
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+
+ ble_gap_test_util_init();
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ 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_OWN_ADDR_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());
+
+ TEST_ASSERT(ble_gap_master_in_progress());
+ TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony
+ * ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Receive connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
+ memcpy(evt.peer_addr, peer_addr.val, 6);
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ 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.val,
+ peer_addr.val, 6) == 0);
+
+ TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_bad_args)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /*** Invalid address type. */
+ rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC,
+ &((ble_addr_t) { 5, { 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_connect(
+ BLE_OWN_ADDR_PUBLIC,
+ &((ble_addr_t) { BLE_ADDR_PUBLIC, { 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_connect(
+ BLE_OWN_ADDR_PUBLIC,
+ &((ble_addr_t) { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }}),
+ 0, NULL, ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_dflt_params)
+{
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 2, 3, 8, 6, 6, 1 }
+ };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, 0, NULL,
+ ble_gap_test_util_connect_cb, NULL, 0);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_already)
+{
+ static const struct ble_gap_conn_params conn_params = { 0 };
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 1, 2, 3, 4, 5, 6 }
+ };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a connect procedure. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_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_OWN_ADDR_PUBLIC, &peer_addr, BLE_HS_FOREVER,
+ &conn_params, ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_done)
+{
+ static const struct ble_gap_conn_params conn_params = { 0 };
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 1, 2, 3, 4, 5, 6 }
+ };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Successfully connect to the peer. */
+ ble_hs_test_util_create_conn(2, peer_addr.val,
+ ble_gap_test_util_connect_cb, NULL);
+
+ /* Ensure host indicates BLE_HS_EDONE if we try to connect to the same
+ * peer.
+ */
+ rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr, BLE_HS_FOREVER,
+ &conn_params, ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EDONE);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_busy)
+{
+ static const struct ble_gap_disc_params disc_params = { 0 };
+ static const struct ble_gap_conn_params conn_params = { 0 };
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 1, 2, 3, 4, 5, 6 }
+ };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a discovery procedure. */
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_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_OWN_ADDR_PUBLIC, &peer_addr, BLE_HS_FOREVER,
+ &conn_params, ble_gap_test_util_connect_cb, NULL);
+ TEST_ASSERT(rc == BLE_HS_EBUSY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_gen_fail_evt)
+{
+ static const ble_addr_t peer_addr = {BLE_ADDR_PUBLIC, {1, 2, 3, 4, 5, 6}};
+ struct ble_gap_conn_complete evt;
+ struct ble_hci_ev_disconn_cmp disc_evt;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start a connect procedure. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr, 0, NULL,
+ ble_gap_test_util_copy_cb, NULL, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Controller indicates failure via connect complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 6;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
+ evt.peer_addr_type = BLE_ADDR_PUBLIC;
+ memcpy(evt.peer_addr, peer_addr.val, 6);
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure failed connect was reported to application. */
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_event.connect.status ==
+ BLE_HS_HCI_ERR(BLE_ERR_SUCCESS));
+
+ memset(&disc_evt, 0, sizeof disc_evt);
+ disc_evt.conn_handle = htole16(6);
+ disc_evt.status = BLE_ERR_SUCCESS;
+ disc_evt.reason = BLE_ERR_CONN_ESTABLISHMENT;
+
+ ble_gap_rx_disconn_complete(&disc_evt);
+
+ /* Ensure failed connect was reported to application. */
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_DISCONNECT);
+ TEST_ASSERT(ble_gap_test_event.disconnect.reason ==
+ BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT));
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_gen)
+{
+ 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_done();
+ ble_gap_test_case_conn_gen_busy();
+ ble_gap_test_case_conn_gen_fail_evt();
+}
+
+/*****************************************************************************
+ * $cancel *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_conn_cancel(uint8_t hci_status)
+{
+ struct ble_gap_conn_complete evt;
+ int rc;
+
+ /* 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_hs_test_util_hci_verify_tx_create_conn_cancel();
+ if (rc != 0) {
+ return;
+ }
+ TEST_ASSERT(ble_gap_master_in_progress());
+
+ /* Receive connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_UNK_CONN_ID;
+ /* test if host correctly ignores other fields if status is error */
+ evt.connection_handle = 0x0fff;
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_event.connect.status == BLE_HS_EAPP);
+}
+
+static void
+ble_gap_test_util_conn_and_cancel(uint8_t *peer_addr, uint8_t hci_status)
+{
+ ble_addr_t addr = { BLE_ADDR_PUBLIC };
+ int rc;
+
+ ble_gap_test_util_init();
+
+ memcpy(addr.val, peer_addr, 6);
+
+ /* Begin creating a connection. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &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);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_cancel_bad_args)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* 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_EALREADY);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_cancel_good)
+{
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_conn_and_cancel(peer_addr, 0);
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_gap_test_event.connect.status == BLE_HS_EAPP);
+ TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == BLE_HS_CONN_HANDLE_NONE);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_cancel_ctlr_fail)
+{
+ struct ble_gap_conn_complete evt;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ 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_event.type == 0xff);
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony
+ * ack
+ */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Allow connection complete to succeed. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ 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, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ 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.val,
+ peer_addr, 6) == 0);
+
+ TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_cancel)
+{
+ ble_gap_test_case_conn_cancel_good();
+ ble_gap_test_case_conn_cancel_bad_args();
+ ble_gap_test_case_conn_cancel_ctlr_fail();
+}
+
+/*****************************************************************************
+ * $terminate *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_terminate(uint8_t *peer_addr, uint8_t hci_status)
+{
+ struct ble_hci_ev_disconn_cmp evt;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Create a connection. */
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ /* Reset the callback event code; we don't care about the successful
+ * connection in this test.
+ */
+ ble_gap_test_event.type = -1;
+
+ /* Terminate the connection. */
+ rc = ble_hs_test_util_conn_terminate(2, hci_status);
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(hci_status));
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Verify tx of disconnect command. */
+ ble_gap_test_util_verify_tx_disconnect();
+
+ if (hci_status == 0) {
+ /* Receive disconnection complete event. */
+ evt.conn_handle = htole16(2);
+ evt.status = 0;
+ evt.reason = BLE_ERR_CONN_TERM_LOCAL;
+ ble_gap_rx_disconn_complete(&evt);
+ }
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_terminate_bad_args)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /*** Nonexistent connection. */
+ rc = ble_hs_test_util_conn_terminate(2, 0);
+ TEST_ASSERT(rc == BLE_HS_ENOTCONN);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_terminate_good)
+{
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_terminate(peer_addr, 0);
+
+ 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_PUBLIC);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
+ peer_addr, 6) == 0);
+ TEST_ASSERT(ble_gap_test_conn_arg == NULL);
+
+ TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_terminate_ctlr_fail)
+{
+ struct ble_hci_ev_disconn_cmp evt;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_init();
+
+ /* Create a connection. */
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ /* Terminate the connection. */
+ rc = ble_hs_test_util_conn_terminate(2, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Verify tx of disconnect command. */
+ ble_gap_test_util_verify_tx_disconnect();
+
+ /* Receive failed disconnection complete event. */
+ evt.conn_handle = htole16(2);
+ evt.status = BLE_ERR_UNSUPPORTED;
+ evt.reason = 0;
+ ble_gap_rx_disconn_complete(&evt);
+
+ 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_PUBLIC);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
+ peer_addr, 6) == 0);
+ TEST_ASSERT(ble_gap_test_conn_arg == NULL);
+
+ TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_terminate_hci_fail)
+{
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_terminate(peer_addr, BLE_ERR_REPEATED_ATTEMPTS);
+
+ 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());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_terminate)
+{
+ ble_gap_test_case_conn_terminate_bad_args();
+ ble_gap_test_case_conn_terminate_good();
+ ble_gap_test_case_conn_terminate_ctlr_fail();
+ ble_gap_test_case_conn_terminate_hci_fail();
+}
+
+/*****************************************************************************
+ * $conn find *
+ *****************************************************************************/
+
+TEST_CASE_SELF(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();
+
+ rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, pub_addr, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_create_rpa_conn(8,
+ BLE_OWN_ADDR_PUBLIC,
+ ((uint8_t[6]){0,0,0,0,0,0}),
+ BLE_ADDR_PUBLIC,
+ ((uint8_t[6]){2,3,4,5,6,7}),
+ ((uint8_t[6]){0,0,0,0,0,0}),
+ BLE_HS_TEST_CONN_FEAT_ALL,
+ ble_gap_test_util_connect_cb,
+ NULL);
+
+ 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_PUBLIC);
+ TEST_ASSERT(desc.our_ota_addr.type == BLE_ADDR_PUBLIC);
+ TEST_ASSERT(desc.peer_ota_addr.type == BLE_ADDR_PUBLIC);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
+ TEST_ASSERT(memcmp(desc.our_ota_addr.val, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.our_id_addr.val, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_ota_addr.val,
+ ((uint8_t[6]){2,3,4,5,6,7}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_id_addr.val,
+ ((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();
+
+ rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, pub_addr, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_create_rpa_conn(54,
+ BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ ((uint8_t[6]){0x40,1,2,3,4,5}),
+ BLE_ADDR_RANDOM_ID,
+ ((uint8_t[6]){3,4,5,6,7,8}),
+ ((uint8_t[6]){0x50,1,2,3,4,5}),
+ BLE_HS_TEST_CONN_FEAT_ALL,
+ 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_PUBLIC);
+ TEST_ASSERT(desc.our_ota_addr.type == BLE_ADDR_RANDOM);
+ TEST_ASSERT(desc.peer_ota_addr.type == BLE_ADDR_RANDOM);
+ TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
+ TEST_ASSERT(memcmp(desc.our_ota_addr.val,
+ ((uint8_t[6]){0x40,1,2,3,4,5}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.our_id_addr.val, pub_addr, 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_ota_addr.val,
+ ((uint8_t[6]){0x50,1,2,3,4,5}), 6) == 0);
+ TEST_ASSERT(memcmp(desc.peer_id_addr.val,
+ ((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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_conn_find)
+{
+ ble_gap_test_case_conn_find();
+}
+
+/*****************************************************************************
+ * $advertise *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_adv(uint8_t own_addr_type,
+ const ble_addr_t *peer_addr, uint8_t conn_mode,
+ uint8_t disc_mode, int connect_status,
+ int cmd_fail_idx, uint8_t fail_status)
+{
+ struct ble_gap_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();
+
+ 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;
+
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+ rc = ble_hs_test_util_adv_set_fields(&adv_fields, cmd_fail_idx,
+ fail_status);
+ if (cmd_fail_idx < 2) {
+ hci_status = fail_status;
+ } else {
+ hci_status = 0;
+ }
+ TEST_ASSERT_FATAL(rc == BLE_HS_HCI_ERR(hci_status));
+ cmd_idx += 2;
+
+ if (rc == 0) {
+ ble_gap_test_util_verify_tx_adv_data();
+ }
+
+ if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
+ rc = ble_hs_test_util_adv_start(own_addr_type,
+ peer_addr, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL,
+ cmd_fail_idx - cmd_idx, fail_status);
+
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
+ cmd_idx++;
+ }
+
+ if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
+ /* Verify tx of set advertising params command. */
+ ble_gap_test_util_verify_tx_adv_params();
+ }
+ cmd_idx++;
+
+ if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
+ /* Verify tx of set advertise enable command. */
+ ble_gap_test_util_verify_tx_adv_enable(1);
+ }
+ cmd_idx++;
+
+ 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) {
+ if (connect_status == BLE_ERR_SUCCESS) {
+ /*
+ * ble_gap_rx_conn_complete() will send extra HCI command, need
+ * phony ack
+ */
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT),
+ 0);
+ }
+
+ memset(&evt, 0, sizeof evt);
+ evt.status = connect_status;
+
+ if (connect_status == BLE_ERR_SUCCESS) {
+ evt.connection_handle = 2;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
+ memcpy(evt.peer_addr, peer_addr->val, 6);
+ } else {
+ /* test if host correctly ignores other fields if status is
+ * error
+ */
+ evt.connection_handle = 0x0fff;
+ }
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ if (connect_status == 0 ||
+ connect_status == BLE_ERR_DIR_ADV_TMO) {
+
+ TEST_ASSERT(!ble_gap_adv_active());
+ } else {
+ TEST_ASSERT(ble_gap_adv_active());
+ }
+ }
+ }
+}
+
+TEST_CASE_SELF(ble_gap_test_case_adv_bad_args)
+{
+ struct ble_gap_adv_params adv_params;
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+ ble_addr_t peer_addr_inv = { 12, { 1, 2, 3, 4, 5, 6 }};
+ int rc;
+
+ ble_gap_test_util_init();
+
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ /*** Invalid discoverable mode. */
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.disc_mode = 43;
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ /*** Invalid connectable mode. */
+ adv_params = ble_hs_test_util_adv_params;
+ adv_params.conn_mode = 27;
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ /*** Invalid peer address type with directed advertisable mode. */
+ 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_OWN_ADDR_PUBLIC,
+ &peer_addr_inv, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ TEST_ASSERT(!ble_gap_adv_active());
+
+ /*** Advertising already in progress. */
+ adv_params = ble_hs_test_util_adv_params;
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(ble_gap_adv_active());
+
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, &adv_params, BLE_HS_FOREVER,
+ ble_gap_test_util_connect_cb, NULL, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+ TEST_ASSERT(ble_gap_adv_active());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+ble_gap_test_util_adv_verify_dflt_params(uint8_t own_addr_type,
+ const ble_addr_t *peer_addr,
+ uint8_t conn_mode,
+ uint8_t disc_mode)
+{
+ struct ble_hci_le_set_adv_params_cp hci_cmd;
+ struct ble_gap_adv_params adv_params;
+ 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_OWN_ADDR_PUBLIC, peer_addr,
+ &adv_params, BLE_HS_FOREVER,
+ 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_hci_verify_tx(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.min_interval = get_le16(hci_buf + 0);
+ hci_cmd.max_interval = get_le16(hci_buf + 2);
+ hci_cmd.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.chan_map = hci_buf[13];
+ hci_cmd.filter_policy = hci_buf[14];
+
+ if (conn_mode == BLE_GAP_CONN_MODE_NON) {
+ TEST_ASSERT(hci_cmd.min_interval == BLE_GAP_ADV_FAST_INTERVAL2_MIN);
+ TEST_ASSERT(hci_cmd.max_interval == BLE_GAP_ADV_FAST_INTERVAL2_MAX);
+ } else {
+ TEST_ASSERT(hci_cmd.min_interval == BLE_GAP_ADV_FAST_INTERVAL1_MIN);
+ TEST_ASSERT(hci_cmd.max_interval == 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.type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND);
+ } else {
+ TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
+ }
+ } else if (conn_mode == BLE_GAP_CONN_MODE_UND) {
+ TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_IND);
+ } else {
+ TEST_ASSERT(hci_cmd.type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD);
+ }
+}
+
+TEST_CASE_SELF(ble_gap_test_case_adv_dflt_params)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 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_verify_dflt_params(
+ BLE_OWN_ADDR_PUBLIC, &peer_addr, c, d);
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_adv_good)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 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_OWN_ADDR_PUBLIC,
+ &peer_addr, c, d, BLE_ERR_SUCCESS, -1, 0);
+
+ if (c != BLE_GAP_CONN_MODE_NON) {
+ 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.val,
+ peer_addr.val, 6) == 0);
+ TEST_ASSERT(ble_gap_test_conn_arg == NULL);
+ }
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_adv_ctlr_fail)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+ int d;
+ int 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(BLE_OWN_ADDR_PUBLIC,
+ &peer_addr, c, d, BLE_ERR_DIR_ADV_TMO,
+ -1, 0);
+
+ 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);
+ TEST_ASSERT(ble_gap_test_conn_arg == NULL);
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_adv_hci_fail)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+ int fail_idx;
+ 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++) {
+ for (fail_idx = 0; fail_idx < 4; fail_idx++) {
+ ble_gap_test_util_adv(BLE_OWN_ADDR_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);
+ }
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_adv)
+{
+ 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();
+}
+
+/*****************************************************************************
+ * $stop advertise *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_stop_adv(const ble_addr_t *peer_addr,
+ uint8_t conn_mode, uint8_t disc_mode,
+ int cmd_fail_idx, uint8_t fail_status)
+{
+ uint8_t hci_status;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Start advertising; don't rx a successful connection event. */
+ ble_gap_test_util_adv(BLE_OWN_ADDR_PUBLIC, peer_addr,
+ conn_mode, disc_mode, -1, -1, 0);
+
+ TEST_ASSERT(ble_gap_adv_active());
+
+ /* Stop advertising. */
+ hci_status = cmd_fail_idx == 0 ? fail_status : 0;
+
+ rc = ble_hs_test_util_adv_stop(hci_status);
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(hci_status));
+
+ /* Verify tx of advertising enable command. */
+ ble_gap_test_util_verify_tx_adv_enable(0);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_stop_adv_good)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 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_stop_adv(&peer_addr, c, d, -1, 0);
+ 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);
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_stop_adv_hci_fail)
+{
+ ble_addr_t peer_addr = { BLE_ADDR_PUBLIC, { 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_stop_adv(&peer_addr, c, d,
+ 0, BLE_ERR_UNSUPPORTED);
+ 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);
+ }
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_stop_adv)
+{
+ ble_gap_test_case_stop_adv_good();
+ ble_gap_test_case_stop_adv_hci_fail();
+}
+
+/*****************************************************************************
+ * $update connection *
+ *****************************************************************************/
+
+static void
+ble_gap_test_util_update_verify_params(struct ble_gap_upd_params *params,
+ uint8_t ble_hs_err)
+{
+ int rc;
+
+ 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);
+
+ rc = ble_hs_test_util_conn_update(2, params, 0);
+ TEST_ASSERT(rc == ble_hs_err);
+}
+
+static void
+ble_gap_test_util_update_no_l2cap(struct ble_gap_upd_params *params,
+ int master,
+ uint8_t hci_status, int event_status)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ 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);
+
+ if (!master) {
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+ }
+
+ /* Erase callback info reported during connection establishment; we only
+ * care about updates.
+ */
+ ble_gap_test_util_reset_cb_info();
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ rc = ble_hs_test_util_conn_update(2, params, hci_status);
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(hci_status));
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Verify tx of connection update command. */
+ ble_gap_test_util_verify_tx_update_conn(params);
+
+ if (rc == 0) {
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ /* Attempt two duplicate updates; ensure BLE_HS_EALREADY gets returned
+ * both times. Make sure initial update still completes successfully
+ * (MYNEWT-702).
+ */
+ rc = ble_hs_test_util_conn_update(2, params, 0);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+ rc = ble_hs_test_util_conn_update(2, params, 0);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+
+ /* Receive connection update complete event. */
+ ble_gap_test_util_rx_update_complete(event_status, params);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(event_status));
+ if (event_status == 0) {
+ TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
+ 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 ==
+ params->supervision_timeout);
+ }
+ } else {
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+ }
+}
+
+static void
+ble_gap_test_util_update_l2cap(struct ble_gap_upd_params *params,
+ uint16_t l2cap_result)
+{
+ struct ble_l2cap_sig_update_params l2cap_params;
+ struct ble_hs_conn *conn;
+ uint8_t id;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_conn_feat(2, peer_addr,
+ BLE_HS_TEST_CONN_FEAT_NO_CONN_PARAM,
+ ble_gap_test_util_connect_cb, NULL);
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ /* Erase callback info reported during connection establishment; we only
+ * care about updates.
+ */
+ ble_gap_test_util_reset_cb_info();
+
+ rc = ble_hs_test_util_conn_update(2, params, 0xFF);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ l2cap_params.itvl_min = params->itvl_min;
+ l2cap_params.itvl_max = params->itvl_max;
+ l2cap_params.slave_latency = params->latency;
+ l2cap_params.timeout_multiplier = params->supervision_timeout;
+ id = ble_hs_test_util_verify_tx_l2cap_update_req(&l2cap_params);
+
+ /* Receive l2cap connection parameter update response. */
+ ble_hs_test_util_rx_l2cap_update_rsp(2, id, l2cap_result);
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ if (l2cap_result == BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT) {
+ /* Receive connection update complete event. */
+ ble_gap_test_util_rx_update_complete(0, params);
+ }
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
+ if (l2cap_result != BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT) {
+ TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_EREJECT);
+ } else {
+ TEST_ASSERT(ble_gap_test_conn_status == 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 ==
+ params->supervision_timeout);
+ }
+
+ TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
+ peer_addr, 6) == 0);
+}
+
+static void
+ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
+ uint8_t hci_status, uint8_t event_status,
+ int rx_l2cap)
+{
+ struct ble_l2cap_sig_update_params l2cap_params;
+ struct ble_hs_conn *conn;
+ uint8_t id;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_conn_feat(2, peer_addr,
+ BLE_HS_TEST_CONN_FEAT_NO_CONN_PARAM,
+ ble_gap_test_util_connect_cb, NULL);
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ /* Erase callback info reported during connection establishment; we only
+ * care about updates.
+ */
+ ble_gap_test_util_reset_cb_info();
+
+ rc = ble_hs_test_util_conn_update(2, params, 0xFF);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ if (rx_l2cap) {
+ l2cap_params.itvl_min = params->itvl_min;
+ l2cap_params.itvl_max = params->itvl_max;
+ l2cap_params.slave_latency = params->latency;
+ l2cap_params.timeout_multiplier = params->supervision_timeout;
+ id = ble_hs_test_util_verify_tx_l2cap_update_req(&l2cap_params);
+
+ /* Receive l2cap connection parameter update response. */
+ ble_hs_test_util_rx_l2cap_update_rsp(
+ 2, id, BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+ } else {
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+ }
+
+ /* Ensure no update event reported. */
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+ /* Advance 29 seconds; ensure no timeout reported.
+ * Note: L2CAP signaling timeout is 30 sec, GAP update timeout is 40 sec
+ */
+ os_time_advance(29 * OS_TICKS_PER_SEC);
+ ble_gap_timer();
+ ble_l2cap_sig_timer();
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+ /* Advance 30th second; ensure timeout reported. */
+ os_time_advance(1 * OS_TICKS_PER_SEC);
+
+ /* If L2CAP response has been received, GAP Timer is removed */
+ if (!rx_l2cap) {
+
+ /* Timeout will result in a terminate HCI command being sent; schedule ack
+ * from controller.
+ */
+ ble_hs_test_util_hci_ack_set_disconnect(0);
+
+ ble_gap_timer();
+ ble_l2cap_sig_timer();
+
+ /* Verify terminate was sent. */
+ ble_gap_test_util_verify_tx_disconnect();
+
+ TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
+ TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
+ TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
+ peer_addr, 6) == 0);
+ } else {
+ ble_gap_timer();
+ ble_l2cap_sig_timer();
+
+ TEST_ASSERT(ble_gap_test_event.type == 0xff);
+ }
+}
+
+static void
+ble_gap_test_util_update_peer(uint8_t status,
+ struct ble_gap_upd_params *params)
+{
+ 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);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Receive connection update complete event. */
+ ble_gap_test_util_rx_update_complete(status, params);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ 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.val,
+ peer_addr, 6) == 0);
+
+ if (status == 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 ==
+ params->supervision_timeout);
+ }
+
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+}
+
+static void
+ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
+ struct ble_gap_upd_params *self_params,
+ int cmd_fail_idx, uint8_t hci_status)
+{
+ int cmd_idx;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_init();
+ cmd_idx = 0;
+
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ ble_gap_test_conn_self_params = *self_params;
+ rc = ble_gap_test_util_rx_param_req(peer_params, 1, &cmd_idx, cmd_fail_idx,
+ hci_status);
+ if (rc != 0) {
+ goto hci_fail;
+ }
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* We don't maintain an update entry when the peer initiates. */
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ /* Verify tx of connection parameters reply command. */
+ ble_gap_test_util_verify_tx_params_reply_pos();
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ /* Receive connection update complete event. */
+ ble_gap_test_util_rx_update_complete(0, self_params);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ 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.val,
+ 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 ==
+ self_params->supervision_timeout);
+
+ return;
+
+hci_fail:
+ 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.val,
+ 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 ==
+ BLE_GAP_INITIAL_CONN_LATENCY);
+ TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
+ BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
+}
+
+static void
+ble_gap_test_util_update_req_neg(struct ble_gap_upd_params *peer_params,
+ int cmd_fail_idx, uint8_t hci_status)
+{
+ int cmd_idx;
+ int reason;
+ int rc;
+
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ ble_gap_test_util_init();
+ cmd_idx = 0;
+
+ reason = BLE_ERR_UNSPECIFIED;
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ &reason);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ rc = ble_gap_test_util_rx_param_req(peer_params, 0, &cmd_idx, cmd_fail_idx,
+ hci_status);
+ if (rc != 0) {
+ goto hci_fail;
+ }
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ /* Verify tx of connection parameters negative reply command. */
+ ble_gap_test_util_verify_tx_params_reply_neg(reason);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ return;
+
+hci_fail:
+ 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.val,
+ 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 ==
+ BLE_GAP_INITIAL_CONN_LATENCY);
+ TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
+ BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
+}
+
+static void
+ble_gap_test_util_update_req_concurrent(
+ struct ble_gap_upd_params *init_params,
+ struct ble_gap_upd_params *peer_params,
+ struct ble_gap_upd_params *self_params,
+ int cmd_fail_idx,
+ uint8_t fail_status)
+{
+ uint8_t hci_status;
+ int cmd_idx;
+ int rc;
+
+ 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);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ hci_status = cmd_fail_idx == 0 ? fail_status : 0;
+ rc = ble_hs_test_util_conn_update(2, init_params, hci_status);
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(hci_status));
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Verify tx of connection update command. */
+ ble_gap_test_util_verify_tx_update_conn(init_params);
+
+ if (rc == 0) {
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+ } else {
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+ return;
+ }
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ /* Receive connection parameter update request from peer. */
+ ble_gap_test_conn_self_params = *self_params;
+ rc = ble_gap_test_util_rx_param_req(peer_params, 1, &cmd_idx, cmd_fail_idx,
+ hci_status);
+ if (rc != 0) {
+ goto hci_fail;
+ }
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ /* Verify tx of connection parameters reply command. */
+ ble_gap_test_util_verify_tx_params_reply_pos();
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+ /* Receive connection update complete event. */
+ ble_gap_test_util_rx_update_complete(0, self_params);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+ 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.val,
+ 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 ==
+ self_params->supervision_timeout);
+
+ return;
+
+hci_fail:
+ 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.val,
+ 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 ==
+ BLE_GAP_INITIAL_CONN_LATENCY);
+ TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
+ BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_conn_good)
+{
+ ble_gap_test_util_update_no_l2cap(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ 1, 0, 0);
+
+ ble_gap_test_util_update_no_l2cap(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ 1, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_conn_verify_params)
+{
+ /* GOOD */
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ 0);
+
+ /* BAD */
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 1,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ BLE_HS_EINVAL);
+
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 0x0C80 + 1,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ BLE_HS_EINVAL);
+
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 50,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ BLE_HS_EINVAL);
+
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .latency = 0x01F4,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ BLE_HS_EINVAL);
+
+ ble_gap_test_util_update_verify_params(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 600,
+ .supervision_timeout = 300,
+ .latency = 1,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ BLE_HS_EINVAL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_conn_bad)
+{
+ ble_gap_test_util_update_no_l2cap(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ 1, 0, BLE_ERR_LMP_COLLISION);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_conn_hci_fail)
+{
+ ble_gap_test_util_update_no_l2cap(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ 1, BLE_ERR_UNSUPPORTED, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_conn_l2cap)
+{
+ struct ble_gap_upd_params params = {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ };
+
+ /* Accepted L2CAP. */
+ ble_gap_test_util_update_l2cap(&params,
+ BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+
+ /* Rejected L2CAP. */
+ ble_gap_test_util_update_l2cap(&params,
+ BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_peer_good)
+{
+ ble_gap_test_util_update_peer(0,
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 0,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}));
+
+ ble_gap_test_util_update_peer(0,
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 100,
+ .supervision_timeout = 100,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}));
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_req_good)
+{
+ ble_gap_test_util_update_req_pos(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ -1, 0);
+
+ ble_gap_test_util_update_req_pos(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 100,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 554,
+ .max_ce_len = 554,
+ }}),
+ -1, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_req_hci_fail)
+{
+ ble_gap_test_util_update_req_pos(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ 0, BLE_ERR_UNSUPPORTED);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_req_reject)
+{
+ ble_gap_test_util_update_req_neg(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ -1, 0);
+
+ ble_gap_test_util_update_req_neg(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ -1, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_concurrent_good)
+{
+ ble_gap_test_util_update_req_concurrent(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ -1, 0);
+
+ ble_gap_test_util_update_req_concurrent(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 20,
+ .itvl_max = 200,
+ .supervision_timeout = 350,
+ .min_ce_len = 111,
+ .max_ce_len = 222,
+ }}),
+ -1, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_update_concurrent_hci_fail)
+{
+ ble_gap_test_util_update_req_concurrent(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 20,
+ .itvl_max = 200,
+ .supervision_timeout = 350,
+ .min_ce_len = 111,
+ .max_ce_len = 222,
+ }}),
+ 0, BLE_ERR_UNSUPPORTED);
+
+ ble_gap_test_util_update_req_concurrent(
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 50,
+ .itvl_max = 500,
+ .supervision_timeout = 800,
+ .min_ce_len = 555,
+ .max_ce_len = 888,
+ }}),
+ ((struct ble_gap_upd_params[]) { {
+ .itvl_min = 20,
+ .itvl_max = 200,
+ .supervision_timeout = 350,
+ .min_ce_len = 111,
+ .max_ce_len = 222,
+ }}),
+ 1, BLE_ERR_UNSUPPORTED);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_update_conn)
+{
+ ble_gap_test_case_update_conn_good();
+ ble_gap_test_case_update_conn_bad();
+ ble_gap_test_case_update_conn_hci_fail();
+ ble_gap_test_case_update_conn_l2cap();
+ ble_gap_test_case_update_peer_good();
+ ble_gap_test_case_update_req_good();
+ ble_gap_test_case_update_req_hci_fail();
+ ble_gap_test_case_update_req_reject();
+ ble_gap_test_case_update_concurrent_good();
+ ble_gap_test_case_update_concurrent_hci_fail();
+ ble_gap_test_case_update_conn_verify_params();
+}
+
+/*****************************************************************************
+ * $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_OWN_ADDR_PUBLIC,
+ &((ble_addr_t) { BLE_ADDR_PUBLIC, { 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_timer();
+ 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_timer();
+ 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 ble_gap_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_OWN_ADDR_PUBLIC,
+ &((ble_addr_t) { BLE_ADDR_PUBLIC, { 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_timer();
+ 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_hci_ack_set(
+ 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_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Ensure cancel create connection command was sent. */
+ ble_hs_test_util_hci_verify_tx_create_conn_cancel();
+
+ /* Ensure timer has been stopped. */
+ ticks_from_now = ble_gap_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Receive the connection complete event indicating a successful cancel. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_UNK_CONN_ID;
+ /* test if host correctly ignores other fields if status is error */
+ evt.connection_handle = 0x0fff;
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ 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_OWN_ADDR_PUBLIC,
+ BLE_HS_FOREVER, &params, ble_gap_test_util_disc_cb,
+ NULL, -1, 0);
+
+ /* Ensure no pending GAP event. */
+ ticks_from_now = ble_gap_timer();
+ 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_OWN_ADDR_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_timer();
+ TEST_ASSERT(ticks_from_now == duration_ticks);
+
+ /* Advance duration ms; ensure timeout event was reported. */
+ os_time_advance(duration_ms);
+
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ 0);
+ ticks_from_now = ble_gap_timer();
+ 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_SELF(ble_gap_test_case_update_timeout)
+{
+ struct ble_gap_upd_params params = {
+ .itvl_min = 10,
+ .itvl_max = 100,
+ .supervision_timeout = 200,
+ .min_ce_len = 123,
+ .max_ce_len = 456,
+ };
+
+ /* L2CAP - Local unsupported; L2CAP timeout. */
+ ble_gap_test_util_update_l2cap_tmo(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
+
+ /* L2CAP - Remote unsupported; L2CAP timeout. */
+ ble_gap_test_util_update_l2cap_tmo(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+ 0);
+
+ /* L2CAP - Remote unsupported; LL timeout. */
+ ble_gap_test_util_update_l2cap_tmo(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+ 1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_timeout_conn_forever)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_conn_timeout(30);
+
+ /* No timeout. */
+ ble_gap_test_util_conn_forever();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_timeout_conn_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_conn_timeout(30);
+
+ /* 20 ms. */
+ ble_gap_test_util_conn_timeout(20);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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();
+
+ /* 30 ms. */
+ ble_gap_test_util_conn_timeout(30);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_disc_timeout_disc_forever)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_disc_timeout(30);
+
+ /* No timeout. */
+ ble_gap_test_util_disc_forever();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_disc_timeout_disc_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 30 ms. */
+ ble_gap_test_util_disc_timeout(30);
+
+ /* 20 ms. */
+ ble_gap_test_util_disc_timeout(20);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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);
+
+ /* 30 ms. */
+ ble_gap_test_util_disc_timeout(30);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_conn_timeout_disc_timeout)
+{
+ ble_gap_test_util_init();
+
+ /* 15 seconds. */
+ ble_gap_test_util_conn_timeout(15000);
+
+ /* 1280 ms. */
+ ble_gap_test_util_disc_timeout(1280);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_timeout)
+{
+ 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();
+
+ ble_gap_test_case_update_timeout();
+}
+
+TEST_CASE_SELF(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);
+
+ rc = ble_hs_test_util_rx_att_mtu_cmd(2, 0, 123);
+ TEST_ASSERT_FATAL(rc == 0);
+ 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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_mtu_peer)
+{
+ 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_hs_test_util_rx_att_mtu_cmd(2, 1, 123);
+ TEST_ASSERT_FATAL(rc == 0);
+ 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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_mtu)
+{
+ ble_gap_test_case_mtu_us();
+ ble_gap_test_case_mtu_peer();
+}
+
+/*****************************************************************************
+ * $set cb *
+ *****************************************************************************/
+
+static int
+ble_gap_test_util_set_cb_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_event *event_arg;
+
+ event_arg = arg;
+
+ *event_arg = *event;
+
+ return 0;
+}
+
+TEST_CASE_SELF(ble_gap_test_case_set_cb_good)
+{
+ const uint8_t peer_addr[6] = { 1,2,3,4,5,6 };
+ struct ble_gap_event event;
+ int rc;
+
+ ble_gap_test_util_init();
+
+ ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+ NULL);
+
+ /* Reconfigure the callback. */
+ rc = ble_gap_set_event_cb(2, ble_gap_test_util_set_cb_event, &event);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Terminate the connection and ensure the new callback gets called. */
+ rc = ble_hs_test_util_conn_terminate(2, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_hci_rx_disconn_complete_event(2, 0, BLE_ERR_REM_USER_CONN_TERM);
+
+ TEST_ASSERT(event.type == BLE_GAP_EVENT_DISCONNECT);
+ TEST_ASSERT(event.disconnect.reason ==
+ BLE_HS_HCI_ERR(BLE_ERR_REM_USER_CONN_TERM));
+ TEST_ASSERT(event.disconnect.conn.conn_handle == 2);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gap_test_case_set_cb_bad)
+{
+ int rc;
+
+ ble_gap_test_util_init();
+
+ /* Ensure error is reported when specified connection doesn't exist. */
+ rc = ble_gap_set_event_cb(123, ble_gap_test_util_set_cb_event, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOTCONN);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gap_test_suite_set_cb)
+{
+ ble_gap_test_case_set_cb_good();
+ ble_gap_test_case_set_cb_bad();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_conn_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_conn_test.c
new file mode 100644
index 00000000..8d95f743
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_conn_test.c
@@ -0,0 +1,746 @@
+/*
+ * 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 "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE 0x9383
+#define BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE 0x1234
+
+static uint8_t ble_gatt_conn_test_write_value[] = { 1, 3, 64, 21, 6 };
+
+struct ble_gatt_conn_test_arg {
+ uint16_t exp_conn_handle;
+ int exp_status;
+ int called;
+};
+
+static struct ble_gap_event ble_gatt_conn_test_gap_event;
+
+static void
+ble_gatt_conn_test_util_init(void)
+{
+ ble_hs_test_util_init();
+ memset(&ble_gatt_conn_test_gap_event, -1,
+ sizeof ble_gatt_conn_test_gap_event);
+}
+
+static int
+ble_gatt_conn_test_indicate_cb(struct ble_gap_event *event, void *arg)
+{
+ /* Only record indication failures. */
+ if (event->type == BLE_GAP_EVENT_NOTIFY_TX &&
+ event->notify_tx.status != 0) {
+
+ ble_gatt_conn_test_gap_event = *event;
+ }
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
+ uint8_t op, uint16_t offset, struct os_mbuf **om,
+ void *arg)
+{
+ uint8_t *buf;
+
+ switch (op) {
+ case BLE_ATT_ACCESS_OP_READ:
+ buf = os_mbuf_extend(*om, 1);
+ TEST_ASSERT_FATAL(buf != NULL);
+ *buf = 1;
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+static int
+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_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 == cb_arg->exp_status);
+ TEST_ASSERT(mtu == 0);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_all_svcs_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(service == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_svc_uuid_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(service == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_find_inc_svcs_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(service == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_all_chrs_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(chr == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_chr_uuid_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(chr == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_disc_all_dscs_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ uint16_t chr_val_handle,
+ const struct ble_gatt_dsc *dsc,
+ void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(dsc == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+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_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+static int
+ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr->om == NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+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_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr != NULL);
+ TEST_ASSERT(attr->handle == BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(attr != NULL);
+ TEST_ASSERT(attr->handle == BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+static int
+ble_gatt_conn_test_write_rel_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attrs,
+ uint8_t num_attrs,
+ void *arg)
+{
+ struct ble_gatt_conn_test_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 == cb_arg->exp_status);
+ TEST_ASSERT(attrs != NULL);
+
+ cb_arg->called++;
+
+ return 0;
+}
+
+TEST_CASE_SELF(ble_gatt_conn_test_disconnect)
+{
+ struct ble_gatt_conn_test_arg mtu_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg disc_all_svcs_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg disc_svc_uuid_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg find_inc_svcs_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg disc_all_chrs_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg disc_chr_uuid_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg disc_all_dscs_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg read_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg read_uuid_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg read_long_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg read_mult_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg write_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg write_long_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_conn_test_arg write_rel_arg = { 0, BLE_HS_ENOTCONN };
+ struct ble_gatt_attr attr;
+ uint16_t attr_handle;
+ uint16_t offset = 0;
+ int rc;
+
+ ble_gatt_conn_test_util_init();
+
+ /*** Register an attribute to allow indicatations to be sent. */
+ rc = ble_att_svr_register(BLE_UUID16_DECLARE(0x1212), BLE_ATT_F_READ, 0,
+ &attr_handle,
+ ble_gatt_conn_test_attr_cb, NULL);
+ TEST_ASSERT(rc == 0);
+
+ /* Create three connections. */
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){1,2,3,4,5,6,7,8}),
+ ble_gatt_conn_test_indicate_cb, NULL);
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ ble_gatt_conn_test_indicate_cb, NULL);
+ ble_hs_test_util_create_conn(3, ((uint8_t[]){3,4,5,6,7,8,9,10}),
+ ble_gatt_conn_test_indicate_cb, NULL);
+
+ /*** Schedule some GATT procedures. */
+ /* Connection 1. */
+ mtu_arg.exp_conn_handle = 1;
+ ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, &mtu_arg);
+
+ disc_all_svcs_arg.exp_conn_handle = 1;
+ rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb,
+ &disc_all_svcs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ disc_svc_uuid_arg.exp_conn_handle = 1;
+ rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16_DECLARE(0x1111),
+ ble_gatt_conn_test_disc_svc_uuid_cb,
+ &disc_svc_uuid_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ find_inc_svcs_arg.exp_conn_handle = 1;
+ rc = ble_gattc_find_inc_svcs(1, 1, 0xffff,
+ ble_gatt_conn_test_find_inc_svcs_cb,
+ &find_inc_svcs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ disc_all_chrs_arg.exp_conn_handle = 1;
+ rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
+ ble_gatt_conn_test_disc_all_chrs_cb,
+ &disc_all_chrs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Connection 2. */
+ disc_all_dscs_arg.exp_conn_handle = 2;
+ 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, 2, 0xffff, BLE_UUID16_DECLARE(0x2222),
+ ble_gatt_conn_test_disc_chr_uuid_cb,
+ &disc_chr_uuid_arg);
+
+ read_arg.exp_conn_handle = 2;
+ rc = ble_gattc_read(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+ ble_gatt_conn_test_read_cb, &read_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ read_uuid_arg.exp_conn_handle = 2;
+ rc = ble_gattc_read_by_uuid(2, 1, 0xffff, BLE_UUID16_DECLARE(0x3333),
+ ble_gatt_conn_test_read_uuid_cb,
+ &read_uuid_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ read_long_arg.exp_conn_handle = 2;
+ rc = ble_gattc_read_long(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, offset,
+ ble_gatt_conn_test_read_long_cb, &read_long_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Connection 3. */
+ read_mult_arg.exp_conn_handle = 3;
+ rc = ble_gattc_read_mult(3, ((uint16_t[3]){5,6,7}), 3,
+ ble_gatt_conn_test_read_mult_cb, &read_mult_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ write_arg.exp_conn_handle = 3;
+ 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_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, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_gattc_indicate(3, attr_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /*** Start the procedures. */
+
+ /*** Break the connections; verify proper callbacks got called. */
+ /* Connection 1. */
+ ble_gattc_connection_broken(1);
+ TEST_ASSERT(mtu_arg.called == 1);
+ TEST_ASSERT(disc_all_svcs_arg.called == 1);
+ TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+ TEST_ASSERT(find_inc_svcs_arg.called == 1);
+ TEST_ASSERT(disc_all_chrs_arg.called == 1);
+ TEST_ASSERT(disc_chr_uuid_arg.called == 0);
+ TEST_ASSERT(disc_all_dscs_arg.called == 0);
+ TEST_ASSERT(read_arg.called == 0);
+ TEST_ASSERT(read_uuid_arg.called == 0);
+ TEST_ASSERT(read_long_arg.called == 0);
+ TEST_ASSERT(read_mult_arg.called == 0);
+ TEST_ASSERT(write_arg.called == 0);
+ TEST_ASSERT(write_long_arg.called == 0);
+ TEST_ASSERT(write_rel_arg.called == 0);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255);
+
+ /* Connection 2. */
+ ble_gattc_connection_broken(2);
+ TEST_ASSERT(mtu_arg.called == 1);
+ TEST_ASSERT(disc_all_svcs_arg.called == 1);
+ TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+ TEST_ASSERT(find_inc_svcs_arg.called == 1);
+ TEST_ASSERT(disc_all_chrs_arg.called == 1);
+ TEST_ASSERT(disc_chr_uuid_arg.called == 1);
+ TEST_ASSERT(disc_all_dscs_arg.called == 1);
+ TEST_ASSERT(read_arg.called == 1);
+ TEST_ASSERT(read_uuid_arg.called == 1);
+ TEST_ASSERT(read_long_arg.called == 1);
+ TEST_ASSERT(read_mult_arg.called == 0);
+ TEST_ASSERT(write_arg.called == 0);
+ TEST_ASSERT(write_long_arg.called == 0);
+ TEST_ASSERT(write_rel_arg.called == 0);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255);
+
+ /* Connection 3. */
+ ble_gattc_connection_broken(3);
+ TEST_ASSERT(mtu_arg.called == 1);
+ TEST_ASSERT(disc_all_svcs_arg.called == 1);
+ TEST_ASSERT(disc_svc_uuid_arg.called == 1);
+ TEST_ASSERT(find_inc_svcs_arg.called == 1);
+ TEST_ASSERT(disc_all_chrs_arg.called == 1);
+ TEST_ASSERT(disc_chr_uuid_arg.called == 1);
+ TEST_ASSERT(disc_all_dscs_arg.called == 1);
+ TEST_ASSERT(read_arg.called == 1);
+ TEST_ASSERT(read_uuid_arg.called == 1);
+ TEST_ASSERT(read_long_arg.called == 1);
+ TEST_ASSERT(read_mult_arg.called == 1);
+ TEST_ASSERT(write_arg.called == 1);
+ TEST_ASSERT(write_long_arg.called == 1);
+ TEST_ASSERT(write_rel_arg.called == 1);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.type == BLE_GAP_EVENT_NOTIFY_TX);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.status ==
+ BLE_HS_ENOTCONN);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.conn_handle == 3);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.attr_handle ==
+ attr_handle);
+ TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.indication);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+ble_gatt_conn_test_util_timeout(uint16_t conn_handle,
+ struct ble_gatt_conn_test_arg *arg)
+{
+ int32_t ticks_from_now;
+
+ ticks_from_now = ble_gattc_timer();
+ TEST_ASSERT(ticks_from_now == 30 * OS_TICKS_PER_SEC);
+
+ os_time_advance(29 * OS_TICKS_PER_SEC);
+ ticks_from_now = ble_gattc_timer();
+ TEST_ASSERT(ticks_from_now == 1 * OS_TICKS_PER_SEC);
+
+ ble_hs_test_util_hci_ack_set_disconnect(0);
+ os_time_advance(1 * OS_TICKS_PER_SEC);
+ ticks_from_now = ble_gattc_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Ensure connection was terminated due to proecedure timeout. */
+ ble_hs_test_util_hci_rx_disconn_complete_event(conn_handle, 0,
+ BLE_ERR_REM_USER_CONN_TERM);
+
+ /* Ensure GATT callback was called with timeout status. */
+ if (arg != NULL) {
+ TEST_ASSERT(arg->called == 1);
+ }
+}
+
+TEST_CASE_SELF(ble_gatt_conn_test_timeout)
+{
+ static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+ struct ble_gatt_conn_test_arg mtu_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg disc_all_svcs_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg disc_svc_uuid_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg find_inc_svcs_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg disc_all_chrs_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg disc_chr_uuid_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg disc_all_dscs_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg read_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg read_uuid_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg read_long_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg read_mult_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg write_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg write_long_arg = { 1, BLE_HS_ETIMEOUT };
+ struct ble_gatt_conn_test_arg write_rel_arg = { 1, BLE_HS_ETIMEOUT };
+
+ struct ble_gatt_attr attr;
+ int32_t ticks_from_now;
+ uint16_t attr_handle;
+ uint16_t offset = 0;
+ int rc;
+
+ ble_gatt_conn_test_util_init();
+
+ ticks_from_now = ble_gattc_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /*** Register an attribute to allow indicatations to be sent. */
+ rc = ble_att_svr_register(BLE_UUID16_DECLARE(0x1212), BLE_ATT_F_READ, 0,
+ &attr_handle,
+ ble_gatt_conn_test_attr_cb, NULL);
+ TEST_ASSERT(rc == 0);
+
+ /*** MTU. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, &mtu_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &mtu_arg);
+
+ /*** Discover all services. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb,
+ &disc_all_svcs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &disc_all_svcs_arg);
+
+ /*** Discover services by UUID. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16_DECLARE(0x1111),
+ ble_gatt_conn_test_disc_svc_uuid_cb,
+ &disc_svc_uuid_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &disc_svc_uuid_arg);
+
+ /*** Find included services. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_find_inc_svcs(1, 1, 0xffff,
+ ble_gatt_conn_test_find_inc_svcs_cb,
+ &find_inc_svcs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &find_inc_svcs_arg);
+
+ /*** Discover all characteristics. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
+ ble_gatt_conn_test_disc_all_chrs_cb,
+ &disc_all_chrs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &disc_all_chrs_arg);
+
+ /*** Discover all descriptors. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_disc_all_dscs(1, 3, 0xffff,
+ ble_gatt_conn_test_disc_all_dscs_cb,
+ &disc_chr_uuid_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &disc_chr_uuid_arg);
+
+ /*** Discover characteristics by UUID. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_disc_chrs_by_uuid(1, 2, 0xffff, BLE_UUID16_DECLARE(0x2222),
+ ble_gatt_conn_test_disc_chr_uuid_cb,
+ &disc_all_dscs_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &disc_all_dscs_arg);
+
+ /*** Read. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_read(1, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+ ble_gatt_conn_test_read_cb, &read_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &read_arg);
+
+ /*** Read by UUID. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_read_by_uuid(1, 1, 0xffff, BLE_UUID16_DECLARE(0x3333),
+ ble_gatt_conn_test_read_uuid_cb,
+ &read_uuid_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &read_uuid_arg);
+
+ /*** Read long. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_read_long(1, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, offset,
+ ble_gatt_conn_test_read_long_cb,
+ &read_long_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &read_long_arg);
+
+ /*** Read multiple. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_read_mult(1, ((uint16_t[3]){5,6,7}), 3,
+ ble_gatt_conn_test_read_mult_cb,
+ &read_mult_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &read_mult_arg);
+
+ /*** Write. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_hs_test_util_gatt_write_flat(
+ 1, 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);
+ ble_gatt_conn_test_util_timeout(1, &write_arg);
+
+ /*** Write long. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 1, 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);
+ ble_gatt_conn_test_util_timeout(1, &write_long_arg);
+
+ /*** Write reliable. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ attr.handle = 8;
+ attr.offset = 0;
+ attr.om = os_msys_get_pkthdr(0, 0);
+ rc = ble_gattc_write_reliable(
+ 1, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, &write_rel_arg);
+
+ /*** Indication. */
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+ rc = ble_gattc_indicate(1, attr_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_gatt_conn_test_util_timeout(1, NULL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_conn_suite)
+{
+ ble_gatt_conn_test_disconnect();
+ ble_gatt_conn_test_timeout();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_c_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_c_test.c
new file mode 100644
index 00000000..e19db341
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_c_test.c
@@ -0,0 +1,722 @@
+/*
+ * 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 <limits.h>
+#include "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_gatt.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+struct ble_gatt_disc_c_test_char {
+ uint16_t def_handle;
+ uint16_t val_handle;
+ uint8_t properties;
+ const ble_uuid_t *uuid;
+};
+
+#define BLE_GATT_DISC_C_TEST_MAX_CHARS 256
+static struct ble_gatt_chr
+ ble_gatt_disc_c_test_chars[BLE_GATT_DISC_C_TEST_MAX_CHARS];
+static int ble_gatt_disc_c_test_num_chars;
+static int ble_gatt_disc_c_test_rx_complete;
+
+static void
+ble_gatt_disc_c_test_init(void)
+{
+ ble_hs_test_util_init();
+
+ ble_gatt_disc_c_test_num_chars = 0;
+ ble_gatt_disc_c_test_rx_complete = 0;
+}
+
+static int
+ble_gatt_disc_c_test_misc_rx_rsp_once(
+ uint16_t conn_handle, struct ble_gatt_disc_c_test_char *chars)
+{
+ struct ble_att_read_type_rsp rsp;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ /* Send the pending ATT Read By Type Request. */
+
+ if (chars[0].uuid->type == BLE_UUID_TYPE_16) {
+ rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
+ BLE_GATT_CHR_DECL_SZ_16;
+ } else {
+ rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
+ BLE_GATT_CHR_DECL_SZ_128;
+ }
+
+ ble_att_read_type_rsp_write(buf, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp);
+
+ off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
+ for (i = 0; ; i++) {
+ if (chars[i].def_handle == 0) {
+ /* No more services. */
+ break;
+ }
+
+ /* If the value length is changing, we need a separate response. */
+ if (((chars[i].uuid->type == BLE_UUID_TYPE_16) ^
+ (chars[0].uuid->type == BLE_UUID_TYPE_16)) != 0) {
+ break;
+ }
+
+ if (chars[i].uuid->type == BLE_UUID_TYPE_16) {
+ if (off + BLE_ATT_READ_TYPE_ADATA_SZ_16 >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ } else {
+ if (off + BLE_ATT_READ_TYPE_ADATA_SZ_128 >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ }
+
+ put_le16(buf + off, chars[i].def_handle);
+ off += 2;
+
+ buf[off] = chars[i].properties;
+ off++;
+
+ put_le16(buf + off, chars[i].val_handle);
+ off += 2;
+
+ ble_uuid_flat(chars[i].uuid, buf + off);
+ off += ble_uuid_length(chars[i].uuid);
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle,
+ uint16_t end_handle,
+ struct ble_gatt_disc_c_test_char *chars)
+{
+ int count;
+ int idx;
+
+ idx = 0;
+ while (chars[idx].def_handle != 0) {
+ count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle,
+ chars + idx);
+ if (count == 0) {
+ break;
+ }
+ idx += count;
+ }
+
+ if (chars[idx - 1].def_handle != end_handle) {
+ /* Send the pending ATT Request. */
+ ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ chars[idx - 1].def_handle);
+ }
+}
+
+static void
+ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char *chars,
+ int stop_after)
+{
+ int i;
+
+ if (stop_after == 0) {
+ stop_after = BLE_GATT_DISC_C_TEST_MAX_CHARS;
+ }
+
+ for (i = 0; i < stop_after && chars[i].def_handle != 0; i++) {
+ TEST_ASSERT(chars[i].def_handle ==
+ ble_gatt_disc_c_test_chars[i].def_handle);
+ TEST_ASSERT(chars[i].val_handle ==
+ ble_gatt_disc_c_test_chars[i].val_handle);
+ TEST_ASSERT(ble_uuid_cmp(chars[i].uuid,
+ &ble_gatt_disc_c_test_chars[i].uuid.u) == 0);
+ }
+
+ TEST_ASSERT(i == ble_gatt_disc_c_test_num_chars);
+ TEST_ASSERT(ble_gatt_disc_c_test_rx_complete);
+}
+
+static int
+ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle,
+ 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(!ble_gatt_disc_c_test_rx_complete);
+
+ stop_after = arg;
+
+ 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) {
+ (*stop_after)--;
+ if (*stop_after == 0) {
+ ble_gatt_disc_c_test_rx_complete = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+ble_gatt_disc_c_test_misc_all(uint16_t start_handle, uint16_t end_handle,
+ int stop_after,
+ struct ble_gatt_disc_c_test_char *chars)
+{
+ int num_left;
+ int rc;
+
+ ble_gatt_disc_c_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ num_left = stop_after;
+ rc = ble_gattc_disc_all_chrs(2, start_handle, end_handle,
+ ble_gatt_disc_c_test_misc_cb, &num_left);
+ TEST_ASSERT(rc == 0);
+
+ ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, chars);
+ ble_gatt_disc_c_test_misc_verify_chars(chars, stop_after);
+}
+
+static void
+ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle, uint16_t end_handle,
+ int stop_after, const ble_uuid_t *uuid,
+ struct ble_gatt_disc_c_test_char *rsp_chars,
+ struct ble_gatt_disc_c_test_char *ret_chars)
+{
+ int rc;
+
+ ble_gatt_disc_c_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ rc = ble_gattc_disc_chrs_by_uuid(2, start_handle, end_handle,
+ uuid,
+ ble_gatt_disc_c_test_misc_cb,
+ &stop_after);
+ TEST_ASSERT(rc == 0);
+
+ ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, rsp_chars);
+ ble_gatt_disc_c_test_misc_verify_chars(ret_chars, 0);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_c_test_disc_all)
+{
+ /*** One 16-bit characteristic. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 0,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, { 0 }
+ });
+
+ /*** Two 16-bit characteristics. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 0,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 57,
+ .val_handle = 58,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, { 0 }
+ });
+
+ /*** Five 16-bit characteristics. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 0,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 57,
+ .val_handle = 58,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, {
+ .def_handle = 59,
+ .val_handle = 60,
+ .uuid = BLE_UUID16_DECLARE(0x5372),
+ }, {
+ .def_handle = 61,
+ .val_handle = 62,
+ .uuid = BLE_UUID16_DECLARE(0xab93),
+ }, {
+ .def_handle = 63,
+ .val_handle = 64,
+ .uuid = BLE_UUID16_DECLARE(0x0023),
+ }, { 0 }
+ });
+
+ /*** Interleaved 16-bit and 128-bit characteristics. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 0,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 83,
+ .val_handle = 84,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 87,
+ .val_handle = 88,
+ .uuid = BLE_UUID128_DECLARE(0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15),
+ }, {
+ .def_handle = 91,
+ .val_handle = 92,
+ .uuid = BLE_UUID16_DECLARE(0x0003),
+ }, {
+ .def_handle = 93,
+ .val_handle = 94,
+ .uuid = BLE_UUID128_DECLARE(1, 0, 4, 0, 6, 9, 17, 7,
+ 8, 43, 7, 4, 12, 43, 19, 35),
+ }, {
+ .def_handle = 98,
+ .val_handle = 99,
+ .uuid = BLE_UUID16_DECLARE(0xabfa),
+ }, { 0 }
+ });
+
+ /*** Ends with final handle ID. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 0,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 99,
+ .val_handle = 100,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, { 0 }
+ });
+
+ /*** Stop after two characteristics. */
+ ble_gatt_disc_c_test_misc_all(50, 100, 2,
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 57,
+ .val_handle = 58,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, {
+ .def_handle = 59,
+ .val_handle = 60,
+ .uuid = BLE_UUID16_DECLARE(0x5372),
+ }, {
+ .def_handle = 61,
+ .val_handle = 62,
+ .uuid = BLE_UUID16_DECLARE(0xab93),
+ }, {
+ .def_handle = 63,
+ .val_handle = 64,
+ .uuid = BLE_UUID16_DECLARE(0x0023),
+ }, { 0 }
+ });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_c_test_disc_uuid)
+{
+ /*** One 16-bit characteristic. */
+ ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, { 0 } }
+ );
+
+ /*** No matching characteristics. */
+ ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ { 0 } }
+ );
+
+ /*** 2/5 16-bit characteristics. */
+ ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 57,
+ .val_handle = 58,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, {
+ .def_handle = 59,
+ .val_handle = 60,
+ .uuid = BLE_UUID16_DECLARE(0x5372),
+ }, {
+ .def_handle = 61,
+ .val_handle = 62,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 63,
+ .val_handle = 64,
+ .uuid = BLE_UUID16_DECLARE(0x0023),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 61,
+ .val_handle = 62,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, { 0 } }
+ );
+
+ /*** Interleaved 16-bit and 128-bit characteristics. */
+ ble_gatt_disc_c_test_misc_uuid(
+ 50, 100, 0,
+ BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 83,
+ .val_handle = 84,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 87,
+ .val_handle = 88,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .def_handle = 91,
+ .val_handle = 92,
+ .uuid = BLE_UUID16_DECLARE(0x0003),
+ }, {
+ .def_handle = 93,
+ .val_handle = 94,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .def_handle = 98,
+ .val_handle = 99,
+ .uuid = BLE_UUID16_DECLARE(0xabfa),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 87,
+ .val_handle = 88,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .def_handle = 93,
+ .val_handle = 94,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, { 0 } }
+ );
+
+ /*** Ends with final handle ID. */
+ ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x64ba),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 99,
+ .val_handle = 100,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 99,
+ .val_handle = 100,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, { 0 } }
+ );
+
+ /*** Stop after first characteristic. */
+ ble_gatt_disc_c_test_misc_uuid(50, 100, 1, BLE_UUID16_DECLARE(0x2010),
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 57,
+ .val_handle = 58,
+ .uuid = BLE_UUID16_DECLARE(0x64ba),
+ }, {
+ .def_handle = 59,
+ .val_handle = 60,
+ .uuid = BLE_UUID16_DECLARE(0x5372),
+ }, {
+ .def_handle = 61,
+ .val_handle = 62,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, {
+ .def_handle = 63,
+ .val_handle = 64,
+ .uuid = BLE_UUID16_DECLARE(0x0023),
+ }, { 0 } },
+ (struct ble_gatt_disc_c_test_char[]) {
+ {
+ .def_handle = 55,
+ .val_handle = 56,
+ .uuid = BLE_UUID16_DECLARE(0x2010),
+ }, { 0 } }
+ );
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all)
+{
+ /* Retrieve enough characteristics to require two transactions. */
+ struct ble_gatt_disc_c_test_char chrs[] = {
+ {
+ .def_handle = 93,
+ .val_handle = 94,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ },
+ {
+ .def_handle = 95,
+ .val_handle = 96,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ },
+ { 0 }
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int stop_after;
+ int num_chrs;
+ int rc;
+
+ ble_gatt_disc_c_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all characteristics procedure. */
+ stop_after = 0;
+ rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
+ ble_gatt_disc_c_test_misc_cb, &stop_after);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs);
+
+ /* Make sure there are still undiscovered characteristics. */
+ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+ ble_gatt_disc_c_test_misc_verify_chars(chrs, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid)
+{
+ /* Retrieve enough characteristics to require two transactions. */
+ struct ble_gatt_disc_c_test_char chrs[] = {
+ {
+ .def_handle = 93,
+ .val_handle = 94,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ },
+ {
+ .def_handle = 95,
+ .val_handle = 96,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ },
+ { 0 }
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int stop_after;
+ int num_chrs;
+ int rc;
+
+ ble_gatt_disc_c_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover characteristics by UUID procedure. */
+ stop_after = 0;
+ rc = ble_gattc_disc_chrs_by_uuid(1, 1, 0xffff, chrs[0].uuid,
+ ble_gatt_disc_c_test_misc_cb,
+ &stop_after);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs);
+
+ /* Make sure there are still undiscovered characteristics. */
+ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+ ble_gatt_disc_c_test_misc_verify_chars(chrs, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_disc_c_test_suite)
+{
+ ble_gatt_disc_c_test_disc_all();
+ ble_gatt_disc_c_test_disc_uuid();
+ ble_gatt_disc_c_test_oom_all();
+ ble_gatt_disc_c_test_oom_uuid();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_d_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_d_test.c
new file mode 100644
index 00000000..e405c86f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_d_test.c
@@ -0,0 +1,446 @@
+/*
+ * 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 <limits.h>
+#include "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_gatt.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+struct ble_gatt_disc_d_test_dsc {
+ uint16_t chr_val_handle; /* 0 if last entry. */
+ uint16_t dsc_handle;
+ ble_uuid_any_t dsc_uuid;
+};
+
+#define BLE_GATT_DISC_D_TEST_MAX_DSCS 256
+static struct ble_gatt_disc_d_test_dsc
+ ble_gatt_disc_d_test_dscs[BLE_GATT_DISC_D_TEST_MAX_DSCS];
+static int ble_gatt_disc_d_test_num_dscs;
+static int ble_gatt_disc_d_test_rx_complete;
+
+static void
+ble_gatt_disc_d_test_init(void)
+{
+ ble_hs_test_util_init();
+
+ ble_gatt_disc_d_test_num_dscs = 0;
+ ble_gatt_disc_d_test_rx_complete = 0;
+}
+
+static int
+ble_gatt_disc_d_test_misc_rx_rsp_once(
+ uint16_t conn_handle, struct ble_gatt_disc_d_test_dsc *dscs)
+{
+ struct ble_att_find_info_rsp rsp;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ /* Send the pending ATT Read By Type Request. */
+
+ if (dscs[0].dsc_uuid.u.type == BLE_UUID_TYPE_16) {
+ rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+ } else {
+ rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT;
+ }
+
+ ble_att_find_info_rsp_write(buf, BLE_ATT_FIND_INFO_RSP_BASE_SZ, &rsp);
+
+ off = BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+ for (i = 0; ; i++) {
+ if (dscs[i].chr_val_handle == 0) {
+ /* No more descriptors. */
+ break;
+ }
+
+ if (dscs[i].dsc_uuid.u.type == BLE_UUID_TYPE_16) {
+ if (off + BLE_ATT_FIND_INFO_IDATA_16_SZ >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ } else {
+ if (off + BLE_ATT_FIND_INFO_IDATA_128_SZ >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ }
+
+ /* If the value length is changing, we need a separate response. */
+ if (((dscs[0].dsc_uuid.u.type == BLE_UUID_TYPE_16) ^
+ (dscs[i].dsc_uuid.u.type == BLE_UUID_TYPE_16)) != 0) {
+ break;
+ }
+
+ put_le16(buf + off, dscs[i].dsc_handle);
+ off += 2;
+
+ ble_uuid_flat(&dscs[i].dsc_uuid.u, buf + off);
+ off += ble_uuid_length(&dscs[i].dsc_uuid.u);
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle,
+ uint16_t end_handle,
+ struct ble_gatt_disc_d_test_dsc *dscs)
+{
+ int count;
+ int idx;
+
+ idx = 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;
+ }
+ idx += count;
+ }
+
+ if (dscs[idx - 1].dsc_handle != end_handle) {
+ /* Send the pending ATT Request. */
+ ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_FIND_INFO_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ end_handle);
+ }
+}
+
+static void
+ble_gatt_disc_d_test_misc_verify_dscs(struct ble_gatt_disc_d_test_dsc *dscs,
+ int stop_after)
+{
+ int i;
+
+ if (stop_after == 0) {
+ stop_after = BLE_GATT_DISC_D_TEST_MAX_DSCS;
+ }
+
+ 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(ble_uuid_cmp(&dscs[i].dsc_uuid.u,
+ &ble_gatt_disc_d_test_dscs[i].dsc_uuid.u) == 0);
+ }
+
+ TEST_ASSERT(i == ble_gatt_disc_d_test_num_dscs);
+ TEST_ASSERT(ble_gatt_disc_d_test_rx_complete);
+}
+
+static int
+ble_gatt_disc_d_test_misc_cb(uint16_t conn_handle,
+ 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(!ble_gatt_disc_d_test_rx_complete);
+
+ stop_after = arg;
+
+ 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_val_handle = chr_val_handle;
+ dst->dsc_handle = dsc->handle;
+ dst->dsc_uuid = dsc->uuid;
+ break;
+
+ case BLE_HS_EDONE:
+ ble_gatt_disc_d_test_rx_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+
+ if (*stop_after > 0) {
+ (*stop_after)--;
+ if (*stop_after == 0) {
+ ble_gatt_disc_d_test_rx_complete = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+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)
+{
+ int num_left;
+ int rc;
+
+ ble_gatt_disc_d_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ num_left = stop_after;
+ 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);
+
+ ble_gatt_disc_d_test_misc_rx_rsp(2, end_handle, dscs);
+ ble_gatt_disc_d_test_misc_verify_dscs(dscs, stop_after);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_d_test_1)
+{
+ /*** One 16-bit descriptor. */
+ ble_gatt_disc_d_test_misc_all(5, 10, 0,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 5,
+ .dsc_handle = 6,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1234),
+ }, {
+ 0
+ } })
+ );
+
+ /*** Two 16-bit descriptors. */
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 50,
+ .dsc_handle = 51,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1111),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 52,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x2222),
+ }, {
+ 0
+ } })
+ );
+
+ /*** Five 16-bit descriptors. */
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 50,
+ .dsc_handle = 51,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1111),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 52,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x2222),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 53,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x3333),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 54,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x4444),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 55,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x5555),
+ }, {
+ 0
+ } })
+ );
+
+ /*** Interleaved 16-bit and 128-bit descriptors. */
+ ble_gatt_disc_d_test_misc_all(50, 100, 0,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 50,
+ .dsc_handle = 51,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1111),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 52,
+ .dsc_uuid.u128 = BLE_UUID128_INIT( 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 53,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x3333),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 54,
+ .dsc_uuid.u128 = BLE_UUID128_INIT(1,0,4,0,6,9,17,7,8,43,7,4,12,43,19,35),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 55,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x5555),
+ }, {
+ 0
+ } })
+ );
+
+ /*** Ends with final handle ID. */
+ ble_gatt_disc_d_test_misc_all(50, 52, 0,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 50,
+ .dsc_handle = 51,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1111),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 52,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x2222),
+ }, {
+ 0
+ } })
+ );
+
+ /*** Stop after two descriptors. */
+ ble_gatt_disc_d_test_misc_all(50, 100, 2,
+ ((struct ble_gatt_disc_d_test_dsc[]) { {
+ .chr_val_handle = 50,
+ .dsc_handle = 51,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x1111),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 52,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x2222),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 53,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x3333),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 54,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x4444),
+ }, {
+ .chr_val_handle = 50,
+ .dsc_handle = 55,
+ .dsc_uuid.u16 = BLE_UUID16_INIT(0x5555),
+ }, {
+ 0
+ } })
+ );
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all)
+{
+ struct ble_gatt_disc_d_test_dsc dscs[] = {
+ {
+ .chr_val_handle = 543,
+ .dsc_handle = 548,
+ .dsc_uuid.u128 = BLE_UUID128_INIT(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ },
+ {
+ .chr_val_handle = 543,
+ .dsc_handle = 549,
+ .dsc_uuid.u128 = BLE_UUID128_INIT(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ },
+ { 0 }
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int stop_after;
+ int num_dscs;
+ int rc;
+
+ ble_gatt_disc_d_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all characteristics procedure. */
+ stop_after = 0;
+ rc = ble_gattc_disc_all_dscs(1, 543, 560,
+ ble_gatt_disc_d_test_misc_cb, &stop_after);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ num_dscs = ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs);
+
+ /* Make sure there are still undiscovered services. */
+ TEST_ASSERT_FATAL(num_dscs < sizeof dscs / sizeof dscs[0] - 1);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs + num_dscs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure succeeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+ ble_gatt_disc_d_test_misc_verify_dscs(dscs, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_disc_d_test_suite)
+{
+ ble_gatt_disc_d_test_1();
+ ble_gatt_disc_d_test_oom_all();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_s_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_s_test.c
new file mode 100644
index 00000000..3e7a3026
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_disc_s_test.c
@@ -0,0 +1,631 @@
+/*
+ * 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 "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+struct ble_gatt_disc_s_test_svc {
+ uint16_t start_handle;
+ uint16_t end_handle;
+ const ble_uuid_t *uuid;
+};
+
+#define BLE_GATT_DISC_S_TEST_MAX_SERVICES 256
+static struct ble_gatt_svc
+ ble_gatt_disc_s_test_svcs[BLE_GATT_DISC_S_TEST_MAX_SERVICES];
+static int ble_gatt_disc_s_test_num_svcs;
+static int ble_gatt_disc_s_test_rx_complete;
+
+static void
+ble_gatt_disc_s_test_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gatt_disc_s_test_num_svcs = 0;
+ ble_gatt_disc_s_test_rx_complete = 0;
+}
+
+static int
+ble_gatt_disc_s_test_misc_svc_length(struct ble_gatt_disc_s_test_svc *service)
+{
+ if (service->uuid->type == BLE_UUID_TYPE_16) {
+ return 6;
+ } else {
+ return 20;
+ }
+}
+
+static int
+ble_gatt_disc_s_test_misc_rx_all_rsp_once(
+ uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services)
+{
+ struct ble_att_read_group_type_rsp rsp;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ /* Send the pending ATT Read By Group Type Request. */
+
+ rsp.bagp_length = ble_gatt_disc_s_test_misc_svc_length(services);
+ ble_att_read_group_type_rsp_write(buf, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ,
+ &rsp);
+
+ off = BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ;
+ for (i = 0; ; i++) {
+ if (services[i].start_handle == 0) {
+ /* No more services. */
+ break;
+ }
+
+ rc = ble_gatt_disc_s_test_misc_svc_length(services + i);
+ if (rc != rsp.bagp_length) {
+ /* UUID length is changing; Need a separate response. */
+ break;
+ }
+
+ if (services[i].uuid->type == BLE_UUID_TYPE_16) {
+ if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16 >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ } else {
+ if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128 >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+ }
+
+ put_le16(buf + off, services[i].start_handle);
+ off += 2;
+
+ put_le16(buf + off, services[i].end_handle);
+ off += 2;
+
+ ble_uuid_flat(services[i].uuid, buf + off);
+ off += ble_uuid_length(services[i].uuid);
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_disc_s_test_misc_rx_all_rsp(
+ uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services)
+{
+ int count;
+ int idx;
+
+ idx = 0;
+ while (services[idx].start_handle != 0) {
+ count = ble_gatt_disc_s_test_misc_rx_all_rsp_once(conn_handle,
+ services + idx);
+ idx += count;
+ }
+
+ if (services[idx - 1].end_handle != 0xffff) {
+ /* Send the pending ATT Request. */
+ ble_hs_test_util_rx_att_err_rsp(conn_handle,
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ services[idx - 1].start_handle);
+ }
+}
+
+static int
+ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(
+ uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services)
+{
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ /* Send the pending ATT Find By Type Value Request. */
+
+ buf[0] = BLE_ATT_OP_FIND_TYPE_VALUE_RSP;
+ off = BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ;
+ for (i = 0; ; i++) {
+ if (services[i].start_handle == 0) {
+ /* No more services. */
+ break;
+ }
+
+ if (off + BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ >
+ ble_att_mtu(conn_handle)) {
+
+ /* Can't fit any more entries. */
+ break;
+ }
+
+ put_le16(buf + off, services[i].start_handle);
+ off += 2;
+
+ put_le16(buf + off, services[i].end_handle);
+ off += 2;
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_disc_s_test_misc_rx_uuid_rsp(
+ uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services)
+{
+ int count;
+ int idx;
+
+ idx = 0;
+ while (services[idx].start_handle != 0) {
+ count = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(conn_handle,
+ services + idx);
+ idx += count;
+ }
+
+ if (services[idx - 1].end_handle != 0xffff) {
+ /* Send the pending ATT Request. */
+ ble_hs_test_util_rx_att_err_rsp(conn_handle,
+ BLE_ATT_OP_FIND_TYPE_VALUE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ services[idx - 1].start_handle);
+ }
+}
+
+static void
+ble_gatt_disc_s_test_misc_verify_services(
+ struct ble_gatt_disc_s_test_svc *services)
+{
+ int i;
+
+ for (i = 0; services[i].start_handle != 0; i++) {
+ TEST_ASSERT(services[i].start_handle ==
+ ble_gatt_disc_s_test_svcs[i].start_handle);
+ TEST_ASSERT(services[i].end_handle ==
+ ble_gatt_disc_s_test_svcs[i].end_handle);
+
+ TEST_ASSERT(ble_uuid_cmp(services[i].uuid,
+ &ble_gatt_disc_s_test_svcs[i].uuid.u) == 0);
+ }
+
+ TEST_ASSERT(i == ble_gatt_disc_s_test_num_svcs);
+ TEST_ASSERT(ble_gatt_disc_s_test_rx_complete);
+}
+
+static int
+ble_gatt_disc_s_test_misc_disc_cb(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service,
+ void *arg)
+{
+ TEST_ASSERT(error != NULL);
+ TEST_ASSERT(!ble_gatt_disc_s_test_rx_complete);
+
+ 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;
+
+ case BLE_HS_ETIMEOUT:
+ ble_gatt_disc_s_test_rx_complete = 1;
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ }
+
+ return 0;
+}
+
+static void
+ble_gatt_disc_s_test_misc_good_all(struct ble_gatt_disc_s_test_svc *services)
+{
+ int rc;
+
+ ble_gatt_disc_s_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ rc = ble_gattc_disc_all_svcs(2, ble_gatt_disc_s_test_misc_disc_cb, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_gatt_disc_s_test_misc_rx_all_rsp(2, services);
+ ble_gatt_disc_s_test_misc_verify_services(services);
+}
+
+static void
+ble_gatt_disc_s_test_misc_good_uuid(
+ struct ble_gatt_disc_s_test_svc *services)
+{
+ int rc;
+
+ ble_gatt_disc_s_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ rc = ble_gattc_disc_svc_by_uuid(2, services[0].uuid,
+ ble_gatt_disc_s_test_misc_disc_cb, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_verify_tx_disc_svc_uuid(services[0].uuid);
+
+ ble_gatt_disc_s_test_misc_rx_uuid_rsp(2, services);
+ ble_gatt_disc_s_test_misc_verify_services(services);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_s_test_disc_all)
+{
+ /*** One 128-bit service. */
+ ble_gatt_disc_s_test_misc_good_all((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 }
+ });
+
+ /*** Two 128-bit services. */
+ ble_gatt_disc_s_test_misc_good_all((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 10, 50, BLE_UUID128_DECLARE(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ), },
+ { 0 }
+ });
+
+ /*** Five 128-bit services. */
+ ble_gatt_disc_s_test_misc_good_all((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 10, 50, BLE_UUID128_DECLARE(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ), },
+ { 80, 120, BLE_UUID128_DECLARE(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ), },
+ { 123, 678, BLE_UUID128_DECLARE(4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ), },
+ { 751, 999, BLE_UUID128_DECLARE(5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ), },
+ { 0 }
+ });
+
+ /*** One 128-bit service, one 16-bit-service. */
+ ble_gatt_disc_s_test_misc_good_all((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 6, 7, BLE_UUID16_DECLARE(0x1234) },
+ { 0 }
+ });
+
+ /*** End with handle 0xffff. */
+ ble_gatt_disc_s_test_misc_good_all((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 7, 0xffff,BLE_UUID128_DECLARE(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ), },
+ { 0 }
+ });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_s_test_disc_uuid)
+{
+ /*** 128-bit service; one entry. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 }
+ });
+
+ /*** 128-bit service; two entries. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 8, 43, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 }
+ });
+
+ /*** 128-bit service; five entries. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 8, 43, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 67, 100, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 102, 103, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 262, 900, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 }
+ });
+
+ /*** 128-bit service; end with handle 0xffff. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 7, 0xffff,BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 }
+ });
+
+ /*** 16-bit service; one entry. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID16_DECLARE(0x1234) },
+ { 0 }
+ });
+
+ /*** 16-bit service; two entries. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID16_DECLARE(0x1234) },
+ { 85, 243, BLE_UUID16_DECLARE(0x1234) },
+ { 0 }
+ });
+
+ /*** 16-bit service; five entries. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID16_DECLARE(0x1234) },
+ { 85, 243, BLE_UUID16_DECLARE(0x1234) },
+ { 382, 383, BLE_UUID16_DECLARE(0x1234) },
+ { 562, 898, BLE_UUID16_DECLARE(0x1234) },
+ { 902, 984, BLE_UUID16_DECLARE(0x1234) },
+ { 0 }
+ });
+
+ /*** 16-bit service; end with handle 0xffff. */
+ ble_gatt_disc_s_test_misc_good_uuid((struct ble_gatt_disc_s_test_svc[]) {
+ { 1, 5, BLE_UUID16_DECLARE(0x1234) },
+ { 9, 0xffff,BLE_UUID16_DECLARE(0x1234) },
+ { 0 }
+ });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all)
+{
+ struct ble_gatt_disc_s_test_svc svcs[] = {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 6, 10, BLE_UUID128_DECLARE(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ), },
+ { 0 },
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int num_svcs;
+ int rc;
+
+ ble_gatt_disc_s_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all services procedure. */
+ rc = ble_gattc_disc_all_svcs(1, ble_gatt_disc_s_test_misc_disc_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ num_svcs = ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs);
+
+ /* Make sure there are still undiscovered services. */
+ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs + num_svcs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+ ble_gatt_disc_s_test_misc_verify_services(svcs);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid)
+{
+ /* Retrieve enough services to require two transactions. */
+ struct ble_gatt_disc_s_test_svc svcs[] = {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 6, 10, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 11, 15, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 16, 20, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 21, 25, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 26, 30, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 0 },
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int num_svcs;
+ int rc;
+
+ ble_gatt_disc_s_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all services procedure. */
+ rc = ble_gattc_disc_svc_by_uuid(1, svcs[0].uuid,
+ ble_gatt_disc_s_test_misc_disc_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ num_svcs = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs);
+
+ /* Make sure there are still undiscovered services. */
+ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs + num_svcs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_GROUP_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+ ble_gatt_disc_s_test_misc_verify_services(svcs);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_disc_s_test_oom_timeout)
+{
+ struct ble_gatt_disc_s_test_svc svcs[] = {
+ { 1, 5, BLE_UUID128_DECLARE(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), },
+ { 6, 10, BLE_UUID128_DECLARE(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ), },
+ { 0 },
+ };
+
+ struct os_mbuf *oms_temp;
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int rc;
+ int i;
+
+ ble_gatt_disc_s_test_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all services procedure. */
+ rc = ble_gattc_disc_all_svcs(1, ble_gatt_disc_s_test_misc_disc_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs);
+
+ /* Keep trying to resume for 30 seconds, but never free any mbufs. Verify
+ * procedure eventually times out.
+ */
+ for (i = 0; i < 30; i++) {
+ /* Ensure no follow-up request got sent. It should not have gotten
+ * sent due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ oms_temp = ble_hs_test_util_mbuf_alloc_all_but(0);
+ if (oms_temp != NULL) {
+ os_mbuf_concat(oms, oms_temp);
+ }
+
+ /* Verify that we will resume the stalled GATT procedure in one
+ * second.
+ */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ os_time_advance(ticks_until);
+ }
+
+ /* Verify the procedure has timed out. The connection should now be
+ * in the process of being terminated. XXX: Check this.
+ */
+ ble_hs_test_util_hci_ack_set_disconnect(0);
+ ble_gattc_timer();
+
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == BLE_HS_FOREVER);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_disc_s_test_suite)
+{
+ ble_gatt_disc_s_test_disc_all();
+ ble_gatt_disc_s_test_disc_uuid();
+ ble_gatt_disc_s_test_oom_all();
+ ble_gatt_disc_s_test_oom_uuid();
+ ble_gatt_disc_s_test_oom_timeout();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_find_s_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_find_s_test.c
new file mode 100644
index 00000000..172bdd33
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_find_s_test.c
@@ -0,0 +1,433 @@
+/*
+ * 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 "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+static struct ble_gatt_svc ble_gatt_find_s_test_svcs[256];
+static int ble_gatt_find_s_test_num_svcs;
+static int ble_gatt_find_s_test_proc_complete;
+
+struct ble_gatt_find_s_test_entry {
+ uint16_t inc_handle; /* 0 indicates no more entries. */
+ uint16_t start_handle;
+ uint16_t end_handle;
+ const ble_uuid_t *uuid;
+};
+
+static void
+ble_gatt_find_s_test_misc_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gatt_find_s_test_num_svcs = 0;
+ ble_gatt_find_s_test_proc_complete = 0;
+}
+
+static int
+ble_gatt_find_s_test_misc_cb(uint16_t conn_handle,
+ 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);
+
+ 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;
+}
+
+static void
+ble_gatt_find_s_test_misc_verify_incs(
+ struct ble_gatt_find_s_test_entry *entries)
+{
+ int i;
+
+ for (i = 0; entries[i].inc_handle != 0; i++) {
+ TEST_ASSERT(ble_gatt_find_s_test_svcs[i].start_handle ==
+ entries[i].start_handle);
+ TEST_ASSERT(ble_gatt_find_s_test_svcs[i].end_handle ==
+ entries[i].end_handle);
+ TEST_ASSERT(ble_uuid_cmp(&ble_gatt_find_s_test_svcs[i].uuid.u,
+ entries[i].uuid) == 0);
+ }
+
+ TEST_ASSERT(i == ble_gatt_find_s_test_num_svcs);
+ TEST_ASSERT(ble_gatt_find_s_test_proc_complete);
+}
+
+static int
+ble_gatt_find_s_test_misc_rx_read_type(
+ uint16_t conn_handle, struct ble_gatt_find_s_test_entry *entries)
+{
+ struct ble_att_read_type_rsp rsp;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ memset(&rsp, 0, sizeof rsp);
+
+ off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
+ for (i = 0; entries[i].inc_handle != 0; i++) {
+ if (rsp.batp_length == BLE_GATTS_INC_SVC_LEN_NO_UUID + 2) {
+ break;
+ }
+
+ if (entries[i].uuid->type != BLE_UUID_TYPE_16) {
+ if (rsp.batp_length != 0) {
+ break;
+ }
+ rsp.batp_length = BLE_GATTS_INC_SVC_LEN_NO_UUID + 2;
+ } else {
+ rsp.batp_length = BLE_GATTS_INC_SVC_LEN_UUID + 2;
+ }
+
+ TEST_ASSERT_FATAL(off + rsp.batp_length <= sizeof buf);
+
+ put_le16(buf + off, entries[i].inc_handle);
+ off += 2;
+
+ put_le16(buf + off, entries[i].start_handle);
+ off += 2;
+
+ put_le16(buf + off, entries[i].end_handle);
+ off += 2;
+
+ if (entries[i].uuid->type == BLE_UUID_TYPE_16) {
+ put_le16(buf + off, ble_uuid_u16(entries[i].uuid));
+ off += 2;
+ }
+ }
+
+ if (i == 0) {
+ ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND, 0);
+ return 0;
+ }
+
+ ble_att_read_type_rsp_write(buf + 0, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, const ble_uuid_t *uuid)
+{
+ uint8_t buf[17];
+ int rc;
+
+ TEST_ASSERT(uuid->type == BLE_UUID_TYPE_128);
+
+ buf[0] = BLE_ATT_OP_READ_RSP;
+ ble_uuid_flat(uuid, buf + 1);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 17);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_gatt_find_s_test_misc_verify_tx_read_type(uint16_t start_handle,
+ uint16_t end_handle)
+{
+ struct ble_att_read_type_req req;
+ struct os_mbuf *om;
+ uint16_t uuid16;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ ble_att_read_type_req_parse(om->om_data, om->om_len, &req);
+
+ TEST_ASSERT(req.batq_start_handle == start_handle);
+ TEST_ASSERT(req.batq_end_handle == end_handle);
+ TEST_ASSERT(om->om_len == BLE_ATT_READ_TYPE_REQ_BASE_SZ + 2);
+ uuid16 = get_le16(om->om_data + BLE_ATT_READ_TYPE_REQ_BASE_SZ);
+ TEST_ASSERT(uuid16 == BLE_ATT_UUID_INCLUDE);
+}
+
+static void
+ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle)
+{
+ struct ble_att_read_req req;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ ble_att_read_req_parse(om->om_data, om->om_len, &req);
+
+ TEST_ASSERT(req.barq_handle == handle);
+ TEST_ASSERT(om->om_len == BLE_ATT_READ_REQ_SZ);
+}
+
+static void
+ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle,
+ uint16_t start_handle, uint16_t end_handle,
+ struct ble_gatt_find_s_test_entry *entries)
+{
+ struct ble_gatt_svc service;
+ int cur_start;
+ int num_found;
+ int idx;
+ int rc;
+ int i;
+
+ rc = ble_gattc_find_inc_svcs(conn_handle, start_handle, end_handle,
+ ble_gatt_find_s_test_misc_cb, &service);
+ TEST_ASSERT(rc == 0);
+
+ cur_start = start_handle;
+ idx = 0;
+ while (1) {
+ ble_gatt_find_s_test_misc_verify_tx_read_type(cur_start, end_handle);
+ num_found = ble_gatt_find_s_test_misc_rx_read_type(conn_handle,
+ entries + idx);
+ if (num_found == 0) {
+ break;
+ }
+
+ if (entries[idx].uuid->type == BLE_UUID_TYPE_128) {
+ TEST_ASSERT(num_found == 1);
+ ble_gatt_find_s_test_misc_verify_tx_read(
+ entries[idx].start_handle);
+ ble_gatt_find_s_test_misc_rx_read(conn_handle,
+ entries[idx].uuid);
+ }
+
+ idx += num_found;
+ cur_start = entries[idx - 1].inc_handle + 1;
+ }
+ TEST_ASSERT(idx == ble_gatt_find_s_test_num_svcs);
+ TEST_ASSERT(ble_gatt_find_s_test_proc_complete);
+
+ for (i = 0; i < ble_gatt_find_s_test_num_svcs; i++) {
+ TEST_ASSERT(ble_gatt_find_s_test_svcs[i].start_handle ==
+ entries[i].start_handle);
+ TEST_ASSERT(ble_gatt_find_s_test_svcs[i].end_handle ==
+ entries[i].end_handle);
+ TEST_ASSERT(ble_uuid_cmp(&ble_gatt_find_s_test_svcs[i].uuid.u,
+ entries[i].uuid) == 0);
+ }
+}
+
+TEST_CASE_SELF(ble_gatt_find_s_test_1)
+{
+ /* Two 16-bit UUID services; one response. */
+ ble_gatt_find_s_test_misc_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+ ble_gatt_find_s_test_misc_find_inc(2, 5, 10,
+ ((struct ble_gatt_find_s_test_entry[]) { {
+ .inc_handle = 6,
+ .start_handle = 35,
+ .end_handle = 49,
+ .uuid = BLE_UUID16_DECLARE(0x5155),
+ }, {
+ .inc_handle = 9,
+ .start_handle = 543,
+ .end_handle = 870,
+ .uuid = BLE_UUID16_DECLARE(0x1122),
+ }, {
+ 0,
+ } })
+ );
+
+ /* One 128-bit UUID service; two responses. */
+ ble_gatt_find_s_test_misc_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+ ble_gatt_find_s_test_misc_find_inc(2, 34, 100,
+ ((struct ble_gatt_find_s_test_entry[]) { {
+ .inc_handle = 36,
+ .start_handle = 403,
+ .end_handle = 859,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ 0,
+ } })
+ );
+
+ /* Two 128-bit UUID service; four responses. */
+ ble_gatt_find_s_test_misc_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+ ble_gatt_find_s_test_misc_find_inc(2, 34, 100,
+ ((struct ble_gatt_find_s_test_entry[]) { {
+ .inc_handle = 36,
+ .start_handle = 403,
+ .end_handle = 859,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ .inc_handle = 39,
+ .start_handle = 900,
+ .end_handle = 932,
+ .uuid = BLE_UUID128_DECLARE(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
+ }, {
+ 0,
+ } })
+ );
+
+ /* Two 16-bit UUID; three 128-bit UUID; seven responses. */
+ ble_gatt_find_s_test_misc_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+ ble_gatt_find_s_test_misc_find_inc(2, 1, 100,
+ ((struct ble_gatt_find_s_test_entry[]) { {
+ .inc_handle = 36,
+ .start_handle = 403,
+ .end_handle = 859,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ }, {
+ .inc_handle = 37,
+ .start_handle = 35,
+ .end_handle = 49,
+ .uuid = BLE_UUID16_DECLARE(0x5155),
+ }, {
+ .inc_handle = 38,
+ .start_handle = 543,
+ .end_handle = 870,
+ .uuid = BLE_UUID16_DECLARE(0x1122),
+ }, {
+ .inc_handle = 39,
+ .start_handle = 900,
+ .end_handle = 932,
+ .uuid = BLE_UUID128_DECLARE(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
+ }, {
+ .inc_handle = 40,
+ .start_handle = 940,
+ .end_handle = 950,
+ .uuid = BLE_UUID128_DECLARE(3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18),
+ }, {
+ 0,
+ } })
+ );
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_find_s_test_oom)
+{
+
+ struct ble_gatt_find_s_test_entry incs[] = {
+ {
+ .inc_handle = 21,
+ .start_handle = 800,
+ .end_handle = 899,
+ .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
+ },
+ {
+ .inc_handle = 22,
+ .start_handle = 900,
+ .end_handle = 999,
+ .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
+ },
+ { 0 }
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int rc;
+
+ ble_gatt_find_s_test_misc_init();
+
+ ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a discover all characteristics procedure. */
+ rc = ble_gattc_find_inc_svcs(1, 20, 30,
+ ble_gatt_find_s_test_misc_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_find_s_test_misc_rx_read_type(1, incs);
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure succeeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* We can't cause a memory exhaustion error on the follow up request. The
+ * GATT client frees the read response immediately before sending the
+ * follow-up request, so there is always an mbuf available.
+ */
+ /* XXX: Find a way to test this. */
+ ble_gatt_find_s_test_misc_rx_read(1, incs[0].uuid);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_find_s_test_misc_rx_read_type(1, incs + 1);
+
+ /* Verify the procedure succeeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ ble_gatt_find_s_test_misc_rx_read(1, incs[1].uuid);
+
+ ble_hs_test_util_rx_att_err_rsp(1,
+ BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ 1);
+
+ ble_gatt_find_s_test_misc_verify_incs(incs);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_find_s_test_suite)
+{
+ ble_gatt_find_s_test_1();
+ ble_gatt_find_s_test_oom();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_read_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_read_test.c
new file mode 100644
index 00000000..572b0bf1
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_read_test.c
@@ -0,0 +1,923 @@
+/*
+ * 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 <limits.h>
+#include "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+struct ble_gatt_read_test_attr {
+ uint16_t conn_handle;
+ uint16_t handle;
+ uint8_t value_len;
+ uint8_t value[BLE_ATT_ATTR_MAX_LEN];
+};
+
+#define BLE_GATT_READ_TEST_MAX_ATTRS 256
+
+struct ble_gatt_read_test_attr
+ ble_gatt_read_test_attrs[BLE_GATT_READ_TEST_MAX_ATTRS];
+int ble_gatt_read_test_num_attrs;
+int ble_gatt_read_test_complete;
+
+uint16_t ble_gatt_read_test_bad_conn_handle;
+int ble_gatt_read_test_bad_status;
+
+static void
+ble_gatt_read_test_misc_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gatt_read_test_num_attrs = 0;
+ ble_gatt_read_test_complete = 0;
+ ble_gatt_read_test_bad_conn_handle = 0;
+ ble_gatt_read_test_bad_status = 0;
+
+ memset(&ble_gatt_read_test_attrs[0], 0,
+ sizeof ble_gatt_read_test_attrs[0]);
+}
+
+static int
+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;
+ int *stop_after;
+ int rc;
+
+ stop_after = arg;
+
+ 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;
+ return 0;
+ }
+
+ if (attr == NULL) {
+ ble_gatt_read_test_complete = 1;
+ return 0;
+ }
+
+ TEST_ASSERT_FATAL(ble_gatt_read_test_num_attrs <
+ BLE_GATT_READ_TEST_MAX_ATTRS);
+ dst = ble_gatt_read_test_attrs + ble_gatt_read_test_num_attrs++;
+
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <= sizeof dst->value);
+
+ dst->conn_handle = conn_handle;
+ dst->handle = attr->handle;
+ dst->value_len = OS_MBUF_PKTLEN(attr->om);
+ rc = os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), dst->value);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ if (stop_after != NULL && *stop_after > 0) {
+ (*stop_after)--;
+ if (*stop_after == 0) {
+ ble_gatt_read_test_complete = 1;
+ return 1;
+ }
+ } else {
+ ble_gatt_read_test_complete = 1;
+ }
+
+ return 0;
+}
+
+static int
+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;
+ int *reads_left;
+ int rc;
+
+ reads_left = arg;
+
+ 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;
+ return 0;
+ }
+
+ if (attr == NULL) {
+ ble_gatt_read_test_complete = 1;
+ return 0;
+ }
+
+ dst = ble_gatt_read_test_attrs + 0;
+
+ 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) {
+ dst->conn_handle = conn_handle;
+ dst->handle = attr->handle;
+ } else {
+ TEST_ASSERT(conn_handle == dst->conn_handle);
+ TEST_ASSERT(attr->handle == dst->handle);
+ }
+ rc = os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om),
+ dst->value + dst->value_len);
+ TEST_ASSERT_FATAL(rc == 0);
+ dst->value_len += OS_MBUF_PKTLEN(attr->om);
+
+ if (reads_left != NULL && *reads_left > 0) {
+ (*reads_left)--;
+ if (*reads_left == 0) {
+ ble_gatt_read_test_complete = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,
+ uint8_t att_op,
+ const void *data, int data_len)
+{
+ uint8_t buf[1024];
+ int rc;
+
+ TEST_ASSERT_FATAL(data_len <= sizeof buf);
+
+ /* Send the pending ATT Read Request. */
+
+ buf[0] = att_op;
+ memcpy(buf + 1, data, data_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, 1 + data_len);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle,
+ 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,
+ attr->value_len);
+}
+
+static void
+ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle,
+ uint8_t att_error, uint16_t err_handle)
+{
+ /* Send the pending ATT Read Request. */
+
+ ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_REQ,
+ att_error, err_handle);
+}
+
+static int
+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];
+ int prev_len;
+ int off;
+ int rc;
+ int i;
+
+ if (ble_gatt_read_test_complete || attrs[0].handle == 0) {
+ return 0;
+ }
+
+ /* Send the pending ATT Read By Type Request. */
+
+ rsp.batp_length = 2 + attrs[0].value_len;
+ ble_att_read_type_rsp_write(buf, sizeof buf, &rsp);
+
+ prev_len = 0;
+ off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
+ for (i = 0; attrs[i].handle != 0; i++) {
+ if (prev_len != 0 && prev_len != attrs[i].value_len) {
+ break;
+ }
+ prev_len = attrs[i].value_len;
+
+ put_le16(buf + off, attrs[i].handle);
+ off += 2;
+
+ memcpy(buf + off, attrs[i].value, attrs[i].value_len);
+ off += attrs[i].value_len;
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr)
+{
+ int rc;
+
+ 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);
+
+ /* Exchange MTU: We need plus 1 for the read response opcode */
+ ble_hs_test_util_set_att_mtu(2, attr->value_len + 1);
+
+ rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_good(2, attr);
+
+ TEST_ASSERT(ble_gatt_read_test_num_attrs == 1);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr->handle);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr->value_len);
+ TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr->value,
+ attr->value_len) == 0);
+}
+
+static void
+ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
+ struct ble_hs_test_util_flat_attr *attr)
+{
+ int rc;
+
+ 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);
+
+ rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle);
+
+ TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
+ TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_bad_status ==
+ BLE_HS_ERR_ATT_BASE + att_status);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+}
+
+static void
+ble_gatt_read_test_misc_uuid_verify_good(
+ uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid,
+ int stop_after, struct ble_hs_test_util_flat_attr *attrs)
+{
+ int num_read;
+ int idx;
+ 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);
+
+ rc = ble_gattc_read_by_uuid(2, start_handle, end_handle, uuid,
+ ble_gatt_read_test_cb, &stop_after);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ idx = 0;
+ while (1) {
+ num_read = ble_gatt_read_test_misc_uuid_rx_rsp_good(2, attrs + idx);
+ if (num_read == 0) {
+ ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_READ_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND,
+ start_handle);
+ break;
+ }
+
+ idx += num_read;
+ }
+
+ TEST_ASSERT(ble_gatt_read_test_complete);
+ TEST_ASSERT(idx == ble_gatt_read_test_num_attrs);
+
+ for (i = 0; i < idx; i++) {
+ TEST_ASSERT(ble_gatt_read_test_attrs[i].conn_handle == 2);
+ 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_ASSERT(!ble_gattc_any_jobs());
+}
+
+static void
+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;
+ int rem_len;
+ int att_op;
+ uint16_t offset = 0;
+ int off;
+ int rc;
+
+ 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);
+
+ if (max_reads == 0) {
+ max_reads = INT_MAX;
+ }
+ reads_left = max_reads;
+ rc = ble_gattc_read_long(2, attr->handle, offset,
+ ble_gatt_read_test_long_cb, &reads_left);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ off = 0;
+ rem_len = attr->value_len;
+ do {
+ if (rem_len > BLE_ATT_MTU_DFLT - 1) {
+ chunk_sz = BLE_ATT_MTU_DFLT - 1;
+ } else {
+ chunk_sz = rem_len;
+ }
+ if (off == 0) {
+ att_op = BLE_ATT_OP_READ_RSP;
+ } else {
+ att_op = BLE_ATT_OP_READ_BLOB_RSP;
+ }
+ ble_gatt_read_test_misc_rx_rsp_good_raw(2, att_op,
+ attr->value + off, chunk_sz);
+ rem_len -= chunk_sz;
+ off += chunk_sz;
+ } while (rem_len > 0 && reads_left > 0);
+
+ TEST_ASSERT(ble_gatt_read_test_complete);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr->handle);
+ if (reads_left > 0) {
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr->value_len);
+ }
+ TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr->value,
+ ble_gatt_read_test_attrs[0].value_len) == 0);
+}
+
+static void
+ble_gatt_read_test_misc_long_verify_bad(
+ uint8_t att_status, struct ble_hs_test_util_flat_attr *attr)
+{
+ uint16_t offset = 0;
+ int rc;
+
+ 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);
+
+ rc = ble_gattc_read_long(2, attr->handle, offset,
+ ble_gatt_read_test_long_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle);
+
+ TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
+ TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_bad_status ==
+ BLE_HS_ERR_ATT_BASE + att_status);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+}
+
+static int
+ble_gatt_read_test_misc_extract_handles(
+ struct ble_hs_test_util_flat_attr *attrs, uint16_t *handles)
+{
+ int i;
+
+ for (i = 0; attrs[i].handle != 0; i++) {
+ handles[i] = attrs[i].handle;
+ }
+ return i;
+}
+
+static void
+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];
+ int num_attrs;
+ int chunk_sz;
+ int off;
+ 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);
+
+ num_attrs = ble_gatt_read_test_misc_extract_handles(attrs, handles);
+
+ off = 0;
+ for (i = 0; i < num_attrs; i++) {
+ if (attrs[i].value_len > BLE_ATT_MTU_DFLT - 1 - off) {
+ chunk_sz = BLE_ATT_MTU_DFLT - 1 - off;
+ } else {
+ chunk_sz = attrs[i].value_len;
+ }
+
+ if (chunk_sz > 0) {
+ memcpy(expected_value + off, attrs[i].value, chunk_sz);
+ off += chunk_sz;
+ }
+ }
+
+ rc = ble_gattc_read_mult(2, handles, num_attrs,
+ ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_MULT_RSP,
+ expected_value, off);
+
+ TEST_ASSERT(ble_gatt_read_test_complete);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == off);
+ TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, expected_value,
+ off) == 0);
+}
+
+static void
+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;
+ int rc;
+
+ 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);
+
+ num_attrs = ble_gatt_read_test_misc_extract_handles(attrs, handles);
+
+ rc = ble_gattc_read_mult(2, handles, num_attrs,
+ ble_gatt_read_test_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, err_handle);
+
+ TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
+ TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_bad_status ==
+ BLE_HS_ERR_ATT_BASE + att_status);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+}
+
+TEST_CASE_SELF(ble_gatt_read_test_by_handle)
+{
+ /* Read a seven-byte attribute. */
+ ble_gatt_read_test_misc_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 0x5432,
+ .value = { 0xff },
+ .value_len = 1
+ } });
+
+ /* Read a 200-byte attribute. */
+ ble_gatt_read_test_misc_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 815,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 719,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 65,
+ .value = { 0xfa, 0x4c },
+ .value_len = 2
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_read_test_by_uuid)
+{
+ /* Read a single seven-byte attribute. */
+ ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 1,2,3,4,5,6,7 },
+ .value_len = 7
+ }, {
+ 0,
+ } });
+
+ /* Read two seven-byte attributes; one response. */
+ ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 1,2,3,4,5,6,7 },
+ .value_len = 7
+ }, {
+ .handle = 44,
+ .value = { 2,3,4,5,6,7,8 },
+ .value_len = 7
+ }, {
+ 0,
+ } });
+
+ /* Read two attributes; two responses. */
+ ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 1,2,3,4,5,6,7 },
+ .value_len = 7
+ }, {
+ .handle = 44,
+ .value = { 2,3,4 },
+ .value_len = 3
+ }, {
+ 0,
+ } });
+
+ /* Stop after three reads. */
+ ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 3,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 1,2,3,4,5,6,7 },
+ .value_len = 7
+ }, {
+ .handle = 44,
+ .value = { 2,3,4 },
+ .value_len = 3
+ }, {
+ .handle = 45,
+ .value = { 2,3,4 },
+ .value_len = 3
+ }, {
+ .handle = 46,
+ .value = { 3,4,5,6 },
+ .value_len = 4
+ }, {
+ .handle = 47,
+ .value = { 2,3,4 },
+ .value_len = 3
+ }, {
+ 0,
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_read_test_long)
+{
+ uint8_t data512[512];
+ int i;
+
+ for (i = 0; i < sizeof data512; i++) {
+ data512[i] = i;
+ }
+
+ /* Read a seven-byte attribute. */
+ ble_gatt_read_test_misc_long_verify_good(0,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 0 },
+ .value_len = 0
+ } });
+
+ /* Read a 60-byte attribute; three requests. */
+ ble_gatt_read_test_misc_long_verify_good(0,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 34,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 34,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 719,
+ .value = { 1, 2, 3, 4, 5, 6, 7 },
+ .value_len = 7
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_read_test_mult)
+{
+ uint8_t data512[512];
+ int i;
+
+ for (i = 0; i < sizeof data512; i++) {
+ data512[i] = i;
+ }
+
+ /* Read one attribute. */
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ .value_len = 7,
+ }, {
+ .handle = 44,
+ .value = { 8, 9, 10, 11 },
+ .value_len = 4,
+ }, {
+ 0
+ } });
+
+ /* Read two attributes (swap order). */
+ ble_gatt_read_test_misc_mult_verify_good(
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 44,
+ .value = { 8, 9, 10, 11 },
+ .value_len = 4,
+ }, {
+ .handle = 43,
+ .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_hs_test_util_flat_attr[]) { {
+ .handle = 43,
+ .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ .value_len = 7,
+ }, {
+ .handle = 44,
+ .value = { 8, 9, 10, 11 },
+ .value_len = 4,
+ }, {
+ .handle = 145,
+ .value = { 12, 13 },
+ .value_len = 2,
+ }, {
+ .handle = 191,
+ .value = { 14, 15, 16 },
+ .value_len = 3,
+ }, {
+ .handle = 352,
+ .value = { 17, 18, 19, 20 },
+ .value_len = 4,
+ }, {
+ 0
+ } });
+
+ /* Fail due to attribute not found. */
+ ble_gatt_read_test_misc_mult_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND, 719,
+ (struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 719,
+ .value = { 1,2,3,4,5,6,7 },
+ .value_len = 7
+ }, {
+ 0
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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);
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_read_test_long_oom)
+{
+ static const struct ble_hs_test_util_flat_attr attr = {
+ .handle = 34,
+ .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,
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int reads_left;
+ int chunk_sz;
+ uint16_t offset = 0;
+ int off;
+ int rc;
+
+ 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);
+
+ /* Initiate a read long procedure. */
+ off = 0;
+ reads_left = 0;
+ rc = ble_gattc_read_long(2, attr.handle, offset, ble_gatt_read_test_long_cb,
+ &reads_left);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ;
+ ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
+ attr.value + off, chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ;
+ ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
+ attr.value + off, chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ chunk_sz = attr.value_len - off;
+ ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
+ attr.value + off, chunk_sz);
+ off += chunk_sz;
+
+ TEST_ASSERT(ble_gatt_read_test_complete);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr.handle);
+ TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr.value_len);
+ TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr.value,
+ ble_gatt_read_test_attrs[0].value_len) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_read_test_suite)
+{
+ 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();
+ ble_gatt_read_test_long_oom();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_write_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_write_test.c
new file mode 100644
index 00000000..caa8e565
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatt_write_test.c
@@ -0,0 +1,832 @@
+/*
+ * 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 "nimble/ble.h"
+#include "ble_hs_test.h"
+#include "host/ble_gatt.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_GATT_WRITE_TEST_MAX_ATTRS 128
+
+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_hs_test_util_flat_attr
+ble_gatt_write_test_attrs[BLE_GATT_WRITE_TEST_MAX_ATTRS];
+static int ble_gatt_write_test_num_attrs;
+
+static void
+ble_gatt_write_test_init(void)
+{
+ int i;
+
+ ble_hs_test_util_init();
+ ble_gatt_write_test_cb_called = 0;
+ ble_gatt_write_test_num_attrs = 0;
+
+ for (i = 0; i < sizeof ble_gatt_write_test_attr_value; i++) {
+ ble_gatt_write_test_attr_value[i] = i;
+ }
+}
+
+static int
+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->status == 0);
+ TEST_ASSERT(attr->handle == 100);
+ }
+
+ ble_gatt_write_test_cb_called = 1;
+
+ return 0;
+}
+
+static void
+ble_gatt_write_test_rx_rsp(uint16_t conn_handle)
+{
+ uint8_t op;
+ int rc;
+
+ op = BLE_ATT_OP_WRITE_RSP;
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ &op, 1);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle,
+ uint16_t offset,
+ const void *attr_data, uint16_t attr_data_len)
+{
+ struct ble_att_prep_write_cmd rsp;
+ uint8_t buf[512];
+ int rc;
+
+ rsp.bapc_handle = attr_handle;
+ rsp.bapc_offset = offset;
+ ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
+
+ memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_data, attr_data_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle)
+{
+ uint8_t op;
+ int rc;
+
+ op = BLE_ATT_OP_EXEC_WRITE_RSP;
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ &op, 1);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_gatt_write_test_misc_long_good(int attr_len)
+{
+ uint16_t mtu;
+ int off;
+ int len;
+ int rc;
+
+ ble_gatt_write_test_init();
+
+ 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_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) {
+ 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_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);
+
+ off += len;
+ }
+
+ /* Verify execute write request sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
+
+ /* Receive Exec Write response. */
+ ble_gatt_write_test_rx_exec_rsp(2);
+
+ /* Verify callback got called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+}
+
+typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle,
+ int off, int len);
+
+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;
+ int rc;
+
+ ble_gatt_write_test_init();
+
+ 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_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_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;
+ if (off + len >= attr_len) {
+ len = attr_len - off;
+ fail_now = 1;
+ }
+ if (!fail_now) {
+ ble_gatt_write_test_rx_prep_rsp(
+ 2, 100, off, ble_gatt_write_test_attr_value + off, len);
+ } else {
+ cb(2, off, len);
+ break;
+ }
+
+ /* Verify callback hasn't gotten called. */
+ TEST_ASSERT(!ble_gatt_write_test_cb_called);
+
+ off += len;
+ }
+
+ /* Verify callback was called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+ TEST_ASSERT(ble_gatt_write_test_error.status == BLE_HS_EBADDATA);
+ TEST_ASSERT(ble_gatt_write_test_error.att_handle == 0);
+}
+
+static void
+ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle,
+ int off, int len)
+{
+ ble_gatt_write_test_rx_prep_rsp(
+ conn_handle, 99, off, ble_gatt_write_test_attr_value + off,
+ len);
+}
+
+static void
+ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle,
+ int off, int len)
+{
+ ble_gatt_write_test_rx_prep_rsp(
+ conn_handle, 100, off + 1, ble_gatt_write_test_attr_value + off,
+ len);
+}
+
+static void
+ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle,
+ int off, int len)
+{
+ ble_gatt_write_test_rx_prep_rsp(
+ conn_handle, 100, off, ble_gatt_write_test_attr_value + off + 1,
+ len);
+}
+
+static void
+ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle,
+ int off, int len)
+{
+ ble_gatt_write_test_rx_prep_rsp(
+ conn_handle, 100, off, ble_gatt_write_test_attr_value + off,
+ len - 1);
+}
+
+static int
+ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attrs,
+ uint8_t num_attrs, void *arg)
+{
+ int i;
+
+ TEST_ASSERT_FATAL(num_attrs <= BLE_GATT_WRITE_TEST_MAX_ATTRS);
+
+ TEST_ASSERT(conn_handle == 2);
+
+ ble_gatt_write_test_num_attrs = num_attrs;
+ for (i = 0; i < num_attrs; i++) {
+ ble_hs_test_util_attr_to_flat(ble_gatt_write_test_attrs + i,
+ attrs + i);
+ }
+
+ ble_gatt_write_test_cb_called = 1;
+
+ return 0;
+}
+
+static void
+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; 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);
+
+ 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_verify_tx_prep_write(attr->handle, off,
+ attr->value + off, len);
+
+ /* Receive Prep Write response. */
+ 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_EXECUTE);
+
+ /* Receive Exec Write response. */
+ ble_gatt_write_test_rx_exec_rsp(2);
+
+ /* Verify callback got called. */
+ 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++) {
+ rc = ble_hs_test_util_flat_attr_cmp(
+ ble_gatt_write_test_attrs + i, flat_attrs + i);
+ TEST_ASSERT(rc == 0);
+ }
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_no_rsp)
+{
+ int attr_len;
+ int rc;
+
+ ble_gatt_write_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ attr_len = 4;
+ 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. */
+
+ /* No response expected; verify callback not called. */
+ TEST_ASSERT(!ble_gatt_write_test_cb_called);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_rsp)
+{
+ int attr_len;
+
+ ble_gatt_write_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ attr_len = 4;
+ 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. */
+
+ /* Response not received yet; verify callback not called. */
+ TEST_ASSERT(!ble_gatt_write_test_cb_called);
+
+ /* Receive write response. */
+ ble_gatt_write_test_rx_rsp(2);
+
+ /* Verify callback got called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_good)
+{
+ /*** 1 prep write req/rsp. */
+ ble_gatt_write_test_misc_long_good(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+
+ /*** 2 prep write reqs/rsps. */
+ ble_gatt_write_test_misc_long_good(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1);
+
+ /*** Maximum reqs/rsps. */
+ ble_gatt_write_test_misc_long_good(BLE_ATT_ATTR_MAX_LEN);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_bad_handle)
+{
+ /*** 1 prep write req/rsp. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ ble_gatt_write_test_misc_long_fail_handle);
+
+ /*** 2 prep write reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+ ble_gatt_write_test_misc_long_fail_handle);
+
+ /*** Maximum reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_ATTR_MAX_LEN,
+ ble_gatt_write_test_misc_long_fail_handle);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_bad_offset)
+{
+ /*** 1 prep write req/rsp. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ ble_gatt_write_test_misc_long_fail_offset);
+
+ /*** 2 prep write reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+ ble_gatt_write_test_misc_long_fail_offset);
+
+ /*** Maximum reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_ATTR_MAX_LEN,
+ ble_gatt_write_test_misc_long_fail_offset);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_bad_value)
+{
+ /*** 1 prep write req/rsp. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ ble_gatt_write_test_misc_long_fail_value);
+
+ /*** 2 prep write reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+ ble_gatt_write_test_misc_long_fail_value);
+
+ /*** Maximum reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_ATTR_MAX_LEN,
+ ble_gatt_write_test_misc_long_fail_value);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_bad_length)
+{
+ /*** 1 prep write req/rsp. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
+ ble_gatt_write_test_misc_long_fail_length);
+
+ /*** 2 prep write reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+ ble_gatt_write_test_misc_long_fail_length);
+
+ /*** Maximum reqs/rsps. */
+ ble_gatt_write_test_misc_long_bad(
+ BLE_ATT_ATTR_MAX_LEN,
+ ble_gatt_write_test_misc_long_fail_length);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_reliable_good)
+{
+ /*** 1 attribute. */
+ ble_gatt_write_test_misc_reliable_good(
+ ((struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 100,
+ .value_len = 2,
+ .value = { 1, 2 },
+ }, {
+ 0
+ } }));
+
+ /*** 2 attributes. */
+ ble_gatt_write_test_misc_reliable_good(
+ ((struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 100,
+ .value_len = 2,
+ .value = { 1,2 },
+ }, {
+ .handle = 113,
+ .value_len = 6,
+ .value = { 5,6,7,8,9,10 },
+ }, {
+ 0
+ } }));
+
+ /*** 3 attributes. */
+ ble_gatt_write_test_misc_reliable_good(
+ ((struct ble_hs_test_util_flat_attr[]) { {
+ .handle = 100,
+ .value_len = 2,
+ .value = { 1,2 },
+ }, {
+ .handle = 113,
+ .value_len = 6,
+ .value = { 5,6,7,8,9,10 },
+ }, {
+ .handle = 144,
+ .value_len = 1,
+ .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
+ } }));
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_queue_full)
+{
+ int off;
+ int len;
+ int rc;
+ int i;
+
+ ble_gatt_write_test_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, 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;
+ for (i = 0; i < 2; i++) {
+ /* Verify prep write request was sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL);
+
+ /* Receive Prep Write response. */
+ len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+ 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);
+
+ off += len;
+ }
+
+ /* Verify prep write request was sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL);
+
+ /* Receive queue full error. */
+ ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_PREP_WRITE_REQ,
+ BLE_ATT_ERR_PREPARE_QUEUE_FULL, 100);
+
+ /* Verify callback was called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+ TEST_ASSERT(ble_gatt_write_test_error.status ==
+ BLE_HS_ATT_ERR(BLE_ATT_ERR_PREPARE_QUEUE_FULL));
+ TEST_ASSERT(ble_gatt_write_test_error.att_handle == 100);
+
+ /* Verify clear queue command got sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_CANCEL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_long_oom)
+{
+ static const struct ble_hs_test_util_flat_attr attr = {
+ .handle = 34,
+ .value = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ },
+ .value_len = 20,
+ };
+
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int chunk_sz;
+ int off;
+ int rc;
+
+ ble_gatt_write_test_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a write long procedure. */
+ off = 0;
+ rc = ble_hs_test_util_gatt_write_long_flat(
+ 2, attr.handle, attr.value, attr.value_len,
+ ble_gatt_write_test_cb_good, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+
+ ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
+ attr.value + off, chunk_sz);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off,
+ chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ chunk_sz = attr.value_len - off;
+ ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
+ attr.value + off, chunk_sz);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_write_test_rx_prep_rsp(
+ 2, attr.handle, off, attr.value + off, chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Verify execute write request sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
+
+ /* Receive Exec Write response. */
+ ble_gatt_write_test_rx_exec_rsp(2);
+
+ /* Verify callback got called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatt_write_test_reliable_oom)
+{
+ static const struct ble_hs_test_util_flat_attr attr = {
+ .handle = 34,
+ .value = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ },
+ .value_len = 20,
+ };
+
+ struct ble_gatt_attr mattr;
+ struct os_mbuf *oms;
+ int32_t ticks_until;
+ int chunk_sz;
+ int off;
+ int rc;
+
+ ble_gatt_write_test_init();
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Initiate a write reliable procedure. */
+ ble_hs_test_util_attr_from_flat(&mattr, &attr);
+
+ off = 0;
+ rc = ble_gattc_write_reliable(2, &mattr, 1,
+ ble_gatt_write_test_reliable_cb_good, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
+
+ ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
+ attr.value + off, chunk_sz);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off,
+ chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify the procedure proceeds after mbufs become available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ chunk_sz = attr.value_len - off;
+ ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
+ attr.value + off, chunk_sz);
+
+ /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */
+ oms = ble_hs_test_util_mbuf_alloc_all_but(1);
+ ble_gatt_write_test_rx_prep_rsp(
+ 2, attr.handle, off, attr.value + off, chunk_sz);
+ off += chunk_sz;
+
+ /* Ensure no follow-up request got sent. It should not have gotten sent
+ * due to mbuf exhaustion.
+ */
+ ble_hs_test_util_prev_tx_queue_clear();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
+
+ /* Verify that we will resume the stalled GATT procedure in one second. */
+ ticks_until = ble_gattc_timer();
+ TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
+
+ /* Verify that procedure completes when mbufs are available. */
+ rc = os_mbuf_free_chain(oms);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_time_advance(ticks_until);
+ ble_gattc_timer();
+
+ /* Verify execute write request sent. */
+ ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
+
+ /* Receive Exec Write response. */
+ ble_gatt_write_test_rx_exec_rsp(2);
+
+ /* Verify callback got called. */
+ TEST_ASSERT(ble_gatt_write_test_cb_called);
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatt_write_test_suite)
+{
+ ble_gatt_write_test_no_rsp();
+ ble_gatt_write_test_rsp();
+ ble_gatt_write_test_long_good();
+ ble_gatt_write_test_long_bad_handle();
+ ble_gatt_write_test_long_bad_offset();
+ ble_gatt_write_test_long_bad_value();
+ ble_gatt_write_test_long_bad_length();
+ ble_gatt_write_test_long_queue_full();
+ ble_gatt_write_test_reliable_good();
+ ble_gatt_write_test_long_oom();
+ ble_gatt_write_test_reliable_oom();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_notify_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_notify_test.c
new file mode 100644
index 00000000..6e04ac36
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_notify_test.c
@@ -0,0 +1,1090 @@
+/*
+ * 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 "nimble/ble.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_GATTS_NOTIFY_TEST_CHR_1_UUID 0x1111
+#define BLE_GATTS_NOTIFY_TEST_CHR_2_UUID 0x2222
+
+#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,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg);
+static void
+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[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(BLE_GATTS_NOTIFY_TEST_CHR_1_UUID),
+ .access_cb = ble_gatts_notify_test_misc_access,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
+ BLE_GATT_CHR_F_INDICATE,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(BLE_GATTS_NOTIFY_TEST_CHR_2_UUID),
+ .access_cb = ble_gatts_notify_test_misc_access,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
+ BLE_GATT_CHR_F_INDICATE,
+ }, {
+ 0
+ } },
+}, {
+ 0
+} };
+
+static uint16_t ble_gatts_notify_test_chr_1_def_handle;
+static uint8_t ble_gatts_notify_test_chr_1_val[1024];
+static int ble_gatts_notify_test_chr_1_len;
+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, const union ble_store_value *val);
+
+typedef int ble_store_delete_fn(int obj_type, const 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)
+{
+ struct ble_att_read_req req;
+ struct os_mbuf *om;
+ uint8_t buf[BLE_ATT_READ_REQ_SZ];
+ uint16_t flags;
+ int rc;
+
+ req.barq_handle = chr_def_handle + 2;
+ ble_att_read_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);
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT_FATAL(om->om_len == 3);
+ TEST_ASSERT_FATAL(om->om_data[0] == BLE_ATT_OP_READ_RSP);
+
+ flags = get_le16(om->om_data + 1);
+ return flags;
+}
+
+static void
+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];
+ int rc;
+
+ req.bawq_handle = chr_def_handle + 2;
+ ble_att_write_req_write(buf, sizeof buf, &req);
+
+ put_le16(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);
+ 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
+ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
+ uint16_t chr1_flags, uint16_t chr2_flags)
+{
+ struct ble_hs_conn *conn;
+ uint16_t flags;
+ int exp_num_cccds;
+
+ ble_hs_test_util_init();
+ ble_gatts_notify_test_num_events = 0;
+
+ ble_hs_test_util_reg_svcs(ble_gatts_notify_test_svcs,
+ ble_gatts_notify_test_misc_reg_cb,
+ NULL);
+ TEST_ASSERT_FATAL(ble_gatts_notify_test_chr_1_def_handle != 0);
+ TEST_ASSERT_FATAL(ble_gatts_notify_test_chr_2_def_handle != 0);
+
+ 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) {
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ 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();
+ }
+
+ /* Ensure notifications disabled on new connection. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ /* 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();
+
+ /* Ensure notification / indication state reads back correctly. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == chr1_flags);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == chr2_flags);
+
+ /* Ensure both CCCDs still persisted. */
+ if (bonding) {
+ exp_num_cccds = (chr1_flags != 0) + (chr2_flags != 0);
+ } else {
+ exp_num_cccds = 0;
+ }
+ TEST_ASSERT(ble_hs_test_util_num_cccds() == exp_num_cccds);
+}
+
+static void
+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)
+{
+ ble_hs_test_util_conn_disconnect(conn_handle);
+
+ 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);
+ }
+
+ /* 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(struct ble_gatt_register_ctxt *ctxt,
+ void *arg)
+{
+ uint16_t uuid16;
+
+ if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) {
+ uuid16 = ble_uuid_u16(ctxt->chr.chr_def->uuid);
+ switch (uuid16) {
+ case BLE_GATTS_NOTIFY_TEST_CHR_1_UUID:
+ 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.def_handle;
+ break;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ break;
+ }
+ }
+}
+
+static int
+ble_gatts_notify_test_misc_access(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(conn_handle == 0xffff);
+
+ if (attr_handle == ble_gatts_notify_test_chr_1_def_handle + 1) {
+ TEST_ASSERT(ctxt->chr ==
+ &ble_gatts_notify_test_svcs[0].characteristics[0]);
+ 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 ==
+ &ble_gatts_notify_test_svcs[0].characteristics[1]);
+ 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_FATAL(0);
+ }
+
+ return 0;
+}
+
+static void
+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;
+
+ ble_att_indicate_rsp_write(buf, sizeof buf);
+
+ 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(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const uint8_t *attr_data, int attr_len)
+{
+ struct ble_att_notify_req req;
+ struct os_mbuf *om;
+ int i;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ 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(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const uint8_t *attr_data, int attr_len)
+{
+ struct ble_att_indicate_req req;
+ struct os_mbuf *om;
+ int i;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ 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);
+}
+
+static void
+ble_gatts_notify_test_misc_verify_tx_gen(uint16_t conn_handle, int attr_idx,
+ uint8_t chr_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;
+ }
+
+ switch (chr_flags) {
+ case 0:
+ break;
+
+ case BLE_GATTS_CLT_CFG_F_NOTIFY:
+ ble_gatts_notify_test_misc_verify_tx_n(conn_handle, attr_handle,
+ attr_val, attr_len);
+ break;
+
+ 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);
+ }
+
+ 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_SELF(ble_gatts_notify_test_n)
+{
+ static const uint8_t fourbytes[] = { 1, 2, 3, 4 };
+ struct os_mbuf *om;
+ uint16_t conn_handle;
+ uint16_t flags;
+ int rc;
+
+ 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(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+ 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_NOTIFY);
+
+ /* Verify custom notification data. */
+ om = ble_hs_mbuf_from_flat(fourbytes, sizeof fourbytes);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = ble_gattc_notify_custom(conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ om);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatts_notify_test_misc_verify_tx_n(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ fourbytes,
+ sizeof fourbytes);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xab;
+ 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(
+ 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;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
+ 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(
+ 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_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;
+ ble_gatts_notify_test_chr_1_val[0] = 0xdd;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
+ 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}),
+ ble_gatts_notify_test_util_gap_event, NULL);
+
+ /* Ensure no notifications sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Ensure notifications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_notify_test_i)
+{
+ static const uint8_t fourbytes[] = { 1, 2, 3, 4 };
+ struct os_mbuf *om;
+ uint16_t conn_handle;
+ uint16_t flags;
+ int rc;
+
+ ble_gatts_notify_test_misc_init(&conn_handle, 0,
+ BLE_GATTS_CLT_CFG_F_INDICATE,
+ BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ /* Verify custom indication data. */
+ om = ble_hs_mbuf_from_flat(fourbytes, sizeof fourbytes);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = ble_gattc_indicate_custom(conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ om);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_gatts_notify_test_misc_verify_tx_i(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1,
+ fourbytes,
+ sizeof fourbytes);
+
+ /* Receive the confirmation for the indication. */
+ ble_gatts_notify_test_misc_rx_indicate_rsp(
+ conn_handle,
+ ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xab;
+ 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(
+ 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;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
+
+ /* Verify the second indication doesn't get sent until the first is
+ * confirmed.
+ */
+ 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_chr_1_def_handle + 1);
+
+ /* Verify indication sent properly. */
+ 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_chr_2_def_handle + 1);
+
+ /* Verify no pending GATT jobs. */
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ /***
+ * Disconnect, modify characteristic values, and reconnect. Ensure
+ * indications are not sent and are no longer enabled.
+ */
+
+ 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;
+ ble_gatts_notify_test_chr_1_val[0] = 0xdd;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
+ 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}),
+ ble_gatts_notify_test_util_gap_event, NULL);
+
+ /* Ensure no indications sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Ensure indications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_notify_test_bonded_n)
+{
+ uint16_t conn_handle;
+ uint16_t flags;
+
+ ble_gatts_notify_test_misc_init(&conn_handle, 1,
+ BLE_GATTS_CLT_CFG_F_NOTIFY,
+ BLE_GATTS_CLT_CFG_F_NOTIFY);
+
+ /* Disconnect. */
+ 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_num_cccds() == 2);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xdd;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
+
+ /* Reconnect; ensure notifications don't get sent while unbonded and that
+ * notifications appear disabled.
+ */
+
+ ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ 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);
+
+ /* Ensure notifications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ /* Simulate a successful encryption procedure (bonding restoration). */
+ 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(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+ 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_NOTIFY);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_notify_test_bonded_i)
+{
+ uint16_t conn_handle;
+ uint16_t flags;
+
+ ble_gatts_notify_test_misc_init(&conn_handle, 1,
+ BLE_GATTS_CLT_CFG_F_INDICATE,
+ BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ /* Disconnect. */
+ 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_num_cccds() == 2);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xab;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
+
+ /* Reconnect; ensure notifications don't get sent while unbonded and that
+ * notifications appear disabled.
+ */
+
+ ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ ble_gatts_notify_test_util_gap_event, NULL);
+
+ /* Ensure no indications sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Ensure notifications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ /* Simulate a successful encryption procedure (bonding restoration). */
+ 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.
+ */
+ 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_chr_1_def_handle + 1);
+
+ /* Verify indication sent properly. */
+ 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_chr_2_def_handle + 1);
+
+ /* Verify no pending GATT jobs. */
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ /* Ensure notifications 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);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_notify_test_bonded_i_no_ack)
+{
+ struct ble_store_value_cccd value_cccd;
+ struct ble_store_key_cccd key_cccd;
+ uint16_t conn_handle;
+ uint16_t flags;
+ int rc;
+
+ ble_gatts_notify_test_misc_init(&conn_handle, 1,
+ BLE_GATTS_CLT_CFG_F_INDICATE, 0);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xab;
+ 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(
+ 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 = *BLE_ADDR_ANY;
+ key_cccd.chr_val_handle = ble_gatts_notify_test_chr_1_def_handle + 1;
+ key_cccd.idx = 0;
+
+ rc = ble_store_read_cccd(&key_cccd, &value_cccd);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(value_cccd.value_changed);
+
+ /* Disconnect. */
+ 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_num_cccds() == 1);
+
+ /* Reconnect. */
+ ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ ble_gatts_notify_test_util_gap_event, NULL);
+
+ /* Simulate a successful encryption procedure (bonding restoration). */
+ 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_chr_1_def_handle + 1);
+
+ /* Verify no pending GATT jobs. */
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ /* Ensure indication 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 == 0);
+
+ /* Ensure CCCD still persisted. */
+ TEST_ASSERT(ble_hs_test_util_num_cccds() == 1);
+
+ /* Verify 'updated' state is no longer persisted. */
+ rc = ble_store_read_cccd(&key_cccd, &value_cccd);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(!value_cccd.value_changed);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_notify_test_disallowed)
+{
+ uint16_t chr1_val_handle;
+ uint16_t chr2_val_handle;
+ uint16_t chr3_val_handle;
+
+ const struct ble_gatt_svc_def svcs[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(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,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(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,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(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();
+
+ ble_hs_test_util_reg_svcs(svcs, NULL, NULL);
+ TEST_ASSERT_FATAL(chr1_val_handle != 0);
+ TEST_ASSERT_FATAL(chr2_val_handle != 0);
+ TEST_ASSERT_FATAL(chr3_val_handle != 0);
+
+ 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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatts_notify_suite)
+{
+ ble_gatts_notify_test_n();
+ ble_gatts_notify_test_i();
+
+ ble_gatts_notify_test_bonded_n();
+ ble_gatts_notify_test_bonded_i();
+
+ 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/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_read_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_read_test.c
new file mode 100644
index 00000000..381b39ad
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_read_test.c
@@ -0,0 +1,257 @@
+/*
+ * 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 "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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(BLE_GATTS_READ_TEST_CHR_1_UUID),
+ .access_cb = ble_gatts_read_test_util_access_1,
+ .flags = BLE_GATT_CHR_F_READ
+ }, {
+ .uuid = BLE_UUID16_DECLARE(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)
+{
+ ble_hs_test_util_init();
+
+ ble_hs_test_util_reg_svcs(ble_gatts_read_test_svcs,
+ ble_gatts_read_test_misc_reg_cb,
+ NULL);
+ 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_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_u16(ctxt->chr.chr_def->uuid);
+ 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_SELF(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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatts_read_test_suite)
+{
+ ble_gatts_read_test_case_basic();
+ ble_gatts_read_test_case_long();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_reg_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_reg_test.c
new file mode 100644
index 00000000..ea69028e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gatts_reg_test.c
@@ -0,0 +1,719 @@
+/*
+ * 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 "nimble/ble.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_GATTS_REG_TEST_MAX_ENTRIES 256
+
+struct ble_gatts_reg_test_entry {
+ uint8_t op;
+ ble_uuid_any_t uuid;
+ 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
+ble_gatts_reg_test_entries[BLE_GATTS_REG_TEST_MAX_ENTRIES];
+
+static int ble_gatts_reg_test_num_entries;
+
+static void
+ble_gatts_reg_test_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gatts_reg_test_num_entries = 0;
+}
+
+static void
+ble_gatts_reg_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+ struct ble_gatts_reg_test_entry *entry;
+
+ TEST_ASSERT_FATAL(ble_gatts_reg_test_num_entries <
+ 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:
+ ble_uuid_to_any(ctxt->svc.svc_def->uuid, &entry->uuid);
+ entry->handle = ctxt->svc.handle;
+ entry->svc = ctxt->svc.svc_def;
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ ble_uuid_to_any(ctxt->chr.chr_def->uuid, &entry->uuid);
+ 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:
+ ble_uuid_to_any(ctxt->dsc.dsc_def->uuid, &entry->uuid);
+ 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;
+ }
+}
+
+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:
+ rc = ble_gatts_find_svc(&entry->uuid.u, &svc_handle);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(svc_handle == entry->handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ rc = ble_gatts_find_chr(entry->svc->uuid, entry->chr->uuid,
+ &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:
+ rc = ble_gatts_find_dsc(entry->svc->uuid, entry->chr->uuid,
+ entry->dsc->uuid, &dsc_handle);
+ break;
+
+ default:
+ TEST_ASSERT(0);
+ break;
+ }
+}
+
+static void
+ble_gatts_reg_test_misc_lookup_bad(struct ble_gatts_reg_test_entry *entry)
+{
+ struct ble_gatts_reg_test_entry *cur;
+ ble_uuid_any_t wrong_uuid;
+ int rc;
+ int i;
+
+ switch (entry->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ /* Wrong service UUID. */
+ ble_uuid_to_any(entry->svc->uuid, &wrong_uuid);
+ wrong_uuid.u16.value++;
+ rc = ble_gatts_find_svc(&wrong_uuid.u, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ /* Correct service UUID, wrong characteristic UUID. */
+ ble_uuid_to_any(entry->chr->uuid, &wrong_uuid);
+ wrong_uuid.u16.value++;
+ rc = ble_gatts_find_chr(entry->svc->uuid, &wrong_uuid.u, NULL, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Incorrect service UUID, correct characteristic UUID. */
+ ble_uuid_to_any(entry->svc->uuid, &wrong_uuid);
+ wrong_uuid.u16.value++;
+ rc = ble_gatts_find_chr(&wrong_uuid.u, entry->chr->uuid, 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->uuid,
+ entry->chr->uuid,
+ 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->uuid,
+ cur->chr->uuid,
+ 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->uuid,
+ cur->dsc->uuid,
+ 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. */
+ ble_uuid_to_any(entry->dsc->uuid, &wrong_uuid);
+ wrong_uuid.u128.value[15]++;
+ rc = ble_gatts_find_dsc(entry->svc->uuid, entry->chr->uuid,
+ &wrong_uuid.u, NULL);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Incorrect svc UUID, correct chr/dsc UUID. */
+ ble_uuid_to_any(entry->svc->uuid, &wrong_uuid);
+ wrong_uuid.u128.value[15]++;
+ rc = ble_gatts_find_dsc(&wrong_uuid.u, entry->chr->uuid,
+ entry->dsc->uuid, 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->uuid,
+ entry->chr->uuid,
+ entry->dsc->uuid,
+ 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->uuid,
+ cur->chr->uuid,
+ entry->dsc->uuid,
+ 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->uuid,
+ cur->chr->uuid,
+ entry->dsc->uuid,
+ 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 ble_uuid_t *uuid)
+{
+ struct ble_gatts_reg_test_entry *entry;
+ int i;
+
+ for (i = 0; i < ble_gatts_reg_test_num_entries; i++) {
+ entry = ble_gatts_reg_test_entries + i;
+ if (entry->op == op && ble_uuid_cmp(&entry->uuid.u, uuid) == 0) {
+ break;
+ }
+ }
+ TEST_ASSERT_FATAL(entry != NULL);
+
+ /* 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,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg)
+{
+ return 0;
+}
+
+TEST_CASE_SELF(ble_gatts_reg_test_svc_return)
+{
+ int rc;
+
+ /*** Missing UUID. */
+ ble_gatts_reg_test_init();
+ struct ble_gatt_svc_def svcs_no_uuid[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_no_uuid, NULL, NULL);
+ 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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .includes = (const struct ble_gatt_svc_def*[]) { svcs_circ + 1, NULL },
+ }, {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .includes = (const struct ble_gatt_svc_def*[]) { svcs_circ + 0, NULL },
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_circ, NULL, NULL);
+ 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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .includes = (const struct ble_gatt_svc_def*[]) { svcs_good + 1, NULL },
+ }, {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_good, NULL, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_reg_test_chr_return)
+{
+ int rc;
+
+ /*** Missing callback. */
+ ble_gatts_reg_test_init();
+ struct ble_gatt_svc_def svcs_no_chr_cb[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .flags = BLE_GATT_CHR_F_READ,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_no_chr_cb, NULL, NULL);
+ 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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_good, NULL, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_gatts_reg_test_dsc_return)
+{
+ int rc;
+
+ /*** Missing callback. */
+ ble_gatts_reg_test_init();
+ struct ble_gatt_svc_def svcs_no_dsc_cb[] = { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .descriptors = (struct ble_gatt_dsc_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x8888),
+ .att_flags = 5,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_no_dsc_cb, NULL, NULL);
+ 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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .descriptors = (struct ble_gatt_dsc_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x8888),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .att_flags = 5,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } };
+
+ rc = ble_gatts_register_svcs(svcs_good, NULL, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+ble_gatts_reg_test_misc_svcs(struct ble_gatt_svc_def *svcs)
+{
+ 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();
+
+ /* Register all the attributes. */
+ rc = ble_gatts_register_svcs(svcs, ble_gatts_reg_test_misc_reg_cb,
+ NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Verify that the appropriate callbacks were executed. */
+ for (svc = svcs; svc->type != BLE_GATT_SVC_TYPE_END; svc++) {
+ ble_gatts_reg_test_misc_verify_entry(BLE_GATT_REGISTER_OP_SVC,
+ svc->uuid);
+
+ if (svc->characteristics != NULL) {
+ for (chr = svc->characteristics; chr->uuid != NULL; chr++) {
+ ble_gatts_reg_test_misc_verify_entry(BLE_GATT_REGISTER_OP_CHR,
+ chr->uuid);
+
+ if (chr->descriptors != NULL) {
+ for (dsc = chr->descriptors; dsc->uuid != NULL; dsc++) {
+ ble_gatts_reg_test_misc_verify_entry(
+ BLE_GATT_REGISTER_OP_DSC, dsc->uuid);
+ }
+ }
+ }
+ }
+ }
+}
+
+TEST_CASE_SELF(ble_gatts_reg_test_svc_cb)
+{
+ /*** 1 primary. */
+ ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ }, {
+ 0
+ } });
+
+ /*** 3 primary. */
+ ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ }, {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x2234),
+ }, {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x3234),
+ }, {
+ 0
+ } });
+
+ /*** 1 primary, 1 secondary. */
+ ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ }, {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x2222),
+ }, {
+ 0
+ } });
+
+ /*** 1 primary, 1 secondary, 1 include. */
+ struct ble_gatt_svc_def svcs[] = {
+ [0] = {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .includes = (const struct ble_gatt_svc_def*[]) { svcs + 1, NULL, },
+ },
+ [1] = {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x2222),
+ }, {
+ 0
+ }
+ };
+ ble_gatts_reg_test_misc_svcs(svcs);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } });
+
+ /*** 3 characteristics. */
+ ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x1111),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 0,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x2222),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_WRITE,
+ .val_handle = val_handles + 1,
+ }, {
+ 0
+ } },
+ }, {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x5678),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x3333),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_READ,
+ .val_handle = val_handles + 2,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(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[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x111a),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } });
+
+ /*** 5+ descriptors. */
+ ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(0x1234),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(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[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x111a),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ 0
+ } },
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x2222),
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ .flags = BLE_GATT_CHR_F_WRITE,
+ .val_handle = val_handles + 1,
+ }, {
+ 0
+ } },
+ }, {
+ .type = BLE_GATT_SVC_TYPE_SECONDARY,
+ .uuid = BLE_UUID16_DECLARE(0x5678),
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ .uuid = BLE_UUID16_DECLARE(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[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x333a),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x333b),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x333c),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x333e),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ 0
+ } },
+ }, {
+ .uuid = BLE_UUID16_DECLARE(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[]) { {
+ .uuid = BLE_UUID16_DECLARE(0x444a),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x444b),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x444c),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ .uuid = BLE_UUID16_DECLARE(0x444e),
+ .att_flags = 5,
+ .access_cb = ble_gatts_reg_test_misc_dummy_access,
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } },
+ }, {
+ 0
+ } });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_gatts_reg_suite)
+{
+ ble_gatts_reg_test_svc_return();
+ ble_gatts_reg_test_chr_return();
+ ble_gatts_reg_test_dsc_return();
+
+ ble_gatts_reg_test_svc_cb();
+ ble_gatts_reg_test_chr_cb();
+ ble_gatts_reg_test_dsc_cb();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_adv_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_adv_test.c
new file mode 100644
index 00000000..b267dc2a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_adv_test.c
@@ -0,0 +1,1280 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_ADV_TEST_DATA_OFF 4
+
+#define BLE_HCI_SET_ADV_DATA_LEN (32)
+#define BLE_HCI_SET_SCAN_RSP_DATA_LEN (32)
+
+static void
+ble_hs_adv_test_misc_verify_tx_adv_data_hdr(uint8_t *cmd, int data_len)
+{
+ uint16_t opcode;
+
+ opcode = get_le16(cmd + 0);
+ TEST_ASSERT(BLE_HCI_OGF(opcode) == BLE_HCI_OGF_LE);
+ TEST_ASSERT(BLE_HCI_OCF(opcode) == BLE_HCI_OCF_LE_SET_ADV_DATA);
+
+ TEST_ASSERT(cmd[2] == BLE_HCI_SET_ADV_DATA_LEN);
+ TEST_ASSERT(cmd[3] == data_len);
+}
+
+static void
+ble_hs_adv_test_misc_verify_tx_rsp_data_hdr(uint8_t *cmd, int data_len)
+{
+ uint16_t opcode;
+
+ opcode = get_le16(cmd + 0);
+ TEST_ASSERT(BLE_HCI_OGF(opcode) == BLE_HCI_OGF_LE);
+ TEST_ASSERT(BLE_HCI_OCF(opcode) == BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA);
+
+ TEST_ASSERT(cmd[2] == BLE_HCI_SET_SCAN_RSP_DATA_LEN);
+ TEST_ASSERT(cmd[3] == data_len);
+}
+
+static void
+ble_hs_adv_test_misc_verify_tx_field(uint8_t *cmd, uint8_t type,
+ uint8_t val_len, void *val)
+{
+ TEST_ASSERT(cmd[0] == val_len + 1);
+ TEST_ASSERT(cmd[1] == type);
+ TEST_ASSERT(memcmp(cmd + 2, val, val_len) == 0);
+}
+
+struct ble_hs_adv_test_field {
+ uint8_t type; /* 0 indicates end of array. */
+ uint8_t *val;
+ uint8_t val_len;
+};
+
+static int
+ble_hs_adv_test_misc_calc_data_len(struct ble_hs_adv_test_field *fields)
+{
+ struct ble_hs_adv_test_field *field;
+ int len;
+
+ len = 0;
+ if (fields != NULL) {
+ for (field = fields; field->type != 0; field++) {
+ len += 2 + field->val_len;
+ }
+ }
+
+ return len;
+}
+
+static void
+ble_hs_adv_test_misc_verify_tx_fields(uint8_t *cmd,
+ struct ble_hs_adv_test_field *fields)
+{
+ struct ble_hs_adv_test_field *field;
+
+ for (field = fields; field->type != 0; field++) {
+ ble_hs_adv_test_misc_verify_tx_field(cmd, field->type, field->val_len,
+ field->val);
+ cmd += 2 + field->val_len;
+ }
+}
+
+static void
+ble_hs_adv_test_misc_verify_tx_adv_data(struct ble_hs_adv_test_field *fields)
+{
+ int data_len;
+ uint8_t *cmd;
+
+ cmd = ble_hs_test_util_hci_out_last();
+ TEST_ASSERT_FATAL(cmd != NULL);
+
+ data_len = ble_hs_adv_test_misc_calc_data_len(fields);
+ ble_hs_adv_test_misc_verify_tx_adv_data_hdr(cmd, data_len);
+ if (fields != NULL) {
+ ble_hs_adv_test_misc_verify_tx_fields(cmd + BLE_ADV_TEST_DATA_OFF,
+ fields);
+ }
+}
+
+static void
+ble_hs_adv_test_misc_verify_tx_rsp_data(struct ble_hs_adv_test_field *fields)
+{
+ int data_len;
+ uint8_t *cmd;
+
+ cmd = ble_hs_test_util_hci_out_last();
+ TEST_ASSERT_FATAL(cmd != NULL);
+
+ data_len = ble_hs_adv_test_misc_calc_data_len(fields);
+ ble_hs_adv_test_misc_verify_tx_rsp_data_hdr(cmd, data_len);
+ if (fields != NULL) {
+ ble_hs_adv_test_misc_verify_tx_fields(cmd + BLE_ADV_TEST_DATA_OFF,
+ fields);
+ }
+}
+
+static void
+ble_hs_adv_test_misc_tx_and_verify_data(
+ uint8_t disc_mode,
+ struct ble_hs_adv_fields *adv_fields,
+ struct ble_hs_adv_test_field *test_adv_fields,
+ 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();
+
+ 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, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_adv_test_misc_verify_tx_adv_data(test_adv_fields);
+
+ if (test_rsp_fields != NULL) {
+ rc = ble_hs_test_util_adv_rsp_set_fields(rsp_fields, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_adv_test_misc_verify_tx_rsp_data(test_rsp_fields);
+ }
+
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
+ BLE_HS_FOREVER, NULL, NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Discard the adv-enable command. */
+ ble_hs_test_util_hci_out_last();
+
+ /* 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_OWN_ADDR_PUBLIC, NULL, &adv_params,
+ BLE_HS_FOREVER, NULL, NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Discard the adv-enable command. */
+ ble_hs_test_util_hci_out_last();
+}
+
+TEST_CASE_SELF(ble_hs_adv_test_case_user)
+{
+ struct ble_hs_adv_fields adv_fields;
+ struct ble_hs_adv_fields rsp_fields;
+
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+
+ /*** Complete 16-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+ adv_fields.uuids16 = (ble_uuid16_t[]) {
+ BLE_UUID16_INIT(0x0001),
+ BLE_UUID16_INIT(0x1234),
+ BLE_UUID16_INIT(0x54ab)
+ };
+ adv_fields.num_uuids16 = 3;
+ adv_fields.uuids16_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS16,
+ .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 },
+ .val_len = 6,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Incomplete 16-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uuids16 = (ble_uuid16_t[]) {
+ BLE_UUID16_INIT(0x0001),
+ BLE_UUID16_INIT(0x1234),
+ BLE_UUID16_INIT(0x54ab)
+ };
+ adv_fields.num_uuids16 = 3;
+ adv_fields.uuids16_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16,
+ .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 },
+ .val_len = 6,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Complete 32-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uuids32 = (ble_uuid32_t[]) {
+ BLE_UUID32_INIT(0x12345678),
+ BLE_UUID32_INIT(0xabacadae)
+ };
+ adv_fields.num_uuids32 = 2;
+ adv_fields.uuids32_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS32,
+ .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab },
+ .val_len = 8,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Incomplete 32-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uuids32 = (ble_uuid32_t[]) {
+ BLE_UUID32_INIT(0x12345678),
+ BLE_UUID32_INIT(0xabacadae)
+ };
+ adv_fields.num_uuids32 = 2;
+ adv_fields.uuids32_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS32,
+ .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab },
+ .val_len = 8,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Complete 128-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uuids128 = (ble_uuid128_t[]) {
+ BLE_UUID128_INIT(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
+ };
+ adv_fields.num_uuids128 = 1;
+ adv_fields.uuids128_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS128,
+ .val = (uint8_t[]) {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ .val_len = 16,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Incomplete 128-bit service class UUIDs. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uuids128 = BLE_UUID128(BLE_UUID128_DECLARE(
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ ));
+ adv_fields.num_uuids128 = 1;
+ adv_fields.uuids128_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS128,
+ .val = (uint8_t[]) {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ .val_len = 16,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Complete name. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.name = (uint8_t *)"myname";
+ adv_fields.name_len = 6;
+ adv_fields.name_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_NAME,
+ .val = (uint8_t*)"myname",
+ .val_len = 6,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Incomplete name. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.name = (uint8_t *)"myname";
+ adv_fields.name_len = 6;
+ adv_fields.name_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_NAME,
+ .val = (uint8_t*)"myname",
+ .val_len = 6,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** Slave interval range. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x16 - Service data - 16-bit UUID. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ 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;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x17 - Public target address. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ 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;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x19 - Appearance. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.appearance = 0x1234;
+ adv_fields.appearance_is_present = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x1a - Advertising interval. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.adv_itvl = 0x1234;
+ adv_fields.adv_itvl_is_present = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x20 - Service data - 32-bit UUID. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ 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;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x21 - Service data - 128-bit UUID. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ 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 };
+ adv_fields.svc_data_uuid128_len = 18;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .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 },
+ .val_len = 18,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0x24 - URI. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.uri = (uint8_t[]){ 1,2,3,4 };
+ adv_fields.uri_len = 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ /*** 0xff - Manufacturer specific data. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ adv_fields.mfg_data = (uint8_t[]){ 1,2,3,4 };
+ adv_fields.mfg_data_len = 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .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,
+ },
+ { 0 },
+ }, &rsp_fields, NULL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_adv_test_case_user_rsp)
+{
+ struct ble_hs_adv_fields rsp_fields;
+ struct ble_hs_adv_fields adv_fields;
+
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ adv_fields.tx_pwr_lvl_is_present = 1;
+
+ /*** Complete 16-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids16 = (ble_uuid16_t[]) {
+ BLE_UUID16_INIT(0x0001),
+ BLE_UUID16_INIT(0x1234),
+ BLE_UUID16_INIT(0x54ab)
+ };
+ rsp_fields.num_uuids16 = 3;
+ rsp_fields.uuids16_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS16,
+ .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 },
+ .val_len = 6,
+ },
+ { 0 },
+ });
+
+ /*** Incomplete 16-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids16 = (ble_uuid16_t[]) {
+ BLE_UUID16_INIT(0x0001),
+ BLE_UUID16_INIT(0x1234),
+ BLE_UUID16_INIT(0x54ab)
+ };
+ rsp_fields.num_uuids16 = 3;
+ rsp_fields.uuids16_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16,
+ .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 },
+ .val_len = 6,
+ },
+ { 0 },
+ });
+
+ /*** Complete 32-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids32 = (ble_uuid32_t[]) {
+ BLE_UUID32_INIT(0x12345678),
+ BLE_UUID32_INIT(0xabacadae)
+ };
+ rsp_fields.num_uuids32 = 2;
+ rsp_fields.uuids32_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS32,
+ .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab },
+ .val_len = 8,
+ },
+ { 0 },
+ });
+
+ /*** Incomplete 32-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids32 = (ble_uuid32_t[]) {
+ BLE_UUID32_INIT(0x12345678),
+ BLE_UUID32_INIT(0xabacadae)
+ };
+ rsp_fields.num_uuids32 = 2;
+ rsp_fields.uuids32_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS32,
+ .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab },
+ .val_len = 8,
+ },
+ { 0 },
+ });
+
+ /*** Complete 128-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids128 = (ble_uuid128_t[]) {
+ BLE_UUID128_INIT(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
+ };
+ rsp_fields.num_uuids128 = 1;
+ rsp_fields.uuids128_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_UUIDS128,
+ .val = (uint8_t[]) {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ .val_len = 16,
+ },
+ { 0 },
+ });
+
+ /*** Incomplete 128-bit service class UUIDs. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uuids128 = (ble_uuid128_t[]) {
+ BLE_UUID128_INIT(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
+ };
+ rsp_fields.num_uuids128 = 1;
+ rsp_fields.uuids128_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS128,
+ .val = (uint8_t[]) {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ .val_len = 16,
+ },
+ { 0 },
+ });
+
+ /*** Complete name. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.name = (uint8_t *)"myname";
+ rsp_fields.name_len = 6;
+ rsp_fields.name_is_complete = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_COMP_NAME,
+ .val = (uint8_t*)"myname",
+ .val_len = 6,
+ },
+ { 0 },
+ });
+
+ /*** Incomplete name. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.name = (uint8_t *)"myname";
+ rsp_fields.name_len = 6;
+ rsp_fields.name_is_complete = 0;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_INCOMP_NAME,
+ .val = (uint8_t*)"myname",
+ .val_len = 6,
+ },
+ { 0 },
+ });
+
+ /*** Slave interval range. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE,
+ .val = (uint8_t[]) { 1,2,3,4 },
+ .val_len = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN,
+ },
+ { 0 },
+ });
+
+ /*** 0x16 - Service data - 16-bit UUID. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.svc_data_uuid16 = (uint8_t[]){ 1,2,3,4 };
+ rsp_fields.svc_data_uuid16_len = 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16,
+ .val = (uint8_t[]) { 1,2,3,4 },
+ .val_len = 4,
+ },
+ { 0 },
+ });
+
+ /*** 0x17 - Public target address. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.public_tgt_addr = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 };
+ rsp_fields.num_public_tgt_addrs = 2;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .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,
+ },
+ { 0 },
+ });
+
+ /*** 0x19 - Appearance. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.appearance = 0x1234;
+ rsp_fields.appearance_is_present = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_APPEARANCE,
+ .val = (uint8_t[]){ 0x34, 0x12 },
+ .val_len = BLE_HS_ADV_APPEARANCE_LEN,
+ },
+ { 0 },
+ });
+
+ /*** 0x1a - Advertising interval. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.adv_itvl = 0x1234;
+ rsp_fields.adv_itvl_is_present = 1;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_ADV_ITVL,
+ .val = (uint8_t[]){ 0x34, 0x12 },
+ .val_len = BLE_HS_ADV_ADV_ITVL_LEN,
+ },
+ { 0 },
+ });
+
+ /*** 0x20 - Service data - 32-bit UUID. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.svc_data_uuid32 = (uint8_t[]){ 1,2,3,4,5 };
+ rsp_fields.svc_data_uuid32_len = 5;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32,
+ .val = (uint8_t[]) { 1,2,3,4,5 },
+ .val_len = 5,
+ },
+ { 0 },
+ });
+
+ /*** 0x21 - Service data - 128-bit UUID. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.svc_data_uuid128 =
+ (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };
+ rsp_fields.svc_data_uuid128_len = 18;
+
+ 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 },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .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 },
+ .val_len = 18,
+ },
+ { 0 },
+ });
+
+ /*** 0x24 - URI. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.uri = (uint8_t[]){ 1,2,3,4 };
+ rsp_fields.uri_len = 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_URI,
+ .val = (uint8_t[]) { 1,2,3,4 },
+ .val_len = 4,
+ },
+ { 0 },
+ });
+
+ /*** 0xff - Manufacturer specific data. */
+ memset(&rsp_fields, 0, sizeof rsp_fields);
+ rsp_fields.mfg_data = (uint8_t[]){ 1,2,3,4 };
+ rsp_fields.mfg_data_len = 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_FLAGS,
+ .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP },
+ .val_len = 1,
+ },
+ {
+ .type = BLE_HS_ADV_TYPE_TX_PWR_LVL,
+ .val = (uint8_t[]){ 0 },
+ .val_len = 1,
+ },
+ { 0 },
+ },
+ &rsp_fields,
+ (struct ble_hs_adv_test_field[]) {
+ {
+ .type = BLE_HS_ADV_TYPE_MFG_DATA,
+ .val = (uint8_t[]) { 1,2,3,4 },
+ .val_len = 4,
+ },
+ { 0 },
+ });
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(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);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_hs_adv_test_suite)
+{
+ ble_hs_adv_test_case_user();
+ ble_hs_adv_test_case_user_rsp();
+ ble_hs_adv_test_case_user_full_payload();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_conn_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_conn_test.c
new file mode 100644
index 00000000..04137d4f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_conn_test.c
@@ -0,0 +1,224 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+#include "../src/ble_gap_priv.h"
+
+static int
+ble_hs_conn_test_util_any(void)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_first();
+ ble_hs_unlock();
+
+ return conn != NULL;
+}
+
+TEST_CASE_SELF(ble_hs_conn_test_direct_connect_success)
+{
+ struct ble_gap_conn_complete evt;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ ble_addr_t addr = { BLE_ADDR_PUBLIC, { 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. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
+ &addr, 0, NULL, NULL, NULL, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_gap_master_in_progress());
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Receive successful connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
+ memcpy(evt.peer_addr, addr.val, 6);
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_first();
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_handle == 2);
+ TEST_ASSERT(memcmp(conn->bhc_peer_addr.val, addr.val, 6) == 0);
+
+ chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+ TEST_ASSERT(chan->my_mtu == MYNEWT_VAL(BLE_ATT_PREFERRED_MTU));
+ TEST_ASSERT(chan->peer_mtu == 0);
+
+ ble_hs_unlock();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_conn_test_direct_connectable_success)
+{
+ struct ble_gap_conn_complete evt;
+ struct ble_gap_adv_params adv_params;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ ble_addr_t addr = { BLE_ADDR_PUBLIC, { 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_gap_adv_active());
+ TEST_ASSERT(!ble_hs_conn_test_util_any());
+
+ /* Initiate advertising. */
+ 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_OWN_ADDR_PUBLIC,
+ &addr, &adv_params, BLE_HS_FOREVER,
+ NULL, NULL, 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Receive successful connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
+ memcpy(evt.peer_addr, addr.val, 6);
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(!ble_gap_master_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_peer_addr.val, addr.val, 6) == 0);
+
+ chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+ TEST_ASSERT(chan->my_mtu == MYNEWT_VAL(BLE_ATT_PREFERRED_MTU));
+ TEST_ASSERT(chan->peer_mtu == 0);
+
+ ble_hs_unlock();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_conn_test_undirect_connectable_success)
+{
+ struct ble_hs_adv_fields adv_fields;
+ struct ble_gap_conn_complete evt;
+ struct ble_gap_adv_params adv_params;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ ble_addr_t addr = { BLE_ADDR_PUBLIC, { 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_gap_adv_active());
+ TEST_ASSERT(!ble_hs_conn_test_util_any());
+
+ /* Initiate advertising. */
+ memset(&adv_fields, 0, sizeof adv_fields);
+ adv_fields.tx_pwr_lvl_is_present = 1;
+ rc = ble_hs_test_util_adv_set_fields(&adv_fields, 0, 0);
+ TEST_ASSERT_FATAL(rc == 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_OWN_ADDR_PUBLIC,
+ &addr, &adv_params,
+ BLE_HS_FOREVER,
+ NULL, NULL, 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(ble_gap_adv_active());
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Receive successful connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
+ memcpy(evt.peer_addr, addr.val, 6);
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(!ble_gap_master_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_peer_addr.val, addr.val, 6) == 0);
+
+ chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+ TEST_ASSERT(chan->my_mtu == MYNEWT_VAL(BLE_ATT_PREFERRED_MTU));
+ TEST_ASSERT(chan->peer_mtu == 0);
+
+ ble_hs_unlock();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_hs_conn_suite)
+{
+ ble_hs_conn_test_direct_connect_success();
+ ble_hs_conn_test_direct_connectable_success();
+ ble_hs_conn_test_undirect_connectable_success();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_hci_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_hci_test.c
new file mode 100644
index 00000000..5f72742c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_hci_test.c
@@ -0,0 +1,342 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+#include "ble_hs_test.h"
+#include "testutil/testutil.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_HCI_READ_RSSI_ACK_PARAM_LEN (3) /* No status byte. */
+
+TEST_CASE_SELF(ble_hs_hci_test_event_bad)
+{
+ 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 = ble_hs_hci_evt_process((void*)buf);
+ TEST_ASSERT(rc == BLE_HS_ENOTSUP);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_hci_test_rssi)
+{
+ uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN];
+ uint16_t opcode;
+ int8_t rssi;
+ int rc;
+
+ opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_STATUS_PARAMS,
+ BLE_HCI_OCF_RD_RSSI);
+
+ /*** Success. */
+ /* Connection handle. */
+ put_le16(params + 0, 1);
+
+ /* RSSI. */
+ params[2] = -8;
+
+ ble_hs_test_util_hci_ack_set_params(opcode, 0, params, sizeof params);
+
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(rssi == -8);
+
+ /*** Failure: incorrect connection handle. */
+ put_le16(params + 0, 99);
+
+ ble_hs_test_util_hci_ack_set_params(opcode, 0, params, sizeof params);
+
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
+ TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
+
+ /*** Failure: params too short. */
+ ble_hs_test_util_hci_ack_set_params(opcode, 0, params, sizeof params - 1);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
+ TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
+
+ /*** Failure: params too long. */
+ ble_hs_test_util_hci_ack_set_params(opcode, 0, params, sizeof params + 1);
+ rc = ble_hs_hci_util_read_rssi(1, &rssi);
+ TEST_ASSERT(rc == BLE_HS_ECONTROLLER);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_hci_acl_one_conn)
+{
+ struct ble_hs_test_util_hci_num_completed_pkts_entry ncpe[2];
+ uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+ uint8_t data[256];
+ int rc;
+ int i;
+
+ memset(ncpe, 0, sizeof(ncpe));
+ for (i = 0; i < sizeof data; i++) {
+ data[i] = i;
+ }
+
+ ble_hs_test_util_init();
+
+ /* The controller has room for five 20-byte payloads. */
+ rc = ble_hs_hci_set_buf_sz(20, 5);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5);
+
+ ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+
+ /* Ensure the ATT doesn't truncate our data packets. */
+ ble_hs_test_util_set_att_mtu(1, 256);
+
+ /* Send two 3-byte data packets. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 3);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 3);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 3);
+
+ /* Send fragmented packet (two fragments). */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 25);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 1);
+
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* Receive a number-of-completed-packets event. Ensure available buffer
+ * count increases.
+ */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 3;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 4);
+
+ /* Use all remaining buffers (four fragments). */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 70);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+
+ /* Attempt to transmit eight more fragments. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 160);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+
+ /* Receive number-of-completed-packets: 5. */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 5;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+
+ /* Receive number-of-completed-packets: 4. */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 5;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 1);
+
+ /* Ensure the stalled fragments were sent in the expected order. */
+ ble_hs_test_util_verify_tx_write_cmd(100, data, 70);
+ ble_hs_test_util_verify_tx_write_cmd(100, data, 160);
+
+ /* Receive a disconnection-complete event. Ensure available buffer count
+ * increases.
+ */
+ ble_hs_test_util_hci_rx_disconn_complete_event(1, 0, BLE_ERR_CONN_TERM_LOCAL);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_hci_acl_two_conn)
+{
+ struct ble_hs_test_util_hci_num_completed_pkts_entry ncpe[2];
+ const struct ble_hs_conn *conn1;
+ const struct ble_hs_conn *conn2;
+ uint8_t peer_addr1[6] = { 1, 2, 3, 4, 5, 6 };
+ uint8_t peer_addr2[6] = { 2, 3, 4, 5, 6, 7 };
+ uint8_t data[256];
+ int rc;
+ int i;
+
+ memset(ncpe, 0, sizeof(ncpe));
+ for (i = 0; i < sizeof data; i++) {
+ data[i] = i;
+ }
+
+ ble_hs_test_util_init();
+
+ /* The controller has room for five 20-byte payloads*/
+ rc = ble_hs_hci_set_buf_sz(20, 5);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5);
+
+ ble_hs_test_util_create_conn(1, peer_addr1, NULL, NULL);
+ ble_hs_test_util_create_conn(2, peer_addr2, NULL, NULL);
+
+ /* This test inspects the connection objects after unlocking the host
+ * mutex. It is not OK for real code to do this, but this test can assume
+ * the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn1 = ble_hs_conn_find_assert(1);
+ conn2 = ble_hs_conn_find_assert(2);
+ ble_hs_unlock();
+
+ /* Ensure the ATT doesn't truncate our data packets. */
+ ble_hs_test_util_set_att_mtu(1, 256);
+ ble_hs_test_util_set_att_mtu(2, 256);
+
+ /* Tx two fragments over connection 1. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data, 25);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 3);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /* Tx two fragments over connection 2. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(2, 100, data + 10, 25);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 1);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /* Tx four fragments over connection 2. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(2, 100, data + 20, 70);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG);
+
+ /* Tx four fragments over connection 1. */
+ rc = ble_hs_test_util_gatt_write_no_rsp_flat(1, 100, data + 30, 70);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /**
+ * controller: (11 222)
+ * conn 1: 1111
+ * conn 2: 222
+ */
+
+ /* Receive number-of-completed-packets: conn=2, num-pkts=1. */
+ ncpe[0].handle_id = 2;
+ ncpe[0].num_pkts = 1;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: (11 222)
+ * conn 1: 1111
+ * conn 2: 22
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+ TEST_ASSERT_FATAL(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG);
+
+ /* Receive number-of-completed-packets: conn=1, num-pkts=1. */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 1;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: (1 2222)
+ * conn 1: 1111
+ * conn 2: 2
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+ TEST_ASSERT_FATAL(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG);
+
+ /* Receive number-of-completed-packets: conn=1, num-pkts=1. */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 1;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: (22222)
+ * conn 1: 1111
+ * conn 2: -
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+ TEST_ASSERT_FATAL(!(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /* Receive number-of-completed-packets: conn=2, num-pkts=3. */
+ ncpe[0].handle_id = 2;
+ ncpe[0].num_pkts = 3;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: (11122)
+ * conn 1: 1
+ * conn 2: -
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 0);
+ TEST_ASSERT_FATAL(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG);
+ TEST_ASSERT_FATAL(!(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /* Receive number-of-completed-packets: conn=2, num-pkts=2. */
+ ncpe[0].handle_id = 2;
+ ncpe[0].num_pkts = 2;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: (1111)
+ * conn 1: -
+ * conn 2: -
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 1);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+ TEST_ASSERT_FATAL(!(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /* Receive number-of-completed-packets: conn=1, num-pkts=4. */
+ ncpe[0].handle_id = 1;
+ ncpe[0].num_pkts = 4;
+ ble_hs_test_util_hci_rx_num_completed_pkts_event(ncpe);
+
+ /**
+ * controller: ()
+ * conn 1: -
+ * conn 2: -
+ */
+ TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5);
+ TEST_ASSERT_FATAL(!(conn1->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+ TEST_ASSERT_FATAL(!(conn2->bhc_flags & BLE_HS_CONN_F_TX_FRAG));
+
+ /*** Verify payloads. */
+ ble_hs_test_util_verify_tx_write_cmd(100, data, 25);
+ ble_hs_test_util_verify_tx_write_cmd(100, data + 10, 25);
+ ble_hs_test_util_verify_tx_write_cmd(100, data + 20, 70);
+ ble_hs_test_util_verify_tx_write_cmd(100, data + 30, 70);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_hs_hci_suite)
+{
+ ble_hs_hci_test_event_bad();
+ ble_hs_hci_test_rssi();
+ ble_hs_hci_acl_one_conn();
+ ble_hs_hci_acl_two_conn();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_id_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_id_test.c
new file mode 100644
index 00000000..c5fe6ce2
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_id_test.c
@@ -0,0 +1,124 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "host/ble_hs_adv.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+static int
+ble_hs_id_test_util_infer_auto(int privacy, uint8_t *own_addr_type)
+{
+ int rc;
+
+ rc = ble_hs_id_infer_auto(privacy, own_addr_type);
+
+ return rc;
+}
+
+TEST_CASE_SELF(ble_hs_id_test_case_auto_none)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ /* Clear public address. */
+ ble_hs_id_set_pub((uint8_t[6]){ 0, 0, 0, 0, 0, 0 });
+
+ rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOADDR);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_id_test_case_auto_public)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_PUBLIC);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_id_test_case_auto_random)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ /* Configure a random address. */
+ ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 });
+
+ rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RANDOM);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_id_test_case_auto_rpa_pub)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ rc = ble_hs_id_test_util_infer_auto(1, &own_addr_type);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_hs_id_test_case_auto_rpa_rnd)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ ble_hs_test_util_init();
+
+ /* Configure a random address. */
+ ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 });
+
+ rc = ble_hs_id_test_util_infer_auto(1, &own_addr_type);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_hs_id_test_suite_auto)
+{
+ ble_hs_id_test_case_auto_none();
+ ble_hs_id_test_case_auto_public();
+ ble_hs_id_test_case_auto_random();
+ ble_hs_id_test_case_auto_rpa_pub();
+ ble_hs_id_test_case_auto_rpa_rnd();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_pvcy_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_pvcy_test.c
new file mode 100644
index 00000000..79b93b83
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_pvcy_test.c
@@ -0,0 +1,509 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_HS_PVCY_TEST_MAX_GAP_EVENTS 256
+static struct ble_gap_event
+ble_hs_pvcy_test_gap_events[BLE_HS_PVCY_TEST_MAX_GAP_EVENTS];
+static int ble_hs_pvcy_test_num_gap_events;
+
+static void
+ble_hs_pvcy_test_util_init(void)
+{
+ ble_hs_test_util_init();
+ ble_hs_pvcy_test_num_gap_events = 0;
+}
+
+static int
+ble_hs_pvcy_test_util_gap_event(struct ble_gap_event *event, void *arg)
+{
+ TEST_ASSERT_FATAL(ble_hs_pvcy_test_num_gap_events <
+ BLE_HS_PVCY_TEST_MAX_GAP_EVENTS);
+ ble_hs_pvcy_test_gap_events[ble_hs_pvcy_test_num_gap_events++] = *event;
+
+ return 0;
+}
+
+static void
+ble_hs_pvcy_test_util_all_gap_procs(int adv_status,
+ int conn_status,
+ int disc_status)
+{
+ struct ble_gap_disc_params disc_params;
+ ble_addr_t peer_addr;
+ int rc;
+
+ /* Advertise. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ NULL, &ble_hs_test_util_adv_params,
+ BLE_HS_FOREVER,
+ ble_hs_pvcy_test_util_gap_event,
+ NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == adv_status);
+
+ if (rc == 0) {
+ rc = ble_hs_test_util_adv_stop(0);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /* Connect. */
+ peer_addr = (ble_addr_t){ BLE_ADDR_PUBLIC, {1,2,3,4,5,6} };
+ rc = ble_hs_test_util_connect(BLE_ADDR_PUBLIC, &peer_addr,
+ BLE_HS_FOREVER, NULL,
+ ble_hs_pvcy_test_util_gap_event, NULL, 0);
+ TEST_ASSERT_FATAL(rc == conn_status);
+
+ if (rc == 0) {
+ ble_hs_test_util_conn_cancel_full();
+ }
+
+ /* Discover. */
+ disc_params = (struct ble_gap_disc_params){ 0 };
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, ble_hs_pvcy_test_util_gap_event,
+ NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == disc_status);
+
+ if (rc == 0) {
+ rc = ble_hs_test_util_disc_cancel(0);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+}
+
+static void
+ble_hs_pvcy_test_util_add_irk_set_acks(bool scanning, bool connecting)
+{
+ ble_hs_test_util_hci_ack_append(
+ BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE), 0);
+
+ if (connecting) {
+ ble_hs_test_util_hci_ack_append(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
+ 0);
+ }
+
+ if (scanning) {
+ ble_hs_test_util_hci_ack_append(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ 0);
+ }
+
+ ble_hs_test_util_hci_ack_append(
+ BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST), 0);
+ ble_hs_test_util_hci_ack_append(
+ BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PRIVACY_MODE), 0);
+}
+
+static void
+ble_hs_pvcy_test_util_start_host(int num_expected_irks)
+{
+ int rc;
+ int i;
+
+ /* Clear our IRK. This ensures the full startup sequence, including
+ * setting the default IRK, takes place. We need this so that we can plan
+ * which HCI acks to fake.
+ */
+ rc = ble_hs_test_util_set_our_irk((uint8_t[16]){0}, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_test_util_hci_out_clear();
+
+ ble_hs_test_util_hci_ack_set_startup();
+
+ for (i = 0; i < num_expected_irks; i++) {
+ ble_hs_pvcy_test_util_add_irk_set_acks(false, false);
+ }
+
+ ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF;
+ rc = ble_hs_start();
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Discard startup HCI commands. */
+ ble_hs_test_util_hci_out_adj(ble_hs_test_util_hci_startup_seq_cnt());
+}
+
+static void
+ble_hs_pvcy_test_util_add_irk_verify_tx(const ble_addr_t *peer_addr,
+ const uint8_t *peer_irk,
+ const uint8_t *local_irk,
+ bool scanning,
+ bool connecting)
+{
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_ENABLE,
+ NULL);
+
+ if (connecting) {
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
+ NULL);
+ }
+
+ if (scanning) {
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
+ NULL);
+ }
+
+ ble_hs_test_util_hci_verify_tx_add_irk(peer_addr->type,
+ peer_addr->val,
+ peer_irk,
+ local_irk);
+
+ ble_hs_test_util_hci_verify_tx_set_priv_mode(peer_addr->type,
+ peer_addr->val,
+ BLE_GAP_PRIVATE_MODE_DEVICE);
+}
+
+static void
+ble_hs_pvcy_test_util_add_irk(const ble_addr_t *peer_addr,
+ const uint8_t *peer_irk,
+ const uint8_t *local_irk,
+ bool scanning,
+ bool connecting)
+{
+ int num_acks;
+ int rc;
+
+ ble_hs_pvcy_test_util_add_irk_set_acks(scanning, connecting);
+
+ rc = ble_hs_pvcy_add_entry(peer_addr->val, peer_addr->type, peer_irk);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ num_acks = 3;
+ if (scanning) {
+ num_acks++;
+ }
+ if (connecting) {
+ num_acks++;
+ }
+ ble_hs_test_util_hci_out_adj(-num_acks);
+ ble_hs_pvcy_test_util_add_irk_verify_tx(peer_addr, peer_irk, local_irk,
+ scanning, connecting);
+}
+
+static void
+ble_hs_pvcy_test_util_add_arbitrary_irk(bool scanning, bool connecting)
+{
+ ble_addr_t peer_addr;
+
+ peer_addr = (ble_addr_t) {
+ .type = BLE_ADDR_PUBLIC,
+ .val = {1,2,3,4,5,6},
+ };
+ ble_hs_pvcy_test_util_add_irk(
+ &peer_addr,
+ (uint8_t[16]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},
+ ble_hs_pvcy_default_irk,
+ scanning,
+ connecting);
+}
+
+static void
+ble_hs_pvcy_test_util_restore_irk(const struct ble_store_value_sec *value_sec,
+ bool scanning,
+ bool connecting)
+{
+ int rc;
+
+ ble_hs_pvcy_test_util_add_irk_set_acks(scanning, connecting);
+
+ rc = ble_store_write_peer_sec(value_sec);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_irk_verify_tx(&value_sec->peer_addr,
+ value_sec->irk,
+ ble_hs_pvcy_default_irk,
+ scanning,
+ connecting);
+}
+
+TEST_CASE_SELF(ble_hs_pvcy_test_case_restore_irks)
+{
+ struct ble_store_value_sec value_sec1;
+ struct ble_store_value_sec value_sec2;
+
+ ble_hs_pvcy_test_util_init();
+
+ /*** No persisted IRKs. */
+ ble_hs_pvcy_test_util_start_host(0);
+
+ /*** One persisted IRK. */
+
+ /* Persist IRK; ensure it automatically gets added to the list. */
+ value_sec1 = (struct ble_store_value_sec) {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .key_size = 16,
+ .ediv = 1,
+ .rand_num = 2,
+ .irk = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ .irk_present = 1,
+ };
+ ble_hs_pvcy_test_util_restore_irk(&value_sec1, false, false);
+
+ /* Ensure it gets added to list on startup. */
+ ble_hs_pvcy_test_util_start_host(1);
+ ble_hs_pvcy_test_util_add_irk_verify_tx(&value_sec1.peer_addr,
+ value_sec1.irk,
+ ble_hs_pvcy_default_irk,
+ false, false);
+
+ /* Two persisted IRKs. */
+ value_sec2 = (struct ble_store_value_sec) {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
+ .key_size = 16,
+ .ediv = 12,
+ .rand_num = 20,
+ .irk = { 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 9, 9, 9, 9, 9, 10 },
+ .irk_present = 1,
+ };
+ ble_hs_pvcy_test_util_restore_irk(&value_sec2, false, false);
+
+ /* Ensure both get added to list on startup. */
+ ble_hs_pvcy_test_util_start_host(2);
+ ble_hs_pvcy_test_util_add_irk_verify_tx(&value_sec1.peer_addr,
+ value_sec1.irk,
+ ble_hs_pvcy_default_irk,
+ false, false);
+ ble_hs_pvcy_test_util_add_irk_verify_tx(&value_sec2.peer_addr,
+ value_sec2.irk,
+ ble_hs_pvcy_default_irk,
+ false, false);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/** No active GAP procedures. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_idle)
+{
+ ble_hs_pvcy_test_util_init();
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(false, false);
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*** Advertising active. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_adv)
+{
+ int rc;
+
+ ble_hs_pvcy_test_util_init();
+
+ /* Start an advertising procedure. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ NULL, &ble_hs_test_util_adv_params,
+ BLE_HS_FOREVER,
+ ble_hs_pvcy_test_util_gap_event,
+ NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(false, false);
+
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 1);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].type ==
+ BLE_GAP_EVENT_ADV_COMPLETE);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].adv_complete.reason ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure GAP procedures are no longer preempted. */
+ ble_hs_pvcy_test_util_all_gap_procs(0, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*** Discovery active. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_disc)
+{
+ struct ble_gap_disc_params disc_params;
+ int rc;
+
+ ble_hs_pvcy_test_util_init();
+
+ /* Start an advertising procedure. */
+ disc_params = (struct ble_gap_disc_params){ 0 };
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, ble_hs_pvcy_test_util_gap_event,
+ NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(true, false);
+
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 1);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].type ==
+ BLE_GAP_EVENT_DISC_COMPLETE);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].disc_complete.reason ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure GAP procedures are no longer preempted. */
+ ble_hs_pvcy_test_util_all_gap_procs(0, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*** Connect active. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_conn)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ ble_hs_pvcy_test_util_init();
+
+ /* Start a connect procedure. */
+ peer_addr = (ble_addr_t){ BLE_ADDR_PUBLIC, {1,2,3,4,5,6} };
+ rc = ble_hs_test_util_connect(BLE_ADDR_PUBLIC, &peer_addr,
+ BLE_HS_FOREVER, NULL,
+ ble_hs_pvcy_test_util_gap_event, NULL, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(false, true);
+
+ /* Cancel is now in progress. */
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 0);
+
+ /* Ensure no GAP procedures are allowed. */
+ ble_hs_pvcy_test_util_all_gap_procs(BLE_HS_EPREEMPTED,
+ BLE_HS_EALREADY,
+ BLE_HS_EBUSY);
+
+ /* Receive cancel event. */
+ ble_hs_test_util_rx_conn_cancel_evt();
+
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 1);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].type ==
+ BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].connect.status ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure GAP procedures are no longer preempted. */
+ ble_hs_pvcy_test_util_all_gap_procs(0, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*** Advertising and discovery active. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_adv_disc)
+{
+ struct ble_gap_disc_params disc_params;
+ int rc;
+
+ ble_hs_pvcy_test_util_init();
+
+ /* Start an advertising procedure. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ NULL, &ble_hs_test_util_adv_params,
+ BLE_HS_FOREVER,
+ ble_hs_pvcy_test_util_gap_event,
+ NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Start a discovery procedure. */
+ disc_params = (struct ble_gap_disc_params){ 0 };
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, ble_hs_pvcy_test_util_gap_event,
+ NULL, -1, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(true, false);
+
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 2);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].type ==
+ BLE_GAP_EVENT_ADV_COMPLETE);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].adv_complete.reason ==
+ BLE_HS_EPREEMPTED);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[1].type ==
+ BLE_GAP_EVENT_DISC_COMPLETE);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[1].disc_complete.reason ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure GAP procedures are no longer preempted. */
+ ble_hs_pvcy_test_util_all_gap_procs(0, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*** Advertising and connecting active. */
+TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_adv_conn)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ ble_hs_pvcy_test_util_init();
+
+ /* Start an advertising procedure. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC,
+ NULL, &ble_hs_test_util_adv_params,
+ BLE_HS_FOREVER,
+ ble_hs_pvcy_test_util_gap_event,
+ NULL, 0, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Start a connect procedure. */
+ peer_addr = (ble_addr_t){ BLE_ADDR_PUBLIC, {1,2,3,4,5,6} };
+ rc = ble_hs_test_util_connect(BLE_ADDR_PUBLIC, &peer_addr,
+ BLE_HS_FOREVER, NULL,
+ ble_hs_pvcy_test_util_gap_event, NULL, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_pvcy_test_util_add_arbitrary_irk(false, true);
+
+ /* Cancel is now in progress. */
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 1);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].type ==
+ BLE_GAP_EVENT_ADV_COMPLETE);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[0].adv_complete.reason ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure no GAP procedures are allowed. */
+ ble_hs_pvcy_test_util_all_gap_procs(BLE_HS_EPREEMPTED,
+ BLE_HS_EALREADY,
+ BLE_HS_EBUSY);
+
+ /* Receive cancel event. */
+ ble_hs_test_util_rx_conn_cancel_evt();
+
+ TEST_ASSERT(ble_hs_pvcy_test_num_gap_events == 2);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[1].type ==
+ BLE_GAP_EVENT_CONNECT);
+ TEST_ASSERT(ble_hs_pvcy_test_gap_events[1].connect.status ==
+ BLE_HS_EPREEMPTED);
+
+ /* Ensure GAP procedures are no longer preempted. */
+ ble_hs_pvcy_test_util_all_gap_procs(0, 0, 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_hs_pvcy_test_suite_irk)
+{
+ ble_hs_pvcy_test_case_restore_irks();
+ ble_hs_pvcy_test_case_add_irk_idle();
+ ble_hs_pvcy_test_case_add_irk_adv();
+ ble_hs_pvcy_test_case_add_irk_disc();
+ ble_hs_pvcy_test_case_add_irk_conn();
+ ble_hs_pvcy_test_case_add_irk_adv_disc();
+ ble_hs_pvcy_test_case_add_irk_adv_conn();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_stop_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_stop_test.c
new file mode 100644
index 00000000..526d5f5a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_stop_test.c
@@ -0,0 +1,203 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "host/ble_hs.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BHST_MAX_EVENTS 32
+
+static struct ble_gap_event bhst_events[BHST_MAX_EVENTS];
+static int bhst_num_events;
+
+static struct ble_hs_stop_listener bhst_listener;
+static struct os_sem bhst_sem;
+
+static int
+bhst_gap_event(struct ble_gap_event *event, void *arg)
+{
+ TEST_ASSERT_FATAL(bhst_num_events < BHST_MAX_EVENTS);
+
+ bhst_events[bhst_num_events++] = *event;
+ return 0;
+}
+
+static void
+bhst_stop_cb(int status, void *arg)
+{
+ int rc;
+
+ rc = os_sem_release(&bhst_sem);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+TEST_CASE_TASK(ble_hs_stop_test_new_procs)
+{
+ static const struct ble_gap_disc_params disc_params;
+ static const struct ble_gap_adv_params adv_params;
+
+ static const ble_addr_t peer_addr = {
+ BLE_ADDR_PUBLIC,
+ { 1, 2, 3, 4, 5, 6 }
+ };
+
+ int rc;
+
+ rc = os_sem_init(&bhst_sem, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Stop the host and wait for the stop procedure to complete. */
+ ble_hs_test_util_hci_ack_set(
+ BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE), 0);
+
+ rc = ble_hs_stop(&bhst_listener, bhst_stop_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = os_sem_pend(&bhst_sem, OS_TIMEOUT_NEVER);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /*** Ensure all GAP procedures fail. */
+
+ /* Advertise. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
+ BLE_HS_FOREVER, bhst_gap_event, NULL,
+ 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EDISABLED);
+
+ /* Discover. */
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, bhst_gap_event, NULL, 0, 0);
+ TEST_ASSERT(rc == BLE_HS_EDISABLED);
+
+ /* Connect. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr,
+ BLE_HS_FOREVER, NULL,
+ bhst_gap_event, NULL, 0);
+ TEST_ASSERT(rc == BLE_HS_EDISABLED);
+
+ /*** Restart stack; ensure GAP procedures succeed. */
+
+ ble_hs_test_util_hci_ack_set_startup();
+ ble_hs_sched_start();
+
+ /* Advertise. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
+ BLE_HS_FOREVER, bhst_gap_event, NULL,
+ 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_adv_stop(0);
+ TEST_ASSERT(rc == 0);
+
+ /* Discover. */
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, bhst_gap_event, NULL, 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_disc_cancel(0);
+ TEST_ASSERT(rc == 0);
+
+ /* Connect. */
+ rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr,
+ BLE_HS_FOREVER, NULL,
+ bhst_gap_event, NULL, 0);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_hs_test_util_conn_cancel(0);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_TASK(ble_hs_stop_test_cur_procs)
+{
+ static const struct ble_gap_disc_params disc_params;
+ static const struct ble_gap_adv_params adv_params;
+
+ int rc;
+
+ rc = os_sem_init(&bhst_sem, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Advertise. */
+ rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
+ BLE_HS_FOREVER, bhst_gap_event, NULL,
+ 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* Discover. */
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
+ &disc_params, bhst_gap_event, NULL, 0, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* Preload the host with HCI acks for the cancel commands that will be sent
+ * automatically when the host stops.
+ */
+ ble_hs_test_util_hci_ack_set(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ 0);
+ ble_hs_test_util_hci_ack_append(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ 0);
+
+ /* Stop the host and wait for the stop procedure to complete. */
+ bhst_num_events = 0;
+ rc = ble_hs_stop(&bhst_listener, bhst_stop_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = os_sem_pend(&bhst_sem, OS_TIMEOUT_NEVER);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure the GAP procedure cancellations were reported. */
+ TEST_ASSERT_FATAL(bhst_num_events == 2);
+ TEST_ASSERT(bhst_events[0].type == BLE_GAP_EVENT_ADV_COMPLETE);
+ TEST_ASSERT(bhst_events[0].adv_complete.reason == BLE_HS_EPREEMPTED);
+ TEST_ASSERT(bhst_events[1].type == BLE_GAP_EVENT_DISC_COMPLETE);
+ TEST_ASSERT(bhst_events[1].disc_complete.reason == BLE_HS_EPREEMPTED);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static void
+bhst_pre_test(void *arg)
+{
+ ble_hs_test_util_init_no_sysinit_no_start();
+
+ /* Preload the host with HCI acks for the startup sequence. */
+ ble_hs_test_util_hci_ack_set_startup();
+}
+
+TEST_SUITE(ble_hs_stop_test_suite)
+{
+ tu_suite_set_pre_test_cb(bhst_pre_test, NULL);
+
+ ble_hs_stop_test_new_procs();
+ ble_hs_stop_test_cur_procs();
+}
+
+int
+ble_stop_test_all(void)
+{
+ ble_hs_stop_test_suite();
+
+ return tu_any_failed;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.c
new file mode 100644
index 00000000..adf99423
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.c
@@ -0,0 +1,83 @@
+/*
+ * 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 "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "nimble/hci_common.h"
+#include "testutil/testutil.h"
+#include "ble_hs_test_util.h"
+#include "ble_hs_test.h"
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+ /* XXX: This test must come before the others; it causes privacy to be
+ * enabled. Subsequent tests depend on this. This is wrong - each test
+ * should enable privacy as needed, but the test util functions are so low
+ * level that they make this very difficult to arrange (individual HCI
+ * commands and responses).
+ *
+ * To fix this, we should implement a set of higher level BLE test
+ * functions that don't require individual HCI commands to be specified.
+ */
+ ble_gap_test_suite_disc();
+
+ ble_att_clt_suite();
+ ble_att_svr_suite();
+ ble_gap_test_suite_adv();
+ ble_gap_test_suite_conn_cancel();
+ ble_gap_test_suite_conn_find();
+ ble_gap_test_suite_conn_gen();
+ ble_gap_test_suite_conn_terminate();
+ ble_gap_test_suite_mtu();
+ ble_gap_test_suite_set_cb();
+ ble_gap_test_suite_stop_adv();
+ ble_gap_test_suite_timeout();
+ ble_gap_test_suite_update_conn();
+ ble_gap_test_suite_wl();
+ ble_gatt_conn_suite();
+ ble_gatt_disc_c_test_suite();
+ ble_gatt_disc_d_test_suite();
+ ble_gatt_disc_s_test_suite();
+ ble_gatt_find_s_test_suite();
+ ble_gatt_read_test_suite();
+ ble_gatt_write_test_suite();
+ ble_gatts_notify_suite();
+ ble_gatts_read_test_suite();
+ ble_gatts_reg_suite();
+ ble_hs_adv_test_suite();
+ ble_hs_conn_suite();
+ ble_hs_hci_suite();
+ ble_hs_id_test_suite_auto();
+ ble_hs_pvcy_test_suite_irk();
+ ble_l2cap_test_suite();
+ ble_os_test_suite();
+ ble_sm_gen_test_suite();
+ ble_sm_lgcy_test_suite();
+ ble_sm_sc_test_suite();
+ ble_store_suite();
+ ble_uuid_test_suite();
+
+ return tu_any_failed;
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.h b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.h
new file mode 100644
index 00000000..3fb1454e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test.h
@@ -0,0 +1,62 @@
+/*
+ * 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_TEST_
+#define H_BLE_HS_TEST_
+
+#include "testutil/testutil.h"
+
+TEST_SUITE_DECL(ble_att_clt_suite);
+TEST_SUITE_DECL(ble_att_svr_suite);
+TEST_SUITE_DECL(ble_gap_test_suite_adv);
+TEST_SUITE_DECL(ble_gap_test_suite_conn_cancel);
+TEST_SUITE_DECL(ble_gap_test_suite_conn_find);
+TEST_SUITE_DECL(ble_gap_test_suite_conn_gen);
+TEST_SUITE_DECL(ble_gap_test_suite_conn_terminate);
+TEST_SUITE_DECL(ble_gap_test_suite_disc);
+TEST_SUITE_DECL(ble_gap_test_suite_mtu);
+TEST_SUITE_DECL(ble_gap_test_suite_set_cb);
+TEST_SUITE_DECL(ble_gap_test_suite_stop_adv);
+TEST_SUITE_DECL(ble_gap_test_suite_timeout);
+TEST_SUITE_DECL(ble_gap_test_suite_update_conn);
+TEST_SUITE_DECL(ble_gap_test_suite_wl);
+TEST_SUITE_DECL(ble_gatt_conn_suite);
+TEST_SUITE_DECL(ble_gatt_disc_c_test_suite);
+TEST_SUITE_DECL(ble_gatt_disc_d_test_suite);
+TEST_SUITE_DECL(ble_gatt_disc_s_test_suite);
+TEST_SUITE_DECL(ble_gatt_find_s_test_suite);
+TEST_SUITE_DECL(ble_gatt_read_test_suite);
+TEST_SUITE_DECL(ble_gatt_write_test_suite);
+TEST_SUITE_DECL(ble_gatts_notify_suite);
+TEST_SUITE_DECL(ble_gatts_read_test_suite);
+TEST_SUITE_DECL(ble_gatts_reg_suite);
+TEST_SUITE_DECL(ble_hs_adv_test_suite);
+TEST_SUITE_DECL(ble_hs_conn_suite);
+TEST_SUITE_DECL(ble_hs_hci_suite);
+TEST_SUITE_DECL(ble_hs_id_test_suite_auto);
+TEST_SUITE_DECL(ble_hs_pvcy_test_suite_irk);
+TEST_SUITE_DECL(ble_l2cap_test_suite);
+TEST_SUITE_DECL(ble_os_test_suite);
+TEST_SUITE_DECL(ble_sm_gen_test_suite);
+TEST_SUITE_DECL(ble_sm_lgcy_test_suite);
+TEST_SUITE_DECL(ble_sm_sc_test_suite);
+TEST_SUITE_DECL(ble_store_suite);
+TEST_SUITE_DECL(ble_uuid_test_suite);
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.c
new file mode 100644
index 00000000..5ee17e76
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.c
@@ -0,0 +1,2048 @@
+/*
+ * 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 "sysinit/sysinit.h"
+#include "stats/stats.h"
+#include "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+#include "host/ble_hs_adv.h"
+#include "host/ble_hs_id.h"
+#include "store/config/ble_store_config.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];
+
+static STAILQ_HEAD(, os_mbuf_pkthdr) ble_hs_test_util_prev_tx_queue;
+struct os_mbuf *ble_hs_test_util_prev_tx_cur;
+
+int ble_sm_test_store_obj_type;
+union ble_store_key ble_sm_test_store_key;
+union ble_store_value ble_sm_test_store_value;
+
+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)
+{
+ struct os_mbuf_pkthdr *omp;
+
+ assert(OS_MBUF_IS_PKTHDR(om));
+
+ omp = OS_MBUF_PKTHDR(om);
+ if (STAILQ_EMPTY(&ble_hs_test_util_prev_tx_queue)) {
+ STAILQ_INSERT_HEAD(&ble_hs_test_util_prev_tx_queue, omp, omp_next);
+ } else {
+ STAILQ_INSERT_TAIL(&ble_hs_test_util_prev_tx_queue, omp, omp_next);
+ }
+}
+
+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 ble_l2cap_hdr l2cap_hdr;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ uint8_t pb;
+ int rc;
+
+ rc = os_mbuf_free_chain(ble_hs_test_util_prev_tx_cur);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ 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.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;
+}
+
+struct os_mbuf *
+ble_hs_test_util_prev_tx_dequeue_pullup(void)
+{
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+ if (om != NULL) {
+ om = os_mbuf_pullup(om, OS_MBUF_PKTLEN(om));
+ TEST_ASSERT_FATAL(om != NULL);
+ ble_hs_test_util_prev_tx_cur = om;
+ }
+
+ return om;
+}
+
+int
+ble_hs_test_util_prev_tx_queue_sz(void)
+{
+ struct os_mbuf_pkthdr *omp;
+ int cnt;
+
+ cnt = 0;
+ STAILQ_FOREACH(omp, &ble_hs_test_util_prev_tx_queue, omp_next) {
+ cnt++;
+ }
+
+ return cnt;
+}
+
+void
+ble_hs_test_util_prev_tx_queue_clear(void)
+{
+ while (!STAILQ_EMPTY(&ble_hs_test_util_prev_tx_queue)) {
+ ble_hs_test_util_prev_tx_dequeue();
+ }
+}
+
+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,
+ const ble_addr_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 == NULL) {
+ 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->val, 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_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,
+ uint8_t conn_features,
+ ble_gap_event_fn *cb, void *cb_arg)
+{
+ ble_addr_t addr;
+ struct ble_gap_conn_complete evt;
+ struct ble_hci_ev_le_subev_rd_rem_used_feat evt2;
+ int rc;
+
+ addr.type = peer_addr_type;
+ memcpy(addr.val, peer_id_addr, 6);
+
+ rc = ble_hs_test_util_connect(own_addr_type, &addr, 0, NULL, cb, cb_arg,
+ 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = handle;
+ evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
+ evt.peer_addr_type = peer_addr_type;
+ memcpy(evt.peer_addr, peer_id_addr, 6);
+ evt.conn_itvl = BLE_GAP_INITIAL_CONN_ITVL_MAX;
+ evt.conn_latency = BLE_GAP_INITIAL_CONN_LATENCY;
+ evt.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT;
+ memcpy(evt.local_rpa, our_rpa, 6);
+ memcpy(evt.peer_rpa, peer_rpa, 6);
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ evt2.subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
+ evt2.status = BLE_ERR_SUCCESS;
+ evt2.conn_handle = htole16(handle);
+ memcpy(evt2.features, ((uint8_t[]){ conn_features, 0, 0, 0, 0, 0, 0, 0 }),
+ 8);
+
+ ble_gap_rx_rd_rem_sup_feat_complete(&evt2);
+
+ ble_hs_test_util_hci_out_clear();
+}
+
+void
+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, BLE_OWN_ADDR_PUBLIC, null_addr,
+ BLE_ADDR_PUBLIC, peer_id_addr,
+ null_addr, BLE_HS_TEST_CONN_FEAT_ALL,
+ cb, cb_arg);
+}
+
+void
+ble_hs_test_util_create_conn_feat(uint16_t handle, const uint8_t *peer_id_addr,
+ uint8_t conn_features, ble_gap_event_fn *cb,
+ void *cb_arg)
+{
+ static uint8_t null_addr[6];
+
+ ble_hs_test_util_create_rpa_conn(handle, BLE_OWN_ADDR_PUBLIC, null_addr,
+ BLE_ADDR_PUBLIC, peer_id_addr,
+ null_addr, conn_features, cb, cb_arg);
+}
+
+int
+ble_hs_test_util_connect(uint8_t own_addr_type, const ble_addr_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_hci_out_clear();
+
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN),
+ ack_status);
+
+ rc = ble_gap_connect(own_addr_type, peer_addr, duration_ms, params, cb,
+ cb_arg);
+ if (ack_status != 0) {
+ TEST_ASSERT(rc == BLE_HS_HCI_ERR(ack_status));
+ } else if (rc != 0) {
+ return rc;
+ }
+
+ 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,
+ params);
+ ble_hs_test_util_hci_verify_tx_create_conn(&hcc);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_conn_cancel(uint8_t ack_status)
+{
+ int rc;
+
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
+ ack_status);
+
+ rc = ble_gap_conn_cancel();
+ return rc;
+}
+
+void
+ble_hs_test_util_rx_conn_cancel_evt(void)
+{
+ ble_hs_test_util_conn_cancel(0);
+ ble_hs_test_util_hci_rx_conn_cancel_evt();
+}
+
+void
+ble_hs_test_util_conn_cancel_full(void)
+{
+ ble_hs_test_util_conn_cancel(0);
+ ble_hs_test_util_rx_conn_cancel_evt();
+}
+
+int
+ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status)
+{
+ int rc;
+
+ ble_hs_test_util_hci_ack_set_disconnect(hci_status);
+ rc = ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+ return rc;
+}
+
+void
+ble_hs_test_util_conn_disconnect(uint16_t conn_handle)
+{
+ int rc;
+
+ rc = ble_hs_test_util_conn_terminate(conn_handle, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Receive disconnection complete event. */
+ ble_hs_test_util_hci_rx_disconn_complete_event(conn_handle, 0,
+ BLE_ERR_CONN_TERM_LOCAL);
+}
+
+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;
+
+ ble_hs_test_util_hci_ack_set_disc(own_addr_type, fail_idx, fail_status);
+ rc = ble_gap_disc(own_addr_type, duration_ms, disc_params,
+ cb, cb_arg);
+ return rc;
+}
+
+int
+ble_hs_test_util_disc_cancel(uint8_t ack_status)
+{
+ int rc;
+
+ ble_hs_test_util_hci_ack_set(
+ 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_hci_verify_tx(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(const struct ble_hs_adv_fields *adv_fields,
+ int cmd_fail_idx, uint8_t hci_status)
+{
+ struct ble_hs_test_util_hci_ack acks[3];
+ int auto_pwr;
+ int rc;
+ int i;
+
+ auto_pwr = adv_fields->tx_pwr_lvl_is_present &&
+ adv_fields->tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+ i = 0;
+ if (auto_pwr) {
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
+ ble_hs_test_util_hci_misc_exp_status(i, cmd_fail_idx, hci_status),
+ {0},
+ 1,
+ };
+ i++;
+ }
+
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_DATA),
+ ble_hs_test_util_hci_misc_exp_status(i, cmd_fail_idx, hci_status),
+ };
+ i++;
+
+ memset(acks + i, 0, sizeof acks[i]);
+ ble_hs_test_util_hci_ack_set_seq(acks);
+
+ 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_rsp_set_fields(const struct ble_hs_adv_fields *adv_fields,
+ int cmd_fail_idx, uint8_t hci_status)
+{
+ struct ble_hs_test_util_hci_ack acks[3];
+ int auto_pwr;
+ int rc;
+ int i;
+
+ auto_pwr = adv_fields->tx_pwr_lvl_is_present &&
+ adv_fields->tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+ i = 0;
+ if (auto_pwr) {
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
+ ble_hs_test_util_hci_misc_exp_status(i, cmd_fail_idx, hci_status),
+ {0},
+ 1,
+ };
+ i++;
+ }
+
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA),
+ ble_hs_test_util_hci_misc_exp_status(i, cmd_fail_idx, hci_status),
+ };
+ i++;
+
+ memset(acks + i, 0, sizeof acks[i]);
+ ble_hs_test_util_hci_ack_set_seq(acks);
+
+ rc = ble_gap_adv_rsp_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, const ble_addr_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params,
+ int32_t duration_ms,
+ ble_gap_event_fn *cb, void *cb_arg,
+ int fail_idx, uint8_t fail_status)
+{
+ struct ble_hs_test_util_hci_ack acks[6];
+ int rc;
+ int i;
+
+ i = 0;
+
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_PARAMS),
+ fail_idx == i ? fail_status : 0,
+ };
+ i++;
+
+ acks[i] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ ble_hs_test_util_hci_misc_exp_status(i, fail_idx, fail_status),
+ };
+ i++;
+
+ memset(acks + i, 0, sizeof acks[i]);
+
+ ble_hs_test_util_hci_ack_set_seq(acks);
+
+ rc = ble_gap_adv_start(own_addr_type, peer_addr,
+ duration_ms, adv_params, cb, cb_arg);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_adv_stop(uint8_t hci_status)
+{
+ int rc;
+
+ ble_hs_test_util_hci_ack_set(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ hci_status);
+
+ rc = ble_gap_adv_stop();
+ return rc;
+}
+
+int
+ble_hs_test_util_wl_set(ble_addr_t *addrs, uint8_t addrs_count,
+ int fail_idx, uint8_t fail_status)
+{
+ struct ble_hs_test_util_hci_ack acks[64];
+ int cmd_idx;
+ int rc;
+ int i;
+
+ TEST_ASSERT_FATAL(addrs_count < 63);
+
+ cmd_idx = 0;
+ acks[cmd_idx] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST),
+ ble_hs_test_util_hci_misc_exp_status(cmd_idx, fail_idx, fail_status),
+ };
+ cmd_idx++;
+
+ for (i = 0; i < addrs_count; i++) {
+ acks[cmd_idx] = (struct ble_hs_test_util_hci_ack) {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_ADD_WHITE_LIST),
+ ble_hs_test_util_hci_misc_exp_status(cmd_idx, fail_idx, fail_status),
+ };
+
+ cmd_idx++;
+ }
+ memset(acks + cmd_idx, 0, sizeof acks[cmd_idx]);
+
+ ble_hs_test_util_hci_ack_set_seq(acks);
+ rc = ble_gap_wl_set(addrs, addrs_count);
+ return rc;
+}
+
+int
+ble_hs_test_util_conn_update(uint16_t conn_handle,
+ struct ble_gap_upd_params *params,
+ uint8_t hci_status)
+{
+ int rc;
+
+ /*
+ * 0xFF is magic value used for cases where we expect update over L2CAP to
+ * be triggered - in this case we don't need phony ack.
+ */
+ if (hci_status != 0xFF) {
+ ble_hs_test_util_hci_ack_set(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CONN_UPDATE),
+ hci_status);
+ }
+
+ rc = ble_gap_update_params(conn_handle, params);
+ return rc;
+}
+
+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_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ ble_hs_test_util_hci_misc_exp_status(0, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
+ ble_hs_test_util_hci_misc_exp_status(1, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+ ble_hs_test_util_hci_misc_exp_status(2, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ ble_hs_test_util_hci_misc_exp_status(3, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
+ ble_hs_test_util_hci_misc_exp_status(4, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_PRIVACY_MODE),
+ ble_hs_test_util_hci_misc_exp_status(5, fail_idx, hci_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_PRIVACY_MODE),
+ ble_hs_test_util_hci_misc_exp_status(6, 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;
+
+ ble_hs_test_util_hci_ack_set(
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_START_ENCRYPT), hci_status);
+
+ rc = ble_gap_security_initiate(conn_handle);
+ return rc;
+}
+
+int
+ble_hs_test_util_l2cap_rx_first_frag(uint16_t conn_handle, uint16_t cid,
+ struct hci_data_hdr *hci_hdr,
+ struct os_mbuf *om)
+{
+ int rc;
+
+ om = ble_l2cap_prepend_hdr(om, cid, OS_MBUF_PKTLEN(om));
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = ble_hs_test_util_l2cap_rx(conn_handle, hci_hdr, om);
+ return rc;
+}
+
+int
+ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
+ struct hci_data_hdr *hci_hdr,
+ struct os_mbuf *om)
+{
+ struct ble_hs_conn *conn;
+ ble_l2cap_rx_fn *rx_cb;
+ int reject_cid;
+ int rc;
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ if (conn != NULL) {
+ rc = ble_l2cap_rx(conn, hci_hdr, om, &rx_cb, &reject_cid);
+ } else {
+ rc = os_mbuf_free_chain(om);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ ble_hs_unlock();
+
+ if (conn == NULL) {
+ rc = BLE_HS_ENOTCONN;
+ } else if (rc == 0) {
+ TEST_ASSERT_FATAL(rx_cb != NULL);
+ rc = rx_cb(conn->bhc_rx_chan);
+ ble_l2cap_remove_rx(conn, conn->bhc_rx_chan);
+ } else if (rc == BLE_HS_EAGAIN) {
+ /* More fragments on the way. */
+ rc = 0;
+ } else {
+ if (reject_cid != -1) {
+ ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, 0, 0, reject_cid);
+ }
+ }
+
+ return rc;
+}
+
+int
+ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
+ const void *data, int len)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ int rc;
+
+ 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 =
+ 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);
+ return rc;
+}
+
+void
+ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ if (mtu <= BLE_ATT_MTU_DFLT) {
+ return;
+ }
+
+ ble_hs_lock();
+
+ rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
+ assert(rc == 0);
+ chan->my_mtu = mtu;
+ chan->peer_mtu = mtu;
+ chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
+
+ ble_hs_unlock();
+}
+
+int
+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);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle)
+{
+ struct ble_att_find_info_req req;
+ uint8_t buf[BLE_ATT_FIND_INFO_REQ_SZ];
+ int rc;
+
+ req.bafq_start_handle = start_handle;
+ req.bafq_end_handle = end_handle;
+
+ ble_att_find_info_req_write(buf, sizeof buf, &req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t attr_type,
+ const void *attr_val,
+ uint16_t attr_len)
+{
+ struct ble_att_find_type_value_req req;
+ uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + 16];
+ int rc;
+
+ TEST_ASSERT(attr_len <= 16);
+
+ req.bavq_start_handle = start_handle;
+ req.bavq_end_handle = end_handle;
+ req.bavq_attr_type = attr_type;
+
+ ble_att_find_type_value_req_write(buf, sizeof buf, &req);
+ memcpy(buf + BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_type_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ const ble_uuid_t *uuid)
+{
+ struct ble_att_read_type_req req;
+ uint8_t buf[BLE_ATT_READ_TYPE_REQ_SZ_128];
+ int req_len;
+ int rc;
+
+ req.batq_start_handle = start_handle;
+ req.batq_end_handle = end_handle;
+
+ ble_att_read_type_req_write(buf, sizeof buf, &req);
+
+ ble_uuid_flat(uuid, buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ);
+ req_len = BLE_ATT_READ_TYPE_REQ_BASE_SZ + ble_uuid_length(uuid);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, req_len);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_type_req16(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t uuid16)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_read_type_req(conn_handle, start_handle,
+ end_handle,
+ BLE_UUID16_DECLARE(uuid16));
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_req(uint16_t conn_handle, uint16_t attr_handle)
+{
+ struct ble_att_read_req req;
+ uint8_t buf[BLE_ATT_READ_REQ_SZ];
+ int rc;
+
+ req.barq_handle = attr_handle;
+ ble_att_read_req_write(buf, sizeof buf, &req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_blob_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint16_t offset)
+{
+ struct ble_att_read_blob_req req;
+ uint8_t buf[BLE_ATT_READ_BLOB_REQ_SZ];
+ int rc;
+
+ req.babq_handle = attr_handle;
+ req.babq_offset = offset;
+ 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);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_mult_req(uint16_t conn_handle,
+ const uint16_t *handles,
+ int num_handles)
+{
+ uint8_t buf[256];
+ int off;
+ int rc;
+ int i;
+
+ ble_att_read_mult_req_write(buf, sizeof buf);
+
+ off = BLE_ATT_READ_MULT_REQ_BASE_SZ;
+ for (i = 0; i < num_handles; i++) {
+ put_le16(buf + off, handles[i]);
+ off += 2;
+ }
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, off);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_group_type_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ const ble_uuid_t *uuid)
+{
+ struct ble_att_read_group_type_req req;
+ uint8_t buf[BLE_ATT_READ_GROUP_TYPE_REQ_SZ_128];
+ int req_len;
+ int rc;
+
+ req.bagq_start_handle = start_handle;
+ req.bagq_end_handle = end_handle;
+
+ ble_uuid_flat(uuid, buf + BLE_ATT_READ_TYPE_REQ_BASE_SZ);
+ req_len = BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ + ble_uuid_length(uuid);
+
+ ble_att_read_group_type_req_write(buf, sizeof buf, &req);
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, req_len);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_read_group_type_req16(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t uuid16)
+{
+ int rc;
+
+ rc = ble_hs_test_util_rx_att_read_group_type_req(conn_handle, start_handle,
+ end_handle,
+ BLE_UUID16_DECLARE(uuid16));
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_write_req(uint16_t conn_handle, uint16_t attr_handle,
+ const void *attr_val, uint16_t attr_len)
+{
+ struct ble_att_write_req req;
+ uint8_t buf[BLE_ATT_WRITE_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
+ int rc;
+
+ req.bawq_handle = attr_handle;
+ ble_att_write_req_write(buf, sizeof buf, &req);
+
+ memcpy(buf + BLE_ATT_WRITE_REQ_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_WRITE_REQ_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_write_cmd(uint16_t conn_handle, uint16_t attr_handle,
+ const void *attr_val, uint16_t attr_len)
+{
+ struct ble_att_write_req req;
+ uint8_t buf[BLE_ATT_WRITE_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
+ int rc;
+
+ req.bawq_handle = attr_handle;
+ ble_att_write_cmd_write(buf, sizeof buf, &req);
+
+ memcpy(buf + BLE_ATT_WRITE_REQ_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_WRITE_REQ_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_prep_write_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint16_t offset,
+ const void *attr_val,
+ uint16_t attr_len)
+{
+ struct ble_att_prep_write_cmd prep_req;
+ uint8_t buf[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
+ int rc;
+
+ prep_req.bapc_handle = attr_handle;
+ prep_req.bapc_offset = offset;
+ ble_att_prep_write_req_write(buf, sizeof buf, &prep_req);
+ memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_exec_write_req(uint16_t conn_handle, uint8_t flags)
+{
+ struct ble_att_exec_write_req exec_req;
+ uint8_t buf[BLE_ATT_EXEC_WRITE_REQ_SZ];
+ int rc;
+
+ exec_req.baeq_flags = flags;
+ ble_att_exec_write_req_write(buf, sizeof buf, &exec_req);
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf,
+ BLE_ATT_EXEC_WRITE_REQ_SZ);
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_notify_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ void *attr_val,
+ uint16_t attr_len)
+{
+ struct ble_att_notify_req req;
+ uint8_t buf[BLE_ATT_NOTIFY_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
+ int rc;
+
+ req.banq_handle = attr_handle;
+ ble_att_notify_req_write(buf, sizeof buf, &req);
+ memcpy(buf + BLE_ATT_NOTIFY_REQ_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_NOTIFY_REQ_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+int
+ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ void *attr_val,
+ uint16_t attr_len)
+{
+ struct ble_att_indicate_req req;
+ uint8_t buf[BLE_ATT_INDICATE_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
+ int rc;
+
+ req.baiq_handle = attr_handle;
+ ble_att_indicate_req_write(buf, sizeof buf, &req);
+ memcpy(buf + BLE_ATT_INDICATE_REQ_BASE_SZ, attr_val, attr_len);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(
+ conn_handle, BLE_L2CAP_CID_ATT, buf,
+ BLE_ATT_INDICATE_REQ_BASE_SZ + attr_len);
+
+ return rc;
+}
+
+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)
+{
+ struct ble_att_error_rsp rsp;
+ uint8_t buf[BLE_ATT_ERROR_RSP_SZ];
+ int rc;
+
+ rsp.baep_req_op = req_op;
+ rsp.baep_handle = err_handle;
+ rsp.baep_error_code = error_code;
+
+ ble_att_error_rsp_write(buf, sizeof buf, &rsp);
+
+ 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_verify_tx_prep_write(uint16_t attr_handle, uint16_t offset,
+ const void *data, int data_len)
+{
+ struct ble_att_prep_write_cmd req;
+ struct os_mbuf *om;
+
+ 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
+ble_hs_test_util_verify_tx_exec_write(uint8_t expected_flags)
+{
+ struct ble_att_exec_write_req req;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ);
+
+ ble_att_exec_write_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.baeq_flags == expected_flags);
+}
+
+void
+ble_hs_test_util_verify_tx_find_type_value(uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t attr_type,
+ const void *value,
+ uint16_t value_len)
+{
+ struct ble_att_find_type_value_req req;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT(om->om_len == BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + value_len);
+
+ ble_att_find_type_value_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.bavq_start_handle == start_handle);
+ TEST_ASSERT(req.bavq_end_handle == end_handle);
+ TEST_ASSERT(req.bavq_attr_type == attr_type);
+ TEST_ASSERT(memcmp(om->om_data + BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ,
+ value,
+ value_len) == 0);
+}
+
+void
+ble_hs_test_util_verify_tx_disc_svc_uuid(const ble_uuid_t *uuid)
+{
+ uint8_t uuid_buf[16];
+
+ ble_uuid_flat(uuid, uuid_buf);
+ ble_hs_test_util_verify_tx_find_type_value(
+ 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE,
+ uuid_buf, ble_uuid_length(uuid));
+}
+
+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;
+
+ 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;
+
+ 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;
+
+ 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_find_info_rsp(
+ struct ble_hs_test_util_att_info_entry *entries)
+{
+ struct ble_hs_test_util_att_info_entry *entry;
+ struct ble_att_find_info_rsp rsp;
+ struct os_mbuf *om;
+ uint16_t handle;
+ uint8_t buf[BLE_ATT_FIND_INFO_RSP_BASE_SZ];
+ ble_uuid_any_t uuid;
+ int off;
+ int rc;
+
+ off = 0;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om);
+
+ rc = os_mbuf_copydata(om, off, sizeof buf, buf);
+ TEST_ASSERT(rc == 0);
+ off += sizeof buf;
+
+ ble_att_find_info_rsp_parse(buf, sizeof buf, &rsp);
+
+ for (entry = entries; entry->handle != 0; entry++) {
+ rc = os_mbuf_copydata(om, off, 2, &handle);
+ TEST_ASSERT(rc == 0);
+ off += 2;
+
+ handle = get_le16((void *)&handle);
+ TEST_ASSERT(handle == entry->handle);
+
+ if (entry->uuid->type == BLE_UUID_TYPE_16) {
+ TEST_ASSERT(rsp.bafp_format ==
+ BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT);
+
+ ble_uuid_init_from_att_mbuf(&uuid, om, off, 2);
+ TEST_ASSERT(rc == 0);
+ off += 2;
+ } else {
+ TEST_ASSERT(rsp.bafp_format ==
+ BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT);
+
+ rc = ble_uuid_init_from_att_mbuf(&uuid, om, off, 16);
+ TEST_ASSERT(rc == 0);
+ off += 16;
+ }
+
+ TEST_ASSERT(ble_uuid_cmp(entry->uuid, &uuid.u) == 0);
+ }
+
+ /* Ensure there is no extra data in the response. */
+ TEST_ASSERT(off == OS_MBUF_PKTHDR(om)->omp_len);
+}
+
+void
+ble_hs_test_util_verify_tx_read_group_type_rsp(
+ struct ble_hs_test_util_att_group_type_entry *entries)
+{
+ struct ble_hs_test_util_att_group_type_entry *entry;
+ struct ble_att_read_group_type_rsp rsp;
+ struct os_mbuf *om;
+ uint16_t u16;
+ ble_uuid_any_t uuid;
+ int off;
+ int rc;
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om);
+
+ ble_att_read_group_type_rsp_parse(om->om_data, om->om_len, &rsp);
+
+ off = BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ;
+ for (entry = entries; entry->start_handle != 0; entry++) {
+ if (entry->uuid->type == BLE_UUID_TYPE_16) {
+ TEST_ASSERT(rsp.bagp_length ==
+ BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16);
+ } else {
+ TEST_ASSERT(rsp.bagp_length ==
+ BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128);
+ }
+
+ rc = os_mbuf_copydata(om, off, 2, &u16);
+ TEST_ASSERT(rc == 0);
+ put_le16(&u16, u16);
+ TEST_ASSERT(u16 == entry->start_handle);
+ off += 2;
+
+ rc = os_mbuf_copydata(om, off, 2, &u16);
+ TEST_ASSERT(rc == 0);
+ put_le16(&u16, u16);
+ TEST_ASSERT(u16 == entry->end_handle);
+ off += 2;
+
+ if (entry->uuid->type == BLE_UUID_TYPE_16) {
+ rc = ble_uuid_init_from_att_mbuf(&uuid, om, off, 2);
+ TEST_ASSERT(rc == 0);
+ } else {
+ rc = ble_uuid_init_from_att_mbuf(&uuid, om, off, 16);
+ TEST_ASSERT(rc == 0);
+ }
+
+ TEST_ASSERT(ble_uuid_cmp(&uuid.u, entry->uuid) == 0);
+ off += ble_uuid_length(&uuid.u);
+ }
+
+ /* Ensure there is no extra data in the response. */
+ TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
+}
+
+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;
+
+ 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_verify_tx_write_cmd(uint16_t handle, const void *data,
+ uint16_t data_len)
+{
+ struct ble_att_write_req req;
+ struct os_mbuf *om;
+ uint8_t buf[BLE_ATT_WRITE_CMD_BASE_SZ];
+ int rc;
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+
+ rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
+ TEST_ASSERT(rc == 0);
+
+ ble_att_write_cmd_parse(buf, sizeof buf, &req);
+
+ TEST_ASSERT(req.bawq_handle == handle);
+
+ os_mbuf_adj(om, sizeof buf);
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == data_len);
+ TEST_ASSERT(os_mbuf_cmpf(om, 0, data, data_len) == 0);
+}
+
+static struct os_mbuf *
+ble_hs_test_util_verify_tx_l2cap_sig_hdr(uint8_t op, uint8_t id,
+ uint16_t payload_len,
+ struct ble_l2cap_sig_hdr *out_hdr)
+{
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_L2CAP_SIG_HDR_SZ + payload_len);
+ ble_l2cap_sig_hdr_parse(om->om_data, om->om_len, &hdr);
+ TEST_ASSERT(hdr.op == op);
+ if (id != 0) {
+ TEST_ASSERT(hdr.identifier == id);
+ }
+ TEST_ASSERT(hdr.length == payload_len);
+
+ om->om_data += BLE_L2CAP_SIG_HDR_SZ;
+ om->om_len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ if (out_hdr != NULL) {
+ *out_hdr = hdr;
+ }
+
+ return om;
+}
+
+int
+ble_hs_test_util_inject_rx_l2cap_sig(uint16_t conn_handle, uint8_t opcode,
+ uint8_t id, void *cmd, uint16_t cmd_size)
+{
+ void *r;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ int rc;
+
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + cmd_size);
+
+ r = ble_l2cap_sig_cmd_get(opcode, id, cmd_size, &om);
+ TEST_ASSERT_FATAL(r != NULL);
+
+ memcpy(r, cmd, cmd_size);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG,
+ &hci_hdr, om);
+ return rc;
+}
+
+/**
+ * @return The L2CAP sig identifier in the request/response.
+ */
+uint8_t
+ble_hs_test_util_verify_tx_l2cap_sig(uint16_t opcode, void *cmd,
+ uint16_t cmd_size)
+{
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_verify_tx_l2cap_sig_hdr(opcode, 0, cmd_size, &hdr);
+ om = os_mbuf_pullup(om, cmd_size);
+
+ /* Verify payload. */
+ TEST_ASSERT(memcmp(om->om_data, cmd, cmd_size) == 0);
+
+ return hdr.identifier;
+}
+
+void
+ble_hs_test_util_verify_tx_l2cap(struct os_mbuf *txom)
+{
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_prev_tx_dequeue();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ /* TODO Handle fragmentation */
+ TEST_ASSERT_FATAL(os_mbuf_cmpm(om, 0, txom, 0, OS_MBUF_PKTLEN(om)) == 0);
+}
+
+void
+ble_hs_test_util_inject_rx_l2cap(uint16_t conn_handle, uint16_t cid,
+ struct os_mbuf *rxom)
+{
+ struct hci_data_hdr hci_hdr;
+ int rc;
+
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ +
+ BLE_L2CAP_SIG_HDR_SZ +
+ OS_MBUF_PKTLEN(rxom));
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, cid, &hci_hdr, rxom);
+ TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_l2cap_test_update_req_swap(struct ble_l2cap_sig_update_req *dst,
+ struct ble_l2cap_sig_update_req *src)
+{
+ dst->itvl_min = le16toh(src->itvl_min);
+ dst->itvl_max = le16toh(src->itvl_max);
+ dst->slave_latency = le16toh(src->slave_latency);
+ dst->timeout_multiplier = le16toh(src->timeout_multiplier);
+}
+
+static void
+ble_l2cap_test_update_req_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_req *dst)
+{
+ BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ ble_l2cap_test_update_req_swap(dst, payload);
+}
+
+/**
+ * @return The L2CAP sig identifier in the request.
+ */
+uint8_t
+ble_hs_test_util_verify_tx_l2cap_update_req(
+ struct ble_l2cap_sig_update_params *params)
+{
+ struct ble_l2cap_sig_update_req req;
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_verify_tx_l2cap_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_REQ,
+ 0,
+ BLE_L2CAP_SIG_UPDATE_REQ_SZ,
+ &hdr);
+
+ /* Verify payload. */
+ ble_l2cap_test_update_req_parse(om->om_data, om->om_len, &req);
+ TEST_ASSERT(req.itvl_min == params->itvl_min);
+ TEST_ASSERT(req.itvl_max == params->itvl_max);
+ TEST_ASSERT(req.slave_latency == params->slave_latency);
+ TEST_ASSERT(req.timeout_multiplier == params->timeout_multiplier);
+
+ return hdr.identifier;
+}
+
+static void
+ble_l2cap_sig_update_rsp_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_rsp *dst)
+{
+ struct ble_l2cap_sig_update_rsp *src = payload;
+
+ BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ dst->result = le16toh(src->result);
+}
+
+int
+ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle,
+ uint8_t id, uint16_t result)
+{
+ struct ble_l2cap_sig_update_rsp *rsp;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ int rc;
+
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+
+ rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_UPDATE_RSP, id,
+ BLE_L2CAP_SIG_UPDATE_RSP_SZ, &om);
+ TEST_ASSERT_FATAL(rsp != NULL);
+
+ rsp->result = htole16(result);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG,
+ &hci_hdr, om);
+ return rc;
+}
+
+void
+ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id,
+ uint16_t exp_result)
+{
+ struct ble_l2cap_sig_update_rsp rsp;
+ struct os_mbuf *om;
+
+ om = ble_hs_test_util_verify_tx_l2cap_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_RSP,
+ exp_id,
+ BLE_L2CAP_SIG_UPDATE_RSP_SZ,
+ NULL);
+
+ ble_l2cap_sig_update_rsp_parse(om->om_data, om->om_len, &rsp);
+ TEST_ASSERT(rsp.result == exp_result);
+}
+
+void
+ble_hs_test_util_set_static_rnd_addr(const uint8_t *addr)
+{
+ int rc;
+
+ ble_hs_test_util_hci_ack_set(
+ 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_hci_out_first();
+}
+
+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);
+
+ rc = os_mbuf_free_chain(om);
+ TEST_ASSERT_FATAL(rc == 0);
+ 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;
+ uint16_t offset = 0;
+ int rc;
+
+ om = ble_hs_test_util_om_from_flat(data, data_len);
+ rc = ble_gattc_write_long(conn_handle, attr_handle, offset, 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;
+}
+
+static int
+ble_hs_test_util_num_mbufs(void)
+{
+ return os_msys_count() + ble_hs_hci_frag_num_mbufs();
+}
+
+static int
+ble_hs_test_util_num_mbufs_free(void)
+{
+ return os_msys_num_free() + ble_hs_hci_frag_num_mbufs_free();
+}
+
+struct os_mbuf *
+ble_hs_test_util_mbuf_alloc_all_but(int count)
+{
+ struct os_mbuf *prev;
+ struct os_mbuf *om;
+ int rc;
+ int i;
+
+ /* Allocate all available mbufs and put them in a single chain. */
+ prev = NULL;
+ while (1) {
+ om = os_msys_get(0, 0);
+ if (om == NULL) {
+ break;
+ }
+
+ if (prev != NULL) {
+ SLIST_NEXT(om, om_next) = prev;
+ }
+
+ prev = om;
+ }
+
+ /* Now free 'count' mbufs. */
+ for (i = 0; i < count; i++) {
+ TEST_ASSERT_FATAL(prev != NULL);
+ om = SLIST_NEXT(prev, om_next);
+ rc = os_mbuf_free(prev);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ prev = om;
+ }
+
+ return prev;
+}
+
+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_rx_data_queue();
+
+ count = ble_hs_test_util_num_mbufs_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, next) {
+ count += ble_hs_test_util_mbuf_chain_len(chan->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_num_mbufs());
+}
+
+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_hci_out_enqueue(cmdbuf);
+ ble_hci_trans_buf_free(cmdbuf);
+ return 0;
+}
+
+int
+ble_hs_test_util_num_cccds(void)
+{
+ struct ble_store_value_cccd val;
+ struct ble_store_key_cccd key = { };
+ int rc;
+
+ key.peer_addr = *BLE_ADDR_ANY;
+ for (key.idx = 0; ; key.idx++) {
+ rc = ble_store_read_cccd(&key, &val);
+ switch (rc) {
+ case 0:
+ break;
+
+ case BLE_HS_ENOENT:
+ return key.idx;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ }
+ }
+}
+
+int
+ble_hs_test_util_num_our_secs(void)
+{
+ struct ble_store_value_sec val;
+ struct ble_store_key_sec key = { };
+ int rc;
+
+ key.peer_addr = *BLE_ADDR_ANY;
+ for (key.idx = 0; ; key.idx++) {
+ rc = ble_store_read_our_sec(&key, &val);
+ switch (rc) {
+ case 0:
+ break;
+
+ case BLE_HS_ENOENT:
+ return key.idx;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ }
+ }
+}
+
+int
+ble_hs_test_util_num_peer_secs(void)
+{
+ struct ble_store_value_sec val;
+ struct ble_store_key_sec key = { };
+ int rc;
+
+ key.peer_addr = *BLE_ADDR_ANY;
+ for (key.idx = 0; ; key.idx++) {
+ rc = ble_store_read_peer_sec(&key, &val);
+ switch (rc) {
+ case 0:
+ break;
+
+ case BLE_HS_ENOENT:
+ return key.idx;
+
+ default:
+ TEST_ASSERT_FATAL(0);
+ }
+ }
+}
+
+static int
+ble_hs_test_util_store_read(int obj_type, const union ble_store_key *key,
+ union ble_store_value *value)
+{
+ int rc;
+
+ ble_sm_test_store_obj_type = obj_type;
+ ble_sm_test_store_key = *key;
+
+ rc = ble_store_config_read(obj_type, key, value);
+ ble_sm_test_store_value = *value;
+
+ return rc;
+}
+
+static int
+ble_hs_test_util_store_write(int obj_type, const union ble_store_value *value)
+{
+ int rc;
+
+ ble_sm_test_store_obj_type = obj_type;
+
+ rc = ble_store_config_write(obj_type, value);
+ ble_sm_test_store_value = *value;
+
+ return rc;
+}
+
+static int
+ble_hs_test_util_store_delete(int obj_type, const union ble_store_key *key)
+{
+ int rc;
+
+ ble_sm_test_store_obj_type = obj_type;
+ ble_sm_test_store_key = *key;
+
+ rc = ble_store_config_delete(obj_type, key);
+ return rc;
+}
+
+void
+ble_hs_test_util_reg_svcs(const struct ble_gatt_svc_def *svcs,
+ ble_gatt_register_fn *reg_cb,
+ void *cb_arg)
+{
+ int rc;
+
+ ble_hs_cfg.gatts_register_cb = reg_cb;
+ ble_hs_cfg.gatts_register_arg = cb_arg;
+
+ rc = ble_gatts_reset();
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_gatts_add_svcs(svcs);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_gatts_start();
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+
+void
+ble_hs_test_util_init_no_sysinit_no_start(void)
+{
+ STAILQ_INIT(&ble_hs_test_util_prev_tx_queue);
+ ble_hs_test_util_prev_tx_cur = NULL;
+
+ ble_hs_hci_set_phony_ack_cb(NULL);
+
+ ble_hci_trans_cfg_ll(ble_hs_test_util_hci_txed, NULL,
+ ble_hs_test_util_pkt_txed, NULL);
+
+ ble_hs_test_util_hci_ack_set_startup();
+
+ ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF;
+
+ ble_hs_max_services = 16;
+ ble_hs_max_client_configs = 32;
+ ble_hs_max_attrs = 64;
+
+ ble_hs_test_util_hci_out_clear();
+
+ ble_hs_cfg.store_read_cb = ble_hs_test_util_store_read;
+ ble_hs_cfg.store_write_cb = ble_hs_test_util_store_write;
+ ble_hs_cfg.store_delete_cb = ble_hs_test_util_store_delete;
+
+ ble_store_clear();
+}
+
+void
+ble_hs_test_util_init_no_start(void)
+{
+ sysinit();
+ ble_hs_test_util_init_no_sysinit_no_start();
+}
+
+void
+ble_hs_test_util_init(void)
+{
+ int rc;
+
+ ble_hs_test_util_init_no_start();
+
+ rc = ble_hs_start();
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_hci_out_clear();
+ ble_hs_test_util_hci_acks_clear();
+
+ /* Clear random address. */
+ ble_hs_id_rnd_reset();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.h b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.h
new file mode 100644
index 00000000..411443cf
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util.h
@@ -0,0 +1,305 @@
+/*
+ * 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_TEST_UTIL_
+#define H_BLE_HS_TEST_UTIL_
+
+#include <inttypes.h>
+#include "host/ble_gap.h"
+#include "ble_hs_priv.h"
+#include "ble_hs_test_util_hci.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* TODO this is currently copied from ble_ll_conn_priv.h and eventually
+ * should not be needed...
+ */
+struct hci_create_conn
+{
+ uint16_t scan_itvl;
+ uint16_t scan_window;
+ uint8_t filter_policy;
+ uint8_t peer_addr_type;
+ uint8_t peer_addr[BLE_DEV_ADDR_LEN];
+ uint8_t own_addr_type;
+ uint16_t conn_itvl_min;
+ uint16_t conn_itvl_max;
+ uint16_t conn_latency;
+ uint16_t supervision_timeout;
+ uint16_t min_ce_len;
+ uint16_t max_ce_len;
+};
+
+struct ble_hs_conn;
+struct ble_l2cap_chan;
+struct hci_disconn_complete;
+struct hci_create_conn;
+
+#define BLE_HS_TEST_UTIL_LE_OPCODE(ocf) \
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE, (ocf))
+
+#define BLE_HS_TEST_UTIL_PUB_ADDR_VAL { 0x0a, 0x54, 0xab, 0x49, 0x7f, 0x06 }
+
+extern const struct ble_gap_adv_params ble_hs_test_util_adv_params;
+
+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;
+};
+
+struct ble_hs_test_util_att_info_entry {
+ uint16_t handle; /* 0 on last entry */
+ const ble_uuid_t *uuid;
+};
+
+struct ble_hs_test_util_att_group_type_entry {
+ uint16_t start_handle; /* 0 on last entry */
+ uint16_t end_handle; /* 0 on last entry */
+ const ble_uuid_t *uuid;
+};
+
+#define BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(handle, pb, len) \
+ ((struct hci_data_hdr) { \
+ .hdh_handle_pb_bc = ((handle) << 0) | \
+ ((pb) << 12), \
+ .hdh_len = (len) \
+ })
+
+#define BLE_HS_TEST_CONN_FEAT_ALL (0xFF)
+#define BLE_HS_TEST_CONN_FEAT_NO_CONN_PARAM (0xFD)
+
+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);
+int ble_hs_test_util_prev_tx_queue_sz(void);
+void ble_hs_test_util_prev_tx_queue_clear(void);
+
+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,
+ const uint8_t *peer_id_addr,
+ const uint8_t *peer_rpa,
+ uint8_t conn_features,
+ ble_gap_event_fn *cb, void *cb_arg);
+void ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *addr,
+ ble_gap_event_fn *cb, void *cb_arg);
+void ble_hs_test_util_create_conn_feat(uint16_t handle, const uint8_t *addr,
+ uint8_t conn_features,
+ ble_gap_event_fn *cb, void *cb_arg);
+int ble_hs_test_util_connect(uint8_t own_addr_type,
+ const ble_addr_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_rx_conn_cancel_evt(void);
+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_rx_disconn_complete(uint16_t conn_handle,
+ uint8_t reason);
+void ble_hs_test_util_conn_disconnect(uint16_t conn_handle);
+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_disc_cancel(uint8_t ack_status);
+int ble_hs_test_util_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
+ int cmd_fail_idx, uint8_t hci_status);
+int ble_hs_test_util_adv_rsp_set_fields(
+ const struct ble_hs_adv_fields *adv_fields,
+ int cmd_fail_idx, uint8_t hci_status);
+int ble_hs_test_util_adv_start(uint8_t own_addr_type,
+ const ble_addr_t *peer_addr,
+ const struct ble_gap_adv_params *adv_params,
+ int32_t duration_ms,
+ 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);
+int ble_hs_test_util_wl_set(ble_addr_t *addrs, uint8_t addrs_count,
+ int fail_idx, uint8_t fail_status);
+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,
+ struct hci_data_hdr *hci_hdr,
+ struct os_mbuf *om);
+int ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
+ struct hci_data_hdr *hci_hdr,
+ struct os_mbuf *om);
+int ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
+ const void *data, int len);
+uint8_t ble_hs_test_util_verify_tx_l2cap_sig(uint16_t opcode, void *cmd,
+ uint16_t cmd_size);
+int ble_hs_test_util_inject_rx_l2cap_sig(uint16_t conn_handle, uint8_t opcode,
+ uint8_t id, void *cmd, uint16_t cmd_size);
+void ble_hs_test_util_verify_tx_l2cap(struct os_mbuf *txom);
+void ble_hs_test_util_inject_rx_l2cap(uint16_t conn_handle, uint16_t cid,
+ struct os_mbuf *rxom);
+void ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu);
+int ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req,
+ uint16_t mtu);
+int ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle);
+int ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t attr_type,
+ const void *attr_val,
+ uint16_t attr_len);
+int ble_hs_test_util_rx_att_read_type_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ const ble_uuid_t *uuid);
+int ble_hs_test_util_rx_att_read_type_req16(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t uuid16);
+int ble_hs_test_util_rx_att_read_req(uint16_t conn_handle,
+ uint16_t attr_handle);
+int ble_hs_test_util_rx_att_read_blob_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint16_t offset);
+int ble_hs_test_util_rx_att_read_mult_req(uint16_t conn_handle,
+ const uint16_t *handles,
+ int num_handles);
+int ble_hs_test_util_rx_att_read_group_type_req(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ const ble_uuid_t *uuid);
+int ble_hs_test_util_rx_att_read_group_type_req16(uint16_t conn_handle,
+ uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t uuid16);
+int ble_hs_test_util_rx_att_write_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *attr_val,
+ uint16_t attr_len);
+int ble_hs_test_util_rx_att_write_cmd(uint16_t conn_handle,
+ uint16_t attr_handle,
+ const void *attr_val,
+ uint16_t attr_len);
+int ble_hs_test_util_rx_att_prep_write_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ uint16_t offset,
+ const void *attr_val,
+ uint16_t attr_len);
+int ble_hs_test_util_rx_att_exec_write_req(uint16_t conn_handle,
+ uint8_t flags);
+int ble_hs_test_util_rx_att_notify_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ void *attr_val,
+ uint16_t attr_len);
+int ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle,
+ uint16_t attr_handle,
+ void *attr_val,
+ uint16_t attr_len);
+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_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_find_type_value(uint16_t start_handle,
+ uint16_t end_handle,
+ uint16_t attr_type,
+ const void *value,
+ uint16_t value_len);
+void ble_hs_test_util_verify_tx_disc_svc_uuid(const ble_uuid_t *uuid);
+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_find_info_rsp(
+ struct ble_hs_test_util_att_info_entry *entries);
+void ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu);
+void ble_hs_test_util_verify_tx_read_group_type_rsp(
+ struct ble_hs_test_util_att_group_type_entry *entries);
+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_verify_tx_write_cmd(uint16_t handle, const void *data,
+ uint16_t data_len);
+
+uint8_t ble_hs_test_util_verify_tx_l2cap_update_req(
+ struct ble_l2cap_sig_update_params *params);
+int ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle,
+ uint8_t id, uint16_t result);
+void ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id,
+ uint16_t exp_result);
+void ble_hs_test_util_set_static_rnd_addr(const uint8_t *addr);
+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);
+struct os_mbuf *ble_hs_test_util_mbuf_alloc_all_but(int count);
+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);
+int ble_hs_test_util_num_cccds(void);
+int ble_hs_test_util_num_our_secs(void);
+int ble_hs_test_util_num_peer_secs(void);
+void ble_hs_test_util_reg_svcs(const struct ble_gatt_svc_def *svcs,
+ ble_gatt_register_fn *reg_cb,
+ void *cb_arg);
+void ble_hs_test_util_init_no_start(void);
+void ble_hs_test_util_init_no_sysinit_no_start(void);
+void ble_hs_test_util_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.c
new file mode 100644
index 00000000..a53c5d9f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.c
@@ -0,0 +1,616 @@
+/*
+ * 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 "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "transport/ram/ble_hci_ram.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN (5)
+#define BLE_HCI_EVENT_CMD_STATUS_LEN (6)
+#define BLE_HCI_ADD_TO_RESOLV_LIST_LEN (39)
+#define BLE_HCI_LE_SET_PRIVACY_MODE_LEN (8)
+#define BLE_HCI_DISCONNECT_CMD_LEN (3)
+#define BLE_HCI_EVENT_HDR_LEN (2)
+#define BLE_HCI_EVENT_DISCONN_COMPLETE_LEN (4)
+
+#define BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT 64
+
+static uint8_t
+ble_hs_test_util_hci_out_queue[BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT][260];
+static int ble_hs_test_util_hci_out_queue_sz;
+static uint8_t ble_hs_test_util_hci_out_cur[260];
+
+static struct ble_hs_test_util_hci_ack
+ble_hs_test_util_hci_acks[BLE_HS_TEST_UTIL_PHONY_ACK_MAX];
+static int ble_hs_test_util_hci_num_acks;
+
+/*****************************************************************************
+ * $tx queue *
+ *****************************************************************************/
+
+void
+ble_hs_test_util_hci_out_adj(int count)
+{
+ if (count >= 0) {
+ TEST_ASSERT(ble_hs_test_util_hci_out_queue_sz >= count);
+
+ ble_hs_test_util_hci_out_queue_sz -= count;
+ if (ble_hs_test_util_hci_out_queue_sz > 0) {
+ memmove(
+ ble_hs_test_util_hci_out_queue,
+ ble_hs_test_util_hci_out_queue + count,
+ sizeof ble_hs_test_util_hci_out_queue[0] *
+ ble_hs_test_util_hci_out_queue_sz);
+ }
+ } else {
+ TEST_ASSERT(ble_hs_test_util_hci_out_queue_sz >= -count);
+
+ ble_hs_test_util_hci_out_adj(
+ ble_hs_test_util_hci_out_queue_sz + count);
+ }
+}
+
+void *
+ble_hs_test_util_hci_out_first(void)
+{
+ if (ble_hs_test_util_hci_out_queue_sz == 0) {
+ return NULL;
+ }
+
+ memcpy(ble_hs_test_util_hci_out_cur, ble_hs_test_util_hci_out_queue[0],
+ sizeof ble_hs_test_util_hci_out_cur);
+
+ ble_hs_test_util_hci_out_adj(1);
+
+ return ble_hs_test_util_hci_out_cur;
+}
+
+void *
+ble_hs_test_util_hci_out_last(void)
+{
+ if (ble_hs_test_util_hci_out_queue_sz == 0) {
+ return NULL;
+ }
+
+ ble_hs_test_util_hci_out_queue_sz--;
+ memcpy(ble_hs_test_util_hci_out_cur,
+ ble_hs_test_util_hci_out_queue + ble_hs_test_util_hci_out_queue_sz,
+ sizeof ble_hs_test_util_hci_out_cur);
+
+ return ble_hs_test_util_hci_out_cur;
+}
+
+void
+ble_hs_test_util_hci_out_enqueue(void *cmd)
+{
+ TEST_ASSERT_FATAL(ble_hs_test_util_hci_out_queue_sz <
+ BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT);
+ memcpy(ble_hs_test_util_hci_out_queue + ble_hs_test_util_hci_out_queue_sz,
+ cmd, 260);
+
+ ble_hs_test_util_hci_out_queue_sz++;
+}
+
+void
+ble_hs_test_util_hci_out_clear(void)
+{
+ ble_hs_test_util_hci_out_queue_sz = 0;
+}
+
+void
+ble_hs_test_util_hci_acks_clear(void)
+{
+ ble_hs_test_util_hci_num_acks = 0;
+}
+
+/*****************************************************************************
+ * $build *
+ *****************************************************************************/
+
+void
+ble_hs_test_util_hci_build_cmd_complete(uint8_t *dst, int len,
+ uint8_t param_len, uint8_t num_pkts,
+ uint16_t opcode)
+{
+ TEST_ASSERT(len >= BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN);
+
+ dst[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE;
+ dst[1] = 3 + param_len;
+ dst[2] = num_pkts;
+ put_le16(dst + 3, opcode);
+}
+
+void
+ble_hs_test_util_hci_build_cmd_status(uint8_t *dst, int len,
+ uint8_t status, uint8_t num_pkts,
+ uint16_t opcode)
+{
+ TEST_ASSERT(len >= BLE_HCI_EVENT_CMD_STATUS_LEN);
+
+ dst[0] = BLE_HCI_EVCODE_COMMAND_STATUS;
+ dst[1] = BLE_HCI_EVENT_CMD_STATUS_LEN;
+ dst[2] = status;
+ dst[3] = num_pkts;
+ put_le16(dst + 4, opcode);
+}
+
+static void
+ble_hs_test_util_hci_build_ack_params(
+ struct ble_hs_test_util_hci_ack *ack,
+ uint16_t opcode, uint8_t status, void *params, uint8_t params_len)
+{
+ ack->opcode = opcode;
+ ack->status = status;
+
+ if (params == NULL || params_len == 0) {
+ ack->evt_params_len = 0;
+ } else {
+ memcpy(ack->evt_params, params, params_len);
+ ack->evt_params_len = params_len;
+ }
+}
+
+/*****************************************************************************
+ * $ack *
+ *****************************************************************************/
+
+static int
+ble_hs_test_util_hci_ack_cb(uint8_t *ack, int ack_buf_len)
+{
+ struct ble_hs_test_util_hci_ack *entry;
+
+ if (ble_hs_test_util_hci_num_acks == 0) {
+ return BLE_HS_ETIMEOUT_HCI;
+ }
+
+ entry = ble_hs_test_util_hci_acks;
+
+ ble_hs_test_util_hci_build_cmd_complete(ack, 256,
+ entry->evt_params_len + 1, 1,
+ entry->opcode);
+ ack[BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN] = entry->status;
+ memcpy(ack + BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN + 1, entry->evt_params,
+ entry->evt_params_len);
+
+ ble_hs_test_util_hci_num_acks--;
+ if (ble_hs_test_util_hci_num_acks > 0) {
+ memmove(ble_hs_test_util_hci_acks,
+ ble_hs_test_util_hci_acks + 1,
+ sizeof *entry * ble_hs_test_util_hci_num_acks);
+ }
+
+ return 0;
+}
+
+void
+ble_hs_test_util_hci_ack_set_params(uint16_t opcode, uint8_t status,
+ void *params, uint8_t params_len)
+{
+ struct ble_hs_test_util_hci_ack *ack;
+
+ ack = ble_hs_test_util_hci_acks + 0;
+ ble_hs_test_util_hci_build_ack_params(ack, opcode, status, params,
+ params_len);
+ ble_hs_test_util_hci_num_acks = 1;
+
+ ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
+}
+
+void
+ble_hs_test_util_hci_ack_set(uint16_t opcode, uint8_t status)
+{
+ ble_hs_test_util_hci_ack_set_params(opcode, status, NULL, 0);
+}
+
+void
+ble_hs_test_util_hci_ack_append_params(uint16_t opcode, uint8_t status,
+ void *params, uint8_t params_len)
+{
+ struct ble_hs_test_util_hci_ack *ack;
+
+ ack = ble_hs_test_util_hci_acks + ble_hs_test_util_hci_num_acks;
+ ble_hs_test_util_hci_build_ack_params(ack, opcode, status, params,
+ params_len);
+ ble_hs_test_util_hci_num_acks++;
+
+ ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
+}
+
+void
+ble_hs_test_util_hci_ack_append(uint16_t opcode, uint8_t status)
+{
+ ble_hs_test_util_hci_ack_append_params(opcode, status, NULL, 0);
+}
+
+static const struct ble_hs_test_util_hci_ack hci_startup_seq[] = {
+ {
+ .opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
+ BLE_HCI_OCF_CB_RESET),
+ },
+ {
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER),
+ .evt_params = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ .evt_params_len = 8,
+ },
+ {
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
+ .evt_params = { 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00},
+ .evt_params_len = 8,
+ },
+ {
+ .opcode = ble_hs_hci_util_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_MASK2),
+ },
+ {
+ .opcode = ble_hs_hci_util_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_RD_BUF_SIZE),
+ /* Use a very low buffer size (20) to test fragmentation.
+ * Use a large num-pkts (200) to prevent controller buf exhaustion.
+ */
+ .evt_params = { 0x14, 0x00, 200 },
+ .evt_params_len = 3,
+ },
+ {
+ .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 = 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 = ble_hs_hci_util_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_SET_ADDR_RES_EN),
+ },
+ {
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ },
+ {
+ .opcode = ble_hs_hci_util_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_SET_PRIVACY_MODE),
+ },
+ { 0 }
+};
+
+void
+ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack *acks)
+{
+ int i;
+
+ for (i = 0; acks[i].opcode != 0; i++) {
+ ble_hs_test_util_hci_acks[i] = acks[i];
+ }
+ ble_hs_test_util_hci_num_acks = i;
+
+ ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
+}
+
+int
+ble_hs_test_util_hci_startup_seq_cnt(void)
+{
+ /* last element is terminator, don't count it*/
+ return sizeof(hci_startup_seq)/sizeof(hci_startup_seq[0]) - 1;
+}
+
+void
+ble_hs_test_util_hci_ack_set_startup(void)
+{
+ /* Receive acknowledgements for the startup sequence. We sent the
+ * corresponding requests when the host task was started.
+ */
+ ble_hs_test_util_hci_ack_set_seq(hci_startup_seq);
+}
+
+void
+ble_hs_test_util_hci_ack_set_disc(uint8_t own_addr_type,
+ int fail_idx, uint8_t fail_status)
+{
+ static bool privacy_enabled;
+
+ /*
+ * SET_RPA_TMO should be expected only when test uses RPA and privacy has
+ * not yet been enabled. The Bluetooth stack remembers that privacy is
+ * enabled and does not send SET_RPA_TMO every time. For test purpose
+ * let's track privacy state in here.
+ */
+ if ((own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT ||
+ own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) &&
+ !privacy_enabled) {
+
+ privacy_enabled = true;
+ ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_RPA_TMO),
+ ble_hs_test_util_hci_misc_exp_status(0, fail_idx, fail_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
+ ble_hs_test_util_hci_misc_exp_status(1, fail_idx, fail_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ ble_hs_test_util_hci_misc_exp_status(2, fail_idx, fail_status),
+ },
+
+ { 0 }
+ }));
+ } else {
+ ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
+ ble_hs_test_util_hci_misc_exp_status(0, fail_idx, fail_status),
+ },
+ {
+ BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+ ble_hs_test_util_hci_misc_exp_status(1, fail_idx, fail_status),
+ },
+
+ { 0 }
+ }));
+ }
+}
+
+void
+ble_hs_test_util_hci_ack_set_disconnect(uint8_t hci_status)
+{
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LINK_CTRL,
+ BLE_HCI_OCF_DISCONNECT_CMD),
+ hci_status);
+}
+
+/*****************************************************************************
+ * $verify tx *
+ *****************************************************************************/
+
+void
+ble_hs_test_util_hci_verify_tx_add_irk(uint8_t addr_type,
+ const uint8_t *addr,
+ const uint8_t *peer_irk,
+ const uint8_t *local_irk)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_ADD_RESOLV_LIST,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_ADD_TO_RESOLV_LIST_LEN);
+
+ TEST_ASSERT(param[0] == addr_type);
+ TEST_ASSERT(memcmp(param + 1, addr, 6) == 0);
+ TEST_ASSERT(memcmp(param + 7, peer_irk, 16) == 0);
+ TEST_ASSERT(memcmp(param + 23, local_irk, 16) == 0);
+}
+
+void
+ble_hs_test_util_hci_verify_tx_set_priv_mode(uint8_t addr_type,
+ const uint8_t *addr,
+ uint8_t priv_mode)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_PRIVACY_MODE,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_LE_SET_PRIVACY_MODE_LEN);
+
+ TEST_ASSERT(param[0] == addr_type);
+ TEST_ASSERT(memcmp(param + 1, addr, 6) == 0);
+ TEST_ASSERT(param[7] == priv_mode);
+}
+
+void
+ble_hs_test_util_hci_verify_tx_disconnect(uint16_t handle, uint8_t reason)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LINK_CTRL,
+ BLE_HCI_OCF_DISCONNECT_CMD,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_DISCONNECT_CMD_LEN);
+
+ TEST_ASSERT(get_le16(param + 0) == handle);
+ TEST_ASSERT(param[2] == reason);
+}
+
+void
+ble_hs_test_util_hci_verify_tx_create_conn(const struct hci_create_conn *exp)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CREATE_CONN,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CREATE_CONN_LEN);
+
+ TEST_ASSERT(get_le16(param + 0) == exp->scan_itvl);
+ TEST_ASSERT(get_le16(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(get_le16(param + 13) == exp->conn_itvl_min);
+ TEST_ASSERT(get_le16(param + 15) == exp->conn_itvl_max);
+ TEST_ASSERT(get_le16(param + 17) == exp->conn_latency);
+ TEST_ASSERT(get_le16(param + 19) == exp->supervision_timeout);
+ TEST_ASSERT(get_le16(param + 21) == exp->min_ce_len);
+ TEST_ASSERT(get_le16(param + 23) == exp->max_ce_len);
+}
+
+uint8_t *
+ble_hs_test_util_hci_verify_tx(uint8_t ogf, uint16_t ocf,
+ uint8_t *out_param_len)
+{
+ uint16_t opcode;
+ uint8_t *cmd;
+
+ cmd = ble_hs_test_util_hci_out_first();
+ TEST_ASSERT_FATAL(cmd != NULL);
+
+ opcode = get_le16(cmd);
+ TEST_ASSERT(BLE_HCI_OGF(opcode) == ogf);
+ TEST_ASSERT(BLE_HCI_OCF(opcode) == ocf);
+
+ if (out_param_len != NULL) {
+ *out_param_len = cmd[2];
+ }
+
+ return cmd + 3;
+}
+
+/*****************************************************************************
+ * $rx *
+ *****************************************************************************/
+
+static void
+ble_hs_test_util_hci_rx_evt(uint8_t *evt)
+{
+ uint8_t *evbuf;
+ int totlen;
+ int rc;
+
+ totlen = BLE_HCI_EVENT_HDR_LEN + evt[1];
+ TEST_ASSERT_FATAL(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
+
+ evbuf = ble_hci_trans_buf_alloc(
+ BLE_HCI_TRANS_BUF_EVT_LO);
+ TEST_ASSERT_FATAL(evbuf != NULL);
+
+ memcpy(evbuf, evt, totlen);
+
+ if (os_started()) {
+ rc = ble_hci_trans_ll_evt_tx(evbuf);
+ } else {
+ rc = ble_hs_hci_evt_process((void *)evbuf);
+ }
+
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+void
+ble_hs_test_util_hci_rx_num_completed_pkts_event(
+ struct ble_hs_test_util_hci_num_completed_pkts_entry *entries)
+{
+ struct ble_hs_test_util_hci_num_completed_pkts_entry *entry;
+ uint8_t buf[1024];
+ int num_entries;
+ int off;
+ int i;
+
+ /* Count number of entries. */
+ num_entries = 0;
+ for (entry = entries; entry->handle_id != 0; entry++) {
+ num_entries++;
+ }
+ TEST_ASSERT_FATAL(num_entries <= UINT8_MAX);
+
+ buf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
+ buf[2] = num_entries;
+
+ off = 3;
+ for (i = 0; i < num_entries; i++) {
+ put_le16(buf + off, entries[i].handle_id);
+ off += 2;
+ put_le16(buf + off, entries[i].num_pkts);
+ off += 2;
+ }
+
+ buf[1] = off - 2;
+
+ ble_hs_test_util_hci_rx_evt(buf);
+}
+
+void
+ble_hs_test_util_hci_rx_disconn_complete_event(uint16_t conn_handle,
+ uint8_t status, uint8_t reason)
+{
+ uint8_t buf[BLE_HCI_EVENT_HDR_LEN + BLE_HCI_EVENT_DISCONN_COMPLETE_LEN];
+
+ buf[0] = BLE_HCI_EVCODE_DISCONN_CMP;
+ buf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN;
+ buf[2] = status;
+ put_le16(buf + 3, conn_handle);
+ buf[5] = reason;
+
+ ble_hs_test_util_hci_rx_evt(buf);
+}
+
+void
+ble_hs_test_util_hci_rx_conn_cancel_evt(void)
+{
+ struct ble_gap_conn_complete evt;
+ int rc;
+
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_UNK_CONN_ID;
+ /* test if host correctly ignores other fields if status is error */
+ evt.connection_handle = 0x0fff;
+
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+/*****************************************************************************
+ * $misc *
+ *****************************************************************************/
+
+int
+ble_hs_test_util_hci_misc_exp_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;
+ }
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.h b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.h
new file mode 100644
index 00000000..dde04557
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_hs_test_util_hci.h
@@ -0,0 +1,105 @@
+/*
+ * 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_TEST_UTIL_HCI_
+#define H_BLE_HS_TEST_UTIL_HCI_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* leave this as macro so it may be used for static const initialization */
+#define ble_hs_hci_util_opcode_join(ogf, ocf) (((ogf) << 10) | (ocf))
+
+#define BLE_HS_TEST_UTIL_PHONY_ACK_MAX 64
+struct ble_hs_test_util_hci_ack {
+ uint16_t opcode;
+ uint8_t status;
+ uint8_t evt_params[256];
+ uint8_t evt_params_len;
+};
+
+struct ble_hs_test_util_hci_num_completed_pkts_entry {
+ uint16_t handle_id; /* 0 for terminating entry in array. */
+ uint16_t num_pkts;
+};
+
+/* $out queue */
+void ble_hs_test_util_hci_out_adj(int count);
+void *ble_hs_test_util_hci_out_first(void);
+void *ble_hs_test_util_hci_out_last(void);
+void ble_hs_test_util_hci_out_enqueue(void *cmd);
+void ble_hs_test_util_hci_out_clear(void);
+void ble_hs_test_util_hci_acks_clear(void);
+
+/* $build */
+void ble_hs_test_util_hci_build_cmd_complete(uint8_t *dst, int len,
+ uint8_t param_len,
+ uint8_t num_pkts,
+ uint16_t opcode);
+void ble_hs_test_util_hci_build_cmd_status(uint8_t *dst, int len,
+ uint8_t status, uint8_t num_pkts,
+ uint16_t opcode);
+
+/* $ack */
+void ble_hs_test_util_hci_ack_set_params(uint16_t opcode, uint8_t status,
+ void *params, uint8_t params_len);
+void ble_hs_test_util_hci_ack_set(uint16_t opcode, uint8_t status);
+void ble_hs_test_util_hci_ack_append_params(uint16_t opcode, uint8_t status,
+ void *params, uint8_t params_len);
+void ble_hs_test_util_hci_ack_append(uint16_t opcode, uint8_t status);
+void ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack *acks);
+void ble_hs_test_util_hci_ack_set_startup(void);
+void ble_hs_test_util_hci_ack_set_disc(uint8_t own_addr_type,
+ int fail_idx, uint8_t fail_status);
+void ble_hs_test_util_hci_ack_set_disconnect(uint8_t hci_status);
+
+int ble_hs_test_util_hci_startup_seq_cnt(void);
+
+/* $verify tx */
+void ble_hs_test_util_hci_verify_tx_add_irk(uint8_t addr_type,
+ const uint8_t *addr,
+ const uint8_t *peer_irk,
+ const uint8_t *local_irk);
+void ble_hs_test_util_hci_verify_tx_set_priv_mode(uint8_t addr_type,
+ const uint8_t *addr,
+ uint8_t priv_mode);
+void ble_hs_test_util_hci_verify_tx_disconnect(uint16_t handle,
+ uint8_t reason);
+void ble_hs_test_util_hci_verify_tx_create_conn(
+ const struct hci_create_conn *exp);
+uint8_t *ble_hs_test_util_hci_verify_tx(uint8_t ogf, uint16_t ocf,
+ uint8_t *out_param_len);
+
+/* $rx */
+void ble_hs_test_util_hci_rx_num_completed_pkts_event(
+ struct ble_hs_test_util_hci_num_completed_pkts_entry *entries);
+void ble_hs_test_util_hci_rx_disconn_complete_event(uint16_t conn_handle,
+ uint8_t status, uint8_t reason);
+void ble_hs_test_util_hci_rx_conn_cancel_evt(void);
+
+/* $misc */
+int ble_hs_test_util_hci_misc_exp_status(int cmd_idx, int fail_idx,
+ uint8_t fail_status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_l2cap_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_l2cap_test.c
new file mode 100644
index 00000000..2b17da06
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_l2cap_test.c
@@ -0,0 +1,1500 @@
+/*
+ * 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 <stddef.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_HCI_CONN_UPDATE_LEN (14)
+
+#define BLE_L2CAP_TEST_PSM (90)
+#define BLE_L2CAP_TEST_CID (99)
+#define BLE_L2CAP_TEST_COC_MTU (256)
+/* We use same pool for incoming and outgoing sdu */
+#define BLE_L2CAP_TEST_COC_BUF_COUNT (6 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM))
+
+static uint16_t ble_l2cap_test_update_conn_handle;
+static int ble_l2cap_test_update_status;
+static void *ble_l2cap_test_update_arg;
+
+static void *test_sdu_coc_mem;
+struct os_mbuf_pool sdu_os_mbuf_pool;
+static struct os_mempool sdu_coc_mbuf_mempool;
+static uint16_t current_cid = 0x0040;
+/*****************************************************************************
+ * $util *
+ *****************************************************************************/
+
+static void
+ble_l2cap_test_util_init(void)
+{
+ ble_hs_test_util_init();
+ ble_l2cap_test_update_conn_handle = BLE_HS_CONN_HANDLE_NONE;
+ ble_l2cap_test_update_status = -1;
+ ble_l2cap_test_update_arg = (void *)(uintptr_t)-1;
+ int rc;
+
+ if (test_sdu_coc_mem) {
+ free(test_sdu_coc_mem);
+ }
+
+ /* For testing we want to support all the available channels */
+ test_sdu_coc_mem = malloc(
+ OS_MEMPOOL_BYTES(BLE_L2CAP_TEST_COC_BUF_COUNT,BLE_L2CAP_TEST_COC_MTU));
+ assert(test_sdu_coc_mem != NULL);
+
+ rc = os_mempool_init(&sdu_coc_mbuf_mempool, BLE_L2CAP_TEST_COC_BUF_COUNT,
+ BLE_L2CAP_TEST_COC_MTU, test_sdu_coc_mem,
+ "test_coc_sdu_pool");
+ assert(rc == 0);
+
+ rc = os_mbuf_pool_init(&sdu_os_mbuf_pool, &sdu_coc_mbuf_mempool,
+ BLE_L2CAP_TEST_COC_MTU, BLE_L2CAP_TEST_COC_BUF_COUNT);
+ assert(rc == 0);
+
+}
+
+static void
+ble_l2cap_test_util_rx_update_req(uint16_t conn_handle, uint8_t id,
+ struct ble_l2cap_sig_update_params *params)
+{
+ struct ble_l2cap_sig_update_req *req;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ int rc;
+
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+
+ req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_UPDATE_REQ, id,
+ BLE_L2CAP_SIG_UPDATE_REQ_SZ, &om);
+ TEST_ASSERT_FATAL(req != NULL);
+
+ req->itvl_min = htole16(params->itvl_min);
+ req->itvl_max = htole16(params->itvl_max);
+ req->slave_latency = htole16(params->slave_latency);
+ req->timeout_multiplier = htole16(params->timeout_multiplier);
+
+ ble_hs_test_util_hci_ack_set(
+ 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);
+}
+
+static void
+ble_l2cap_test_util_verify_tx_update_conn(
+ struct ble_gap_upd_params *params)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CONN_UPDATE,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN);
+ TEST_ASSERT(get_le16(param + 0) == 2);
+ TEST_ASSERT(get_le16(param + 2) == params->itvl_min);
+ TEST_ASSERT(get_le16(param + 4) == params->itvl_max);
+ TEST_ASSERT(get_le16(param + 6) == params->latency);
+ TEST_ASSERT(get_le16(param + 8) == params->supervision_timeout);
+ TEST_ASSERT(get_le16(param + 10) == params->min_ce_len);
+ TEST_ASSERT(get_le16(param + 12) == params->max_ce_len);
+}
+
+static int
+ble_l2cap_test_util_dummy_rx(struct ble_l2cap_chan *chan)
+{
+ return 0;
+}
+
+static void
+ble_l2cap_test_util_create_conn(uint16_t conn_handle, uint8_t *addr,
+ ble_gap_event_fn *cb, void *cb_arg)
+{
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+
+ ble_hs_test_util_create_conn(conn_handle, addr, cb, cb_arg);
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+
+ chan = ble_l2cap_chan_alloc(conn_handle);
+ TEST_ASSERT_FATAL(chan != NULL);
+
+ chan->scid = BLE_L2CAP_TEST_CID;
+ chan->my_mtu = 240;
+ chan->rx_fn = ble_l2cap_test_util_dummy_rx;
+
+ ble_hs_conn_chan_insert(conn, chan);
+
+ ble_hs_test_util_hci_out_clear();
+
+ ble_hs_unlock();
+}
+
+static int
+ble_l2cap_test_util_rx_first_frag(uint16_t conn_handle,
+ uint16_t l2cap_frag_len,
+ uint16_t cid, uint16_t l2cap_len)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ uint16_t hci_len;
+ void *v;
+ int rc;
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ v = os_mbuf_extend(om, l2cap_frag_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ om = ble_l2cap_prepend_hdr(om, cid, l2cap_len);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ hci_len = sizeof hci_hdr + l2cap_frag_len;
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle,
+ BLE_HCI_PB_FIRST_FLUSH, hci_len);
+ rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om);
+ return rc;
+}
+
+static int
+ble_l2cap_test_util_rx_next_frag(uint16_t conn_handle, uint16_t hci_len)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int rc;
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ v = os_mbuf_extend(om, hci_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle,
+ BLE_HCI_PB_MIDDLE, hci_len);
+ rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om);
+ return rc;
+}
+
+static void
+ble_l2cap_test_util_verify_first_frag(uint16_t conn_handle,
+ uint16_t l2cap_frag_len,
+ uint16_t l2cap_len)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ rc = ble_l2cap_test_util_rx_first_frag(conn_handle, l2cap_frag_len,
+ BLE_L2CAP_TEST_CID, l2cap_len);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_rx_chan != NULL &&
+ conn->bhc_rx_chan->scid == BLE_L2CAP_TEST_CID);
+
+ ble_hs_unlock();
+}
+
+static void
+ble_l2cap_test_util_verify_middle_frag(uint16_t conn_handle,
+ uint16_t hci_len)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ rc = ble_l2cap_test_util_rx_next_frag(conn_handle, hci_len);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_rx_chan != NULL &&
+ conn->bhc_rx_chan->scid == BLE_L2CAP_TEST_CID);
+
+ ble_hs_unlock();
+}
+
+static void
+ble_l2cap_test_util_verify_last_frag(uint16_t conn_handle,
+ uint16_t hci_len)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ rc = ble_l2cap_test_util_rx_next_frag(conn_handle, hci_len);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_rx_chan == NULL);
+
+ ble_hs_unlock();
+}
+
+/*****************************************************************************
+ * $rx *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_l2cap_test_case_bad_header)
+{
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ rc = ble_l2cap_test_util_rx_first_frag(2, 14, 1234, 10);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_bad_handle)
+{
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ rc = ble_l2cap_test_util_rx_first_frag(1234, 14, 1234, 10);
+ TEST_ASSERT(rc == BLE_HS_ENOTCONN);
+
+ /* Ensure we did not send anything in return. */
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*****************************************************************************
+ * $fragmentation *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_l2cap_test_case_frag_single)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ /*** HCI header specifies middle fragment without start. */
+ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ om = ble_l2cap_prepend_hdr(om, 0, 5);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = ble_hs_test_util_l2cap_rx(2, &hci_hdr, om);
+ TEST_ASSERT(rc == BLE_HS_EBADDATA);
+
+ /*** Packet consisting of three fragments. */
+ ble_l2cap_test_util_verify_first_frag(2, 10, 30);
+ ble_l2cap_test_util_verify_middle_frag(2, 10);
+ ble_l2cap_test_util_verify_last_frag(2, 10);
+
+ /*** Packet consisting of five fragments. */
+ ble_l2cap_test_util_verify_first_frag(2, 8, 49);
+ ble_l2cap_test_util_verify_middle_frag(2, 13);
+ ble_l2cap_test_util_verify_middle_frag(2, 2);
+ ble_l2cap_test_util_verify_middle_frag(2, 21);
+ ble_l2cap_test_util_verify_last_frag(2, 5);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_frag_multiple)
+{
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+ ble_l2cap_test_util_create_conn(3, ((uint8_t[]){2,3,4,5,6,7}),
+ NULL, NULL);
+ ble_l2cap_test_util_create_conn(4, ((uint8_t[]){3,4,5,6,7,8}),
+ NULL, NULL);
+
+ ble_l2cap_test_util_verify_first_frag(2, 3, 10);
+ ble_l2cap_test_util_verify_first_frag(3, 2, 5);
+ ble_l2cap_test_util_verify_middle_frag(2, 6);
+ ble_l2cap_test_util_verify_first_frag(4, 1, 4);
+ ble_l2cap_test_util_verify_middle_frag(3, 2);
+ ble_l2cap_test_util_verify_last_frag(3, 1);
+ ble_l2cap_test_util_verify_middle_frag(4, 2);
+ ble_l2cap_test_util_verify_last_frag(4, 1);
+ ble_l2cap_test_util_verify_last_frag(2, 1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_frag_channels)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+ uint16_t data_len = 30;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ /* Receive a starting fragment on the first channel. */
+ rc = ble_l2cap_test_util_rx_first_frag(2, 14, BLE_L2CAP_TEST_CID, data_len);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_rx_chan != NULL &&
+ conn->bhc_rx_chan->scid == BLE_L2CAP_TEST_CID);
+ ble_hs_unlock();
+
+ /* Receive a starting fragment on a different channel. The first fragment
+ * should get discarded.
+ */
+ ble_hs_test_util_set_att_mtu(conn->bhc_handle, data_len);
+ rc = ble_l2cap_test_util_rx_first_frag(2, 14, BLE_L2CAP_CID_ATT, data_len);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ TEST_ASSERT(conn->bhc_rx_chan != NULL &&
+ conn->bhc_rx_chan->scid == BLE_L2CAP_CID_ATT);
+ ble_hs_unlock();
+
+ /* Terminate the connection. The received fragments should get freed.
+ * Mbuf leaks are tested in the post-test-case callback.
+ */
+ ble_hs_test_util_conn_disconnect(2);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_frag_timeout)
+{
+ int32_t ticks_from_now;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ /* Ensure timer is not set. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT_FATAL(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Receive the first fragment of a multipart ACL data packet. */
+ rc = ble_l2cap_test_util_rx_first_frag(2, 14, BLE_L2CAP_TEST_CID, 30);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure timer will expire in 30 seconds. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT));
+
+ /* Almost let the timer expire. */
+ os_time_advance(MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) - 1);
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == 1);
+
+ /* Receive a second fragment. */
+ rc = ble_l2cap_test_util_rx_next_frag(2, 14);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure timer got reset. */
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT));
+
+ /* Allow the timer to expire. */
+ ble_hs_test_util_hci_ack_set_disconnect(0);
+ os_time_advance(MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT));
+ ticks_from_now = ble_hs_conn_timer();
+ TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+ /* Ensure connection was terminated. */
+ ble_hs_test_util_hci_verify_tx_disconnect(2, BLE_ERR_REM_USER_CONN_TERM);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*****************************************************************************
+ * $unsolicited response *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_unsol_rsp)
+{
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ /* Receive an unsolicited response. */
+ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, 100, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure we did not send anything in return. */
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*****************************************************************************
+ * $update *
+ *****************************************************************************/
+
+static int
+ble_l2cap_test_util_conn_cb(struct ble_gap_event *event, void *arg)
+{
+ int *accept;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_L2CAP_UPDATE_REQ:
+ accept = arg;
+ return !*accept;
+
+ default:
+ return 0;
+ }
+}
+
+static void
+ble_l2cap_test_util_peer_updates(int accept)
+{
+ struct ble_l2cap_sig_update_params l2cap_params;
+ struct ble_gap_upd_params params;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb,
+ &accept);
+
+ l2cap_params.itvl_min = 0x200;
+ l2cap_params.itvl_max = 0x300;
+ l2cap_params.slave_latency = 0;
+ l2cap_params.timeout_multiplier = 0x500;
+ ble_l2cap_test_util_rx_update_req(2, 1, &l2cap_params);
+
+ /* Ensure an update response command got sent. */
+ ble_hs_test_util_verify_tx_l2cap_update_rsp(1, !accept);
+
+ if (accept) {
+ params.itvl_min = 0x200;
+ params.itvl_max = 0x300;
+ params.latency = 0;
+ params.supervision_timeout = 0x500;
+ params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
+ params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
+ ble_l2cap_test_util_verify_tx_update_conn(&params);
+ } else {
+ /* Ensure no update got scheduled. */
+ TEST_ASSERT(!ble_gap_dbg_update_active(2));
+ }
+}
+
+static void
+ble_l2cap_test_util_update_cb(uint16_t conn_handle, int status, void *arg)
+{
+ ble_l2cap_test_update_conn_handle = conn_handle;
+ ble_l2cap_test_update_status = status;
+ ble_l2cap_test_update_arg = arg;
+}
+
+static void
+ble_l2cap_test_util_we_update(int peer_accepts)
+{
+ struct ble_l2cap_sig_update_params params;
+ uint8_t id;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ /* Only the slave can initiate the L2CAP connection update procedure. */
+ ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0);
+
+ params.itvl_min = 0x200;
+ params.itvl_max = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(2, &params, ble_l2cap_test_util_update_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure an update request got sent. */
+ id = ble_hs_test_util_verify_tx_l2cap_update_req(&params);
+
+ /* Receive response from peer. */
+ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, !peer_accepts);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ if (peer_accepts) {
+ TEST_ASSERT(ble_l2cap_test_update_status == 0);
+ } else {
+ TEST_ASSERT(ble_l2cap_test_update_status == BLE_HS_EREJECT);
+ }
+ TEST_ASSERT(ble_l2cap_test_update_arg == NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_accept)
+{
+ ble_l2cap_test_util_peer_updates(1);
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_reject)
+{
+ ble_l2cap_test_util_peer_updates(0);
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_init_accept)
+{
+ ble_l2cap_test_util_we_update(1);
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_init_reject)
+{
+ ble_l2cap_test_util_we_update(0);
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_init_fail_master)
+{
+ struct ble_l2cap_sig_update_params params;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ params.itvl_min = 0x200;
+ params.itvl_max = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(2, &params, ble_l2cap_test_util_update_cb, NULL);
+ TEST_ASSERT_FATAL(rc == BLE_HS_EINVAL);
+
+ /* Ensure callback never called. */
+ TEST_ASSERT(ble_l2cap_test_update_status == -1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_update_init_fail_bad_id)
+{
+ struct ble_l2cap_sig_update_params params;
+ uint8_t id;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ /* Only the slave can initiate the L2CAP connection update procedure. */
+ ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0);
+
+ params.itvl_min = 0x200;
+ params.itvl_max = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(2, &params, ble_l2cap_test_util_update_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure an update request got sent. */
+ id = ble_hs_test_util_verify_tx_l2cap_update_req(&params);
+
+ /* Receive response from peer with incorrect ID. */
+ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id + 1, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback did not get called. */
+ TEST_ASSERT(ble_l2cap_test_update_status == -1);
+
+ /* Receive response from peer with correct ID. */
+ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ TEST_ASSERT(ble_l2cap_test_update_status == 0);
+ TEST_ASSERT(ble_l2cap_test_update_arg == NULL);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/* Test enum but first four events matches to events which L2CAP sends to
+ * application. We need this in order to add additional SEND_DATA event for
+ * testing
+ */
+
+enum {
+ BLE_L2CAP_TEST_EVENT_COC_CONNECT = 0,
+ BLE_L2CAP_TEST_EVENT_COC_DISCONNECT,
+ BLE_L2CAP_TEST_EVENT_COC_ACCEPT,
+ BLE_L2CAP_TEST_EVENT_COC_RECV_DATA,
+ BLE_L2CAP_TEST_EVENT_COC_SEND_DATA,
+};
+
+struct event {
+ uint8_t type;
+ uint16_t early_error;
+ uint16_t l2cap_status;
+ uint16_t app_status;
+ uint8_t handled;
+ uint8_t *data;
+ uint16_t data_len;
+};
+
+struct test_data {
+ struct event event[3];
+ uint16_t expected_num_of_ev;
+ uint16_t expected_num_iters;
+ /* This we use to track number of events sent to application*/
+ uint16_t event_cnt;
+ /* This we use to track verified events (received or not) */
+ uint16_t event_iter;
+ uint16_t psm;
+ uint16_t mtu;
+ uint8_t num;
+ struct ble_l2cap_chan *chan[5];
+};
+
+static int
+ble_l2cap_test_event(struct ble_l2cap_event *event, void *arg)
+{
+ struct test_data *t = arg;
+ struct event *ev = &t->event[t->event_cnt++];
+ struct os_mbuf *sdu_rx;
+
+ assert(ev->type == event->type);
+ ev->handled = 1;
+ switch(event->type) {
+ case BLE_L2CAP_EVENT_COC_CONNECTED:
+ assert(ev->app_status == event->connect.status);
+ t->chan[0] = event->connect.chan;
+ return 0;
+ case BLE_L2CAP_EVENT_COC_DISCONNECTED:
+ return 0;
+ case BLE_L2CAP_EVENT_COC_ACCEPT:
+ if (ev->app_status != 0) {
+ return ev->app_status;
+ }
+
+ sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu_rx != NULL);
+ ble_l2cap_recv_ready(event->accept.chan, sdu_rx);
+
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
+ sdu_rx = os_mbuf_pullup(event->receive.sdu_rx,
+ OS_MBUF_PKTLEN(event->receive.sdu_rx));
+ TEST_ASSERT(memcmp(sdu_rx->om_data, ev->data, ev->data_len) == 0);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
+ /* TODO Add tests for this */
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static uint16_t ble_l2cap_calculate_credits(uint16_t mtu, uint16_t mps)
+{
+ int credits;
+
+ credits = mtu / mps;
+ if (mtu % mps) {
+ credits++;
+ }
+
+ return credits;
+}
+
+static void
+ble_l2cap_test_coc_connect_multi(struct test_data *t)
+{
+ struct ble_l2cap_sig_credit_base_connect_req *req;
+ struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+ struct os_mbuf *sdu_rx[t->num];
+ struct event *ev = &t->event[t->event_iter++];
+ uint8_t id;
+ int rc;
+ int i;
+
+ req = malloc(sizeof(*req) + (sizeof(uint16_t) * t->num));
+ rsp = malloc(sizeof(*rsp) + (sizeof(uint16_t) * t->num));
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]) {1, 2, 3, 4, 5, 6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ for (i = 0; i < t->num; i++) {
+ sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu_rx[i] != NULL);
+ }
+
+ rc = ble_l2cap_sig_ecoc_connect(2, t->psm, t->mtu, t->num, sdu_rx,
+ ble_l2cap_test_event, t);
+ TEST_ASSERT_FATAL(rc == ev->early_error);
+
+ if (rc != 0) {
+ for (i = 0; i< t->num; i++) {
+ rc = os_mbuf_free_chain(sdu_rx[i]);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ return;
+ }
+
+ req->credits = htole16(
+ ble_l2cap_calculate_credits(t->mtu,
+ MYNEWT_VAL(BLE_L2CAP_COC_MPS)));
+ req->mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS));
+ req->mtu = htole16(t->mtu);
+ req->psm = htole16(t->psm);
+ for (i = 0; i < t->num; i++) {
+ req->scids[i] = htole16(current_cid + i);
+ }
+
+ /* Ensure an update request got sent. */
+ id = ble_hs_test_util_verify_tx_l2cap_sig(
+ BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ,
+ req, sizeof(*req) + t->num * sizeof(uint16_t));
+
+ /* Use some different parameters for peer. Just keep mtu same for testing
+ * only*/
+ rsp->credits = htole16(10);
+ for (i = 0; i < t->num; i++) {
+ rsp->dcids[i] = htole16(current_cid + i);
+ }
+ rsp->mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS) + 16);
+ rsp->mtu = htole16(t->mtu);
+ rsp->result = htole16(ev->l2cap_status);
+
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2,
+ BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+ id, rsp, sizeof(*rsp) + t->num * sizeof(uint16_t));
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ TEST_ASSERT(ev->handled);
+}
+
+static void
+ble_l2cap_test_coc_connect(struct test_data *t)
+{
+ struct ble_l2cap_sig_le_con_req req = {};
+ struct ble_l2cap_sig_le_con_rsp rsp = {};
+ struct os_mbuf *sdu_rx;
+ struct event *ev = &t->event[t->event_iter++];
+ uint8_t id;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu_rx != NULL);
+
+ rc = ble_l2cap_sig_coc_connect(2, t->psm, t->mtu, sdu_rx,
+ ble_l2cap_test_event, t);
+ TEST_ASSERT_FATAL(rc == ev->early_error);
+
+ if (rc != 0) {
+ rc = os_mbuf_free_chain(sdu_rx);
+ TEST_ASSERT_FATAL(rc == 0);
+ return;
+ }
+
+ req.credits = htole16(
+ ble_l2cap_calculate_credits(t->mtu,
+ MYNEWT_VAL(BLE_L2CAP_COC_MPS)));
+ req.mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS));
+ req.mtu = htole16(t->mtu);
+ req.psm = htole16(t->psm);
+ req.scid = htole16(current_cid);
+
+ /* Ensure an update request got sent. */
+ id = ble_hs_test_util_verify_tx_l2cap_sig(
+ BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_REQ,
+ &req, sizeof(req));
+
+ /* Use some different parameters for peer. Just keep mtu same for testing
+ * only*/
+ rsp.credits = htole16(10);
+ rsp.dcid = htole16(current_cid);
+ rsp.mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS) + 16);
+ rsp.mtu = htole16(t->mtu);
+ rsp.result = htole16(ev->l2cap_status);
+
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2,
+ BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP,
+ id, &rsp, sizeof(rsp));
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ TEST_ASSERT(ev->handled);
+}
+
+static void
+ble_l2cap_test_coc_connect_by_peer(struct test_data *t)
+{
+ struct ble_l2cap_sig_le_con_req req = {};
+ struct ble_l2cap_sig_le_con_rsp rsp = {};
+ uint8_t id = 10;
+ int rc;
+ struct event *ev = &t->event[t->event_iter++];
+
+ ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ /* Use some different parameters for peer */
+ req.credits = htole16(30);
+ req.mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS) + 16);
+ req.mtu = htole16(t->mtu);
+ req.psm = htole16(t->psm);
+ req.scid = htole16(0x0040);
+
+ /* Receive remote request*/
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2,
+ BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_REQ,
+ id, &req, sizeof(req));
+ TEST_ASSERT_FATAL(rc == 0);
+
+ if (ev->type == BLE_L2CAP_EVENT_COC_ACCEPT) {
+ /* Lets check if there is accept event */
+ TEST_ASSERT(ev->handled);
+ /* Ensure callback got called. */
+ ev = &t->event[t->event_iter++];
+ }
+
+ if (ev->l2cap_status != 0) {
+ rsp.result = htole16(ev->l2cap_status);
+ } else {
+ /* Receive response from peer.*/
+ rsp.credits = htole16(
+ ble_l2cap_calculate_credits(t->mtu,
+ MYNEWT_VAL(BLE_L2CAP_COC_MPS)));
+ rsp.dcid = htole16(current_cid);
+ rsp.mps = htole16(MYNEWT_VAL(BLE_L2CAP_COC_MPS));
+ rsp.mtu = htole16(t->mtu);
+ }
+
+ /* Ensure we sent response. */
+ TEST_ASSERT(id == ble_hs_test_util_verify_tx_l2cap_sig(
+ BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP,
+ &rsp, sizeof(rsp)));
+
+ if (ev->l2cap_status == 0) {
+ TEST_ASSERT(ev->handled);
+ } else {
+ TEST_ASSERT(!ev->handled);
+ }
+}
+
+static void
+ble_l2cap_test_coc_disc(struct test_data *t)
+{
+ struct ble_l2cap_sig_disc_req req;
+ struct event *ev = &t->event[t->event_iter++];
+ uint8_t id;
+ int rc;
+
+ rc = ble_l2cap_sig_disconnect(t->chan[0]);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ req.dcid = htole16(t->chan[0]->dcid);
+ req.scid = htole16(t->chan[0]->scid);
+
+ /* Ensure an update request got sent. */
+ id = ble_hs_test_util_verify_tx_l2cap_sig(BLE_L2CAP_SIG_OP_DISCONN_REQ,
+ &req, sizeof(req));
+
+ /* Receive response from peer. Note it shall be same as request */
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2, BLE_L2CAP_SIG_OP_DISCONN_RSP,
+ id, &req, sizeof(req));
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ TEST_ASSERT(ev->handled);
+}
+
+static void
+ble_l2cap_test_coc_disc_by_peer(struct test_data *t)
+{
+ struct ble_l2cap_sig_disc_req req;
+ struct event *ev = &t->event[t->event_iter++];
+ uint8_t id = 10;
+ int rc;
+
+ /* Receive disconnect request from peer. Note that source cid
+ * and destination cid are from peer perspective */
+ req.dcid = htole16(t->chan[0]->scid);
+ req.scid = htole16(t->chan[0]->dcid);
+
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2, BLE_L2CAP_SIG_OP_DISCONN_REQ,
+ id, &req, sizeof(req));
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ TEST_ASSERT(ev->handled);
+
+ /* Ensure an we sent back response. Note that payload is same as request,
+ * lets reuse it */
+ TEST_ASSERT(ble_hs_test_util_verify_tx_l2cap_sig(
+ BLE_L2CAP_SIG_OP_DISCONN_RSP,
+ &req, sizeof(req)) == id);
+}
+
+static void
+ble_l2cap_test_coc_invalid_disc_by_peer(struct test_data *t)
+{
+ struct ble_l2cap_sig_disc_req req;
+ uint8_t id = 10;
+ int rc;
+ struct event *ev = &t->event[t->event_iter++];
+
+ /* Receive disconnect request from peer. Note that source cid
+ * and destination cid are from peer perspective */
+ req.dcid = htole16(t->chan[0]->scid);
+ req.scid = htole16(0);
+
+ rc = ble_hs_test_util_inject_rx_l2cap_sig(2, BLE_L2CAP_SIG_OP_DISCONN_REQ,
+ id, &req, sizeof(req));
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback HAS NOT BEEN*/
+ TEST_ASSERT(!ev->handled);
+}
+
+static void
+ble_l2cap_test_coc_send_data(struct test_data *t)
+{
+ struct os_mbuf *sdu;
+ struct os_mbuf *sdu_copy;
+ struct event *ev = &t->event[t->event_iter++];
+ int rc;
+
+ /* Send data event is created only for testing.
+ * Since application callback do caching of real stack event
+ * and checks the type of the event, lets increase event counter here and
+ * fake that this event is handled*/
+ t->event_cnt++;
+
+ sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu != NULL);
+
+ sdu_copy = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu_copy != NULL);
+
+ rc = os_mbuf_append(sdu, ev->data, ev->data_len);
+ TEST_ASSERT(rc == 0);
+
+ rc = os_mbuf_append(sdu_copy, ev->data, ev->data_len);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_l2cap_send(t->chan[0], sdu);
+ TEST_ASSERT(rc == ev->early_error);
+
+ if (rc) {
+ rc = os_mbuf_free(sdu);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = os_mbuf_free(sdu_copy);
+ TEST_ASSERT_FATAL(rc == 0);
+ return;
+ }
+
+ /* Add place for SDU len */
+ sdu_copy = os_mbuf_prepend_pullup(sdu_copy, 2);
+ assert(sdu_copy != NULL);
+ put_le16(sdu_copy->om_data, ev->data_len);
+
+ ble_hs_test_util_verify_tx_l2cap(sdu);
+
+ rc = os_mbuf_free_chain(sdu_copy);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_l2cap_test_coc_recv_data(struct test_data *t)
+{
+ struct os_mbuf *sdu;
+ int rc;
+ struct event *ev = &t->event[t->event_iter++];
+
+ sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu != NULL);
+
+ rc = os_mbuf_append(sdu, ev->data, ev->data_len);
+ TEST_ASSERT(rc == 0);
+
+ /* TODO handle fragmentation */
+
+ /* Add place for SDU len */
+ sdu = os_mbuf_prepend_pullup(sdu, 2);
+ assert(sdu != NULL);
+ put_le16(sdu->om_data, ev->data_len);
+
+ ble_hs_test_util_inject_rx_l2cap(2, t->chan[0]->scid, sdu);
+}
+
+static void
+ble_l2cap_test_set_chan_test_conf(uint16_t psm, uint16_t mtu,
+ struct test_data *t)
+{
+ memset(t, 0, sizeof(*t));
+
+ t->psm = psm;
+ t->mtu = mtu;
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_invalid_psm)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+ t.expected_num_iters = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = BLE_HS_ENOTSUP;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM;
+
+ ble_l2cap_test_coc_connect(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+ TEST_ASSERT(t.expected_num_iters == t.event_iter);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_out_of_resource)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+ t.expected_num_iters = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = BLE_HS_ENOMEM;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_NO_RESOURCES;
+
+ ble_l2cap_test_coc_connect(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+ TEST_ASSERT(t.expected_num_iters == t.event_iter);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_invalid_cid)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = BLE_HS_EREJECT;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID;
+
+ ble_l2cap_test_coc_connect(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_insuff_authen)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = BLE_HS_EAUTHEN;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN;
+
+ ble_l2cap_test_coc_connect(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_insuff_author)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = BLE_HS_EAUTHOR;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR;
+
+ ble_l2cap_test_coc_connect(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_conn_invalid_psm)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 0;
+ t.expected_num_iters = 1;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM;
+
+ ble_l2cap_test_coc_connect_by_peer(&t);
+
+ TEST_ASSERT(t.expected_num_iters == t.event_iter);
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_conn_rejected_by_app)
+{
+ struct test_data t;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+ t.expected_num_iters = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_ACCEPT;
+ t.event[0].app_status = BLE_HS_ENOMEM;
+
+ /* This event will not be called and test is going to verify it*/
+ t.event[1].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[1].l2cap_status = BLE_L2CAP_COC_ERR_NO_RESOURCES;
+
+ /* Register server */
+ rc = ble_l2cap_create_server(t.psm, BLE_L2CAP_TEST_COC_MTU,
+ ble_l2cap_test_event, &t);
+ TEST_ASSERT(rc == 0);
+
+ ble_l2cap_test_coc_connect_by_peer(&t);
+
+ TEST_ASSERT(t.expected_num_iters == t.event_iter);
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_conn_success)
+{
+ struct test_data t;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_ACCEPT;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+
+ /* Register server */
+ rc = ble_l2cap_create_server(t.psm, BLE_L2CAP_TEST_COC_MTU,
+ ble_l2cap_test_event, &t);
+ TEST_ASSERT(rc == 0);
+
+ ble_l2cap_test_coc_connect_by_peer(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_disconnect_succeed)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t. expected_num_of_ev = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = 0;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_DISCONNECTED;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_disc(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_disconnect_succeed)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = 0;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_DISCONNECTED;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_disc_by_peer(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_disconnect_failed)
+{
+ struct test_data t;
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 1;
+ t.expected_num_iters = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[0].app_status = 0;
+ t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_DISCONNECTED;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_invalid_disc_by_peer(&t);
+
+ TEST_ASSERT(t.expected_num_iters == t.event_iter);
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_coc_send_data_succeed)
+{
+ struct test_data t;
+ uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 3;
+
+ t.event[0].type = BLE_L2CAP_TEST_EVENT_COC_CONNECT;
+ t.event[1].type = BLE_L2CAP_TEST_EVENT_COC_SEND_DATA;
+ t.event[1].data = buf;
+ t.event[1].data_len = sizeof(buf);
+ t.event[2].type = BLE_L2CAP_TEST_EVENT_COC_DISCONNECT;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_send_data(&t);
+ ble_l2cap_test_coc_disc(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_coc_send_data_failed_too_big_sdu)
+{
+ struct test_data t = {};
+ uint16_t small_mtu = 27;
+ uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM, small_mtu, &t);
+ t.expected_num_of_ev = 3;
+
+ t.event[0].type = BLE_L2CAP_TEST_EVENT_COC_CONNECT;
+ t.event[1].type = BLE_L2CAP_TEST_EVENT_COC_SEND_DATA;
+ t.event[1].data = buf;
+ t.event[1].data_len = sizeof(buf);
+ t.event[1].early_error = BLE_HS_EBADDATA;
+ t.event[2].type = BLE_L2CAP_TEST_EVENT_COC_DISCONNECT;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_send_data(&t);
+ ble_l2cap_test_coc_disc(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_coc_recv_data_succeed)
+{
+ struct test_data t = {};
+ uint8_t buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+ ble_l2cap_test_util_init();
+
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 3;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_DATA_RECEIVED;
+ t.event[1].data = buf;
+ t.event[1].data_len = sizeof(buf);
+ t.event[2].type = BLE_L2CAP_EVENT_COC_DISCONNECTED;
+
+ ble_l2cap_test_coc_connect(&t);
+ ble_l2cap_test_coc_recv_data(&t);
+ ble_l2cap_test_coc_disc(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_multi)
+{
+ struct test_data t;
+ int rc;
+
+ ble_l2cap_test_util_init();
+ ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM,
+ BLE_L2CAP_TEST_COC_MTU, &t);
+ t.expected_num_of_ev = 2;
+ t.num = 2;
+
+ t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+ t.event[1].type = BLE_L2CAP_EVENT_COC_CONNECTED;
+
+ /* Register server */
+ rc = ble_l2cap_create_server(t.psm, BLE_L2CAP_TEST_COC_MTU,
+ ble_l2cap_test_event, &t);
+ TEST_ASSERT(rc == 0);
+
+ ble_l2cap_test_coc_connect_multi(&t);
+
+ TEST_ASSERT(t.expected_num_of_ev == t.event_cnt);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_l2cap_test_suite)
+{
+ ble_l2cap_test_case_bad_header();
+ ble_l2cap_test_case_bad_handle();
+ ble_l2cap_test_case_frag_single();
+ ble_l2cap_test_case_frag_multiple();
+ ble_l2cap_test_case_frag_channels();
+ ble_l2cap_test_case_frag_timeout();
+ ble_l2cap_test_case_sig_unsol_rsp();
+ ble_l2cap_test_case_sig_update_accept();
+ ble_l2cap_test_case_sig_update_reject();
+ ble_l2cap_test_case_sig_update_init_accept();
+ ble_l2cap_test_case_sig_update_init_reject();
+ ble_l2cap_test_case_sig_update_init_fail_master();
+ ble_l2cap_test_case_sig_update_init_fail_bad_id();
+ ble_l2cap_test_case_sig_coc_conn_invalid_psm();
+ ble_l2cap_test_case_sig_coc_conn_out_of_resource();
+ ble_l2cap_test_case_sig_coc_conn_invalid_cid();
+ ble_l2cap_test_case_sig_coc_conn_insuff_authen();
+ ble_l2cap_test_case_sig_coc_conn_insuff_author();
+ ble_l2cap_test_case_sig_coc_incoming_conn_invalid_psm();
+ ble_l2cap_test_case_sig_coc_incoming_conn_rejected_by_app();
+ ble_l2cap_test_case_sig_coc_incoming_conn_success();
+ ble_l2cap_test_case_sig_coc_disconnect_succeed();
+ ble_l2cap_test_case_sig_coc_incoming_disconnect_succeed();
+ ble_l2cap_test_case_sig_coc_incoming_disconnect_failed();
+ ble_l2cap_test_case_coc_send_data_succeed();
+ ble_l2cap_test_case_coc_send_data_failed_too_big_sdu();
+ ble_l2cap_test_case_coc_recv_data_succeed();
+ ble_l2cap_test_case_sig_coc_conn_multi();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_os_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_os_test.c
new file mode 100644
index 00000000..fa57571b
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_os_test.c
@@ -0,0 +1,388 @@
+/*
+ * 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 "os/os.h"
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+#include "ble_hs_test.h"
+#include "host/ble_gap.h"
+#include "ble_hs_test_util.h"
+
+#define BLE_OS_TEST_STACK_SIZE 256
+#define BLE_OS_TEST_APP_STACK_SIZE 256
+
+#define BLE_OS_TEST_APP_PRIO 9
+#define BLE_OS_TEST_TASK_PRIO 10
+
+static struct os_task ble_os_test_task;
+static struct os_task ble_os_test_app_task;
+static os_stack_t ble_os_test_stack[OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE)];
+
+static os_stack_t
+ble_os_test_app_stack[OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE)];
+
+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_type;
+
+static void
+ble_os_test_init_app_task(void)
+{
+ int rc;
+
+ rc = os_task_init(&ble_os_test_app_task,
+ "ble_gap_terminate_test_task",
+ ble_os_test_app_task_handler, NULL,
+ BLE_OS_TEST_APP_PRIO, OS_WAIT_FOREVER,
+ ble_os_test_app_stack,
+ OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE));
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_os_test_misc_init(void)
+{
+ extern os_time_t g_os_time;
+
+ ble_hs_test_util_init_no_start();
+
+ /* Allow the OS to approach tick rollover. This will help ensure host
+ * timers don't break when the tick counter resets.
+ */
+ g_os_time = UINT32_MAX - 10 * OS_TICKS_PER_SEC;
+
+ /* Receive acknowledgements for the startup sequence. We sent the
+ * corresponding requests when the host task was started.
+ */
+ ble_hs_test_util_hci_ack_set_startup();
+
+ ble_os_test_init_app_task();
+}
+
+static int
+ble_os_test_misc_conn_exists(uint16_t conn_handle)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+
+ if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
+ conn = ble_hs_conn_first();
+ } else {
+ conn = ble_hs_conn_find(conn_handle);
+ }
+
+ ble_hs_unlock();
+
+ return conn != NULL;
+}
+
+static int
+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->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_PUBLIC);
+ TEST_ASSERT(memcmp(desc.peer_id_addr.val, ble_os_test_peer_addr, 6) == 0);
+
+ return 0;
+}
+
+static void
+ble_gap_direct_connect_test_task_handler(void *arg)
+{
+ struct ble_gap_conn_complete evt;
+ ble_addr_t addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+ int cb_called;
+ int rc;
+
+ /* Set the connect callback so we can verify that it gets called with the
+ * proper arguments.
+ */
+ cb_called = 0;
+
+ /* Make sure there are no created connections and no connections in
+ * progress.
+ */
+ TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
+
+ /* Initiate a direct connection. */
+ ble_hs_test_util_connect(BLE_OWN_ADDR_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);
+
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+
+ /* Receive an HCI connection-complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ memcpy(evt.peer_addr, addr.val, 6);
+ rc = ble_gap_rx_conn_complete(&evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ /* The connection should now be created. */
+ TEST_ASSERT(ble_os_test_misc_conn_exists(2));
+ TEST_ASSERT(cb_called);
+
+ tu_restart();
+}
+
+TEST_CASE_SELF(ble_gap_direct_connect_test_case)
+{
+ ble_os_test_misc_init();
+
+ os_task_init(&ble_os_test_task,
+ "ble_gap_direct_connect_test_task",
+ ble_gap_direct_connect_test_task_handler, NULL,
+ BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
+ OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
+
+ os_start();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+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->type == BLE_GAP_EVENT_DISC_COMPLETE);
+
+ return 0;
+}
+
+static void
+ble_os_disc_test_task_handler(void *arg)
+{
+ struct ble_gap_disc_params disc_params;
+ int cb_called;
+ int rc;
+
+ /* Receive acknowledgements for the startup sequence. We sent the
+ * corresponding requests when the host task was started.
+ */
+ ble_hs_test_util_hci_ack_set_startup();
+
+ /* Set the connect callback so we can verify that it gets called with the
+ * proper arguments.
+ */
+ cb_called = 0;
+
+ os_time_delay(10);
+
+ /* Make sure there are no created connections and no connections in
+ * progress.
+ */
+ 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 300 ms timeout. */
+ memset(&disc_params, 0, sizeof disc_params);
+ rc = ble_hs_test_util_disc(BLE_OWN_ADDR_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));
+ TEST_ASSERT(ble_gap_master_in_progress());
+ TEST_ASSERT(!cb_called);
+
+ /* Receive acks from the controller. */
+ TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
+ TEST_ASSERT(ble_gap_master_in_progress());
+ TEST_ASSERT(!cb_called);
+
+ /* Wait 100 ms; verify scan still in progress. */
+ os_time_delay(100 * OS_TICKS_PER_SEC / 1000);
+ TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
+ TEST_ASSERT(ble_gap_master_in_progress());
+ TEST_ASSERT(!cb_called);
+
+ ble_hs_test_util_hci_ack_set(
+ 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. */
+ os_time_delay(250 * OS_TICKS_PER_SEC / 1000);
+ TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
+ TEST_ASSERT(!ble_gap_master_in_progress());
+ TEST_ASSERT(cb_called);
+
+ tu_restart();
+}
+
+TEST_CASE_SELF(ble_os_disc_test_case)
+{
+ ble_os_test_misc_init();
+
+ os_task_init(&ble_os_test_task,
+ "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));
+
+ os_start();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+static int
+ble_gap_terminate_cb(struct ble_gap_event *event, void *arg)
+{
+ int *disconn_handle;
+
+ ble_os_test_gap_event_type = event->type;
+
+ if (event->type == BLE_GAP_EVENT_DISCONNECT) {
+ disconn_handle = arg;
+ *disconn_handle = event->disconnect.conn.conn_handle;
+ }
+
+ return 0;
+}
+
+static void
+ble_gap_terminate_test_task_handler(void *arg)
+{
+ struct ble_gap_conn_complete conn_evt;
+ ble_addr_t addr1 = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
+ ble_addr_t addr2 = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 }};
+ int disconn_handle;
+ int rc;
+
+ /* Receive acknowledgements for the startup sequence. We sent the
+ * corresponding requests when the host task was started.
+ */
+ ble_hs_test_util_hci_ack_set_startup();
+
+ /* Set the connect callback so we can verify that it gets called with the
+ * proper arguments.
+ */
+ disconn_handle = 0;
+
+ /* Make sure there are no created connections and no connections in
+ * progress.
+ */
+ TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
+ TEST_ASSERT(!ble_gap_master_in_progress());
+
+ /* Create two direct connections. */
+ ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
+ &addr1, 0, NULL, ble_gap_terminate_cb,
+ &disconn_handle, 0);
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+ memset(&conn_evt, 0, sizeof conn_evt);
+ conn_evt.status = BLE_ERR_SUCCESS;
+ conn_evt.connection_handle = 1;
+ memcpy(conn_evt.peer_addr, addr1.val, 6);
+ rc = ble_gap_rx_conn_complete(&conn_evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
+ &addr2, 0, NULL, ble_gap_terminate_cb,
+ &disconn_handle, 0);
+ /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
+ ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
+ memset(&conn_evt, 0, sizeof conn_evt);
+ conn_evt.status = BLE_ERR_SUCCESS;
+ conn_evt.connection_handle = 2;
+ memcpy(conn_evt.peer_addr, addr2.val, 6);
+ rc = ble_gap_rx_conn_complete(&conn_evt, 0);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(1));
+ TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
+
+ /* Terminate the first one. */
+ rc = ble_hs_test_util_conn_terminate(1, 0);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_hci_rx_disconn_complete_event(1, 0, BLE_ERR_REM_USER_CONN_TERM);
+ 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));
+
+ /* Terminate the second one. */
+ rc = ble_hs_test_util_conn_terminate(2, 0);
+ TEST_ASSERT(rc == 0);
+ ble_hs_test_util_hci_rx_disconn_complete_event(2, 0, BLE_ERR_REM_USER_CONN_TERM);
+ 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));
+
+ tu_restart();
+}
+
+static void
+ble_os_test_app_task_handler(void *arg)
+{
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+}
+
+TEST_CASE_SELF(ble_gap_terminate_test_case)
+{
+ ble_os_test_misc_init();
+
+ os_task_init(&ble_os_test_task,
+ "ble_gap_terminate_test_task",
+ ble_gap_terminate_test_task_handler, NULL,
+ BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
+ OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
+
+ os_start();
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_os_test_suite)
+{
+ ble_os_disc_test_case();
+ ble_gap_direct_connect_test_case();
+ ble_gap_terminate_test_case();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_lgcy_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_lgcy_test.c
new file mode 100644
index 00000000..4529d362
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_lgcy_test.c
@@ -0,0 +1,849 @@
+/*
+ * 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 <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "nimble/nimble_opt.h"
+#include "host/ble_sm.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+#include "ble_sm_test_util.h"
+
+#if NIMBLE_BLE_SM
+
+/**
+ * Legacy pairing
+ * Master: peer
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 4
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_PUBLIC
+ * Initiator key distribution: 7
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_lgcy_peer_jw_iio4_rio3_b1_iat0_rat0_ik7_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0xcd, 0x5b, 0x79, 0x29, 0x53, 0x31, 0x56, 0x23,
+ 0x2c, 0x08, 0xed, 0x81, 0x16, 0x55, 0x8e, 0x01,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x49, 0x39, 0x22, 0x0f, 0x7b, 0x1b, 0x80, 0xcd,
+ 0xbe, 0x89, 0xd1, 0x4c, 0xbd, 0x6f, 0xda, 0x2c,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x7f, 0x42, 0xc0, 0x2f, 0x1d, 0x07, 0x37, 0xfc,
+ 0x04, 0x5b, 0x05, 0x9a, 0xed, 0x67, 0xa5, 0x68,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x42, 0x1a, 0x58, 0xa2, 0x3b, 0x80, 0xde, 0xef,
+ 0x95, 0x0d, 0xf7, 0xca, 0x06, 0x05, 0x01, 0x3c,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0x2f, 0x9b, 0x16, 0xff, 0xf3, 0x73, 0x30, 0x08,
+ 0xa8, 0xe5, 0x01, 0xb1, 0x3b, 0xe1, 0x87, 0x00,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0xf8e0,
+ .rand_val = 0xef7c818b00000000,
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0xc6, 0x17, 0xc0, 0x02, 0x40, 0x0d, 0x27, 0x51,
+ 0x8a, 0x77, 0xb5, 0xae, 0xd8, 0xa9, 0x7a, 0x7a,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0xd7, 0x07, 0x22, 0x79, 0x24, 0xc6, 0xcb, 0x4d,
+ 0xa3, 0xdd, 0x01, 0xfb, 0x48, 0x87, 0xd4, 0xcf,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x9a39,
+ .rand_val = 0x8e76d9b00000000,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xeb, 0x8a, 0x06, 0xc4, 0x93, 0x51, 0x04, 0xb3,
+ 0x8b, 0xbf, 0xe8, 0x1f, 0x0e, 0x96, 0x2a, 0x54,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x14, 0x55, 0x93, 0xe1, 0xd1, 0xe7, 0xc4, 0x5d,
+ 0x35, 0x97, 0xd3, 0x05, 0x30, 0xc8, 0x9d, 0x83,
+ },
+ },
+ .stk = {
+ 0x1c, 0xd7, 0xb6, 0x35, 0x48, 0xfc, 0x9f, 0xef,
+ 0x0e, 0x2f, 0x51, 0x77, 0xed, 0xdd, 0xbc, 0xaf,
+ },
+ .pair_alg = 0,
+ .authenticated = false,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_peer_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Legacy pairing
+ * Master: peer
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 4
+ * Responder IO capabilities: 0
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_PUBLIC
+ * Initiator key distribution: 7
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_lgcy_peer_pk_iio4_rio0_b1_iat0_rat0_ik7_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0xa0, 0x10, 0x4a, 0xaa, 0x8b, 0x53, 0x78, 0xbb,
+ 0xd2, 0xae, 0x71, 0x1f, 0x4e, 0x00, 0x70, 0x8b,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x62, 0xf3, 0xba, 0x0e, 0xe5, 0xbe, 0x2e, 0xd8,
+ 0x25, 0xb2, 0xec, 0x4c, 0x28, 0x77, 0x28, 0x60,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x84, 0xcf, 0xe4, 0x04, 0x7d, 0xf3, 0xfc, 0xa1,
+ 0x3f, 0x75, 0xd6, 0x5a, 0x7c, 0xb7, 0xa4, 0x39,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0xef, 0x6a, 0x61, 0x6e, 0x02, 0x60, 0x7f, 0x5d,
+ 0x7f, 0x0d, 0xa6, 0x3c, 0x06, 0x1a, 0x5d, 0xd6,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0xad, 0x01, 0x6d, 0x76, 0xa9, 0xd0, 0x23, 0xc9,
+ 0x40, 0x0c, 0xbf, 0x2a, 0x4c, 0x23, 0x31, 0xc5,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0xa74f,
+ .rand_val = 0x81cab3fd00000000,
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x60, 0x08, 0x49, 0x00, 0x6d, 0x76, 0x98, 0x73,
+ 0x9c, 0x95, 0xc4, 0xd9, 0xe8, 0x3a, 0x69, 0xbb,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0x5b, 0x73, 0x39, 0xd9, 0x51, 0x3d, 0x92, 0xa4,
+ 0x34, 0x65, 0xa5, 0x70, 0x49, 0xbe, 0x11, 0x28,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x9705,
+ .rand_val = 0x592f1e8d00000000,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xeb, 0x8a, 0x06, 0xc4, 0x93, 0x51, 0x04, 0xb3,
+ 0x8b, 0xbf, 0xe8, 0x1f, 0x0e, 0x96, 0x2a, 0x54,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xc9, 0x9b, 0xf2, 0x75, 0xb7, 0x0d, 0xe8, 0x60,
+ 0x3d, 0xf0, 0xd6, 0xa8, 0x16, 0xc5, 0x6c, 0x2a,
+ },
+ },
+ .stk = {
+ 0xf2, 0x3c, 0x36, 0xc4, 0xa1, 0xfb, 0x5a, 0xa7,
+ 0x96, 0x20, 0xe4, 0x29, 0xb7, 0x58, 0x22, 0x7a,
+ },
+ .pair_alg = 1,
+ .authenticated = true,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_DISP,
+ .passkey = 46128,
+ },
+ },
+ };
+ ble_sm_test_util_peer_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Legacy pairing
+ * Master: us
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_RANDOM
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_lgcy_us_jw_iio3_rio3_b1_iat0_rat1_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
+ },
+ .resp_addr_type = BLE_ADDR_RANDOM,
+ .resp_id_addr = {
+ 0x11, 0x22, 0x11, 0x22, 0x11, 0xcc,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x01,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x01,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x1c, 0xb6, 0x10, 0xea, 0x02, 0x08, 0x90, 0x64,
+ 0xc7, 0xf8, 0xe5, 0x9c, 0xb4, 0x3a, 0x18, 0xca,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0xb8, 0x6f, 0xd1, 0xc6, 0x74, 0x35, 0xa3, 0x94,
+ 0x68, 0x2f, 0xf1, 0x4c, 0x78, 0x44, 0xe8, 0x0d,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x40, 0x48, 0x17, 0x4d, 0x42, 0xa0, 0xf8, 0xd5,
+ 0xbf, 0x65, 0x67, 0xb8, 0x5e, 0x57, 0x38, 0xac,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x2c, 0xa1, 0xb1, 0xf5, 0x54, 0x9b, 0x43, 0xe9,
+ 0xb0, 0x62, 0x6a, 0xb0, 0x02, 0xb8, 0x6c, 0xca,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0x01, 0x15, 0xb6, 0x93, 0xc9, 0xff, 0xfe, 0x27,
+ 0x02, 0x41, 0xfd, 0x7b, 0x0e, 0x31, 0xd4, 0xa6,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0xe4fb,
+ .rand_val = 0x8eee76b100000000,
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x00, 0x2d, 0xf6, 0x3e, 0x5e, 0x0f, 0xd1, 0xe8,
+ 0x4e, 0x5f, 0x61, 0x1c, 0x2c, 0x0b, 0xa5, 0x51,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0x88, 0xbc, 0x95, 0x8d, 0xaa, 0x26, 0x8d, 0xd5,
+ 0x18, 0xc9, 0x06, 0x70, 0xc2, 0x30, 0x56, 0x4c,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x4413,
+ .rand_val = 0xfad1c27300000000,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x03, 0xad, 0xa4, 0xe1, 0x34, 0x76, 0x95, 0x54,
+ 0xe5, 0x8f, 0xa4, 0x06, 0x72, 0xe6, 0xfc, 0x65,
+ },
+ },
+ .stk = {
+ 0x31, 0x54, 0x42, 0x6c, 0x1c, 0x03, 0x36, 0x44,
+ 0x0b, 0x72, 0x90, 0xa5, 0x1f, 0x79, 0x5b, 0xe9,
+ },
+ .pair_alg = 0,
+ .authenticated = false,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_us_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Legacy pairing
+ * Master: us
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 4
+ * Responder IO capabilities: 2
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_RANDOM
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_lgcy_us_pk_iio4_rio2_b1_iat0_rat1_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
+ },
+ .resp_addr_type = BLE_ADDR_RANDOM,
+ .resp_id_addr = {
+ 0x11, 0x22, 0x11, 0x22, 0x11, 0xcc,
+ },
+ .pair_req = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0xb5, 0xd4, 0xc5, 0xe8, 0xef, 0xef, 0xd8, 0xd7,
+ 0x2b, 0x14, 0x34, 0x35, 0x29, 0x18, 0xda, 0x12,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x1a, 0x03, 0x20, 0xda, 0x60, 0x21, 0x9b, 0x4b,
+ 0x5d, 0x45, 0x90, 0x64, 0xe1, 0x24, 0x2c, 0xb6,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x45, 0xa3, 0x1a, 0x0b, 0xf6, 0x0f, 0x7c, 0xcf,
+ 0x1a, 0xfb, 0xfc, 0x1a, 0xad, 0x62, 0x0e, 0x76,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x82, 0xbb, 0x9f, 0x67, 0xc4, 0x88, 0xcb, 0x58,
+ 0xee, 0xf9, 0x34, 0x35, 0x23, 0xa3, 0xd0, 0x22,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0xfa, 0x43, 0x8f, 0x1f, 0xe6, 0x2a, 0x94, 0x5b,
+ 0x54, 0x89, 0x2b, 0x0f, 0xd7, 0x23, 0x77, 0x9e,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0x88b3,
+ .rand_val = 0x7c970e18dec74560,
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x2e, 0x70, 0x3c, 0xbf, 0x20, 0xbe, 0x7d, 0x2d,
+ 0xb3, 0x50, 0x46, 0x33, 0x4c, 0x20, 0x0e, 0xc8,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0xc1, 0x64, 0x33, 0x10, 0x0f, 0x70, 0x2f, 0x9c,
+ 0xe7, 0x31, 0xc5, 0x32, 0xdd, 0x98, 0x16, 0x75,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x1c19,
+ .rand_val = 0xef308872dc2a4cc2,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xd7, 0x75, 0xfa, 0xed, 0xd7, 0xdd, 0x7b, 0xb3,
+ 0xa4, 0x20, 0xea, 0x2f, 0x75, 0x60, 0xb1, 0x84,
+ },
+ },
+ .stk = {
+ 0x9e, 0xe8, 0x35, 0x22, 0xb6, 0xbb, 0x54, 0x0d,
+ 0x48, 0x1b, 0x25, 0xa0, 0xd8, 0xe2, 0xa5, 0x08,
+ },
+ .pair_alg = 1,
+ .authenticated = true,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_DISP,
+ .passkey = 46128,
+ },
+ },
+ };
+ ble_sm_test_util_us_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Legacy pairing
+ * Master: us
+ * Pair algorithm: out of band
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_PUBLIC
+ * Initiator key distribution: 7
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_lgcy_us_ob_iio3_rio3_b1_iat0_rat0_ik7_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ .resp_id_addr = {
+ 0x66, 0x33, 0x22, 0x66, 0x55, 0x11,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x01,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x01,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x2c, 0x3f, 0x3e, 0xf5, 0x39, 0x50, 0x78, 0x4a,
+ 0x3e, 0x14, 0x1a, 0x51, 0xfb, 0x8d, 0x6c, 0x10,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0xa9, 0x5c, 0x18, 0xb1, 0xdb, 0x51, 0x53, 0xa5,
+ 0xd3, 0xe7, 0x72, 0x17, 0xfb, 0xa8, 0xfb, 0xeb,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x40, 0x2f, 0x42, 0xba, 0x10, 0x7b, 0x22, 0x65,
+ 0x84, 0xef, 0x63, 0xdf, 0x84, 0x7b, 0x04, 0xef,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x94, 0xdc, 0x3c, 0xef, 0x65, 0xf7, 0x99, 0x2e,
+ 0x50, 0x29, 0x97, 0x2a, 0x57, 0xfd, 0xe6, 0x6a,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0x8c, 0x8e, 0x57, 0xba, 0x17, 0xbb, 0x04, 0xb5,
+ 0x16, 0xad, 0x31, 0x37, 0xf8, 0x3e, 0x4f, 0x21,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0xaaa4,
+ .rand_val = 0xc0c830e300000000,
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x66, 0x33, 0x22, 0x66, 0x55, 0x11,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x5a, 0xe4, 0x2b, 0x40, 0x3a, 0x34, 0x1d, 0x94,
+ 0x56, 0x7d, 0xf4, 0x41, 0x23, 0x81, 0xc4, 0x11,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0xa6, 0x8e, 0xa0, 0xa4, 0x02, 0x64, 0x4c, 0x09,
+ 0x31, 0x25, 0x8a, 0x4f, 0x49, 0x35, 0xb0, 0x1f,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x57a3,
+ .rand_val = 0x8276af9000000000,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x8e, 0xef, 0x53, 0x5c, 0x1b, 0x21, 0x67, 0x8d,
+ 0x07, 0x5e, 0xaa, 0xe8, 0x41, 0xa9, 0x36, 0xcf,
+ },
+ },
+ .stk = {
+ 0x4c, 0xd4, 0xa7, 0xee, 0x83, 0xcd, 0xd1, 0x9e,
+ 0x84, 0xeb, 0xb8, 0xd2, 0xaf, 0x4a, 0x71, 0x2e,
+ },
+ .pair_alg = 2,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_OOB,
+ .oob = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ },
+ },
+ },
+ };
+ ble_sm_test_util_us_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Legacy pairing
+ * Master: peer
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 4
+ * Responder IO capabilities: 4
+ * Bonding: true
+ * Initiator address type: BLE_ADDR_PUBLIC
+ * Responder address type: BLE_ADDR_PUBLIC
+ * Initiator key distribution: 7
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_lgcy_peer_pk_iio4_rio4_b1_iat0_rat0_ik7_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x05,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x93, 0x64, 0xb1, 0xb0, 0x07, 0x41, 0x22, 0xe7,
+ 0x3e, 0x5a, 0x87, 0xf5, 0x1f, 0x25, 0x79, 0x11,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x2d, 0x40, 0x15, 0xc4, 0x21, 0xeb, 0xd5, 0x73,
+ 0xc8, 0x5d, 0xb8, 0xb9, 0x45, 0x31, 0xd5, 0x58,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x8c, 0x2c, 0x3b, 0xf3, 0x90, 0xaa, 0x2e, 0xcf,
+ 0xc7, 0x5b, 0xf6, 0xae, 0xb6, 0x4c, 0xc3, 0x61,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x7a, 0x94, 0x97, 0x0a, 0xbe, 0xaf, 0xc0, 0x6b,
+ 0xd4, 0xf4, 0x04, 0xd1, 0x21, 0x46, 0x34, 0xf3,
+ },
+ },
+ .enc_info_req = {
+ .ltk = {
+ 0x3a, 0x10, 0xd1, 0xab, 0x13, 0xee, 0x16, 0xee,
+ 0xcf, 0xae, 0xf1, 0x63, 0xf0, 0x6f, 0xb0, 0x89,
+ },
+ },
+ .master_id_req = {
+ .ediv = 0xb634,
+ .rand_val = 0xa99ac2007b4278a8,
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x51, 0x4b, 0x7b, 0x31, 0xf7, 0xa6, 0x8a, 0x60,
+ 0x4f, 0x10, 0x04, 0x5f, 0xb8, 0xee, 0xf6, 0xb3,
+ },
+ },
+ .enc_info_rsp = {
+ .ltk = {
+ 0xa1, 0x1d, 0xdd, 0xee, 0x85, 0xcb, 0xe0, 0x48,
+ 0x1e, 0xdd, 0xa4, 0x9d, 0xed, 0x3f, 0x15, 0x17,
+ },
+ },
+ .master_id_rsp = {
+ .ediv = 0x7e06,
+ .rand_val = 0xe6077f688c5ca67,
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xeb, 0x8a, 0x06, 0xc4, 0x93, 0x51, 0x04, 0xb3,
+ 0x8b, 0xbf, 0xe8, 0x1f, 0x0e, 0x96, 0x2a, 0x54,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x16, 0x7a, 0x2e, 0x9d, 0x43, 0x4d, 0x7b, 0x0b,
+ 0x88, 0xe2, 0x11, 0xb0, 0x4d, 0xa1, 0xed, 0x08,
+ },
+ },
+ .stk = {
+ 0x6c, 0x3e, 0x78, 0x47, 0xe8, 0x57, 0x9f, 0xe9,
+ 0x3a, 0x8f, 0x0a, 0xbb, 0xd4, 0x60, 0xf6, 0x0d,
+ },
+ .pair_alg = 1,
+ .authenticated = true,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_INPUT,
+ .passkey = 449182,
+ },
+ },
+ };
+ ble_sm_test_util_peer_lgcy_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_sm_lgcy_test_suite)
+{
+ /*** No privacy. */
+
+ /* Peer as initiator. */
+ ble_sm_lgcy_peer_jw_iio4_rio3_b1_iat0_rat0_ik7_rk7();
+ ble_sm_lgcy_peer_pk_iio4_rio0_b1_iat0_rat0_ik7_rk7();
+ ble_sm_lgcy_peer_pk_iio4_rio4_b1_iat0_rat0_ik7_rk7();
+
+ /* Us as initiator. */
+ ble_sm_lgcy_us_jw_iio3_rio3_b1_iat0_rat1_ik7_rk5();
+ ble_sm_lgcy_us_pk_iio4_rio2_b1_iat0_rat1_ik7_rk5();
+ ble_sm_lgcy_us_ob_iio3_rio3_b1_iat0_rat0_ik7_rk7();
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_sc_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_sc_test.c
new file mode 100644
index 00000000..c3d19550
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_sc_test.c
@@ -0,0 +1,4938 @@
+/*
+ * 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 <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "nimble/nimble_opt.h"
+#include "host/ble_sm.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+#include "ble_sm_test_util.h"
+
+#if NIMBLE_BLE_SM
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 5
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_jw_iio3_rio3_b1_iat0_rat0_ik5_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x0d,
+ .resp_key_dist = 0x0f,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x05,
+ .resp_key_dist = 0x07,
+ },
+ .our_priv_key = {
+ 0x54, 0x8d, 0x20, 0xb8, 0x97, 0x0b, 0xbc, 0x43,
+ 0x9a, 0xad, 0x10, 0x6f, 0x60, 0x74, 0xd4, 0x6a,
+ 0x55, 0xc1, 0x7a, 0x17, 0x8b, 0x60, 0xe0, 0xb4,
+ 0x5a, 0xe6, 0x58, 0xf1, 0xea, 0x12, 0xd9, 0xfb,
+ },
+ .public_key_req = {
+ .x = {
+ 0xbc, 0xf2, 0xd8, 0xa5, 0xdb, 0xa3, 0x95, 0x6c,
+ 0x99, 0xf9, 0x11, 0x0d, 0x4d, 0x2e, 0xf0, 0xbd,
+ 0xee, 0x9b, 0x69, 0xb6, 0xcd, 0x88, 0x74, 0xbe,
+ 0x40, 0xe8, 0xe5, 0xcc, 0xdc, 0x88, 0x44, 0x53,
+ },
+ .y = {
+ 0xbf, 0xa9, 0x82, 0x0e, 0x18, 0x7a, 0x14, 0xf8,
+ 0x77, 0xfd, 0x8e, 0x92, 0x2a, 0xf8, 0x5d, 0x39,
+ 0xd1, 0x6d, 0x92, 0x1f, 0x38, 0x74, 0x99, 0xdc,
+ 0x6c, 0x2c, 0x94, 0x23, 0xf9, 0x72, 0x56, 0xab,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x72, 0x8c, 0xd1, 0x88, 0xd7, 0xbe, 0x49, 0xb2,
+ 0xc5, 0x5c, 0x95, 0xb3, 0x64, 0xe0, 0x12, 0x32,
+ 0xb6, 0xc9, 0x47, 0x63, 0x37, 0x38, 0x5b, 0x9c,
+ 0x1e, 0x1b, 0x1a, 0x06, 0x09, 0xe2, 0x31, 0x85,
+ },
+ .y = {
+ 0x19, 0x3a, 0x29, 0x69, 0x62, 0xd6, 0x30, 0xe7,
+ 0xe8, 0x48, 0x63, 0xdc, 0x00, 0x73, 0x0a, 0x70,
+ 0x7d, 0x2e, 0x29, 0xcc, 0x91, 0x77, 0x71, 0xb1,
+ 0x75, 0xb8, 0xf7, 0xdc, 0xb0, 0xe2, 0x91, 0x10,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x82, 0xed, 0xd0, 0x62, 0x91, 0x3d, 0x96, 0x7f,
+ 0x13, 0xc5, 0x0d, 0x02, 0x2b, 0x5e, 0x43, 0x16,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xa4, 0x34, 0x5f, 0xb3, 0xaf, 0x73, 0x43, 0x64,
+ 0xcd, 0x19, 0x1b, 0x5b, 0x87, 0x58, 0x31, 0x66,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0xc0, 0x91, 0xfb, 0xb3, 0x77, 0xa2, 0x02, 0x0b,
+ 0xc6, 0xcd, 0x6c, 0x04, 0x51, 0x45, 0x45, 0x39,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x82, 0x65, 0x1d, 0x02, 0xed, 0x89, 0x13, 0x44,
+ 0x04, 0x1a, 0x14, 0x7c, 0x32, 0x9a, 0x1e, 0x7d,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x06, 0x3c, 0x28, 0x4a, 0xe5, 0x48, 0x4b, 0x51,
+ 0x65, 0x4e, 0x14, 0x5e, 0x2f, 0xdd, 0xfa, 0x22,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x40, 0x53, 0xeb, 0x7a, 0x4d, 0x8e, 0xa2, 0xb5,
+ 0xca, 0xa1, 0xb6, 0xae, 0x7e, 0x6a, 0x4d, 0xd9,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xbc, 0x13, 0x4b, 0x45, 0xda, 0x76, 0x5b, 0xcd,
+ 0xc2, 0x43, 0x81, 0xb8, 0xc3, 0x68, 0x12, 0xbb,
+ },
+ },
+ .ltk = {
+ 0x63, 0x59, 0x8a, 0x14, 0x09, 0x4b, 0x94, 0x6e,
+ 0xff, 0xae, 0x5e, 0x53, 0x86, 0x02, 0xa3, 0x6c,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_JW,
+ .authenticated = 0,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 0
+ * Responder IO capabilities: 2
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 5
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_pk_iio0_rio2_b1_iat0_rat0_ik5_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x0d,
+ .resp_key_dist = 0x0f,
+ },
+ .pair_rsp = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x05,
+ .resp_key_dist = 0x07,
+ },
+ .our_priv_key = {
+ 0x54, 0x8d, 0x20, 0xb8, 0x97, 0x0b, 0xbc, 0x43,
+ 0x9a, 0xad, 0x10, 0x6f, 0x60, 0x74, 0xd4, 0x6a,
+ 0x55, 0xc1, 0x7a, 0x17, 0x8b, 0x60, 0xe0, 0xb4,
+ 0x5a, 0xe6, 0x58, 0xf1, 0xea, 0x12, 0xd9, 0xfb,
+ },
+ .public_key_req = {
+ .x = {
+ 0x22, 0x26, 0xcc, 0x64, 0x4d, 0xc1, 0x01, 0xd1,
+ 0xb9, 0x8d, 0xe2, 0xd4, 0xbc, 0x55, 0x37, 0x4c,
+ 0x12, 0x81, 0x14, 0x83, 0x81, 0xe8, 0x36, 0x1b,
+ 0x78, 0xff, 0x49, 0xfc, 0xe9, 0x2e, 0x56, 0xc0,
+ },
+ .y = {
+ 0xd9, 0x31, 0xa5, 0x8d, 0x02, 0xf1, 0x94, 0xb6,
+ 0x83, 0x97, 0xd1, 0xfb, 0x01, 0x97, 0x4d, 0x06,
+ 0xec, 0x18, 0x8d, 0x4a, 0xd2, 0x14, 0x12, 0x95,
+ 0x2d, 0x4d, 0x18, 0xde, 0x4d, 0xaa, 0x91, 0x25,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x72, 0x8c, 0xd1, 0x88, 0xd7, 0xbe, 0x49, 0xb2,
+ 0xc5, 0x5c, 0x95, 0xb3, 0x64, 0xe0, 0x12, 0x32,
+ 0xb6, 0xc9, 0x47, 0x63, 0x37, 0x38, 0x5b, 0x9c,
+ 0x1e, 0x1b, 0x1a, 0x06, 0x09, 0xe2, 0x31, 0x85,
+ },
+ .y = {
+ 0x19, 0x3a, 0x29, 0x69, 0x62, 0xd6, 0x30, 0xe7,
+ 0xe8, 0x48, 0x63, 0xdc, 0x00, 0x73, 0x0a, 0x70,
+ 0x7d, 0x2e, 0x29, 0xcc, 0x91, 0x77, 0x71, 0xb1,
+ 0x75, 0xb8, 0xf7, 0xdc, 0xb0, 0xe2, 0x91, 0x10,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x2c, 0x16, 0x15, 0x0d, 0xe8, 0x18, 0x50, 0xd8,
+ 0xae, 0x04, 0x6c, 0xa8, 0x50, 0xb8, 0xe5, 0x85,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x62, 0x53, 0xfb, 0x69, 0x94, 0x33, 0x11, 0xd3,
+ 0x8e, 0x03, 0xd5, 0x05, 0xd7, 0x68, 0x33, 0x16,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xd5, 0x0e, 0x27, 0xcf, 0xa4, 0xc1, 0x52, 0x1b,
+ 0xf1, 0x9d, 0x5f, 0xbe, 0xe2, 0xc0, 0x48, 0x38,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x94, 0x31, 0x95, 0x44, 0x6c, 0xc5, 0x73, 0xc8,
+ 0x8d, 0x72, 0x06, 0xe7, 0xfd, 0x16, 0x70, 0x5d,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0x80, 0xae, 0x74, 0xaa, 0x9a, 0xfc, 0x09, 0x97,
+ 0x10, 0x01, 0x4e, 0xbb, 0x16, 0x36, 0x6b, 0xc7,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0x5a, 0xb1, 0xe5, 0x81, 0x5a, 0x1b, 0xef, 0xf4,
+ 0xa8, 0x3d, 0xaa, 0x3f, 0x02, 0x1f, 0x78, 0x55,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0x04, 0x4a, 0xf4, 0xd5, 0x4b, 0x4f, 0x77, 0x37,
+ 0x2a, 0x3c, 0xfe, 0x83, 0x34, 0x6b, 0x38, 0x1a,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0x24, 0xb3, 0x47, 0xc8, 0xb0, 0xa2, 0xa3, 0xd8,
+ 0x78, 0x3d, 0x09, 0x8d, 0xea, 0x49, 0xf6, 0x22,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0x56, 0x5f, 0x07, 0x30, 0x3a, 0xc1, 0x44, 0xf9,
+ 0x00, 0x03, 0xb3, 0x93, 0x58, 0xb4, 0x2c, 0x85,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0x50, 0x8a, 0xb3, 0x0b, 0xe4, 0x2e, 0xd3, 0x49,
+ 0x59, 0x40, 0xb2, 0x71, 0xc9, 0x49, 0x29, 0x19,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0x32, 0x37, 0x8e, 0x63, 0x6d, 0xbd, 0xd6, 0x18,
+ 0xee, 0xa7, 0x0e, 0xe5, 0x7e, 0x5f, 0xe1, 0x80,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0xa2, 0x1a, 0x92, 0xcd, 0xc0, 0x8f, 0x92, 0xb0,
+ 0xe6, 0xbe, 0x43, 0x55, 0xc8, 0x47, 0x56, 0x4b,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0x1b, 0xa0, 0x82, 0xda, 0xfc, 0xaf, 0x3f, 0x9c,
+ 0xdf, 0xff, 0xa2, 0x18, 0xba, 0xbd, 0x9b, 0x48,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0x6a, 0x90, 0xb7, 0x1c, 0x93, 0x4e, 0x4a, 0x8b,
+ 0xda, 0xe8, 0x13, 0x6e, 0x01, 0x91, 0x74, 0xb1,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0x41, 0xbf, 0x60, 0x64, 0x1d, 0xfc, 0xe2, 0xee,
+ 0x00, 0xa3, 0x2a, 0xb1, 0xf8, 0x34, 0x6b, 0xeb,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0xeb, 0x9c, 0xaf, 0x20, 0x14, 0x0f, 0xf2, 0x3e,
+ 0xee, 0x45, 0xca, 0xe8, 0xdc, 0x17, 0xab, 0x22,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x75, 0x8f, 0x97, 0xbb, 0x87, 0xa8, 0x70, 0xda,
+ 0x94, 0x5a, 0xd6, 0x09, 0x78, 0xe3, 0xdd, 0x43,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x8c, 0x2d, 0xa7, 0x44, 0xd9, 0x15, 0xa8, 0x9e,
+ 0xdf, 0x3a, 0x59, 0xa5, 0xee, 0x92, 0x24, 0x3c,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0xb9, 0xe0, 0xf3, 0xf6, 0x6f, 0xbd, 0xa0, 0x7a,
+ 0x82, 0x20, 0x61, 0xbe, 0xf3, 0xe6, 0x4e, 0xac,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0xdd, 0x9b, 0xd3, 0x10, 0xed, 0x12, 0xe8, 0xb5,
+ 0xa2, 0x59, 0xe1, 0xdc, 0x5c, 0xd8, 0x6e, 0x96,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0x9d, 0xc7, 0x97, 0x67, 0x8d, 0xd0, 0xd6, 0x1a,
+ 0x4d, 0x52, 0xc0, 0x8d, 0x87, 0xa9, 0x75, 0xf5,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0xd4, 0x5d, 0x61, 0x76, 0x38, 0xe3, 0x81, 0x85,
+ 0x18, 0x5f, 0xac, 0xde, 0x49, 0x57, 0xf6, 0x9b,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0xfe, 0x83, 0xe9, 0xc6, 0xe9, 0xa4, 0x83, 0x0d,
+ 0xaf, 0x27, 0x6f, 0x79, 0x7a, 0x2b, 0x2d, 0x1f,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0xf2, 0x0c, 0x9e, 0x75, 0x5b, 0xb1, 0x8c, 0xf1,
+ 0x46, 0x4f, 0x68, 0xe8, 0x0a, 0x65, 0xd5, 0x81,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0x15, 0x2b, 0x2e, 0x14, 0xf7, 0x31, 0xa2, 0xff,
+ 0x93, 0xa7, 0x28, 0x65, 0xb1, 0x68, 0x96, 0xc6,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0x6f, 0x01, 0x22, 0x14, 0x78, 0xfb, 0x93, 0xf4,
+ 0xfa, 0xf1, 0x6d, 0x33, 0x49, 0x0e, 0x7d, 0x56,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0x05, 0xe5, 0xed, 0x99, 0x63, 0x05, 0x29, 0xb1,
+ 0xbd, 0xf7, 0x2b, 0xa6, 0x94, 0xfe, 0x45, 0xb2,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0x51, 0xf1, 0x2a, 0xa6, 0x7b, 0xe0, 0xb3, 0x20,
+ 0x7d, 0x7e, 0xd3, 0x47, 0xfb, 0x83, 0xe1, 0xc6,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0x9e, 0x7a, 0x3d, 0x12, 0x3b, 0x30, 0x81, 0x23,
+ 0x1c, 0x94, 0x42, 0x73, 0x41, 0x68, 0xc6, 0x17,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0x55, 0x31, 0x41, 0xe8, 0x1f, 0x11, 0xa6, 0x06,
+ 0x7a, 0x7c, 0x84, 0x10, 0xad, 0xd3, 0x73, 0xcf,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0xcb, 0x92, 0x18, 0xf6, 0x59, 0x6a, 0x1b, 0x18,
+ 0x63, 0x72, 0x54, 0xc2, 0x1a, 0x3d, 0x09, 0x67,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0xae, 0xf2, 0x96, 0xfd, 0xff, 0xd7, 0x18, 0xac,
+ 0x5d, 0xb2, 0x9d, 0x89, 0x56, 0x2a, 0x19, 0xae,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0x06, 0x8d, 0x5d, 0x19, 0xb3, 0x27, 0xc9, 0x6a,
+ 0xe8, 0x58, 0xe7, 0x17, 0x10, 0x6a, 0xf9, 0xf7,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0xf0, 0xbc, 0x2a, 0x03, 0x1f, 0x9b, 0x7b, 0x58,
+ 0x43, 0x0f, 0xf5, 0x17, 0xc4, 0xbd, 0xec, 0x23,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0xbe, 0x78, 0xcd, 0x84, 0x91, 0x4a, 0x1b, 0xdd,
+ 0x6a, 0x0d, 0x88, 0x72, 0x9e, 0xc2, 0x4f, 0x5a,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0xff, 0xac, 0xfe, 0x71, 0x2f, 0x6a, 0x13, 0xdc,
+ 0xd3, 0x02, 0x81, 0x88, 0xbf, 0xc9, 0x9c, 0xd6,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0xb0, 0x8d, 0x47, 0x23, 0x7e, 0xdb, 0xf5, 0x64,
+ 0x5e, 0x83, 0x52, 0x9f, 0x06, 0x65, 0x84, 0x10,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0x4d, 0x3f, 0xd4, 0x5a, 0x45, 0x57, 0xe9, 0xd7,
+ 0x1e, 0x65, 0x7a, 0xa0, 0xd8, 0x5a, 0xa8, 0x29,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0xb0, 0xcd, 0xfa, 0x39, 0x0d, 0x2e, 0x07, 0xfe,
+ 0x36, 0x47, 0x8d, 0x8e, 0x1a, 0x47, 0x67, 0xf2,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0xb4, 0xf5, 0x12, 0x64, 0xf4, 0xf6, 0xd7, 0x6e,
+ 0xeb, 0x1e, 0x9a, 0x3f, 0x18, 0xba, 0xfb, 0x99,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0xc9, 0x76, 0xb3, 0x3f, 0x80, 0xd9, 0x0c, 0xfb,
+ 0xe3, 0x90, 0x1b, 0x7a, 0xbc, 0xe1, 0x7c, 0xde,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0x21, 0x6a, 0x45, 0x6e, 0x6a, 0xac, 0xba, 0x9e,
+ 0x66, 0x39, 0x5b, 0xb6, 0x74, 0xfe, 0x2b, 0x28,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0xc0, 0xd4, 0xdf, 0x7b, 0x0f, 0x2f, 0xaa, 0x68,
+ 0x4e, 0x3d, 0xa4, 0x59, 0x6f, 0x24, 0xe6, 0x7e,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0xdf, 0x89, 0x49, 0xe7, 0x9f, 0x60, 0xdd, 0xf6,
+ 0x44, 0x97, 0xe3, 0x15, 0x52, 0x65, 0x67, 0x3e,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0xb0, 0x3f, 0x34, 0xce, 0x7d, 0x2e, 0xf1, 0xab,
+ 0x23, 0xd5, 0x89, 0xf5, 0xaa, 0xa8, 0x59, 0x9f,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0xb1, 0x33, 0x6a, 0x64, 0xd8, 0xeb, 0x8b, 0xa0,
+ 0xf4, 0x1a, 0x15, 0x28, 0xb9, 0xe4, 0xa1, 0x31,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0xd2, 0x88, 0x24, 0xfe, 0x95, 0x11, 0xc5, 0x0a,
+ 0x21, 0xfb, 0x96, 0xea, 0x61, 0xb9, 0x8b, 0x26,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0x8f, 0x22, 0x66, 0x8e, 0x7e, 0x62, 0x34, 0x37,
+ 0xfc, 0x4a, 0x48, 0x1f, 0xf7, 0x38, 0x3b, 0x4e,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0xc4, 0x50, 0xc8, 0x53, 0x58, 0xfb, 0xea, 0x9a,
+ 0xdc, 0x35, 0xc7, 0xf3, 0x5b, 0x7c, 0xfb, 0xe4,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0x27, 0xd9, 0x32, 0xd6, 0x43, 0xbf, 0x57, 0x3f,
+ 0x35, 0x73, 0x3c, 0x3e, 0xbe, 0x53, 0x19, 0xff,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x99, 0xa1, 0x7a, 0x5f, 0xe0, 0x48, 0x1c, 0x6c,
+ 0x84, 0xac, 0xab, 0xed, 0x69, 0x55, 0x1e, 0x66,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0x37, 0x50, 0x90, 0x35, 0xef, 0x84, 0x06, 0x18,
+ 0xfd, 0x3b, 0xc1, 0x8a, 0x46, 0x91, 0xb8, 0x21,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x2f, 0xcb, 0x3e, 0xc3, 0xce, 0x82, 0x0b, 0x5c,
+ 0xdc, 0x9c, 0xbd, 0x44, 0xf9, 0x04, 0x22, 0x8c,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0xab, 0xf2, 0x2e, 0x40, 0xd0, 0x74, 0x4f, 0xd4,
+ 0x26, 0x9c, 0x89, 0x9e, 0x38, 0x77, 0xac, 0x9d,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0xbc, 0xda, 0x58, 0xa2, 0x98, 0x88, 0xfe, 0x9f,
+ 0x95, 0x0e, 0x3a, 0x91, 0xba, 0xe9, 0xbf, 0x02,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0x04, 0xb9, 0x4c, 0x26, 0xce, 0x87, 0x8f, 0x17,
+ 0xdc, 0xbc, 0x36, 0x94, 0x47, 0x67, 0x9f, 0xde,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0xbd, 0xb6, 0x54, 0xc8, 0x1f, 0x51, 0x23, 0x98,
+ 0x48, 0x3d, 0x47, 0x9d, 0xa3, 0xb8, 0xe7, 0x55,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0x06, 0xc2, 0x7b, 0x80, 0x76, 0x9c, 0x37, 0x78,
+ 0x46, 0xc5, 0x45, 0x43, 0x5d, 0x8d, 0x5b, 0x3e,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0xef, 0x9e, 0x8a, 0x3a, 0xb7, 0xde, 0xa8, 0x07,
+ 0x58, 0x73, 0xe0, 0x07, 0xfc, 0x62, 0xdb, 0x62,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0xfa, 0xd5, 0xb2, 0x4e, 0x20, 0x01, 0x93, 0xc0,
+ 0xb3, 0x76, 0xa5, 0x7a, 0x92, 0x8f, 0xb9, 0x6d,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x76, 0x2e, 0xc6, 0x64, 0x6c, 0x13, 0x01, 0x7e,
+ 0x34, 0x78, 0x12, 0xb8, 0x1a, 0xb7, 0xf7, 0x39,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0xbd, 0xae, 0x10, 0x32, 0xdb, 0x63, 0x30, 0x6f,
+ 0x68, 0x19, 0x49, 0x5e, 0x34, 0x4f, 0x13, 0xc6,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0x95, 0x2e, 0xe4, 0xe3, 0xb2, 0xdc, 0x79, 0xad,
+ 0x5f, 0x0c, 0x19, 0x9c, 0x47, 0x9c, 0x79, 0x17,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0x9e, 0x3d, 0x7f, 0xcd, 0x18, 0x40, 0xd7, 0xac,
+ 0xa1, 0x45, 0x5f, 0xcb, 0x29, 0x57, 0x2b, 0x63,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0x10, 0x18, 0x9d, 0xf2, 0xed, 0x76, 0x5c, 0x5f,
+ 0x32, 0xa6, 0x29, 0x61, 0x12, 0xb2, 0xb8, 0xa2,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0x3c, 0xd4, 0xbd, 0xe9, 0xd3, 0x29, 0xac, 0xf7,
+ 0xfc, 0x04, 0xd3, 0xe4, 0x46, 0x14, 0x28, 0x2c,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x6d, 0xe8, 0x77, 0xc3, 0xab, 0x49, 0x6b, 0x79,
+ 0x4f, 0x0f, 0x4c, 0x65, 0xc5, 0x77, 0x68, 0xd9,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0xd0, 0x59, 0xf3, 0x53, 0xb1, 0x14, 0x81, 0x88,
+ 0x26, 0x88, 0xef, 0x4b, 0xa4, 0x7d, 0x0a, 0x84,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0xa3, 0x96, 0x9f, 0x96, 0x53, 0x0e, 0x38, 0x78,
+ 0x9e, 0xbd, 0xf7, 0x65, 0x23, 0x73, 0x99, 0xa7,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0x6b, 0x25, 0x8d, 0x51, 0xd8, 0xc4, 0xd9, 0xbf,
+ 0xa6, 0x4f, 0xa3, 0x25, 0x28, 0xb5, 0x7c, 0x05,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0xa5, 0xac, 0xd9, 0xb6, 0x9e, 0x98, 0x75, 0xae,
+ 0x9b, 0x16, 0xe1, 0x60, 0xc6, 0xa5, 0x07, 0xf2,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0x65, 0x53, 0x56, 0xe6, 0x2c, 0x22, 0x68, 0xc9,
+ 0xb8, 0xbe, 0xb1, 0x40, 0x08, 0xe2, 0xb6, 0xb9,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0x67, 0xcd, 0x0e, 0x4f, 0xfc, 0x38, 0x7f, 0x8a,
+ 0x3b, 0xea, 0xff, 0x86, 0xf3, 0x8a, 0x92, 0xcb,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0x22, 0x95, 0x1f, 0x20, 0xc9, 0x5c, 0x73, 0x39,
+ 0xa4, 0xd9, 0xc1, 0x37, 0x9d, 0x94, 0xb2, 0xfd,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0xe1, 0x80, 0x82, 0xdd, 0x21, 0x6c, 0xe4, 0x93,
+ 0xa3, 0x41, 0x0f, 0xfc, 0x96, 0x42, 0x8b, 0xde,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0x11, 0x1c, 0xd7, 0x7a, 0xe7, 0x1a, 0x88, 0xdd,
+ 0x2a, 0xdf, 0xe5, 0x30, 0xca, 0x0b, 0x9f, 0xb6,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0x45, 0x9b, 0x36, 0x3d, 0xf8, 0xc0, 0x43, 0x6d,
+ 0x94, 0xcf, 0xbd, 0x5f, 0xfe, 0xec, 0xd7, 0x4b,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0xf0, 0xaa, 0xfd, 0xae, 0xb7, 0x73, 0x3c, 0x9d,
+ 0x93, 0xd4, 0x00, 0xea, 0x81, 0x31, 0xde, 0x41,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0x1a, 0xaa, 0xff, 0x2a, 0xdc, 0xcc, 0x89, 0xbc,
+ 0xcf, 0x48, 0x5c, 0x1e, 0x4d, 0x69, 0x85, 0x39,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0xe7, 0xd0, 0xcb, 0x9a, 0xb5, 0x76, 0xec, 0xfc,
+ 0x48, 0xa3, 0x41, 0x48, 0x4c, 0xa7, 0xec, 0xb7,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xe3, 0x4e, 0x42, 0xb5, 0xe3, 0x63, 0x4b, 0x7c,
+ 0xf0, 0x9f, 0xef, 0x6e, 0x97, 0xe2, 0x86, 0xc0,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0xea, 0x8a, 0xab, 0x7f, 0x15, 0x21, 0x5a, 0x36,
+ 0x9b, 0x56, 0xee, 0x51, 0x61, 0x97, 0xe2, 0x0a,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x85, 0x54, 0x52, 0xe3, 0xb4, 0xe8, 0x26, 0xa4,
+ 0x38, 0xb0, 0x4c, 0xa0, 0x41, 0xf5, 0x30, 0x6e,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x6f, 0x93, 0xb8, 0x9c, 0x26, 0x88, 0xb4, 0x20,
+ 0x87, 0x95, 0xf2, 0xf4, 0x3a, 0xbe, 0x92, 0xb7,
+ },
+ },
+ .ltk = {
+ 0x30, 0xf6, 0xd3, 0x2e, 0x1c, 0x81, 0x2c, 0x96,
+ 0x56, 0x30, 0x55, 0xec, 0x9b, 0x72, 0xf4, 0x83,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_INPUT,
+ .passkey = 879894,
+ },
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 2
+ * Responder IO capabilities: 0
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 5
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_pk_iio2_rio0_b1_iat0_rat0_ik5_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x0d,
+ .resp_key_dist = 0x0f,
+ },
+ .pair_rsp = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x05,
+ .resp_key_dist = 0x07,
+ },
+ .our_priv_key = {
+ 0xd6, 0x2f, 0x4f, 0x6b, 0xeb, 0xfc, 0xbd, 0xee,
+ 0x9b, 0x94, 0xd7, 0x15, 0x98, 0xc6, 0x0c, 0x83,
+ 0x9b, 0xc7, 0xa2, 0x45, 0xfd, 0x00, 0xe8, 0xa4,
+ 0x52, 0xe9, 0x70, 0x2f, 0xd7, 0x62, 0xf1, 0xa4,
+ },
+ .public_key_req = {
+ .x = {
+ 0xd6, 0xa7, 0xaf, 0xc1, 0x18, 0x8b, 0x92, 0x2f,
+ 0xbc, 0xbc, 0x4d, 0xb8, 0x5c, 0xfb, 0x39, 0x7c,
+ 0x1e, 0x90, 0x7e, 0xfa, 0xa2, 0x0d, 0xee, 0x9e,
+ 0xb4, 0x9e, 0xbe, 0x50, 0xf0, 0xbc, 0x2c, 0x10,
+ },
+ .y = {
+ 0xa4, 0x25, 0xad, 0x75, 0xbe, 0xab, 0x1e, 0xcf,
+ 0x4e, 0xc8, 0x19, 0xab, 0x6c, 0x68, 0x38, 0xa4,
+ 0xe7, 0x43, 0x7b, 0x19, 0xef, 0x28, 0xd5, 0x93,
+ 0x52, 0xe9, 0xb9, 0x31, 0x68, 0x60, 0x19, 0x71,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0xbc, 0x6a, 0xcf, 0xc6, 0x8a, 0x3a, 0xdc, 0x89,
+ 0xdd, 0xa9, 0xaf, 0x29, 0xc7, 0xaf, 0xe2, 0x8b,
+ 0x25, 0xee, 0xce, 0xa6, 0x10, 0x1d, 0x33, 0x2f,
+ 0xd5, 0xfc, 0x30, 0xb8, 0xb1, 0x7b, 0xb1, 0x6e,
+ },
+ .y = {
+ 0x1a, 0xc6, 0x42, 0x36, 0x98, 0x40, 0x4f, 0x90,
+ 0x82, 0xa0, 0x10, 0x3a, 0xa5, 0x0f, 0xcf, 0x57,
+ 0xd2, 0x2e, 0x80, 0x9d, 0x61, 0xc7, 0x21, 0xac,
+ 0x47, 0x5b, 0x93, 0x75, 0x02, 0x30, 0x40, 0x14,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0xd1, 0x64, 0x49, 0xa0, 0xc4, 0x28, 0x81, 0x57,
+ 0x0c, 0x25, 0x62, 0xfb, 0x2c, 0xa2, 0xb0, 0xc7,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0xea, 0xae, 0x4e, 0x03, 0x00, 0xf9, 0xd1, 0x65,
+ 0xc7, 0x6a, 0x0d, 0x74, 0x4f, 0x02, 0x0b, 0x94,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x05, 0xb2, 0x09, 0x9b, 0x36, 0x23, 0x4f, 0x74,
+ 0x4e, 0xc9, 0x7a, 0x2c, 0x65, 0x3a, 0xd1, 0xf6,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x50, 0xd8, 0x88, 0xd4, 0x7e, 0xc1, 0x36, 0x92,
+ 0x0f, 0xa7, 0x17, 0x3c, 0xb4, 0xeb, 0xee, 0xa6,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0xab, 0xa2, 0xd0, 0xec, 0xdd, 0xf3, 0xd2, 0xa9,
+ 0x2d, 0xde, 0x4b, 0x02, 0x66, 0x45, 0x2f, 0xc0,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0xa9, 0xc1, 0x9d, 0x75, 0xd0, 0xb6, 0xec, 0x06,
+ 0x31, 0x87, 0xb6, 0x9d, 0x31, 0xdc, 0x92, 0x7c,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0xb9, 0x5b, 0xe0, 0x0f, 0x83, 0xe7, 0x2d, 0x77,
+ 0x2f, 0x55, 0x0a, 0x2c, 0xd9, 0xc1, 0x46, 0xcd,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0xa2, 0x9a, 0x5b, 0x99, 0xb1, 0xc0, 0xc5, 0xd6,
+ 0xf1, 0x87, 0x0b, 0x49, 0x9c, 0xfd, 0xfe, 0xd5,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0x3a, 0x9d, 0x58, 0xe5, 0xb0, 0x31, 0xd9, 0xde,
+ 0xac, 0xd2, 0x44, 0xb7, 0xe1, 0xe5, 0x89, 0x50,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0xae, 0x4e, 0x4f, 0x84, 0x5f, 0x4c, 0xd1, 0x9b,
+ 0x81, 0x22, 0x9c, 0x68, 0x52, 0xe0, 0x9a, 0xfc,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0xa5, 0xbb, 0x5f, 0x9a, 0xa2, 0x97, 0xdb, 0xcd,
+ 0x3d, 0xfe, 0xd9, 0x58, 0x21, 0x52, 0x99, 0xb7,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0xea, 0x44, 0xdd, 0x0c, 0xbf, 0xb5, 0x6b, 0xc7,
+ 0xe1, 0x19, 0xe8, 0x0b, 0xc2, 0x15, 0x04, 0x37,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0xa8, 0xa3, 0xdb, 0x08, 0xca, 0x31, 0xd5, 0xef,
+ 0x17, 0x37, 0x77, 0xd0, 0x64, 0x2e, 0x2f, 0x2f,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0xe4, 0xf6, 0xa5, 0x94, 0x1a, 0x09, 0x4b, 0x75,
+ 0x79, 0xb8, 0x0c, 0xe6, 0xe2, 0x28, 0x5a, 0x2c,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0x1a, 0x3f, 0x80, 0x6f, 0xd3, 0xe8, 0xc5, 0xfb,
+ 0x9b, 0xda, 0xa1, 0x07, 0x68, 0x1a, 0x54, 0xbc,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0x1b, 0x48, 0x22, 0x87, 0x04, 0x24, 0x87, 0xba,
+ 0x14, 0xb9, 0x85, 0xb2, 0xa6, 0xf5, 0xea, 0x89,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x31, 0xcb, 0xc4, 0x0c, 0x36, 0xb5, 0xe2, 0x32,
+ 0xd8, 0x0e, 0xd3, 0x86, 0x96, 0xe3, 0x8c, 0x84,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x90, 0x11, 0x30, 0x35, 0x5f, 0xe5, 0x45, 0xff,
+ 0xab, 0xd3, 0xe0, 0xbe, 0x1c, 0x20, 0x23, 0xb8,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0xa0, 0xc7, 0x79, 0x28, 0x87, 0x19, 0xa3, 0x78,
+ 0x33, 0xe5, 0x1a, 0x81, 0xba, 0x9b, 0xe3, 0x5c,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0x43, 0xcf, 0x20, 0x1b, 0x39, 0x3f, 0xdf, 0x73,
+ 0x58, 0xd2, 0x0d, 0xc7, 0x41, 0xd7, 0x58, 0xea,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0x59, 0xda, 0x78, 0xeb, 0xd5, 0xcd, 0x8e, 0x23,
+ 0xe5, 0x5e, 0xa7, 0xa5, 0xba, 0x13, 0x00, 0xff,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0x31, 0x7a, 0xf0, 0x56, 0x82, 0x69, 0xdb, 0xcd,
+ 0x27, 0x5a, 0x11, 0xd3, 0x65, 0x82, 0x0d, 0xda,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0x2e, 0xe8, 0x76, 0x40, 0x9c, 0x49, 0x07, 0x42,
+ 0x1e, 0x45, 0x7b, 0x1e, 0x73, 0xa3, 0x71, 0x05,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0x64, 0x99, 0x42, 0x5d, 0x05, 0xd6, 0x12, 0x41,
+ 0x2a, 0x44, 0x55, 0x26, 0xe7, 0x08, 0x5e, 0xfb,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0x1c, 0x55, 0xe1, 0x75, 0x4f, 0x6e, 0xdd, 0x7e,
+ 0xc8, 0xff, 0x76, 0x25, 0xdb, 0x2a, 0x6d, 0xe3,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0xf6, 0x36, 0x78, 0x88, 0x62, 0xa8, 0x78, 0xe6,
+ 0xf9, 0xa1, 0x17, 0x63, 0x86, 0xd3, 0xae, 0x60,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0x96, 0x9a, 0x1c, 0xbe, 0x82, 0x82, 0xc2, 0xa7,
+ 0x18, 0xc3, 0x7b, 0x40, 0x5d, 0x6c, 0x4e, 0xe3,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0x2b, 0x7d, 0x36, 0xc3, 0xf7, 0x59, 0x63, 0x40,
+ 0x6f, 0xc0, 0x2a, 0x2b, 0x1b, 0xd7, 0x41, 0x38,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0x88, 0x99, 0x53, 0xae, 0x2a, 0xaf, 0x97, 0x5a,
+ 0xcc, 0x9f, 0xfd, 0xe2, 0x1d, 0xd3, 0x27, 0x66,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0xdb, 0xae, 0xfb, 0xf7, 0x33, 0xd4, 0xd1, 0xcb,
+ 0xfe, 0x75, 0x8e, 0x81, 0x16, 0xd1, 0x49, 0xeb,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0x13, 0x5c, 0x00, 0x34, 0xe5, 0x96, 0xd0, 0x97,
+ 0xb1, 0x84, 0x3d, 0x00, 0xb4, 0x2a, 0x4a, 0x12,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0xed, 0x94, 0x1f, 0x41, 0x12, 0xe5, 0x35, 0x5b,
+ 0xa6, 0x6a, 0x72, 0x1e, 0xa2, 0x7c, 0xe1, 0x6c,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0xa3, 0xc7, 0x17, 0xad, 0xb6, 0xe6, 0xaa, 0x16,
+ 0x8d, 0x4b, 0x70, 0x5f, 0x49, 0x73, 0xa7, 0x19,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0x10, 0xb0, 0x31, 0xa7, 0x16, 0x61, 0xf7, 0xd6,
+ 0xe6, 0x16, 0x9e, 0xb1, 0x9e, 0xb5, 0x5e, 0x94,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0x6f, 0xe7, 0x62, 0x73, 0xfb, 0xbf, 0xf1, 0x4a,
+ 0x14, 0xa1, 0x09, 0x45, 0xd4, 0xde, 0x26, 0xad,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0x3f, 0x48, 0xa7, 0xdf, 0x4a, 0xd5, 0x55, 0x26,
+ 0xd3, 0x32, 0xbf, 0x98, 0x4a, 0x20, 0xad, 0xb0,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0x88, 0x1c, 0xef, 0xfe, 0x4e, 0x68, 0x41, 0x7c,
+ 0xe8, 0xe8, 0x81, 0x1a, 0xb9, 0x9e, 0xaf, 0xc6,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0xa3, 0x53, 0x2a, 0xe1, 0xbd, 0x9d, 0xbe, 0x89,
+ 0xf8, 0xc7, 0x70, 0x6e, 0xa9, 0x12, 0x07, 0x0d,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0x52, 0x06, 0x56, 0x09, 0xf4, 0xb2, 0xb9, 0x63,
+ 0x3f, 0x2e, 0x59, 0x6c, 0x6b, 0x43, 0xb6, 0xc0,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0x36, 0xb0, 0x33, 0x84, 0x52, 0xd1, 0x60, 0xac,
+ 0x37, 0x81, 0x6b, 0x18, 0x5f, 0xfc, 0x61, 0xb1,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0xc8, 0x55, 0xb7, 0x9e, 0x3e, 0xf0, 0x26, 0xa4,
+ 0x55, 0xb3, 0x1d, 0x4d, 0xa1, 0x5d, 0xa9, 0xaf,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0xb7, 0xb9, 0x6b, 0x8e, 0xef, 0xd3, 0xbc, 0x58,
+ 0x10, 0xbe, 0x5a, 0x9a, 0x4d, 0xbc, 0xec, 0xe3,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0x55, 0xa1, 0xf4, 0xd7, 0xfa, 0xe1, 0x84, 0x03,
+ 0xed, 0xb6, 0x95, 0x63, 0x4b, 0x93, 0x93, 0xc2,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0x72, 0xa9, 0xe5, 0xf7, 0x48, 0x1f, 0x64, 0x71,
+ 0xd9, 0x81, 0xf0, 0xc5, 0x4d, 0x38, 0xac, 0x9a,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0x12, 0x37, 0x56, 0xa6, 0x66, 0xa1, 0x23, 0xee,
+ 0xe3, 0x1e, 0x20, 0x66, 0x66, 0x85, 0x7c, 0xa8,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0x74, 0xaa, 0xbb, 0x5a, 0xdf, 0xd9, 0xc4, 0xaf,
+ 0xe4, 0xa7, 0xe6, 0x4b, 0x45, 0x97, 0xf8, 0x7d,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0x29, 0xce, 0xcc, 0xb7, 0xb2, 0x1e, 0x0e, 0xa8,
+ 0x48, 0x90, 0x43, 0x6d, 0x34, 0xa4, 0xa3, 0x12,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0x2e, 0xaf, 0x4c, 0x63, 0x84, 0x2c, 0x62, 0x67,
+ 0x68, 0x8f, 0x0b, 0xfd, 0xff, 0xef, 0x15, 0x26,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0xec, 0xcf, 0x6a, 0x60, 0x77, 0x04, 0x2c, 0x62,
+ 0x42, 0xf0, 0x21, 0xfd, 0x53, 0xd6, 0x8a, 0xe8,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0x2c, 0x13, 0x65, 0x69, 0xd7, 0x66, 0x04, 0x13,
+ 0x3c, 0xa8, 0xfb, 0xe5, 0x76, 0xbb, 0x4f, 0x48,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x0d, 0x93, 0x30, 0xe2, 0x76, 0xf1, 0xbc, 0x24,
+ 0x61, 0x0d, 0xcd, 0xef, 0x33, 0x98, 0xe2, 0x3b,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0xb6, 0x32, 0x69, 0x81, 0xc0, 0x81, 0x46, 0xae,
+ 0x8d, 0x5a, 0x17, 0xb5, 0xc0, 0x0f, 0x9f, 0x4e,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x89, 0x96, 0x22, 0x0c, 0x76, 0xdf, 0x27, 0x13,
+ 0x96, 0x5a, 0x0c, 0x88, 0x65, 0x18, 0x74, 0x52,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0x1c, 0x77, 0x25, 0x22, 0xc0, 0x28, 0x88, 0x45,
+ 0x29, 0x62, 0x7a, 0x8e, 0xc0, 0x2a, 0x5c, 0xd8,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0xcc, 0x84, 0xb6, 0x98, 0x3e, 0xf9, 0x09, 0xd2,
+ 0x71, 0x47, 0x56, 0xb1, 0x09, 0xf5, 0xd2, 0x0b,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0xf0, 0xcf, 0x1c, 0xa6, 0x24, 0xcd, 0xfa, 0x42,
+ 0xa4, 0x93, 0x8b, 0xa0, 0xe3, 0x42, 0x72, 0x51,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0xab, 0xb0, 0xa3, 0x80, 0x0d, 0xcb, 0x8e, 0xf6,
+ 0x6c, 0x07, 0x50, 0xe9, 0x8a, 0x85, 0x02, 0xae,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0xf6, 0x52, 0xd8, 0x34, 0x15, 0x62, 0x9f, 0x6e,
+ 0x2b, 0x52, 0xdc, 0x1c, 0x70, 0x17, 0x0a, 0x31,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0x8d, 0xc9, 0x0a, 0x45, 0xe9, 0x81, 0x0d, 0x5e,
+ 0xbb, 0xd8, 0x94, 0x29, 0x68, 0x42, 0x44, 0xe2,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0x96, 0x2a, 0x35, 0x39, 0x09, 0xf7, 0x66, 0x5a,
+ 0xb6, 0x33, 0x77, 0x6d, 0xba, 0xd3, 0x8a, 0xfb,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x53, 0x08, 0x9b, 0x37, 0xc3, 0x79, 0xe6, 0x8c,
+ 0x42, 0x30, 0x94, 0x73, 0x6f, 0x39, 0x64, 0x20,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0x4d, 0xb7, 0xe9, 0x50, 0x8e, 0x0f, 0xe0, 0xd5,
+ 0x3e, 0xf6, 0x32, 0xdd, 0xb8, 0x18, 0x77, 0xd3,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0x8d, 0x49, 0x14, 0xdd, 0x95, 0x57, 0x55, 0x14,
+ 0x48, 0x97, 0xd3, 0x73, 0x29, 0xa0, 0xb9, 0x2b,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0xcf, 0x38, 0x8b, 0xab, 0xe4, 0x2b, 0x3f, 0x13,
+ 0xc3, 0xfb, 0x07, 0xee, 0x0e, 0x33, 0x2f, 0x04,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0xc6, 0x58, 0x13, 0x19, 0x56, 0x06, 0x52, 0x4b,
+ 0x3d, 0x5e, 0x9d, 0xa8, 0x48, 0xf2, 0x40, 0xf3,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0xbb, 0x93, 0xd2, 0xed, 0x89, 0x66, 0xa5, 0x1c,
+ 0xc9, 0x2a, 0x42, 0x2c, 0xff, 0x4a, 0x80, 0x84,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x3d, 0x9c, 0x11, 0x2a, 0xd3, 0xce, 0x4b, 0x20,
+ 0xf2, 0xfb, 0xdd, 0x18, 0x4d, 0x7c, 0x58, 0xb6,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0xda, 0x80, 0x63, 0x9d, 0xa2, 0x73, 0x61, 0xdd,
+ 0x9a, 0x45, 0x91, 0x4d, 0x78, 0x39, 0x54, 0x75,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0x2e, 0xe4, 0x44, 0xe8, 0xdb, 0xc2, 0xbd, 0x62,
+ 0xd1, 0xc4, 0x23, 0x4e, 0x5f, 0x65, 0xb6, 0x3b,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0x19, 0x91, 0xa3, 0xc7, 0x3b, 0x68, 0x12, 0x24,
+ 0xcd, 0xd6, 0x02, 0xf5, 0xcd, 0x19, 0x6c, 0x88,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0xf0, 0x28, 0x18, 0xe8, 0xa7, 0x3e, 0xd8, 0x21,
+ 0x42, 0x58, 0xb3, 0x72, 0xa0, 0x34, 0x89, 0x04,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0xe9, 0xff, 0x0b, 0x9a, 0xfd, 0x29, 0x95, 0x37,
+ 0x89, 0x2c, 0x84, 0xfa, 0x02, 0xa0, 0xb6, 0xeb,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0x4f, 0x90, 0x70, 0xbe, 0xc4, 0x81, 0x9f, 0xc1,
+ 0x74, 0xa3, 0x01, 0x2e, 0x78, 0x7a, 0xe2, 0x61,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0xbb, 0xd5, 0x91, 0xec, 0x81, 0xe0, 0x9b, 0x5e,
+ 0xe9, 0xd2, 0x93, 0x57, 0xa8, 0x27, 0xdd, 0x9b,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0x78, 0xa4, 0x35, 0x1a, 0xbc, 0xa7, 0x19, 0x8c,
+ 0x96, 0x8f, 0x63, 0x9d, 0x11, 0xee, 0x27, 0x44,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0x39, 0x5b, 0x71, 0xfd, 0x7e, 0x39, 0x6b, 0xbe,
+ 0xaf, 0xe1, 0x55, 0x90, 0xa6, 0x58, 0xec, 0xc5,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0x91, 0x43, 0xe5, 0xc8, 0x26, 0x0c, 0x8c, 0x6c,
+ 0xf3, 0xd1, 0x30, 0xb3, 0x22, 0x94, 0x4c, 0x67,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0x51, 0xc4, 0x3e, 0x09, 0xca, 0x03, 0xbe, 0x2c,
+ 0xe8, 0x1a, 0x5d, 0x07, 0x12, 0x14, 0x2d, 0x43,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0x2f, 0xa1, 0x20, 0xde, 0xf5, 0xb4, 0xa6, 0x92,
+ 0x31, 0xe9, 0x86, 0x63, 0xef, 0xc1, 0x85, 0x3b,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0x41, 0xd0, 0xd0, 0x96, 0x93, 0xd1, 0xcb, 0xed,
+ 0xab, 0x27, 0xd5, 0x88, 0x5e, 0xe6, 0x5e, 0x5c,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xec, 0xc5, 0x5f, 0xf3, 0xae, 0xfe, 0x79, 0x65,
+ 0x17, 0x5a, 0x60, 0xf7, 0x36, 0x4f, 0x90, 0x45,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0xa7, 0x45, 0x7a, 0x54, 0x1b, 0x64, 0x08, 0x60,
+ 0x51, 0x7d, 0x74, 0x27, 0x48, 0xa2, 0xf1, 0x0f,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x36, 0x9a, 0xd9, 0x25, 0x5c, 0xdb, 0x78, 0xdc,
+ 0x1d, 0x2c, 0x83, 0xf7, 0xde, 0x99, 0xa0, 0x66,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x61, 0x6e, 0x9a, 0x26, 0xc5, 0xd0, 0x85, 0xdc,
+ 0xea, 0x9d, 0xca, 0x3b, 0x17, 0xd7, 0x43, 0x80,
+ },
+ },
+ .ltk = {
+ 0xd6, 0x02, 0xba, 0x3d, 0xa2, 0xce, 0x93, 0x1a,
+ 0xfd, 0xd6, 0xb5, 0x54, 0x90, 0xc4, 0x2a, 0x8f,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_DISP,
+ .passkey = 222333,
+ },
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: numeric comparison
+ * Initiator IO capabilities: 1
+ * Responder IO capabilities: 1
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 5
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_nc_iio1_rio1_b1_iat0_rat0_ik5_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .resp_id_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ .pair_req = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x0d,
+ .resp_key_dist = 0x0f,
+ },
+ .pair_rsp = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x05,
+ .resp_key_dist = 0x07,
+ },
+ .our_priv_key = {
+ 0xd6, 0x2f, 0x4f, 0x6b, 0xeb, 0xfc, 0xbd, 0xee,
+ 0x9b, 0x94, 0xd7, 0x15, 0x98, 0xc6, 0x0c, 0x83,
+ 0x9b, 0xc7, 0xa2, 0x45, 0xfd, 0x00, 0xe8, 0xa4,
+ 0x52, 0xe9, 0x70, 0x2f, 0xd7, 0x62, 0xf1, 0xa4,
+ },
+ .public_key_req = {
+ .x = {
+ 0x41, 0x0d, 0x95, 0x8a, 0x68, 0xb8, 0xcf, 0x07,
+ 0x58, 0x25, 0x5f, 0x97, 0xd2, 0x99, 0x71, 0x44,
+ 0x06, 0xfc, 0x9c, 0x4d, 0xd1, 0x74, 0x80, 0xed,
+ 0x49, 0xd1, 0x36, 0x6b, 0x55, 0x8b, 0x54, 0x3b,
+ },
+ .y = {
+ 0x0f, 0x1a, 0x61, 0x45, 0xe5, 0x4b, 0x11, 0x13,
+ 0xb3, 0x15, 0x87, 0x09, 0xec, 0x16, 0xf8, 0x41,
+ 0x2e, 0xe2, 0x15, 0x93, 0x14, 0x56, 0x9f, 0xcd,
+ 0x60, 0x7d, 0x92, 0xec, 0xd3, 0xb5, 0x85, 0xc5,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0xbc, 0x6a, 0xcf, 0xc6, 0x8a, 0x3a, 0xdc, 0x89,
+ 0xdd, 0xa9, 0xaf, 0x29, 0xc7, 0xaf, 0xe2, 0x8b,
+ 0x25, 0xee, 0xce, 0xa6, 0x10, 0x1d, 0x33, 0x2f,
+ 0xd5, 0xfc, 0x30, 0xb8, 0xb1, 0x7b, 0xb1, 0x6e,
+ },
+ .y = {
+ 0x1a, 0xc6, 0x42, 0x36, 0x98, 0x40, 0x4f, 0x90,
+ 0x82, 0xa0, 0x10, 0x3a, 0xa5, 0x0f, 0xcf, 0x57,
+ 0xd2, 0x2e, 0x80, 0x9d, 0x61, 0xc7, 0x21, 0xac,
+ 0x47, 0x5b, 0x93, 0x75, 0x02, 0x30, 0x40, 0x14,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x73, 0xc8, 0x56, 0x5e, 0x33, 0x37, 0x26, 0xb6,
+ 0x00, 0x65, 0x9c, 0xa1, 0xee, 0xbf, 0x61, 0xf6,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x7c, 0x23, 0x03, 0x70, 0x54, 0xa2, 0x70, 0xe4,
+ 0x2d, 0xe9, 0x88, 0x6f, 0x40, 0xd6, 0x2f, 0xb2,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x2d, 0x9f, 0xe8, 0x1d, 0xf2, 0x4e, 0x2e, 0x58,
+ 0x16, 0x8c, 0x83, 0x89, 0x92, 0x70, 0xa2, 0xba,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xc0, 0x8a, 0x1c, 0xff, 0x7f, 0xd6, 0xbc, 0xee,
+ 0x19, 0xa5, 0xc6, 0x3a, 0xbd, 0x48, 0x4b, 0xc3,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x38, 0x36, 0x83, 0xd5, 0x1a, 0xfb, 0xe6, 0x3c,
+ 0x80, 0x0c, 0x81, 0x81, 0x78, 0x12, 0x41, 0x38,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x33, 0x22, 0x11, 0x00, 0x45, 0x0a,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x52, 0xf4, 0xcc, 0x2f, 0xc6, 0xc1, 0xdb, 0x07,
+ 0xa5, 0x38, 0xc1, 0x09, 0x82, 0x2e, 0xa3, 0x53,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xc1, 0xa3, 0x62, 0x6a, 0x9e, 0xaa, 0x37, 0xd9,
+ 0x65, 0x9f, 0x7f, 0x5d, 0x62, 0x0c, 0x1c, 0x6c,
+ },
+ },
+ .ltk = {
+ 0xd8, 0x7f, 0x0a, 0x94, 0x41, 0xa5, 0xfd, 0x84,
+ 0x15, 0x01, 0xb7, 0x2a, 0x7a, 0xe4, 0xfd, 0xfb,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_NUMCMP,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NUMCMP,
+ .numcmp_accept = 1,
+ },
+ .exp_numcmp = 516214,
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 4
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_sc_us_jw_iio3_rio4_b1_iat0_rat0_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ .resp_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .our_priv_key = {
+ 0xaf, 0xce, 0x12, 0x45, 0xa8, 0xe0, 0xa9, 0x45,
+ 0x8a, 0x56, 0xc5, 0xbf, 0x3b, 0xf9, 0x04, 0x69,
+ 0xf2, 0xf9, 0xe4, 0xd4, 0x7e, 0xb7, 0xc9, 0x65,
+ 0xb1, 0x68, 0x3e, 0xab, 0xcd, 0x8e, 0x6f, 0x1f,
+ },
+ .public_key_req = {
+ .x = {
+ 0x45, 0xca, 0xda, 0xe3, 0x65, 0x7c, 0xf5, 0x37,
+ 0x36, 0x66, 0x8b, 0x3b, 0x54, 0xb9, 0x2b, 0xb2,
+ 0x09, 0xd5, 0x6e, 0xe0, 0x04, 0x1d, 0xd6, 0x49,
+ 0xff, 0x55, 0x41, 0x35, 0xa0, 0x2f, 0x12, 0xee,
+ },
+ .y = {
+ 0x65, 0x41, 0xd3, 0x7b, 0x59, 0xf2, 0xaf, 0x94,
+ 0x78, 0xd8, 0x63, 0xc4, 0x9b, 0x9a, 0x9a, 0x92,
+ 0x33, 0x0f, 0x14, 0x67, 0x98, 0x51, 0x9d, 0xff,
+ 0xef, 0x59, 0xb7, 0x17, 0xc2, 0x16, 0x72, 0x18,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x9e, 0x44, 0x09, 0x57, 0xb7, 0x01, 0x78, 0x5b,
+ 0x4e, 0x50, 0x0d, 0x99, 0x0d, 0x52, 0x88, 0x24,
+ 0x19, 0xf5, 0x40, 0x53, 0x06, 0x1e, 0x68, 0xd0,
+ 0xfd, 0xd2, 0x84, 0x8b, 0xae, 0x9d, 0xf7, 0xd9,
+ },
+ .y = {
+ 0xc2, 0xe7, 0xe0, 0x01, 0xb3, 0x2a, 0x1b, 0x01,
+ 0x19, 0xd1, 0x14, 0xb5, 0xc8, 0x98, 0x02, 0x2a,
+ 0xbe, 0x6b, 0x33, 0x1a, 0x99, 0x18, 0x77, 0x23,
+ 0xd4, 0x8b, 0x8c, 0x09, 0xf5, 0x77, 0x20, 0xa0,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0xbd, 0x85, 0xbe, 0x80, 0xd9, 0x77, 0x16, 0xa3,
+ 0x65, 0x1a, 0xdf, 0xff, 0x5a, 0x6f, 0x8b, 0x37,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xb5, 0x59, 0x7c, 0x8e, 0x7b, 0x01, 0xac, 0x09,
+ 0x8f, 0xe8, 0x97, 0x98, 0x8d, 0x3f, 0xb7, 0x63,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x86, 0x1f, 0x76, 0x11, 0x2e, 0x83, 0xed, 0x99,
+ 0x9b, 0xc0, 0x9a, 0xab, 0x7f, 0x94, 0x20, 0xcb,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xe0, 0x9f, 0x87, 0x87, 0x9f, 0x82, 0xc5, 0x06,
+ 0x5f, 0x11, 0xfa, 0xa0, 0xe3, 0xbf, 0x72, 0xf2,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x26, 0xc2, 0xf1, 0xb9, 0xf1, 0xc2, 0xbd, 0xcb,
+ 0xdb, 0x94, 0x96, 0x8e, 0x08, 0xcc, 0x53, 0xd4,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x74, 0x14, 0xcd, 0x5a, 0x49, 0x2e, 0xb6, 0x0d,
+ 0xc6, 0x82, 0xb0, 0x0f, 0x9c, 0xe6, 0xe5, 0x41,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xfb, 0x93, 0xa2, 0xb7, 0x4d, 0x0e, 0xcc, 0x92,
+ 0xe4, 0xbf, 0x5b, 0x3c, 0x6d, 0x87, 0x5b, 0x2d,
+ },
+ },
+ .ltk = {
+ 0x2e, 0x6c, 0x8b, 0xdb, 0x9e, 0x19, 0x3e, 0x3d,
+ 0x4d, 0x6d, 0x29, 0xbc, 0x89, 0xca, 0x57, 0xed,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_JW,
+ .authenticated = 0,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 2
+ * Responder IO capabilities: 4
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_sc_us_pk_iio2_rio4_b1_iat0_rat0_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ .resp_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .pair_req = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .our_priv_key = {
+ 0xb1, 0x6b, 0x4f, 0x81, 0xbc, 0xe3, 0x60, 0x9e,
+ 0x00, 0x20, 0xf1, 0x73, 0x3e, 0xfb, 0xcc, 0x6e,
+ 0x8c, 0xb6, 0xd2, 0x51, 0xd9, 0x36, 0x8a, 0x6d,
+ 0xca, 0x8c, 0xd7, 0xbe, 0x96, 0x03, 0xdf, 0xd6,
+ },
+ .public_key_req = {
+ .x = {
+ 0xe5, 0x0f, 0x02, 0x0a, 0x37, 0x90, 0x94, 0x5a,
+ 0x06, 0x21, 0xf7, 0xbc, 0xd5, 0xbe, 0xb9, 0x24,
+ 0x8a, 0x35, 0xfd, 0xf8, 0x5e, 0xe2, 0x70, 0xd5,
+ 0x5a, 0xe8, 0xe7, 0xdd, 0x13, 0x90, 0xeb, 0xd4,
+ },
+ .y = {
+ 0x41, 0xc8, 0x51, 0x1a, 0x25, 0x44, 0x01, 0x53,
+ 0x42, 0x74, 0x07, 0x9c, 0x18, 0xe6, 0x3b, 0x8a,
+ 0xce, 0x7a, 0x37, 0x1f, 0x18, 0x5c, 0x02, 0x7c,
+ 0x67, 0x16, 0xf5, 0x30, 0x2b, 0x31, 0xa9, 0xc7,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1b, 0xd2, 0x03, 0x79, 0xb4, 0x9b, 0x0a, 0xd7,
+ 0x1b, 0x28, 0x73, 0x2a, 0xd7, 0xe6, 0xa0, 0xd4,
+ 0x2d, 0x95, 0x8d, 0x29, 0xaf, 0x6a, 0xab, 0xee,
+ 0xa0, 0x0d, 0x13, 0x4d, 0xe7, 0x16, 0x76, 0x91,
+ },
+ .y = {
+ 0x2a, 0x26, 0x2c, 0x50, 0x55, 0xd1, 0x2b, 0x83,
+ 0xf6, 0x5f, 0xdb, 0x99, 0x5f, 0x85, 0xf6, 0x78,
+ 0x1c, 0x14, 0xed, 0xd3, 0x70, 0x5e, 0xe5, 0x2c,
+ 0x05, 0x1e, 0x5c, 0xec, 0xf8, 0x65, 0x43, 0x49,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x55, 0x2c, 0xaa, 0x41, 0x59, 0x42, 0x4d, 0xfe,
+ 0x47, 0x74, 0xcd, 0x2b, 0x11, 0xab, 0x21, 0xe6,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x6a, 0x3c, 0x45, 0xf5, 0xb2, 0xe2, 0x04, 0x30,
+ 0xde, 0xd6, 0x3c, 0x6d, 0x85, 0x00, 0x00, 0x2c,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x78, 0x06, 0x04, 0x60, 0x76, 0xe9, 0xc4, 0x5a,
+ 0xfb, 0x34, 0x44, 0xae, 0x45, 0xa0, 0x84, 0xde,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x91, 0xc8, 0xfd, 0x1b, 0xb2, 0x85, 0x08, 0x76,
+ 0xd3, 0xf1, 0xc4, 0xa0, 0xfa, 0x92, 0x8c, 0x94,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0xb1, 0x2f, 0x68, 0x35, 0xa1, 0xa5, 0x84, 0xb1,
+ 0x4f, 0x1a, 0xb1, 0xb5, 0xf0, 0xb2, 0xbe, 0x61,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0x07, 0xd8, 0x43, 0x74, 0xe8, 0x42, 0xf3, 0xf1,
+ 0x87, 0x3d, 0x9e, 0x92, 0xea, 0x33, 0xe8, 0x54,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0x4c, 0xb7, 0xcc, 0x6d, 0x90, 0x9f, 0x1e, 0x2d,
+ 0x9d, 0x1e, 0x52, 0xa7, 0xe0, 0x0c, 0x7b, 0xf7,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0x5c, 0x32, 0x82, 0xc8, 0x76, 0x17, 0x3b, 0x18,
+ 0x66, 0xda, 0xbf, 0xc3, 0x13, 0x49, 0x05, 0xfb,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0x27, 0x61, 0x4d, 0x04, 0x64, 0xa9, 0x58, 0xf1,
+ 0xe0, 0xf9, 0xe5, 0x78, 0x0b, 0x54, 0x89, 0x0a,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0xe4, 0x8f, 0xdb, 0xc8, 0x35, 0xed, 0x4e, 0x7d,
+ 0xbc, 0x92, 0x7f, 0x58, 0x02, 0xaa, 0xbf, 0x6b,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0xfe, 0x85, 0x08, 0xe0, 0x35, 0x90, 0x13, 0xa9,
+ 0xd3, 0xcf, 0xb6, 0x6d, 0x36, 0xaf, 0xbd, 0x59,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0x47, 0x40, 0x8e, 0x97, 0xe3, 0xfe, 0x8f, 0x52,
+ 0x29, 0x5e, 0x6b, 0x44, 0xdf, 0x0d, 0x60, 0xf4,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0xac, 0xab, 0x13, 0x7c, 0x1a, 0x6e, 0x7a, 0xdb,
+ 0xf6, 0xe8, 0x72, 0x9f, 0xc5, 0xc3, 0x99, 0x1b,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0x79, 0xf2, 0xd1, 0x89, 0x5e, 0xa5, 0xa2, 0x90,
+ 0xee, 0x25, 0x36, 0x81, 0x5a, 0x87, 0x20, 0x82,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0xd4, 0x46, 0xa0, 0xc4, 0x3d, 0xae, 0x22, 0x06,
+ 0xaf, 0x5d, 0x93, 0x96, 0xb7, 0x06, 0xc3, 0x61,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0x5f, 0x81, 0x97, 0x8b, 0x52, 0x87, 0x1c, 0x67,
+ 0xe0, 0x04, 0xcc, 0x50, 0xd9, 0x2b, 0x16, 0xb5,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x6c, 0x51, 0xc3, 0x61, 0x77, 0x7f, 0xf1, 0x05,
+ 0x9e, 0x0f, 0xba, 0xfd, 0x32, 0x02, 0x09, 0x45,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x54, 0xe5, 0x24, 0x81, 0x62, 0x68, 0xe2, 0x45,
+ 0x86, 0x2c, 0x11, 0x28, 0x15, 0xa8, 0x8e, 0x5b,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0xbb, 0x29, 0x3a, 0xba, 0xe6, 0x4f, 0x06, 0xcf,
+ 0xa3, 0x13, 0x27, 0xf2, 0xcb, 0xe4, 0xd2, 0xe6,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0x50, 0xba, 0xd0, 0x0e, 0x26, 0xab, 0x04, 0xf8,
+ 0xa2, 0x03, 0x1e, 0x63, 0x9a, 0xf7, 0x15, 0xdc,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0x12, 0x3e, 0xfe, 0x5a, 0xb1, 0x09, 0x6f, 0x17,
+ 0xb7, 0x77, 0x7e, 0x65, 0x88, 0xd4, 0x95, 0x56,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0xc6, 0x9b, 0xac, 0xde, 0x7e, 0x03, 0x7a, 0xd3,
+ 0xf1, 0xff, 0x3c, 0x4f, 0x4a, 0x85, 0xba, 0x73,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0x17, 0xd5, 0x5e, 0x69, 0x30, 0x2c, 0x1f, 0x01,
+ 0x87, 0x9c, 0xd6, 0xd2, 0xe4, 0x48, 0x8c, 0x84,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0x9d, 0x54, 0x83, 0x4a, 0xcd, 0x93, 0x7c, 0x1e,
+ 0x5b, 0xaf, 0xd2, 0x66, 0x8c, 0x2d, 0xaa, 0xc3,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0xdc, 0x24, 0x69, 0xa8, 0xd3, 0xa9, 0x17, 0x11,
+ 0x08, 0x37, 0x1a, 0x1e, 0x92, 0x03, 0xee, 0x36,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0x98, 0xf8, 0x72, 0x71, 0x99, 0xa0, 0xbd, 0xcd,
+ 0xb1, 0x97, 0x4c, 0x8a, 0xb8, 0xa8, 0x1a, 0x52,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0xbf, 0xb1, 0x8e, 0xa5, 0x14, 0xe3, 0xeb, 0x9e,
+ 0x29, 0x27, 0xe0, 0x19, 0xb1, 0xb2, 0x5c, 0xfe,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0xae, 0x8a, 0x92, 0x78, 0x53, 0x7b, 0xdb, 0x8c,
+ 0xec, 0x3a, 0x99, 0x2b, 0x94, 0xf1, 0x17, 0xfe,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0xcf, 0xaf, 0x70, 0x73, 0x53, 0x65, 0x89, 0x57,
+ 0x36, 0x98, 0xd2, 0x28, 0x86, 0x79, 0xfe, 0x85,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0x0d, 0x2d, 0x77, 0x8a, 0x21, 0x11, 0xd9, 0x61,
+ 0x9f, 0x80, 0x32, 0x8a, 0x32, 0x09, 0x42, 0x42,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0x8b, 0xd2, 0x53, 0xcd, 0x96, 0xd1, 0x14, 0xb5,
+ 0xea, 0x17, 0xb1, 0xa3, 0xa8, 0xfc, 0x3c, 0x2b,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0xc2, 0x4f, 0x84, 0x60, 0x54, 0x79, 0x16, 0xed,
+ 0x1a, 0x6e, 0x78, 0xa0, 0x99, 0x58, 0xf2, 0x94,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0x9a, 0x4c, 0xbc, 0x9c, 0x55, 0x15, 0xa2, 0x4f,
+ 0xa2, 0x5d, 0x3b, 0xa7, 0x43, 0xb3, 0x9c, 0x63,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0xa3, 0xb1, 0x88, 0xa5, 0x70, 0xca, 0xa3, 0xa9,
+ 0x67, 0x2a, 0xac, 0x99, 0x5e, 0x61, 0x68, 0xa0,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0xcf, 0xcf, 0x5b, 0x94, 0xe0, 0xb2, 0x9d, 0x5a,
+ 0x86, 0x71, 0x45, 0xce, 0xd9, 0xce, 0x13, 0xba,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0x10, 0x96, 0x8a, 0x50, 0xa4, 0xd0, 0xaa, 0x5f,
+ 0xd6, 0x32, 0xdb, 0x09, 0x7e, 0x22, 0x96, 0x42,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0xf0, 0x90, 0x61, 0x25, 0x04, 0x29, 0x4f, 0xb6,
+ 0x8b, 0xd5, 0x73, 0x49, 0xbd, 0xf7, 0x9b, 0xe7,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0x5b, 0xe6, 0xb4, 0x3f, 0x1b, 0x77, 0x12, 0x75,
+ 0x84, 0x94, 0xc6, 0x07, 0xfa, 0xa1, 0x41, 0x94,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0x3d, 0x1a, 0xa3, 0x95, 0xec, 0x72, 0x84, 0xf4,
+ 0xc5, 0xcd, 0xaa, 0x48, 0xe9, 0x0c, 0x0f, 0xe3,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0x8a, 0x5a, 0x53, 0xfc, 0x07, 0x52, 0x01, 0xb9,
+ 0xe9, 0x2d, 0xe7, 0x9d, 0x8c, 0x7c, 0xc7, 0xb3,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0xe7, 0x8e, 0xc5, 0x08, 0x7f, 0x7e, 0xb8, 0xdc,
+ 0x05, 0x88, 0x3a, 0x92, 0x5a, 0xf5, 0x9b, 0xa9,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0xf7, 0xa2, 0xb6, 0xec, 0xcd, 0xef, 0xcb, 0xb7,
+ 0x6f, 0xc3, 0xac, 0x17, 0xe2, 0xfd, 0xfa, 0x42,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0x0d, 0xd1, 0xa2, 0x1d, 0xff, 0x74, 0xc5, 0x99,
+ 0xe0, 0x67, 0x07, 0x99, 0x95, 0x75, 0x39, 0x76,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0x2f, 0x13, 0xd1, 0x59, 0xfe, 0x20, 0x60, 0xf0,
+ 0x02, 0x0c, 0xea, 0x79, 0xd7, 0x40, 0x86, 0x85,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0x8b, 0x57, 0x87, 0xdd, 0xb1, 0xcc, 0x2d, 0x65,
+ 0xc1, 0xba, 0xac, 0x88, 0x48, 0x23, 0xda, 0xe7,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0xb3, 0xc4, 0x2e, 0xea, 0x33, 0xaf, 0x12, 0x9c,
+ 0xb5, 0xab, 0xa1, 0x95, 0x30, 0xca, 0x46, 0x48,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0x35, 0x57, 0xcd, 0xd5, 0xd2, 0xf8, 0xd7, 0xf2,
+ 0x7b, 0xe3, 0xd7, 0xba, 0x31, 0xa5, 0xca, 0xfd,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0xe2, 0x3b, 0x20, 0xbe, 0xec, 0xa5, 0x34, 0x3b,
+ 0x76, 0x23, 0x53, 0x28, 0x36, 0xc4, 0x60, 0x13,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0xc9, 0xfe, 0x03, 0x49, 0xe4, 0xff, 0x7e, 0xf7,
+ 0x00, 0xd1, 0x2b, 0x13, 0xb1, 0x15, 0x6e, 0x92,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0xbc, 0xa2, 0xf2, 0x03, 0x5c, 0xfd, 0x20, 0x7b,
+ 0xd0, 0x1f, 0xd6, 0x50, 0xec, 0xc6, 0x7b, 0x31,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x04, 0x50, 0xea, 0xb8, 0xca, 0x36, 0x1a, 0x61,
+ 0x92, 0xed, 0xa0, 0x67, 0x78, 0x15, 0x10, 0xb5,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0x0c, 0x8e, 0x9d, 0x7b, 0x9d, 0x7e, 0xda, 0x23,
+ 0xbb, 0x61, 0xd9, 0xff, 0x46, 0x77, 0x33, 0x1b,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x9a, 0xff, 0xd6, 0xe5, 0x1a, 0xc3, 0xd3, 0x37,
+ 0x34, 0xeb, 0x3e, 0x3a, 0x8e, 0x0b, 0x86, 0xb4,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0xf6, 0x32, 0x19, 0xb4, 0x08, 0x6b, 0x8a, 0x0f,
+ 0xc9, 0x9c, 0x1b, 0x68, 0xb8, 0xa0, 0xd0, 0xc9,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0x86, 0xeb, 0x5c, 0xf9, 0x33, 0x54, 0x7d, 0xe4,
+ 0xa4, 0xe2, 0xe1, 0xf6, 0x6b, 0xea, 0x34, 0xed,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0xad, 0x53, 0xa0, 0x6e, 0xde, 0x1d, 0xda, 0x99,
+ 0x31, 0x45, 0xe5, 0x3a, 0x73, 0xa1, 0x5e, 0xe1,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0x93, 0xd4, 0xe0, 0xaa, 0x0c, 0x91, 0xba, 0xde,
+ 0xc9, 0x5c, 0x68, 0xb0, 0xce, 0xb6, 0x84, 0xcd,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0x85, 0xc7, 0x05, 0x02, 0x21, 0x9d, 0x4c, 0x4c,
+ 0x16, 0xf7, 0x8f, 0x7b, 0xaa, 0xb4, 0x8f, 0x37,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0x84, 0xfd, 0xf1, 0x39, 0x1a, 0x9a, 0xa5, 0xb8,
+ 0x49, 0xc0, 0x66, 0xdc, 0x33, 0x71, 0x32, 0x87,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0x5d, 0xaf, 0x38, 0xcd, 0xb5, 0x83, 0xaa, 0xa0,
+ 0xab, 0x30, 0x82, 0xed, 0x6f, 0xd2, 0x75, 0xe7,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x88, 0x12, 0xe8, 0x89, 0xd4, 0x52, 0x6d, 0xac,
+ 0x61, 0x2a, 0x85, 0x85, 0x1e, 0x9c, 0x82, 0x21,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0xc1, 0xe9, 0xcd, 0x21, 0x29, 0x6a, 0x78, 0xe4,
+ 0x7b, 0x7d, 0x73, 0x25, 0x9e, 0x9b, 0x95, 0x8b,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0x95, 0x87, 0x9d, 0x5a, 0x10, 0x14, 0xa0, 0xdf,
+ 0x5e, 0x02, 0x22, 0x39, 0x23, 0xc9, 0xbc, 0xba,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0x1b, 0x91, 0xe2, 0xdf, 0xca, 0xfe, 0x2b, 0x61,
+ 0x33, 0x8c, 0x83, 0xbf, 0xcf, 0xc3, 0x72, 0xcc,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0xce, 0xc9, 0x68, 0xf7, 0xea, 0x41, 0x18, 0x5c,
+ 0x16, 0x6a, 0x98, 0x13, 0x0c, 0x10, 0xc2, 0xa3,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0x97, 0x73, 0xc9, 0x72, 0x68, 0x99, 0x63, 0xed,
+ 0x81, 0x3b, 0x5c, 0xee, 0x37, 0xfc, 0xca, 0xae,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x5b, 0x85, 0xb0, 0x1b, 0xc3, 0xde, 0x18, 0xba,
+ 0xc1, 0xc7, 0x89, 0x99, 0xfe, 0xcd, 0xdb, 0x6a,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0x5e, 0x1a, 0xcb, 0xbc, 0xda, 0x41, 0x06, 0x5a,
+ 0x14, 0x34, 0x3a, 0xb1, 0xa1, 0x6f, 0xb2, 0xd8,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0x1d, 0x59, 0x8a, 0xb0, 0x19, 0xe5, 0xff, 0x45,
+ 0xb6, 0xc3, 0x33, 0x64, 0xd1, 0x6e, 0xee, 0xdd,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0x4c, 0x9b, 0xe8, 0x68, 0x52, 0x34, 0xef, 0xe1,
+ 0x84, 0xbd, 0x37, 0x85, 0x53, 0x0d, 0xd5, 0xc1,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0xa6, 0xf7, 0x97, 0x18, 0x9a, 0x3e, 0x9d, 0xcf,
+ 0x91, 0xa3, 0xa3, 0x8e, 0xda, 0x8f, 0x8f, 0x90,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0x94, 0x10, 0x19, 0x17, 0x8d, 0x0a, 0x72, 0xfd,
+ 0x24, 0x9d, 0xfd, 0x37, 0x4e, 0xdf, 0x4c, 0x30,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0xfc, 0x64, 0x8a, 0x8b, 0x37, 0x17, 0x90, 0x6d,
+ 0x25, 0x0e, 0xc6, 0x18, 0xc9, 0xc9, 0xc2, 0x2a,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0x50, 0x98, 0x86, 0xf5, 0xc0, 0xda, 0x45, 0x2d,
+ 0xea, 0xc8, 0x9d, 0x28, 0x04, 0xd8, 0x73, 0x6f,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0x13, 0x10, 0x38, 0xe8, 0x17, 0x6d, 0x72, 0xd5,
+ 0x94, 0xaf, 0xed, 0x4f, 0x23, 0xa0, 0x41, 0xfc,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0xdf, 0xed, 0xf7, 0x08, 0xce, 0x64, 0xbc, 0x11,
+ 0x41, 0x7a, 0xd9, 0xf7, 0x4a, 0xd9, 0x4a, 0x15,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0xae, 0x24, 0x8f, 0xdf, 0xb0, 0x57, 0xc4, 0x9c,
+ 0xe6, 0xae, 0x9b, 0xc2, 0x4d, 0x3d, 0x1c, 0xcb,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0xcc, 0x5c, 0xa3, 0xbe, 0xd7, 0x83, 0xee, 0x60,
+ 0x80, 0xff, 0x5f, 0x1a, 0x07, 0xbf, 0x4c, 0x33,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0x93, 0xc3, 0x62, 0x06, 0xcb, 0xe5, 0xb0, 0x01,
+ 0x02, 0x18, 0xa2, 0x50, 0x4c, 0x73, 0xa2, 0x27,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0x11, 0x2a, 0xd3, 0x06, 0x28, 0x9c, 0xdf, 0x73,
+ 0xa5, 0xa4, 0xe5, 0x1e, 0x07, 0xcf, 0xee, 0x71,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x73, 0xa0, 0x40, 0x58, 0x78, 0x20, 0x5f, 0x2c,
+ 0xf4, 0x19, 0x23, 0xa8, 0x74, 0xbd, 0xc2, 0x3e,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x5a, 0x30, 0xbc, 0xce, 0xec, 0xdf, 0xf0, 0x32,
+ 0x3c, 0x18, 0xa3, 0xd3, 0x3f, 0x20, 0x87, 0x10,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x2e, 0x81, 0x09, 0xde, 0x32, 0xc5, 0x28, 0x34,
+ 0xe1, 0x45, 0x4a, 0x35, 0x49, 0xef, 0xa2, 0xed,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x90, 0x3d, 0x26, 0x65, 0xc1, 0xd1, 0x5a, 0x9d,
+ 0xda, 0xab, 0x0d, 0x00, 0x05, 0x0e, 0x6c, 0x5d,
+ },
+ },
+ .ltk = {
+ 0xf1, 0x41, 0x1a, 0x5b, 0x60, 0xc1, 0x43, 0xc6,
+ 0x80, 0x34, 0x5e, 0x7f, 0xd8, 0x0c, 0x75, 0xdc,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_INPUT,
+ .passkey = 516645,
+ },
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 0
+ * Responder IO capabilities: 4
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_sc_us_pk_iio0_rio4_b1_iat0_rat0_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ .resp_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .pair_req = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .our_priv_key = {
+ 0xb1, 0x6b, 0x4f, 0x81, 0xbc, 0xe3, 0x60, 0x9e,
+ 0x00, 0x20, 0xf1, 0x73, 0x3e, 0xfb, 0xcc, 0x6e,
+ 0x8c, 0xb6, 0xd2, 0x51, 0xd9, 0x36, 0x8a, 0x6d,
+ 0xca, 0x8c, 0xd7, 0xbe, 0x96, 0x03, 0xdf, 0xd6,
+ },
+ .public_key_req = {
+ .x = {
+ 0xe5, 0x0f, 0x02, 0x0a, 0x37, 0x90, 0x94, 0x5a,
+ 0x06, 0x21, 0xf7, 0xbc, 0xd5, 0xbe, 0xb9, 0x24,
+ 0x8a, 0x35, 0xfd, 0xf8, 0x5e, 0xe2, 0x70, 0xd5,
+ 0x5a, 0xe8, 0xe7, 0xdd, 0x13, 0x90, 0xeb, 0xd4,
+ },
+ .y = {
+ 0x41, 0xc8, 0x51, 0x1a, 0x25, 0x44, 0x01, 0x53,
+ 0x42, 0x74, 0x07, 0x9c, 0x18, 0xe6, 0x3b, 0x8a,
+ 0xce, 0x7a, 0x37, 0x1f, 0x18, 0x5c, 0x02, 0x7c,
+ 0x67, 0x16, 0xf5, 0x30, 0x2b, 0x31, 0xa9, 0xc7,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x03, 0x0d, 0x13, 0x55, 0xd9, 0xee, 0x3f, 0xac,
+ 0x8e, 0x8a, 0xa6, 0x2a, 0xcb, 0x60, 0x35, 0xb9,
+ 0xb2, 0x4d, 0x63, 0x91, 0x5e, 0xa1, 0xdd, 0xdf,
+ 0x60, 0xdc, 0x6e, 0x09, 0xb9, 0x9e, 0xf1, 0x4d,
+ },
+ .y = {
+ 0xa8, 0x09, 0x31, 0x1e, 0x39, 0x96, 0x74, 0x41,
+ 0xea, 0x19, 0x4f, 0x24, 0x36, 0x57, 0x7c, 0x9f,
+ 0x21, 0xa3, 0xad, 0xa1, 0x3d, 0xe2, 0x1c, 0x6a,
+ 0xd6, 0xc9, 0xdb, 0xff, 0xce, 0x0a, 0x94, 0x12,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x3b, 0x3d, 0xb2, 0x2f, 0x72, 0x0f, 0x93, 0x19,
+ 0x95, 0xdb, 0x88, 0xdf, 0x5d, 0x58, 0x95, 0x37,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x98, 0xab, 0x20, 0x8d, 0x51, 0x3b, 0x6c, 0x29,
+ 0x2d, 0x73, 0x15, 0xf6, 0x6d, 0x6d, 0xb9, 0xb3,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xc1, 0xdf, 0x20, 0x3d, 0x7b, 0xcb, 0x5f, 0xe2,
+ 0x9a, 0x23, 0x9c, 0xba, 0x2f, 0x42, 0x3c, 0xb8,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x7d, 0x82, 0xb4, 0xae, 0x41, 0xdb, 0x67, 0x8f,
+ 0x54, 0x01, 0x21, 0x64, 0x31, 0xd4, 0xfc, 0xb5,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0xc3, 0xa5, 0xd0, 0xdd, 0xd5, 0xec, 0x1d, 0xc3,
+ 0x14, 0x95, 0x79, 0xb2, 0x61, 0x4d, 0x4f, 0x36,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0xe2, 0x20, 0xf4, 0x4d, 0xa1, 0x9c, 0x83, 0x51,
+ 0x18, 0xf9, 0x35, 0x2a, 0x51, 0x50, 0xdf, 0xe7,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0x71, 0xcb, 0x01, 0xb4, 0x83, 0xdc, 0xd8, 0x54,
+ 0x0f, 0xe5, 0xd5, 0x6b, 0x6a, 0x0d, 0x98, 0xb6,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0x30, 0xbf, 0xd3, 0xfd, 0xf4, 0xc2, 0xa1, 0xd0,
+ 0xba, 0x4b, 0x27, 0x7c, 0x29, 0x98, 0x54, 0xa2,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0xf0, 0x92, 0xc4, 0xda, 0x8a, 0x17, 0x7c, 0xc6,
+ 0x14, 0x05, 0x7d, 0xbb, 0xfc, 0x7c, 0xcd, 0x0a,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0xf3, 0x89, 0xca, 0xe0, 0xfb, 0xbe, 0x8c, 0xc3,
+ 0x4c, 0x6c, 0x6e, 0x11, 0x36, 0x4e, 0xaa, 0x25,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0x78, 0x5a, 0xf0, 0x1e, 0x2a, 0x0d, 0x16, 0xb3,
+ 0x03, 0x4b, 0x4b, 0x68, 0x17, 0xe0, 0xf0, 0x82,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0xbf, 0x96, 0xdd, 0xf5, 0x30, 0x2a, 0xe9, 0x8c,
+ 0xb9, 0x13, 0xc5, 0xb7, 0x15, 0x1f, 0xa3, 0x9b,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0x36, 0xe4, 0x4c, 0x00, 0xe7, 0x0d, 0xee, 0xe4,
+ 0x95, 0xb8, 0x6a, 0xf9, 0xf7, 0x24, 0xef, 0xea,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0x2e, 0x90, 0x87, 0x85, 0xb8, 0x29, 0x93, 0x9e,
+ 0x38, 0xa6, 0xdb, 0x17, 0xb2, 0xa8, 0x32, 0x65,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0x0a, 0xee, 0x93, 0xf6, 0x56, 0x35, 0x8e, 0xed,
+ 0x3f, 0x45, 0xa5, 0x01, 0x59, 0xeb, 0xea, 0xa8,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0x38, 0xd0, 0xf8, 0x11, 0x5e, 0x47, 0x72, 0x66,
+ 0xce, 0x56, 0x9c, 0x81, 0x5f, 0x52, 0xd4, 0x9a,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x2c, 0x98, 0x9b, 0x71, 0xe4, 0xde, 0x6d, 0x20,
+ 0x84, 0x30, 0xab, 0x7a, 0xfc, 0x43, 0x82, 0xc6,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x76, 0xfe, 0x1f, 0x78, 0xaa, 0x42, 0xd5, 0xc6,
+ 0x9f, 0xe4, 0xa7, 0xc7, 0xb8, 0xd2, 0x1e, 0x59,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0x61, 0x5e, 0x47, 0xb1, 0x77, 0x6f, 0x04, 0xee,
+ 0x94, 0xc4, 0x6c, 0xa9, 0xf5, 0xf8, 0x11, 0x6e,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0xa5, 0xad, 0x98, 0x65, 0x28, 0xfc, 0x6b, 0x02,
+ 0x6d, 0x9a, 0x29, 0x61, 0x1c, 0x02, 0x0a, 0x6b,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0x4d, 0x55, 0x3e, 0x1f, 0x87, 0x12, 0xc7, 0x6c,
+ 0xd7, 0x9a, 0xa6, 0xf1, 0x6e, 0x48, 0xd3, 0x7d,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0xff, 0x77, 0x6e, 0xba, 0x1f, 0xb7, 0xbd, 0x0b,
+ 0x3f, 0xce, 0xd5, 0x39, 0x81, 0x17, 0x51, 0xfc,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0xf9, 0x2c, 0x77, 0x41, 0xcd, 0x9a, 0x10, 0x99,
+ 0xc6, 0x70, 0x5a, 0xc8, 0x24, 0x26, 0xb2, 0xc8,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0xa0, 0x44, 0x0a, 0x8b, 0xda, 0x6a, 0x74, 0x90,
+ 0x5f, 0x89, 0x44, 0xa5, 0x9a, 0x58, 0xd5, 0x08,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0x7e, 0x6e, 0x89, 0xc8, 0xbe, 0xde, 0x1c, 0xc3,
+ 0x45, 0xb6, 0x4c, 0x83, 0x71, 0xe2, 0xd6, 0xda,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0x4a, 0x29, 0x7b, 0x88, 0x97, 0xc1, 0x60, 0x85,
+ 0x32, 0x7d, 0xf1, 0xaa, 0x04, 0x13, 0x89, 0x11,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0x2a, 0xaf, 0x7d, 0x21, 0x4e, 0x14, 0xf5, 0x7e,
+ 0xcc, 0x39, 0xf7, 0x56, 0x45, 0x87, 0x23, 0x64,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0x74, 0xd2, 0xff, 0xf0, 0x19, 0xf7, 0x87, 0xe7,
+ 0x0d, 0x65, 0x27, 0x61, 0xea, 0x9e, 0x05, 0x3d,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0x4f, 0x77, 0x22, 0x08, 0x58, 0xed, 0x8c, 0x60,
+ 0xbf, 0xbc, 0x78, 0x0c, 0x80, 0xc9, 0xb7, 0x60,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0xd2, 0x47, 0xfd, 0xea, 0xa3, 0x32, 0x53, 0xc1,
+ 0x06, 0xcd, 0x64, 0xeb, 0x88, 0x64, 0x0e, 0xe5,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0xc8, 0xd0, 0x45, 0xa8, 0x29, 0xdb, 0x5a, 0x42,
+ 0xfe, 0x68, 0xa8, 0x7a, 0x0a, 0x13, 0x22, 0xa4,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0x78, 0x14, 0x46, 0xe2, 0x47, 0x0e, 0xd4, 0xb4,
+ 0xde, 0x35, 0x4a, 0x82, 0x4b, 0x32, 0x9b, 0x46,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0x24, 0x96, 0xe5, 0x50, 0xfa, 0xff, 0xba, 0xdf,
+ 0x6b, 0x76, 0x40, 0x60, 0x56, 0x5e, 0x5a, 0x66,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0x09, 0xfe, 0x15, 0x3e, 0x55, 0xe5, 0xbe, 0xb7,
+ 0x8d, 0xaa, 0x04, 0x59, 0xe6, 0x8b, 0x2c, 0x4e,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0x02, 0x25, 0xbe, 0x88, 0x37, 0xb4, 0x6e, 0xcb,
+ 0xbc, 0xa9, 0xef, 0x5a, 0xfd, 0x1a, 0x5f, 0x5f,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0x0b, 0x35, 0xdc, 0x9b, 0x3d, 0xf7, 0xa6, 0x99,
+ 0xf3, 0xb9, 0x3c, 0x73, 0x67, 0x0e, 0xcc, 0x12,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0x38, 0x1c, 0xf7, 0xf0, 0x31, 0xb1, 0x20, 0xa0,
+ 0x51, 0x1c, 0xf1, 0xbd, 0x67, 0xfa, 0x84, 0xb4,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0x8e, 0xa1, 0xc1, 0xf5, 0x39, 0xf0, 0x00, 0x49,
+ 0xfb, 0xfc, 0xdc, 0xdf, 0x87, 0x0e, 0x96, 0x7e,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0xd0, 0xed, 0x6c, 0x52, 0x20, 0x4b, 0x7b, 0x24,
+ 0xdd, 0x28, 0x53, 0x2d, 0x71, 0x76, 0xfb, 0x8f,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0xac, 0xd7, 0x34, 0x6b, 0x7b, 0x59, 0x9e, 0x9b,
+ 0x5b, 0x37, 0xc6, 0x5c, 0x3e, 0x9d, 0xe2, 0x13,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0xa6, 0xd7, 0xb6, 0xd6, 0xb5, 0x01, 0x4a, 0x02,
+ 0x0d, 0xf0, 0x22, 0xcb, 0x68, 0xad, 0x7d, 0x73,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0x01, 0xcc, 0x5f, 0xbc, 0xd0, 0x22, 0xa1, 0xb2,
+ 0x71, 0x9d, 0x5c, 0x97, 0xfa, 0xd3, 0x6a, 0xc7,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0x9f, 0x3a, 0x25, 0xc7, 0x9b, 0xb7, 0xb3, 0x51,
+ 0xff, 0xde, 0x3b, 0x1c, 0xdd, 0xf5, 0x08, 0x21,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0x75, 0x1e, 0x8d, 0xa4, 0x5b, 0x35, 0xec, 0xae,
+ 0x17, 0xda, 0xa5, 0x43, 0x76, 0x3c, 0x6a, 0x67,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0xfc, 0x0c, 0x3f, 0x86, 0xbf, 0xbe, 0x96, 0x0f,
+ 0x99, 0x11, 0xa5, 0x36, 0x03, 0xcd, 0xbd, 0x7f,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0x48, 0xcd, 0xc8, 0x89, 0xd6, 0x1c, 0x0d, 0xb1,
+ 0x90, 0x01, 0x0e, 0xea, 0x80, 0xbc, 0xff, 0xb3,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0xec, 0xfc, 0xe3, 0x0a, 0x97, 0xed, 0xe8, 0x51,
+ 0x5d, 0x64, 0x3c, 0x73, 0x59, 0x2e, 0x62, 0xac,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0x81, 0x74, 0x44, 0xca, 0xec, 0x38, 0x20, 0x6d,
+ 0x52, 0x27, 0x49, 0x55, 0x61, 0x97, 0x01, 0x34,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0x27, 0x8c, 0x88, 0x09, 0xcb, 0xd6, 0x45, 0xb7,
+ 0x30, 0x4b, 0x1b, 0xcd, 0xc3, 0xac, 0x83, 0xd6,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0xea, 0xbc, 0xe2, 0x43, 0xc8, 0xe0, 0x06, 0xd8,
+ 0x7b, 0x3e, 0xa4, 0x55, 0x95, 0xa2, 0x23, 0x9b,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x68, 0x8f, 0xb6, 0x7b, 0x91, 0x0d, 0xc9, 0x30,
+ 0xe7, 0xb7, 0xb7, 0x7a, 0x79, 0x29, 0x59, 0x7d,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0xfd, 0xa1, 0x3d, 0xaf, 0x8d, 0xd2, 0xa0, 0x02,
+ 0x82, 0x92, 0xeb, 0x2e, 0x4d, 0x6c, 0x8d, 0x69,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x6f, 0xa8, 0x20, 0x81, 0x1c, 0x4b, 0xe8, 0xe3,
+ 0xdc, 0xea, 0x39, 0xbd, 0xfb, 0xbf, 0x79, 0xc4,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0x2a, 0x09, 0xec, 0x32, 0x63, 0x3d, 0x38, 0x5d,
+ 0x28, 0xb2, 0xb1, 0x62, 0xee, 0x6c, 0x0a, 0x6c,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0x35, 0xb5, 0xc5, 0xc0, 0x74, 0x1f, 0x40, 0xac,
+ 0x23, 0x52, 0x02, 0x68, 0xdf, 0x62, 0x73, 0xca,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0xb8, 0xe2, 0x65, 0xdc, 0x22, 0xcb, 0xc2, 0xdb,
+ 0x00, 0x60, 0x37, 0xe2, 0xcc, 0xc0, 0x41, 0x72,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0x05, 0x0b, 0x5c, 0xa7, 0x58, 0x9c, 0x08, 0x81,
+ 0x4a, 0x6b, 0x12, 0xae, 0xaa, 0xe5, 0x81, 0xf3,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0xdd, 0x2b, 0xd1, 0xdd, 0x49, 0x92, 0xf3, 0xe1,
+ 0xae, 0xf3, 0x6d, 0x89, 0xfd, 0x77, 0xf9, 0xaa,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0xbc, 0x27, 0x29, 0x1b, 0xc4, 0xbc, 0x0e, 0x88,
+ 0x95, 0x50, 0xf7, 0x92, 0xe6, 0xf7, 0x29, 0xe8,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0xe7, 0x15, 0xfe, 0x53, 0x77, 0xd9, 0x98, 0x1d,
+ 0x5b, 0x4e, 0x37, 0xa3, 0x1f, 0xc9, 0x47, 0x5d,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x75, 0x70, 0x9f, 0x84, 0x3e, 0x6b, 0x88, 0xcb,
+ 0x66, 0xda, 0x8f, 0x79, 0xbc, 0xf8, 0x44, 0x99,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0x13, 0xe4, 0x43, 0xb2, 0x61, 0x72, 0xfd, 0x33,
+ 0xba, 0x87, 0x44, 0x27, 0x6f, 0x9a, 0xea, 0x19,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0xda, 0x90, 0x59, 0x72, 0xed, 0x67, 0xde, 0x65,
+ 0x21, 0xab, 0x7d, 0x9d, 0x72, 0x8c, 0x88, 0x8e,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0x94, 0x92, 0x0f, 0x6c, 0x08, 0xde, 0xae, 0xa7,
+ 0xfd, 0x36, 0xe0, 0x02, 0xc8, 0xfd, 0xdd, 0x69,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0x35, 0x68, 0x1e, 0x80, 0x37, 0xc4, 0x91, 0xe8,
+ 0xbf, 0x5e, 0x27, 0x0c, 0xaa, 0x8e, 0x85, 0x7b,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0x1e, 0x42, 0x47, 0x29, 0x06, 0xdc, 0x2b, 0x45,
+ 0xec, 0x95, 0x23, 0x31, 0x29, 0x24, 0x95, 0xf0,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x4e, 0x9f, 0x5d, 0x5a, 0x8f, 0xf7, 0x28, 0xc9,
+ 0x29, 0x62, 0x0a, 0x67, 0x19, 0x17, 0x5e, 0xa7,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0x7c, 0xd4, 0x13, 0xba, 0x27, 0x16, 0x39, 0xe7,
+ 0xf0, 0xbf, 0xec, 0x1e, 0xe5, 0xcc, 0x20, 0x0b,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0xb9, 0xcd, 0xf5, 0xf9, 0x2b, 0x4f, 0x6d, 0x08,
+ 0x51, 0xe0, 0x92, 0x99, 0x15, 0xca, 0x15, 0x2a,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0xb8, 0xf2, 0xf9, 0x61, 0x4f, 0x0e, 0xfd, 0x19,
+ 0xcb, 0x5d, 0x7e, 0x93, 0x87, 0x7a, 0x0a, 0x6e,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0x8b, 0xf8, 0xc8, 0xeb, 0xe5, 0xdb, 0xcf, 0xfe,
+ 0x68, 0x70, 0x1f, 0xbe, 0x1e, 0x3c, 0x94, 0x7d,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0x0d, 0xfc, 0x68, 0x2e, 0x50, 0x31, 0x9f, 0x60,
+ 0xe6, 0x12, 0x72, 0x24, 0x7c, 0xad, 0xf7, 0x48,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0x27, 0x68, 0x07, 0xaa, 0xa6, 0x33, 0x13, 0x49,
+ 0x65, 0x4c, 0x80, 0x54, 0xfb, 0x69, 0xcb, 0x0e,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0xc5, 0x8d, 0x45, 0x81, 0xb0, 0x5a, 0x69, 0x0f,
+ 0x6c, 0x89, 0x0b, 0x60, 0x1e, 0x27, 0x9b, 0x9e,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0x97, 0x46, 0x95, 0xb5, 0x86, 0xa1, 0xc1, 0x86,
+ 0x3a, 0x8a, 0x1f, 0x29, 0x38, 0xe0, 0x69, 0x7f,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0x8f, 0x0e, 0x56, 0x17, 0x1c, 0x4b, 0x78, 0x1f,
+ 0xd1, 0x8a, 0x69, 0xbd, 0x65, 0xe3, 0xde, 0x3c,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0xd2, 0xa5, 0x4e, 0x31, 0x34, 0xde, 0x68, 0xf0,
+ 0x69, 0x88, 0x6f, 0x28, 0xa2, 0xdd, 0xba, 0xe1,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0xf8, 0x5e, 0x4f, 0x4d, 0x56, 0xf6, 0x22, 0xc0,
+ 0x57, 0x04, 0x04, 0x45, 0x24, 0x83, 0x09, 0x80,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0x64, 0xe1, 0x5a, 0x76, 0x71, 0x94, 0xc0, 0x64,
+ 0x2b, 0xea, 0x9d, 0xaf, 0xbd, 0x10, 0x25, 0x9b,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0x1e, 0x38, 0x6e, 0x66, 0x55, 0xf1, 0x7f, 0x55,
+ 0x7c, 0x00, 0xff, 0xad, 0x07, 0x13, 0x25, 0x97,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x98, 0xf1, 0x5a, 0x24, 0x81, 0x5d, 0xb5, 0xac,
+ 0x04, 0x4e, 0x3a, 0x31, 0x8b, 0x7d, 0xf6, 0x09,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x1a, 0xb4, 0xf4, 0xf3, 0xc0, 0x5a, 0xf3, 0x13,
+ 0x8d, 0x6e, 0x01, 0x16, 0x1e, 0x54, 0xf3, 0xe1,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x4b, 0x01, 0x33, 0x5f, 0x4b, 0xfe, 0x12, 0x8b,
+ 0x9f, 0x81, 0x44, 0x78, 0x90, 0x03, 0x9e, 0x53,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0xd2, 0xa1, 0x2c, 0xf0, 0xa6, 0xeb, 0x97, 0x5e,
+ 0xac, 0x53, 0xa1, 0x3d, 0x41, 0x40, 0x36, 0x2f,
+ },
+ },
+ .ltk = {
+ 0xce, 0x28, 0x91, 0xa9, 0x36, 0xb7, 0xe1, 0xda,
+ 0x3c, 0x66, 0xd9, 0x33, 0x3d, 0x03, 0x8e, 0x31,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_DISP,
+ .passkey = 866744,
+ },
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: numeric comparison
+ * Initiator IO capabilities: 1
+ * Responder IO capabilities: 4
+ * Bonding: true
+ * Initiator address type: 0
+ * Responder address type: 0
+ * Initiator key distribution: 7
+ * Responder key distribution: 5
+ */
+TEST_CASE_SELF(ble_sm_sc_us_nc_iio1_rio4_b1_iat0_rat0_ik7_rk5)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ .resp_id_addr = {
+ 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0,
+ },
+ .pair_req = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x04,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x05,
+ },
+ .our_priv_key = {
+ 0xb1, 0x6b, 0x4f, 0x81, 0xbc, 0xe3, 0x60, 0x9e,
+ 0x00, 0x20, 0xf1, 0x73, 0x3e, 0xfb, 0xcc, 0x6e,
+ 0x8c, 0xb6, 0xd2, 0x51, 0xd9, 0x36, 0x8a, 0x6d,
+ 0xca, 0x8c, 0xd7, 0xbe, 0x96, 0x03, 0xdf, 0xd6,
+ },
+ .public_key_req = {
+ .x = {
+ 0xe5, 0x0f, 0x02, 0x0a, 0x37, 0x90, 0x94, 0x5a,
+ 0x06, 0x21, 0xf7, 0xbc, 0xd5, 0xbe, 0xb9, 0x24,
+ 0x8a, 0x35, 0xfd, 0xf8, 0x5e, 0xe2, 0x70, 0xd5,
+ 0x5a, 0xe8, 0xe7, 0xdd, 0x13, 0x90, 0xeb, 0xd4,
+ },
+ .y = {
+ 0x41, 0xc8, 0x51, 0x1a, 0x25, 0x44, 0x01, 0x53,
+ 0x42, 0x74, 0x07, 0x9c, 0x18, 0xe6, 0x3b, 0x8a,
+ 0xce, 0x7a, 0x37, 0x1f, 0x18, 0x5c, 0x02, 0x7c,
+ 0x67, 0x16, 0xf5, 0x30, 0x2b, 0x31, 0xa9, 0xc7,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x7c, 0x27, 0x39, 0xdc, 0x10, 0xfa, 0x57, 0x97,
+ 0x4a, 0x18, 0xdc, 0x0e, 0xfc, 0x4b, 0xd0, 0xac,
+ 0x3a, 0xa4, 0x4c, 0x65, 0xb5, 0xbe, 0x7b, 0xd8,
+ 0xd1, 0xfd, 0x9d, 0xf8, 0xe3, 0x00, 0x4e, 0xf3,
+ },
+ .y = {
+ 0xae, 0xfd, 0x8e, 0x93, 0xb4, 0xa9, 0x4d, 0xd3,
+ 0xb6, 0xbd, 0x4c, 0x1d, 0xc1, 0x7e, 0x67, 0x57,
+ 0x07, 0x10, 0x4e, 0xd0, 0x0f, 0x23, 0x23, 0xab,
+ 0x09, 0x86, 0xc3, 0xb9, 0x63, 0x14, 0xe4, 0xe5,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x40, 0x35, 0x6d, 0xa1, 0x19, 0xa6, 0x8b, 0xff,
+ 0x4f, 0x0c, 0x86, 0x7e, 0x95, 0x7c, 0xb8, 0xc1,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x95, 0x84, 0x0d, 0x2d, 0x7a, 0xfd, 0x5a, 0xa6,
+ 0xea, 0xfd, 0x7b, 0xf0, 0x68, 0x95, 0xeb, 0x77,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x25, 0x41, 0xda, 0xdf, 0xdd, 0xca, 0xcd, 0x2e,
+ 0x49, 0x79, 0xb0, 0xaa, 0x7a, 0x23, 0x28, 0x7f,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x49, 0xbb, 0x89, 0x9e, 0xa1, 0x10, 0x26, 0x7a,
+ 0xe7, 0x42, 0x51, 0xcd, 0x1f, 0x3b, 0x22, 0x1d,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x59, 0x51, 0xc8, 0x7b, 0x4f, 0xae, 0xfe, 0xb8,
+ 0x0c, 0x41, 0xe8, 0xe0, 0xf9, 0x4c, 0x2b, 0xc7,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0x37, 0x26, 0xc0, 0x79, 0x59, 0xcd, 0xb7, 0x0f,
+ 0xa6, 0xd8, 0xe4, 0x02, 0xc9, 0xe6, 0x02, 0x71,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d,
+ 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x01, 0x01, 0x01, 0x07, 0x08, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x45, 0x69, 0x05, 0xe3, 0x0c, 0x9e, 0x01, 0xb3,
+ 0xe8, 0xea, 0xa0, 0x5b, 0x70, 0xd9, 0x62, 0x0e,
+ },
+ },
+ .ltk = {
+ 0xf5, 0x60, 0x02, 0x97, 0x2f, 0xbb, 0x3c, 0xe9,
+ 0x97, 0xd7, 0xd5, 0x58, 0x04, 0x96, 0xa6, 0xe7,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_NUMCMP,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NUMCMP,
+ .numcmp_accept = 1,
+ },
+ .exp_numcmp = 344302,
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 7
+ * Responder key distribution: 7
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_jw_iio3_rio3_b1_iat2_rat2_ik7_rk7)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0xd0, 0x8e, 0xf7, 0x42, 0x8c, 0x69,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0x1a, 0x6e, 0x83, 0x55, 0x5b, 0x5a,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .our_priv_key = {
+ 0xc5, 0x04, 0xc5, 0xf9, 0x28, 0x95, 0x78, 0x17,
+ 0xd5, 0x97, 0x1d, 0x01, 0xbb, 0x2c, 0xcf, 0x77,
+ 0x5c, 0x70, 0x52, 0xc6, 0x5e, 0x33, 0x2e, 0xe7,
+ 0x79, 0x58, 0xc8, 0xf1, 0xc2, 0x2d, 0xb0, 0x61,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x1e, 0x07, 0x87, 0xb2, 0x54, 0x3a, 0x44, 0x6b,
+ 0x97, 0x45, 0xa7, 0xa2, 0x36, 0xf4, 0x10, 0x42,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x99, 0xc4, 0xdf, 0x4a, 0x2f, 0x14, 0xd8, 0x11,
+ 0xd3, 0x93, 0x53, 0xac, 0x64, 0xc8, 0x67, 0xe6,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0xc5, 0xb0, 0xf5, 0x2a, 0x65, 0x77, 0x05, 0xb8,
+ 0xf7, 0x5b, 0xad, 0x4e, 0xa9, 0x9e, 0x79, 0x98,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xbb, 0x44, 0x9b, 0x1b, 0xcd, 0xfc, 0xdf, 0xff,
+ 0xbb, 0x34, 0xb7, 0x3b, 0x3e, 0x30, 0xa1, 0x6e,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x58, 0x8f, 0xbe, 0xa2, 0x5f, 0xe3, 0x0a, 0xbc,
+ 0x17, 0x0f, 0x3b, 0x23, 0x27, 0xa5, 0xfb, 0x25,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .sign_info_req = {
+ .sig_key = {
+ 0xd3, 0x46, 0x86, 0xf7, 0xeb, 0x19, 0x0a, 0x18,
+ 0x5a, 0xb2, 0xd0, 0x5b, 0x0f, 0x03, 0x64, 0x01,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x84, 0x91, 0x5d, 0x89, 0xf6, 0xf0, 0x01, 0x65,
+ 0xed, 0xa9, 0xcc, 0x9b, 0xa4, 0xd4, 0x97, 0x86,
+ },
+ },
+ .ltk = {
+ 0x4b, 0xb6, 0x1d, 0xd2, 0xba, 0xa4, 0x94, 0xe5,
+ 0x78, 0xde, 0xee, 0x47, 0x7a, 0x95, 0x91, 0x1c,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_JW,
+ .authenticated = 0,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: numeric comparison
+ * Initiator IO capabilities: 1
+ * Responder IO capabilities: 1
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 3
+ * Responder key distribution: 3
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_nc_iio1_rio1_b1_iat2_rat2_ik3_rk3)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0xc5, 0xf3, 0x5d, 0x83, 0xcd, 0x4a,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0x9f, 0x56, 0x57, 0x5e, 0x12, 0x65,
+ },
+ .pair_req = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .pair_rsp = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .our_priv_key = {
+ 0xc5, 0x04, 0xc5, 0xf9, 0x28, 0x95, 0x78, 0x17,
+ 0xd5, 0x97, 0x1d, 0x01, 0xbb, 0x2c, 0xcf, 0x77,
+ 0x5c, 0x70, 0x52, 0xc6, 0x5e, 0x33, 0x2e, 0xe7,
+ 0x79, 0x58, 0xc8, 0xf1, 0xc2, 0x2d, 0xb0, 0x61,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x39, 0xba, 0x86, 0x47, 0x06, 0x87, 0x14, 0xe4,
+ 0x5c, 0x82, 0xe9, 0x6a, 0x80, 0xca, 0x87, 0xcd,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xce, 0xe2, 0xa3, 0x29, 0x8a, 0xc6, 0x76, 0x1d,
+ 0xa2, 0xfd, 0xe0, 0x7f, 0x8c, 0xbe, 0xf8, 0x1d,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x3d, 0xac, 0xf0, 0xfe, 0x7c, 0x78, 0x73, 0x03,
+ 0xe2, 0xb6, 0x59, 0x7e, 0x80, 0xb4, 0x69, 0x07,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xaa, 0x95, 0x9f, 0x33, 0x32, 0xa1, 0xbd, 0xf9,
+ 0xef, 0xb9, 0x3d, 0xfb, 0x08, 0xd1, 0x28, 0xa0,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x3c, 0x10, 0x17, 0x76, 0x55, 0x65, 0x6f, 0x14,
+ 0xfa, 0x80, 0xd3, 0x52, 0x04, 0x82, 0xe2, 0xf7,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xd4, 0x66, 0x94, 0xc9, 0x96, 0xd0, 0x28, 0x96,
+ 0x1c, 0xa1, 0x3b, 0xf7, 0x15, 0x95, 0x95, 0x43,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xb7, 0x98, 0xac, 0x85, 0xc4, 0x0a, 0x69, 0x8d,
+ 0xa6, 0xaf, 0xf3, 0x1f, 0x63, 0x3c, 0xf2, 0x33,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .ltk = {
+ 0x95, 0x46, 0xe6, 0x8e, 0x52, 0xcc, 0x05, 0xca,
+ 0xf4, 0x59, 0x57, 0x54, 0x8c, 0x0d, 0x51, 0xfc,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_NUMCMP,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NUMCMP,
+ .numcmp_accept = 1,
+ },
+ .exp_numcmp = 70210,
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: peer
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 2
+ * Responder IO capabilities: 0
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 7
+ * Responder key distribution: 3
+ */
+TEST_CASE_SELF(ble_sm_sc_peer_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0x6e, 0x56, 0x09, 0xef, 0x1e, 0x76,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0xb5, 0x29, 0xdf, 0xb4, 0x9b, 0x62,
+ },
+ .pair_req = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x03,
+ },
+ .pair_rsp = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x03,
+ },
+ .our_priv_key = {
+ 0xc5, 0x04, 0xc5, 0xf9, 0x28, 0x95, 0x78, 0x17,
+ 0xd5, 0x97, 0x1d, 0x01, 0xbb, 0x2c, 0xcf, 0x77,
+ 0x5c, 0x70, 0x52, 0xc6, 0x5e, 0x33, 0x2e, 0xe7,
+ 0x79, 0x58, 0xc8, 0xf1, 0xc2, 0x2d, 0xb0, 0x61,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x12, 0xe3, 0x01, 0xd0, 0x30, 0x59, 0xca, 0xd9,
+ 0x78, 0x0b, 0x45, 0x73, 0xb1, 0x7a, 0x4d, 0xca,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x47, 0x68, 0x16, 0x24, 0xd4, 0x07, 0x60, 0x6c,
+ 0xa5, 0x47, 0x6f, 0x05, 0x78, 0x71, 0x3e, 0xa8,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x2a, 0x29, 0xa8, 0xef, 0x0b, 0x70, 0x5f, 0x1b,
+ 0x81, 0x4d, 0x97, 0xff, 0xfb, 0x7f, 0x30, 0x90,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x12, 0x9e, 0x1d, 0x12, 0x11, 0x44, 0x36, 0x74,
+ 0xa3, 0x0c, 0xea, 0x36, 0x4d, 0xdf, 0x2d, 0x5d,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0x4d, 0x6a, 0x32, 0xfe, 0xe2, 0xa0, 0xdd, 0x92,
+ 0x60, 0x5c, 0x82, 0x7f, 0xa6, 0xa6, 0x24, 0xd6,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0xd5, 0x3e, 0xa7, 0xa0, 0xbf, 0x39, 0x8e, 0xfe,
+ 0xfd, 0x73, 0x47, 0x4c, 0x92, 0x8b, 0x74, 0x06,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0xc1, 0x88, 0xdf, 0xb0, 0x99, 0xbb, 0xbf, 0xed,
+ 0xdc, 0x40, 0x66, 0x55, 0xbe, 0x91, 0x56, 0x9a,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0xed, 0xed, 0x9a, 0x61, 0xb8, 0x21, 0x03, 0x77,
+ 0xa6, 0xcf, 0x34, 0x65, 0x8c, 0x18, 0x82, 0x9f,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0xdb, 0xea, 0x94, 0x29, 0xe4, 0x44, 0x7d, 0x7b,
+ 0xd3, 0x16, 0x81, 0x8e, 0xaf, 0xe6, 0x9c, 0x85,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0x3f, 0xdd, 0x54, 0x76, 0xab, 0x45, 0x7f, 0x53,
+ 0x64, 0x6b, 0x37, 0xa6, 0xc7, 0xc6, 0x4a, 0x73,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0x5a, 0xf1, 0xfb, 0xde, 0xb3, 0xbe, 0x6e, 0xac,
+ 0x68, 0x51, 0x47, 0x8e, 0x0b, 0xcd, 0xc1, 0xa0,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0x29, 0x0f, 0x5e, 0x83, 0x87, 0xca, 0xd3, 0x21,
+ 0xa7, 0x7e, 0x3d, 0x78, 0x47, 0x54, 0xf8, 0xe4,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0xca, 0x3e, 0xd5, 0xe3, 0x59, 0xb0, 0x5d, 0x1e,
+ 0x0f, 0x4c, 0x95, 0x0f, 0x6a, 0x72, 0xcf, 0x25,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0x2f, 0x4d, 0x06, 0x40, 0x09, 0x68, 0x68, 0x45,
+ 0x87, 0x79, 0x78, 0x48, 0xda, 0xe4, 0xf5, 0xae,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0x63, 0x5a, 0xee, 0x91, 0xe4, 0xf8, 0xe8, 0x69,
+ 0xd1, 0x46, 0x18, 0x0d, 0xd2, 0x94, 0xd8, 0x20,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0x76, 0x36, 0xf5, 0xc2, 0x41, 0xb6, 0x3c, 0x1f,
+ 0x36, 0x19, 0x58, 0xce, 0x8f, 0x41, 0xeb, 0x8c,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x76, 0xfd, 0x84, 0x0f, 0x0f, 0x58, 0x70, 0x45,
+ 0x41, 0x33, 0x5d, 0xce, 0xe5, 0xe2, 0x2f, 0x83,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x87, 0xcf, 0xdf, 0xa5, 0x60, 0x82, 0x4f, 0x09,
+ 0x4c, 0x50, 0x24, 0xba, 0x91, 0x96, 0x0d, 0x65,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0x67, 0xdb, 0x73, 0x1e, 0x57, 0x5c, 0xb7, 0x86,
+ 0xf8, 0xaf, 0x58, 0xd8, 0x0f, 0x97, 0x47, 0xce,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0xaa, 0x99, 0x90, 0x05, 0x11, 0xfc, 0xc2, 0xd9,
+ 0xb8, 0xd6, 0x9d, 0xef, 0x86, 0x10, 0xcf, 0x26,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0xfc, 0x22, 0xd9, 0x1f, 0x5f, 0x86, 0x25, 0xe7,
+ 0x5e, 0x55, 0x48, 0x35, 0xec, 0x32, 0x37, 0x6d,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0x98, 0xbc, 0x07, 0x72, 0xa2, 0xe7, 0xa7, 0x66,
+ 0x64, 0xf7, 0x29, 0x3a, 0xaf, 0x52, 0x18, 0x04,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0xd3, 0x36, 0xb9, 0x69, 0x6a, 0x6d, 0x55, 0xbc,
+ 0x82, 0xdf, 0x1c, 0x04, 0xa7, 0xd5, 0x00, 0x68,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0xb9, 0x03, 0xbf, 0xd9, 0x86, 0x5a, 0x1a, 0xb4,
+ 0xdc, 0xe6, 0x8f, 0x9b, 0xa4, 0xa8, 0x2a, 0x12,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0xfe, 0x14, 0xab, 0x1c, 0xfd, 0x36, 0x64, 0x38,
+ 0xc1, 0xf8, 0xdd, 0xcd, 0xf4, 0x77, 0xa1, 0xb8,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0x2e, 0x70, 0x54, 0xdc, 0xa6, 0xae, 0xb2, 0xcd,
+ 0x4a, 0x26, 0x97, 0xf8, 0xbf, 0xb4, 0xb4, 0x52,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0x1e, 0x27, 0x73, 0x94, 0x44, 0xfc, 0xd4, 0x44,
+ 0xbf, 0x5b, 0x7d, 0x5d, 0x6d, 0x13, 0x68, 0xb1,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0xeb, 0xfd, 0x0b, 0xa1, 0x7b, 0xda, 0x61, 0xdc,
+ 0x6d, 0xe4, 0x3b, 0x51, 0xa7, 0x09, 0x29, 0x6d,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0x38, 0x2b, 0x23, 0xb9, 0x18, 0x2d, 0xb9, 0x0b,
+ 0xe7, 0x4d, 0x20, 0x83, 0xab, 0x17, 0xfd, 0x88,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0x65, 0x60, 0x85, 0xef, 0x0e, 0x9a, 0x23, 0x96,
+ 0xe7, 0xa9, 0xee, 0xba, 0x9e, 0x48, 0xb9, 0x1c,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0x8b, 0xa8, 0x7a, 0x33, 0x15, 0x1e, 0xa7, 0x78,
+ 0x27, 0x01, 0x3e, 0x90, 0x43, 0x47, 0x5a, 0x9d,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0x76, 0xf1, 0x21, 0x67, 0x94, 0x20, 0x6f, 0xc7,
+ 0x84, 0xc8, 0xdb, 0x07, 0xdb, 0x77, 0xdd, 0x50,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0x4e, 0x7f, 0x83, 0x8e, 0xa6, 0x28, 0xaa, 0x46,
+ 0xa2, 0x69, 0x95, 0x3b, 0xf0, 0x71, 0x14, 0x24,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0x93, 0x0b, 0x4d, 0xbe, 0x49, 0x36, 0xa0, 0x26,
+ 0xe9, 0x18, 0x4e, 0xc8, 0x19, 0x59, 0xc1, 0x7d,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0x11, 0xa9, 0xce, 0x26, 0x0e, 0x2f, 0x11, 0x0e,
+ 0xc1, 0xbd, 0x68, 0x80, 0xc8, 0xf8, 0x41, 0x65,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0xb6, 0x3d, 0x6b, 0x62, 0xb5, 0x37, 0x31, 0x28,
+ 0x79, 0xc4, 0xe2, 0x62, 0xbb, 0x63, 0xf9, 0x91,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0x5f, 0x55, 0xb5, 0xa4, 0x80, 0xa8, 0x54, 0x47,
+ 0xa7, 0x79, 0x87, 0x12, 0x2e, 0x44, 0x92, 0x42,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0x01, 0x69, 0xa2, 0xac, 0xd6, 0x62, 0x8a, 0x64,
+ 0xa2, 0x0b, 0xd0, 0xb4, 0x0e, 0x68, 0xe0, 0x88,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0x75, 0x1e, 0x56, 0xd0, 0xcb, 0x06, 0xfd, 0x51,
+ 0x55, 0xae, 0x77, 0xa4, 0xf2, 0xe7, 0x86, 0x3c,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0xff, 0xab, 0x8a, 0x7d, 0xb7, 0x40, 0xe5, 0x07,
+ 0xfe, 0x8f, 0x74, 0xdb, 0x2c, 0x35, 0x35, 0x12,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0x1f, 0x2a, 0xed, 0xcd, 0x6b, 0x87, 0xea, 0xa2,
+ 0xf8, 0xd8, 0xad, 0x04, 0x23, 0xc7, 0x5d, 0x47,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0x5b, 0x18, 0x2d, 0x96, 0x3b, 0xf6, 0xdc, 0x82,
+ 0x3b, 0xfa, 0xc9, 0x81, 0xc7, 0x33, 0xa0, 0x07,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0xd1, 0x3a, 0x82, 0xce, 0x31, 0x75, 0xa2, 0xbf,
+ 0x6f, 0x12, 0xf2, 0xac, 0xf6, 0xcc, 0xea, 0x34,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0xcf, 0x11, 0x3d, 0x44, 0x10, 0x0d, 0x26, 0x32,
+ 0xa5, 0x61, 0x13, 0xfd, 0xb8, 0xed, 0x31, 0x53,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0x67, 0x14, 0x8a, 0xf6, 0xc8, 0xb8, 0x73, 0x6b,
+ 0xb2, 0xec, 0xa9, 0x61, 0xaa, 0xc0, 0xc9, 0x28,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0xa5, 0xbf, 0x00, 0x07, 0x48, 0xff, 0x30, 0x36,
+ 0x20, 0x83, 0xd7, 0xd6, 0xd0, 0x90, 0x46, 0x03,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0x75, 0x99, 0x9a, 0xa3, 0xad, 0x9a, 0xe5, 0x9d,
+ 0x2f, 0x21, 0xdb, 0x72, 0x2f, 0xaf, 0xb8, 0x79,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0xa3, 0xb7, 0xb7, 0x46, 0x39, 0x99, 0xc2, 0x82,
+ 0xe9, 0x31, 0x8d, 0xc2, 0x28, 0x1b, 0x86, 0x91,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0x46, 0x2f, 0xc8, 0x0e, 0x2c, 0x70, 0x3a, 0xdb,
+ 0x25, 0x2f, 0xce, 0xe6, 0x15, 0x1f, 0x9a, 0x06,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0x9a, 0xa4, 0xe0, 0x03, 0x3a, 0xb5, 0x43, 0x75,
+ 0x8e, 0x93, 0x35, 0x25, 0xe6, 0x5e, 0x9d, 0x7f,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x1f, 0x01, 0x32, 0x56, 0x64, 0x45, 0xc5, 0x20,
+ 0xd4, 0xad, 0x13, 0x8f, 0xbe, 0x82, 0xc8, 0x01,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0xd4, 0x3f, 0xa4, 0xc9, 0xe9, 0x2e, 0x62, 0x77,
+ 0x4e, 0x21, 0x55, 0xd8, 0xde, 0x31, 0xf5, 0xea,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x4e, 0x48, 0x88, 0x4e, 0x4f, 0x74, 0x7e, 0xec,
+ 0x99, 0x5d, 0xb1, 0xcb, 0x84, 0x88, 0x80, 0xe9,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0x1a, 0x84, 0xfa, 0x2f, 0xd7, 0x3c, 0x5f, 0xee,
+ 0x3e, 0x81, 0xc0, 0x4b, 0x35, 0x4b, 0x7e, 0x98,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0xe3, 0x3a, 0xc5, 0x2f, 0x9f, 0x91, 0x93, 0xfb,
+ 0xcb, 0xd8, 0x53, 0x63, 0xab, 0xc4, 0xa5, 0x85,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0xa0, 0xcf, 0xad, 0x30, 0x2d, 0xec, 0xea, 0x81,
+ 0xfd, 0x7f, 0xcf, 0x7c, 0x70, 0xc9, 0x89, 0x7b,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0xe1, 0x64, 0x22, 0x19, 0x41, 0x44, 0x37, 0x2b,
+ 0x92, 0x60, 0xa4, 0x1f, 0xd6, 0x53, 0xe0, 0xa0,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0x08, 0xfa, 0xa4, 0xf8, 0x04, 0x08, 0xb8, 0x9f,
+ 0x61, 0xb5, 0x68, 0xaf, 0x31, 0x12, 0x8d, 0x3f,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0xad, 0x76, 0xc3, 0x1a, 0x4c, 0x64, 0x2c, 0x11,
+ 0x5e, 0x48, 0x6d, 0x41, 0xf5, 0x77, 0xc2, 0x40,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0x1b, 0xec, 0x78, 0x2b, 0xd9, 0xbe, 0x93, 0xbd,
+ 0x0b, 0x03, 0xf1, 0xd8, 0x31, 0xe8, 0x60, 0x67,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x5e, 0x22, 0x44, 0x09, 0x97, 0xf9, 0xc5, 0xc7,
+ 0x23, 0xc7, 0x74, 0x51, 0xe5, 0x9d, 0x5c, 0xed,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0xfe, 0xb2, 0x90, 0xa7, 0x06, 0xaf, 0xdd, 0x6a,
+ 0x83, 0x26, 0x3c, 0x78, 0x66, 0xe0, 0x9d, 0xd9,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0xb2, 0xa0, 0x75, 0x6f, 0x77, 0xc1, 0x0b, 0x4e,
+ 0x99, 0xfa, 0x9a, 0x02, 0xf6, 0xe4, 0x66, 0x27,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0xf9, 0xdd, 0x69, 0xae, 0xc8, 0x66, 0xa9, 0xab,
+ 0xb8, 0x01, 0x38, 0xc3, 0x2a, 0x6b, 0x94, 0x66,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0x17, 0xc9, 0xf7, 0x2d, 0xe6, 0xb7, 0x99, 0x77,
+ 0x65, 0xf7, 0x62, 0xc8, 0x0d, 0x7d, 0xbd, 0x81,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0x39, 0xef, 0xbf, 0x39, 0xfa, 0x79, 0xc3, 0x7b,
+ 0x71, 0x40, 0x3c, 0x1f, 0x67, 0xe5, 0x60, 0xe5,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x32, 0xab, 0x8b, 0xed, 0x90, 0x04, 0x5e, 0x17,
+ 0xd2, 0x5e, 0xa8, 0x91, 0xf7, 0x77, 0xe3, 0xd7,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0x6c, 0xc7, 0x14, 0x13, 0xdf, 0xfb, 0xc6, 0xed,
+ 0xa3, 0x9c, 0xa7, 0x90, 0xae, 0x4c, 0x61, 0x47,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0xc5, 0x17, 0x07, 0x35, 0x34, 0xbf, 0xc1, 0x4d,
+ 0xc4, 0x57, 0xc0, 0xd9, 0xfd, 0xe9, 0x10, 0x08,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0xbb, 0xcf, 0x41, 0xd2, 0x94, 0xea, 0xbe, 0x2f,
+ 0xde, 0xb2, 0xb4, 0x20, 0x72, 0x1c, 0xf8, 0x35,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0x59, 0x20, 0xb5, 0xdc, 0xaf, 0xc3, 0x8b, 0x32,
+ 0xe6, 0x40, 0x0f, 0x02, 0x67, 0x45, 0x49, 0x1f,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0xf5, 0x95, 0x60, 0x4c, 0x5f, 0x39, 0x54, 0xbf,
+ 0x62, 0x9e, 0x85, 0xca, 0x31, 0x9a, 0x95, 0xee,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0x36, 0x50, 0x78, 0x6b, 0x0f, 0x11, 0xe3, 0xa9,
+ 0x79, 0x3a, 0xa6, 0x9d, 0xd4, 0x8b, 0x13, 0x3f,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0xa5, 0x34, 0x5d, 0x5e, 0x43, 0x01, 0xf2, 0xe1,
+ 0x3f, 0xf2, 0x1c, 0x8b, 0x13, 0xf7, 0x17, 0x3e,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0x77, 0xa1, 0xbe, 0xbf, 0x49, 0xb8, 0x74, 0x73,
+ 0x47, 0x78, 0x2a, 0xf8, 0x66, 0x6b, 0xff, 0xd2,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0xa2, 0x05, 0x69, 0x65, 0x3f, 0xd4, 0xb4, 0xcd,
+ 0xed, 0x8c, 0x36, 0x6d, 0x51, 0x6a, 0xbb, 0xef,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0xda, 0xd8, 0x96, 0xfd, 0x1c, 0x0d, 0x1e, 0x56,
+ 0xe2, 0x62, 0xed, 0x18, 0x4b, 0xd3, 0x46, 0x48,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0xeb, 0x79, 0x5e, 0x52, 0x70, 0x25, 0xa7, 0x41,
+ 0x33, 0xfa, 0xac, 0xd3, 0x27, 0x35, 0xfc, 0x5f,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0xa8, 0x9c, 0xb9, 0xcd, 0x13, 0xb8, 0xdd, 0xd2,
+ 0x09, 0xd6, 0xc8, 0x12, 0xc3, 0x69, 0x9a, 0x64,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0x06, 0xe3, 0x8a, 0xef, 0xe4, 0x42, 0xae, 0x86,
+ 0xef, 0x58, 0x80, 0xe8, 0xe3, 0xa2, 0x09, 0x44,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x6f, 0xa5, 0x37, 0x06, 0x4a, 0x89, 0x98, 0x39,
+ 0xf6, 0x69, 0x48, 0x56, 0x17, 0x6d, 0x44, 0x7c,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x82, 0x48, 0xd4, 0x9e, 0xb8, 0x3c, 0xb4, 0xdc,
+ 0x44, 0xcb, 0x19, 0xdb, 0xcb, 0xa2, 0x00, 0x5d,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62, 0x0d,
+ 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7, 0x07,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xda, 0x6b, 0x27, 0xa0, 0xac, 0x71, 0xf0, 0xc3,
+ 0x75, 0x51, 0xf6, 0x21, 0x94, 0xec, 0x81, 0x92,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x49, 0x5b, 0x11, 0xb3, 0x4c, 0x1a, 0x23, 0x5c,
+ 0x61, 0x4f, 0xe3, 0x08, 0xf9, 0x47, 0x8b, 0xdc,
+ },
+ },
+ .ltk = {
+ 0x5a, 0x49, 0x28, 0xf0, 0x11, 0x3b, 0x6f, 0x6b,
+ 0x3a, 0x69, 0x6d, 0xdd, 0xb2, 0xe5, 0xa8, 0x97,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_DISP,
+ .passkey = 4915,
+ },
+ },
+ };
+ ble_sm_test_util_peer_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: just works
+ * Initiator IO capabilities: 3
+ * Responder IO capabilities: 3
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 3
+ * Responder key distribution: 3
+ */
+TEST_CASE_SELF(ble_sm_sc_us_jw_iio3_rio3_b1_iat2_rat2_ik3_rk3)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0x46, 0x85, 0x37, 0x90, 0x86, 0x58,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0x6d, 0x59, 0x7d, 0xa9, 0x87, 0x74,
+ },
+ .pair_req = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .pair_rsp = {
+ .io_cap = 0x03,
+ .oob_data_flag = 0x00,
+ .authreq = 0x09,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .our_priv_key = {
+ 0xdb, 0x24, 0x2e, 0x91, 0xda, 0xaa, 0x33, 0x33,
+ 0x23, 0xa2, 0x1e, 0xbe, 0x06, 0x69, 0xdb, 0xad,
+ 0xa9, 0x2a, 0x91, 0xb1, 0x24, 0x0a, 0xc7, 0xaf,
+ 0x50, 0x0c, 0x65, 0x5b, 0x97, 0x1e, 0x12, 0x10,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x32, 0x5b, 0xee, 0x46, 0x42, 0x63, 0xca, 0x86,
+ 0x2d, 0xe7, 0xd2, 0x75, 0x23, 0x7b, 0x4d, 0x59,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xd4, 0x66, 0x94, 0xc9, 0x96, 0xd0, 0x28, 0x96,
+ 0x1c, 0xa1, 0x3b, 0xf7, 0x15, 0x95, 0x95, 0x43,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0xb7, 0x98, 0xac, 0x85, 0xc4, 0x0a, 0x69, 0x8d,
+ 0xa6, 0xaf, 0xf3, 0x1f, 0x63, 0x3c, 0xf2, 0x33,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x1a, 0xc7, 0x0b, 0xfe, 0xc0, 0x55, 0xc3, 0xdb,
+ 0x94, 0x00, 0x89, 0x4f, 0x0e, 0x64, 0x05, 0xcd,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0xf2, 0x45, 0x41, 0xc0, 0xba, 0x8d, 0x58, 0xec,
+ 0x61, 0xfb, 0x48, 0x71, 0xb4, 0x0e, 0x7b, 0x19,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .ltk = {
+ 0x8b, 0xb6, 0xf6, 0x5a, 0x52, 0x7b, 0xb8, 0xf4,
+ 0xb8, 0x4c, 0xe7, 0x60, 0x4f, 0x0b, 0x88, 0xfe,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_JW,
+ .authenticated = 0,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NONE,
+ },
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: numeric comparison
+ * Initiator IO capabilities: 1
+ * Responder IO capabilities: 1
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 3
+ * Responder key distribution: 3
+ */
+TEST_CASE_SELF(ble_sm_sc_us_nc_iio1_rio1_b1_iat2_rat2_ik3_rk3)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0xc5, 0xf3, 0x5d, 0x83, 0xcd, 0x4a,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0x9f, 0x56, 0x57, 0x5e, 0x12, 0x65,
+ },
+ .pair_req = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .pair_rsp = {
+ .io_cap = 0x01,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x03,
+ .resp_key_dist = 0x03,
+ },
+ .our_priv_key = {
+ 0xdb, 0x24, 0x2e, 0x91, 0xda, 0xaa, 0x33, 0x33,
+ 0x23, 0xa2, 0x1e, 0xbe, 0x06, 0x69, 0xdb, 0xad,
+ 0xa9, 0x2a, 0x91, 0xb1, 0x24, 0x0a, 0xc7, 0xaf,
+ 0x50, 0x0c, 0x65, 0x5b, 0x97, 0x1e, 0x12, 0x10,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x39, 0xba, 0x86, 0x47, 0x06, 0x87, 0x14, 0xe4,
+ 0x5c, 0x82, 0xe9, 0x6a, 0x80, 0xca, 0x87, 0xcd,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0xce, 0xe2, 0xa3, 0x29, 0x8a, 0xc6, 0x76, 0x1d,
+ 0xa2, 0xfd, 0xe0, 0x7f, 0x8c, 0xbe, 0xf8, 0x1d,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x3d, 0xac, 0xf0, 0xfe, 0x7c, 0x78, 0x73, 0x03,
+ 0xe2, 0xb6, 0x59, 0x7e, 0x80, 0xb4, 0x69, 0x07,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0xaa, 0x95, 0x9f, 0x33, 0x32, 0xa1, 0xbd, 0xf9,
+ 0xef, 0xb9, 0x3d, 0xfb, 0x08, 0xd1, 0x28, 0xa0,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x3c, 0x10, 0x17, 0x76, 0x55, 0x65, 0x6f, 0x14,
+ 0xfa, 0x80, 0xd3, 0x52, 0x04, 0x82, 0xe2, 0xf7,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0xd4, 0x66, 0x94, 0xc9, 0x96, 0xd0, 0x28, 0x96,
+ 0x1c, 0xa1, 0x3b, 0xf7, 0x15, 0x95, 0x95, 0x43,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xb7, 0x98, 0xac, 0x85, 0xc4, 0x0a, 0x69, 0x8d,
+ 0xa6, 0xaf, 0xf3, 0x1f, 0x63, 0x3c, 0xf2, 0x33,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .ltk = {
+ 0x95, 0x46, 0xe6, 0x8e, 0x52, 0xcc, 0x05, 0xca,
+ 0xf4, 0x59, 0x57, 0x54, 0x8c, 0x0d, 0x51, 0xfc,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_NUMCMP,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_NUMCMP,
+ .numcmp_accept = 1,
+ },
+ .exp_numcmp = 70210,
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/**
+ * Secure connections pairing
+ * Master: us
+ * Pair algorithm: passkey entry
+ * Initiator IO capabilities: 2
+ * Responder IO capabilities: 0
+ * Bonding: true
+ * Initiator address type: BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
+ * Responder address type: BLE_ADDR_PUBLIC_ID
+ * Initiator key distribution: 7
+ * Responder key distribution: 3
+ */
+TEST_CASE_SELF(ble_sm_sc_us_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3)
+{
+ struct ble_sm_test_params params;
+
+ params = (struct ble_sm_test_params) {
+ .init_addr_type = BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
+ .init_id_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ .init_rpa = {
+ 0x6e, 0x56, 0x09, 0xef, 0x1e, 0x76,
+ },
+ .resp_addr_type = BLE_ADDR_PUBLIC_ID,
+ .resp_id_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ .resp_rpa = {
+ 0xb5, 0x29, 0xdf, 0xb4, 0x9b, 0x62,
+ },
+ .pair_req = {
+ .io_cap = 0x02,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x03,
+ },
+ .pair_rsp = {
+ .io_cap = 0x00,
+ .oob_data_flag = 0x00,
+ .authreq = 0x0d,
+ .max_enc_key_size = 0x10,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x03,
+ },
+ .our_priv_key = {
+ 0xdb, 0x24, 0x2e, 0x91, 0xda, 0xaa, 0x33, 0x33,
+ 0x23, 0xa2, 0x1e, 0xbe, 0x06, 0x69, 0xdb, 0xad,
+ 0xa9, 0x2a, 0x91, 0xb1, 0x24, 0x0a, 0xc7, 0xaf,
+ 0x50, 0x0c, 0x65, 0x5b, 0x97, 0x1e, 0x12, 0x10,
+ },
+ .public_key_req = {
+ .x = {
+ 0x54, 0xd9, 0x8f, 0xeb, 0xc1, 0xbb, 0xe6, 0x74,
+ 0x8a, 0x55, 0x3a, 0x80, 0x0e, 0xef, 0x90, 0xc9,
+ 0xab, 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62,
+ 0x0d, 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7,
+ },
+ .y = {
+ 0x07, 0x33, 0x91, 0x40, 0xde, 0x25, 0xb4, 0x3d,
+ 0x81, 0x2f, 0xd2, 0x41, 0x98, 0xe7, 0xaf, 0x0f,
+ 0x5f, 0x17, 0x85, 0x1f, 0x75, 0x6e, 0xf4, 0x0e,
+ 0x05, 0x19, 0x7f, 0x03, 0x9b, 0xf4, 0x41, 0x23,
+ },
+ },
+ .public_key_rsp = {
+ .x = {
+ 0x1d, 0x44, 0x66, 0x0d, 0x3a, 0x03, 0x71, 0x17,
+ 0xb3, 0x10, 0x2e, 0xf0, 0xd3, 0xf8, 0xa2, 0x6c,
+ 0x1f, 0xfc, 0xbf, 0x02, 0x62, 0x6b, 0x11, 0x5a,
+ 0x76, 0x5b, 0x30, 0x20, 0xb1, 0xef, 0xb3, 0x76,
+ },
+ .y = {
+ 0xf1, 0x23, 0x63, 0x75, 0xfc, 0xb6, 0xc9, 0x32,
+ 0xa4, 0x36, 0xbe, 0x18, 0xa0, 0x7d, 0x0b, 0x16,
+ 0x65, 0x24, 0xd0, 0xe3, 0x74, 0x1b, 0x34, 0x1a,
+ 0xf9, 0xe2, 0xcb, 0x30, 0x93, 0x88, 0xd7, 0xfa,
+ },
+ },
+ .confirm_req[0] = {
+ .value = {
+ 0x12, 0xe3, 0x01, 0xd0, 0x30, 0x59, 0xca, 0xd9,
+ 0x78, 0x0b, 0x45, 0x73, 0xb1, 0x7a, 0x4d, 0xca,
+ },
+ },
+ .confirm_rsp[0] = {
+ .value = {
+ 0x47, 0x68, 0x16, 0x24, 0xd4, 0x07, 0x60, 0x6c,
+ 0xa5, 0x47, 0x6f, 0x05, 0x78, 0x71, 0x3e, 0xa8,
+ },
+ },
+ .random_req[0] = {
+ .value = {
+ 0x2a, 0x29, 0xa8, 0xef, 0x0b, 0x70, 0x5f, 0x1b,
+ 0x81, 0x4d, 0x97, 0xff, 0xfb, 0x7f, 0x30, 0x90,
+ },
+ },
+ .random_rsp[0] = {
+ .value = {
+ 0x12, 0x9e, 0x1d, 0x12, 0x11, 0x44, 0x36, 0x74,
+ 0xa3, 0x0c, 0xea, 0x36, 0x4d, 0xdf, 0x2d, 0x5d,
+ },
+ },
+ .confirm_req[1] = {
+ .value = {
+ 0x4d, 0x6a, 0x32, 0xfe, 0xe2, 0xa0, 0xdd, 0x92,
+ 0x60, 0x5c, 0x82, 0x7f, 0xa6, 0xa6, 0x24, 0xd6,
+ },
+ },
+ .confirm_rsp[1] = {
+ .value = {
+ 0xd5, 0x3e, 0xa7, 0xa0, 0xbf, 0x39, 0x8e, 0xfe,
+ 0xfd, 0x73, 0x47, 0x4c, 0x92, 0x8b, 0x74, 0x06,
+ },
+ },
+ .random_req[1] = {
+ .value = {
+ 0xc1, 0x88, 0xdf, 0xb0, 0x99, 0xbb, 0xbf, 0xed,
+ 0xdc, 0x40, 0x66, 0x55, 0xbe, 0x91, 0x56, 0x9a,
+ },
+ },
+ .random_rsp[1] = {
+ .value = {
+ 0xed, 0xed, 0x9a, 0x61, 0xb8, 0x21, 0x03, 0x77,
+ 0xa6, 0xcf, 0x34, 0x65, 0x8c, 0x18, 0x82, 0x9f,
+ },
+ },
+ .confirm_req[2] = {
+ .value = {
+ 0xdb, 0xea, 0x94, 0x29, 0xe4, 0x44, 0x7d, 0x7b,
+ 0xd3, 0x16, 0x81, 0x8e, 0xaf, 0xe6, 0x9c, 0x85,
+ },
+ },
+ .confirm_rsp[2] = {
+ .value = {
+ 0x3f, 0xdd, 0x54, 0x76, 0xab, 0x45, 0x7f, 0x53,
+ 0x64, 0x6b, 0x37, 0xa6, 0xc7, 0xc6, 0x4a, 0x73,
+ },
+ },
+ .random_req[2] = {
+ .value = {
+ 0x5a, 0xf1, 0xfb, 0xde, 0xb3, 0xbe, 0x6e, 0xac,
+ 0x68, 0x51, 0x47, 0x8e, 0x0b, 0xcd, 0xc1, 0xa0,
+ },
+ },
+ .random_rsp[2] = {
+ .value = {
+ 0x29, 0x0f, 0x5e, 0x83, 0x87, 0xca, 0xd3, 0x21,
+ 0xa7, 0x7e, 0x3d, 0x78, 0x47, 0x54, 0xf8, 0xe4,
+ },
+ },
+ .confirm_req[3] = {
+ .value = {
+ 0xca, 0x3e, 0xd5, 0xe3, 0x59, 0xb0, 0x5d, 0x1e,
+ 0x0f, 0x4c, 0x95, 0x0f, 0x6a, 0x72, 0xcf, 0x25,
+ },
+ },
+ .confirm_rsp[3] = {
+ .value = {
+ 0x2f, 0x4d, 0x06, 0x40, 0x09, 0x68, 0x68, 0x45,
+ 0x87, 0x79, 0x78, 0x48, 0xda, 0xe4, 0xf5, 0xae,
+ },
+ },
+ .random_req[3] = {
+ .value = {
+ 0x63, 0x5a, 0xee, 0x91, 0xe4, 0xf8, 0xe8, 0x69,
+ 0xd1, 0x46, 0x18, 0x0d, 0xd2, 0x94, 0xd8, 0x20,
+ },
+ },
+ .random_rsp[3] = {
+ .value = {
+ 0x76, 0x36, 0xf5, 0xc2, 0x41, 0xb6, 0x3c, 0x1f,
+ 0x36, 0x19, 0x58, 0xce, 0x8f, 0x41, 0xeb, 0x8c,
+ },
+ },
+ .confirm_req[4] = {
+ .value = {
+ 0x76, 0xfd, 0x84, 0x0f, 0x0f, 0x58, 0x70, 0x45,
+ 0x41, 0x33, 0x5d, 0xce, 0xe5, 0xe2, 0x2f, 0x83,
+ },
+ },
+ .confirm_rsp[4] = {
+ .value = {
+ 0x87, 0xcf, 0xdf, 0xa5, 0x60, 0x82, 0x4f, 0x09,
+ 0x4c, 0x50, 0x24, 0xba, 0x91, 0x96, 0x0d, 0x65,
+ },
+ },
+ .random_req[4] = {
+ .value = {
+ 0x67, 0xdb, 0x73, 0x1e, 0x57, 0x5c, 0xb7, 0x86,
+ 0xf8, 0xaf, 0x58, 0xd8, 0x0f, 0x97, 0x47, 0xce,
+ },
+ },
+ .random_rsp[4] = {
+ .value = {
+ 0xaa, 0x99, 0x90, 0x05, 0x11, 0xfc, 0xc2, 0xd9,
+ 0xb8, 0xd6, 0x9d, 0xef, 0x86, 0x10, 0xcf, 0x26,
+ },
+ },
+ .confirm_req[5] = {
+ .value = {
+ 0xfc, 0x22, 0xd9, 0x1f, 0x5f, 0x86, 0x25, 0xe7,
+ 0x5e, 0x55, 0x48, 0x35, 0xec, 0x32, 0x37, 0x6d,
+ },
+ },
+ .confirm_rsp[5] = {
+ .value = {
+ 0x98, 0xbc, 0x07, 0x72, 0xa2, 0xe7, 0xa7, 0x66,
+ 0x64, 0xf7, 0x29, 0x3a, 0xaf, 0x52, 0x18, 0x04,
+ },
+ },
+ .random_req[5] = {
+ .value = {
+ 0xd3, 0x36, 0xb9, 0x69, 0x6a, 0x6d, 0x55, 0xbc,
+ 0x82, 0xdf, 0x1c, 0x04, 0xa7, 0xd5, 0x00, 0x68,
+ },
+ },
+ .random_rsp[5] = {
+ .value = {
+ 0xb9, 0x03, 0xbf, 0xd9, 0x86, 0x5a, 0x1a, 0xb4,
+ 0xdc, 0xe6, 0x8f, 0x9b, 0xa4, 0xa8, 0x2a, 0x12,
+ },
+ },
+ .confirm_req[6] = {
+ .value = {
+ 0xfe, 0x14, 0xab, 0x1c, 0xfd, 0x36, 0x64, 0x38,
+ 0xc1, 0xf8, 0xdd, 0xcd, 0xf4, 0x77, 0xa1, 0xb8,
+ },
+ },
+ .confirm_rsp[6] = {
+ .value = {
+ 0x2e, 0x70, 0x54, 0xdc, 0xa6, 0xae, 0xb2, 0xcd,
+ 0x4a, 0x26, 0x97, 0xf8, 0xbf, 0xb4, 0xb4, 0x52,
+ },
+ },
+ .random_req[6] = {
+ .value = {
+ 0x1e, 0x27, 0x73, 0x94, 0x44, 0xfc, 0xd4, 0x44,
+ 0xbf, 0x5b, 0x7d, 0x5d, 0x6d, 0x13, 0x68, 0xb1,
+ },
+ },
+ .random_rsp[6] = {
+ .value = {
+ 0xeb, 0xfd, 0x0b, 0xa1, 0x7b, 0xda, 0x61, 0xdc,
+ 0x6d, 0xe4, 0x3b, 0x51, 0xa7, 0x09, 0x29, 0x6d,
+ },
+ },
+ .confirm_req[7] = {
+ .value = {
+ 0x38, 0x2b, 0x23, 0xb9, 0x18, 0x2d, 0xb9, 0x0b,
+ 0xe7, 0x4d, 0x20, 0x83, 0xab, 0x17, 0xfd, 0x88,
+ },
+ },
+ .confirm_rsp[7] = {
+ .value = {
+ 0x65, 0x60, 0x85, 0xef, 0x0e, 0x9a, 0x23, 0x96,
+ 0xe7, 0xa9, 0xee, 0xba, 0x9e, 0x48, 0xb9, 0x1c,
+ },
+ },
+ .random_req[7] = {
+ .value = {
+ 0x8b, 0xa8, 0x7a, 0x33, 0x15, 0x1e, 0xa7, 0x78,
+ 0x27, 0x01, 0x3e, 0x90, 0x43, 0x47, 0x5a, 0x9d,
+ },
+ },
+ .random_rsp[7] = {
+ .value = {
+ 0x76, 0xf1, 0x21, 0x67, 0x94, 0x20, 0x6f, 0xc7,
+ 0x84, 0xc8, 0xdb, 0x07, 0xdb, 0x77, 0xdd, 0x50,
+ },
+ },
+ .confirm_req[8] = {
+ .value = {
+ 0x4e, 0x7f, 0x83, 0x8e, 0xa6, 0x28, 0xaa, 0x46,
+ 0xa2, 0x69, 0x95, 0x3b, 0xf0, 0x71, 0x14, 0x24,
+ },
+ },
+ .confirm_rsp[8] = {
+ .value = {
+ 0x93, 0x0b, 0x4d, 0xbe, 0x49, 0x36, 0xa0, 0x26,
+ 0xe9, 0x18, 0x4e, 0xc8, 0x19, 0x59, 0xc1, 0x7d,
+ },
+ },
+ .random_req[8] = {
+ .value = {
+ 0x11, 0xa9, 0xce, 0x26, 0x0e, 0x2f, 0x11, 0x0e,
+ 0xc1, 0xbd, 0x68, 0x80, 0xc8, 0xf8, 0x41, 0x65,
+ },
+ },
+ .random_rsp[8] = {
+ .value = {
+ 0xb6, 0x3d, 0x6b, 0x62, 0xb5, 0x37, 0x31, 0x28,
+ 0x79, 0xc4, 0xe2, 0x62, 0xbb, 0x63, 0xf9, 0x91,
+ },
+ },
+ .confirm_req[9] = {
+ .value = {
+ 0x5f, 0x55, 0xb5, 0xa4, 0x80, 0xa8, 0x54, 0x47,
+ 0xa7, 0x79, 0x87, 0x12, 0x2e, 0x44, 0x92, 0x42,
+ },
+ },
+ .confirm_rsp[9] = {
+ .value = {
+ 0x01, 0x69, 0xa2, 0xac, 0xd6, 0x62, 0x8a, 0x64,
+ 0xa2, 0x0b, 0xd0, 0xb4, 0x0e, 0x68, 0xe0, 0x88,
+ },
+ },
+ .random_req[9] = {
+ .value = {
+ 0x75, 0x1e, 0x56, 0xd0, 0xcb, 0x06, 0xfd, 0x51,
+ 0x55, 0xae, 0x77, 0xa4, 0xf2, 0xe7, 0x86, 0x3c,
+ },
+ },
+ .random_rsp[9] = {
+ .value = {
+ 0xff, 0xab, 0x8a, 0x7d, 0xb7, 0x40, 0xe5, 0x07,
+ 0xfe, 0x8f, 0x74, 0xdb, 0x2c, 0x35, 0x35, 0x12,
+ },
+ },
+ .confirm_req[10] = {
+ .value = {
+ 0x1f, 0x2a, 0xed, 0xcd, 0x6b, 0x87, 0xea, 0xa2,
+ 0xf8, 0xd8, 0xad, 0x04, 0x23, 0xc7, 0x5d, 0x47,
+ },
+ },
+ .confirm_rsp[10] = {
+ .value = {
+ 0x5b, 0x18, 0x2d, 0x96, 0x3b, 0xf6, 0xdc, 0x82,
+ 0x3b, 0xfa, 0xc9, 0x81, 0xc7, 0x33, 0xa0, 0x07,
+ },
+ },
+ .random_req[10] = {
+ .value = {
+ 0xd1, 0x3a, 0x82, 0xce, 0x31, 0x75, 0xa2, 0xbf,
+ 0x6f, 0x12, 0xf2, 0xac, 0xf6, 0xcc, 0xea, 0x34,
+ },
+ },
+ .random_rsp[10] = {
+ .value = {
+ 0xcf, 0x11, 0x3d, 0x44, 0x10, 0x0d, 0x26, 0x32,
+ 0xa5, 0x61, 0x13, 0xfd, 0xb8, 0xed, 0x31, 0x53,
+ },
+ },
+ .confirm_req[11] = {
+ .value = {
+ 0x67, 0x14, 0x8a, 0xf6, 0xc8, 0xb8, 0x73, 0x6b,
+ 0xb2, 0xec, 0xa9, 0x61, 0xaa, 0xc0, 0xc9, 0x28,
+ },
+ },
+ .confirm_rsp[11] = {
+ .value = {
+ 0xa5, 0xbf, 0x00, 0x07, 0x48, 0xff, 0x30, 0x36,
+ 0x20, 0x83, 0xd7, 0xd6, 0xd0, 0x90, 0x46, 0x03,
+ },
+ },
+ .random_req[11] = {
+ .value = {
+ 0x75, 0x99, 0x9a, 0xa3, 0xad, 0x9a, 0xe5, 0x9d,
+ 0x2f, 0x21, 0xdb, 0x72, 0x2f, 0xaf, 0xb8, 0x79,
+ },
+ },
+ .random_rsp[11] = {
+ .value = {
+ 0xa3, 0xb7, 0xb7, 0x46, 0x39, 0x99, 0xc2, 0x82,
+ 0xe9, 0x31, 0x8d, 0xc2, 0x28, 0x1b, 0x86, 0x91,
+ },
+ },
+ .confirm_req[12] = {
+ .value = {
+ 0x46, 0x2f, 0xc8, 0x0e, 0x2c, 0x70, 0x3a, 0xdb,
+ 0x25, 0x2f, 0xce, 0xe6, 0x15, 0x1f, 0x9a, 0x06,
+ },
+ },
+ .confirm_rsp[12] = {
+ .value = {
+ 0x9a, 0xa4, 0xe0, 0x03, 0x3a, 0xb5, 0x43, 0x75,
+ 0x8e, 0x93, 0x35, 0x25, 0xe6, 0x5e, 0x9d, 0x7f,
+ },
+ },
+ .random_req[12] = {
+ .value = {
+ 0x1f, 0x01, 0x32, 0x56, 0x64, 0x45, 0xc5, 0x20,
+ 0xd4, 0xad, 0x13, 0x8f, 0xbe, 0x82, 0xc8, 0x01,
+ },
+ },
+ .random_rsp[12] = {
+ .value = {
+ 0xd4, 0x3f, 0xa4, 0xc9, 0xe9, 0x2e, 0x62, 0x77,
+ 0x4e, 0x21, 0x55, 0xd8, 0xde, 0x31, 0xf5, 0xea,
+ },
+ },
+ .confirm_req[13] = {
+ .value = {
+ 0x4e, 0x48, 0x88, 0x4e, 0x4f, 0x74, 0x7e, 0xec,
+ 0x99, 0x5d, 0xb1, 0xcb, 0x84, 0x88, 0x80, 0xe9,
+ },
+ },
+ .confirm_rsp[13] = {
+ .value = {
+ 0x1a, 0x84, 0xfa, 0x2f, 0xd7, 0x3c, 0x5f, 0xee,
+ 0x3e, 0x81, 0xc0, 0x4b, 0x35, 0x4b, 0x7e, 0x98,
+ },
+ },
+ .random_req[13] = {
+ .value = {
+ 0xe3, 0x3a, 0xc5, 0x2f, 0x9f, 0x91, 0x93, 0xfb,
+ 0xcb, 0xd8, 0x53, 0x63, 0xab, 0xc4, 0xa5, 0x85,
+ },
+ },
+ .random_rsp[13] = {
+ .value = {
+ 0xa0, 0xcf, 0xad, 0x30, 0x2d, 0xec, 0xea, 0x81,
+ 0xfd, 0x7f, 0xcf, 0x7c, 0x70, 0xc9, 0x89, 0x7b,
+ },
+ },
+ .confirm_req[14] = {
+ .value = {
+ 0xe1, 0x64, 0x22, 0x19, 0x41, 0x44, 0x37, 0x2b,
+ 0x92, 0x60, 0xa4, 0x1f, 0xd6, 0x53, 0xe0, 0xa0,
+ },
+ },
+ .confirm_rsp[14] = {
+ .value = {
+ 0x08, 0xfa, 0xa4, 0xf8, 0x04, 0x08, 0xb8, 0x9f,
+ 0x61, 0xb5, 0x68, 0xaf, 0x31, 0x12, 0x8d, 0x3f,
+ },
+ },
+ .random_req[14] = {
+ .value = {
+ 0xad, 0x76, 0xc3, 0x1a, 0x4c, 0x64, 0x2c, 0x11,
+ 0x5e, 0x48, 0x6d, 0x41, 0xf5, 0x77, 0xc2, 0x40,
+ },
+ },
+ .random_rsp[14] = {
+ .value = {
+ 0x1b, 0xec, 0x78, 0x2b, 0xd9, 0xbe, 0x93, 0xbd,
+ 0x0b, 0x03, 0xf1, 0xd8, 0x31, 0xe8, 0x60, 0x67,
+ },
+ },
+ .confirm_req[15] = {
+ .value = {
+ 0x5e, 0x22, 0x44, 0x09, 0x97, 0xf9, 0xc5, 0xc7,
+ 0x23, 0xc7, 0x74, 0x51, 0xe5, 0x9d, 0x5c, 0xed,
+ },
+ },
+ .confirm_rsp[15] = {
+ .value = {
+ 0xfe, 0xb2, 0x90, 0xa7, 0x06, 0xaf, 0xdd, 0x6a,
+ 0x83, 0x26, 0x3c, 0x78, 0x66, 0xe0, 0x9d, 0xd9,
+ },
+ },
+ .random_req[15] = {
+ .value = {
+ 0xb2, 0xa0, 0x75, 0x6f, 0x77, 0xc1, 0x0b, 0x4e,
+ 0x99, 0xfa, 0x9a, 0x02, 0xf6, 0xe4, 0x66, 0x27,
+ },
+ },
+ .random_rsp[15] = {
+ .value = {
+ 0xf9, 0xdd, 0x69, 0xae, 0xc8, 0x66, 0xa9, 0xab,
+ 0xb8, 0x01, 0x38, 0xc3, 0x2a, 0x6b, 0x94, 0x66,
+ },
+ },
+ .confirm_req[16] = {
+ .value = {
+ 0x17, 0xc9, 0xf7, 0x2d, 0xe6, 0xb7, 0x99, 0x77,
+ 0x65, 0xf7, 0x62, 0xc8, 0x0d, 0x7d, 0xbd, 0x81,
+ },
+ },
+ .confirm_rsp[16] = {
+ .value = {
+ 0x39, 0xef, 0xbf, 0x39, 0xfa, 0x79, 0xc3, 0x7b,
+ 0x71, 0x40, 0x3c, 0x1f, 0x67, 0xe5, 0x60, 0xe5,
+ },
+ },
+ .random_req[16] = {
+ .value = {
+ 0x32, 0xab, 0x8b, 0xed, 0x90, 0x04, 0x5e, 0x17,
+ 0xd2, 0x5e, 0xa8, 0x91, 0xf7, 0x77, 0xe3, 0xd7,
+ },
+ },
+ .random_rsp[16] = {
+ .value = {
+ 0x6c, 0xc7, 0x14, 0x13, 0xdf, 0xfb, 0xc6, 0xed,
+ 0xa3, 0x9c, 0xa7, 0x90, 0xae, 0x4c, 0x61, 0x47,
+ },
+ },
+ .confirm_req[17] = {
+ .value = {
+ 0xc5, 0x17, 0x07, 0x35, 0x34, 0xbf, 0xc1, 0x4d,
+ 0xc4, 0x57, 0xc0, 0xd9, 0xfd, 0xe9, 0x10, 0x08,
+ },
+ },
+ .confirm_rsp[17] = {
+ .value = {
+ 0xbb, 0xcf, 0x41, 0xd2, 0x94, 0xea, 0xbe, 0x2f,
+ 0xde, 0xb2, 0xb4, 0x20, 0x72, 0x1c, 0xf8, 0x35,
+ },
+ },
+ .random_req[17] = {
+ .value = {
+ 0x59, 0x20, 0xb5, 0xdc, 0xaf, 0xc3, 0x8b, 0x32,
+ 0xe6, 0x40, 0x0f, 0x02, 0x67, 0x45, 0x49, 0x1f,
+ },
+ },
+ .random_rsp[17] = {
+ .value = {
+ 0xf5, 0x95, 0x60, 0x4c, 0x5f, 0x39, 0x54, 0xbf,
+ 0x62, 0x9e, 0x85, 0xca, 0x31, 0x9a, 0x95, 0xee,
+ },
+ },
+ .confirm_req[18] = {
+ .value = {
+ 0x36, 0x50, 0x78, 0x6b, 0x0f, 0x11, 0xe3, 0xa9,
+ 0x79, 0x3a, 0xa6, 0x9d, 0xd4, 0x8b, 0x13, 0x3f,
+ },
+ },
+ .confirm_rsp[18] = {
+ .value = {
+ 0xa5, 0x34, 0x5d, 0x5e, 0x43, 0x01, 0xf2, 0xe1,
+ 0x3f, 0xf2, 0x1c, 0x8b, 0x13, 0xf7, 0x17, 0x3e,
+ },
+ },
+ .random_req[18] = {
+ .value = {
+ 0x77, 0xa1, 0xbe, 0xbf, 0x49, 0xb8, 0x74, 0x73,
+ 0x47, 0x78, 0x2a, 0xf8, 0x66, 0x6b, 0xff, 0xd2,
+ },
+ },
+ .random_rsp[18] = {
+ .value = {
+ 0xa2, 0x05, 0x69, 0x65, 0x3f, 0xd4, 0xb4, 0xcd,
+ 0xed, 0x8c, 0x36, 0x6d, 0x51, 0x6a, 0xbb, 0xef,
+ },
+ },
+ .confirm_req[19] = {
+ .value = {
+ 0xda, 0xd8, 0x96, 0xfd, 0x1c, 0x0d, 0x1e, 0x56,
+ 0xe2, 0x62, 0xed, 0x18, 0x4b, 0xd3, 0x46, 0x48,
+ },
+ },
+ .confirm_rsp[19] = {
+ .value = {
+ 0xeb, 0x79, 0x5e, 0x52, 0x70, 0x25, 0xa7, 0x41,
+ 0x33, 0xfa, 0xac, 0xd3, 0x27, 0x35, 0xfc, 0x5f,
+ },
+ },
+ .random_req[19] = {
+ .value = {
+ 0xa8, 0x9c, 0xb9, 0xcd, 0x13, 0xb8, 0xdd, 0xd2,
+ 0x09, 0xd6, 0xc8, 0x12, 0xc3, 0x69, 0x9a, 0x64,
+ },
+ },
+ .random_rsp[19] = {
+ .value = {
+ 0x06, 0xe3, 0x8a, 0xef, 0xe4, 0x42, 0xae, 0x86,
+ 0xef, 0x58, 0x80, 0xe8, 0xe3, 0xa2, 0x09, 0x44,
+ },
+ },
+ .dhkey_check_req = {
+ .value = {
+ 0x6f, 0xa5, 0x37, 0x06, 0x4a, 0x89, 0x98, 0x39,
+ 0xf6, 0x69, 0x48, 0x56, 0x17, 0x6d, 0x44, 0x7c,
+ },
+ },
+ .dhkey_check_rsp = {
+ .value = {
+ 0x82, 0x48, 0xd4, 0x9e, 0xb8, 0x3c, 0xb4, 0xdc,
+ 0x44, 0xcb, 0x19, 0xdb, 0xcb, 0xa2, 0x00, 0x5d,
+ },
+ },
+ .id_info_req = {
+ .irk = {
+ 0x79, 0x12, 0x88, 0x97, 0xd9, 0x1c, 0x62, 0x0d,
+ 0x26, 0x43, 0x7d, 0x25, 0x86, 0x79, 0xc7, 0x07,
+ },
+ },
+ .id_addr_info_req = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
+ },
+ },
+ .id_info_rsp = {
+ .irk = {
+ 0xda, 0x6b, 0x27, 0xa0, 0xac, 0x71, 0xf0, 0xc3,
+ 0x75, 0x51, 0xf6, 0x21, 0x94, 0xec, 0x81, 0x92,
+ },
+ },
+ .id_addr_info_rsp = {
+ .addr_type = 0,
+ .bd_addr = {
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
+ },
+ },
+ .sign_info_rsp = {
+ .sig_key = {
+ 0x49, 0x5b, 0x11, 0xb3, 0x4c, 0x1a, 0x23, 0x5c,
+ 0x61, 0x4f, 0xe3, 0x08, 0xf9, 0x47, 0x8b, 0xdc,
+ },
+ },
+ .ltk = {
+ 0x5a, 0x49, 0x28, 0xf0, 0x11, 0x3b, 0x6f, 0x6b,
+ 0x3a, 0x69, 0x6d, 0xdd, 0xb2, 0xe5, 0xa8, 0x97,
+ },
+ .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
+ .authenticated = 1,
+ .passkey_info = {
+ .passkey = {
+ .action = BLE_SM_IOACT_INPUT,
+ .passkey = 4915,
+ },
+ },
+ };
+ ble_sm_test_util_us_sc_good(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_sm_sc_test_suite)
+{
+ /*** No privacy. */
+
+ /* Peer as initiator. */
+ ble_sm_sc_peer_jw_iio3_rio3_b1_iat0_rat0_ik5_rk7();
+ ble_sm_sc_peer_pk_iio0_rio2_b1_iat0_rat0_ik5_rk7();
+ ble_sm_sc_peer_pk_iio2_rio0_b1_iat0_rat0_ik5_rk7();
+ ble_sm_sc_peer_nc_iio1_rio1_b1_iat0_rat0_ik5_rk7();
+
+ /* Us as initiator. */
+ ble_sm_sc_us_jw_iio3_rio4_b1_iat0_rat0_ik7_rk5();
+ ble_sm_sc_us_pk_iio2_rio4_b1_iat0_rat0_ik7_rk5();
+ ble_sm_sc_us_pk_iio0_rio4_b1_iat0_rat0_ik7_rk5();
+ ble_sm_sc_us_nc_iio1_rio4_b1_iat0_rat0_ik7_rk5();
+
+ /*** Privacy (id = public). */
+ // FIXME: needs to be fixed due to fix for address type used
+#if 0
+ /* Peer as initiator. */
+ ble_sm_sc_peer_jw_iio3_rio3_b1_iat2_rat2_ik7_rk7();
+ ble_sm_sc_peer_nc_iio1_rio1_b1_iat2_rat2_ik3_rk3();
+ ble_sm_sc_peer_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3();
+
+ /* Us as initiator. */
+ ble_sm_sc_us_jw_iio3_rio3_b1_iat2_rat2_ik3_rk3();
+ ble_sm_sc_us_nc_iio1_rio1_b1_iat2_rat2_ik3_rk3();
+ ble_sm_sc_us_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3();
+#endif
+}
+
+#endif /* NIMBLE_BLE_SM */
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test.c
new file mode 100644
index 00000000..be4285fd
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test.c
@@ -0,0 +1,414 @@
+/*
+ * 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 <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "nimble/nimble_opt.h"
+#include "host/ble_sm.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+#include "ble_sm_test_util.h"
+
+#if NIMBLE_BLE_SM
+
+/*****************************************************************************
+ * $misc *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_sm_test_case_f4)
+{
+ uint8_t u[32] = { 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 };
+ uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+ 0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+ 0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+ 0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+ uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+ 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+ uint8_t z = 0x00;
+ uint8_t exp[16] = { 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1,
+ 0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 };
+ uint8_t res[16];
+ int err;
+
+ err = ble_sm_alg_f4(u, v, x, z, res);
+ TEST_ASSERT_FATAL(err == 0);
+ TEST_ASSERT(memcmp(res, exp, 16) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_f5)
+{
+ uint8_t w[32] = { 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86,
+ 0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99,
+ 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
+ 0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec };
+ uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+ 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+ uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+ 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+ uint8_t a1t = 0x00;
+ uint8_t a1[6] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 };
+ uint8_t a2t = 0x00;
+ uint8_t a2[6] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 };
+ uint8_t exp_ltk[16] = { 0x38, 0x0a, 0x75, 0x94, 0xb5, 0x22, 0x05,
+ 0x98, 0x23, 0xcd, 0xd7, 0x69, 0x11, 0x79,
+ 0x86, 0x69 };
+ uint8_t exp_mackey[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f,
+ 0xfd, 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1,
+ 0x65, 0x29 };
+ uint8_t mackey[16], ltk[16];
+ int err;
+
+ err = ble_sm_alg_f5(w, n1, n2, a1t, a1, a2t, a2, mackey, ltk);
+ TEST_ASSERT_FATAL(err == 0);
+ TEST_ASSERT(memcmp(mackey, exp_mackey, 16) == 0);
+ TEST_ASSERT(memcmp(ltk, exp_ltk, 16) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_f6)
+{
+ uint8_t w[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd,
+ 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 };
+ uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+ 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+ uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+ 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+ uint8_t r[16] = { 0xc8, 0x0f, 0x2d, 0x0c, 0xd2, 0x42, 0xda, 0x08,
+ 0x54, 0xbb, 0x53, 0xb4, 0x3b, 0x34, 0xa3, 0x12 };
+ uint8_t io_cap[3] = { 0x02, 0x01, 0x01 };
+ uint8_t a1t = 0x00;
+ uint8_t a1[6] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 };
+ uint8_t a2t = 0x00;
+ uint8_t a2[6] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 };
+ uint8_t exp[16] = { 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2,
+ 0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3 };
+ uint8_t res[16];
+ int err;
+
+ err = ble_sm_alg_f6(w, n1, n2, r, io_cap, a1t, a1, a2t, a2, res);
+ TEST_ASSERT_FATAL(err == 0);
+ TEST_ASSERT(memcmp(res, exp, 16) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_g2)
+{
+ uint8_t u[32] = { 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 };
+ uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+ 0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+ 0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+ 0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+ uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+ 0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+ uint8_t y[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+ 0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+ uint32_t exp_val = 0x2f9ed5ba % 1000000;
+ uint32_t val;
+ int err;
+
+ err = ble_sm_alg_g2(u, v, x, y, &val);
+ TEST_ASSERT_FATAL(err == 0);
+ TEST_ASSERT(val == exp_val);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_conn_broken)
+{
+ struct ble_hci_ev_disconn_cmp disconn_evt;
+ int rc;
+
+ ble_sm_test_util_init();
+
+ ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
+ ble_sm_test_util_conn_cb, NULL);
+
+ /* Initiate the pairing procedure. */
+ rc = ble_hs_test_util_security_initiate(2, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Terminate the connection. */
+ disconn_evt.conn_handle = htole16(2);
+ disconn_evt.status = 0;
+ disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
+ ble_gap_rx_disconn_complete(&disconn_evt);
+
+ /* Verify security callback got called. */
+ TEST_ASSERT(ble_sm_test_gap_status == BLE_HS_ENOTCONN);
+ TEST_ASSERT(!ble_sm_test_sec_state.encrypted);
+ TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*****************************************************************************
+ * $peer *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_sm_test_case_peer_fail_inval)
+{
+ /* Invalid role detected before other arguments. */
+ ble_sm_test_util_peer_fail_inval(
+ 1,
+ ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}),
+ ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}),
+ ((struct ble_sm_pair_cmd[1]) { {
+ .io_cap = 0x14,
+ .oob_data_flag = 0,
+ .authreq = 0x12,
+ .max_enc_key_size = 20,
+ .init_key_dist = 0x0b,
+ .resp_key_dist = 0x11,
+ } }),
+ ((struct ble_sm_pair_fail[1]) { {
+ .reason = BLE_SM_ERR_CMD_NOT_SUPP,
+ } })
+ );
+
+ /* Invalid key size - too small. */
+ ble_sm_test_util_peer_fail_inval(
+ 0,
+ ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}),
+ ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}),
+ ((struct ble_sm_pair_cmd[1]) { {
+ .io_cap = 0x04,
+ .oob_data_flag = 0,
+ .authreq = 0x5,
+ .max_enc_key_size = 6,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ } }),
+ ((struct ble_sm_pair_fail[1]) { {
+ .reason = BLE_SM_ERR_ENC_KEY_SZ,
+ } })
+ );
+
+ /* Invalid key size - too large. */
+ ble_sm_test_util_peer_fail_inval(
+ 0,
+ ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}),
+ ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}),
+ ((struct ble_sm_pair_cmd[1]) { {
+ .io_cap = 0x04,
+ .oob_data_flag = 0,
+ .authreq = 0x5,
+ .max_enc_key_size = 17,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ } }),
+ ((struct ble_sm_pair_fail[1]) { {
+ .reason = BLE_SM_ERR_INVAL,
+ } })
+ );
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_peer_lgcy_fail_confirm)
+{
+ ble_sm_test_util_peer_lgcy_fail_confirm(
+ ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}),
+ ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}),
+ ((struct ble_sm_pair_cmd[1]) { {
+ .io_cap = 0x04,
+ .oob_data_flag = 0,
+ .authreq = 0x05,
+ .max_enc_key_size = 16,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ } }),
+ ((struct ble_sm_pair_cmd[1]) { {
+ .io_cap = 3,
+ .oob_data_flag = 0,
+ .authreq = 0,
+ .max_enc_key_size = 16,
+ .init_key_dist = 0,
+ .resp_key_dist = 0,
+ } }),
+ ((struct ble_sm_pair_confirm[1]) { {
+ .value = {
+ 0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
+ 0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
+ },
+ } }),
+ ((struct ble_sm_pair_confirm[1]) { {
+ .value = {
+ 0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
+ 0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
+ },
+ } }),
+ ((struct ble_sm_pair_random[1]) { {
+ .value = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ },
+ } }),
+ ((struct ble_sm_pair_random[1]) { {
+ .value = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ } }),
+ ((struct ble_sm_pair_fail[1]) { {
+ .reason = BLE_SM_ERR_CONFIRM_MISMATCH,
+ } })
+ );
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_peer_bonding_bad)
+{
+ ble_sm_test_util_peer_bonding_bad(0x5684, 32);
+ ble_sm_test_util_peer_bonding_bad(54325, 65437);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_sm_test_case_peer_sec_req_inval)
+{
+ struct ble_sm_pair_fail fail;
+ struct ble_sm_sec_req sec_req;
+ int rc;
+
+ ble_sm_test_util_init();
+
+ ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
+ ble_sm_test_util_conn_cb,
+ NULL);
+
+ /*** We are the slave; reject the security request. */
+ ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0);
+
+ sec_req.authreq = 0;
+ ble_sm_test_util_rx_sec_req(
+ 2, &sec_req, BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP));
+
+ fail.reason = BLE_SM_ERR_CMD_NOT_SUPP;
+ ble_sm_test_util_verify_tx_pair_fail(&fail);
+
+ /*** Pairing already in progress; ignore security request. */
+ ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 1);
+ rc = ble_sm_pair_initiate(2);
+ TEST_ASSERT_FATAL(rc == 0);
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ ble_sm_test_util_rx_sec_req(2, &sec_req, BLE_HS_EALREADY);
+ TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+/*****************************************************************************
+ * $us *
+ *****************************************************************************/
+
+TEST_CASE_SELF(ble_sm_test_case_us_fail_inval)
+{
+ struct ble_sm_test_params params;
+
+ /* Invalid key size - too small. */
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
+ .resp_id_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
+ .pair_req = (struct ble_sm_pair_cmd) {
+ .io_cap = 3,
+ .oob_data_flag = 0,
+ .authreq = 0,
+ .max_enc_key_size = 16,
+ .init_key_dist = 0,
+ .resp_key_dist = 0,
+ },
+ .pair_rsp = (struct ble_sm_pair_cmd) {
+ .io_cap = 0x04,
+ .oob_data_flag = 0,
+ .authreq = 0x05,
+ .max_enc_key_size = 6,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_fail = (struct ble_sm_pair_fail) {
+ .reason = BLE_SM_ERR_ENC_KEY_SZ,
+ },
+ };
+ ble_sm_test_util_us_fail_inval(&params);
+
+ /* Invalid key size - too large. */
+ params = (struct ble_sm_test_params) {
+ .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
+ .resp_id_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
+ .pair_req = (struct ble_sm_pair_cmd) {
+ .io_cap = 3,
+ .oob_data_flag = 0,
+ .authreq = 0,
+ .max_enc_key_size = 16,
+ .init_key_dist = 0,
+ .resp_key_dist = 0,
+ },
+ .pair_rsp = (struct ble_sm_pair_cmd) {
+ .io_cap = 0x04,
+ .oob_data_flag = 0,
+ .authreq = 0x05,
+ .max_enc_key_size = 17,
+ .init_key_dist = 0x07,
+ .resp_key_dist = 0x07,
+ },
+ .pair_fail = (struct ble_sm_pair_fail) {
+ .reason = BLE_SM_ERR_INVAL,
+ },
+ };
+ ble_sm_test_util_us_fail_inval(&params);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_sm_gen_test_suite)
+{
+ ble_sm_test_case_f4();
+ ble_sm_test_case_f5();
+ ble_sm_test_case_f6();
+ ble_sm_test_case_g2();
+
+ ble_sm_test_case_peer_fail_inval();
+ ble_sm_test_case_peer_lgcy_fail_confirm();
+ ble_sm_test_case_us_fail_inval();
+ ble_sm_test_case_peer_bonding_bad();
+ ble_sm_test_case_conn_broken();
+ ble_sm_test_case_peer_sec_req_inval();
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.c
new file mode 100644
index 00000000..6170371f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.c
@@ -0,0 +1,2967 @@
+/*
+ * 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 <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/hci_common.h"
+#include "nimble/nimble_opt.h"
+#include "host/ble_sm.h"
+#include "ble_hs_test.h"
+#include "host/ble_hs_id.h"
+#include "ble_hs_test_util.h"
+#include "ble_sm_test_util.h"
+
+#define BLE_HCI_LT_KEY_REQ_REPLY_LEN (18)
+#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN (2)
+#define BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN (2) /* No status byte. */
+#define BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN (2)
+#define BLE_HCI_LE_START_ENCRYPT_LEN (28)
+#define BLE_HCI_ADD_TO_RESOLV_LIST_LEN (39)
+
+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;
+
+static struct {
+ /** Handle reported in previous repeat pairing event. */
+ struct ble_gap_repeat_pairing rp;
+
+ struct ble_sm_test_params params;
+
+ /** What the callback should return this time. */
+ int rc;
+
+ /** What the callback should return next time. */
+ int next_rc;
+
+ /**
+ * Whether the callback should erase the conflicting entry before retrying.
+ */
+ int erase_on_retry;
+
+ /** The number of times the event got reported. */
+ int num_calls;
+} ble_sm_test_repeat_pairing;
+
+struct ble_sm_test_util_entity {
+ uint8_t addr_type;
+ uint8_t id_addr_type;
+ uint8_t *id_addr;
+ uint8_t *rpa;
+
+ struct ble_sm_pair_cmd *pair_cmd;
+ struct ble_sm_pair_confirm *confirms;
+ struct ble_sm_pair_random *randoms;
+ struct ble_sm_id_info *id_info;
+ struct ble_sm_id_addr_info *id_addr_info;
+ struct ble_sm_sign_info *sign_info;
+ uint8_t *ltk;
+
+ uint8_t key_dist;
+
+ /*** Secure connections fields. */
+ struct ble_sm_public_key *public_key;
+ struct ble_sm_dhkey_check *dhkey_check;
+
+ /*** Legacy fields. */
+ struct ble_sm_enc_info *enc_info;
+ struct ble_sm_master_id *master_id;
+ uint64_t rand_num;
+ uint16_t ediv;
+};
+
+static void ble_sm_test_util_repeat_pairing(struct ble_sm_test_params *params,
+ int sc);
+
+#define BLE_SM_TEST_UTIL_HCI_HDR(handle, pb, len) \
+ ((struct hci_data_hdr) { \
+ .hdh_handle_pb_bc = ((handle) << 0) | \
+ ((pb) << 12), \
+ .hdh_len = (len) \
+ })
+
+static void
+ble_sm_pair_cmd_parse(void *payload, int len, struct ble_sm_pair_cmd *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_pair_cmd));
+
+ u8ptr = payload;
+ cmd->io_cap = u8ptr[0];
+ cmd->oob_data_flag = u8ptr[1];
+ cmd->authreq = u8ptr[2];
+ cmd->max_enc_key_size = u8ptr[3];
+ cmd->init_key_dist = u8ptr[4];
+ cmd->resp_key_dist = u8ptr[5];
+}
+
+static void
+ble_sm_pair_cmd_write(void *payload, int len, int is_req,
+ struct ble_sm_pair_cmd *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd));
+
+ u8ptr = payload;
+ u8ptr[0] = is_req ? BLE_SM_OP_PAIR_REQ : BLE_SM_OP_PAIR_RSP;
+ u8ptr[1] = cmd->io_cap;
+ u8ptr[2] = cmd->oob_data_flag;
+ u8ptr[3] = cmd->authreq;
+ u8ptr[4] = cmd->max_enc_key_size;
+ u8ptr[5] = cmd->init_key_dist;
+ u8ptr[6] = cmd->resp_key_dist;
+}
+
+static void
+ble_sm_pair_confirm_parse(void *payload, int len,
+ struct ble_sm_pair_confirm *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_pair_confirm));
+ memcpy(cmd->value, payload, sizeof cmd->value);
+}
+
+static void
+ble_sm_pair_confirm_write(void *payload, int len,
+ struct ble_sm_pair_confirm *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_confirm));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_PAIR_CONFIRM;
+ memcpy(u8ptr + sizeof(struct ble_sm_hdr), cmd->value, sizeof cmd->value);
+}
+
+static void
+ble_sm_pair_random_parse(void *payload, int len,
+ struct ble_sm_pair_random *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_pair_random));
+ memcpy(cmd->value, payload, sizeof cmd->value);
+}
+
+static void
+ble_sm_pair_random_write(void *payload, int len,
+ struct ble_sm_pair_random *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_random));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_PAIR_RANDOM;
+ memcpy(u8ptr + sizeof(struct ble_sm_hdr), cmd->value, sizeof cmd->value);
+}
+
+static void
+ble_sm_pair_fail_parse(void *payload, int len, struct ble_sm_pair_fail *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_pair_fail));
+
+ u8ptr = payload;
+ cmd->reason = u8ptr[0];
+}
+
+static void
+ble_sm_enc_info_parse(void *payload, int len, struct ble_sm_enc_info *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_enc_info));
+
+ memcpy(cmd->ltk, payload, sizeof cmd->ltk);
+}
+
+static void
+ble_sm_enc_info_write(void *payload, int len, struct ble_sm_enc_info *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_enc_info));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_ENC_INFO;
+ memcpy(u8ptr + 1, cmd->ltk, sizeof cmd->ltk);
+}
+
+static void
+ble_sm_master_id_parse(void *payload, int len, struct ble_sm_master_id *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_master_id));
+
+ u8ptr = payload;
+
+ cmd->ediv = get_le16(u8ptr);
+ cmd->rand_val = get_le64(u8ptr + 2);
+}
+
+static void
+ble_sm_master_id_write(void *payload, int len, struct ble_sm_master_id *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_master_id));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_MASTER_ID;
+ put_le16(u8ptr + 1, cmd->ediv);
+ put_le64(u8ptr + 3, cmd->rand_val);
+}
+
+static void
+ble_sm_id_info_parse(void *payload, int len, struct ble_sm_id_info *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_id_info));
+
+ memcpy(cmd->irk, payload, 16);
+}
+
+static void
+ble_sm_id_info_write(void *payload, int len, struct ble_sm_id_info *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_info));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_IDENTITY_INFO;
+ memcpy(u8ptr + sizeof(struct ble_sm_hdr), cmd->irk, sizeof cmd->irk);
+}
+
+static void
+ble_sm_id_addr_info_parse(void *payload, int len,
+ struct ble_sm_id_addr_info *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_id_addr_info));
+
+ u8ptr = payload;
+
+ cmd->addr_type = *u8ptr;
+ memcpy(cmd->bd_addr, u8ptr + 1, 6);
+}
+
+static void
+ble_sm_id_addr_info_write(void *payload, int len,
+ struct ble_sm_id_addr_info *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_addr_info));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_IDENTITY_ADDR_INFO;
+ u8ptr[1] = cmd->addr_type;
+ memcpy(u8ptr + 2, cmd->bd_addr, sizeof cmd->bd_addr);
+}
+
+static void
+ble_sm_sign_info_parse(void *payload, int len, struct ble_sm_sign_info *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_sign_info));
+
+ memcpy(cmd->sig_key, payload, 16);
+}
+
+static void
+ble_sm_sign_info_write(void *payload, int len, struct ble_sm_sign_info *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sign_info));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_SIGN_INFO;
+ memcpy(u8ptr + sizeof(struct ble_sm_hdr),
+ cmd->sig_key, sizeof cmd->sig_key);
+}
+
+static void
+ble_sm_sec_req_parse(void *payload, int len, struct ble_sm_sec_req *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_sec_req));
+
+ u8ptr = payload;
+ cmd->authreq = *u8ptr;
+}
+
+static void
+ble_sm_sec_req_write(void *payload, int len, struct ble_sm_sec_req *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sec_req));
+
+ u8ptr = payload;
+
+ u8ptr[0] = BLE_SM_OP_SEC_REQ;
+ u8ptr[1] = cmd->authreq;
+}
+
+static void
+ble_sm_public_key_parse(void *payload, int len, struct ble_sm_public_key *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_public_key));
+
+ u8ptr = payload;
+
+ memcpy(cmd->x, u8ptr, sizeof cmd->x);
+ u8ptr += sizeof cmd->x;
+
+ memcpy(cmd->y, u8ptr, sizeof cmd->y);
+ u8ptr += sizeof cmd->y;
+}
+
+static void
+ble_sm_public_key_write(void *payload, int len, struct ble_sm_public_key *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_public_key));
+
+ u8ptr = payload;
+
+ *u8ptr = BLE_SM_OP_PAIR_PUBLIC_KEY;
+ u8ptr++;
+
+ memcpy(u8ptr, cmd->x, sizeof cmd->x);
+ memcpy(u8ptr + 32, cmd->y, sizeof cmd->y);
+}
+
+static void
+ble_sm_dhkey_check_parse(void *payload, int len,
+ struct ble_sm_dhkey_check *cmd)
+{
+ BLE_HS_DBG_ASSERT(len >= sizeof(struct ble_sm_dhkey_check));
+
+ memcpy(cmd->value, payload, sizeof cmd->value);
+}
+
+static void
+ble_sm_dhkey_check_write(void *payload, int len,
+ struct ble_sm_dhkey_check *cmd)
+{
+ uint8_t *u8ptr;
+
+ BLE_HS_DBG_ASSERT(
+ len >= sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_dhkey_check));
+
+ u8ptr = payload;
+
+ *u8ptr = BLE_SM_OP_PAIR_DHKEY_CHECK;
+ u8ptr++;
+
+ memcpy(u8ptr, cmd->value, sizeof cmd->value);
+}
+
+void
+ble_sm_test_util_init(void)
+{
+ ble_hs_test_util_init();
+
+ ble_sm_test_gap_event_type = -1;
+ ble_sm_test_gap_status = -1;
+ memset(&ble_sm_test_repeat_pairing, 0, sizeof ble_sm_test_repeat_pairing);
+ ble_sm_test_repeat_pairing.rp.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+
+ memset(&ble_sm_test_ioact, 0, sizeof ble_sm_test_ioact);
+ memset(&ble_sm_test_sec_state, 0xff, sizeof ble_sm_test_sec_state);
+}
+
+static void
+ble_sm_test_util_params_to_entity(struct ble_sm_test_params *params,
+ int initiator,
+ struct ble_sm_test_util_entity *out_entity)
+{
+ int sc;
+
+ memset(out_entity, 0, sizeof *out_entity);
+
+ sc = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_SC &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_SC;
+
+ if (initiator) {
+ out_entity->key_dist = params->pair_rsp.init_key_dist;
+
+ out_entity->addr_type = params->init_addr_type;
+ out_entity->id_addr = params->init_id_addr;
+ out_entity->rpa = params->init_rpa;
+
+ out_entity->pair_cmd = &params->pair_req;
+ out_entity->confirms = params->confirm_req;
+ out_entity->randoms = params->random_req;
+ out_entity->id_info = &params->id_info_rsp;
+ out_entity->id_addr_info = &params->id_addr_info_rsp;
+ out_entity->sign_info = &params->sign_info_rsp;
+
+ if (sc) {
+ out_entity->ltk = params->ltk;
+ out_entity->public_key = &params->public_key_req;
+ out_entity->dhkey_check = &params->dhkey_check_req;
+ } else {
+ out_entity->enc_info = &params->enc_info_rsp;
+ out_entity->master_id = &params->master_id_rsp;
+ if (out_entity->key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
+ out_entity->rand_num = params->master_id_rsp.rand_val;
+ out_entity->ediv = params->master_id_rsp.ediv;
+ out_entity->ltk = params->enc_info_rsp.ltk;
+ }
+ }
+ } else {
+ out_entity->key_dist = params->pair_rsp.resp_key_dist;
+
+ out_entity->addr_type = params->resp_addr_type;
+ out_entity->id_addr = params->resp_id_addr;
+ out_entity->rpa = params->resp_rpa;
+
+ out_entity->pair_cmd = &params->pair_rsp;
+ out_entity->confirms = params->confirm_rsp;
+ out_entity->randoms = params->random_rsp;
+ out_entity->id_info = &params->id_info_req;
+ out_entity->id_addr_info = &params->id_addr_info_req;
+ out_entity->sign_info = &params->sign_info_req;
+
+ if (sc) {
+ out_entity->ltk = params->ltk;
+ out_entity->public_key = &params->public_key_rsp;
+ out_entity->dhkey_check = &params->dhkey_check_rsp;
+ } else {
+ out_entity->enc_info = &params->enc_info_req;
+ out_entity->master_id = &params->master_id_req;
+ if (out_entity->key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
+ out_entity->rand_num = params->master_id_req.rand_val;
+ out_entity->ediv = params->master_id_req.ediv;
+ out_entity->ltk = params->enc_info_req.ltk;
+ }
+ }
+ }
+
+ out_entity->id_addr_type =
+ ble_hs_misc_own_addr_type_to_id(out_entity->addr_type);
+}
+
+static void
+ble_sm_test_util_params_to_entities(struct ble_sm_test_params *params,
+ int we_are_initiator,
+ struct ble_sm_test_util_entity *out_us,
+ struct ble_sm_test_util_entity *out_peer)
+{
+ ble_sm_test_util_params_to_entity(params, we_are_initiator, out_us);
+ ble_sm_test_util_params_to_entity(params, !we_are_initiator, out_peer);
+}
+
+static void
+ble_sm_test_util_init_good(struct ble_sm_test_params *params,
+ int we_are_initiator,
+ struct ble_hs_conn **out_conn,
+ struct ble_sm_test_util_entity *out_us,
+ struct ble_sm_test_util_entity *out_peer)
+{
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init();
+
+ ble_sm_test_util_params_to_entities(params, we_are_initiator,
+ out_us, out_peer);
+
+ ble_hs_cfg.sm_io_cap = out_us->pair_cmd->io_cap;
+ ble_hs_cfg.sm_oob_data_flag = out_us->pair_cmd->oob_data_flag;
+ ble_hs_cfg.sm_bonding = !!(out_us->pair_cmd->authreq &
+ BLE_SM_PAIR_AUTHREQ_BOND);
+ ble_hs_cfg.sm_mitm = !!(out_us->pair_cmd->authreq &
+ BLE_SM_PAIR_AUTHREQ_MITM);
+ ble_hs_cfg.sm_sc = !!(out_us->pair_cmd->authreq &
+ BLE_SM_PAIR_AUTHREQ_SC);
+ ble_hs_cfg.sm_keypress = !!(out_us->pair_cmd->authreq &
+ BLE_SM_PAIR_AUTHREQ_KEYPRESS);
+
+ if (we_are_initiator) {
+ ble_hs_cfg.sm_our_key_dist = out_us->pair_cmd->init_key_dist;
+ ble_hs_cfg.sm_their_key_dist = out_us->pair_cmd->resp_key_dist;
+ } else {
+ ble_hs_cfg.sm_our_key_dist = out_us->pair_cmd->resp_key_dist;
+ ble_hs_cfg.sm_their_key_dist = out_us->pair_cmd->init_key_dist;
+ }
+
+ 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_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((uint8_t *)out_us->public_key,
+ params->our_priv_key);
+ }
+
+ 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_HS_TEST_CONN_FEAT_ALL,
+ ble_sm_test_util_conn_cb,
+ NULL);
+
+ /* This test code and modifies the connection object after unlocking
+ * the host mutex. It is not OK for real code to do this, but this test
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ if (!we_are_initiator) {
+ /* Peer is the initiator so we must be the slave. */
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ }
+
+ if (out_conn != NULL) {
+ *out_conn = conn;
+ }
+}
+
+static int
+ble_sm_test_util_repeat_pairing_cb(const struct ble_gap_repeat_pairing *rp)
+{
+ struct ble_store_value_sec value_sec;
+ struct ble_store_key_sec key_sec;
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ TEST_ASSERT_FATAL(rp->conn_handle != BLE_HS_CONN_HANDLE_NONE);
+
+ ble_sm_test_repeat_pairing.num_calls++;
+
+ rc = ble_gap_conn_find(rp->conn_handle, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ memset(&key_sec, 0, sizeof key_sec);
+ key_sec.peer_addr = desc.peer_id_addr;
+ rc = ble_store_read_peer_sec(&key_sec, &value_sec);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Verify current bond is reported correctly. */
+ TEST_ASSERT(rp->cur_key_size == value_sec.key_size);
+ TEST_ASSERT(rp->cur_authenticated == value_sec.authenticated);
+ TEST_ASSERT(rp->cur_sc == value_sec.sc);
+
+ /* Verify new pairing request is reported correctly. */
+ TEST_ASSERT(
+ rp->new_key_size ==
+ min(ble_sm_test_repeat_pairing.params.pair_req.max_enc_key_size,
+ ble_sm_test_repeat_pairing.params.pair_rsp.max_enc_key_size));
+ TEST_ASSERT(
+ rp->new_authenticated ==
+ !!(ble_sm_test_repeat_pairing.params.passkey_info.passkey.action));
+ TEST_ASSERT(
+ rp->new_sc ==
+ ((ble_sm_test_repeat_pairing.params.pair_req.authreq &
+ BLE_SM_PAIR_AUTHREQ_SC)
+ &&
+ (ble_sm_test_repeat_pairing.params.pair_rsp.authreq &
+ BLE_SM_PAIR_AUTHREQ_SC)));
+ TEST_ASSERT(
+ rp->new_bonding ==
+ ((ble_sm_test_repeat_pairing.params.pair_req.authreq &
+ BLE_SM_PAIR_AUTHREQ_BOND)
+ &&
+ (ble_sm_test_repeat_pairing.params.pair_rsp.authreq &
+ BLE_SM_PAIR_AUTHREQ_BOND)));
+
+ if (ble_sm_test_repeat_pairing.rp.conn_handle ==
+ BLE_HS_CONN_HANDLE_NONE) {
+
+ ble_sm_test_repeat_pairing.rp.conn_handle = rp->conn_handle;
+ } else {
+ /* Ensure the correct connection handle gets reported each time. */
+ TEST_ASSERT(rp->conn_handle ==
+ ble_sm_test_repeat_pairing.rp.conn_handle);
+ }
+
+ ble_sm_test_repeat_pairing.rp = *rp;
+
+ if (ble_sm_test_repeat_pairing.rc == BLE_GAP_REPEAT_PAIRING_RETRY &&
+ ble_sm_test_repeat_pairing.erase_on_retry) {
+
+ rc = ble_gap_conn_find(rp->conn_handle, &desc);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_store_util_delete_peer(&desc.peer_id_addr);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ rc = ble_sm_test_repeat_pairing.rc;
+ ble_sm_test_repeat_pairing.rc = ble_sm_test_repeat_pairing.next_rc;
+
+ return rc;
+}
+
+int
+ble_sm_test_util_conn_cb(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_ENC_CHANGE:
+ 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;
+ rc = 0;
+ break;
+
+ case BLE_GAP_EVENT_PASSKEY_ACTION:
+ ble_sm_test_ioact = event->passkey.params;
+ rc = 0;
+ break;
+
+ case BLE_GAP_EVENT_REPEAT_PAIRING:
+ rc = ble_sm_test_util_repeat_pairing_cb(&event->repeat_pairing);
+ break;
+
+ default:
+ return 0;
+ }
+
+ ble_sm_test_gap_event_type = event->type;
+ return rc;
+}
+
+static void
+ble_sm_test_util_rx_pair_cmd(uint16_t conn_handle, uint8_t op,
+ struct ble_sm_pair_cmd *cmd,
+ int rx_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ +
+ sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_pair_cmd_write(v, payload_len, op == BLE_SM_OP_PAIR_REQ, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT(rc == rx_status);
+}
+
+static void
+ble_sm_test_util_rx_pair_req(uint16_t conn_handle,
+ struct ble_sm_pair_cmd *req,
+ int rx_status)
+{
+ ble_sm_test_util_rx_pair_cmd(conn_handle, BLE_SM_OP_PAIR_REQ,
+ req, rx_status);
+}
+
+static void
+ble_sm_test_util_rx_pair_rsp(uint16_t conn_handle, struct ble_sm_pair_cmd *rsp,
+ int rx_status)
+{
+ ble_sm_test_util_rx_pair_cmd(conn_handle, BLE_SM_OP_PAIR_RSP,
+ rsp, rx_status);
+}
+
+static void
+ble_sm_test_util_rx_confirm(uint16_t conn_handle,
+ struct ble_sm_pair_confirm *cmd)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ +
+ sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_confirm));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len =
+ sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_confirm);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_pair_confirm_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_sm_test_util_rx_random(uint16_t conn_handle,
+ struct ble_sm_pair_random *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_random));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_random);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_pair_random_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+void
+ble_sm_test_util_rx_sec_req(uint16_t conn_handle, struct ble_sm_sec_req *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sec_req));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sec_req);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_sec_req_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_public_key(uint16_t conn_handle,
+ struct ble_sm_public_key *cmd)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_public_key));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_public_key);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_public_key_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_sm_test_util_rx_dhkey_check(uint16_t conn_handle,
+ struct ble_sm_dhkey_check *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_dhkey_check));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_dhkey_check);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_dhkey_check_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_enc_info(uint16_t conn_handle,
+ struct ble_sm_enc_info *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_enc_info));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_enc_info);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_enc_info_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_master_id(uint16_t conn_handle,
+ struct ble_sm_master_id *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_master_id));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_master_id);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_master_id_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_id_info(uint16_t conn_handle,
+ struct ble_sm_id_info *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_info));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_info);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_id_info_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_id_addr_info(uint16_t conn_handle,
+ struct ble_sm_id_addr_info *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_addr_info));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_id_addr_info);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_id_addr_info_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static void
+ble_sm_test_util_rx_sign_info(uint16_t conn_handle,
+ struct ble_sm_sign_info *cmd,
+ int exp_status)
+{
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int payload_len;
+ int rc;
+
+ hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sign_info));
+
+ om = ble_hs_mbuf_l2cap_pkt();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_sign_info);
+
+ v = os_mbuf_extend(om, payload_len);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ ble_sm_sign_info_write(v, payload_len, cmd);
+
+ rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM,
+ &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == exp_status);
+}
+
+static struct os_mbuf *
+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_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == sizeof(struct ble_sm_hdr) + payload_len);
+ TEST_ASSERT_FATAL(om->om_data[0] == sm_op);
+
+ om->om_data += sizeof(struct ble_sm_hdr);
+ om->om_len -= sizeof(struct ble_sm_hdr);
+
+ return om;
+}
+
+static void
+ble_sm_test_util_verify_tx_pair_cmd(
+ uint8_t op,
+ struct ble_sm_pair_cmd *exp_cmd)
+{
+ struct ble_sm_pair_cmd cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(op, sizeof(struct ble_sm_pair_cmd));
+ ble_sm_pair_cmd_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.io_cap == exp_cmd->io_cap);
+ TEST_ASSERT(cmd.oob_data_flag == exp_cmd->oob_data_flag);
+ TEST_ASSERT(cmd.authreq == exp_cmd->authreq);
+ TEST_ASSERT(cmd.max_enc_key_size == exp_cmd->max_enc_key_size);
+ TEST_ASSERT(cmd.init_key_dist == exp_cmd->init_key_dist);
+ TEST_ASSERT(cmd.resp_key_dist == exp_cmd->resp_key_dist);
+}
+
+static void
+ble_sm_test_util_verify_tx_pair_req(
+ struct ble_sm_pair_cmd *exp_req)
+{
+ ble_sm_test_util_verify_tx_pair_cmd(BLE_SM_OP_PAIR_REQ,
+ exp_req);
+}
+
+static void
+ble_sm_test_util_verify_tx_pair_rsp(
+ struct ble_sm_pair_cmd *exp_rsp)
+{
+ ble_sm_test_util_verify_tx_pair_cmd(BLE_SM_OP_PAIR_RSP,
+ exp_rsp);
+}
+
+static void
+ble_sm_test_util_verify_tx_pair_confirm(
+ struct ble_sm_pair_confirm *exp_cmd)
+{
+ struct ble_sm_pair_confirm cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_PAIR_CONFIRM, sizeof(cmd));
+ ble_sm_pair_confirm_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.value, exp_cmd->value, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_pair_random(
+ struct ble_sm_pair_random *exp_cmd)
+{
+ struct ble_sm_pair_random cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_PAIR_RANDOM,
+ sizeof(struct ble_sm_pair_random));
+ ble_sm_pair_random_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.value, exp_cmd->value, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_public_key(
+ struct ble_sm_public_key *exp_cmd)
+{
+ struct ble_sm_public_key cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_PAIR_PUBLIC_KEY,
+ sizeof(struct ble_sm_public_key));
+ ble_sm_public_key_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.x, exp_cmd->x, sizeof cmd.x) == 0);
+ TEST_ASSERT(memcmp(cmd.y, exp_cmd->y, sizeof cmd.y) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_dhkey_check(
+ struct ble_sm_dhkey_check *exp_cmd)
+{
+ struct ble_sm_dhkey_check cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_PAIR_DHKEY_CHECK,
+ sizeof(struct ble_sm_dhkey_check));
+ ble_sm_dhkey_check_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.value, exp_cmd->value, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_enc_info(struct ble_sm_enc_info *exp_cmd)
+{
+ struct ble_sm_enc_info cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_ENC_INFO,
+ sizeof(struct ble_sm_enc_info));
+ ble_sm_enc_info_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.ltk, exp_cmd->ltk, 16) == 0);
+
+ /* Ensure LTK is sent in little endian. */
+ TEST_ASSERT(memcmp(om->om_data, cmd.ltk, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_master_id(struct ble_sm_master_id *exp_cmd)
+{
+ struct ble_sm_master_id cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_MASTER_ID,
+ sizeof(struct ble_sm_master_id));
+ ble_sm_master_id_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.ediv == exp_cmd->ediv);
+ TEST_ASSERT(cmd.rand_val == exp_cmd->rand_val);
+}
+
+static void
+ble_sm_test_util_verify_tx_id_info(struct ble_sm_id_info *exp_cmd)
+{
+ struct ble_sm_id_info cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_IDENTITY_INFO,
+ sizeof(struct ble_sm_id_info));
+ ble_sm_id_info_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.irk, exp_cmd->irk, 16) == 0);
+
+ /* Ensure IRK is sent in little endian. */
+ TEST_ASSERT(memcmp(om->om_data, cmd.irk, 16) == 0);
+}
+
+static void
+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;
+ const uint8_t *our_id_addr;
+ int rc;
+
+ ble_hs_lock();
+ rc = ble_hs_id_addr(exp_cmd->addr_type, &our_id_addr, NULL);
+ ble_hs_unlock();
+
+ TEST_ASSERT_FATAL(rc == 0);
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_IDENTITY_ADDR_INFO,
+ sizeof(struct ble_sm_id_addr_info));
+ ble_sm_id_addr_info_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.addr_type == exp_cmd->addr_type);
+ TEST_ASSERT(memcmp(cmd.bd_addr, exp_cmd->bd_addr, 6) == 0);
+ TEST_ASSERT(memcmp(cmd.bd_addr, our_id_addr, 6) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_sign_info(struct ble_sm_sign_info *exp_cmd)
+{
+ struct ble_sm_sign_info cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_SIGN_INFO,
+ sizeof(struct ble_sm_sign_info));
+ ble_sm_sign_info_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(memcmp(cmd.sig_key, exp_cmd->sig_key, 16) == 0);
+
+ /* Ensure CSRK is sent in little endian. */
+ TEST_ASSERT(memcmp(om->om_data, cmd.sig_key, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_sec_req(struct ble_sm_sec_req *exp_cmd)
+{
+ struct ble_sm_sec_req cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_SEC_REQ, sizeof(struct ble_sm_sec_req));
+ ble_sm_sec_req_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.authreq == exp_cmd->authreq);
+}
+
+void
+ble_sm_test_util_verify_tx_pair_fail(
+ struct ble_sm_pair_fail *exp_cmd)
+{
+ struct ble_sm_pair_fail cmd;
+ struct os_mbuf *om;
+
+ om = ble_sm_test_util_verify_tx_hdr(BLE_SM_OP_PAIR_FAIL,
+ sizeof(struct ble_sm_pair_fail));
+ ble_sm_pair_fail_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.reason == exp_cmd->reason);
+}
+
+static void
+ble_sm_test_util_rx_lt_key_req(uint16_t conn_handle, uint64_t r, uint16_t ediv)
+{
+ struct ble_hci_ev_le_subev_lt_key_req evt;
+ int rc;
+
+ evt.subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
+ evt.conn_handle = htole16(conn_handle);
+ evt.rand = htole64(r);
+ evt.div = htole16(ediv);
+
+ rc = ble_sm_ltk_req_rx(&evt);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_lt_key_req_reply(uint16_t conn_handle, uint8_t *stk)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_LT_KEY_REQ_REPLY_LEN);
+ TEST_ASSERT(get_le16(param + 0) == conn_handle);
+ TEST_ASSERT(memcmp(param + 2, stk, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_lt_key_req_neg_reply(uint16_t conn_handle)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN);
+ TEST_ASSERT(get_le16(param + 0) == conn_handle);
+}
+
+static void
+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];
+
+ put_le16(params, conn_handle);
+ ble_hs_test_util_hci_ack_set_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];
+
+ put_le16(params, conn_handle);
+ ble_hs_test_util_hci_ack_set_params(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
+ status, params, sizeof params);
+}
+
+static void
+ble_sm_test_util_rx_enc_change(uint16_t conn_handle, uint8_t status,
+ uint8_t encryption_enabled)
+{
+ struct ble_hci_ev_enrypt_chg evt;
+
+ evt.status = status;
+ evt.enabled = encryption_enabled;
+ evt.connection_handle = htole16(conn_handle);
+
+ ble_sm_enc_change_rx(&evt);
+}
+
+static void
+ble_sm_test_util_verify_tx_start_enc(uint16_t conn_handle,
+ uint64_t random_number,
+ uint16_t ediv,
+ uint8_t *ltk)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_START_ENCRYPT,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_LE_START_ENCRYPT_LEN);
+ TEST_ASSERT(get_le16(param + 0) == conn_handle);
+ TEST_ASSERT(get_le64(param + 2) == random_number);
+ TEST_ASSERT(get_le16(param + 10) == ediv);
+ TEST_ASSERT(memcmp(param + 12, ltk, 16) == 0);
+}
+
+static void
+ble_sm_test_util_verify_tx_add_resolve_list(uint8_t peer_id_addr_type,
+ uint8_t *peer_id_addr,
+ uint8_t *peer_irk,
+ uint8_t *our_irk)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_SET_ADV_ENABLE,
+ NULL);
+
+ param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_ADD_RESOLV_LIST,
+ &param_len);
+ TEST_ASSERT(param_len == BLE_HCI_ADD_TO_RESOLV_LIST_LEN);
+ TEST_ASSERT(param[0] == peer_id_addr_type);
+ TEST_ASSERT(memcmp(param + 1, peer_id_addr, 6) == 0);
+
+ /* Ensure IRKs are sent in little endian. */
+ TEST_ASSERT(memcmp(param + 7, peer_irk, 16) == 0);
+ TEST_ASSERT(memcmp(param + 23, our_irk, 16) == 0);
+}
+
+void
+ble_sm_test_util_io_inject(struct ble_sm_test_passkey_info *passkey_info,
+ uint8_t cur_sm_state)
+{
+ uint8_t io_sm_state;
+ int rc;
+
+ 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
+ble_sm_test_util_io_inject_bad(uint16_t conn_handle, uint8_t correct_io_act)
+{
+ struct ble_sm_proc *proc;
+ struct ble_sm_io io;
+ uint8_t io_sm_state;
+ int already_injected;
+ int rc;
+ int i;
+
+ /* Lock mutex to prevent thread-safety assert from failing. */
+ ble_hs_lock();
+ proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
+ ble_hs_unlock();
+
+ TEST_ASSERT_FATAL(proc != NULL);
+
+ io_sm_state = ble_sm_ioact_state(correct_io_act);
+
+ for (i = 1; i < BLE_SM_IOACT_MAX_PLUS_ONE; i++) {
+ if (io_sm_state != proc->state ||
+ i != correct_io_act ||
+ proc->flags & BLE_SM_PROC_F_IO_INJECTED) {
+
+ already_injected = proc->flags & BLE_SM_PROC_F_IO_INJECTED;
+
+ io.action = i;
+ rc = ble_sm_inject_io(conn_handle, &io);
+
+ if (already_injected) {
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+ } else {
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ }
+ }
+ }
+}
+
+void
+ble_sm_test_util_io_check_pre(struct ble_sm_test_passkey_info *passkey_info,
+ uint8_t cur_sm_state)
+{
+ uint8_t io_sm_state;
+ int rc;
+
+ io_sm_state = ble_sm_ioact_state(passkey_info->passkey.action);
+ if (io_sm_state != cur_sm_state) {
+ return;
+ }
+
+ if (!passkey_info->io_before_rx) {
+ return;
+ }
+
+ 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);
+}
+
+void
+ble_sm_test_util_io_check_post(struct ble_sm_test_passkey_info *passkey_info,
+ uint8_t cur_sm_state)
+{
+ uint8_t io_sm_state;
+ int rc;
+
+ io_sm_state = ble_sm_ioact_state(passkey_info->passkey.action);
+ if (io_sm_state != cur_sm_state) {
+ return;
+ }
+
+ if (passkey_info->io_before_rx) {
+ return;
+ }
+
+ if (passkey_info->passkey.action == BLE_SM_IOACT_NUMCMP) {
+ TEST_ASSERT(ble_sm_test_ioact.numcmp == passkey_info->exp_numcmp);
+ }
+
+ /* Ensure response not sent until user performs IO. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
+
+ rc = ble_sm_inject_io(2, &passkey_info->passkey);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
+static void
+ble_sm_test_util_verify_persist(struct ble_sm_test_params *params,
+ int we_are_initiator)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_store_value_sec value_sec;
+ struct ble_store_key_sec key_sec;
+ int csrk_expected;
+ int ltk_expected;
+ int peer_irk_expected;
+ int our_irk_expected;
+ int bonding;
+ int sc;
+ int rc;
+
+ ble_sm_test_util_params_to_entities(params, we_are_initiator,
+ &our_entity, &peer_entity);
+
+ sc = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_SC &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_SC;
+
+ bonding = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_BOND &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_BOND;
+
+ memset(&key_sec, 0, sizeof key_sec);
+ key_sec.peer_addr = *BLE_ADDR_ANY;
+
+ rc = ble_store_read_peer_sec(&key_sec, &value_sec);
+ if (!bonding) {
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ peer_irk_expected = 0;
+ } else {
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ltk_expected =
+ sc || !!(peer_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ENC);
+ peer_irk_expected =
+ !!(peer_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ID);
+ csrk_expected =
+ !!(peer_entity.key_dist & BLE_SM_PAIR_KEY_DIST_SIGN);
+
+ TEST_ASSERT(value_sec.peer_addr.type == peer_entity.id_addr_type);
+ TEST_ASSERT(
+ memcmp(value_sec.peer_addr.val, peer_entity.id_addr, 6) == 0);
+ TEST_ASSERT(value_sec.ediv == peer_entity.ediv);
+ TEST_ASSERT(value_sec.rand_num == peer_entity.rand_num);
+ TEST_ASSERT(value_sec.authenticated == params->authenticated);
+
+ TEST_ASSERT(value_sec.ltk_present == ltk_expected);
+ TEST_ASSERT(memcmp(value_sec.ltk, peer_entity.ltk, 16) == 0);
+
+ TEST_ASSERT(value_sec.irk_present == peer_irk_expected);
+ if (peer_irk_expected) {
+ TEST_ASSERT(memcmp(value_sec.irk,
+ peer_entity.id_info->irk, 16) == 0);
+ }
+
+ TEST_ASSERT(value_sec.csrk_present == csrk_expected);
+ if (csrk_expected) {
+ TEST_ASSERT(memcmp(value_sec.csrk,
+ peer_entity.sign_info->sig_key, 16) == 0);
+ }
+ }
+
+ rc = ble_store_read_our_sec(&key_sec, &value_sec);
+ if (!bonding) {
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ } else {
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ltk_expected =
+ sc || !!(our_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ENC);
+ our_irk_expected =
+ !!(our_entity.key_dist & BLE_SM_PAIR_KEY_DIST_ID);
+ csrk_expected =
+ !!(our_entity.key_dist & BLE_SM_PAIR_KEY_DIST_SIGN);
+
+ TEST_ASSERT(value_sec.peer_addr.type == peer_entity.id_addr_type);
+ TEST_ASSERT(memcmp(value_sec.peer_addr.val, peer_entity.id_addr, 6) == 0);
+ TEST_ASSERT(value_sec.ediv == our_entity.ediv);
+ TEST_ASSERT(value_sec.rand_num == our_entity.rand_num);
+ TEST_ASSERT(value_sec.authenticated == params->authenticated);
+
+ TEST_ASSERT(value_sec.ltk_present == ltk_expected);
+ TEST_ASSERT(memcmp(value_sec.ltk, our_entity.ltk, 16) == 0);
+
+ TEST_ASSERT(value_sec.irk_present == our_irk_expected);
+ if (our_irk_expected) {
+ TEST_ASSERT(memcmp(value_sec.irk,
+ our_entity.id_info->irk, 16) == 0);
+ }
+
+ TEST_ASSERT(value_sec.csrk_present == csrk_expected);
+ if (csrk_expected) {
+ TEST_ASSERT(memcmp(value_sec.csrk,
+ our_entity.sign_info->sig_key, 16) == 0);
+ }
+ }
+
+ /* Verify no other keys were persisted. */
+ key_sec.idx++;
+ rc = ble_store_read_our_sec(&key_sec, &value_sec);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
+ rc = ble_store_read_peer_sec(&key_sec, &value_sec);
+ TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
+
+ /* Verify we sent the peer's IRK to the controller. */
+ if (peer_irk_expected) {
+ ble_sm_test_util_verify_tx_add_resolve_list(peer_entity.id_addr_type,
+ peer_entity.id_addr,
+ peer_entity.id_info->irk,
+ our_entity.id_info->irk);
+ }
+}
+
+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,
+ uint8_t *peer_rpa,
+ uint8_t *ltk, int authenticated,
+ uint16_t ediv, uint64_t rand_num)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ ble_hs_test_util_create_rpa_conn(2, our_addr_type, our_rpa, peer_addr_type,
+ peer_id_addr, peer_rpa,
+ BLE_HS_TEST_CONN_FEAT_ALL,
+ 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ if (send_enc_req) {
+ rc = ble_sm_slave_initiate(2);
+ TEST_ASSERT(rc == 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_rx_lt_key_req(2, rand_num, ediv);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+
+ /* Ensure the LTK request event got sent to the application. */
+ TEST_ASSERT(ble_sm_test_store_obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC);
+ TEST_ASSERT(ble_sm_test_store_key.sec.peer_addr.type ==
+ ble_hs_misc_peer_addr_type_to_id(peer_addr_type));
+ TEST_ASSERT(ble_sm_test_store_key.sec.ediv_rand_present);
+ TEST_ASSERT(ble_sm_test_store_key.sec.ediv == ediv);
+ TEST_ASSERT(ble_sm_test_store_key.sec.rand_num == rand_num);
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Ensure we sent the expected long term key request reply command. */
+ ble_sm_test_util_verify_tx_lt_key_req_reply(2, ltk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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 ==
+ authenticated);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ authenticated);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+void
+ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num)
+{
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init();
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,4,5,6}),
+ 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Receive a long term key request from the controller. */
+ 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);
+
+ /* Ensure the LTK request event got sent to the application. */
+ TEST_ASSERT(ble_sm_test_store_obj_type ==
+ BLE_STORE_OBJ_TYPE_OUR_SEC);
+ TEST_ASSERT(ble_sm_test_store_key.sec.ediv_rand_present);
+ TEST_ASSERT(ble_sm_test_store_key.sec.ediv == ediv);
+ TEST_ASSERT(ble_sm_test_store_key.sec.rand_num == rand_num);
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+
+ /* Ensure we sent the expected long term key request neg reply command. */
+ ble_sm_test_util_verify_tx_lt_key_req_neg_reply(2);
+
+ /* Ensure the security procedure was aborted. */
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(!conn->bhc_sec_state.authenticated);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+}
+
+/**
+ * @param send_enc_req Whether this procedure is initiated by a slave
+ * security request;
+ * 1: Peer sends a security request at start.
+ * 0: No security request; we initiate.
+ */
+static void
+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,
+ uint16_t ediv, uint64_t rand_num)
+{
+ struct ble_sm_sec_req sec_req;
+ struct ble_hs_conn *conn;
+
+ ble_hs_test_util_create_rpa_conn(2, our_addr_type, our_rpa,
+ peer_addr_type, peer_id_addr,
+ peer_rpa, BLE_HS_TEST_CONN_FEAT_ALL,
+ 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ ble_hs_test_util_hci_ack_set(
+ ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_START_ENCRYPT),
+ 0);
+
+ if (send_enc_req) {
+ sec_req.authreq = 0;
+ sec_req.authreq |= BLE_SM_PAIR_AUTHREQ_BOND;
+ if (authenticated) {
+ sec_req.authreq |= BLE_SM_PAIR_AUTHREQ_MITM;
+ }
+ ble_sm_test_util_rx_sec_req(2, &sec_req, 0);
+ } else {
+ ble_gap_security_initiate(2);
+ }
+
+ /* Ensure we sent the expected start encryption command. */
+ ble_sm_test_util_verify_tx_start_enc(2, rand_num, ediv, ltk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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 ==
+ authenticated);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ authenticated);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+void
+ble_sm_test_util_peer_fail_inval(
+ int we_are_master,
+ uint8_t *init_id_addr,
+ uint8_t *resp_addr,
+ struct ble_sm_pair_cmd *pair_req,
+ struct ble_sm_pair_fail *pair_fail)
+{
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init();
+ ble_hs_id_set_pub(resp_addr);
+
+ ble_hs_test_util_create_conn(2, init_id_addr, 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ if (!we_are_master) {
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ }
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Receive a pair request from the peer. */
+ ble_sm_test_util_rx_pair_req(2, pair_req,
+ BLE_HS_SM_US_ERR(pair_fail->reason));
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Ensure we sent the expected pair fail. */
+ ble_sm_test_util_verify_tx_pair_fail(pair_fail);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was not executed. */
+ TEST_ASSERT(ble_sm_test_gap_event_type == -1);
+ TEST_ASSERT(ble_sm_test_gap_status == -1);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(!conn->bhc_sec_state.authenticated);
+}
+
+void
+ble_sm_test_util_peer_lgcy_fail_confirm(
+ uint8_t *init_id_addr,
+ uint8_t *resp_addr,
+ struct ble_sm_pair_cmd *pair_req,
+ struct ble_sm_pair_cmd *pair_rsp,
+ struct ble_sm_pair_confirm *confirm_req,
+ struct ble_sm_pair_confirm *confirm_rsp,
+ struct ble_sm_pair_random *random_req,
+ struct ble_sm_pair_random *random_rsp,
+ struct ble_sm_pair_fail *fail_rsp)
+{
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init();
+ ble_hs_id_set_pub(resp_addr);
+ ble_sm_dbg_set_next_pair_rand(random_rsp->value);
+
+ if (pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_SC) {
+ ble_hs_cfg.sm_sc = 1;
+ } else {
+ ble_hs_cfg.sm_sc = 0;
+ }
+
+ ble_hs_test_util_create_conn(2, init_id_addr, 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ /* Peer is the initiator so we must be the slave. */
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Receive a pair request from the peer. */
+ ble_sm_test_util_rx_pair_req(2, pair_req, 0);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Ensure we sent the expected pair response. */
+ ble_sm_test_util_verify_tx_pair_rsp(pair_rsp);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Receive a pair confirm from the peer. */
+ ble_sm_test_util_rx_confirm(2, confirm_req);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Ensure we sent the expected pair confirm. */
+ ble_sm_test_util_verify_tx_pair_confirm(confirm_rsp);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, BLE_SM_IOACT_NONE);
+
+ /* Receive a pair random from the peer. */
+ ble_sm_test_util_rx_random(
+ 2, random_req, BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH));
+
+ /* Ensure we sent the expected pair fail. */
+ ble_sm_test_util_verify_tx_pair_fail(fail_rsp);
+
+ /* The proc should now be freed. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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);
+ TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted ==
+ conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ conn->bhc_sec_state.authenticated);
+}
+
+static void
+ble_sm_test_util_bonding_all(struct ble_sm_test_params *params,
+ int we_are_original_initiator)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ int sc;
+
+ if (!(params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_BOND) ||
+ !(params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_BOND)) {
+
+ /* Bonding not performed. */
+ return;
+ }
+
+ sc = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_SC &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_SC;
+
+ ble_sm_test_util_params_to_entities(params, we_are_original_initiator,
+ &our_entity, &peer_entity);
+
+ 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.addr_type,
+ our_entity.rpa,
+ peer_entity.addr_type,
+ peer_entity.id_addr,
+ peer_entity.rpa,
+ peer_entity.ltk,
+ params->authenticated,
+ peer_entity.ediv,
+ peer_entity.rand_num);
+
+ /* We are master; peer initiates procedure via security request. */
+ 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,
+ peer_entity.ltk,
+ params->authenticated,
+ peer_entity.ediv,
+ peer_entity.rand_num);
+ }
+
+ 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.addr_type,
+ our_entity.rpa,
+ peer_entity.addr_type,
+ peer_entity.id_addr,
+ peer_entity.rpa,
+ our_entity.ltk,
+ params->authenticated,
+ our_entity.ediv,
+ our_entity.rand_num);
+
+ /* Peer is master; we initiate procedure via security request. */
+ 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,
+ our_entity.ltk,
+ params->authenticated,
+ our_entity.ediv,
+ our_entity.rand_num);
+ }
+}
+
+static void
+ble_sm_test_util_rx_keys(struct ble_sm_test_params *params,
+ int we_are_initiator)
+{
+ struct ble_sm_id_addr_info *peer_id_addr_info;
+ struct ble_sm_sign_info *peer_sign_info;
+ struct ble_sm_master_id *peer_master_id;
+ struct ble_sm_enc_info *peer_enc_info;
+ struct ble_sm_id_info *peer_id_info;
+ uint8_t peer_key_dist;
+ int sc;
+
+ if (we_are_initiator) {
+ peer_key_dist = params->pair_rsp.resp_key_dist;
+ peer_id_addr_info = &params->id_addr_info_req;
+ peer_sign_info = &params->sign_info_req;
+ peer_master_id = &params->master_id_req;
+ peer_enc_info = &params->enc_info_req;
+ peer_id_info = &params->id_info_req;
+ } else {
+ peer_key_dist = params->pair_rsp.init_key_dist;
+ peer_id_addr_info = &params->id_addr_info_rsp;
+ peer_sign_info = &params->sign_info_rsp;
+ peer_master_id = &params->master_id_rsp;
+ peer_enc_info = &params->enc_info_rsp;
+ peer_id_info = &params->id_info_rsp;
+ }
+
+ sc = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_SC &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_SC;
+
+ /* Receive key material from peer. */
+ if (!sc && (peer_key_dist & BLE_SM_PAIR_KEY_DIST_ENC)) {
+ ble_sm_test_util_rx_enc_info(2, peer_enc_info, 0);
+ ble_sm_test_util_rx_master_id(2, peer_master_id, 0);
+ }
+ if (peer_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
+
+ ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
+ {
+ .opcode = ble_hs_hci_util_opcode_join(
+ BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+ },
+ {
+ .opcode = ble_hs_hci_util_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_SET_PRIVACY_MODE),
+ },
+ { 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);
+ }
+ if (peer_key_dist & BLE_SM_PAIR_KEY_DIST_SIGN) {
+ ble_sm_test_util_rx_sign_info(2, peer_sign_info, 0);
+ }
+}
+
+static void
+ble_sm_test_util_verify_tx_keys(struct ble_sm_test_params *params,
+ int we_are_initiator)
+{
+ struct ble_sm_id_addr_info *our_id_addr_info;
+ struct ble_sm_sign_info *our_sign_info;
+ struct ble_sm_master_id *our_master_id;
+ struct ble_sm_enc_info *our_enc_info;
+ struct ble_sm_id_info *our_id_info;
+ uint8_t our_key_dist;
+ int sc;
+
+ if (we_are_initiator) {
+ our_key_dist = params->pair_rsp.init_key_dist;
+ our_id_addr_info = &params->id_addr_info_rsp;
+ our_sign_info = &params->sign_info_rsp;
+ our_master_id = &params->master_id_rsp;
+ our_enc_info = &params->enc_info_rsp;
+ our_id_info = &params->id_info_rsp;
+ } else {
+ our_key_dist = params->pair_rsp.resp_key_dist;
+ our_id_addr_info = &params->id_addr_info_req;
+ our_sign_info = &params->sign_info_req;
+ our_master_id = &params->master_id_req;
+ our_enc_info = &params->enc_info_req;
+ our_id_info = &params->id_info_req;
+ }
+
+ sc = params->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_SC &&
+ params->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_SC;
+
+ if (!sc && our_key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
+ ble_sm_test_util_verify_tx_enc_info(our_enc_info);
+ ble_sm_test_util_verify_tx_master_id(our_master_id);
+ }
+ if (our_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
+ ble_sm_test_util_verify_tx_id_info(our_id_info);
+ ble_sm_test_util_verify_tx_id_addr_info(our_id_addr_info);
+ }
+ if (our_key_dist & BLE_SM_PAIR_KEY_DIST_SIGN) {
+ ble_sm_test_util_verify_tx_sign_info(our_sign_info);
+ }
+}
+
+static void
+ble_sm_test_util_us_lgcy_good_once_no_init(
+ struct ble_sm_test_params *params,
+ struct ble_hs_conn *conn,
+ struct ble_sm_test_util_entity *our_entity,
+ struct ble_sm_test_util_entity *peer_entity)
+{
+ int rc;
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ ble_hs_test_util_hci_ack_set(
+ 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 {
+ /* Initiate the pairing procedure. */
+ rc = ble_gap_security_initiate(2);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /* Ensure we sent the expected pair request. */
+ ble_sm_test_util_verify_tx_pair_req(our_entity->pair_cmd);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair response from the peer. */
+ ble_sm_test_util_rx_pair_rsp(2, peer_entity->pair_cmd, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ ble_sm_test_util_io_inject(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+
+ /* Ensure we sent the expected pair confirm. */
+ ble_sm_test_util_verify_tx_pair_confirm(our_entity->confirms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair confirm from the peer. */
+ ble_sm_test_util_rx_confirm(2, peer_entity->confirms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair random. */
+ ble_sm_test_util_verify_tx_pair_random(our_entity->randoms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair random from the peer. */
+ ble_sm_test_util_rx_random(2, peer_entity->randoms, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected start encryption command. */
+ ble_sm_test_util_verify_tx_start_enc(2, 0, 0, params->stk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Receive key material from peer. */
+ ble_sm_test_util_rx_keys(params, 1);
+
+ /* Verify key material gets sent to peer. */
+ ble_sm_test_util_verify_tx_keys(params, 1);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted ==
+ conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ conn->bhc_sec_state.authenticated);
+
+ /* Verify the appropriate security material was persisted. */
+ ble_sm_test_util_verify_persist(params, 1);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+static void
+ble_sm_test_util_us_lgcy_good_once(struct ble_sm_test_params *params)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init_good(params, 1, &conn, &our_entity, &peer_entity);
+ ble_sm_test_util_us_lgcy_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+}
+
+void
+ble_sm_test_util_us_lgcy_good(struct ble_sm_test_params *params)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ /*** We are master. */
+
+ /* We initiate pairing. */
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_us_lgcy_good_once(params);
+
+ /* Peer initiates with security request. */
+ params->sec_req.authreq = params->pair_rsp.authreq;
+ ble_sm_test_util_us_lgcy_good_once(params);
+
+ /* Verify link can be restored via the encryption procedure. */
+ ble_sm_test_util_bonding_all(params, 1);
+
+ /* Verify programmatic unbonding. */
+ peer_addr.type = ble_hs_misc_peer_addr_type_to_id(params->resp_addr_type);
+ memcpy(peer_addr.val, params->resp_id_addr, sizeof peer_addr.val);
+ rc = ble_store_util_delete_peer(&peer_addr);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0);
+ TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0);
+}
+
+void
+ble_sm_test_util_peer_lgcy_good_once_no_init(
+ struct ble_sm_test_params *params,
+ struct ble_hs_conn *conn,
+ struct ble_sm_test_util_entity *our_entity,
+ struct ble_sm_test_util_entity *peer_entity)
+{
+ int rc;
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ if (params->sec_req.authreq != 0) {
+ rc = ble_sm_slave_initiate(2);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure we sent the expected security request. */
+ ble_sm_test_util_verify_tx_sec_req(&params->sec_req);
+ }
+
+ /* Receive a pair request from the peer. */
+ ble_sm_test_util_rx_pair_req(2, peer_entity->pair_cmd, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair response. */
+ ble_sm_test_util_verify_tx_pair_rsp(our_entity->pair_cmd);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ ble_sm_test_util_io_check_pre(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+
+ /* Receive a pair confirm from the peer. */
+ ble_sm_test_util_rx_confirm(2, peer_entity->confirms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ ble_sm_test_util_io_check_post(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+
+ /* Ensure we sent the expected pair confirm. */
+ ble_sm_test_util_verify_tx_pair_confirm(our_entity->confirms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair random from the peer. */
+ ble_sm_test_util_rx_random(2, peer_entity->randoms, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair random. */
+ ble_sm_test_util_verify_tx_pair_random(our_entity->randoms);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* 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_rx_lt_key_req(2, 0, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected long term key request reply command. */
+ ble_sm_test_util_verify_tx_lt_key_req_reply(2, params->stk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Verify key material gets sent to peer. */
+ ble_sm_test_util_verify_tx_keys(params, 0);
+
+ /* Receive key material from peer. */
+ ble_sm_test_util_rx_keys(params, 0);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted ==
+ conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ conn->bhc_sec_state.authenticated);
+
+ /* Verify the appropriate security material was persisted. */
+ ble_sm_test_util_verify_persist(params, 0);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+void
+ble_sm_test_util_peer_lgcy_good_once(struct ble_sm_test_params *params)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init_good(params, 0, &conn, &our_entity, &peer_entity);
+ ble_sm_test_util_peer_lgcy_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+}
+
+void
+ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ /*** Peer is master. */
+
+ /* Peer performs IO first; peer initiates pairing. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_peer_lgcy_good_once(params);
+
+ /* Peer performs IO first; we initiate with security request. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = params->pair_rsp.authreq;
+ ble_sm_test_util_peer_lgcy_good_once(params);
+
+ /* We perform IO first; peer initiates pairing. */
+ params->passkey_info.io_before_rx = 1;
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_peer_lgcy_good_once(params);
+
+ /* We perform IO first; we initiate with security request. */
+ params->passkey_info.io_before_rx = 1;
+ params->sec_req.authreq = params->pair_rsp.authreq;
+ ble_sm_test_util_peer_lgcy_good_once(params);
+
+ /* Verify link can be restored via the encryption procedure. */
+ ble_sm_test_util_bonding_all(params, 0);
+
+ /* Verify repeating pairing event generated when peer attempts to pair
+ * while bonded.
+ */
+ ble_sm_test_util_repeat_pairing(params, 0);
+
+ /* Verify programmatic unbonding. */
+ peer_addr.type = ble_hs_misc_peer_addr_type_to_id(params->init_addr_type);
+ memcpy(peer_addr.val, params->init_id_addr, sizeof peer_addr.val);
+ rc = ble_store_util_delete_peer(&peer_addr);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0);
+ TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0);
+}
+
+static void
+ble_sm_test_util_us_sc_good_once_no_init(
+ struct ble_sm_test_params *params,
+ struct ble_hs_conn *conn,
+ struct ble_sm_test_util_entity *our_entity,
+ struct ble_sm_test_util_entity *peer_entity)
+{
+ int num_iters;
+ int rc;
+ int i;
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ ble_hs_test_util_hci_ack_set(
+ 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 {
+ /* Initiate the pairing procedure. */
+ rc = ble_gap_security_initiate(2);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /* Ensure we sent the expected pair request. */
+ ble_sm_test_util_verify_tx_pair_req(our_entity->pair_cmd);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair response from the peer. */
+ ble_sm_test_util_rx_pair_rsp(2, peer_entity->pair_cmd, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected public key. */
+ ble_sm_test_util_verify_tx_public_key(our_entity->public_key);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a public key from the peer. */
+ ble_sm_test_util_rx_public_key(2, peer_entity->public_key);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ switch (params->pair_alg) {
+ case BLE_SM_PAIR_ALG_PASSKEY:
+ num_iters = 20;
+ break;
+
+ default:
+ num_iters = 1;
+ break;
+ }
+
+ ble_sm_test_util_io_inject(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+
+ for (i = 0; i < num_iters; i++) {
+ if (params->pair_alg != BLE_SM_PAIR_ALG_JW &&
+ params->pair_alg != BLE_SM_PAIR_ALG_NUMCMP) {
+
+ if (i < num_iters - 1) {
+ ble_sm_dbg_set_next_pair_rand(
+ our_entity->randoms[i + 1].value);
+ }
+
+ /* Ensure we sent the expected pair confirm. */
+ ble_sm_test_util_verify_tx_pair_confirm(our_entity->confirms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(
+ 2, params->passkey_info.passkey.action);
+ }
+
+ /* Receive a pair confirm from the peer. */
+ ble_sm_test_util_rx_confirm(2, peer_entity->confirms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair random. */
+ ble_sm_test_util_verify_tx_pair_random(our_entity->randoms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair random from the peer. */
+ ble_sm_test_util_rx_random(2, peer_entity->randoms + i, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+ }
+
+ ble_sm_test_util_io_inject(&params->passkey_info,
+ BLE_SM_PROC_STATE_DHKEY_CHECK);
+
+ /* Ensure we sent the expected dhkey check. */
+ ble_sm_test_util_verify_tx_dhkey_check(our_entity->dhkey_check);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a dhkey check from the peer. */
+ ble_sm_test_util_rx_dhkey_check(2, peer_entity->dhkey_check, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected start encryption command. */
+ ble_sm_test_util_verify_tx_start_enc(2, 0, 0, params->ltk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Receive key material from peer. */
+ ble_sm_test_util_rx_keys(params, 1);
+
+ /* Verify key material gets sent to peer. */
+ ble_sm_test_util_verify_tx_keys(params, 1);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted ==
+ conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ conn->bhc_sec_state.authenticated);
+
+ /* Verify the appropriate security material was persisted. */
+ ble_sm_test_util_verify_persist(params, 1);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+static void
+ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init_good(params, 1, &conn, &our_entity, &peer_entity);
+ ble_sm_test_util_us_sc_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+}
+
+void
+ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ /*** We are master. */
+
+ /* We initiate pairing. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_us_sc_good_once(params);
+
+ /* Peer initiates with security request. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = params->pair_rsp.authreq;
+ ble_sm_test_util_us_sc_good_once(params);
+
+ /* Verify link can be restored via the encryption procedure. */
+ ble_sm_test_util_bonding_all(params, 1);
+
+ /* Verify programmatic unbonding. */
+ peer_addr.type = ble_hs_misc_peer_addr_type_to_id(params->resp_addr_type);
+ memcpy(peer_addr.val, params->resp_id_addr, sizeof peer_addr.val);
+ rc = ble_store_util_delete_peer(&peer_addr);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0);
+ TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0);
+}
+
+static void
+ble_sm_test_util_peer_sc_good_once_no_init(
+ struct ble_sm_test_params *params,
+ struct ble_hs_conn *conn,
+ struct ble_sm_test_util_entity *our_entity,
+ struct ble_sm_test_util_entity *peer_entity)
+{
+ int num_iters;
+ int rc;
+ int i;
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ if (params->sec_req.authreq != 0) {
+ rc = ble_sm_slave_initiate(2);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure we sent the expected security request. */
+ ble_sm_test_util_verify_tx_sec_req(&params->sec_req);
+ }
+
+ /* Receive a pair request from the peer. */
+ ble_sm_test_util_rx_pair_req(2, peer_entity->pair_cmd, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair response. */
+ ble_sm_test_util_verify_tx_pair_rsp(our_entity->pair_cmd);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a public key from the peer. */
+ ble_sm_test_util_rx_public_key(2, peer_entity->public_key);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected public key. */
+ ble_sm_test_util_verify_tx_public_key(our_entity->public_key);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ switch (params->pair_alg) {
+ case BLE_SM_PAIR_ALG_PASSKEY:
+ num_iters = 20;
+ break;
+
+ default:
+ num_iters = 1;
+ break;
+ }
+
+ ble_sm_test_util_io_check_pre(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+
+ for (i = 0; i < num_iters; i++) {
+ if (params->pair_alg != BLE_SM_PAIR_ALG_JW &&
+ params->pair_alg != BLE_SM_PAIR_ALG_NUMCMP) {
+
+ /* Receive a pair confirm from the peer. */
+ ble_sm_test_util_rx_confirm(2, peer_entity->confirms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(
+ 2, params->passkey_info.passkey.action);
+
+ if (i < num_iters - 1) {
+ ble_sm_dbg_set_next_pair_rand(
+ our_entity->randoms[i + 1].value);
+ }
+ }
+
+ if (i == 0) {
+ ble_sm_test_util_io_check_post(&params->passkey_info,
+ BLE_SM_PROC_STATE_CONFIRM);
+ }
+
+ /* Ensure we sent the expected pair confirm. */
+ ble_sm_test_util_verify_tx_pair_confirm(our_entity->confirms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair random from the peer. */
+ ble_sm_test_util_rx_random(2, peer_entity->randoms + i, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected pair random. */
+ ble_sm_test_util_verify_tx_pair_random(our_entity->randoms + i);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ }
+
+ ble_sm_test_util_io_check_pre(&params->passkey_info,
+ BLE_SM_PROC_STATE_DHKEY_CHECK);
+
+ /* Receive a dhkey check from the peer. */
+ ble_sm_test_util_rx_dhkey_check(2, peer_entity->dhkey_check, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ ble_sm_test_util_io_check_post(&params->passkey_info,
+ BLE_SM_PROC_STATE_DHKEY_CHECK);
+
+ /* Ensure we sent the expected dhkey check. */
+ ble_sm_test_util_verify_tx_dhkey_check(our_entity->dhkey_check);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* 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_rx_lt_key_req(2, 0, 0);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Ensure we sent the expected long term key request reply command. */
+ ble_sm_test_util_verify_tx_lt_key_req_reply(2, params->ltk);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive an encryption changed event. */
+ ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+ /* Verify key material gets sent to peer. */
+ ble_sm_test_util_verify_tx_keys(params, 0);
+
+ /* Receive key material from peer. */
+ ble_sm_test_util_rx_keys(params, 0);
+
+ /* Pairing should now be complete. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was executed. */
+ 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);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(ble_sm_test_sec_state.encrypted ==
+ conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+ conn->bhc_sec_state.authenticated);
+
+ /* Verify the appropriate security material was persisted. */
+ ble_sm_test_util_verify_persist(params, 0);
+
+ ble_hs_test_util_conn_disconnect(2);
+}
+
+static void
+ble_sm_test_util_peer_sc_good_once(struct ble_sm_test_params *params)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_init_good(params, 0, &conn, &our_entity, &peer_entity);
+ ble_sm_test_util_peer_sc_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+}
+
+void
+ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params)
+{
+ ble_addr_t peer_addr;
+ int rc;
+
+ /*** Peer is master. */
+
+ /* Peer performs IO first; peer initiates pairing. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_peer_sc_good_once(params);
+
+ /* Peer performs IO first; we initiate with security request. */
+ params->passkey_info.io_before_rx = 0;
+ params->sec_req.authreq = params->pair_req.authreq;
+ ble_sm_test_util_peer_sc_good_once(params);
+
+ /* We perform IO first; peer initiates pairing. */
+ params->passkey_info.io_before_rx = 1;
+ params->sec_req.authreq = 0;
+ ble_sm_test_util_peer_sc_good_once(params);
+
+ /* We perform IO first; we initiate with security request. */
+ params->passkey_info.io_before_rx = 1;
+ params->sec_req.authreq = params->pair_req.authreq;
+ ble_sm_test_util_peer_sc_good_once(params);
+
+ /* Verify link can be restored via the encryption procedure. */
+ ble_sm_test_util_bonding_all(params, 0);
+
+ /* Verify repeating pairing event generated when peer attempts to pair
+ * while bonded.
+ */
+ ble_sm_test_util_repeat_pairing(params, 1);
+
+ /* Verify programmatic unbonding. */
+ peer_addr.type = ble_hs_misc_peer_addr_type_to_id(params->init_addr_type);
+ memcpy(peer_addr.val, params->init_id_addr, sizeof peer_addr.val);
+ rc = ble_store_util_delete_peer(&peer_addr);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_hs_test_util_num_our_secs() == 0);
+ TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0);
+}
+
+void
+ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ ble_sm_test_util_init();
+ ble_hs_id_set_pub(params->resp_id_addr);
+
+ ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
+
+ ble_hs_test_util_create_conn(2, params->init_id_addr,
+ 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
+ * can assume the connection list is unchanging.
+ */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Initiate the pairing procedure. */
+ rc = ble_hs_test_util_security_initiate(2, 0);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure we sent the expected pair request. */
+ ble_sm_test_util_verify_tx_pair_req(&params->pair_req);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 1);
+ ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action);
+
+ /* Receive a pair response from the peer. */
+ ble_sm_test_util_rx_pair_rsp(
+ 2, &params->pair_rsp, BLE_HS_SM_US_ERR(params->pair_fail.reason));
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Ensure we sent the expected pair fail. */
+ ble_sm_test_util_verify_tx_pair_fail(&params->pair_fail);
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify that security callback was not executed. */
+ TEST_ASSERT(ble_sm_test_gap_event_type == -1);
+ TEST_ASSERT(ble_sm_test_gap_status == -1);
+
+ /* Verify that connection has correct security state. */
+ TEST_ASSERT(!conn->bhc_sec_state.encrypted);
+ TEST_ASSERT(!conn->bhc_sec_state.authenticated);
+}
+
+static void
+ble_sm_test_util_repeat_pairing(struct ble_sm_test_params *params, int sc)
+{
+ struct ble_sm_test_util_entity peer_entity;
+ struct ble_sm_test_util_entity our_entity;
+ struct ble_hs_conn *conn;
+
+ ble_sm_test_util_params_to_entities(params, 0, &our_entity, &peer_entity);
+
+ ble_sm_test_repeat_pairing.params = *params;
+ ble_hs_id_set_pub(our_entity.id_addr);
+ ble_sm_dbg_set_next_pair_rand(our_entity.randoms[0].value);
+ ble_sm_dbg_set_next_ediv(our_entity.ediv);
+ ble_sm_dbg_set_next_master_id_rand(our_entity.rand_num);
+ ble_sm_dbg_set_next_ltk(our_entity.ltk);
+ ble_hs_test_util_set_our_irk(our_entity.id_info->irk, 0, 0);
+ ble_sm_dbg_set_next_csrk(our_entity.sign_info->sig_key);
+
+ ble_hs_test_util_create_rpa_conn(2, our_entity.addr_type, our_entity.rpa,
+ peer_entity.addr_type,
+ peer_entity.id_addr, peer_entity.rpa,
+ BLE_HS_TEST_CONN_FEAT_ALL,
+ ble_sm_test_util_conn_cb,
+ NULL);
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+ ble_hs_unlock();
+
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* First repeat pairing event: retry;
+ * Second repeat pairing event: ignore.
+ */
+ ble_sm_test_repeat_pairing.rc = BLE_GAP_REPEAT_PAIRING_RETRY;
+ ble_sm_test_repeat_pairing.next_rc = BLE_GAP_REPEAT_PAIRING_IGNORE;
+
+ /* Receive a pair request from the peer. */
+ ble_sm_test_util_rx_pair_req(2, peer_entity.pair_cmd, BLE_HS_EALREADY);
+
+ /* Verify repeat pairing event got reported twice. */
+ TEST_ASSERT(ble_sm_test_repeat_pairing.num_calls == 2);
+
+ /* Verify no pairing procedures in progress. */
+ TEST_ASSERT(ble_sm_num_procs() == 0);
+
+ /* Verify no SM messages were sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /*** Receive another pairing request. */
+
+ ble_sm_test_repeat_pairing.num_calls = 0;
+
+ /* First repeat pairing event: erase and retry. */
+ ble_sm_test_repeat_pairing.rc = BLE_GAP_REPEAT_PAIRING_RETRY;
+ ble_sm_test_repeat_pairing.erase_on_retry = 1;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+ ble_hs_unlock();
+
+ /* Receive a pair request from the peer; verify pairing procedure completes
+ * successfully.
+ */
+ if (!sc) {
+ ble_sm_test_util_peer_lgcy_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+ } else {
+ ble_sm_test_util_peer_sc_good_once_no_init(
+ params, conn, &our_entity, &peer_entity);
+ }
+
+ /* Verify repeat pairing event got reported once. */
+ TEST_ASSERT(ble_sm_test_repeat_pairing.num_calls == 1);
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.h b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.h
new file mode 100644
index 00000000..d8629b60
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_sm_test_util.h
@@ -0,0 +1,128 @@
+/*
+ * 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_SM_TEST_UTIL_
+#define H_BLE_SM_TEST_UTIL_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ble_sm_test_passkey_info {
+ struct ble_sm_io passkey;
+ uint32_t exp_numcmp;
+ unsigned io_before_rx:1;
+};
+
+struct ble_sm_test_params {
+ uint8_t init_addr_type;
+ uint8_t init_id_addr[6];
+ uint8_t init_rpa[6];
+ uint8_t resp_addr_type;
+ uint8_t resp_id_addr[6];
+ uint8_t resp_rpa[6];
+ struct ble_sm_test_passkey_info passkey_info;
+
+ struct ble_sm_sec_req sec_req;
+ struct ble_sm_pair_cmd pair_req;
+ struct ble_sm_pair_cmd pair_rsp;
+ struct ble_sm_pair_confirm confirm_req[20];
+ struct ble_sm_pair_confirm confirm_rsp[20];
+ struct ble_sm_pair_random random_req[20];
+ struct ble_sm_pair_random random_rsp[20];
+ struct ble_sm_id_info id_info_req;
+ struct ble_sm_id_info id_info_rsp;
+ struct ble_sm_id_addr_info id_addr_info_req;
+ struct ble_sm_id_addr_info id_addr_info_rsp;
+ struct ble_sm_sign_info sign_info_req;
+ struct ble_sm_sign_info sign_info_rsp;
+ struct ble_sm_pair_fail pair_fail;
+
+ int pair_alg;
+ unsigned authenticated:1;
+
+ /*** Secure connections fields. */
+ uint8_t ltk[16];
+ uint8_t our_priv_key[32];
+ struct ble_sm_public_key public_key_req;
+ struct ble_sm_public_key public_key_rsp;
+ struct ble_sm_dhkey_check dhkey_check_req;
+ struct ble_sm_dhkey_check dhkey_check_rsp;
+
+ /*** Legacy fields. */
+ uint8_t stk[16];
+ struct ble_sm_enc_info enc_info_req;
+ struct ble_sm_enc_info enc_info_rsp;
+ struct ble_sm_master_id master_id_req;
+ struct ble_sm_master_id master_id_rsp;
+};
+
+extern int ble_sm_test_gap_event;
+extern int ble_sm_test_gap_status;
+extern struct ble_gap_sec_state ble_sm_test_sec_state;
+
+extern int ble_sm_test_store_obj_type;
+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(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,
+ uint8_t correct_io_act);
+void ble_sm_test_util_io_check_pre(
+ struct ble_sm_test_passkey_info *passkey_info,
+ uint8_t cur_sm_state);
+void ble_sm_test_util_io_check_post(
+ struct ble_sm_test_passkey_info *passkey_info,
+ uint8_t cur_sm_state);
+void ble_sm_test_util_rx_sec_req(uint16_t conn_handle,
+ struct ble_sm_sec_req *cmd,
+ int exp_status);
+void ble_sm_test_util_verify_tx_pair_fail(struct ble_sm_pair_fail *exp_cmd);
+void ble_sm_test_util_us_lgcy_good(struct ble_sm_test_params *params);
+void ble_sm_test_util_peer_fail_inval(int we_are_master,
+ uint8_t *init_addr,
+ uint8_t *resp_addr,
+ struct ble_sm_pair_cmd *pair_req,
+ struct ble_sm_pair_fail *pair_fail);
+void ble_sm_test_util_peer_lgcy_fail_confirm(
+ uint8_t *init_addr,
+ uint8_t *resp_addr,
+ struct ble_sm_pair_cmd *pair_req,
+ struct ble_sm_pair_cmd *pair_rsp,
+ struct ble_sm_pair_confirm *confirm_req,
+ struct ble_sm_pair_confirm *confirm_rsp,
+ struct ble_sm_pair_random *random_req,
+ struct ble_sm_pair_random *random_rsp,
+ struct ble_sm_pair_fail *fail_rsp);
+
+void ble_sm_test_util_peer_lgcy_good_once(struct ble_sm_test_params *params);
+void ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params);
+void ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num);
+void ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params);
+void ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params);
+void ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_store_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_store_test.c
new file mode 100644
index 00000000..75d3a490
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_store_test.c
@@ -0,0 +1,435 @@
+/*
+ * 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 "testutil/testutil.h"
+#include "ble_hs_test.h"
+#include "ble_hs_test_util.h"
+
+static struct ble_store_status_event ble_store_test_status_event;
+
+static void
+ble_store_test_util_verify_peer_deleted(const ble_addr_t *addr)
+{
+ union ble_store_value value;
+ union ble_store_key key;
+ ble_addr_t addrs[64];
+ int num_addrs;
+ int rc;
+ int i;
+
+ memset(&key, 0, sizeof key);
+ key.sec.peer_addr = *addr;
+ rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+ rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, &key, &value);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ memset(&key, 0, sizeof key);
+ key.cccd.peer_addr = *addr;
+ rc = ble_store_read(BLE_STORE_OBJ_TYPE_CCCD, &key, &value);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ rc = ble_store_util_bonded_peers(addrs, &num_addrs,
+ sizeof addrs / sizeof addrs[0]);
+ TEST_ASSERT_FATAL(rc == 0);
+ for (i = 0; i < num_addrs; i++) {
+ TEST_ASSERT(ble_addr_cmp(addr, addrs + i) != 0);
+ }
+}
+
+static int
+ble_store_test_util_status_overflow(struct ble_store_status_event *event,
+ void *arg)
+{
+ int *status;
+
+ status = arg;
+
+ ble_store_test_status_event = *event;
+ return *status;
+}
+
+static void
+ble_store_test_util_overflow_sec(int is_our_sec)
+{
+ union ble_store_value val;
+ int obj_type;
+ int status;
+ int rc;
+ int i;
+
+ ble_hs_test_util_init();
+
+ ble_hs_cfg.store_status_cb = ble_store_test_util_status_overflow;
+ ble_hs_cfg.store_status_arg = &status;
+
+ if (is_our_sec) {
+ obj_type = BLE_STORE_OBJ_TYPE_OUR_SEC;
+ } else {
+ obj_type = BLE_STORE_OBJ_TYPE_PEER_SEC;
+ }
+
+ memset(&ble_store_test_status_event, 0,
+ sizeof ble_store_test_status_event);
+ memset(&val, 0, sizeof val);
+
+ val.sec.peer_addr =
+ (ble_addr_t){ BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } };
+ val.sec.ltk_present = 1,
+
+ status = BLE_HS_ESTORE_CAP;
+ for (i = 0; ; i++) {
+ rc = ble_store_write(obj_type, &val);
+ if (i < MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
+ TEST_ASSERT_FATAL(rc == 0);
+ } else {
+ /* This record should have caused an overflow. */
+ TEST_ASSERT(rc == BLE_HS_ESTORE_CAP);
+ TEST_ASSERT(ble_store_test_status_event.event_code ==
+ BLE_STORE_EVENT_OVERFLOW);
+ TEST_ASSERT(ble_store_test_status_event.overflow.obj_type ==
+ obj_type);
+ TEST_ASSERT(ble_store_test_status_event.overflow.value == &val);
+ break;
+ }
+
+ val.sec.peer_addr.val[0]++;
+ }
+}
+
+static int
+ble_store_test_util_count(int obj_type)
+{
+ int count;
+ int rc;
+
+ rc = ble_store_util_count(obj_type, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ return count;
+}
+
+TEST_CASE_SELF(ble_store_test_peers)
+{
+ struct ble_store_value_sec secs[3] = {
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ /* Address value is a duplicate of above, but type differs. */
+ .peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
+ .ltk_present = 1,
+ },
+ };
+ ble_addr_t peer_addrs[3];
+ int num_addrs;
+ int rc;
+ int i;
+
+ ble_hs_test_util_init();
+
+ for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
+ rc = ble_store_write_our_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_store_write_peer_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ rc = ble_store_util_bonded_peers(peer_addrs, &num_addrs,
+ sizeof peer_addrs / sizeof peer_addrs[0]);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ TEST_ASSERT(num_addrs == sizeof secs / sizeof secs[0]);
+ for (i = 0; i < num_addrs; i++) {
+ TEST_ASSERT(ble_addr_cmp(&peer_addrs[i], &secs[i].peer_addr) == 0);
+ }
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_store_test_delete_peer)
+{
+ struct ble_store_value_sec secs[2] = {
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ /* Address value is a duplicate of above, but type differs. */
+ .peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ };
+ struct ble_store_value_cccd cccds[3] = {
+ /* First two belong to first peer. */
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 5,
+ },
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 8,
+ },
+
+ /* Last belongs to second peer. */
+ {
+ .peer_addr = secs[1].peer_addr,
+ .chr_val_handle = 5,
+ },
+ };
+ union ble_store_value value;
+ union ble_store_key key;
+ int count;
+ int rc;
+ int i;
+
+ ble_hs_test_util_init();
+
+ for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
+ rc = ble_store_write_our_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_store_write_peer_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ for (i = 0; i < sizeof cccds / sizeof cccds[0]; i++) {
+ rc = ble_store_write_cccd(cccds + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /* Delete first peer. */
+ rc = ble_store_util_delete_peer(&secs[0].peer_addr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure all traces of first peer have been removed. */
+ ble_store_test_util_verify_peer_deleted(&secs[0].peer_addr);
+
+ /* Ensure second peer data is still intact. */
+ ble_store_key_from_value_sec(&key.sec, secs + 1);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 1);
+
+ rc = ble_store_read_our_sec(&key.sec, &value.sec);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(memcmp(&value.sec, secs + 1, sizeof value.sec) == 0);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 1);
+
+ rc = ble_store_read_peer_sec(&key.sec, &value.sec);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(memcmp(&value.sec, secs + 1, sizeof value.sec) == 0);
+
+ ble_store_key_from_value_cccd(&key.cccd, cccds + 2);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 1);
+
+ rc = ble_store_read_cccd(&key.cccd, &value.cccd);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(memcmp(&value.cccd, cccds + 2, sizeof value.cccd) == 0);
+
+ /* Delete second peer. */
+ rc = ble_store_util_delete_peer(&secs[1].peer_addr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ /* Ensure all traces of first peer have been removed. */
+ ble_store_test_util_verify_peer_deleted(&secs[1].peer_addr);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_store_test_count)
+{
+ struct ble_store_value_sec secs[4] = {
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ .peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
+ .ltk_present = 1,
+ },
+ {
+ .peer_addr = { BLE_ADDR_RANDOM, { 3, 4, 5, 6, 7, 8 } },
+ .ltk_present = 1,
+ },
+ };
+ struct ble_store_value_cccd cccds[2] = {
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 5,
+ },
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 8,
+ },
+ };
+ int count;
+ int rc;
+ int i;
+
+ ble_hs_test_util_init();
+
+ /*** Verify initial counts are 0. */
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 0);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 0);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 0);
+
+ /* Write some test data. */
+
+ for (i = 0; i < 3; i++) {
+ rc = ble_store_write_our_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+ for (i = 0; i < 2; i++) {
+ rc = ble_store_write_peer_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+ for (i = 0; i < 1; i++) {
+ rc = ble_store_write_cccd(cccds + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /*** Verify counts after populating store. */
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 3);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 2);
+
+ rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(count == 1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_store_test_overflow)
+{
+ ble_store_test_util_overflow_sec(0);
+ ble_store_test_util_overflow_sec(1);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_CASE_SELF(ble_store_test_clear)
+{
+ const struct ble_store_value_sec secs[2] = {
+ {
+ .peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ {
+ /* Address value is a duplicate of above, but type differs. */
+ .peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
+ .ltk_present = 1,
+ },
+ };
+ const struct ble_store_value_cccd cccds[3] = {
+ /* First two belong to first peer. */
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 5,
+ },
+ {
+ .peer_addr = secs[0].peer_addr,
+ .chr_val_handle = 8,
+ },
+
+ /* Last belongs to second peer. */
+ {
+ .peer_addr = secs[1].peer_addr,
+ .chr_val_handle = 5,
+ },
+ };
+ int rc;
+ int i;
+
+ ble_hs_test_util_init();
+
+ for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
+ rc = ble_store_write_our_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ rc = ble_store_write_peer_sec(secs + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ for (i = 0; i < sizeof cccds / sizeof cccds[0]; i++) {
+ rc = ble_store_write_cccd(cccds + i);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+
+ /* Sanity check. */
+ TEST_ASSERT_FATAL(
+ ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 2);
+ TEST_ASSERT_FATAL(
+ ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 2);
+ TEST_ASSERT_FATAL(
+ ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 3);
+
+ /* Ensure store is empty after clear gets called. */
+ rc = ble_store_clear();
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 0);
+
+ /* Ensure second clear succeeds with no effect. */
+ rc = ble_store_clear();
+ TEST_ASSERT_FATAL(rc == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 0);
+ TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_store_suite)
+{
+ ble_store_test_peers();
+ ble_store_test_delete_peer();
+ ble_store_test_count();
+ ble_store_test_overflow();
+ ble_store_test_clear();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_uuid_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_uuid_test.c
new file mode 100644
index 00000000..786e371a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_uuid_test.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <stddef.h>
+#include <string.h>
+#include "testutil/testutil.h"
+#include "ble_hs_test.h"
+#include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
+
+TEST_CASE_SELF(ble_uuid_test)
+{
+ uint8_t buf_16[2] = { 0x00, 0x18 };
+ uint8_t buf_128[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
+
+ const ble_uuid_t *uuid16_1 = BLE_UUID16_DECLARE(0x1800);
+ const ble_uuid_t *uuid16_2 = BLE_UUID16_DECLARE(0x1801);
+
+ const ble_uuid_t *uuid128_1 =
+ BLE_UUID128_DECLARE(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF);
+ const ble_uuid_t *uuid128_2 =
+ BLE_UUID128_DECLARE(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE);
+
+ ble_uuid_any_t uuid;
+ int rc;
+
+ rc = ble_uuid_init_from_buf(&uuid, buf_16, 2);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_uuid_cmp(&uuid.u, uuid16_1);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_uuid_cmp(&uuid.u, uuid16_2);
+ TEST_ASSERT(rc != 0);
+
+ rc = ble_uuid_cmp(uuid16_1, uuid16_2);
+ TEST_ASSERT(rc != 0);
+
+ rc = ble_uuid_init_from_buf(&uuid, buf_128, 16);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_uuid_cmp(&uuid.u, uuid128_1);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_uuid_cmp(&uuid.u, uuid128_2);
+ TEST_ASSERT(rc != 0);
+
+ rc = ble_uuid_cmp(uuid128_1, uuid128_2);
+ TEST_ASSERT(rc != 0);
+
+ ble_hs_test_util_assert_mbufs_freed(NULL);
+}
+
+TEST_SUITE(ble_uuid_test_suite)
+{
+ ble_uuid_test();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/test/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/test/syscfg.yml
new file mode 100644
index 00000000..6307398e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/test/syscfg.yml
@@ -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.
+#
+
+syscfg.vals:
+ BLE_HS_DEBUG: 1
+ BLE_HS_PHONY_HCI_ACKS: 1
+ BLE_HS_REQUIRE_OS: 0
+ BLE_MAX_CONNECTIONS: 8
+ BLE_GATT_MAX_PROCS: 16
+ BLE_SM: 1
+ BLE_SM_SC: 1
+ MSYS_1_BLOCK_COUNT: 100
+ BLE_L2CAP_COC_MAX_NUM: 2
+ CONFIG_FCB: 1
+ BLE_VERSION: 52
+ BLE_L2CAP_ENHANCED_COC: 1