diff --git a/lib/pbio/drv/bluetooth/bluetooth_btstack.c b/lib/pbio/drv/bluetooth/bluetooth_btstack.c index 88f1102b5..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; } @@ -1000,6 +1005,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 +1024,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; /** @@ -1034,6 +1040,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, }; @@ -1055,6 +1063,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..ec2f01a01 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack.h +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack.h @@ -11,6 +11,22 @@ #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); + +/** + * Optional platform poll handler, called on every process iteration. + */ +void pbdrv_bluetooth_btstack_platform_poll(void); + /** Chipset info */ typedef struct { /** Version */ @@ -21,15 +37,31 @@ typedef struct { const uint32_t init_script_size; } pbdrv_bluetooth_btstack_chipset_info_t; -void pbdrv_bluetooth_btstack_run_loop_trigger(void); +/** + * 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 5ec20340e..13b592f8f 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c @@ -66,8 +66,15 @@ static const hci_dump_t bluetooth_btstack_classic_hci_dump = { #define DEBUG_PRINT(...) #endif -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 ? +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(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); @@ -218,7 +225,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) { @@ -250,11 +257,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(); } } @@ -427,7 +434,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 f065cf02f..dbe4c7d9e 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c +++ b/lib/pbio/drv/bluetooth/bluetooth_btstack_stm32_hal.c @@ -24,7 +24,16 @@ #include -void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) { +#include + +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(pbdrv_bluetooth_btstack_device_discriminator_t *device_info) { const pbdrv_bluetooth_btstack_platform_data_t *pdata = &pbdrv_bluetooth_btstack_platform_data; @@ -92,12 +101,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 9d4559851..6ce89fbed 100644 --- a/lib/pbio/test/drv/test_bluetooth_btstack.c +++ b/lib/pbio/test/drv/test_bluetooth_btstack.c @@ -770,9 +770,15 @@ 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) { + 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; @@ -786,20 +792,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);