@@ -858,14 +858,37 @@ void pbdrv_bluetooth_controller_reset_hard(void) {
858858 hci_power_control (HCI_POWER_OFF );
859859}
860860
861- pbio_error_t pbdrv_bluetooth_controller_reset (pbio_os_state_t * state , pbio_os_timer_t * timer ) {
861+ /**
862+ * btstack's hci_power_control() synchronously emits an event that would cause
863+ * it to re-enter the event loop. This would not be safe to call from within
864+ * the event loop. This wrapper ensures it is called at most once.
865+ */
866+ static pbio_error_t bluetooth_btstack_handle_power_control (pbio_os_state_t * state , HCI_POWER_MODE power_mode , HCI_STATE end_state ) {
867+
868+ bool do_it_this_time = false;
862869
863- // The event handler also pushes the bluetooth process along, but shouldn't
864- // be needing to touch the power state.
865- if (event_packet ) {
866- return PBIO_ERROR_AGAIN ;
870+ PBIO_OS_ASYNC_BEGIN (state );
871+
872+ do_it_this_time = true;
873+ PBIO_OS_ASYNC_SET_CHECKPOINT (state );
874+
875+ // The first time we get here, do_it_this_time = true, so we call
876+ // hci_power_control. When it re-enters at the checkpoint above, it will
877+ // be false, so move on.
878+ if (do_it_this_time ) {
879+ hci_power_control (power_mode );
867880 }
868881
882+ // Wait for the power state to take effect.
883+ PBIO_OS_AWAIT_UNTIL (state , hci_get_state () == end_state );
884+
885+ PBIO_OS_ASYNC_END (PBIO_SUCCESS );
886+ }
887+
888+ pbio_error_t pbdrv_bluetooth_controller_reset (pbio_os_state_t * state , pbio_os_timer_t * timer ) {
889+
890+ static pbio_os_state_t sub ;
891+
869892 PBIO_OS_ASYNC_BEGIN (state );
870893
871894 // Disconnect gracefully if connected to host.
@@ -874,24 +897,20 @@ pbio_error_t pbdrv_bluetooth_controller_reset(pbio_os_state_t *state, pbio_os_ti
874897 PBIO_OS_AWAIT_UNTIL (state , le_con_handle == HCI_CON_HANDLE_INVALID );
875898 }
876899
877- pbdrv_bluetooth_controller_reset_hard ();
878- PBIO_OS_AWAIT_UNTIL (state , hci_get_state () == HCI_STATE_OFF );
900+ // Wait for power off.
901+ PBIO_OS_AWAIT (state , & sub , bluetooth_btstack_handle_power_control ( & sub , HCI_POWER_OFF , HCI_STATE_OFF ) );
879902
880903 PBIO_OS_ASYNC_END (PBIO_SUCCESS );
881904}
882905
883906pbio_error_t pbdrv_bluetooth_controller_initialize (pbio_os_state_t * state , pbio_os_timer_t * timer ) {
884907
885- // The event handler also pushes the bluetooth process along, but shouldn't
886- // be needing to touch the power state.
887- if (event_packet ) {
888- return PBIO_ERROR_AGAIN ;
889- }
908+ static pbio_os_state_t sub ;
890909
891910 PBIO_OS_ASYNC_BEGIN (state );
892911
893- hci_power_control ( HCI_POWER_ON );
894- PBIO_OS_AWAIT_UNTIL (state , hci_get_state () == HCI_STATE_WORKING );
912+ // Wait for power on.
913+ PBIO_OS_AWAIT (state , & sub , bluetooth_btstack_handle_power_control ( & sub , HCI_POWER_ON , HCI_STATE_WORKING ) );
895914
896915 PBIO_OS_ASYNC_END (PBIO_SUCCESS );
897916}
0 commit comments