// SPDX-License-Identifier: GPL-2.0-or-later /* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2013 Intel Corporation. All rights reserved. * * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "monitor/bt.h" #include "src/shared/hci.h" #include "src/shared/util.h" #include "src/shared/ecc.h" #include "src/shared/tester.h" struct user_data { const void *test_data; uint16_t index_ut; uint16_t index_lt; struct bt_hci *hci_ut; /* Upper Tester / IUT */ struct bt_hci *hci_lt; /* Lower Tester / Reference */ uint8_t bdaddr_ut[6]; uint8_t bdaddr_lt[6]; uint16_t handle_ut; }; struct le_keys { uint8_t remote_sk[32]; uint8_t local_pk[64]; } key_test_data; static void swap_buf(const uint8_t *src, uint8_t *dst, uint16_t len) { int i; for (i = 0; i < len; i++) dst[len - 1 - i] = src[i]; } static void test_debug(const char *str, void *user_data) { tester_debug("%s", str); } static void test_pre_setup_lt_address(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); const struct bt_hci_rsp_read_bd_addr *rsp = data; if (rsp->status) { tester_warn("Read lower tester address failed (0x%02x)", rsp->status); tester_pre_setup_failed(); return; } memcpy(user->bdaddr_lt, rsp->bdaddr, 6); tester_pre_setup_complete(); } static void test_pre_setup_lt_complete(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Reset lower tester failed (0x%02x)", status); tester_pre_setup_failed(); return; } if (!bt_hci_send(user->hci_lt, BT_HCI_CMD_READ_BD_ADDR, NULL, 0, test_pre_setup_lt_address, NULL, NULL)) { tester_warn("Failed to read lower tester address"); tester_pre_setup_failed(); return; } } static void test_pre_setup_ut_address(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); const struct bt_hci_rsp_read_bd_addr *rsp = data; if (rsp->status) { tester_warn("Read upper tester address failed (0x%02x)", rsp->status); tester_pre_setup_failed(); return; } memcpy(user->bdaddr_ut, rsp->bdaddr, 6); user->hci_lt = bt_hci_new_user_channel(user->index_lt); if (!user->hci_lt) { tester_warn("Failed to setup lower tester user channel"); tester_pre_setup_failed(); return; } if (!bt_hci_send(user->hci_lt, BT_HCI_CMD_RESET, NULL, 0, test_pre_setup_lt_complete, NULL, NULL)) { tester_warn("Failed to reset lower tester"); tester_pre_setup_failed(); return; } } static void test_pre_setup_ut_complete(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Reset upper tester failed (0x%02x)", status); tester_pre_setup_failed(); return; } if (user->index_lt == 0xffff) { tester_pre_setup_complete(); return; } if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_READ_BD_ADDR, NULL, 0, test_pre_setup_ut_address, NULL, NULL)) { tester_warn("Failed to read upper tester address"); tester_pre_setup_failed(); return; } } static void test_pre_setup(const void *test_data) { struct user_data *user = tester_get_data(); user->hci_ut = bt_hci_new_user_channel(user->index_ut); if (!user->hci_ut) { tester_warn("Failed to setup upper tester user channel"); tester_pre_setup_failed(); return; } if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_RESET, NULL, 0, test_pre_setup_ut_complete, NULL, NULL)) { tester_warn("Failed to reset upper tester"); tester_pre_setup_failed(); return; } } 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 user_data_free(void *data) { struct user_data *user = data; free(user); } #define test_hci(name, data, setup, func, teardown) \ do { \ struct user_data *user; \ user = calloc(1, sizeof(struct user_data)); \ if (!user) \ break; \ user->test_data = data; \ user->index_ut = 0; \ user->index_lt = 1; \ tester_add_full(name, data, \ test_pre_setup, setup, func, teardown, \ test_post_teardown, 30, user, user_data_free); \ } while (0) #define test_hci_local(name, data, setup, func) \ do { \ struct user_data *user; \ user = calloc(1, sizeof(struct user_data)); \ if (!user) \ break; \ user->test_data = data; \ user->index_ut = 0; \ user->index_lt = 0xffff; \ tester_add_full(name, data, \ test_pre_setup, setup, func, NULL, \ test_post_teardown, 30, user, user_data_free); \ } while (0) static void setup_features_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_rsp_read_local_features *rsp = data; if (rsp->status) { tester_warn("Failed to get HCI features (0x%02x)", rsp->status); tester_setup_failed(); return; } tester_setup_complete(); } static void setup_features(const void *test_data) { struct user_data *user = tester_get_data(); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_READ_LOCAL_FEATURES, NULL, 0, setup_features_complete, NULL, NULL)) { tester_warn("Failed to send HCI features command"); tester_setup_failed(); return; } } static void test_reset(const void *test_data) { tester_test_passed(); } static void test_command_complete(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI command failed (0x%02x)", status); tester_test_failed(); return; } tester_test_passed(); } static void test_command(uint16_t opcode) { struct user_data *user = tester_get_data(); if (!bt_hci_send(user->hci_ut, opcode, NULL, 0, test_command_complete, NULL, NULL)) { tester_warn("Failed to send HCI command 0x%04x", opcode); tester_test_failed(); return; } } static void test_read_local_version_information(const void *test_data) { test_command(BT_HCI_CMD_READ_LOCAL_VERSION); } static void test_read_local_supported_commands(const void *test_data) { test_command(BT_HCI_CMD_READ_LOCAL_COMMANDS); } static void test_read_local_supported_features(const void *test_data) { test_command(BT_HCI_CMD_READ_LOCAL_FEATURES); } static void test_local_extended_features_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_rsp_read_local_ext_features *rsp = data; if (rsp->status) { tester_warn("Failed to get HCI extended features (0x%02x)", rsp->status); tester_test_failed(); return; } tester_test_passed(); } 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 test_read_buffer_size(const void *test_data) { test_command(BT_HCI_CMD_READ_BUFFER_SIZE); } static void test_read_country_code(const void *test_data) { test_command(BT_HCI_CMD_READ_COUNTRY_CODE); } static void test_read_bd_addr(const void *test_data) { test_command(BT_HCI_CMD_READ_BD_ADDR); } static void test_read_local_supported_codecs(const void *test_data) { test_command(BT_HCI_CMD_READ_LOCAL_CODECS); } static void test_le_read_accept_list_size(const void *test_data) { test_command(BT_HCI_CMD_LE_READ_ACCEPT_LIST_SIZE); } static void test_le_clear_accept_list(const void *test_data) { test_command(BT_HCI_CMD_LE_CLEAR_ACCEPT_LIST); } static void test_le_encrypt_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_rsp_le_encrypt *rsp = data; uint8_t sample[16] = { 0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3, 0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f }; uint8_t enc_data[16]; if (rsp->status) { tester_warn("Failed HCI LE Encrypt (0x%02x)", rsp->status); tester_test_failed(); return; } swap_buf(rsp->data, enc_data, 16); util_hexdump('>', enc_data, 16, test_debug, NULL); if (!memcmp(sample, enc_data, 16)) tester_test_passed(); else tester_test_failed(); } /* Data are taken from RFC 4493 Test Vectors */ static void test_le_encrypt(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_le_encrypt cmd; uint8_t key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; uint8_t plaintext[16] = { 0 }; /* Swap bytes since our interface has LE interface, opposed to * common crypto interface */ swap_buf(key, cmd.key, 16); swap_buf(plaintext, cmd.plaintext, 16); util_hexdump('<', cmd.key, 16, test_debug, NULL); util_hexdump('<', cmd.plaintext, 16, test_debug, NULL); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_ENCRYPT, &cmd, sizeof(cmd), test_le_encrypt_complete, NULL, NULL)) { tester_warn("Failed to send HCI LE Encrypt command"); tester_test_failed(); return; } } static void test_le_rand(const void *test_data) { test_command(BT_HCI_CMD_LE_RAND); } static void test_le_read_local_pk_complete(const void *data, uint8_t size, void *user_data) { const uint8_t *event = data; const struct bt_hci_evt_le_read_local_pk256_complete *evt; struct le_keys *keys = user_data; if (*event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { tester_warn("Failed Read Local PK256 command"); tester_test_failed(); return; } evt = (void *)(event + 1); if (evt->status) { tester_warn("HCI Read Local PK complete failed (0x%02x)", evt->status); tester_test_failed(); return; } memcpy(keys->local_pk, evt->local_pk256, 64); util_hexdump('>', evt->local_pk256, 64, test_debug, NULL); tester_test_passed(); } static void test_le_read_local_pk_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to send Read Local PK256 cmd (0x%02x)", status); tester_test_failed(); return; } } static void test_le_read_local_pk(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; bt_hci_register(user->hci_ut, BT_HCI_EVT_LE_META_EVENT, test_le_read_local_pk_complete, (void *)test_data, 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_ut, BT_HCI_CMD_SET_EVENT_MASK, &sem, sizeof(sem), NULL, NULL, NULL); memset(lsem.mask, 0, 8); lsem.mask[0] |= 0x80; /* LE Read Local P-256 Public Key Complete */ bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_EVENT_MASK, &lsem, sizeof(lsem), NULL, NULL, NULL); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_READ_LOCAL_PK256, NULL, 0, test_le_read_local_pk_status, NULL, NULL)) { tester_warn("Failed to send HCI LE Read Local PK256 command"); tester_test_failed(); return; } } static void setup_le_read_local_pk_complete(const void *data, uint8_t size, void *user_data) { const uint8_t *event = data; const struct bt_hci_evt_le_read_local_pk256_complete *evt; struct le_keys *keys = user_data; if (*event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { tester_warn("Failed Read Local PK256 command"); tester_setup_failed(); return; } evt = (void *)(event + 1); if (evt->status) { tester_warn("HCI Read Local PK complete failed (0x%02x)", evt->status); tester_setup_failed(); return; } memcpy(keys->local_pk, evt->local_pk256, 64); util_hexdump('>', evt->local_pk256, 64, test_debug, NULL); tester_setup_complete(); } static void setup_le_read_local_pk_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to send DHKey gen cmd (0x%02x)", status); tester_setup_failed(); return; } } static void setup_le_generate_dhkey(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; bt_hci_register(user->hci_ut, BT_HCI_EVT_LE_META_EVENT, setup_le_read_local_pk_complete, (void *)test_data, 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_ut, BT_HCI_CMD_SET_EVENT_MASK, &sem, sizeof(sem), NULL, NULL, NULL); memset(lsem.mask, 0, 8); lsem.mask[0] |= 0x80; /* LE Read Local P-256 Public Key Complete */ lsem.mask[1] |= 0x01; /* LE Generate DHKey Complete */ bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_EVENT_MASK, &lsem, sizeof(lsem), NULL, NULL, 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 test_le_generate_dhkey_complete(const void *data, uint8_t size, void *user_data) { const uint8_t *event = data; const struct bt_hci_evt_le_generate_dhkey_complete *evt; struct le_keys *keys = user_data; uint8_t dhkey[32]; if (*event != BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE) { tester_warn("Failed DHKey generation command"); tester_test_failed(); return; } evt = (void *)(event + 1); if (evt->status) { tester_warn("HCI Generate DHKey complete failed (0x%02x)", evt->status); tester_test_failed(); return; } util_hexdump('>', evt->dhkey, 32, test_debug, NULL); util_hexdump('S', keys->remote_sk, 32, test_debug, NULL); util_hexdump('P', keys->local_pk, 64, test_debug, NULL); /* Generate DHKey ourself with local public key and remote * private key we got when generated public / private key * pair for BT_HCI_CMD_LE_GENERATE_DHKEY argument. */ ecdh_shared_secret(keys->local_pk, keys->remote_sk, dhkey); util_hexdump('D', dhkey, 32, test_debug, NULL); if (!memcmp(dhkey, evt->dhkey, 32)) tester_test_passed(); else tester_test_failed(); } static void test_le_generate_dhkey_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to send DHKey gen cmd (0x%02x)", status); tester_test_failed(); return; } } static void test_le_generate_dhkey(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_le_generate_dhkey cmd; struct le_keys *keys = (void *)test_data; ecc_make_key(cmd.remote_pk256, keys->remote_sk); /* Unregister handler for META event */ bt_hci_unregister(user->hci_ut, 1); bt_hci_register(user->hci_ut, BT_HCI_EVT_LE_META_EVENT, test_le_generate_dhkey_complete, keys, NULL); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_GENERATE_DHKEY, &cmd, sizeof(cmd), test_le_generate_dhkey_status, NULL, NULL)) { tester_warn("Failed to send HCI LE Encrypt command"); tester_test_failed(); return; } } static void test_inquiry_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_evt_inquiry_complete *evt = data; if (evt->status) { tester_warn("HCI inquiry complete failed (0x%02x)", evt->status); tester_test_failed(); return; } tester_test_passed(); } static void test_inquiry_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI inquiry command failed (0x%02x)", status); tester_test_failed(); return; } } static void test_inquiry_liac(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_inquiry cmd; bt_hci_register(user->hci_ut, BT_HCI_EVT_INQUIRY_COMPLETE, test_inquiry_complete, NULL, NULL); cmd.lap[0] = 0x00; cmd.lap[1] = 0x8b; cmd.lap[2] = 0x9e; cmd.length = 0x08; cmd.num_resp = 0x00; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_INQUIRY, &cmd, sizeof(cmd), test_inquiry_status, NULL, NULL)) { tester_warn("Failed to send HCI inquiry command"); tester_test_failed(); return; } } static void setup_lt_connectable_complete(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to set HCI scan enable (0x%02x)", status); tester_setup_failed(); return; } tester_setup_complete(); } 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 setup_lt_connectable(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_write_scan_enable cmd; bt_hci_register(user->hci_lt, BT_HCI_EVT_CONN_REQUEST, setup_lt_connect_request_accept, NULL, NULL); cmd.enable = 0x02; if (!bt_hci_send(user->hci_lt, BT_HCI_CMD_WRITE_SCAN_ENABLE, &cmd, sizeof(cmd), setup_lt_connectable_complete, NULL, NULL)) { tester_warn("Failed to send HCI scan enable command"); tester_setup_failed(); return; } } static void test_create_connection_disconnect(void *user_data) { tester_test_passed(); } static void test_create_connection_complete(const void *data, uint8_t size, void *user_data) { struct user_data *user = tester_get_data(); const struct bt_hci_evt_conn_complete *evt = data; if (evt->status) { tester_warn("HCI create connection complete failed (0x%02x)", evt->status); tester_test_failed(); return; } user->handle_ut = le16_to_cpu(evt->handle); tester_wait(2, test_create_connection_disconnect, NULL); } static void test_create_connection_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI create connection command failed (0x%02x)", status); tester_test_failed(); return; } } static void test_create_connection(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_create_conn cmd; bt_hci_register(user->hci_ut, BT_HCI_EVT_CONN_COMPLETE, test_create_connection_complete, NULL, NULL); memcpy(cmd.bdaddr, user->bdaddr_lt, 6); cmd.pkt_type = cpu_to_le16(0x0008); cmd.pscan_rep_mode = 0x02; cmd.pscan_mode = 0x00; cmd.clock_offset = cpu_to_le16(0x0000); cmd.role_switch = 0x01; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_CREATE_CONN, &cmd, sizeof(cmd), test_create_connection_status, NULL, NULL)) { tester_warn("Failed to send HCI create connection command"); tester_test_failed(); return; } } static void teardown_timeout(void *user_data) { tester_teardown_complete(); } static void teardown_disconnect_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI disconnect failed (0x%02x)", status); tester_teardown_failed(); return; } tester_wait(1, teardown_timeout, 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_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 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 test_reset_in_advertising_state_timeout(void *user_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_le_set_adv_enable lsae; struct bt_hci_cmd_le_set_scan_enable lsse; lsae.enable = 0x00; bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_ADV_ENABLE, &lsae, sizeof(lsae), NULL, NULL, NULL); lsse.enable = 0x00; lsse.filter_dup = 0x00; bt_hci_send(user->hci_lt, BT_HCI_CMD_LE_SET_SCAN_ENABLE, &lsse, sizeof(lsse), NULL, NULL, NULL); tester_test_passed(); } static void test_reset_in_advertising_state(const void *test_data) { struct user_data *user = tester_get_data(); bt_hci_send(user->hci_ut, BT_HCI_CMD_RESET, NULL, 0, NULL, NULL, NULL); tester_wait(5, test_reset_in_advertising_state_timeout, NULL); } int main(int argc, char *argv[]) { tester_init(&argc, &argv); test_hci_local("Reset", NULL, NULL, test_reset); test_hci_local("Read Local Version Information", NULL, NULL, test_read_local_version_information); test_hci_local("Read Local Supported Commands", NULL, NULL, test_read_local_supported_commands); test_hci_local("Read Local Supported Features", NULL, NULL, test_read_local_supported_features); test_hci_local("Read Local Extended Features", NULL, setup_features, test_read_local_extended_features); test_hci_local("Read Buffer Size", NULL, NULL, test_read_buffer_size); test_hci_local("Read Country Code", NULL, NULL, test_read_country_code); test_hci_local("Read BD_ADDR", NULL, NULL, test_read_bd_addr); test_hci_local("Read Local Supported Codecs", NULL, NULL, test_read_local_supported_codecs); test_hci_local("LE Read Accept List Size", NULL, NULL, test_le_read_accept_list_size); test_hci_local("LE Clear Accept List", NULL, NULL, test_le_clear_accept_list); test_hci_local("LE Encrypt", NULL, NULL, test_le_encrypt); test_hci_local("LE Rand", NULL, NULL, test_le_rand); test_hci_local("LE Read Local PK", &key_test_data, NULL, test_le_read_local_pk); test_hci_local("LE Generate DHKey", &key_test_data, setup_le_generate_dhkey, test_le_generate_dhkey); test_hci_local("Inquiry (LIAC)", NULL, NULL, test_inquiry_liac); test_hci("Create Connection", NULL, setup_lt_connectable, test_create_connection, teardown_connection); test_hci("TP/DSU/BV-02-C Reset in Advertising State", NULL, setup_advertising_initiated, test_reset_in_advertising_state, NULL); return tester_run(); }