/*
|
* 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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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,
|
¶m_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. This is acceptable now with the wl_set API
|
* change. */
|
rc = ble_hs_test_util_wl_set(NULL, 0, 0, 0);
|
TEST_ASSERT(rc == 0);
|
|
/*** 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, ¶ms,
|
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(¶ms, 0, sizeof params);
|
params.limited = limited;
|
|
rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, 0, ¶ms,
|
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, ¶ms,
|
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(¶ms,
|
BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
|
|
/* Rejected L2CAP. */
|
ble_gap_test_util_update_l2cap(¶ms,
|
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(¶ms, 0, sizeof params);
|
|
/* Initiate a discovery procedure with no timeout. */
|
ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC,
|
BLE_HS_FOREVER, ¶ms, 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(¶ms, 0, sizeof params);
|
|
/* Initiate a discovery procedure with the specified timeout. */
|
ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC,
|
duration_ms, ¶ms, 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(¶ms, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
|
|
/* L2CAP - Remote unsupported; L2CAP timeout. */
|
ble_gap_test_util_update_l2cap_tmo(¶ms, 0, BLE_ERR_UNSUPP_REM_FEATURE,
|
0);
|
|
/* L2CAP - Remote unsupported; LL timeout. */
|
ble_gap_test_util_update_l2cap_tmo(¶ms, 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();
|
}
|