/* * 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 #include #include #include "nimble/hci_common.h" #include "nimble/ble_hci_trans.h" #include "host/ble_hs_test.h" #include "testutil/testutil.h" #include "ble_hs_test_util.h" TEST_CASE(ble_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(buf); TEST_ASSERT(rc == BLE_HS_ENOTSUP); } TEST_CASE(ble_hs_hci_test_rssi) { uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN]; uint16_t opcode; int8_t rssi; int rc; opcode = 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); } TEST_CASE(ble_hs_hci_acl_one_conn) { struct ble_hs_test_util_hci_num_completed_pkts_entry ncpe[2]; struct hci_disconn_complete evt; 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 (+ 4-byte header). */ rc = ble_hs_hci_set_buf_sz(24, 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. */ evt.connection_handle = 1; evt.status = 0; evt.reason = BLE_ERR_CONN_TERM_LOCAL; ble_hs_test_util_hci_rx_disconn_complete_event(&evt); TEST_ASSERT_FATAL(ble_hs_hci_avail_pkts == 5); } TEST_CASE(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 (+ 4-byte header). */ rc = ble_hs_hci_set_buf_sz(24, 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); } TEST_SUITE(ble_hs_hci_suite) { tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); ble_hs_hci_test_event_bad(); ble_hs_hci_test_rssi(); ble_hs_hci_acl_one_conn(); ble_hs_hci_acl_two_conn(); } int ble_hs_hci_test_all(void) { ble_hs_hci_suite(); return tu_any_failed; }