You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/09/22 02:13:00 UTC

[53/59] [abbrv] incubator-mynewt-core git commit: Merge branch 'develop' into sterly_refactor

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/test/src/ble_gap_test.c
----------------------------------------------------------------------
diff --cc net/nimble/host/test/src/ble_gap_test.c
index 16a7309,0000000..3fe398f
mode 100644,000000..100644
--- a/net/nimble/host/test/src/ble_gap_test.c
+++ b/net/nimble/host/test/src/ble_gap_test.c
@@@ -1,2580 -1,0 +1,2920 @@@
 +/**
 + * 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 "host/ble_hs_test.h"
 +#include "ble_hs_test_util.h"
 +
- static int ble_gap_test_conn_event_type;
++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 int
- ble_gap_test_util_update_in_progress(uint16_t conn_handle)
- {
-     ble_hs_conn_flags_t conn_flags;
-     int rc;
- 
-     rc = ble_hs_atomic_conn_flags(conn_handle, &conn_flags);
-     return rc == 0 && conn_flags & BLE_HS_CONN_F_UPDATE;
- }
- 
 +static void
 +ble_gap_test_util_reset_cb_info(void)
 +{
-     ble_gap_test_conn_event_type = -1;
++    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();
 +    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;
 +
-     ble_gap_test_conn_event_type = event->type;
++    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;
 +        ble_gap_conn_find(event->connect.conn_handle, &ble_gap_test_conn_desc);
 +        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;
 +        ble_gap_conn_find(event->conn_update.conn_handle,
 +                          &ble_gap_test_conn_desc);
 +        break;
 +
 +    case BLE_GAP_EVENT_CONN_CANCEL:
 +        break;
 +
 +    case BLE_GAP_EVENT_TERM_FAILURE:
 +        ble_gap_test_conn_status = event->term_failure.status;
 +        ble_gap_conn_find(event->term_failure.conn_handle,
 +                          &ble_gap_test_conn_desc);
 +        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;
 +        ble_gap_conn_find(event->conn_update_req.conn_handle,
 +                          &ble_gap_test_conn_desc);
 +
 +        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 void
 +ble_gap_test_util_verify_tx_clear_wl(void)
 +{
 +    uint8_t param_len;
 +
 +    ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                   BLE_HCI_OCF_LE_CLEAR_WHITE_LIST,
 +                                   &param_len);
 +    TEST_ASSERT(param_len == 0);
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_add_wl(struct ble_gap_white_entry *entry)
 +{
 +    uint8_t param_len;
 +    uint8_t *param;
 +    int i;
 +
 +    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_ADD_WHITE_LIST,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == 7);
 +    TEST_ASSERT(param[0] == entry->addr_type);
 +    for (i = 0; i < 6; i++) {
 +        TEST_ASSERT(param[1 + i] == entry->addr[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_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_SET_SCAN_PARAM_LEN);
 +    TEST_ASSERT(param[0] == scan_type);
 +    TEST_ASSERT(le16toh(param + 1) == itvl);
 +    TEST_ASSERT(le16toh(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_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_SET_SCAN_ENABLE_LEN);
 +    TEST_ASSERT(param[0] == enable);
 +    TEST_ASSERT(param[1] == filter_duplicates);
 +}
 +
 +static void
 +ble_hs_test_util_verify_tx_create_conn_cancel(void)
 +{
 +    uint8_t param_len;
 +
 +    ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                   BLE_HCI_OCF_LE_CREATE_CONN_CANCEL,
 +                                   &param_len);
 +    TEST_ASSERT(param_len == 0);
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_disconnect(void)
 +{
 +    uint8_t param_len;
 +    uint8_t *param;
 +
 +    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LINK_CTRL,
 +                                           BLE_HCI_OCF_DISCONNECT_CMD,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_DISCONNECT_CMD_LEN);
 +    TEST_ASSERT(le16toh(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_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                   BLE_HCI_OCF_LE_SET_ADV_PARAMS,
 +                                   &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_SET_ADV_PARAM_LEN);
 +
 +    /* Note: Content of message verified in ble_hs_adv_test.c. */
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_adv_data(void)
 +{
 +    uint8_t param_len;
 +
 +    ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                   BLE_HCI_OCF_LE_SET_ADV_DATA,
 +                                   &param_len);
 +    /* Note: Content of message verified in ble_hs_adv_test.c. */
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_rsp_data(void)
 +{
 +    uint8_t param_len;
 +    uint8_t *param;
 +
 +    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA,
 +                                           &param_len);
 +    (void)param; /* XXX: Verify other fields. */
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_adv_enable(int enabled)
 +{
 +    uint8_t param_len;
 +    uint8_t *param;
 +
 +    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_SET_ADV_ENABLE,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_SET_ADV_ENABLE_LEN);
 +    TEST_ASSERT(param[0] == !!enabled);
 +}
 +
 +static void
 +ble_gap_test_util_verify_tx_update_conn(struct ble_gap_upd_params *params)
 +{
 +    uint8_t param_len;
 +    uint8_t *param;
 +
 +    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_CONN_UPDATE,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN);
 +    TEST_ASSERT(le16toh(param + 0) == 2);
 +    TEST_ASSERT(le16toh(param + 2) == params->itvl_min);
 +    TEST_ASSERT(le16toh(param + 4) == params->itvl_max);
 +    TEST_ASSERT(le16toh(param + 6) == params->latency);
 +    TEST_ASSERT(le16toh(param + 8) == params->supervision_timeout);
 +    TEST_ASSERT(le16toh(param + 10) == params->min_ce_len);
 +    TEST_ASSERT(le16toh(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_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_CONN_PARAM_REPLY_LEN);
 +    TEST_ASSERT(le16toh(param + 0) == 2);
 +    TEST_ASSERT(le16toh(param + 2) == ble_gap_test_conn_self_params.itvl_min);
 +    TEST_ASSERT(le16toh(param + 4) == ble_gap_test_conn_self_params.itvl_max);
 +    TEST_ASSERT(le16toh(param + 6) == ble_gap_test_conn_self_params.latency);
 +    TEST_ASSERT(le16toh(param + 8) ==
 +                ble_gap_test_conn_self_params.supervision_timeout);
 +    TEST_ASSERT(le16toh(param + 10) ==
 +                ble_gap_test_conn_self_params.min_ce_len);
 +    TEST_ASSERT(le16toh(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_verify_tx_hci(BLE_HCI_OGF_LE,
 +                                           BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
 +                                           &param_len);
 +    TEST_ASSERT(param_len == BLE_HCI_CONN_PARAM_NEG_REPLY_LEN);
 +    TEST_ASSERT(le16toh(param + 0) == 2);
 +    TEST_ASSERT(param[2] == reason);
 +}
 +
 +static void
 +ble_gap_test_util_rx_update_complete(
 +    uint8_t status,
-     struct ble_gap_upd_params *params)
++    const struct ble_gap_upd_params *params)
 +{
 +    struct hci_le_conn_upd_complete evt;
 +
 +    evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
 +    evt.status = status;
 +    evt.connection_handle = 2;
 +    evt.conn_itvl = params->itvl_max;
 +    evt.conn_latency = params->latency;
 +    evt.supervision_timeout = 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 hci_le_conn_param_req evt;
 +    uint16_t opcode;
 +    uint8_t hci_status;
 +
 +    evt.subevent_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
 +    evt.connection_handle = 2;
 +    evt.itvl_min = params->itvl_min;
 +    evt.itvl_max = params->itvl_max;
 +    evt.latency = 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_set_ack(opcode, hci_status);
 +    ble_gap_rx_param_req(&evt);
 +
 +    return hci_status;
 +}
 +
 +/*****************************************************************************
 + * $white list                                                               *
 + *****************************************************************************/
 +
 +static void
 +ble_gap_test_util_wl_set(struct ble_gap_white_entry *white_list,
 +                         int white_list_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(white_list, white_list_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 < white_list_count; i++) {
 +        ble_gap_test_util_verify_tx_add_wl(white_list + i);
 +        if (cmd_idx >= cmd_fail_idx) {
 +            return;
 +        }
 +        cmd_idx++;
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_wl_bad_args)
 +{
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    /*** 0 white list entries. */
 +    rc = ble_hs_test_util_wl_set(NULL, 0, 0, 0);
 +    TEST_ASSERT(rc == BLE_HS_EINVAL);
 +
 +    /*** Invalid address type. */
 +    rc = ble_hs_test_util_wl_set(
 +        ((struct ble_gap_white_entry[]) { {
 +            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_ADDR_TYPE_PUBLIC,
 +                                  BLE_GAP_ADDR_TYPE_WL, NULL, 0, NULL,
 +                                  ble_gap_test_util_connect_cb, NULL, 0);
 +    TEST_ASSERT(rc == 0);
 +
 +    rc = ble_hs_test_util_wl_set(
 +        ((struct ble_gap_white_entry[]) { {
 +            BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 }
 +        }, }),
 +        1, 0, 0);
 +    TEST_ASSERT(rc == BLE_HS_EBUSY);
 +}
 +
 +TEST_CASE(ble_gap_test_case_wl_ctlr_fail)
 +{
 +    int i;
 +
 +    struct ble_gap_white_entry white_list[] = {
 +        { BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 3, 4, 5, 6, 7, 8 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 4, 5, 6, 7, 8, 9 } },
 +    };
 +    int white_list_count = sizeof white_list / sizeof white_list[0];
 +
 +    for (i = 0; i < 5; i++) {
 +        ble_gap_test_util_wl_set(white_list, white_list_count, i,
 +                                 BLE_ERR_UNSPECIFIED);
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_wl_good)
 +{
 +    struct ble_gap_white_entry white_list[] = {
 +        { BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 3, 4, 5, 6, 7, 8 } },
 +        { BLE_ADDR_TYPE_PUBLIC, { 4, 5, 6, 7, 8, 9 } },
 +    };
 +    int white_list_count = sizeof white_list / sizeof white_list[0];
 +
 +    ble_gap_test_util_wl_set(white_list, white_list_count, 0, 0);
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_wl)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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(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_ADDR_TYPE_PUBLIC, 0, &params,
 +                      ble_gap_test_util_disc_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EINVAL);
 +}
 +
 +TEST_CASE(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_type = BLE_ADDR_TYPE_PUBLIC,
 +        .length_data = 0,
 +        .rssi = 0,
 +        .addr = { 1, 2, 3, 4, 5, 6 },
 +        .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,
 +                             desc.data, &desc.length_data,
 +                             sizeof adv_data);
 +    TEST_ASSERT_FATAL(rc == 0);
 +
 +    for (own_addr_type = 0;
 +         own_addr_type <= BLE_ADDR_TYPE_RPA_RND_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_TYPE_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, desc.addr, 6) == 0);
 +        TEST_ASSERT(ble_gap_test_disc_arg == NULL);
 +
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_disc_ltd_mismatch)
 +{
 +    int rc;
 +    struct ble_gap_disc_desc desc = {
 +        .event_type = BLE_HCI_ADV_TYPE_ADV_IND,
 +        .addr_type = BLE_ADDR_TYPE_PUBLIC,
 +        .length_data = 0,
 +        .rssi = 0,
 +        .addr = { 1, 2, 3, 4, 5, 6 },
 +        .data = (uint8_t[BLE_HCI_MAX_ADV_DATA_LEN]){
 +            2, 
 +            BLE_HS_ADV_TYPE_FLAGS,
 +            BLE_HS_ADV_F_DISC_GEN,
 +        },
 +    };
 +    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_ADDR_TYPE_PUBLIC, &disc_params, &desc,
 +                                -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);
 +
 +    desc.data[2] = BLE_HS_ADV_F_DISC_LTD;
 +    disc_params.limited = 0;
 +    rc = ble_gap_test_util_disc(BLE_ADDR_TYPE_PUBLIC, &disc_params, &desc,
 +                                -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(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,
 +        .addr_type = BLE_ADDR_TYPE_PUBLIC,
 +        .length_data = 0,
 +        .rssi = 0,
 +        .addr = { 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_ADDR_TYPE_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());
 +        }
 +    }
 +}
 +
 +static void
 +ble_gap_test_util_disc_dflts_once(int limited)
 +{
 +    struct ble_gap_disc_params params;
 +    uint16_t exp_window;
 +    uint16_t exp_itvl;
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    memset(&params, 0, sizeof params);
 +    params.limited = limited;
 +
 +    rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_PUBLIC, 0, &params,
 +                               ble_gap_test_util_disc_cb, NULL, -1, 0);
 +    TEST_ASSERT_FATAL(rc == 0);
 +
 +    if (limited) {
 +        exp_itvl = BLE_GAP_LIM_DISC_SCAN_INT;
 +        exp_window = BLE_GAP_LIM_DISC_SCAN_WINDOW;
 +    } else {
 +        exp_itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN;
 +        exp_window = BLE_GAP_SCAN_FAST_WINDOW;
 +    }
 +    ble_gap_test_util_verify_tx_set_scan_params(
 +        BLE_ADDR_TYPE_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(ble_gap_test_case_disc_dflts)
 +{
 +    ble_gap_test_util_disc_dflts_once(0);
 +    ble_gap_test_util_disc_dflts_once(1);
 +}
 +
 +TEST_CASE(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_ADDR_TYPE_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_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER, &disc_params,
 +                               ble_gap_test_util_disc_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EALREADY);
 +}
 +
 +TEST_CASE(ble_gap_test_case_disc_busy)
 +{
 +    static const struct ble_gap_disc_params disc_params = { 0 };
 +    static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    /* Start a connect procedure. */
 +    rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_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_ADDR_TYPE_PUBLIC, BLE_HS_FOREVER, &disc_params,
 +                               ble_gap_test_util_disc_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EBUSY);
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_disc)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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(ble_gap_test_case_conn_gen_good)
 +{
 +    struct hci_le_conn_complete evt;
 +    struct ble_gap_conn_params params;
 +    int rc;
 +
 +    uint8_t peer_addr[6] = { 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_ADDR_TYPE_PUBLIC,
 +                                  BLE_ADDR_TYPE_PUBLIC, peer_addr, 0, &params,
 +                                  ble_gap_test_util_connect_cb, NULL, 0);
 +    TEST_ASSERT(rc == 0);
 +
 +    TEST_ASSERT(ble_gap_master_in_progress());
 +    TEST_ASSERT(ble_gap_conn_active());
 +
 +    TEST_ASSERT(ble_gap_master_in_progress());
 +    TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == BLE_HS_ENOTCONN);
 +
 +    /* Receive connection complete event. */
 +    memset(&evt, 0, sizeof evt);
 +    evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
 +    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);
 +    TEST_ASSERT(rc == 0);
 +
 +    TEST_ASSERT(!ble_gap_master_in_progress());
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONNECT);
++    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,
 +                       peer_addr, 6) == 0);
 +
 +    TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
 +}
 +
 +TEST_CASE(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_ADDR_TYPE_PUBLIC, 5,
 +                         ((uint8_t[]){ 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_ADDR_TYPE_PUBLIC,
 +                                  BLE_ADDR_TYPE_PUBLIC,
 +                                  ((uint8_t[]){ 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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                         ((uint8_t[]){ 1, 2, 3, 4, 5, 6 }), 0, NULL,
 +                         ble_gap_test_util_connect_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EALREADY);
 +}
 +
 +TEST_CASE(ble_gap_test_case_conn_gen_dflt_params)
 +{
 +    static const uint8_t peer_addr[6] = { 2, 3, 8, 6, 6, 1 };
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
 +                                  BLE_ADDR_TYPE_PUBLIC, peer_addr, 0, NULL,
 +                                  ble_gap_test_util_connect_cb, NULL, 0);
 +    TEST_ASSERT(rc == 0);
 +}
 +
 +TEST_CASE(ble_gap_test_case_conn_gen_already)
 +{
 +    static const struct ble_gap_conn_params conn_params = { 0 };
 +    static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    /* Start a connect procedure. */
 +    rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                         peer_addr, BLE_HS_FOREVER, &conn_params,
 +                         ble_gap_test_util_connect_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EALREADY);
 +}
 +
 +TEST_CASE(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 uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    /* Start a discovery procedure. */
 +    rc = ble_hs_test_util_disc(BLE_ADDR_TYPE_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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                         peer_addr, BLE_HS_FOREVER, &conn_params,
 +                         ble_gap_test_util_connect_cb, NULL);
 +    TEST_ASSERT(rc == BLE_HS_EBUSY);
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_conn_gen)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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_busy();
 +}
 +
 +/*****************************************************************************
 + * $cancel                                                                   *
 + *****************************************************************************/
 +
 +static void
 +ble_gap_test_util_conn_cancel(uint8_t hci_status)
 +{
 +    struct hci_le_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_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.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
 +    evt.status = BLE_ERR_UNK_CONN_ID;
 +    rc = ble_gap_rx_conn_complete(&evt);
 +    TEST_ASSERT(rc == 0);
 +    TEST_ASSERT(!ble_gap_master_in_progress());
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_CANCEL);
++    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
 +}
 +
 +static void
 +ble_gap_test_util_conn_and_cancel(uint8_t *peer_addr, uint8_t hci_status)
 +{
 +    int rc;
 +
 +    ble_gap_test_util_init();
 +
 +    /* Begin creating a connection. */
 +    rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC,
 +                                  BLE_ADDR_TYPE_PUBLIC, peer_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(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);
 +}
 +
 +TEST_CASE(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_conn_event_type == BLE_GAP_EVENT_CONN_CANCEL);
++    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
 +    TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == BLE_HS_CONN_HANDLE_NONE);
 +}
 +
 +TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
 +{
 +    struct hci_le_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_conn_event_type == -1);
++    TEST_ASSERT(ble_gap_test_event.type == 0xff);
 +
 +    /* Allow connection complete to succeed. */
 +    memset(&evt, 0, sizeof evt);
 +    evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
 +    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);
 +    TEST_ASSERT(rc == 0);
 +
 +    TEST_ASSERT(!ble_gap_master_in_progress());
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONNECT);
++    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,
 +                       peer_addr, 6) == 0);
 +
 +    TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_conn_cancel)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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 hci_disconn_complete 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_conn_event_type = -1;
++    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.connection_handle = 2;
 +        evt.status = 0;
 +        evt.reason = BLE_ERR_CONN_TERM_LOCAL;
 +        ble_gap_rx_disconn_complete(&evt);
 +    }
 +}
 +
 +TEST_CASE(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);
 +}
 +
 +TEST_CASE(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_conn_event_type == BLE_GAP_EVENT_DISCONNECT);
++    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_TYPE_PUBLIC);
 +    TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
 +                       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());
 +}
 +
 +TEST_CASE(ble_gap_test_case_conn_terminate_ctlr_fail)
 +{
 +    struct hci_disconn_complete 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.connection_handle = 2;
 +    evt.status = BLE_ERR_UNSUPPORTED;
 +    evt.reason = 0;
 +    ble_gap_rx_disconn_complete(&evt);
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_TERM_FAILURE);
++    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_TYPE_PUBLIC);
 +    TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
 +                       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());
 +}
 +
 +TEST_CASE(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_conn_event_type == -1);
++    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());
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_conn_terminate)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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(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();
 +
 +    ble_hs_test_util_create_rpa_conn(8,
 +                                     BLE_ADDR_TYPE_PUBLIC,
 +                                     ((uint8_t[6]){0,0,0,0,0,0}),
 +                                     BLE_ADDR_TYPE_PUBLIC,
 +                                     ((uint8_t[6]){2,3,4,5,6,7}),
 +                                     ((uint8_t[6]){0,0,0,0,0,0}),
 +                                     ble_gap_test_util_connect_cb,
 +                                     NULL);
 +
 +
 +    rc = ble_hs_id_copy_addr(BLE_ADDR_TYPE_PUBLIC, pub_addr, NULL);
 +    TEST_ASSERT_FATAL(rc == 0);
 +
 +    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_TYPE_PUBLIC);
 +    TEST_ASSERT(desc.our_ota_addr_type == BLE_ADDR_TYPE_PUBLIC);
 +    TEST_ASSERT(desc.peer_ota_addr_type == BLE_ADDR_TYPE_PUBLIC);
 +    TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
 +    TEST_ASSERT(memcmp(desc.our_ota_addr, pub_addr, 6) == 0);
 +    TEST_ASSERT(memcmp(desc.our_id_addr, pub_addr, 6) == 0);
 +    TEST_ASSERT(memcmp(desc.peer_ota_addr,
 +                       ((uint8_t[6]){2,3,4,5,6,7}), 6) == 0);
 +    TEST_ASSERT(memcmp(desc.peer_id_addr,
 +                       ((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();
 +
 +    ble_hs_test_util_create_rpa_conn(54,
 +                                     BLE_ADDR_TYPE_RPA_PUB_DEFAULT,
 +                                     ((uint8_t[6]){0x40,1,2,3,4,5}),
 +                                     BLE_ADDR_TYPE_RPA_RND_DEFAULT,
 +                                     ((uint8_t[6]){3,4,5,6,7,8}),
 +                                     ((uint8_t[6]){0x50,1,2,3,4,5}),
 +                                     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_TYPE_PUBLIC);
 +    TEST_ASSERT(desc.our_ota_addr_type == BLE_ADDR_TYPE_RPA_PUB_DEFAULT);
 +    TEST_ASSERT(desc.peer_ota_addr_type == BLE_ADDR_TYPE_RPA_RND_DEFAULT);
 +    TEST_ASSERT(desc.role == BLE_GAP_ROLE_MASTER);
 +    TEST_ASSERT(memcmp(desc.our_ota_addr,
 +                       ((uint8_t[6]){0x40,1,2,3,4,5}), 6) == 0);
 +    TEST_ASSERT(memcmp(desc.our_id_addr, pub_addr, 6) == 0);
 +    TEST_ASSERT(memcmp(desc.peer_ota_addr,
 +                       ((uint8_t[6]){0x50,1,2,3,4,5}), 6) == 0);
 +    TEST_ASSERT(memcmp(desc.peer_id_addr,
 +                       ((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);
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_conn_find)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    ble_gap_test_case_conn_find();
 +}
 +
 +/*****************************************************************************
 + * $advertise                                                                *
 + *****************************************************************************/
 +
 +static void
 +ble_gap_test_util_adv(uint8_t own_addr_type, uint8_t peer_addr_type,
 +                      const uint8_t *peer_addr, uint8_t conn_mode,
 +                      uint8_t disc_mode, int connect_status,
 +                      int cmd_fail_idx, uint8_t fail_status)
 +{
 +    struct hci_le_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;
 +
 +    if (conn_mode != BLE_GAP_CONN_MODE_DIR) {
 +        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;
 +
 +        hci_status = ble_hs_test_util_exp_hci_status(cmd_idx, cmd_fail_idx,
 +                                                     fail_status);
 +        rc = ble_hs_test_util_adv_set_fields(&adv_fields, hci_status);
 +
 +        if (adv_fields.tx_pwr_lvl_is_present &&
 +            adv_fields.tx_pwr_lvl == BLE_HS_ADV_TX_PWR_LVL_AUTO) {
 +
 +            TEST_ASSERT_FATAL(rc == BLE_HS_HCI_ERR(hci_status));
 +            cmd_idx++;
 +        }
 +    }
 +
 +    if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
 +        rc = ble_hs_test_util_adv_start(own_addr_type, peer_addr_type,
 +                                        peer_addr, &adv_params,
 +                                        ble_gap_test_util_connect_cb, NULL,
 +                                        cmd_fail_idx - cmd_idx, fail_status);
 +
 +        TEST_ASSERT(rc == BLE_HS_HCI_ERR(fail_status));
 +    }
 +
 +    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 (conn_mode != BLE_GAP_CONN_MODE_DIR) {
 +        if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
 +            /* Verify tx of set advertise data command. */
 +            ble_gap_test_util_verify_tx_adv_data();
 +        }
 +        cmd_idx++;
 +
 +        if (fail_status == 0 || cmd_fail_idx >= cmd_idx) {
 +            /* Verify tx of set scan response data command. */
 +            ble_gap_test_util_verify_tx_rsp_data();
 +        }
 +        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) {
 +            memset(&evt, 0, sizeof evt);
 +            evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
 +            evt.status = connect_status;
 +            evt.connection_handle = 2;
 +            evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE;
 +            memcpy(evt.peer_addr, peer_addr, 6);
 +            rc = ble_gap_rx_conn_complete(&evt);
 +            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(ble_gap_test_case_adv_bad_args)
 +{
 +    struct ble_gap_adv_params adv_params;
 +    uint8_t peer_addr[6] = { 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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                    peer_addr, &adv_params,
 +                                    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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                    peer_addr, &adv_params,
 +                                    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_ADDR_TYPE_PUBLIC, 12,
 +                                    peer_addr, &adv_params,
 +                                    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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                    peer_addr, &adv_params,
 +                                    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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                    peer_addr, &adv_params,
 +                                    ble_gap_test_util_connect_cb, NULL, 0, 0);
 +    TEST_ASSERT(rc == BLE_HS_EALREADY);
 +    TEST_ASSERT(ble_gap_adv_active());
 +}
 +
 +static void
 +ble_gap_test_util_adv_verify_dflt_params(uint8_t own_addr_type,
 +                                         uint8_t peer_addr_type,
 +                                         const uint8_t *peer_addr,
 +                                         uint8_t conn_mode,
 +                                         uint8_t disc_mode)
 +{
 +    struct ble_gap_adv_params adv_params;
 +    struct hci_adv_params hci_cmd;
 +    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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                    peer_addr, &adv_params,
 +                                    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_verify_tx_hci(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.adv_itvl_min = le16toh(hci_buf + 0);
 +    hci_cmd.adv_itvl_max = le16toh(hci_buf + 2);
 +    hci_cmd.adv_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.adv_channel_map = hci_buf[13];
 +    hci_cmd.adv_filter_policy = hci_buf[14];
 +
 +    if (conn_mode == BLE_GAP_CONN_MODE_NON) {
 +        TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL2_MIN);
 +        TEST_ASSERT(hci_cmd.adv_itvl_max == BLE_GAP_ADV_FAST_INTERVAL2_MAX);
 +    } else {
 +        TEST_ASSERT(hci_cmd.adv_itvl_min == BLE_GAP_ADV_FAST_INTERVAL1_MIN);
 +        TEST_ASSERT(hci_cmd.adv_itvl_max == 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.adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND);
 +        } else {
 +            TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND);
 +        }
 +    } else if (conn_mode == BLE_GAP_CONN_MODE_UND) {
 +        TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_IND);
 +    } else {
 +        TEST_ASSERT(hci_cmd.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD);
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_adv_dflt_params)
 +{
 +    uint8_t peer_addr[6] = { 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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d);
 +        }
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_adv_good)
 +{
 +    uint8_t peer_addr[6] = { 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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_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_conn_event_type ==
-                                 BLE_GAP_EVENT_CONNECT);
++                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,
 +                                   peer_addr, 6) == 0);
 +                TEST_ASSERT(ble_gap_test_conn_arg == NULL);
 +            }
 +        }
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_adv_ctlr_fail)
 +{
 +    uint8_t peer_addr[6] = { 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_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
 +                                  peer_addr, c, d, BLE_ERR_DIR_ADV_TMO, -1, 0);
 +
 +            TEST_ASSERT(!ble_gap_adv_active());
-             TEST_ASSERT(ble_gap_test_conn_event_type ==
-                         BLE_GAP_EVENT_ADV_COMPLETE);
++            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);
 +        }
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_adv_hci_fail)
 +{
 +    uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
 +    int num_hci_cmds;
 +    int fail_idx;
 +    int d;
 +    int c;
 +
 +    for (c = BLE_GAP_CONN_MODE_NON; c < BLE_GAP_CONN_MODE_MAX; c++) {
 +        if (c == BLE_GAP_CONN_MODE_DIR) {
 +            num_hci_cmds = 2;
 +        } else {
 +            num_hci_cmds = 5;
 +        }
 +
 +        for (d = BLE_GAP_DISC_MODE_NON; d < BLE_GAP_DISC_MODE_MAX; d++) {
 +            for (fail_idx = 0; fail_idx < num_hci_cmds; fail_idx++) {
 +                ble_gap_test_util_adv(BLE_ADDR_TYPE_PUBLIC,
 +                                      BLE_ADDR_TYPE_PUBLIC, peer_addr,
 +                                      c, d, 0, fail_idx, BLE_ERR_UNSUPPORTED);
 +
 +                TEST_ASSERT(!ble_gap_adv_active());
-                 TEST_ASSERT(ble_gap_test_conn_event_type == -1);
++                TEST_ASSERT(ble_gap_test_event.type == 0xff);
 +            }
 +        }
 +    }
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_adv)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    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(uint8_t peer_addr_type, const uint8_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_ADDR_TYPE_PUBLIC, peer_addr_type, 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(ble_gap_test_case_stop_adv_good)
 +{
 +    uint8_t peer_addr[6] = { 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(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
 +                                       -1, 0);
 +            TEST_ASSERT(!ble_gap_adv_active());
-             TEST_ASSERT(ble_gap_test_conn_event_type == -1);
++            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);
 +        }
 +    }
 +}
 +
 +TEST_CASE(ble_gap_test_case_stop_adv_hci_fail)
 +{
 +    uint8_t peer_addr[6] = { 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(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
 +                                       0, BLE_ERR_UNSUPPORTED);
 +            TEST_ASSERT(ble_gap_adv_active());
-             TEST_ASSERT(ble_gap_test_conn_event_type == -1);
++            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);
 +        }
 +    }
 +}
 +
 +TEST_SUITE(ble_gap_test_suite_stop_adv)
 +{
 +    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 +
 +    ble_gap_test_case_stop_adv_good();
 +    ble_gap_test_case_stop_adv_hci_fail();
 +}
 +
 +/*****************************************************************************
 + * $update connection                                                        *
 + *****************************************************************************/
 +
 +static void
- ble_gap_test_util_update(struct ble_gap_upd_params *params,
-                          int cmd_fail_idx, uint8_t hci_status,
-                          uint8_t event_status)
++ble_gap_test_util_update_no_l2cap(struct ble_gap_upd_params *params,
++                                  int master,
++                                  uint8_t hci_status, int event_status)
 +{
-     int 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_test_util_update_in_progress(2));
++        TEST_ASSERT(ble_gap_dbg_update_active(2));
++
++        /* 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,
++                               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_test_util_update_in_progress(2));
-         return;
++        TEST_ASSERT(!ble_gap_master_in_progress());
++        TEST_ASSERT(!ble_gap_dbg_update_active(2));
++
++        TEST_ASSERT(ble_gap_test_event.type == 0xff);
 +    }
++}
 +
-     /* Receive connection update complete event. */
-     ble_gap_test_util_rx_update_complete(event_status, params);
++static void
++ble_gap_test_util_update_l2cap(struct ble_gap_upd_params *params,
++                               uint8_t hci_status, int event_status,
++                               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(2, peer_addr, 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, hci_status);
++    TEST_ASSERT(rc == 0);
++
++    /* Verify tx of connection update command. */
++    ble_gap_test_util_verify_tx_update_conn(params);
++
++    switch (hci_status) {
++    case 0:
++        /* Receive connection update complete event. */
++        ble_gap_test_util_rx_update_complete(event_status, params);
++        break;
++    case BLE_ERR_UNKNOWN_HCI_CMD:
++        break;
++    default:
++        TEST_ASSERT_FATAL(0);
++        break;
++    }
++
++    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);
 +
-     if (event_status != 0) {
-         status = BLE_HS_HCI_ERR(event_status);
-         goto fail;
++    /* Receive l2cap connection parameter update response. */
++    ble_hs_test_util_rx_l2cap_update_rsp(2, id, l2cap_result);
++    if (l2cap_result == BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT) {
++        TEST_ASSERT(ble_gap_dbg_update_active(2));
++
++        /* Receive connection update complete event. */
++        ble_gap_test_util_rx_update_complete(0, params);
++    }
++
++    TEST_ASSERT(!ble_gap_dbg_update_active(2));
++
++    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,
++                       peer_addr, 6) == 0);
++}
++
++static void
++ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
++                                      int master)
++{
++    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());
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
-     TEST_ASSERT(ble_gap_test_conn_status == 0);
++    rc = ble_hs_test_util_conn_update(2, params, 0);
++    TEST_ASSERT(rc == 0);
++    TEST_ASSERT(!ble_gap_master_in_progress());
++
++    /* Verify tx of connection update command. */
++    ble_gap_test_util_verify_tx_update_conn(params);
++
++    /* Ensure no update event reported. */
++    TEST_ASSERT(ble_gap_test_event.type == 0xff);
++
++    /* Advance 29 seconds; ensure no timeout reported. */
++    os_time_advance(29 * OS_TICKS_PER_SEC);
++    ble_gap_heartbeat();
++    TEST_ASSERT(ble_gap_test_event.type == 0xff);
++
++    /* Advance 30th second; ensure timeout reported. */
++    os_time_advance(1 * OS_TICKS_PER_SEC);
++
++    /* Timeout will result in a terminate HCI command being sent; schedule ack
++     * from controller.
++     */
++    ble_hs_test_util_set_ack_disconnect(0);
++
++    ble_gap_heartbeat();
++
++    /* 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,
 +                       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);
++}
 +
-     TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
++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;
 +
-     return;
++    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);
++
++    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, hci_status);
++    TEST_ASSERT(rc == 0);
++
++    /* Verify tx of connection update command. */
++    ble_gap_test_util_verify_tx_update_conn(params);
++
++    switch (hci_status) {
++    case 0:
++        /* Receive connection update complete event. */
++        ble_gap_test_util_rx_update_complete(event_status, params);
++        break;
++    case BLE_ERR_UNKNOWN_HCI_CMD:
++        break;
++    default:
++        TEST_ASSERT_FATAL(0);
++        break;
++    }
++
++    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));
++
++    /* Ensure no update event reported. */
++    TEST_ASSERT(ble_gap_test_event.type == 0xff);
++
++    /* Advance 29 seconds; ensure no timeout reported. */
++    os_time_advance(29 * OS_TICKS_PER_SEC);
++    ble_gap_heartbeat();
++    ble_l2cap_sig_heartbeat();
++    TEST_ASSERT(ble_gap_test_event.type == 0xff);
++
++    /* Advance 30th second; ensure timeout reported. */
++    os_time_advance(1 * OS_TICKS_PER_SEC);
 +
- fail:
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
-     TEST_ASSERT(ble_gap_test_conn_status == status);
++    /* Timeout will result in a terminate HCI command being sent; schedule ack
++     * from controller.
++     */
++    ble_hs_test_util_set_ack_disconnect(0);
++
++    ble_gap_heartbeat();
++    ble_l2cap_sig_heartbeat();
++
++    /* 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,
 +                       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_ASSERT(!ble_gap_test_util_update_in_progress(2));
 +}
 +
 +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_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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_test_util_update_in_progress(2));
++    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());
-     TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
++
++    /* 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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 +
 +    return;
 +
 +hci_fail:
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++        TEST_ASSERT(ble_gap_dbg_update_active(2));
 +    } else {
-         TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
++        TEST_ASSERT(!ble_gap_dbg_update_active(2));
 +        return;
 +    }
 +
 +    TEST_ASSERT(!ble_gap_master_in_progress());
-     TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    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_test_util_update_in_progress(2));
++    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 +
-     TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
++    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,
 +                       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(ble_gap_test_case_update_conn_good)
 +{
-     ble_gap_test_util_update(
++    ble_gap_test_util_update_no_l2cap(
 +        ((struct ble_gap_upd_params[]) { {
 +            .itvl_min = 10,
 +            .itvl_max = 100,
 +            .supervision_timeout = 0,
 +            .min_ce_len = 123,
 +            .max_ce_len = 456,
 +        }}),
-         -1, 0, 0);
++        1, 0, 0);
 +
-     ble_gap_test_util_update(
++    ble_gap_test_util_update_no_l2cap(
 +        ((struct ble_gap_upd_params[]) { {
 +            .itvl_min = 100,
 +            .itvl_max = 100,
 +            .supervision_timeout = 100,
 +            .min_ce_len = 554,
 +            .max_ce_len = 554,
 +        }}),
-         -1, 0, 0);
++        1, 0, 0);
 +}
 +
 +TEST_CASE(ble_gap_test_case_update_conn_bad)
 +{
-     ble_gap_test_util_update(
++    ble_gap_test_util_update_no_l2cap(
 +        ((struct ble_gap_upd_params[]) { {
 +            .itvl_min = 10,
 +            .itvl_max = 100,
 +            .supervision_timeout = 0,
 +            .min_ce_len = 123,
 +            .max_ce_len = 456,
 +        }}),
-         -1, 0, BLE_ERR_LMP_COLLISION);
++        1, 0, BLE_ERR_LMP_COLLISION);
 +}
 +
 +TEST_CASE(ble_gap_test_case_update_conn_hci_fail)
 +{
-     ble_gap_test_util_update(
++    ble_gap_test_util_update_no_l2cap(
 +        ((struct ble_gap_upd_params[]) { {
 +            .itvl_min = 10,
 +            .itvl_max = 100,
 +            .supervision_timeout = 0,
 +            .min_ce_len = 123,
 +            .max_ce_len = 456,
 +        }}),
-         0, BLE_ERR_UNSUPPORTED, 0);
++        1, BLE_ERR_UNSUPPORTED, 0);
++}
++
++TEST_CASE(ble_gap_test_case_update_conn_l2cap)
++{
++    struct ble_gap_upd_params params = {
++        .itvl_min = 10,
++        .itvl_max = 100,
++        .supervision_timeout = 0,
++        .min_ce_len = 123,
++        .max_ce_len = 456,
++    };
++
++    /* Accepted L2CAP failover; success. */
++    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0,
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
++    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
++
++    /* Accepted L2CAP failover; failure. */
++    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
++    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
++
++    /* Rejected L2CAP failovers. */
++    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT);
++    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
++                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT);
++
++    /* Don't attempt L2CAP failover on other event status. */
++    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
 +}
 +
 +TEST_CASE(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,
 +        }}));
 +}
 +
 +TEST_CASE(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 = 20,
 +            .min_ce_len = 555,
 +            .max_ce_len = 888,
 +        }}),
 +        ((struct ble_gap_upd_params[]) { {
 +            .itvl_min = 10,
 +            .itvl_max = 100,
 +            .su

<TRUNCATED>