blob: 9847be90de4df505ebca07ff908bf1fc3e6a6ae2 [file] [log] [blame]
/*
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/btstack_run_loop_async_context.h"
#include "hardware/sync.h"
static async_context_t *btstack_async_context;
static async_at_time_worker_t btstack_timeout_worker;
static async_when_pending_worker_t btstack_processing_worker;
static void btstack_timeout_reached(async_context_t *context, async_at_time_worker_t *worker);
static void btstack_work_pending(async_context_t *context, async_when_pending_worker_t *worker);
static volatile bool run_loop_exit;
static void btstack_run_loop_async_context_init(void) {
btstack_run_loop_base_init();
btstack_timeout_worker.do_work = btstack_timeout_reached;
btstack_processing_worker.do_work = btstack_work_pending;
async_context_add_when_pending_worker(btstack_async_context, &btstack_processing_worker);
}
static void btstack_run_loop_async_context_add_data_source(btstack_data_source_t * data_source) {
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_add_data_source(data_source);
async_context_release_lock(btstack_async_context);
}
static bool btstack_run_loop_async_context_remove_data_source(btstack_data_source_t * data_source) {
async_context_acquire_lock_blocking(btstack_async_context);
bool rc = btstack_run_loop_base_remove_data_source(data_source);
async_context_release_lock(btstack_async_context);
return rc;
}
static void btstack_run_loop_async_context_enable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks) {
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_enable_data_source_callbacks(data_source, callbacks);
async_context_release_lock(btstack_async_context);
}
static void btstack_run_loop_async_context_disable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks) {
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_disable_data_source_callbacks(data_source, callbacks);
async_context_release_lock(btstack_async_context);
}
static void btstack_run_loop_async_context_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){
async_context_acquire_lock_blocking(btstack_async_context);
ts->timeout = to_ms_since_boot(get_absolute_time()) + timeout_in_ms + 1;
async_context_set_work_pending(btstack_async_context, &btstack_processing_worker);
async_context_release_lock(btstack_async_context);
}
static void btstack_run_loop_async_context_add_timer(btstack_timer_source_t *timer) {
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_add_timer(timer);
async_context_set_work_pending(btstack_async_context, &btstack_processing_worker);
async_context_release_lock(btstack_async_context);
}
static bool btstack_run_loop_async_context_remove_timer(btstack_timer_source_t *timer) {
async_context_acquire_lock_blocking(btstack_async_context);
bool rc = btstack_run_loop_base_remove_timer(timer);
async_context_release_lock(btstack_async_context);
return rc;
}
static void btstack_run_loop_async_context_dump_timer(void){
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_dump_timer();
async_context_release_lock(btstack_async_context);
}
static uint32_t btstack_run_loop_async_context_get_time_ms(void)
{
return to_ms_since_boot(get_absolute_time());
}
static void btstack_run_loop_async_context_execute(void)
{
run_loop_exit = false;
while (!run_loop_exit) {
async_context_poll(btstack_async_context);
async_context_wait_for_work_until(btstack_async_context, at_the_end_of_time);
}
}
static void btstack_run_loop_async_context_trigger_exit(void)
{
run_loop_exit = true;
}
static void btstack_run_loop_async_context_execute_on_main_thread(btstack_context_callback_registration_t *callback_registration)
{
async_context_acquire_lock_blocking(btstack_async_context);
btstack_run_loop_base_add_callback(callback_registration);
async_context_set_work_pending(btstack_async_context, &btstack_processing_worker);
async_context_release_lock(btstack_async_context);
}
static void btstack_run_loop_async_context_poll_data_sources_from_irq(void)
{
async_context_set_work_pending(btstack_async_context, &btstack_processing_worker);
}
static const btstack_run_loop_t btstack_run_loop_async_context = {
&btstack_run_loop_async_context_init,
&btstack_run_loop_async_context_add_data_source,
&btstack_run_loop_async_context_remove_data_source,
&btstack_run_loop_async_context_enable_data_source_callbacks,
&btstack_run_loop_async_context_disable_data_source_callbacks,
&btstack_run_loop_async_context_set_timer,
&btstack_run_loop_async_context_add_timer,
&btstack_run_loop_async_context_remove_timer,
&btstack_run_loop_async_context_execute,
&btstack_run_loop_async_context_dump_timer,
&btstack_run_loop_async_context_get_time_ms,
&btstack_run_loop_async_context_poll_data_sources_from_irq,
&btstack_run_loop_async_context_execute_on_main_thread,
&btstack_run_loop_async_context_trigger_exit,
};
const btstack_run_loop_t *btstack_run_loop_async_context_get_instance(async_context_t *async_context)
{
assert(!btstack_async_context || btstack_async_context == async_context);
btstack_async_context = async_context;
return &btstack_run_loop_async_context;
}
static void btstack_timeout_reached(__unused async_context_t *context, __unused async_at_time_worker_t *worker) {
// simply wakeup worker
async_context_set_work_pending(btstack_async_context, &btstack_processing_worker);
}
static void btstack_work_pending(__unused async_context_t *context, __unused async_when_pending_worker_t *worker) {
// poll data sources
btstack_run_loop_base_poll_data_sources();
// execute callbacks
btstack_run_loop_base_execute_callbacks();
uint32_t now = to_ms_since_boot(get_absolute_time());
// process timers
btstack_run_loop_base_process_timers(now);
now = to_ms_since_boot(get_absolute_time());
int ms = btstack_run_loop_base_get_time_until_timeout(now);
if (ms == -1) {
async_context_remove_at_time_worker(btstack_async_context, &btstack_timeout_worker);
} else {
async_context_add_at_time_worker_in_ms(btstack_async_context, &btstack_timeout_worker, ms);
}
}