struct ble_hs_conn *
ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr,
                             ble_gap_conn_fn *cb, void *cb_arg)
{
    struct hci_le_conn_complete evt;
    struct ble_hs_conn *conn;
    int rc;

    ble_hs_test_util_set_ack(
        BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CREATE_CONN), 0);
    rc = ble_gap_conn_initiate(0, addr, NULL, cb, cb_arg);
    TEST_ASSERT(rc == 0);

    memset(&evt, 0, sizeof evt);
    evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
    evt.status = BLE_ERR_SUCCESS;
    evt.connection_handle = handle;
    evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER;
    evt.peer_addr_type = BLE_ADDR_TYPE_PUBLIC;
    memcpy(evt.peer_addr, addr, 6);
    evt.conn_itvl = BLE_GAP_INITIAL_CONN_ITVL_MAX;
    evt.conn_latency = BLE_GAP_INITIAL_CONN_LATENCY;
    evt.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT;
    rc = ble_gap_rx_conn_complete(&evt);
    TEST_ASSERT(rc == 0);

    conn = ble_hs_conn_find(handle);
    TEST_ASSERT_FATAL(conn != NULL);

    ble_hs_test_util_prev_hci_tx_clear();

    return conn;
}
static int
ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
{
    struct hci_le_conn_complete evt;
    int extended_offset = 0;
    int rc;

    if (len < BLE_HCI_LE_CONN_COMPLETE_LEN) {
        return BLE_HS_ECONTROLLER;
    }

    /* this code processes two different events that are really similar */
    if ((subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) &&
        ( len < BLE_HCI_LE_ENH_CONN_COMPLETE_LEN)) {
        return BLE_HS_ECONTROLLER;
    }

    evt.subevent_code = data[0];
    evt.status = data[1];
    evt.connection_handle = get_le16(data + 2);
    evt.role = data[4];
    evt.peer_addr_type = data[5];
    memcpy(evt.peer_addr, data + 6, BLE_DEV_ADDR_LEN);

    /* enhanced connection event has the same information with these
     * extra fields stuffed into the middle */
    if (subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) {
        memcpy(evt.local_rpa, data + 12, BLE_DEV_ADDR_LEN);
        memcpy(evt.peer_rpa, data + 18, BLE_DEV_ADDR_LEN);
        extended_offset = 12;
    } else {
        memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN);
        memset(evt.peer_rpa, 0, BLE_DEV_ADDR_LEN);
    }

    evt.conn_itvl = get_le16(data + 12 + extended_offset);
    evt.conn_latency = get_le16(data + 14 + extended_offset);
    evt.supervision_timeout = get_le16(data + 16 + extended_offset);
    evt.master_clk_acc = data[18 + extended_offset];

    if (evt.status == 0) {
        if (evt.role != BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER &&
            evt.role != BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) {

            return BLE_HS_EBADDATA;
        }
    }

    rc = ble_gap_rx_conn_complete(&evt);
    if (rc != 0) {
        return rc;
    }

    return 0;
}
static void
ble_gap_direct_connect_test_task_handler(void *arg)
{
    struct hci_le_conn_complete evt;
    uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
    int cb_called;
    int rc;

    /* Set the connect callback so we can verify that it gets called with the
     * proper arguments.
     */
    cb_called = 0;

    /* Make sure there are no created connections and no connections in
     * progress.
     */
    TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));

    /* Initiate a direct connection. */
    ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
                             addr, 0, NULL,
                             ble_gap_direct_connect_test_connect_cb,
                             &cb_called, 0);
    TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
    TEST_ASSERT(!cb_called);

    /* Receive an HCI 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;
    memcpy(evt.peer_addr, addr, 6);
    rc = ble_gap_rx_conn_complete(&evt);
    TEST_ASSERT(rc == 0);

    /* The connection should now be created. */
    TEST_ASSERT(ble_os_test_misc_conn_exists(2));
    TEST_ASSERT(cb_called);

    tu_restart();
}
Example #4
0
static int
host_hci_rx_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
{
    struct hci_le_conn_complete evt;
    int rc;

    if (len < BLE_HCI_LE_CONN_COMPLETE_LEN) {
        return BLE_HS_EMSGSIZE;
    }

    evt.subevent_code = data[0];
    evt.status = data[1];
    evt.connection_handle = le16toh(data + 2);
    evt.role = data[4];
    evt.peer_addr_type = data[5];
    memcpy(evt.peer_addr, data + 6, BLE_DEV_ADDR_LEN);
    evt.conn_itvl = le16toh(data + 12);
    evt.conn_latency = le16toh(data + 14);
    evt.supervision_timeout = le16toh(data + 16);
    evt.master_clk_acc = data[18];

    if (evt.status == 0) {
        if (evt.role != BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER &&
            evt.role != BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) {

            return BLE_HS_EBADDATA;
        }
    }

    rc = ble_gap_rx_conn_complete(&evt);
    if (rc != 0) {
        return rc;
    }

    return 0;
}
static void
ble_gap_terminate_test_task_handler(void *arg)
{
    struct hci_disconn_complete disconn_evt;
    struct hci_le_conn_complete conn_evt;
    uint8_t addr1[6] = { 1, 2, 3, 4, 5, 6 };
    uint8_t addr2[6] = { 2, 3, 4, 5, 6, 7 };
    int disconn_handle;
    int rc;

    /* Receive acknowledgements for the startup sequence.  We sent the
     * corresponding requests when the host task was started.
     */
    ble_hs_test_util_set_startup_acks();

    /* Set the connect callback so we can verify that it gets called with the
     * proper arguments.
     */
    disconn_handle = 0;

    /* Make sure there are no created connections and no connections in
     * progress.
     */
    TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
    TEST_ASSERT(!ble_gap_master_in_progress());

    /* Create two direct connections. */
    ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
                             addr1, 0, NULL, ble_gap_terminate_cb,
                             &disconn_handle, 0);
    memset(&conn_evt, 0, sizeof conn_evt);
    conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
    conn_evt.status = BLE_ERR_SUCCESS;
    conn_evt.connection_handle = 1;
    memcpy(conn_evt.peer_addr, addr1, 6);
    rc = ble_gap_rx_conn_complete(&conn_evt);
    TEST_ASSERT(rc == 0);

    ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC,
                             addr2, 0, NULL, ble_gap_terminate_cb,
                             &disconn_handle, 0);
    memset(&conn_evt, 0, sizeof conn_evt);
    conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
    conn_evt.status = BLE_ERR_SUCCESS;
    conn_evt.connection_handle = 2;
    memcpy(conn_evt.peer_addr, addr2, 6);
    rc = ble_gap_rx_conn_complete(&conn_evt);
    TEST_ASSERT(rc == 0);

    TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(1));
    TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));

    /* Terminate the first one. */
    rc = ble_hs_test_util_conn_terminate(1, 0);
    TEST_ASSERT(rc == 0);
    disconn_evt.connection_handle = 1;
    disconn_evt.status = 0;
    disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
    ble_hs_test_util_rx_disconn_complete_event(&disconn_evt);
    TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
    TEST_ASSERT(disconn_handle == 1);
    TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
    TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));

    /* Terminate the second one. */
    rc = ble_hs_test_util_conn_terminate(2, 0);
    TEST_ASSERT(rc == 0);
    disconn_evt.connection_handle = 2;
    disconn_evt.status = 0;
    disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
    ble_hs_test_util_rx_disconn_complete_event(&disconn_evt);
    TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
    TEST_ASSERT(disconn_handle == 2);
    TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
    TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(2));

    tu_restart();
}