/* * Copyright (c) 2016 Nordic Semiconductor ASA * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include // Nordic NDK #if defined(CONFIG_HAS_NORDIC_DRIVERS) #include "nrf.h" #include #endif // BTstack #include "btstack_debug.h" #include "btstack_event.h" #include "btstack_memory.h" #include "hci.h" #include "hci_dump.h" #ifdef ENABLE_HCI_DUMP #ifdef ENABLE_SEGGER_RTT_BINARY #include "hci_dump_segger_rtt_binary.h" #else #include "hci_dump_embedded_stdout.h" #endif #endif #include "hci_transport.h" #include "bluetooth_company_id.h" #include "btstack_chipset_zephyr.h" #include "btstack_tlv.h" #include "btstack_tlv_none.h" #include "ble/le_device_db_tlv.h" #include "hci_transport_zephyr.h" #include "btstack_run_loop_zephyr.h" static btstack_packet_callback_registration_t hci_event_callback_registration; static bd_addr_t local_addr = { 0 }; void nrf_get_static_random_addr( bd_addr_t addr ) { // nRF5 chipsets don't have an official public address // Instead, a Static Random Address is assigned during manufacturing // let's use it as well #if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_SERIES_NRF52X) big_endian_store_16(addr, 0, NRF_FICR->DEVICEADDR[1] | 0xc000); big_endian_store_32(addr, 2, NRF_FICR->DEVICEADDR[0]); #elif defined(CONFIG_SOC_SERIES_NRF53X) big_endian_store_16(addr, 0, NRF_FICR->INFO.DEVICEID[1] | 0xc000 ); big_endian_store_32(addr, 2, NRF_FICR->INFO.DEVICEID[0]); #endif } static void local_version_information_handler(uint8_t * packet){ printf("Local version information:\n"); uint16_t hci_version = packet[6]; uint16_t hci_revision = little_endian_read_16(packet, 7); uint16_t lmp_version = packet[9]; uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t lmp_subversion = little_endian_read_16(packet, 12); printf("- HCI Version %#04x\n", hci_version); printf("- HCI Revision %#04x\n", hci_revision); printf("- LMP Version %#04x\n", lmp_version); printf("- LMP Subversion %#04x\n", lmp_subversion); printf("- Manufacturer %#04x\n", manufacturer); switch (manufacturer){ case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA: case BLUETOOTH_COMPANY_ID_THE_LINUX_FOUNDATION: printf("Nordic Semiconductor nRF5 chipset.\n"); hci_set_chipset(btstack_chipset_zephyr_instance()); break; case BLUETOOTH_COMPANY_ID_PACKETCRAFT_INC: printf("PacketCraft HCI Controller\n"); nrf_get_static_random_addr( local_addr ); gap_random_address_set( local_addr ); break; default: printf("Unknown manufacturer.\n"); nrf_get_static_random_addr( local_addr ); gap_random_address_set( local_addr ); break; } } static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ const uint8_t *params; if (packet_type != HCI_EVENT_PACKET) return; switch (hci_event_packet_get_type(packet)){ case BTSTACK_EVENT_STATE: switch(btstack_event_state_get_state(packet)){ case HCI_STATE_WORKING: printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); break; case HCI_STATE_OFF: log_info("Good bye, see you.\n"); break; default: break; } break; case HCI_EVENT_COMMAND_COMPLETE: switch (hci_event_command_complete_get_command_opcode(packet)){ case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: local_version_information_handler(packet); break; case HCI_OPCODE_HCI_READ_BD_ADDR: params = hci_event_command_complete_get_return_parameters(packet); if(params[0] != 0) break; if(size < 12) break; reverse_48(¶ms[1], local_addr); break; case HCI_OPCODE_HCI_ZEPHYR_READ_STATIC_ADDRESS: params = hci_event_command_complete_get_return_parameters(packet); if(params[0] != 0) break; if(size < 13) break; reverse_48(¶ms[2], local_addr); gap_random_address_set(local_addr); break; default: break; } break; default: break; } } int btstack_main(void); #if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) void bt_ctlr_assert_handle(char *file, uint32_t line) { printf("CONFIG_BT_CTLR_ASSERT_HANDLER: file %s, line %u\n", file, line); while (1) { } } #endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ int main(void) { #if defined(CONFIG_SOC_SERIES_NRF53X) // switch the nrf5340_cpuapp to 128MHz nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1); #endif printf("BTstack booting up..\n"); // start with BTstack init - especially configure HCI Transport btstack_memory_init(); btstack_run_loop_init(btstack_run_loop_zephyr_get_instance()); #ifdef ENABLE_HCI_DUMP // enable full log output while porting #ifdef ENABLE_SEGGER_RTT_BINARY hci_dump_segger_rtt_binary_open( HCI_DUMP_PACKETLOGGER ); hci_dump_init(hci_dump_segger_rtt_binary_get_instance()); #else hci_dump_init(hci_dump_embedded_stdout_get_instance()); #endif #endif const btstack_tlv_t * btstack_tlv_impl = btstack_tlv_none_init_instance(); // setup global tlv btstack_tlv_set_instance(btstack_tlv_impl, NULL); // setup LE Device DB using TLV le_device_db_tlv_configure(btstack_tlv_impl, NULL); // init HCI hci_init(hci_transport_zephyr_get_instance(), NULL); // inform about BTstack state hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); // hand over to btstack embedded code btstack_main(); // go btstack_run_loop_execute(); while (1){}; return 0; }