This patch tests read extended controller info command added in kernel. It also adds support for sending multiple mgmt commands on setup and expecting hci command on setup. --- emulator/hciemu.c | 10 ++ emulator/hciemu.h | 2 + tools/mgmt-tester.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+) diff --git a/emulator/hciemu.c b/emulator/hciemu.c index ea1e3cf..7debb8f 100644 --- a/emulator/hciemu.c +++ b/emulator/hciemu.c @@ -467,6 +467,16 @@ bool hciemu_add_master_post_command_hook(struct hciemu *hciemu, return true; } +bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu) +{ + if (!hciemu) + return false; + + queue_remove_all(hciemu->post_command_hooks, + NULL, NULL, destroy_command_hook); + return true; +} + int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type, uint16_t opcode, hciemu_hook_func_t function, void *user_data) diff --git a/emulator/hciemu.h b/emulator/hciemu.h index c5578d1..783f99c 100644 --- a/emulator/hciemu.h +++ b/emulator/hciemu.h @@ -66,6 +66,8 @@ typedef bool (*hciemu_hook_func_t)(const void *data, uint16_t len, bool hciemu_add_master_post_command_hook(struct hciemu *hciemu, hciemu_command_func_t function, void *user_data); +bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu); + int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type, uint16_t opcode, hciemu_hook_func_t function, void *user_data); diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c index b6f4873..1533cc1 100644 --- a/tools/mgmt-tester.c +++ b/tools/mgmt-tester.c @@ -384,6 +384,12 @@ static void controller_setup(const void *test_data) tester_test_passed(); } +struct setup_mgmt_cmd { + uint8_t send_opcode; + const void *send_param; + uint16_t send_len; +}; + struct generic_data { const uint16_t *setup_settings; bool setup_nobredr; @@ -394,6 +400,7 @@ struct generic_data { uint16_t setup_send_opcode; const void *setup_send_param; uint16_t setup_send_len; + const struct setup_mgmt_cmd *setup_mgmt_cmd_arr; bool send_index_none; uint16_t send_opcode; const void *send_param; @@ -4862,6 +4869,199 @@ static const struct generic_data read_local_oob_success_sc_test = { .expect_hci_command = BT_HCI_CMD_READ_LOCAL_OOB_EXT_DATA, }; +static const char ext_ctrl_info1[] = { + 0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */ + 0x08, /* version */ + 0x3f, 0x00, /* manufacturer */ + 0xff, 0xbf, 0x00, 0x00, /* supported settings */ + 0x80, 0x00, 0x00, 0x00, /* current settings */ + 0x09, 0x00, /* eir length */ + 0x04, /* dev class length */ + 0x0d, /* dev class info */ + 0x00, /* minor */ + 0x00, /* major */ + 0x00, /* service classes */ + 0x01, /* complete name data length */ + 0x09, /* complete name flag */ + 0x01, /* short name data length */ + 0x08, /* short name flag */ +}; + +static const struct generic_data read_ext_ctrl_info1 = { + .send_opcode = MGMT_OP_READ_EXT_INFO, + .expect_status = MGMT_STATUS_SUCCESS, + .expect_param = ext_ctrl_info1, + .expect_len = sizeof(ext_ctrl_info1), +}; + +static const char set_dev_class1[] = { 0x03, 0xe0 }; + +static const struct setup_mgmt_cmd set_dev_class_cmd_arr1[] = { + { + .send_opcode = MGMT_OP_SET_DEV_CLASS, + .send_param = set_dev_class1, + .send_len = sizeof(set_dev_class1), + }, + { + .send_opcode = MGMT_OP_ADD_UUID, + .send_param = add_spp_uuid_param, + .send_len = sizeof(add_spp_uuid_param), + }, + { /* last element should always have opcode 0x00 */ + .send_opcode = 0x00, + .send_param = NULL, + .send_len = 0, + } +}; + +static const char ext_ctrl_info2[] = { + 0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */ + 0x08, /* version */ + 0x3f, 0x00, /* manufacturer */ + 0xff, 0xbf, 0x00, 0x00, /* supported settings */ + 0x81, 0x02, 0x00, 0x00, /* current settings */ + 0x09, 0x00, /* eir length */ + 0x04, /* dev class length */ + 0x0d, /* dev class info */ + 0xe0, /* minor */ + 0x03, /* major */ + 0x00, /* service classes */ + 0x01, /* complete name data length */ + 0x09, /* complete name flag */ + 0x01, /* short name data length */ + 0x08, /* short name flag */ +}; + +static const struct generic_data read_ext_ctrl_info2 = { + .setup_settings = settings_powered_le, + .setup_mgmt_cmd_arr = set_dev_class_cmd_arr1, + .send_opcode = MGMT_OP_READ_EXT_INFO, + .expect_status = MGMT_STATUS_SUCCESS, + .expect_param = ext_ctrl_info2, + .expect_len = sizeof(ext_ctrl_info2), +}; + +static const char ext_ctrl_info3[] = { + 0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */ + 0x08, /* version */ + 0x3f, 0x00, /* manufacturer */ + 0xff, 0xbf, 0x00, 0x00, /* supported settings */ + 0x80, 0x02, 0x00, 0x00, /* current settings */ + 0x12, 0x00, /* eir length */ + 0x04, /* dev class length */ + 0x0d, /* dev class info */ + 0x00, /* minor */ + 0x00, /* major */ + 0x00, /* service classes */ + 0x0A, /* Local name length */ + 0x09, /* Complete name */ + 0x54, 0x65, 0x73, 0x74, + 0x20, 0x6E, 0x61, 0x6D, 0x65, /* "Test name" */ + 0x01, /* short name data length */ + 0x08, /* short name flag */ +}; + +static const struct generic_data read_ext_ctrl_info3 = { + .setup_settings = settings_le, + .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME, + .setup_send_param = set_local_name_param, + .setup_send_len = sizeof(set_local_name_param), + .send_opcode = MGMT_OP_READ_EXT_INFO, + .expect_status = MGMT_STATUS_SUCCESS, + .expect_param = ext_ctrl_info3, + .expect_len = sizeof(ext_ctrl_info3), +}; + +static const struct mgmt_cp_set_local_name set_local_name_cp = { + .name = {'T', 'e', 's', 't', ' ', 'n', 'a', 'm', 'e'}, + .short_name = {'T', 'e', 's', 't'}, +}; + +static const char ext_ctrl_info4[] = { + 0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */ + 0x08, /* version */ + 0x3f, 0x00, /* manufacturer */ + 0xff, 0xbf, 0x00, 0x00, /* supported settings */ + 0x80, 0x02, 0x00, 0x00, /* current settings */ + 0x16, 0x00, /* eir length */ + 0x04, /* dev class length */ + 0x0d, /* dev class info */ + 0x00, /* minor */ + 0x00, /* major */ + 0x00, /* service classes */ + 0x0A, /* Complete Local name len */ + 0x09, /* Complete name */ + 0x54, 0x65, 0x73, 0x74, + 0x20, 0x6E, 0x61, 0x6D, 0x65, /* "Test name" */ + 0x05, /* Short Local name len */ + 0x08, /* Short name */ + 0x54, 0x65, 0x73, 0x74, /* "Test" */ +}; + +static const struct generic_data read_ext_ctrl_info4 = { + .setup_settings = settings_le, + .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME, + .setup_send_param = &set_local_name_cp, + .setup_send_len = sizeof(set_local_name_cp), + .send_opcode = MGMT_OP_READ_EXT_INFO, + .expect_status = MGMT_STATUS_SUCCESS, + .expect_param = ext_ctrl_info4, + .expect_len = sizeof(ext_ctrl_info4), +}; + +static const struct setup_mgmt_cmd set_dev_class_cmd_arr2[] = { + { + .send_opcode = MGMT_OP_SET_DEV_CLASS, + .send_param = set_dev_class1, + .send_len = sizeof(set_dev_class1), + }, + { + .send_opcode = MGMT_OP_ADD_UUID, + .send_param = add_spp_uuid_param, + .send_len = sizeof(add_spp_uuid_param), + }, + { + .send_opcode = MGMT_OP_SET_LOCAL_NAME, + .send_param = &set_local_name_cp, + .send_len = sizeof(set_local_name_cp), + }, + { /* last element should always have opcode 0x00 */ + .send_opcode = 0x00, + .send_param = NULL, + .send_len = 0, + } +}; + +static const char ext_ctrl_info5[] = { + 0x00, 0x00, 0x00, 0x01, 0xaa, 0x00, /* btaddr */ + 0x08, /* version */ + 0x3f, 0x00, /* manufacturer */ + 0xff, 0xbf, 0x00, 0x00, /* supported settings */ + 0x81, 0x02, 0x00, 0x00, /* current settings */ + 0x16, 0x00, /* eir len */ + 0x04, /* dev class len */ + 0x0d, /* dev class info */ + 0xe0, /* minor */ + 0x03, /* major */ + 0x00, /* service classes */ + 0x0A, /* Complete Local name len */ + 0x09, /* Complete name */ + 0x54, 0x65, 0x73, 0x74, + 0x20, 0x6E, 0x61, 0x6D, 0x65, /* "Test name" */ + 0x05, /* Short Local name len */ + 0x08, /* Short name */ + 0x54, 0x65, 0x73, 0x74, /* "Test" */ +}; + +static const struct generic_data read_ext_ctrl_info5 = { + .setup_settings = settings_powered_le, + .setup_mgmt_cmd_arr = set_dev_class_cmd_arr2, + .send_opcode = MGMT_OP_READ_EXT_INFO, + .expect_status = MGMT_STATUS_SUCCESS, + .expect_param = ext_ctrl_info5, + .expect_len = sizeof(ext_ctrl_info5), +}; + static void client_cmd_complete(uint16_t opcode, uint8_t status, const void *param, uint8_t len, void *user_data) @@ -5844,6 +6044,35 @@ static void command_generic_callback(uint8_t status, uint16_t length, test_condition_complete(data); } +static void command_setup_hci_callback(uint16_t opcode, const void *param, + uint8_t length, void *user_data) +{ + struct test_data *data = user_data; + const struct generic_data *test = data->test_data; + const void *setup_expect_hci_param = test->setup_expect_hci_param; + uint8_t setup_expect_hci_len = test->setup_expect_hci_len; + + tester_print("HCI Command 0x%04x length %u", opcode, length); + + if (opcode != test->setup_expect_hci_command) + return; + + if (length != setup_expect_hci_len) { + tester_warn("Invalid parameter size for HCI command"); + tester_test_failed(); + return; + } + + if (memcmp(param, setup_expect_hci_param, length) != 0) { + tester_warn("Unexpected HCI command parameter value"); + tester_test_failed(); + return; + } + + hciemu_clear_master_post_command_hooks(data->hciemu); + test_condition_complete(data); +} + static void command_hci_callback(uint16_t opcode, const void *param, uint8_t length, void *user_data) { @@ -5875,6 +6104,65 @@ static void command_hci_callback(uint16_t opcode, const void *param, test_condition_complete(data); } +static void setup_mgmt_cmd_callback(uint8_t status, uint16_t length, + const void *param, void *user_data) +{ + if (status != MGMT_STATUS_SUCCESS) { + tester_setup_failed(); + return; + } + + tester_setup_complete(); +} + +static void setup_set_local_name(const void *test_data) +{ + struct test_data *data = tester_get_data(); + const struct generic_data *test = data->test_data; + const void *send_param = test->setup_send_param; + uint16_t send_len = test->setup_send_len; + size_t i = 0; + + if (test->setup_expect_hci_command) { + tester_print("Registering setup expected HCI command callback"); + tester_print("Setup expected HCI command 0x%04x", + test->setup_expect_hci_command); + hciemu_add_master_post_command_hook(data->hciemu, + command_setup_hci_callback, data); + test_add_condition(data); + } + + if (test->setup_send_opcode) { + tester_print("Setup sending %s (0x%04x)", + mgmt_opstr(test->setup_send_opcode), + test->setup_send_opcode); + mgmt_send(data->mgmt, test->setup_send_opcode, data->mgmt_index, + send_len, send_param, + setup_mgmt_cmd_callback, + NULL, NULL); + return; + } + + tester_print("Sending setup opcode array"); + for (; test->setup_mgmt_cmd_arr + i; ++i) { + const struct setup_mgmt_cmd *cmd = test->setup_mgmt_cmd_arr + i; + + if (cmd->send_opcode == 0x00) + break; + + tester_print("Setup sending %s (0x%04x)", + mgmt_opstr(cmd->send_opcode), + cmd->send_opcode); + + mgmt_send(data->mgmt, cmd->send_opcode, data->mgmt_index, + cmd->send_len, cmd->send_param, + setup_mgmt_cmd_callback, + NULL, NULL); + } + + tester_setup_complete(); +} + static bool power_off(uint16_t index) { int sk, err; @@ -7100,6 +7388,26 @@ int main(int argc, char *argv[]) setup_add_advertising_duration, test_command_generic, 3); + test_bredrle("Read Ext Controller Info 1", + &read_ext_ctrl_info1, + setup_set_local_name, test_command_generic); + + test_bredrle("Read Ext Controller Info 2", + &read_ext_ctrl_info2, + setup_set_local_name, test_command_generic); + + test_bredrle("Read Ext Controller Info 3", + &read_ext_ctrl_info3, + setup_set_local_name, test_command_generic); + + test_bredrle("Read Ext Controller Info 4", + &read_ext_ctrl_info4, + setup_set_local_name, test_command_generic); + + test_bredrle("Read Ext Controller Info 5", + &read_ext_ctrl_info5, + setup_set_local_name, test_command_generic); + test_bredrle("Read Local OOB Data - Not powered", &read_local_oob_not_powered_test, NULL, test_command_generic); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html