/*
|
* 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/transport.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_transport_alloc_evt(0);
|
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();
|
}
|