// SPDX-License-Identifier: LGPL-2.1-or-later /* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2022 Intel Corporation. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "lib/bluetooth.h" #include "lib/mgmt.h" #include "lib/hci.h" #include "lib/hci_lib.h" #include "monitor/bt.h" #include "emulator/bthost.h" #include "emulator/hciemu.h" #include "src/shared/tester.h" #include "src/shared/mgmt.h" #include "src/shared/util.h" struct test_data { const void *test_data; int sock_fd; struct hciemu *hciemu; enum hciemu_type hciemu_type; uint8_t client_num; uint16_t hci_dev_id; struct mgmt *mgmt; uint16_t mgmt_index; struct mgmt *mgmt_alt; unsigned int mgmt_alt_ev_id; uint16_t handle; uint16_t acl_handle; GIOChannel *io; unsigned int io_id[2]; int step; bool reconnect; int unmet_conditions; }; struct ioctl_data { uint32_t cmd; const uint32_t opt; const void *param; int (*cmd_param_func)(void *param, uint32_t *length); int expected_ioctl_err; const void *block_bdaddr; const void *expected_data; int (*expect_data_check_func)(const void *param, uint32_t length); }; static void print_debug(const char *str, void *user_data) { const char *prefix = user_data; tester_print("%s%s", prefix, str); } static void test_add_condition(struct test_data *data) { data->unmet_conditions++; tester_print("Test condition added, total %d", data->unmet_conditions); } static void test_condition_complete(struct test_data *data) { data->unmet_conditions--; tester_print("Test condition complete, %d left", data->unmet_conditions); if (data->unmet_conditions > 0) return; tester_test_passed(); } static int update_hci_dev_id(struct test_data *data) { struct hci_dev_list_req *dl; struct hci_dev_req *dr; int ret = 0; dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(uint16_t)); if (!dl) return -ENOMEM; dl->dev_num = HCI_MAX_DEV; dr = dl->dev_req; if (ioctl(data->sock_fd, HCIGETDEVLIST, (void *) dl) < 0) { ret = -EIO; goto exit; } if (dl->dev_num != 1) { tester_warn("dev num mismatch returned %d:expected 1", dl->dev_num); ret = -ENODEV; goto exit; } data->hci_dev_id = dr->dev_id; tester_print("HCI device id: %d", data->hci_dev_id); exit: free(dl); return ret; } static void read_info_callback(uint8_t status, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); const struct mgmt_rp_read_info *rp = param; char addr[18]; uint16_t manufacturer; uint32_t supported_settings, current_settings; tester_print("Read Info callback"); tester_print(" Status: 0x%02x", status); if (status || !param) { tester_pre_setup_failed(); return; } ba2str(&rp->bdaddr, addr); manufacturer = btohs(rp->manufacturer); supported_settings = btohl(rp->supported_settings); current_settings = btohl(rp->current_settings); tester_print(" Address: %s", addr); tester_print(" Version: 0x%02x", rp->version); tester_print(" Manufacturer: 0x%04x", manufacturer); tester_print(" Supported settings: 0x%08x", supported_settings); tester_print(" Current settings: 0x%08x", current_settings); tester_print(" Class: 0x%02x%02x%02x", rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]); tester_print(" Name: %s", rp->name); tester_print(" Short name: %s", rp->short_name); if (strcmp(hciemu_get_address(data->hciemu), addr)) { tester_pre_setup_failed(); return; } tester_pre_setup_complete(); } 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 index_removed_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); tester_print("Index Removed callback"); tester_print(" Index: 0x%04x", index); if (index != data->mgmt_index) return; mgmt_unregister_index(data->mgmt, data->mgmt_index); mgmt_unregister_index(data->mgmt_alt, data->mgmt_index); mgmt_unref(data->mgmt); data->mgmt = NULL; mgmt_unref(data->mgmt_alt); data->mgmt_alt = NULL; tester_post_teardown_complete(); } static void read_index_list_callback(uint8_t status, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); tester_print("Read Index List callback"); tester_print(" Status: 0x%02x", status); if (status || !param) { tester_pre_setup_failed(); return; } mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE, index_added_callback, NULL, NULL); mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE, index_removed_callback, NULL, NULL); data->hciemu = hciemu_new(data->hciemu_type); if (!data->hciemu) { tester_warn("Failed to setup HCI emulation"); tester_pre_setup_failed(); } if (tester_use_debug()) hciemu_set_debug(data->hciemu, print_debug, "hciemu: ", NULL); tester_print("New hciemu instance created"); data->sock_fd = hci_open_dev(0); if (data->sock_fd < 0) { tester_warn("Failed to open socket for ioctl"); tester_pre_setup_failed(); return; } update_hci_dev_id(data); } static void test_pre_setup(const void *test_data) { struct test_data *data = tester_get_data(); data->mgmt = mgmt_new_default(); if (!data->mgmt) { tester_warn("Failed to setup mgmt interface"); tester_pre_setup_failed(); return; } data->mgmt_alt = mgmt_new_default(); if (!data->mgmt_alt) { tester_warn("Failed to setup alternate management interface"); tester_pre_setup_failed(); mgmt_unref(data->mgmt); data->mgmt = NULL; return; } if (tester_use_debug()) { mgmt_set_debug(data->mgmt, print_debug, "mgmt: ", NULL); mgmt_set_debug(data->mgmt_alt, print_debug, "mgmt-alt: ", NULL); } mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL, read_index_list_callback, NULL, NULL); } static void test_post_teardown(const void *test_data) { struct test_data *data = tester_get_data(); if (data->sock_fd >= 0) { tester_print("Socket closed"); hci_close_dev(data->sock_fd); } hciemu_unref(data->hciemu); data->hciemu = NULL; } static void test_data_free(void *test_data) { struct test_data *data = test_data; // TODO: free any data allocated during pre-setup free(data); } #define test_ioctl_full(name, data, setup, func, num) \ do { \ struct test_data *user; \ user = new0(struct test_data, 1); \ if (!user) \ break; \ user->hciemu_type = HCIEMU_TYPE_BREDRLE; \ user->test_data = data; \ user->client_num = num; \ tester_add_full(name, data, \ test_pre_setup, setup, func, NULL, \ test_post_teardown, 2, user, test_data_free); \ } while (0) #define test_ioctl(name, data, setup, func) \ test_ioctl_full(name, data, setup, func, 1) static void setup_powered_callback(uint8_t status, uint16_t length, const void *param, void *user_data) { if (status != MGMT_STATUS_SUCCESS) { tester_setup_failed(); return; } tester_print("Controller powered on"); tester_setup_complete(); } static void setup_powered(const void *test_data) { struct test_data *data = tester_get_data(); unsigned char param[] = { 0x01 }; mgmt_send(data->mgmt, MGMT_OP_SET_BONDABLE, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_SSP, data->mgmt_index, sizeof(param), param, NULL, NULL, NULL); mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, sizeof(param), param, setup_powered_callback, NULL, NULL); } static void setup_add_block_bdaddr(const void *test_data) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; if (!ioctl_data->block_bdaddr) { tester_warn("Invalid test data: block bdaddr"); tester_setup_failed(); return; } if (ioctl(data->sock_fd, HCIBLOCKADDR, ioctl_data->block_bdaddr) < 0) { tester_warn("Failed to add block bdaddr"); tester_setup_failed(); return; } tester_print("Added block BDADDR"); tester_setup_complete(); } static int conn_list_empty_check_func(const void *param, uint32_t length) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; const struct hci_conn_list_req *cl_input = ioctl_data->expected_data; const struct hci_conn_list_req *cl = param; if (cl->conn_num != cl_input->conn_num) return -1; return 0; } static int conn_info_cmd_param_func(void *param, uint32_t *length) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; const struct hci_conn_info_req *cr_input = ioctl_data->param; struct hci_conn_info_req *cr = param; memcpy(&cr->bdaddr, &cr_input->bdaddr, sizeof(bdaddr_t)); cr->type = cr_input->type; return 0; } static int auth_info_cmd_param_func(void *param, uint32_t *length) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; const struct hci_auth_info_req *ar_input = ioctl_data->param; struct hci_auth_info_req *ar = param; memcpy(&ar->bdaddr, &ar_input->bdaddr, sizeof(bdaddr_t)); if (ar_input->type) ar->type = ar_input->type; return 0; } static const struct ioctl_data dev_down = { .cmd = HCIDEVDOWN, }; static const struct hci_dev_list_req dev_list_1 = { .dev_num = 0x01, .dev_req = {{ .dev_id = 0x00, .dev_opt = 0x04, }}, }; static const struct ioctl_data dev_list = { .cmd = HCIGETDEVLIST, .expected_data = (void *)&dev_list_1, }; static const struct hci_dev_list_req dev_list_invalid_1_param = { .dev_num = 0x00, }; static const struct ioctl_data dev_list_invalid_1 = { .cmd = HCIGETDEVLIST, .param = (void *)&dev_list_invalid_1_param, .expected_ioctl_err = EINVAL, }; static const struct ioctl_data dev_info = { .cmd = HCIGETDEVINFO, }; static const struct ioctl_data reset_stat = { .cmd = HCIDEVRESTAT, }; static const struct ioctl_data set_link_mode_master = { .cmd = HCISETLINKMODE, .opt = HCI_LM_MASTER, }; static const struct ioctl_data set_link_mode_accept = { .cmd = HCISETLINKMODE, .opt = HCI_LM_ACCEPT, }; static const struct ioctl_data set_pkt_type_dm = { .cmd = HCISETPTYPE, .opt = HCI_DM1 | HCI_DM3 | HCI_DM5, }; static const struct ioctl_data set_pkt_type_dh = { .cmd = HCISETPTYPE, .opt = HCI_DH1 | HCI_DH3 | HCI_DH5, }; static const struct ioctl_data set_pkt_type_hv = { .cmd = HCISETPTYPE, .opt = HCI_HV1 | HCI_HV2 | HCI_HV3, }; static const struct ioctl_data set_pkt_type_2dh = { .cmd = HCISETPTYPE, .opt = HCI_2DH1 | HCI_2DH3 | HCI_2DH5, }; static const struct ioctl_data set_pkt_type_3dh = { .cmd = HCISETPTYPE, .opt = HCI_3DH1 | HCI_3DH3 | HCI_3DH5, }; static const struct ioctl_data set_pkt_type_all = { .cmd = HCISETPTYPE, .opt = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5 | HCI_HV1 | HCI_HV2 | HCI_HV3 | HCI_2DH1 | HCI_2DH3 | HCI_2DH5 | HCI_3DH1 | HCI_3DH3 | HCI_3DH5, }; static const struct ioctl_data set_acl_mtu_1 = { .cmd = HCISETACLMTU, .opt = 0x1 | (0x3FE << 16), }; static const struct ioctl_data set_acl_mtu_2 = { .cmd = HCISETACLMTU, .opt = 0x4 | (0x63 << 16), }; static const struct ioctl_data set_sco_mtu_1 = { .cmd = HCISETSCOMTU, .opt = 0x1 | (0x3FE << 16), }; static const struct ioctl_data set_sco_mtu_2 = { .cmd = HCISETSCOMTU, .opt = 0x4 | (0x63 << 16), }; static const uint8_t bdaddr1[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; static const struct ioctl_data block_bdaddr_success = { .cmd = HCIBLOCKADDR, .param = bdaddr1, }; static const struct ioctl_data block_bdaddr_fail = { .cmd = HCIBLOCKADDR, .param = bdaddr1, .expected_ioctl_err = EEXIST, .block_bdaddr = bdaddr1, }; static const struct ioctl_data unblock_bdaddr_success = { .cmd = HCIUNBLOCKADDR, .param = bdaddr1, .block_bdaddr = bdaddr1, }; static const struct ioctl_data unblock_bdaddr_fail = { .cmd = HCIUNBLOCKADDR, .param = bdaddr1, .expected_ioctl_err = ENOENT, }; static const struct hci_conn_list_req conn_list_empty = { .dev_id = 0x00, .conn_num = 0x00, }; static const struct ioctl_data conn_list_no_conn = { .cmd = HCIGETCONNLIST, .expected_data = (void *)&conn_list_empty, .expect_data_check_func = conn_list_empty_check_func, }; static const struct hci_conn_list_req conn_list_req_1 = { .dev_id = 0x00, .conn_num = 0x01, .conn_info = {{ .handle = 0x002a, .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = 0x01, .out = 0x00, .state = 0x0001, .link_mode = 0x00000000, }}, }; static const struct ioctl_data conn_list = { .cmd = HCIGETCONNLIST, .expected_data = (void *)&conn_list_req_1, }; static const struct hci_conn_info_req conn_info_req = { .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = ACL_LINK, .conn_info = {{ .handle = 0x002a, .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = 0x01, .out = 0x00, .state = 0x0001, .link_mode = 0x00000000, }}, }; static const struct hci_conn_info_req conn_info_req_acl = { .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = ACL_LINK, }; static const struct hci_conn_info_req conn_info_req_sco = { .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = SCO_LINK, }; static const struct ioctl_data conn_info = { .cmd = HCIGETCONNINFO, .param = (void *)&conn_info_req_acl, .cmd_param_func = conn_info_cmd_param_func, .expected_data = (void *)&conn_info_req, }; static const struct ioctl_data conn_info_no_conn = { .cmd = HCIGETCONNINFO, .param = (void *)&conn_info_req_acl, .expected_ioctl_err = ENOENT, .cmd_param_func = conn_info_cmd_param_func, }; static const struct ioctl_data conn_info_wrong_type = { .cmd = HCIGETCONNINFO, .param = (void *)&conn_info_req_sco, .expected_ioctl_err = ENOENT, .cmd_param_func = conn_info_cmd_param_func, }; static const struct hci_auth_info_req auth_info_req = { .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, }; static const struct hci_auth_info_req auth_info_connected = { .bdaddr = {{ 0x00, 0x00, 0x01, 0x01, 0xaa, 0x00 }}, .type = 0x04, }; static const struct ioctl_data auth_info_no_conn = { .cmd = HCIGETAUTHINFO, .param = (void *)&auth_info_req, .expected_ioctl_err = ENOENT, .cmd_param_func = auth_info_cmd_param_func, }; static const struct ioctl_data auth_info = { .cmd = HCIGETAUTHINFO, .param = (void *)&auth_info_req, .cmd_param_func = auth_info_cmd_param_func, .expected_data = (void *)&auth_info_connected, }; /* Allocate the command request parameters based on the command. * returns the allocated request buffer and its length */ static int test_alloc_cmd_param(void **req, uint32_t *req_len) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; struct hci_dev_req *dr = NULL; struct hci_dev_info *di = NULL; struct hci_dev_list_req *dl = NULL; struct hci_conn_list_req *cl = NULL; struct hci_conn_info *ci = NULL; struct hci_conn_info_req *cr = NULL; struct hci_auth_info_req *ar = NULL; bdaddr_t *bdaddr = NULL; uint32_t len; switch (ioctl_data->cmd) { case HCISETAUTH: case HCISETENCRYPT: case HCISETLINKMODE: case HCISETPTYPE: case HCISETACLMTU: case HCISETSCOMTU: len = sizeof(*dr); dr = malloc(len); if (!dr) return -ENOMEM; memset(dr, 0, len); dr->dev_id = data->hci_dev_id; dr->dev_opt = ioctl_data->opt; *req = dr; *req_len = len; break; case HCIGETDEVINFO: len = sizeof(*di); di = malloc(len); if (!di) return -ENOMEM; memset(di, 0, len); di->dev_id = data->hci_dev_id; *req = di; *req_len = len; break; case HCIGETDEVLIST: len = sizeof(*dr) + sizeof(uint16_t); dl = malloc(len); if (!dl) return -ENOMEM; memset(dl, 0, len); dl->dev_num = 1; *req = dl; *req_len = len; break; case HCIGETCONNLIST: len = sizeof(*cl) + sizeof(*ci); cl = malloc(len); if (!cl) return -ENOMEM; memset(cl, 0, len); cl->dev_id = data->hci_dev_id; cl->conn_num = 1; *req = cl; *req_len = len; break; case HCIGETCONNINFO: len = sizeof(*cr) + sizeof(*ci); cr = malloc(len); if (!cr) return -ENOMEM; memset(cr, 0, len); *req = cr; *req_len = len; break; case HCIGETAUTHINFO: len = sizeof(*ar); ar = malloc(len); if (!ar) return -ENOMEM; memset(ar, 0, len); *req = ar; *req_len = len; break; case HCIBLOCKADDR: case HCIUNBLOCKADDR: len = sizeof(bdaddr_t); bdaddr = malloc(len); if (!bdaddr) return -ENOMEM; memset(bdaddr, 0, len); *req = bdaddr; *req_len = len; break; case HCIDEVUP: case HCIDEVDOWN: case HCIDEVRESET: case HCIDEVRESTAT: /* These command uses the HCI dev id for param */ return -ENODATA; default: return -EINVAL; } return 0; } static void test_ioctl_common(const void *test_data) { struct test_data *data = tester_get_data(); const struct ioctl_data *ioctl_data = data->test_data; bool use_dev_id = false; void *req = NULL; uint32_t req_len = 0; int ret; ret = test_alloc_cmd_param(&req, &req_len); if (ret < 0) { if (ret == -ENODATA) use_dev_id = true; else { tester_warn("Failed to allocate CMD parameter"); tester_test_failed(); return; } } if (ioctl_data->expected_ioctl_err) test_add_condition(data); if (ioctl_data->expected_data) test_add_condition(data); if (!use_dev_id && ioctl_data->param) { test_add_condition(data); if (ioctl_data->cmd_param_func) { ret = ioctl_data->cmd_param_func(req, &req_len); if (ret) { tester_warn("Failed to update cmd param"); tester_test_failed(); goto exit_free; } } else memcpy(req, ioctl_data->param, req_len); tester_print("Command Parameter is updated"); test_condition_complete(data); } if (use_dev_id) ret = ioctl(data->sock_fd, ioctl_data->cmd, data->hci_dev_id); else ret = ioctl(data->sock_fd, ioctl_data->cmd, req); if (ret < 0) { if (ioctl_data->expected_ioctl_err) { if (errno != ioctl_data->expected_ioctl_err) { tester_warn("Unexpected error: %d expected: %d", errno, ioctl_data->expected_ioctl_err); tester_test_failed(); goto exit_free; } test_condition_complete(data); tester_print("Received expected error: %d", errno); goto exit_pass; } tester_warn("IOCTL failed with error: %d", errno); tester_test_failed(); goto exit_free; } if (ioctl_data->expected_data && req) { if (ioctl_data->expect_data_check_func) ret = ioctl_data->expect_data_check_func(req, req_len); else ret = memcmp(req, ioctl_data->expected_data, req_len); if (ret != 0) { tester_warn("Mismatch expected data"); util_hexdump('>', req, req_len, print_debug, ""); util_hexdump('!', ioctl_data->expected_data, req_len, print_debug, ""); tester_test_failed(); goto exit_free; } test_condition_complete(data); } exit_pass: tester_test_passed(); exit_free: if (req) free(req); } static void test_ioctl_connected_event(uint16_t index, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); tester_print("Device Connected"); test_ioctl_common(data); } static void test_ioctl_connection(const void *test_data) { struct test_data *data = tester_get_data(); unsigned int id; const uint8_t *central_bdaddr; struct bthost *bthost; uint8_t addr_type; tester_print("Registering %s notification", mgmt_evstr(MGMT_EV_DEVICE_CONNECTED)); id = mgmt_register(data->mgmt_alt, MGMT_EV_DEVICE_CONNECTED, data->mgmt_index, test_ioctl_connected_event, NULL, NULL); data->mgmt_alt_ev_id = id; central_bdaddr = hciemu_get_central_bdaddr(data->hciemu); if (!central_bdaddr) { tester_warn("No central bdaddr"); tester_setup_failed(); return; } addr_type = data->hciemu_type == HCIEMU_TYPE_BREDRLE ? BDADDR_BREDR : BDADDR_LE_PUBLIC; tester_print("ADDR TYPE: %d", addr_type); bthost = hciemu_client_get_host(data->hciemu); bthost_hci_connect(bthost, central_bdaddr, addr_type); } int main(int argc, char *argv[]) { tester_init(&argc, &argv); test_ioctl("HCI Down", &dev_down, NULL, test_ioctl_common); test_ioctl("Device List", &dev_list, NULL, test_ioctl_common); test_ioctl("Device List - Invalid Param 1", &dev_list_invalid_1, NULL, test_ioctl_common); test_ioctl("Device Info", &dev_info, NULL, test_ioctl_common); test_ioctl("Reset Stat", &reset_stat, setup_powered, test_ioctl_common); test_ioctl("Set Link Mode - ACCEPT", &set_link_mode_accept, NULL, test_ioctl_common); test_ioctl("Set Link Mode - MASTER", &set_link_mode_master, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - DM", &set_pkt_type_dm, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - DH", &set_pkt_type_dh, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - HV", &set_pkt_type_hv, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - 2-DH", &set_pkt_type_2dh, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - 2-DH", &set_pkt_type_3dh, NULL, test_ioctl_common); test_ioctl("Set Pkt Type - ALL", &set_pkt_type_all, NULL, test_ioctl_common); test_ioctl("Set ACL MTU - 1", &set_acl_mtu_1, NULL, test_ioctl_common); test_ioctl("Set ACL MTU - 2", &set_acl_mtu_2, NULL, test_ioctl_common); test_ioctl("Set SCO MTU - 1", &set_sco_mtu_1, NULL, test_ioctl_common); test_ioctl("Set SCO MTU - 2", &set_sco_mtu_2, NULL, test_ioctl_common); test_ioctl("Block BDADDR - Success", &block_bdaddr_success, NULL, test_ioctl_common); test_ioctl("Block BDADDR - Fail", &block_bdaddr_fail, setup_add_block_bdaddr, test_ioctl_common); test_ioctl("Unblock BDADDR - Success", &unblock_bdaddr_success, setup_add_block_bdaddr, test_ioctl_common); test_ioctl("Unblock BDADDR - Fail", &unblock_bdaddr_fail, NULL, test_ioctl_common); test_ioctl("Connection List - No Conn", &conn_list_no_conn, NULL, test_ioctl_common); test_ioctl("Connection List", &conn_list, setup_powered, test_ioctl_connection); test_ioctl("Connection Info", &conn_info, setup_powered, test_ioctl_connection); test_ioctl("Connection Info - No Connection", &conn_info_no_conn, setup_powered, test_ioctl_common); test_ioctl("Connection Info - Wrong Type", &conn_info_wrong_type, setup_powered, test_ioctl_common); test_ioctl("Authentication Info - No Connection", &auth_info_no_conn, setup_powered, test_ioctl_common); test_ioctl("Authentication Info", &auth_info, setup_powered, test_ioctl_connection); return tester_run(); }