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(); }
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(); }