| /* |
| * 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 "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; |
| } |