From 424dcbf50f360d316dabccf523ecb7578e1bcaf4 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Dec 2025 14:36:17 +0100 Subject: [PATCH 1/4] pbio/drv/bluetooth_btstack: Add init hook. This is needed for the POSIX port, so we don't have to make special handlers to protect init from running twice. --- lib/pbio/drv/bluetooth/bluetooth_btstack.c | 6 ++++++ lib/pbio/drv/bluetooth/bluetooth_btstack.h | 11 +++++++++++ lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c | 4 ++++ lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c | 6 ++++++ lib/pbio/test/drv/test_bluetooth_btstack.c | 3 +++ 5 files changed, 30 insertions(+) diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.c b/lib/pbio/drv/bluetooth/bluetooth_btstack.c index 88f1102b5..60f7727c1 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.c @@ -1055,6 +1055,12 @@ const uint8_t cc256x_init_script[] = {}; void pbdrv_bluetooth_init_hci(void) { + // Proceed to start Bluetooth process only if platform init passes. + pbio_error_t err = pbdrv_bluetooth_btstack_platform_init(); + if (err != PBIO_SUCCESS) { + return; + } + static btstack_packet_callback_registration_t hci_event_callback_registration; #if PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.h b/lib/pbio/drv/bluetooth/bluetooth_btstack.h index 26e0304bd..65e47b04c 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.h +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.h @@ -11,6 +11,17 @@ #include #include +#include + +/** + * Optional platform initialization before BTstack takes over. + * + * Unlike some BTstack init code, this is guaranteed to be called only once. + * + * @return Any error code to skip Bluetooth or ::PBIO_SUCCESS to proceed. + */ +pbio_error_t pbdrv_bluetooth_btstack_platform_init(void); + /** Chipset info */ typedef struct { /** Version */ diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c index 5ec20340e..e5d40cead 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c @@ -66,6 +66,10 @@ static const hci_dump_t bluetooth_btstack_classic_hci_dump = { #define DEBUG_PRINT(...) #endif +pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { + return PBIO_SUCCESS; +} + void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { const pbdrv_bluetooth_btstack_chipset_info_t *info = lmp_pal_subversion == cc2560_info.lmp_version ? &cc2560_info : &cc2560a_info; diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c index f065cf02f..72b2e343f 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c @@ -24,6 +24,12 @@ #include +#include + +pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { + return PBIO_SUCCESS; +} + void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { const pbdrv_bluetooth_btstack_platform_data_t *pdata = diff --git a/lib/pbio/test/drv/test_bluetooth_btstack.c b/lib/pbio/test/drv/test_bluetooth_btstack.c index 9d4559851..3a80bce04 100644 --- a/lib/pbio/test/drv/test_bluetooth_btstack.c +++ b/lib/pbio/test/drv/test_bluetooth_btstack.c @@ -773,6 +773,9 @@ static void handle_data_source(btstack_data_source_t *ds, btstack_data_source_c void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { } +pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { + return PBIO_SUCCESS; +} static pbio_error_t test_btstack_run_loop_contiki_poll(pbio_os_state_t *state, void *context) { static btstack_data_source_t data_source; From fb0a244bca61811836539d3c3e7801d816aec4b5 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Dec 2025 14:44:29 +0100 Subject: [PATCH 2/4] pbio/drv/bluetooth_btstack: Use standard mechanism for IRQ poll. Most BTstack ports do it this way, including embedded variants. This will let us use the POSIX libusb variant without modifying it. --- lib/pbio/drv/bluetooth/bluetooth_btstack.c | 15 ++++++++------- lib/pbio/drv/bluetooth/bluetooth_btstack.h | 2 -- lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c | 8 ++++---- .../drv/bluetooth/bluetooth_btstack_stm32_hal.c | 4 ++-- lib/pbio/test/drv/test_bluetooth_btstack.c | 6 +++--- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.c b/lib/pbio/drv/bluetooth/bluetooth_btstack.c index 60f7727c1..32b62a333 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.c @@ -1000,6 +1000,13 @@ static void bluetooth_btstack_run_loop_execute(void) { // not used } +static bool do_poll_handler; + +static void pbdrv_bluetooth_btstack_run_loop_trigger(void) { + do_poll_handler = true; + pbio_os_request_poll(); +} + static const btstack_run_loop_t bluetooth_btstack_run_loop = { .init = btstack_run_loop_base_init, .add_data_source = btstack_run_loop_base_add_data_source, @@ -1012,15 +1019,9 @@ static const btstack_run_loop_t bluetooth_btstack_run_loop = { .execute = bluetooth_btstack_run_loop_execute, .dump_timer = btstack_run_loop_base_dump_timer, .get_time_ms = pbdrv_clock_get_ms, + .poll_data_sources_from_irq = pbdrv_bluetooth_btstack_run_loop_trigger, }; -static bool do_poll_handler; - -void pbdrv_bluetooth_btstack_run_loop_trigger(void) { - do_poll_handler = true; - pbio_os_request_poll(); -} - static pbio_os_process_t pbdrv_bluetooth_hci_process; /** diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.h b/lib/pbio/drv/bluetooth/bluetooth_btstack.h index 65e47b04c..176457584 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.h +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.h @@ -32,8 +32,6 @@ typedef struct { const uint32_t init_script_size; } pbdrv_bluetooth_btstack_chipset_info_t; -void pbdrv_bluetooth_btstack_run_loop_trigger(void); - /** * Hook called when BTstack reads the local version information. * diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c index e5d40cead..4f80cb63f 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c @@ -222,7 +222,7 @@ static volatile bool rx_interrupts_enabled; void pbdrv_bluetooth_btstack_ev3_handle_tx_complete(void) { EDMA3DisableTransfer(EDMA_BASE, DMA_CHA_TX, EDMA3_TRIG_MODE_EVENT); dma_write_complete = true; - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); } static inline void uart_rx_interrupt_set_enabled(bool enabled) { @@ -254,11 +254,11 @@ static void uart_rx_interrupt_handler(void) { // RX buffer full, disable further RX interrupts until btstack consumes // some of the data. uart_rx_interrupt_set_enabled(false); - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); return; } if (read_buf && (size_t)read_buf_len <= lwrb_get_full(&uart_rx_pending_ring_buffer)) { - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); } } @@ -431,7 +431,7 @@ static void pbdrv_bluetooth_btstack_ev3_receive_block(uint8_t *buffer, read_buf = buffer; read_buf_len = len; - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); } static void pbdrv_bluetooth_btstack_ev3_send_block(const uint8_t *data, diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c index 72b2e343f..86fdd5ab7 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c @@ -98,12 +98,12 @@ static void (*block_received)(void); void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { send_complete = true; - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { receive_complete = true; - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); } static int btstack_stm32_hal_init(const btstack_uart_config_t *config) { diff --git a/lib/pbio/test/drv/test_bluetooth_btstack.c b/lib/pbio/test/drv/test_bluetooth_btstack.c index 3a80bce04..f967a5677 100644 --- a/lib/pbio/test/drv/test_bluetooth_btstack.c +++ b/lib/pbio/test/drv/test_bluetooth_btstack.c @@ -789,20 +789,20 @@ static pbio_error_t test_btstack_run_loop_contiki_poll(pbio_os_state_t *state, v btstack_run_loop_enable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_add_data_source(&data_source); - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); PBIO_OS_AWAIT_ONCE(state); tt_want_uint_op(callback_count, ==, 1); callback_count = 0; btstack_run_loop_disable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); PBIO_OS_AWAIT_ONCE(state); tt_want_uint_op(callback_count, ==, 0); callback_count = 0; btstack_run_loop_enable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_remove_data_source(&data_source); - pbdrv_bluetooth_btstack_run_loop_trigger(); + btstack_run_loop_poll_data_sources_from_irq(); PBIO_OS_AWAIT_ONCE(state); tt_want_uint_op(callback_count, ==, 0); From b3c6702230b9c042b34b1264531e1b82ed11d311 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Dec 2025 14:57:37 +0100 Subject: [PATCH 3/4] pbio/drv/bluetooth_btstack: Add poll hook. This is needed for the POSIX port, which needs to poll files. --- lib/pbio/drv/bluetooth/bluetooth_btstack.c | 2 ++ lib/pbio/drv/bluetooth/bluetooth_btstack.h | 5 +++++ lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c | 3 +++ lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c | 3 +++ lib/pbio/test/drv/test_bluetooth_btstack.c | 3 +++ 5 files changed, 16 insertions(+) diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.c b/lib/pbio/drv/bluetooth/bluetooth_btstack.c index 32b62a333..2059241c4 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.c @@ -1035,6 +1035,8 @@ static pbio_error_t pbdrv_bluetooth_hci_process_thread(pbio_os_state_t *state, v btstack_run_loop_base_poll_data_sources(); } + pbdrv_bluetooth_btstack_platform_poll(); + static pbio_os_timer_t btstack_timer = { .duration = 1, }; diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.h b/lib/pbio/drv/bluetooth/bluetooth_btstack.h index 176457584..e78b9109e 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.h +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.h @@ -22,6 +22,11 @@ */ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void); +/** + * Optional platform poll handler, called on every process iteration. + */ +void pbdrv_bluetooth_btstack_platform_poll(void); + /** Chipset info */ typedef struct { /** Version */ diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c index 4f80cb63f..37eb9b42f 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c @@ -70,6 +70,9 @@ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { return PBIO_SUCCESS; } +void pbdrv_bluetooth_btstack_platform_poll(void) { +} + void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { const pbdrv_bluetooth_btstack_chipset_info_t *info = lmp_pal_subversion == cc2560_info.lmp_version ? &cc2560_info : &cc2560a_info; diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c index 86fdd5ab7..311dc5172 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c @@ -30,6 +30,9 @@ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { return PBIO_SUCCESS; } +void pbdrv_bluetooth_btstack_platform_poll(void) { +} + void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { const pbdrv_bluetooth_btstack_platform_data_t *pdata = diff --git a/lib/pbio/test/drv/test_bluetooth_btstack.c b/lib/pbio/test/drv/test_bluetooth_btstack.c index f967a5677..701078ecf 100644 --- a/lib/pbio/test/drv/test_bluetooth_btstack.c +++ b/lib/pbio/test/drv/test_bluetooth_btstack.c @@ -777,6 +777,9 @@ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { return PBIO_SUCCESS; } +void pbdrv_bluetooth_btstack_platform_poll(void) { +} + static pbio_error_t test_btstack_run_loop_contiki_poll(pbio_os_state_t *state, void *context) { static btstack_data_source_t data_source; static uint32_t callback_count; From 4402e8a58a23e48318ed0f9b142a05f91913f174 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Tue, 23 Dec 2025 15:44:40 +0100 Subject: [PATCH 4/4] pbio/drv/bluetooth_btstack: Read full HCI version info payload. Co-authored-by: James Aguilar --- lib/pbio/drv/bluetooth/bluetooth_btstack.c | 19 +++++++++++------- lib/pbio/drv/bluetooth/bluetooth_btstack.h | 20 ++++++++++++++++++- .../drv/bluetooth/bluetooth_btstack_ev3.c | 4 ++-- .../bluetooth/bluetooth_btstack_stm32_hal.c | 2 +- lib/pbio/test/drv/test_bluetooth_btstack.c | 2 +- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.c b/lib/pbio/drv/bluetooth/bluetooth_btstack.c index 2059241c4..c2f704a3a 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.c @@ -228,18 +228,23 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe const uint8_t *rp = hci_event_command_complete_get_return_parameters(packet); switch (hci_event_command_complete_get_command_opcode(packet)) { case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: { - uint16_t lmp_pal_subversion = pbio_get_uint16_le(&rp[7]); - pbdrv_bluetooth_btstack_set_chipset(lmp_pal_subversion); + pbdrv_bluetooth_btstack_device_discriminator_t info; + info.hci_version = rp[1]; + info.hci_revision = pbio_get_uint16_le(&rp[2]); + info.lmp_pal_version = rp[4]; + info.manufacturer = pbio_get_uint16_le(&rp[5]); + info.lmp_pal_subversion = pbio_get_uint16_le(&rp[7]); + pbdrv_bluetooth_btstack_set_chipset(&info); #if DEBUG // Show version in ev3dev format. - uint16_t chip = (lmp_pal_subversion & 0x7C00) >> 10; - uint16_t min_ver = (lmp_pal_subversion & 0x007F); - uint16_t maj_ver = (lmp_pal_subversion & 0x0380) >> 7; - if (lmp_pal_subversion & 0x8000) { + uint16_t chip = (info.lmp_pal_subversion & 0x7C00) >> 10; + uint16_t min_ver = (info.lmp_pal_subversion & 0x007F); + uint16_t maj_ver = (info.lmp_pal_subversion & 0x0380) >> 7; + if (info.lmp_pal_subversion & 0x8000) { maj_ver |= 0x0008; } - DEBUG_PRINT("LMP %04x: TIInit_%d.%d.%d.bts\n", lmp_pal_subversion, chip, maj_ver, min_ver); + DEBUG_PRINT("LMP %04x: TIInit_%d.%d.%d.bts\n", info.lmp_pal_subversion, chip, maj_ver, min_ver); #endif break; } diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.h b/lib/pbio/drv/bluetooth/bluetooth_btstack.h index e78b9109e..ec2f01a01 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.h +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.h @@ -37,13 +37,31 @@ typedef struct { const uint32_t init_script_size; } pbdrv_bluetooth_btstack_chipset_info_t; +/** + * Device discriminator info from the HCI read local version information command. + */ +typedef struct { + /** HCI version. */ + uint8_t hci_version; + /** HCI revision. */ + uint16_t hci_revision; + /** LMP/PAL version. */ + uint8_t lmp_pal_version; + /** Manufacturer. */ + uint16_t manufacturer; + /** LMP/PAL subversion. */ + uint16_t lmp_pal_subversion; +} pbdrv_bluetooth_btstack_device_discriminator_t; + /** * Hook called when BTstack reads the local version information. * * This is called _after_ hci_set_chipset but _before_ the init script is sent * over the wire, so this can be used to dynamically select the init script. + * + * @param device_info The device information read from the Bluetooth chip. */ -void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion); +void pbdrv_bluetooth_btstack_set_chipset(pbdrv_bluetooth_btstack_device_discriminator_t *device_info); typedef struct { const hci_transport_t *(*transport_instance)(void); diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c index 37eb9b42f..13b592f8f 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c @@ -73,8 +73,8 @@ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { void pbdrv_bluetooth_btstack_platform_poll(void) { } -void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { - const pbdrv_bluetooth_btstack_chipset_info_t *info = lmp_pal_subversion == cc2560_info.lmp_version ? +void pbdrv_bluetooth_btstack_set_chipset(pbdrv_bluetooth_btstack_device_discriminator_t *device_info) { + const pbdrv_bluetooth_btstack_chipset_info_t *info = device_info->lmp_pal_subversion == cc2560_info.lmp_version ? &cc2560_info : &cc2560a_info; btstack_chipset_cc256x_set_init_script((uint8_t *)info->init_script, info->init_script_size); diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c index 311dc5172..dbe4c7d9e 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c @@ -33,7 +33,7 @@ pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) { void pbdrv_bluetooth_btstack_platform_poll(void) { } -void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { +void pbdrv_bluetooth_btstack_set_chipset(pbdrv_bluetooth_btstack_device_discriminator_t *device_info) { const pbdrv_bluetooth_btstack_platform_data_t *pdata = &pbdrv_bluetooth_btstack_platform_data; diff --git a/lib/pbio/test/drv/test_bluetooth_btstack.c b/lib/pbio/test/drv/test_bluetooth_btstack.c index 701078ecf..6ce89fbed 100644 --- a/lib/pbio/test/drv/test_bluetooth_btstack.c +++ b/lib/pbio/test/drv/test_bluetooth_btstack.c @@ -770,7 +770,7 @@ static void handle_data_source(btstack_data_source_t *ds, btstack_data_source_c } } -void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { +void pbdrv_bluetooth_btstack_set_chipset(pbdrv_bluetooth_btstack_device_discriminator_t *device_info) { } pbio_error_t pbdrv_bluetooth_btstack_platform_init(void) {