static void test_post_teardown(const void *test_data) { struct user_data *user = tester_get_data(); bt_hci_unref(user->hci_lt); user->hci_lt = NULL; bt_hci_unref(user->hci_ut); user->hci_ut = NULL; tester_post_teardown_complete(); }
static void hidhost_virtual_unplug_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->virtual_unplug(&bdaddr); schedule_action_verification(step); }
static void avrcp_reg_notif_play_status_changed_rsp(void) { struct test_data *data = tester_get_data(); struct step *step = g_new0(struct step, 1); btrc_register_notification_t reg; reg.play_status = BTRC_PLAYSTATE_STOPPED; step->action_status = data->if_avrcp->register_notification_rsp( BTRC_EVT_PLAY_STATUS_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED, ®); schedule_action_verification(step); }
static void index_added_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); tester_print("Index Added callback"); tester_print(" Index: 0x%04x", index); data->mgmt_index = index; mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL, read_info_callback, NULL, NULL); }
static void avrcp_disconnect_action(void) { struct test_data *data = tester_get_data(); const uint8_t *addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) addr, &bdaddr); step->action_status = data->if_a2dp->disconnect(&bdaddr); schedule_action_verification(step); }
static void hidhost_set_report_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); char *buf = "fe0201"; bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->send_data(&bdaddr, buf); schedule_action_verification(step); }
static void avrcp_reg_notif_play_position_changed_rsp(void) { struct test_data *data = tester_get_data(); struct step *step = g_new0(struct step, 1); btrc_register_notification_t reg; reg.song_pos = 0xffffffff; step->action_status = data->if_avrcp->register_notification_rsp( BTRC_EVT_PLAY_POS_CHANGED, BTRC_NOTIFICATION_TYPE_INTERIM, ®); schedule_action_verification(step); }
static void client_new_conn(uint16_t handle, void *user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_server_data *server_data = data->test_data; struct bthost *bthost; bthost = hciemu_client_get_host(data->hciemu); bthost_add_rfcomm_chan_hook(bthost, handle, server_data->client_channel, server_hook_func, NULL); bthost_connect_rfcomm(bthost, handle, server_data->client_channel, connection_cb, NULL); }
static void setup_powered_client(const void *test_data) { struct test_data *data = tester_get_data(); unsigned char param[] = { 0x01 }; setup_powered_common(); tester_print("Powering on controller"); mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, sizeof(param), param, setup_powered_client_callback, NULL, NULL); }
static void test_adv_report(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); uint8_t subevent = *((uint8_t *) data); const struct bt_hci_evt_le_adv_report *lar = data + 1; switch (subevent) { case BT_HCI_EVT_LE_ADV_REPORT: if (!memcmp(lar->addr, user->bdaddr_ut, 6)) tester_setup_complete(); break; } }
static void test_server(const void *test_data) { struct test_data *data = tester_get_data(); const struct l2cap_server_data *l2data = data->test_data; const uint8_t *master_bdaddr; uint8_t addr_type; struct bthost *bthost; GIOChannel *io; int sk; if (l2data->server_psm) { sk = create_l2cap_sock(data, l2data->server_psm); if (sk < 0) { tester_test_failed(); return; } if (listen(sk, 5) < 0) { tester_warn("listening on socket failed: %s (%u)", strerror(errno), errno); tester_test_failed(); return; } io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); data->io_id = g_io_add_watch(io, G_IO_IN, l2cap_listen_cb, NULL); g_io_channel_unref(io); tester_print("Listening for connections"); } master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); tester_test_failed(); return; } bthost = hciemu_client_get_host(data->hciemu); bthost_set_connect_cb(bthost, client_new_conn, data); if (data->hciemu_type == HCIEMU_TYPE_BREDR) addr_type = BDADDR_BREDR; else addr_type = BDADDR_LE_PUBLIC; bthost_hci_connect(bthost, master_bdaddr, addr_type); }
static void rfcomm_connect_cb(uint16_t handle, uint16_t cid, void *user_data, bool status) { struct test_data *data = tester_get_data(); const struct rfcomm_client_data *client_data = data->test_data; struct bthost *bthost = hciemu_client_get_host(data->hciemu); if (client_data->send_data) bthost_add_rfcomm_chan_hook(bthost, handle, client_data->client_channel, client_hook_func, NULL); else if (client_data->read_data) data->conn_handle = handle; }
static void user_confirm_request_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { const struct mgmt_ev_user_confirm_request *ev = param; struct test_data *data = tester_get_data(); struct mgmt_cp_user_confirm_reply cp; memset(&cp, 0, sizeof(cp)); memcpy(&cp.addr, &ev->addr, sizeof(cp.addr)); mgmt_reply(data->mgmt, MGMT_OP_USER_CONFIRM_REPLY, data->mgmt_index, sizeof(cp), &cp, NULL, NULL, NULL); }
static void hidhost_set_protocol_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->set_protocol(&bdaddr, BTHH_REPORT_MODE); schedule_action_verification(step); }
static void test_open_failed(const void *test_data) { struct test_data *data = tester_get_data(); struct bt_hci *hci; hci = bt_hci_new_user_channel(data->mgmt_index); if (!hci) { tester_test_passed(); return; } bt_hci_unref(hci); tester_test_failed(); }
static void test_server(const void *test_data) { struct test_data *data = tester_get_data(); struct bthost *bthost; data->out = true; init_bdaddr(data); bthost = hciemu_client_get_host(data->hciemu); bthost_set_connect_cb(bthost, smp_new_conn, data); bthost_hci_connect(bthost, data->ra, BDADDR_LE_PUBLIC); }
static void toggle_powered(const void *test_data) { struct test_data *data = tester_get_data(); bool power = PTR_TO_INT(test_data); unsigned char param[1]; param[0] = power ? 0x01 : 0x00; tester_print("Powering %s controller", power ? "on" : "off"); mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, sizeof(param), param, toggle_powered_client_callback, INT_TO_PTR(power), NULL); }
static void setup_advertising_initiated(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_set_event_mask sem; struct bt_hci_cmd_le_set_event_mask lsem; struct bt_hci_cmd_le_set_scan_enable lsse; struct bt_hci_cmd_le_set_adv_parameters lsap; struct bt_hci_cmd_le_set_adv_enable lsae; bt_hci_register(user->hci_lt, BT_HCI_EVT_LE_META_EVENT, test_adv_report, NULL, NULL); memset(sem.mask, 0, 8); sem.mask[1] |= 0x20; /* Command Complete */ sem.mask[1] |= 0x40; /* Command Status */ sem.mask[7] |= 0x20; /* LE Meta */ bt_hci_send(user->hci_lt, BT_HCI_CMD_SET_EVENT_MASK, &sem, sizeof(sem), NULL, NULL, NULL); memset(lsem.mask, 0, 8); lsem.mask[0] |= 0x02; /* LE Advertising Report */ bt_hci_send(user->hci_lt, BT_HCI_CMD_LE_SET_EVENT_MASK, &lsem, sizeof(lsem), NULL, NULL, NULL); lsse.enable = 0x01; lsse.filter_dup = 0x00; bt_hci_send(user->hci_lt, BT_HCI_CMD_LE_SET_SCAN_ENABLE, &lsse, sizeof(lsse), NULL, NULL, NULL); lsap.min_interval = cpu_to_le16(0x0800); lsap.max_interval = cpu_to_le16(0x0800); lsap.type = 0x03; lsap.own_addr_type = 0x00; lsap.direct_addr_type = 0x00; memset(lsap.direct_addr, 0, 6); lsap.channel_map = 0x07; lsap.filter_policy = 0x00; bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_ADV_PARAMETERS, &lsap, sizeof(lsap), NULL, NULL, NULL); lsae.enable = 0x01; bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_ADV_ENABLE, &lsae, sizeof(lsae), NULL, NULL, NULL); }
static void avrcp_reg_notif_track_changed_rsp(void) { struct test_data *data = tester_get_data(); struct step *step = g_new0(struct step, 1); uint64_t track; btrc_register_notification_t reg; track = 0xffffffffffffffff; memcpy(reg.track, &track, sizeof(btrc_uid_t)); step->action_status = data->if_avrcp->register_notification_rsp( BTRC_EVT_TRACK_CHANGE, BTRC_NOTIFICATION_TYPE_INTERIM, ®); schedule_action_verification(step); }
static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_client_data *client_data = data->test_data; socklen_t len = sizeof(int); int sk, err, sk_err; data->io_id = 0; sk = g_io_channel_unix_get_fd(io); if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) err = -errno; else err = -sk_err; if (client_data->expected_connect_err && err == client_data->expected_connect_err) { tester_test_passed(); return false; } if (client_data->send_data) { ssize_t ret; ret = write(sk, client_data->send_data, client_data->data_len); if (client_data->data_len != ret) tester_test_failed(); return false; } else if (client_data->read_data) { g_io_add_watch(io, G_IO_IN, client_received_data, NULL); bthost_send_rfcomm_data(hciemu_client_get_host(data->hciemu), data->conn_handle, client_data->client_channel, client_data->read_data, client_data->data_len); return false; } if (err < 0) tester_test_failed(); else tester_test_passed(); return false; }
static void test_read_local_extended_features(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_read_local_ext_features cmd; cmd.page = 0x00; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_READ_LOCAL_EXT_FEATURES, &cmd, sizeof(cmd), test_local_extended_features_complete, NULL, NULL)) { tester_warn("Failed to send HCI extended features command"); tester_test_failed(); return; } }
static void server_bthost_received_data(const void *buf, uint16_t len, void *user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; if (len != l2data->data_len) { tester_test_failed(); return; } if (memcmp(buf, l2data->write_data, l2data->data_len)) tester_test_failed(); else tester_test_passed(); }
static void test_connect_two_sockets_part_2(void) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; const uint8_t *client_bdaddr; client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); connect_socket(client_bdaddr, &data->sk2, test_two_sockets_connect_cb); if (l2data->close_one_socket) { tester_print("Closing first socket! %d", data->sk); close(data->sk); } g_idle_add(enable_advertising, NULL); }
static void setup_le_generate_dhkey(const void *test_data) { struct user_data *user = tester_get_data(); bt_hci_register(user->hci_ut, BT_HCI_EVT_LE_META_EVENT, setup_le_read_local_pk_complete, (void *)test_data, NULL); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_READ_LOCAL_PK256, NULL, 0, setup_le_read_local_pk_status, NULL, NULL)) { tester_warn("Failed to send HCI LE Read Local PK256 command"); tester_setup_failed(); return; } }
static void setup_lt_connect_request_accept(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); const struct bt_hci_evt_conn_request *evt = data; struct bt_hci_cmd_accept_conn_request cmd; memcpy(cmd.bdaddr, evt->bdaddr, 6); cmd.role = 0x01; if (!bt_hci_send(user->hci_lt, BT_HCI_CMD_ACCEPT_CONN_REQUEST, &cmd, sizeof(cmd), NULL, NULL, NULL)) { tester_warn("Failed to send HCI accept connection command"); return; } }
static void test_close_socket(const void *test_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; const uint8_t *client_bdaddr; hciemu_add_master_post_command_hook(data->hciemu, test_close_socket_router, data); if (l2data->client_bdaddr != NULL) client_bdaddr = l2data->client_bdaddr; else client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); connect_socket(client_bdaddr, &data->sk, NULL); }
static void setup_powered_client_callback(uint8_t status, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); struct bthost *bthost; if (status != MGMT_STATUS_SUCCESS) { tester_setup_failed(); return; } tester_print("Controller powered on"); bthost = hciemu_client_get_host(data->hciemu); bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data); bthost_set_adv_enable(bthost, 0x01, 0x00); }
static void test_post_teardown(const void *test_data) { struct test_data *data = tester_get_data(); if (data->io_id > 0) { g_source_remove(data->io_id); data->io_id = 0; } if (data->crypto) { bt_crypto_unref(data->crypto); data->crypto = NULL; } hciemu_unref(data->hciemu); data->hciemu = NULL; }
static void teardown_connection(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_disconnect cmd; cmd.handle = cpu_to_le16(user->handle_ut); cmd.reason = 0x13; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_DISCONNECT, &cmd, sizeof(cmd), teardown_disconnect_status, NULL, NULL)) { tester_warn("Failed to send HCI disconnect command"); tester_test_failed(); return; } }
static void test_pre_setup(const void *data) { struct test_data *test_data = tester_get_data(); if (!tester_use_debug()) fclose(stderr); test_data->mgmt = mgmt_new_default(); if (!test_data->mgmt) { tester_warn("Failed to setup management interface"); tester_pre_setup_failed(); return; } mgmt_send(test_data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL, read_index_list_callback, NULL, NULL); }