#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "CppUTest/TestHarness.h" #include "CppUTest/CommandLineTestRunner.h" #include "CppUTestExt/MockSupport.h" #include "hci_cmd.h" #include "btstack_memory.h" #include "hci.h" #include <bluetooth_company_id.h> #include "ble/gatt_client.h" #include "btstack_event.h" #include "hci_dump.h" #include "hci_dump_posix_fs.h" #include "btstack_debug.h" #include "btstack_util.h" #include "btstack_run_loop_posix.h" typedef struct { uint8_t type; uint16_t size; uint8_t buffer[258]; } hci_packet_t; #define MAX_HCI_PACKETS 10 static uint16_t transport_count_packets; static hci_packet_t transport_packets[MAX_HCI_PACKETS]; static int can_send_now = 1; static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); #if 0 static btstack_timer_source_t packet_sent_timer; static const uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; // sm_trigger_run allows to schedule callback from main run loop // reduces stack depth static void hci_transport_emit_packet_sent(btstack_timer_source_t * ts){ UNUSED(ts); // notify upper stack that it can send again can_send_now = 1; packet_handler(HCI_EVENT_PACKET, (uint8_t *) &packet_sent_event[0], sizeof(packet_sent_event)); } static void hci_transport_trigger_packet_sent(void) { btstack_run_loop_remove_timer(&packet_sent_timer); btstack_run_loop_set_timer_handler(&packet_sent_timer, &hci_transport_emit_packet_sent); btstack_run_loop_set_timer(&packet_sent_timer, 0); btstack_run_loop_add_timer(&packet_sent_timer); } static int hci_transport_test_can_send_now(uint8_t packet_type){ return can_send_now; } #endif static int hci_transport_test_set_baudrate(uint32_t baudrate){ return 0; } static int hci_transport_test_send_packet(uint8_t packet_type, uint8_t * packet, int size){ btstack_assert(transport_count_packets < MAX_HCI_PACKETS); memcpy(transport_packets[transport_count_packets].buffer, packet, size); transport_packets[transport_count_packets].type = packet_type; transport_packets[transport_count_packets].size = size; transport_count_packets++; return 0; } static void hci_transport_test_init(const void * transport_config){ } static int hci_transport_test_open(void){ return 0; } static int hci_transport_test_close(void){ return 0; } static void hci_transport_test_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ packet_handler = handler; } static const hci_transport_t hci_transport_test = { /* const char * name; */ "TEST", /* void (*init) (const void *transport_config); */ &hci_transport_test_init, /* int (*open)(void); */ &hci_transport_test_open, /* int (*close)(void); */ &hci_transport_test_close, /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_test_register_packet_handler, /* int (*can_send_packet_now)(uint8_t packet_type); */ NULL, /* int (*send_packet)(...); */ &hci_transport_test_send_packet, /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_test_set_baudrate, /* void (*reset_link)(void); */ NULL, /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, }; static uint16_t next_hci_packet; void CHECK_EQUAL_ARRAY(const uint8_t * expected, const uint8_t * actual, int size){ for (int i=0; i<size; i++){ BYTES_EQUAL(expected[i], actual[i]); } } void CHECK_HCI_COMMAND(const hci_cmd_t * expected_hci_command){ uint16_t actual_opcode = little_endian_read_16(transport_packets[next_hci_packet].buffer, 0); next_hci_packet++; CHECK_EQUAL(expected_hci_command->opcode, actual_opcode); } TEST_GROUP(HCI){ hci_stack_t * hci_stack; void setup(void){ transport_count_packets = 0; can_send_now = 1; next_hci_packet = 0; hci_init(&hci_transport_test, NULL); hci_stack = hci_get_stack(); hci_simulate_working_fuzz(); hci_setup_test_connections_fuzz(); // register for HCI events mock().expectOneCall("hci_can_send_packet_now_using_packet_buffer").andReturnValue(1); } void teardown(void){ mock().clear(); } }; TEST(HCI, GetSetConnectionRange){ le_connection_parameter_range_t range; gap_get_connection_parameter_range(&range); gap_set_connection_parameter_range(&range); } TEST(HCI, ConnectionRangeValid){ le_connection_parameter_range_t range = { .le_conn_interval_min = 1, .le_conn_interval_max = 10, .le_conn_latency_min = 1, .le_conn_latency_max = 10, .le_supervision_timeout_min = 1, .le_supervision_timeout_max = 10 }; CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 0, 0, 0, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 11, 0, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 9, 11, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 0, 0, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 9, 0, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 9, 10, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 9, 5, 0)); CHECK_EQUAL( 0, gap_connection_parameter_range_included(&range, 2, 9, 5, 11)); CHECK_EQUAL( 1, gap_connection_parameter_range_included(&range, 2, 9, 5, 5)); } TEST(HCI, other_functions){ gap_set_scan_phys(1); gap_set_connection_phys(1); hci_enable_custom_pre_init(); gap_whitelist_clear(); } TEST(HCI, gap_whitelist_add_remove){ bd_addr_type_t addr_type = BD_ADDR_TYPE_ACL; bd_addr_t addr = { 0 }; uint8_t status = gap_whitelist_add(addr_type, addr); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); status = gap_whitelist_add(addr_type, addr); CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); status = gap_whitelist_remove(addr_type, addr); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); status = gap_whitelist_remove(addr_type, addr); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); status = gap_whitelist_remove(BD_ADDR_TYPE_SCO, addr); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); } TEST(HCI, gap_connect_with_whitelist){ uint8_t status = gap_connect_with_whitelist(); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); bd_addr_type_t addr_type = BD_ADDR_TYPE_LE_PUBLIC; bd_addr_t addr = { 0 }; gap_auto_connection_start(addr_type, addr); status = gap_connect_with_whitelist(); CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); } TEST(HCI, gap_auto_connection_start_stop){ bd_addr_type_t addr_type = BD_ADDR_TYPE_LE_PUBLIC; bd_addr_t addr = { 0 }; uint8_t status = gap_auto_connection_start(addr_type, addr); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); status = gap_auto_connection_stop(addr_type, addr); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); } TEST(HCI, gap_auto_connection_stop_all){ bd_addr_type_t addr_type = BD_ADDR_TYPE_LE_PUBLIC; bd_addr_t addr = { 0 }; uint8_t status = gap_auto_connection_start(addr_type, addr); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); status = gap_auto_connection_stop_all(); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); } TEST(HCI, gap_read_rssi){ int status = gap_read_rssi(HCI_CON_HANDLE_INVALID); CHECK_EQUAL(0, status); status = gap_read_rssi(0x01); CHECK_EQUAL(1, status); } TEST(HCI, gap_le_connection_interval){ uint16_t con_interval = gap_le_connection_interval(HCI_CON_HANDLE_INVALID); CHECK_EQUAL(0, con_interval); con_interval = gap_le_connection_interval(0x01); CHECK_EQUAL(0, con_interval); } TEST(HCI, gap_get_connection_type){ gap_connection_type_t type = gap_get_connection_type(HCI_CON_HANDLE_INVALID); CHECK_EQUAL(GAP_CONNECTION_INVALID, type); type = gap_get_connection_type(0x01); CHECK_EQUAL(GAP_CONNECTION_ACL, type); } TEST(HCI, gap_le_set_phy){ uint8_t status = gap_le_set_phy(HCI_CON_HANDLE_INVALID, 0, 0, 0, 0); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); status = gap_le_set_phy(0x01, 0, 0, 0, 0); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); } TEST(HCI, hci_connection_for_bd_addr_and_type){ bd_addr_type_t addr_type = BD_ADDR_TYPE_ACL; bd_addr_t addr = { 0 }; hci_connection_t * con = hci_connection_for_bd_addr_and_type(addr , addr_type); CHECK_EQUAL(NULL, con); } TEST(HCI, hci_number_free_acl_slots_for_handle){ int free_acl_slots_num = hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_INVALID); CHECK_EQUAL(0, free_acl_slots_num); } TEST(HCI, hci_send_acl_packet_buffer_no_connection){ hci_reserve_packet_buffer(); uint8_t status = hci_send_acl_packet_buffer(16); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); } TEST(HCI, hci_send_acl_packet_buffer){ hci_reserve_packet_buffer(); uint8_t * packet = hci_get_outgoing_packet_buffer(); uint8_t flags = 0x02; // LE Packet uint16_t acl_len = 50; hci_stack->le_data_packets_length = acl_len - 10;; little_endian_store_16(packet, 0, 0x05 | (flags << 12)); uint8_t status = hci_send_acl_packet_buffer(acl_len); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); hci_stack->le_data_packets_length = 0; } TEST(HCI, hci_send_cmd_packet){ bd_addr_t addr = { 0 }; uint8_t status = hci_send_cmd(&hci_write_loopback_mode, 1); CHECK_EQUAL(0, status); uint8_t i; for (i = 0; i < 3; i++){ status = hci_send_cmd(&hci_le_create_connection, 1000, // scan interval: 625 ms 1000, // scan interval: 625 ms i, // don't use whitelist 0, // peer address type: public addr, // remote bd addr 0, // random or public 80, // conn interval min 80, // conn interval max (3200 * 0.625) 0, // conn latency 2000, // supervision timeout 0, // min ce length 1000 // max ce length ); CHECK_EQUAL(0, status); } } TEST(HCI, hci_send_cmd_va_arg){ hci_reserve_packet_buffer(); uint8_t status = hci_send_cmd(&hci_write_loopback_mode, 1); CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); } TEST(HCI, hci_power_control){ int status = hci_power_control(HCI_POWER_ON); CHECK_EQUAL(0, status); } TEST(HCI, NumPeripherals){ gap_set_max_number_peripheral_connections(1); } TEST(HCI, MaxAclLen){ hci_max_acl_data_packet_length(); } TEST(HCI, Flushable){ hci_non_flushable_packet_boundary_flag_supported(); } TEST(HCI, RemovePacketHandler){ hci_remove_event_handler(NULL); } static void dummy_fn(const void * config){}; TEST(HCI, SetChipset){ hci_set_chipset(NULL); btstack_chipset_t chipset_driver = { 0 }; hci_set_chipset(NULL); chipset_driver.init = dummy_fn; } TEST(HCI, SetControl){ btstack_control_t hardware_control = { .init = &dummy_fn}; hci_set_control(&hardware_control); } //TEST(HCI, Close){ // hci_close(); //} TEST(HCI, SetPublicAddress){ bd_addr_t addr = { 0 }; hci_set_bd_addr(addr); } TEST(HCI, DisconnectSecurityBlock){ hci_disconnect_security_block(HCI_CON_HANDLE_INVALID); hci_disconnect_security_block(3); } TEST(HCI, SetDuplicateFilter){ gap_set_scan_duplicate_filter(true); } TEST(HCI, ConnectCancel){ uint8_t status; status = gap_connect_with_whitelist(); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); gap_connect_cancel(); bd_addr_type_t addr_type = BD_ADDR_TYPE_LE_PUBLIC; bd_addr_t addr = { 0 }; gap_connect(addr, addr_type); gap_connect_cancel(); } TEST(HCI, SetGapConnParams){ gap_set_connection_parameters(0, 0, 0, 0, 0, 0, 0, 0); } TEST(HCI, UpdateConnParams){ gap_update_connection_parameters(HCI_CON_HANDLE_INVALID, 0, 0, 0, 0); gap_update_connection_parameters(5, 0, 0, 0, 0); } TEST(HCI, RequestConnParamUpdate){ gap_request_connection_parameter_update(HCI_CON_HANDLE_INVALID, 0, 0, 0, 0); gap_request_connection_parameter_update(5, 0, 0, 0, 0); } TEST(HCI, SetScanResponse){ gap_scan_response_set_data(0, NULL); } TEST(HCI, SetAddrType){ hci_le_set_own_address_type(0); hci_le_set_own_address_type(1); } TEST(HCI, AdvEnable){ gap_advertisements_enable(0); gap_advertisements_enable(1); } TEST(HCI, SetRandomAddr){ bd_addr_t addr = { 0 }; hci_le_random_address_set(addr); } TEST(HCI, Disconnect){ gap_disconnect(HCI_CON_HANDLE_INVALID); gap_disconnect(5); } TEST(HCI, GetRole){ gap_get_role(HCI_CON_HANDLE_INVALID); gap_get_role(5); } TEST(HCI, hci_is_le_identity_address_type_other){ hci_is_le_identity_address_type(BD_ADDR_TYPE_LE_PUBLIC_IDENTITY); hci_is_le_identity_address_type(BD_ADDR_TYPE_LE_RANDOM); } TEST(HCI, hci_can_send_command_packet_now){ can_send_now = 0; hci_can_send_command_packet_now(); can_send_now = 1; hci_can_send_command_packet_now(); } TEST(HCI, hci_can_send_prepared_acl_packet_now){ can_send_now = 0; hci_can_send_prepared_acl_packet_now(0); can_send_now = 1; hci_can_send_prepared_acl_packet_now(0); } TEST(HCI, hci_can_send_acl_le_packet_now) { can_send_now = 0; hci_can_send_acl_le_packet_now(); can_send_now = 1; hci_can_send_acl_le_packet_now(); } TEST(HCI, hci_number_free_acl_slots_for_connection_type) { CHECK_EQUAL(0, hci_number_free_acl_slots_for_connection_type(BD_ADDR_TYPE_UNKNOWN)); CHECK_EQUAL(255, hci_number_free_acl_slots_for_connection_type(BD_ADDR_TYPE_ACL)); CHECK_EQUAL(255, hci_number_free_acl_slots_for_connection_type(BD_ADDR_TYPE_LE_PUBLIC)); // tweak stack hci_stack_t * hci_stack = hci_get_stack(); hci_stack->le_acl_packets_total_num = 1; CHECK_EQUAL(1, hci_number_free_acl_slots_for_connection_type(BD_ADDR_TYPE_LE_PUBLIC)); } // TEST(HCI, hci_close) { // hci_close(); // } TEST(HCI, gap_connect) { bd_addr_type_t addr_type = BD_ADDR_TYPE_LE_PUBLIC; bd_addr_t addr = { 0 }; uint8_t status; status = gap_connect(addr, addr_type); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); status = gap_connect(addr, addr_type); CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); } TEST(HCI, hci_emit_state) { hci_emit_state(); } TEST(HCI, gap_request_connection_subrating) { int status = gap_request_connection_subrating(HCI_CON_HANDLE_INVALID, 0, 0, 0, 0, 0); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); status = gap_request_connection_subrating(0x01, 0, 0, 0, 0, 0); CHECK_EQUAL(ERROR_CODE_SUCCESS, status); } TEST(HCI, hci_set_hardware_error_callback) { hci_set_hardware_error_callback(NULL); } TEST(HCI, hci_disconnect_all) { hci_disconnect_all(); } TEST(HCI, hci_get_manufacturer) { hci_get_manufacturer(); } TEST(HCI, gap_authorization_state) { gap_authorization_state(HCI_CON_HANDLE_INVALID); } #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION TEST(HCI, hci_load_le_device_db_entry_into_resolving_list) { hci_load_le_device_db_entry_into_resolving_list(0); } TEST(HCI, hci_remove_le_device_db_entry_from_resolving_list) { hci_remove_le_device_db_entry_from_resolving_list(0); } TEST(HCI, gap_load_resolving_list_from_le_device_db) { gap_load_resolving_list_from_le_device_db(); } #endif TEST(HCI, gap_privacy_client) { gap_privacy_client_t client; gap_privacy_client_register(&client); gap_privacy_client_ready(&client); gap_privacy_client_unregister(&client); } TEST(HCI, acl_handling) { uint16_t con_handle = 1; uint8_t flags = 0; uint8_t packet[16]; // no connection for invalid handle memset(packet, 0xff, sizeof(packet)); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // invalid length little_endian_store_16(packet, 0, con_handle | (flags << 12)); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // fix length little_endian_store_16(packet, 2, 12); little_endian_store_16(packet, 6, 8); // unexpected acl continuation flags = 0x01; little_endian_store_16(packet, 0, con_handle | (flags << 12)); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // invalid packet boundary flags flags = 0x03; little_endian_store_16(packet, 0, con_handle | (flags << 12)); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // oversized first fragment flags = 0x02; little_endian_store_16(packet, 0, con_handle | (flags << 12)); little_endian_store_16(packet, 2, 1996); packet_handler(HCI_ACL_DATA_PACKET, packet, 2000); // 1a store first flushable fragment flags = 0x02; little_endian_store_16(packet, 0, con_handle | (flags << 12)); little_endian_store_16(packet, 2, 12); little_endian_store_16(packet, 4, 20); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // 1b another first non-flushable flags = 0x06; little_endian_store_16(packet, 0, con_handle | (flags << 12)); packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // 1c another first packet_handler(HCI_ACL_DATA_PACKET, packet, sizeof(packet)); // oversized continuation fragment flags = 0x01; little_endian_store_16(packet, 0, con_handle | (flags << 12)); little_endian_store_16(packet, 2, 1996); packet_handler(HCI_ACL_DATA_PACKET, packet, 2000); } TEST(HCI, gap_le_get_own_address) { uint8_t addr_type; bd_addr_t addr; hci_stack->le_own_addr_type = BD_ADDR_TYPE_LE_PUBLIC; gap_le_get_own_address(&addr_type, addr); hci_stack->le_own_addr_type = BD_ADDR_TYPE_LE_RANDOM; gap_le_get_own_address(&addr_type, addr); } static void simulate_hci_command_complete(uint16_t opcode, uint8_t status, uint8_t variant) { uint8_t packet[2 + 255]; packet[0] = HCI_EVENT_COMMAND_COMPLETE; packet[1] = sizeof(packet) - 2; packet[2] = 1; little_endian_store_16(packet, 3, opcode); packet[5] = status; switch (opcode) { case HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE: little_endian_store_16(packet, 6, 2000); break; case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: switch (variant) { case 0: little_endian_store_16(packet, 10, BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION); break; case 1: little_endian_store_16(packet, 10, BLUETOOTH_COMPANY_ID_INFINEON_TECHNOLOGIES_AG); break; case 2: little_endian_store_16(packet, 10, BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR); break; } break; default: break; } packet_handler(HCI_EVENT_PACKET, packet, sizeof(packet)); } TEST(HCI, handle_command_complete_event) { struct { uint16_t opcode; uint8_t status; uint8_t variants; } variations[] = { {.opcode = HCI_OPCODE_HCI_READ_LOCAL_NAME, .status = ERROR_CODE_SUCCESS}, {.opcode = HCI_OPCODE_HCI_READ_LOCAL_NAME, .status = ERROR_CODE_UNKNOWN_HCI_COMMAND }, {.opcode = HCI_OPCODE_HCI_READ_BUFFER_SIZE, .status = ERROR_CODE_SUCCESS}, {.opcode = HCI_OPCODE_HCI_READ_RSSI, .status = ERROR_CODE_SUCCESS}, {.opcode = HCI_OPCODE_HCI_READ_RSSI, .status = ERROR_CODE_UNKNOWN_HCI_COMMAND}, {.opcode = HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE }, {.opcode = HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE_V2 }, {.opcode = HCI_OPCODE_HCI_LE_READ_MAXIMUM_DATA_LENGTH }, {.opcode = HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION, .variants = 3}, }; for (uint8_t i = 0; i < sizeof(variations) / sizeof(variations[0]); i++) { // extras uint16_t opcode = variations[i].opcode; uint8_t status = variations[i].status; uint8_t variants = btstack_max(1, variations[i].variants); switch (opcode) { default: break; } for (uint8_t j=0; j < variants; j++) { simulate_hci_command_complete(opcode, status, j); } switch (opcode) { default: break; } } } static void simulate_hci_command_status(uint16_t opcode, uint8_t status, uint8_t variant) { uint8_t packet[2 + 255]; packet[0] = HCI_EVENT_COMMAND_STATUS; packet[1] = sizeof(packet) - 2; packet[2] = status; packet[3] = 1; little_endian_store_16(packet, 4, opcode); switch (opcode) { default: break; } packet_handler(HCI_EVENT_PACKET, packet, sizeof(packet)); } TEST(HCI, handle_command_status_event) { struct { uint16_t opcode; uint8_t status; uint8_t variants; } variations[] = { {.opcode = HCI_OPCODE_HCI_LE_CREATE_CONNECTION, .status = ERROR_CODE_COMMAND_DISALLOWED, .variants = 2}, }; // default address: 66:55:44:33:00:01 bd_addr_t addr = { 0x66, 0x55, 0x44, 0x33, 0x00, 0x00}; for (uint8_t i = 0; i < sizeof(variations) / sizeof(variations[0]); i++) { // extras uint16_t opcode = variations[i].opcode; uint8_t status = variations[i].status; uint8_t variants = btstack_max(1, variations[i].variants); for (uint8_t j=0; j < variants; j++) { switch (opcode) { case HCI_OPCODE_HCI_LE_CREATE_CONNECTION: hci_stack->outgoing_addr_type = BD_ADDR_TYPE_LE_PUBLIC; addr[5] = 0x05 + j; memcpy(hci_stack->outgoing_addr, &addr, sizeof(addr)); break; default: break; } simulate_hci_command_status(opcode, status, j); switch (opcode) { default: break; } } } } int main (int argc, const char * argv[]){ btstack_run_loop_init(btstack_run_loop_posix_get_instance()); return CommandLineTestRunner::RunAllTests(argc, argv); }