1277e512cSDirk Helbig /* 2277e512cSDirk Helbig * Copyright (c) 2016 Nordic Semiconductor ASA 3277e512cSDirk Helbig * Copyright (c) 2015-2016 Intel Corporation 4277e512cSDirk Helbig * 5277e512cSDirk Helbig * SPDX-License-Identifier: Apache-2.0 6277e512cSDirk Helbig */ 7277e512cSDirk Helbig 8277e512cSDirk Helbig #include <errno.h> 9277e512cSDirk Helbig #include <stddef.h> 10277e512cSDirk Helbig #include <stdio.h> 11277e512cSDirk Helbig #include <string.h> 12277e512cSDirk Helbig 13277e512cSDirk Helbig #include <zephyr/kernel.h> 14277e512cSDirk Helbig #include <zephyr/bluetooth/bluetooth.h> 15277e512cSDirk Helbig #include <zephyr/bluetooth/l2cap.h> 16277e512cSDirk Helbig #include <zephyr/bluetooth/hci.h> 17277e512cSDirk Helbig #include <zephyr/bluetooth/buf.h> 18277e512cSDirk Helbig #include <zephyr/bluetooth/hci_raw.h> 19277e512cSDirk Helbig 20277e512cSDirk Helbig // Nordic NDK 21277e512cSDirk Helbig #include "nrf.h" 22277e512cSDirk Helbig 23277e512cSDirk Helbig // BTstack 24277e512cSDirk Helbig #include "btstack_debug.h" 25277e512cSDirk Helbig #include "btstack_event.h" 26277e512cSDirk Helbig #include "btstack_memory.h" 27277e512cSDirk Helbig #include "hci.h" 28277e512cSDirk Helbig #include "hci_dump.h" 29277e512cSDirk Helbig #include "hci_dump_embedded_stdout.h" 30277e512cSDirk Helbig #include "hci_transport.h" 31277e512cSDirk Helbig 32277e512cSDirk Helbig #include "btstack_tlv.h" 33277e512cSDirk Helbig #include "btstack_tlv_none.h" 34277e512cSDirk Helbig #include "ble/le_device_db_tlv.h" 35277e512cSDirk Helbig 36277e512cSDirk Helbig static K_FIFO_DEFINE(tx_queue); 37277e512cSDirk Helbig static K_FIFO_DEFINE(rx_queue); 38277e512cSDirk Helbig 39277e512cSDirk Helbig // 40277e512cSDirk Helbig // hci_transport_zephyr.c 41277e512cSDirk Helbig // 42277e512cSDirk Helbig 43277e512cSDirk Helbig static void (*transport_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); 44277e512cSDirk Helbig 45277e512cSDirk Helbig /** 46277e512cSDirk Helbig * init transport 47277e512cSDirk Helbig * @param transport_config 48277e512cSDirk Helbig */ 49277e512cSDirk Helbig static void transport_init(const void *transport_config){ 50277e512cSDirk Helbig /* startup Controller */ 51277e512cSDirk Helbig bt_enable_raw(&rx_queue); 52277e512cSDirk Helbig } 53277e512cSDirk Helbig 54277e512cSDirk Helbig /** 55277e512cSDirk Helbig * open transport connection 56277e512cSDirk Helbig */ 57277e512cSDirk Helbig static int transport_open(void){ 58277e512cSDirk Helbig return 0; 59277e512cSDirk Helbig } 60277e512cSDirk Helbig 61277e512cSDirk Helbig /** 62277e512cSDirk Helbig * close transport connection 63277e512cSDirk Helbig */ 64277e512cSDirk Helbig static int transport_close(void){ 65277e512cSDirk Helbig return 0; 66277e512cSDirk Helbig } 67277e512cSDirk Helbig 68277e512cSDirk Helbig /** 69277e512cSDirk Helbig * register packet handler for HCI packets: ACL, SCO, and Events 70277e512cSDirk Helbig */ 71277e512cSDirk Helbig static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 72277e512cSDirk Helbig transport_packet_handler = handler; 73277e512cSDirk Helbig } 74277e512cSDirk Helbig 75277e512cSDirk Helbig static void send_hardware_error(uint8_t error_code){ 76277e512cSDirk Helbig // hci_outgoing_event[0] = HCI_EVENT_HARDWARE_ERROR; 77277e512cSDirk Helbig // hci_outgoing_event[1] = 1; 78277e512cSDirk Helbig // hci_outgoing_event[2] = error_code; 79277e512cSDirk Helbig // hci_outgoing_event_ready = 1; 80277e512cSDirk Helbig } 81277e512cSDirk Helbig 82277e512cSDirk Helbig static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){ 83277e512cSDirk Helbig struct net_buf *buf; 84277e512cSDirk Helbig switch (packet_type){ 85277e512cSDirk Helbig case HCI_COMMAND_DATA_PACKET: 86277e512cSDirk Helbig buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, packet, size); 87277e512cSDirk Helbig if (!buf) { 88277e512cSDirk Helbig log_error("No available command buffers!\n"); 89277e512cSDirk Helbig break; 90277e512cSDirk Helbig } 91277e512cSDirk Helbig 92277e512cSDirk Helbig memcpy(net_buf_add(buf, size), packet, size); 93277e512cSDirk Helbig bt_send(buf); 94277e512cSDirk Helbig break; 95277e512cSDirk Helbig case HCI_ACL_DATA_PACKET: 96277e512cSDirk Helbig buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, packet, size); 97277e512cSDirk Helbig if (!buf) { 98277e512cSDirk Helbig log_error("No available ACL buffers!\n"); 99277e512cSDirk Helbig break; 100277e512cSDirk Helbig } 101277e512cSDirk Helbig 102277e512cSDirk Helbig memcpy(net_buf_add(buf, size), packet, size); 103277e512cSDirk Helbig bt_send(buf); 104277e512cSDirk Helbig break; 105277e512cSDirk Helbig default: 106277e512cSDirk Helbig send_hardware_error(0x01); // invalid HCI packet 107277e512cSDirk Helbig break; 108277e512cSDirk Helbig } 109277e512cSDirk Helbig 110277e512cSDirk Helbig return 0; 111277e512cSDirk Helbig } 112277e512cSDirk Helbig 113277e512cSDirk Helbig static const hci_transport_t transport = { 114*fba2f984SMatthias Ringwald /* const char * name; */ "zephyr", 115277e512cSDirk Helbig /* void (*init) (const void *transport_config); */ &transport_init, 116277e512cSDirk Helbig /* int (*open)(void); */ &transport_open, 117277e512cSDirk Helbig /* int (*close)(void); */ &transport_close, 118277e512cSDirk Helbig /* void (*register_packet_handler)(void (*handler)(...); */ &transport_register_packet_handler, 119277e512cSDirk Helbig /* int (*can_send_packet_now)(uint8_t packet_type); */ NULL, 120277e512cSDirk Helbig /* int (*send_packet)(...); */ &transport_send_packet, 121277e512cSDirk Helbig /* int (*set_baudrate)(uint32_t baudrate); */ NULL, 122277e512cSDirk Helbig /* void (*reset_link)(void); */ NULL, 123277e512cSDirk Helbig }; 124277e512cSDirk Helbig 125277e512cSDirk Helbig static const hci_transport_t * transport_get_instance(void){ 126277e512cSDirk Helbig return &transport; 127277e512cSDirk Helbig } 128277e512cSDirk Helbig 129277e512cSDirk Helbig static void transport_deliver_controller_packet(struct net_buf * buf){ 130277e512cSDirk Helbig uint16_t size = buf->len; 131277e512cSDirk Helbig uint8_t * packet = buf->data; 132277e512cSDirk Helbig switch (bt_buf_get_type(buf)) { 133277e512cSDirk Helbig case BT_BUF_ACL_IN: 134277e512cSDirk Helbig transport_packet_handler(HCI_ACL_DATA_PACKET, packet, size); 135277e512cSDirk Helbig break; 136277e512cSDirk Helbig case BT_BUF_EVT: 137277e512cSDirk Helbig transport_packet_handler(HCI_EVENT_PACKET, packet, size); 138277e512cSDirk Helbig break; 139277e512cSDirk Helbig default: 140277e512cSDirk Helbig log_error("Unknown type %u\n", bt_buf_get_type(buf)); 141277e512cSDirk Helbig break; 142277e512cSDirk Helbig } 143277e512cSDirk Helbig net_buf_unref(buf); 144277e512cSDirk Helbig } 145277e512cSDirk Helbig 146277e512cSDirk Helbig // btstack_run_loop_zephry.c 147277e512cSDirk Helbig 148277e512cSDirk Helbig // the run loop 149277e512cSDirk Helbig //static btstack_linked_list_t timers; 150277e512cSDirk Helbig 151277e512cSDirk Helbig // TODO: handle 32 bit ms time overrun 152277e512cSDirk Helbig static uint32_t btstack_run_loop_zephyr_get_time_ms(void){ 153277e512cSDirk Helbig return k_uptime_get_32(); 154277e512cSDirk Helbig } 155277e512cSDirk Helbig 156277e512cSDirk Helbig static void btstack_run_loop_zephyr_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){ 157277e512cSDirk Helbig ts->timeout = k_uptime_get_32() + 1 + timeout_in_ms; 158277e512cSDirk Helbig } 159277e512cSDirk Helbig 160277e512cSDirk Helbig /** 161277e512cSDirk Helbig * Execute run_loop 162277e512cSDirk Helbig */ 163277e512cSDirk Helbig static void btstack_run_loop_zephyr_execute(void) { 164277e512cSDirk Helbig while (1) { 165277e512cSDirk Helbig // process timers 166277e512cSDirk Helbig uint32_t now = k_uptime_get_32(); 167277e512cSDirk Helbig btstack_run_loop_base_process_timers(now); 168277e512cSDirk Helbig 169277e512cSDirk Helbig // get time until next timer expires 170277e512cSDirk Helbig k_timeout_t timeout; 171277e512cSDirk Helbig timeout.ticks = btstack_run_loop_base_get_time_until_timeout(now); 172277e512cSDirk Helbig if (timeout.ticks < 0){ 173277e512cSDirk Helbig timeout.ticks = K_TICKS_FOREVER; 174277e512cSDirk Helbig } 175277e512cSDirk Helbig 176277e512cSDirk Helbig // process RX fifo only 177277e512cSDirk Helbig struct net_buf *buf = net_buf_get(&rx_queue, timeout); 178277e512cSDirk Helbig if (buf){ 179277e512cSDirk Helbig transport_deliver_controller_packet(buf); 180277e512cSDirk Helbig } 181277e512cSDirk Helbig } 182277e512cSDirk Helbig } 183277e512cSDirk Helbig 184277e512cSDirk Helbig static void btstack_run_loop_zephyr_btstack_run_loop_init(void){ 185277e512cSDirk Helbig btstack_run_loop_base_init(); 186277e512cSDirk Helbig } 187277e512cSDirk Helbig 188277e512cSDirk Helbig static const btstack_run_loop_t btstack_run_loop_zephyr = { 189277e512cSDirk Helbig &btstack_run_loop_zephyr_btstack_run_loop_init, 190277e512cSDirk Helbig NULL, 191277e512cSDirk Helbig NULL, 192277e512cSDirk Helbig NULL, 193277e512cSDirk Helbig NULL, 194277e512cSDirk Helbig &btstack_run_loop_zephyr_set_timer, 195277e512cSDirk Helbig &btstack_run_loop_base_add_timer, 196277e512cSDirk Helbig &btstack_run_loop_base_remove_timer, 197277e512cSDirk Helbig &btstack_run_loop_zephyr_execute, 198277e512cSDirk Helbig &btstack_run_loop_base_dump_timer, 199277e512cSDirk Helbig &btstack_run_loop_zephyr_get_time_ms, 200277e512cSDirk Helbig }; 201277e512cSDirk Helbig /** 202277e512cSDirk Helbig * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init 203277e512cSDirk Helbig */ 204277e512cSDirk Helbig const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void){ 205277e512cSDirk Helbig return &btstack_run_loop_zephyr; 206277e512cSDirk Helbig } 207277e512cSDirk Helbig 208277e512cSDirk Helbig static btstack_packet_callback_registration_t hci_event_callback_registration; 209277e512cSDirk Helbig 210277e512cSDirk Helbig static bd_addr_t static_address; 211277e512cSDirk Helbig 212277e512cSDirk Helbig static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 213277e512cSDirk Helbig if (packet_type != HCI_EVENT_PACKET) return; 214277e512cSDirk Helbig if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return; 215277e512cSDirk Helbig if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 216277e512cSDirk Helbig printf("BTstack up and running as %s.\n", bd_addr_to_str(static_address)); 217277e512cSDirk Helbig } 218277e512cSDirk Helbig 219277e512cSDirk Helbig int btstack_main(void); 220277e512cSDirk Helbig 221277e512cSDirk Helbig #if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) 222277e512cSDirk Helbig void bt_ctlr_assert_handle(char *file, uint32_t line) 223277e512cSDirk Helbig { 224277e512cSDirk Helbig printf("CONFIG_BT_CTLR_ASSERT_HANDLER: file %s, line %u\n", file, line); 225277e512cSDirk Helbig while (1) { 226277e512cSDirk Helbig } 227277e512cSDirk Helbig } 228277e512cSDirk Helbig #endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ 229277e512cSDirk Helbig 230277e512cSDirk Helbig void main(void) 231277e512cSDirk Helbig { 232277e512cSDirk Helbig // configure console UART by replacing CONFIG_UART_NRF5_BAUD_RATE with 115200 in uart_console.c 233277e512cSDirk Helbig 234277e512cSDirk Helbig printf("BTstack booting up..\n"); 235277e512cSDirk Helbig 236277e512cSDirk Helbig // start with BTstack init - especially configure HCI Transport 237277e512cSDirk Helbig btstack_memory_init(); 238277e512cSDirk Helbig btstack_run_loop_init(btstack_run_loop_zephyr_get_instance()); 239277e512cSDirk Helbig 240277e512cSDirk Helbig // enable full log output while porting 241277e512cSDirk Helbig hci_dump_init(hci_dump_embedded_stdout_get_instance()); 242277e512cSDirk Helbig 243277e512cSDirk Helbig const btstack_tlv_t * btstack_tlv_impl = btstack_tlv_none_init_instance(); 244277e512cSDirk Helbig // setup global tlv 245277e512cSDirk Helbig btstack_tlv_set_instance(btstack_tlv_impl, NULL); 246277e512cSDirk Helbig 247277e512cSDirk Helbig // setup LE Device DB using TLV 248277e512cSDirk Helbig le_device_db_tlv_configure(btstack_tlv_impl, NULL); 249277e512cSDirk Helbig 250277e512cSDirk Helbig // init HCI 251277e512cSDirk Helbig hci_init(transport_get_instance(), NULL); 252277e512cSDirk Helbig 253277e512cSDirk Helbig // nRF5 chipsets don't have an official public address 254277e512cSDirk Helbig // Instead, a Static Random Address is assigned during manufacturing 255277e512cSDirk Helbig // let's use it as well 256277e512cSDirk Helbig big_endian_store_16(static_address, 0, NRF_FICR->DEVICEADDR[1] | 0xc000); 257277e512cSDirk Helbig big_endian_store_32(static_address, 2, NRF_FICR->DEVICEADDR[0]); 258277e512cSDirk Helbig gap_random_address_set(static_address); 259277e512cSDirk Helbig 260277e512cSDirk Helbig // inform about BTstack state 261277e512cSDirk Helbig hci_event_callback_registration.callback = &packet_handler; 262277e512cSDirk Helbig hci_add_event_handler(&hci_event_callback_registration); 263277e512cSDirk Helbig 264277e512cSDirk Helbig // hand over to btstack embedded code 265277e512cSDirk Helbig btstack_main(); 266277e512cSDirk Helbig 267277e512cSDirk Helbig // go 268277e512cSDirk Helbig btstack_run_loop_execute(); 269277e512cSDirk Helbig 270277e512cSDirk Helbig while (1){}; 271277e512cSDirk Helbig } 272