From cc3744117d596aa862ef923beec65b3672329c08 Mon Sep 17 00:00:00 2001 From: Dirk Helbig <42479019+hegdi@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:18:57 +0100 Subject: [PATCH] platform/zephyr: full run loop support and transport --- platform/zephyr/btstack_run_loop_zephyr.c | 225 ++++++++++++++++++ platform/zephyr/btstack_run_loop_zephyr.h | 71 ++++++ .../zephyr}/hal_flash_bank_zephyr.c | 0 .../zephyr}/hal_flash_bank_zephyr.h | 0 platform/zephyr/hci_transport_zephyr.c | 182 ++++++++++++++ platform/zephyr/hci_transport_zephyr.h | 57 +++++ port/zephyr/CMakeLists.txt | 7 +- port/zephyr/src/main.c | 193 +-------------- 8 files changed, 544 insertions(+), 191 deletions(-) create mode 100644 platform/zephyr/btstack_run_loop_zephyr.c create mode 100644 platform/zephyr/btstack_run_loop_zephyr.h rename {port/zephyr/src => platform/zephyr}/hal_flash_bank_zephyr.c (100%) rename {port/zephyr/src => platform/zephyr}/hal_flash_bank_zephyr.h (100%) create mode 100644 platform/zephyr/hci_transport_zephyr.c create mode 100644 platform/zephyr/hci_transport_zephyr.h diff --git a/platform/zephyr/btstack_run_loop_zephyr.c b/platform/zephyr/btstack_run_loop_zephyr.c new file mode 100644 index 000000000..41f7ba8f6 --- /dev/null +++ b/platform/zephyr/btstack_run_loop_zephyr.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +//#include +//#include +//#include +//#include + +// Zephyr +#include + +// BTstack +#include "btstack_debug.h" +#include "btstack_run_loop_zephyr.h" + +#define SIGNAL_POLL (0xCA11) +#define SIGNAL_EXEC (0xE8EC) + +#define NUM_EVENTS 10 + +static struct k_poll_event events[NUM_EVENTS]; +static btstack_data_source_t *data_sources[NUM_EVENTS]; + +bool btstack_run_loop_zephyr_exit_requested = false; +bool btstack_run_loop_zephyr_data_sources_modified = false; + +/** + * Add data_source to run_loop + */ +static void btstack_run_loop_zephyr_add_data_source(btstack_data_source_t *ds){ + btstack_run_loop_zephyr_data_sources_modified = true; + btstack_run_loop_base_add_data_source(ds); +} + +/** + * Remove data_source from run loop + */ +static bool btstack_run_loop_zephyr_remove_data_source(btstack_data_source_t *ds){ + btstack_run_loop_zephyr_data_sources_modified = true; + return btstack_run_loop_base_remove_data_source(ds); +} + +// TODO: handle 32 bit ms time overrun +static uint32_t btstack_run_loop_zephyr_get_time_ms(void){ + return k_uptime_get_32(); +} + +static void btstack_run_loop_zephyr_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){ + ts->timeout = k_uptime_get_32() + 1 + timeout_in_ms; +} + +static struct k_poll_signal signal; +static fat_variable_t signal_variable = { .variable = &signal, .id = K_POLL_TYPE_SIGNAL }; +static btstack_data_source_t signal_data_source; + +static void btstack_run_loop_zephyr_signal( int value ) { + k_poll_signal_raise(&signal, value); +} + +static K_MUTEX_DEFINE(btstack_run_loop_zephyr_callbacks_mutex); + +static void btstack_run_loop_zephyr_signal_handler( + btstack_data_source_t * ds, + btstack_data_source_callback_type_t callback_type ) { + int signaled, result; + k_poll_signal_check(&signal, &signaled, &result); + k_poll_signal_reset(&signal); + if( !signaled ) { + return; + } + log_debug("%s( %x )", __func__, result ); + switch( result ) { + case SIGNAL_POLL: + btstack_run_loop_base_poll_data_sources(); + break; + case SIGNAL_EXEC: + for (;;){ + k_mutex_lock(&btstack_run_loop_zephyr_callbacks_mutex, K_FOREVER); + btstack_context_callback_registration_t * callback_registration = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&btstack_run_loop_base_callbacks); + k_mutex_unlock(&btstack_run_loop_zephyr_callbacks_mutex); + if (callback_registration == NULL){ + break; + } + (*callback_registration->callback)(callback_registration->context); + } + break; + default: + break; + } + +} + +#ifdef ENABLE_LOG_DEBUG +#define STR(x) #x +static const char *event_state_to_text[] = { + [K_POLL_STATE_SEM_AVAILABLE] = STR(K_POLL_STATE_SEM_AVAILABLE), + [K_POLL_STATE_FIFO_DATA_AVAILABLE] = STR(K_POLL_STATE_FIFO_DATA_AVAILABLE), + [K_POLL_STATE_MSGQ_DATA_AVAILABLE] = STR(K_POLL_STATE_MSGQ_DATA_AVAILABLE), + [K_POLL_STATE_PIPE_DATA_AVAILABLE] = STR(K_POLL_STATE_PIPE_DATA_AVAILABLE), + [K_POLL_STATE_SIGNALED] = STR(K_POLL_STATE_SIGNALED), +}; + +static const char *event_type_to_text[] = { + [K_POLL_TYPE_SEM_AVAILABLE] = STR(K_POLL_TYPE_SEM_AVAILABLE), + [K_POLL_TYPE_FIFO_DATA_AVAILABLE] = STR(K_POLL_TYPE_FIFO_DATA_AVAILABLE), + [K_POLL_TYPE_MSGQ_DATA_AVAILABLE] = STR(K_POLL_TYPE_MSGQ_DATA_AVAILABLE), + [K_POLL_TYPE_PIPE_DATA_AVAILABLE] = STR(K_POLL_TYPE_PIPE_DATA_AVAILABLE), + [K_POLL_TYPE_SIGNAL] = STR(K_POLL_TYPE_SIGNAL), +}; +#endif + +/** + * Execute run_loop + */ +static void btstack_run_loop_zephyr_execute(void) { + btstack_linked_list_iterator_t it; + btstack_run_loop_zephyr_exit_requested = false; + + k_poll_signal_init( &signal ); + + btstack_data_source_t *ds = &signal_data_source; + btstack_run_loop_set_data_source_handle(ds, &signal_variable); + btstack_run_loop_set_data_source_handler(ds, &btstack_run_loop_zephyr_signal_handler); + btstack_run_loop_add_data_source(ds); + btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); + + const uint32_t state_mask = + K_POLL_STATE_SEM_AVAILABLE | + K_POLL_STATE_FIFO_DATA_AVAILABLE | + K_POLL_STATE_MSGQ_DATA_AVAILABLE | + K_POLL_STATE_PIPE_DATA_AVAILABLE | + K_POLL_STATE_SIGNALED; + + for (;btstack_run_loop_zephyr_exit_requested!=true;) { + // process timers + uint32_t now = k_uptime_get_32(); + btstack_run_loop_base_process_timers(now); + + btstack_linked_list_iterator_init(&it, &btstack_run_loop_base_data_sources); + int nbr_events = 0; + while( btstack_linked_list_iterator_has_next(&it) && (nbr_eventssource.handle; + int current_event = nbr_events++; + log_debug("arm [%d] %s", current_event, event_type_to_text[fat->id]); + k_poll_event_init( &events[current_event], + fat->id, + K_POLL_MODE_NOTIFY_ONLY, + fat->variable); + data_sources[current_event] = ds; + } + // get time until next timer expires + int32_t timeout_ms = btstack_run_loop_base_get_time_until_timeout(now); + k_timeout_t timeout = K_MSEC(timeout_ms); + if (timeout_ms < 0){ + timeout = K_FOREVER; + } + int rc = k_poll(events, nbr_events, timeout); + if( btstack_run_loop_zephyr_exit_requested ) { + return; + } + // handle timeouts on -EAGAIN + if( rc != 0 ) { + continue; + } + for( int i=0; i 0) { + log_debug("trigger [%d] %s", i, event_state_to_text[state]); + btstack_data_source_t *ds = data_sources[i]; + ds->process(ds, DATA_SOURCE_CALLBACK_READ); + } + } + } +} + +static void btstack_run_loop_zephyr_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration){ + // protect list with mutex + k_mutex_lock(&btstack_run_loop_zephyr_callbacks_mutex, K_FOREVER); + btstack_run_loop_base_add_callback(callback_registration); + k_mutex_unlock(&btstack_run_loop_zephyr_callbacks_mutex); + // trigger run loop + btstack_run_loop_zephyr_signal( SIGNAL_EXEC ); +} + +static void btstack_run_loop_zephyr_btstack_run_loop_init(void){ + btstack_run_loop_base_init(); +} + +static void btstack_run_loop_zephyr_poll_data_sources_from_irq(void) { + btstack_run_loop_zephyr_signal( SIGNAL_POLL ); +} + +static void btstack_run_loop_zephyr_trigger_exit(void) { + btstack_run_loop_zephyr_exit_requested = true; + btstack_run_loop_zephyr_signal( SIGNAL_POLL ); +} + +static const btstack_run_loop_t btstack_run_loop_zephyr = { + &btstack_run_loop_zephyr_btstack_run_loop_init, + &btstack_run_loop_zephyr_add_data_source, + &btstack_run_loop_zephyr_remove_data_source, + &btstack_run_loop_base_enable_data_source_callbacks, + &btstack_run_loop_base_disable_data_source_callbacks, + &btstack_run_loop_zephyr_set_timer, + &btstack_run_loop_base_add_timer, + &btstack_run_loop_base_remove_timer, + &btstack_run_loop_zephyr_execute, + &btstack_run_loop_base_dump_timer, + &btstack_run_loop_zephyr_get_time_ms, + &btstack_run_loop_zephyr_poll_data_sources_from_irq, + &btstack_run_loop_zephyr_execute_on_main_thread, + &btstack_run_loop_zephyr_trigger_exit, +}; +/** + * @brief Provide btstack_run_loop_zephyr instance for use with btstack_run_loop_init + */ +const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void){ + return &btstack_run_loop_zephyr; +} + diff --git a/platform/zephyr/btstack_run_loop_zephyr.h b/platform/zephyr/btstack_run_loop_zephyr.h new file mode 100644 index 000000000..6a7768ba8 --- /dev/null +++ b/platform/zephyr/btstack_run_loop_zephyr.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2025 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN + * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +/* + * btstack_run_loop_zephyr.h + * Functionality special to the Zephyr run loop + */ + +#ifndef BTSTACK_RUN_LOOP_ZEPHYR_H +#define BTSTACK_RUN_LOOP_ZEPHYR_H + +#include "btstack_run_loop.h" + +#if defined __cplusplus +extern "C" { +#endif + +typedef struct { + union { + void *variable; + intptr_t value; + }; + int id; +} fat_variable_t; + +/** + * Provide btstack_run_loop_zephyr instance + */ +const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void); + +/* API_END */ + +#if defined __cplusplus +} +#endif + +#endif // BTSTACK_RUN_LOOP_ZEPHYR_H diff --git a/port/zephyr/src/hal_flash_bank_zephyr.c b/platform/zephyr/hal_flash_bank_zephyr.c similarity index 100% rename from port/zephyr/src/hal_flash_bank_zephyr.c rename to platform/zephyr/hal_flash_bank_zephyr.c diff --git a/port/zephyr/src/hal_flash_bank_zephyr.h b/platform/zephyr/hal_flash_bank_zephyr.h similarity index 100% rename from port/zephyr/src/hal_flash_bank_zephyr.h rename to platform/zephyr/hal_flash_bank_zephyr.h diff --git a/platform/zephyr/hci_transport_zephyr.c b/platform/zephyr/hci_transport_zephyr.c new file mode 100644 index 000000000..f246a3257 --- /dev/null +++ b/platform/zephyr/hci_transport_zephyr.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2025 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN + * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +// Zephyr +#include +#include +#include +#include + +// BTstack +#include "btstack_debug.h" +#include "hci.h" +#include "hci_transport.h" + +#include "btstack_run_loop_zephyr.h" + +static K_FIFO_DEFINE(rx_queue); + +static void (*transport_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); + +static btstack_data_source_t hci_transport_zephyr_receive; +static fat_variable_t rx_queue_handle = { .variable = &rx_queue, .id = K_POLL_TYPE_FIFO_DATA_AVAILABLE }; + +static void hci_transport_zephyr_handler(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type) { + UNUSED(ds); + UNUSED(callback_type); + struct net_buf *buf = k_fifo_get( &rx_queue, K_FOREVER ); + + uint16_t size = buf->len; + uint8_t * packet = buf->data; + switch (bt_buf_get_type(buf)) { + case BT_BUF_ISO_IN: + transport_packet_handler(HCI_ISO_DATA_PACKET, packet, size); + break; + case BT_BUF_ACL_IN: + transport_packet_handler(HCI_ACL_DATA_PACKET, packet, size); + break; + case BT_BUF_EVT: + transport_packet_handler(HCI_EVENT_PACKET, packet, size); + break; + default: + log_error("Unknown type %u\n", bt_buf_get_type(buf)); + break; + } + net_buf_unref(buf); +} + + +/** + * init transport + * @param transport_config + */ +static void transport_init(const void *transport_config){ + + btstack_data_source_t *ds = &hci_transport_zephyr_receive; + btstack_run_loop_set_data_source_handle(ds, &rx_queue_handle); + btstack_run_loop_set_data_source_handler(ds, &hci_transport_zephyr_handler); + btstack_run_loop_add_data_source(ds); + btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); + + /* startup Controller */ + bt_enable_raw(&rx_queue); + bt_hci_raw_set_mode( BT_HCI_RAW_MODE_PASSTHROUGH ); +} + +/** + * open transport connection + */ +static int transport_open(void){ + return 0; +} + +/** + * close transport connection + */ +static int transport_close(void){ + return 0; +} + +/** + * register packet handler for HCI packets: ACL, SCO, and Events + */ +static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ + transport_packet_handler = handler; +} + +static void send_hardware_error(uint8_t error_code){ + // hci_outgoing_event[0] = HCI_EVENT_HARDWARE_ERROR; + // hci_outgoing_event[1] = 1; + // hci_outgoing_event[2] = error_code; + // hci_outgoing_event_ready = 1; +} + +static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){ + struct net_buf *buf; + switch (packet_type){ + case HCI_COMMAND_DATA_PACKET: + buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, packet, size); + if (!buf) { + log_error("No available command buffers!\n"); + break; + } + + bt_send(buf); + break; + case HCI_ACL_DATA_PACKET: + buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, packet, size); + if (!buf) { + log_error("No available ACL buffers!\n"); + break; + } + + bt_send(buf); + break; + case HCI_ISO_DATA_PACKET: + buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_NO_WAIT, packet, size); + if (!buf) { + log_error("No available ISO buffers!\n"); + break; + } + + bt_send(buf); + break; + default: + send_hardware_error(0x01); // invalid HCI packet + break; + } + + return 0; +} + +static const hci_transport_t transport = { + /* const char * name; */ "zephyr", + /* void (*init) (const void *transport_config); */ &transport_init, + /* int (*open)(void); */ &transport_open, + /* int (*close)(void); */ &transport_close, + /* void (*register_packet_handler)(void (*handler)(...); */ &transport_register_packet_handler, + /* int (*can_send_packet_now)(uint8_t packet_type); */ NULL, + /* int (*send_packet)(...); */ &transport_send_packet, + /* int (*set_baudrate)(uint32_t baudrate); */ NULL, + /* void (*reset_link)(void); */ NULL, +}; + +const hci_transport_t * hci_transport_zephyr_get_instance(void){ + return &transport; +} + + diff --git a/platform/zephyr/hci_transport_zephyr.h b/platform/zephyr/hci_transport_zephyr.h new file mode 100644 index 000000000..1fcb7f14b --- /dev/null +++ b/platform/zephyr/hci_transport_zephyr.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN + * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +/* + * hci_transport_zephyr + * + */ + +#ifndef HCI_TRANSPORT_ZEPHYR_H +#define HCI_TRANSPORT_ZEPHYR_H + +#include "hci_transport.h" + +#if defined __cplusplus +extern "C" { +#endif + +const hci_transport_t * hci_transport_zephyr_get_instance(void); + +#if defined __cplusplus +} +#endif +#endif // HCI_TRANSPORT_ZEPHYR_H diff --git a/port/zephyr/CMakeLists.txt b/port/zephyr/CMakeLists.txt index caa37e8ee..6730350a5 100644 --- a/port/zephyr/CMakeLists.txt +++ b/port/zephyr/CMakeLists.txt @@ -38,6 +38,7 @@ list(APPEND INCLUDES_PATH 3rd-party/tinydir) list(APPEND INCLUDES_PATH src) list(APPEND INCLUDES_PATH chipset/zephyr) list(APPEND INCLUDES_PATH platform/embedded) +list(APPEND INCLUDES_PATH platform/zephyr) list(APPEND INCLUDES_PATH platform/lwip) list(APPEND INCLUDES_PATH platform/lwip/port) list(TRANSFORM INCLUDES_PATH PREPEND ${BTSTACK_ROOT}/) @@ -57,7 +58,7 @@ file(GLOB SOURCES_UECC "${BTSTACK_ROOT}/3rd-party/micro-ecc/uECC.c") file(GLOB SOURCES_YXML "${BTSTACK_ROOT}/3rd-party/yxml/yxml.c") file(GLOB SOURCES_HXCMOD "${BTSTACK_ROOT}/3rd-party/hxcmod-player/*.c" "${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods/*.c") file(GLOB SOURCES_RIJNDAEL "${BTSTACK_ROOT}/3rd-party/rijndael/rijndael.c") -file(GLOB SOURCES_EMBEDDED "${BTSTACK_ROOT}/platform/embedded/*.c") +file(GLOB SOURCES_ZEPHYR "${BTSTACK_ROOT}/platform/zephyr/*.c") file(GLOB SOURCES_CHIPSET_ZEPHYR "${BTSTACK_ROOT}/chipset/zephyr/*.c") file(GLOB SOURCES_LC3_GOOGLE "${BTSTACK_ROOT}/3rd-party/lc3-google/src/*.c") @@ -124,12 +125,13 @@ set(SOURCES ${SOURCES_UECC} ${SOURCES_HXCMOD} ${SOURCES_CHIPSET_ZEPHYR} + ${SOURCES_ZEPHYR} ) list(SORT SOURCES) # create static lib add_library(btstack STATIC ${SOURCES}) - +add_dependencies(btstack zephyr_interface) # extra compiler warnings target_compile_options(btstack PRIVATE $<$,$>: @@ -180,6 +182,7 @@ foreach(EXAMPLE ${EXAMPLES}) set (SOURCES_EXAMPLE ${EXAMPLE}.c) endif() list(APPEND SOURCES_EXAMPLE "${CMAKE_SOURCE_DIR}/src/main.c") + message("${BTSTACK_ROOT}") message("${SOURCES_EXAMPLE}") # add lwip sources for lwip examples diff --git a/port/zephyr/src/main.c b/port/zephyr/src/main.c index 220a528a1..384b0394b 100644 --- a/port/zephyr/src/main.c +++ b/port/zephyr/src/main.c @@ -10,13 +10,6 @@ #include #include -#include -#include -#include -#include -#include -#include - // Nordic NDK #if defined(CONFIG_HAS_NORDIC_DRIVERS) #include "nrf.h" @@ -37,6 +30,7 @@ #endif #endif #include "hci_transport.h" + #include "bluetooth_company_id.h" #include "btstack_chipset_zephyr.h" @@ -44,187 +38,8 @@ #include "btstack_tlv_none.h" #include "ble/le_device_db_tlv.h" -static K_FIFO_DEFINE(tx_queue); -static K_FIFO_DEFINE(rx_queue); - -// -// hci_transport_zephyr.c -// - -static void (*transport_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); - -/** - * init transport - * @param transport_config - */ -static void transport_init(const void *transport_config){ - /* startup Controller */ - bt_enable_raw(&rx_queue); - bt_hci_raw_set_mode( BT_HCI_RAW_MODE_PASSTHROUGH ); -} - -/** - * open transport connection - */ -static int transport_open(void){ - return 0; -} - -/** - * close transport connection - */ -static int transport_close(void){ - return 0; -} - -/** - * register packet handler for HCI packets: ACL, SCO, and Events - */ -static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ - transport_packet_handler = handler; -} - -static void send_hardware_error(uint8_t error_code){ - // hci_outgoing_event[0] = HCI_EVENT_HARDWARE_ERROR; - // hci_outgoing_event[1] = 1; - // hci_outgoing_event[2] = error_code; - // hci_outgoing_event_ready = 1; -} - -static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){ - struct net_buf *buf; - switch (packet_type){ - case HCI_COMMAND_DATA_PACKET: - buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, packet, size); - if (!buf) { - log_error("No available command buffers!\n"); - break; - } - - bt_send(buf); - break; - case HCI_ACL_DATA_PACKET: - buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, packet, size); - if (!buf) { - log_error("No available ACL buffers!\n"); - break; - } - - bt_send(buf); - break; - case HCI_ISO_DATA_PACKET: - buf = bt_buf_get_tx(BT_BUF_ISO_OUT, K_NO_WAIT, packet, size); - if (!buf) { - log_error("No available ISO buffers!\n"); - break; - } - - bt_send(buf); - break; - default: - send_hardware_error(0x01); // invalid HCI packet - break; - } - - return 0; -} - -static const hci_transport_t transport = { - /* const char * name; */ "zephyr", - /* void (*init) (const void *transport_config); */ &transport_init, - /* int (*open)(void); */ &transport_open, - /* int (*close)(void); */ &transport_close, - /* void (*register_packet_handler)(void (*handler)(...); */ &transport_register_packet_handler, - /* int (*can_send_packet_now)(uint8_t packet_type); */ NULL, - /* int (*send_packet)(...); */ &transport_send_packet, - /* int (*set_baudrate)(uint32_t baudrate); */ NULL, - /* void (*reset_link)(void); */ NULL, -}; - -static const hci_transport_t * transport_get_instance(void){ - return &transport; -} - -static void transport_deliver_controller_packet(struct net_buf * buf){ - uint16_t size = buf->len; - uint8_t * packet = buf->data; - switch (bt_buf_get_type(buf)) { - case BT_BUF_ISO_IN: - transport_packet_handler(HCI_ISO_DATA_PACKET, packet, size); - break; - case BT_BUF_ACL_IN: - transport_packet_handler(HCI_ACL_DATA_PACKET, packet, size); - break; - case BT_BUF_EVT: - transport_packet_handler(HCI_EVENT_PACKET, packet, size); - break; - default: - log_error("Unknown type %u\n", bt_buf_get_type(buf)); - break; - } - net_buf_unref(buf); -} - -// btstack_run_loop_zephry.c - -// the run loop - -// TODO: handle 32 bit ms time overrun -static uint32_t btstack_run_loop_zephyr_get_time_ms(void){ - return k_uptime_get_32(); -} - -static void btstack_run_loop_zephyr_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){ - ts->timeout = k_uptime_get_32() + 1 + timeout_in_ms; -} - -/** - * Execute run_loop - */ -static void btstack_run_loop_zephyr_execute(void) { - while (1) { - // process timers - uint32_t now = k_uptime_get_32(); - btstack_run_loop_base_process_timers(now); - - // get time until next timer expires - k_timeout_t timeout; - timeout.ticks = btstack_run_loop_base_get_time_until_timeout(now); - if (timeout.ticks < 0){ - timeout = K_FOREVER; - } - - // process RX fifo only - struct net_buf *buf = k_fifo_get(&rx_queue, timeout); - if (buf){ - transport_deliver_controller_packet(buf); - } - } -} - -static void btstack_run_loop_zephyr_btstack_run_loop_init(void){ - btstack_run_loop_base_init(); -} - -static const btstack_run_loop_t btstack_run_loop_zephyr = { - &btstack_run_loop_zephyr_btstack_run_loop_init, - NULL, - NULL, - NULL, - NULL, - &btstack_run_loop_zephyr_set_timer, - &btstack_run_loop_base_add_timer, - &btstack_run_loop_base_remove_timer, - &btstack_run_loop_zephyr_execute, - &btstack_run_loop_base_dump_timer, - &btstack_run_loop_zephyr_get_time_ms, -}; -/** - * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init - */ -static const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void){ - return &btstack_run_loop_zephyr; -} +#include "hci_transport_zephyr.h" +#include "btstack_run_loop_zephyr.h" static btstack_packet_callback_registration_t hci_event_callback_registration; @@ -363,7 +178,7 @@ int main(void) le_device_db_tlv_configure(btstack_tlv_impl, NULL); // init HCI - hci_init(transport_get_instance(), NULL); + hci_init(hci_transport_zephyr_get_instance(), NULL); // inform about BTstack state hci_event_callback_registration.callback = &packet_handler;