1b7d596c1SMatthias Ringwald /* 2b7d596c1SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3b7d596c1SMatthias Ringwald * 4b7d596c1SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5b7d596c1SMatthias Ringwald * modification, are permitted provided that the following conditions 6b7d596c1SMatthias Ringwald * are met: 7b7d596c1SMatthias Ringwald * 8b7d596c1SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9b7d596c1SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10b7d596c1SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11b7d596c1SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12b7d596c1SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13b7d596c1SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14b7d596c1SMatthias Ringwald * contributors may be used to endorse or promote products derived 15b7d596c1SMatthias Ringwald * from this software without specific prior written permission. 16b7d596c1SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17b7d596c1SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18b7d596c1SMatthias Ringwald * monetary gain. 19b7d596c1SMatthias Ringwald * 20b7d596c1SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21b7d596c1SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22b7d596c1SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23b7d596c1SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24b7d596c1SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25b7d596c1SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26b7d596c1SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27b7d596c1SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28b7d596c1SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29b7d596c1SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30b7d596c1SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b7d596c1SMatthias Ringwald * SUCH DAMAGE. 32b7d596c1SMatthias Ringwald * 33b7d596c1SMatthias Ringwald * Please inquire about commercial licensing options at 34b7d596c1SMatthias Ringwald * [email protected] 35b7d596c1SMatthias Ringwald * 36b7d596c1SMatthias Ringwald */ 37b7d596c1SMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_run_loop_posix.c" 39ab2c6ae4SMatthias Ringwald 40b7d596c1SMatthias Ringwald /* 414ab92137SMatthias Ringwald * btstack_run_loop.c 42b7d596c1SMatthias Ringwald * 43b7d596c1SMatthias Ringwald * Created by Matthias Ringwald on 6/6/09. 44b7d596c1SMatthias Ringwald */ 45b7d596c1SMatthias Ringwald 4692b78dd7SMatthias Ringwald // enable POSIX functions (needed for -std=c99) 4792b78dd7SMatthias Ringwald #define _POSIX_C_SOURCE 200809 4892b78dd7SMatthias Ringwald 498f2a52f4SMatthias Ringwald #include "btstack_run_loop_posix.h" 50b6fc147fSMatthias Ringwald 51b6fc147fSMatthias Ringwald #include "btstack_run_loop.h" 52b6fc147fSMatthias Ringwald #include "btstack_util.h" 53b7d596c1SMatthias Ringwald #include "btstack_linked_list.h" 54b7d596c1SMatthias Ringwald #include "btstack_debug.h" 55b7d596c1SMatthias Ringwald 56b7d596c1SMatthias Ringwald #include <stdio.h> 57b7d596c1SMatthias Ringwald #include <stdlib.h> 58b6fc147fSMatthias Ringwald #include <sys/select.h> 59f316a845SMatthias Ringwald #include <sys/time.h> 6092b78dd7SMatthias Ringwald #include <time.h> 6192b78dd7SMatthias Ringwald #include <unistd.h> 62b7d596c1SMatthias Ringwald 63528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_dump_timer(void); 64b7d596c1SMatthias Ringwald 65b7d596c1SMatthias Ringwald // the run loop 668f2a52f4SMatthias Ringwald static btstack_linked_list_t data_sources; 67b7d596c1SMatthias Ringwald static int data_sources_modified; 688f2a52f4SMatthias Ringwald static btstack_linked_list_t timers; 6992b78dd7SMatthias Ringwald 7092b78dd7SMatthias Ringwald // start time. tv_usec/tv_nsec = 0 7192b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 7292b78dd7SMatthias Ringwald // use monotonic clock if available 7392b78dd7SMatthias Ringwald static struct timespec init_ts; 7492b78dd7SMatthias Ringwald #else 7592b78dd7SMatthias Ringwald // fallback to gettimeofday 76b7d596c1SMatthias Ringwald static struct timeval init_tv; 7792b78dd7SMatthias Ringwald #endif 78b7d596c1SMatthias Ringwald 79b7d596c1SMatthias Ringwald /** 80b7d596c1SMatthias Ringwald * Add data_source to run_loop 81b7d596c1SMatthias Ringwald */ 82ec820d77SMatthias Ringwald static void btstack_run_loop_posix_add_data_source(btstack_data_source_t *ds){ 83b7d596c1SMatthias Ringwald data_sources_modified = 1; 84398a95ecSMatthias Ringwald // log_info("btstack_run_loop_posix_add_data_source %x with fd %u\n", (int) ds, ds->source.fd); 85b7d596c1SMatthias Ringwald btstack_linked_list_add(&data_sources, (btstack_linked_item_t *) ds); 86b7d596c1SMatthias Ringwald } 87b7d596c1SMatthias Ringwald 88b7d596c1SMatthias Ringwald /** 89b7d596c1SMatthias Ringwald * Remove data_source from run loop 90b7d596c1SMatthias Ringwald */ 91*d58a1b5fSMatthias Ringwald static bool btstack_run_loop_posix_remove_data_source(btstack_data_source_t *ds){ 92b7d596c1SMatthias Ringwald data_sources_modified = 1; 93bd539f2bSMatthias Ringwald log_debug("btstack_run_loop_posix_remove_data_source %p\n", ds); 94b7d596c1SMatthias Ringwald return btstack_linked_list_remove(&data_sources, (btstack_linked_item_t *) ds); 95b7d596c1SMatthias Ringwald } 96b7d596c1SMatthias Ringwald 97b7d596c1SMatthias Ringwald /** 98b7d596c1SMatthias Ringwald * Add timer to run_loop (keep list sorted) 99b7d596c1SMatthias Ringwald */ 100ec820d77SMatthias Ringwald static void btstack_run_loop_posix_add_timer(btstack_timer_source_t *ts){ 101b7d596c1SMatthias Ringwald btstack_linked_item_t *it; 102b7d596c1SMatthias Ringwald for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){ 103f316a845SMatthias Ringwald btstack_timer_source_t * next = (btstack_timer_source_t *) it->next; 104160fcf34SMatthias Ringwald btstack_assert(next != ts); 105b6fc147fSMatthias Ringwald // exit if new timeout before list timeout 106b6fc147fSMatthias Ringwald int32_t delta = btstack_time_delta(ts->timeout, next->timeout); 107b6fc147fSMatthias Ringwald if (delta < 0) break; 108b7d596c1SMatthias Ringwald } 109b7d596c1SMatthias Ringwald ts->item.next = it->next; 110b7d596c1SMatthias Ringwald it->next = (btstack_linked_item_t *) ts; 111f316a845SMatthias Ringwald log_debug("Added timer %p at %u\n", ts, ts->timeout); 112528a4a3bSMatthias Ringwald // btstack_run_loop_posix_dump_timer(); 113b7d596c1SMatthias Ringwald } 114b7d596c1SMatthias Ringwald 115b7d596c1SMatthias Ringwald /** 116b7d596c1SMatthias Ringwald * Remove timer from run loop 117b7d596c1SMatthias Ringwald */ 118*d58a1b5fSMatthias Ringwald static bool btstack_run_loop_posix_remove_timer(btstack_timer_source_t *ts){ 119b7d596c1SMatthias Ringwald // log_info("Removed timer %x at %u\n", (int) ts, (unsigned int) ts->timeout.tv_sec); 120528a4a3bSMatthias Ringwald // btstack_run_loop_posix_dump_timer(); 121b7d596c1SMatthias Ringwald return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts); 122b7d596c1SMatthias Ringwald } 123b7d596c1SMatthias Ringwald 124528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_dump_timer(void){ 125b7d596c1SMatthias Ringwald btstack_linked_item_t *it; 126b7d596c1SMatthias Ringwald int i = 0; 127b7d596c1SMatthias Ringwald for (it = (btstack_linked_item_t *) timers; it ; it = it->next){ 128ec820d77SMatthias Ringwald btstack_timer_source_t *ts = (btstack_timer_source_t*) it; 129bd539f2bSMatthias Ringwald log_info("timer %u (%p): timeout %u\n", i, ts, ts->timeout); 130b7d596c1SMatthias Ringwald } 131b7d596c1SMatthias Ringwald } 132b7d596c1SMatthias Ringwald 1339120e843SMatthias Ringwald static void btstack_run_loop_posix_enable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){ 1349120e843SMatthias Ringwald ds->flags |= callback_types; 1359120e843SMatthias Ringwald } 1369120e843SMatthias Ringwald 1379120e843SMatthias Ringwald static void btstack_run_loop_posix_disable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){ 1389120e843SMatthias Ringwald ds->flags &= ~callback_types; 1399120e843SMatthias Ringwald } 1409120e843SMatthias Ringwald 14192b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 14292b78dd7SMatthias Ringwald /** 14392b78dd7SMatthias Ringwald * @brief Returns the timespec which represents the time(stop - start). It might be negative 14492b78dd7SMatthias Ringwald */ 14592b78dd7SMatthias Ringwald static void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result){ 14692b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec; 14792b78dd7SMatthias Ringwald if ((stop->tv_nsec - start->tv_nsec) < 0) { 14892b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec - 1; 14992b78dd7SMatthias Ringwald result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000; 15092b78dd7SMatthias Ringwald } else { 15192b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec; 15292b78dd7SMatthias Ringwald result->tv_nsec = stop->tv_nsec - start->tv_nsec; 15392b78dd7SMatthias Ringwald } 15492b78dd7SMatthias Ringwald } 15592b78dd7SMatthias Ringwald 15692b78dd7SMatthias Ringwald /** 15792b78dd7SMatthias Ringwald * @brief Convert timespec to miliseconds, might overflow 15892b78dd7SMatthias Ringwald */ 15992b78dd7SMatthias Ringwald static uint64_t timespec_to_milliseconds(struct timespec *a){ 16092b78dd7SMatthias Ringwald uint64_t ret = 0; 16192b78dd7SMatthias Ringwald uint64_t sec_val = (uint64_t)(a->tv_sec); 16292b78dd7SMatthias Ringwald uint64_t nsec_val = (uint64_t)(a->tv_nsec); 16392b78dd7SMatthias Ringwald ret = (sec_val*1000) + (nsec_val/1000000); 16492b78dd7SMatthias Ringwald return ret; 16592b78dd7SMatthias Ringwald } 16692b78dd7SMatthias Ringwald 16792b78dd7SMatthias Ringwald /** 16892b78dd7SMatthias Ringwald * @brief Returns the milisecond value of (stop - start). Might overflow 16992b78dd7SMatthias Ringwald */ 17092b78dd7SMatthias Ringwald static uint64_t timespec_diff_milis(struct timespec* start, struct timespec* stop){ 17192b78dd7SMatthias Ringwald struct timespec diff_ts; 17292b78dd7SMatthias Ringwald timespec_diff(start, stop, &diff_ts); 17392b78dd7SMatthias Ringwald return timespec_to_milliseconds(&diff_ts); 17492b78dd7SMatthias Ringwald } 17592b78dd7SMatthias Ringwald #endif 17692b78dd7SMatthias Ringwald 177b7d596c1SMatthias Ringwald /** 178f316a845SMatthias Ringwald * @brief Queries the current time in ms since start 179f316a845SMatthias Ringwald */ 180f316a845SMatthias Ringwald static uint32_t btstack_run_loop_posix_get_time_ms(void){ 18192b78dd7SMatthias Ringwald uint32_t time_ms; 18292b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 18392b78dd7SMatthias Ringwald struct timespec now_ts; 18492b78dd7SMatthias Ringwald clock_gettime(CLOCK_MONOTONIC, &now_ts); 18592b78dd7SMatthias Ringwald time_ms = (uint32_t) timespec_diff_milis(&init_ts, &now_ts); 18692b78dd7SMatthias Ringwald #else 187f316a845SMatthias Ringwald struct timeval tv; 188f316a845SMatthias Ringwald gettimeofday(&tv, NULL); 18992b78dd7SMatthias Ringwald time_ms = (uint32_t) ((tv.tv_sec - init_tv.tv_sec) * 1000) + (tv.tv_usec / 1000); 19092b78dd7SMatthias Ringwald #endif 191f316a845SMatthias Ringwald return time_ms; 192f316a845SMatthias Ringwald } 193f316a845SMatthias Ringwald 194f316a845SMatthias Ringwald /** 195b7d596c1SMatthias Ringwald * Execute run_loop 196b7d596c1SMatthias Ringwald */ 197528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_execute(void) { 1989120e843SMatthias Ringwald fd_set descriptors_read; 1999120e843SMatthias Ringwald fd_set descriptors_write; 200b7d596c1SMatthias Ringwald 201ec820d77SMatthias Ringwald btstack_timer_source_t *ts; 202b7d596c1SMatthias Ringwald btstack_linked_list_iterator_t it; 203f316a845SMatthias Ringwald struct timeval * timeout; 204f316a845SMatthias Ringwald struct timeval tv; 205f316a845SMatthias Ringwald uint32_t now_ms; 206b7d596c1SMatthias Ringwald 20792b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 20892b78dd7SMatthias Ringwald log_info("POSIX run loop with monotonic clock"); 20992b78dd7SMatthias Ringwald #else 21092b78dd7SMatthias Ringwald log_info("POSIX run loop using ettimeofday fallback."); 21192b78dd7SMatthias Ringwald #endif 21292b78dd7SMatthias Ringwald 213b7d596c1SMatthias Ringwald while (1) { 214b7d596c1SMatthias Ringwald // collect FDs 2159120e843SMatthias Ringwald FD_ZERO(&descriptors_read); 2169120e843SMatthias Ringwald FD_ZERO(&descriptors_write); 217f316a845SMatthias Ringwald int highest_fd = -1; 218b7d596c1SMatthias Ringwald btstack_linked_list_iterator_init(&it, &data_sources); 219b7d596c1SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 220ec820d77SMatthias Ringwald btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); 221398a95ecSMatthias Ringwald if (ds->source.fd < 0) continue; 2229120e843SMatthias Ringwald if (ds->flags & DATA_SOURCE_CALLBACK_READ){ 223398a95ecSMatthias Ringwald FD_SET(ds->source.fd, &descriptors_read); 224398a95ecSMatthias Ringwald if (ds->source.fd > highest_fd) { 225398a95ecSMatthias Ringwald highest_fd = ds->source.fd; 2269120e843SMatthias Ringwald } 227398a95ecSMatthias Ringwald log_debug("btstack_run_loop_execute adding fd %u for read", ds->source.fd); 2289120e843SMatthias Ringwald } 2299120e843SMatthias Ringwald if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){ 230398a95ecSMatthias Ringwald FD_SET(ds->source.fd, &descriptors_write); 231398a95ecSMatthias Ringwald if (ds->source.fd > highest_fd) { 232398a95ecSMatthias Ringwald highest_fd = ds->source.fd; 233b7d596c1SMatthias Ringwald } 234398a95ecSMatthias Ringwald log_debug("btstack_run_loop_execute adding fd %u for write", ds->source.fd); 235b7d596c1SMatthias Ringwald } 236b7d596c1SMatthias Ringwald } 237b7d596c1SMatthias Ringwald 238b7d596c1SMatthias Ringwald // get next timeout 239b7d596c1SMatthias Ringwald timeout = NULL; 240b7d596c1SMatthias Ringwald if (timers) { 241ec820d77SMatthias Ringwald ts = (btstack_timer_source_t *) timers; 242f316a845SMatthias Ringwald timeout = &tv; 243b6fc147fSMatthias Ringwald uint32_t list_timeout = ts->timeout; 244f316a845SMatthias Ringwald now_ms = btstack_run_loop_posix_get_time_ms(); 245b6fc147fSMatthias Ringwald int32_t delta = btstack_time_delta(list_timeout, now_ms); 246f316a845SMatthias Ringwald if (delta < 0){ 247f316a845SMatthias Ringwald delta = 0; 248b7d596c1SMatthias Ringwald } 249f316a845SMatthias Ringwald tv.tv_sec = delta / 1000; 2507c959318SMatthias Ringwald tv.tv_usec = (int) (delta - (tv.tv_sec * 1000)) * 1000; 251f316a845SMatthias Ringwald log_debug("btstack_run_loop_execute next timeout in %u ms", delta); 252b7d596c1SMatthias Ringwald } 253b7d596c1SMatthias Ringwald 254b7d596c1SMatthias Ringwald // wait for ready FDs 2559120e843SMatthias Ringwald select( highest_fd+1 , &descriptors_read, &descriptors_write, NULL, timeout); 256b7d596c1SMatthias Ringwald 25788e0b3b2SMatthias Ringwald 258b7d596c1SMatthias Ringwald data_sources_modified = 0; 259b7d596c1SMatthias Ringwald btstack_linked_list_iterator_init(&it, &data_sources); 260b7d596c1SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it) && !data_sources_modified){ 261ec820d77SMatthias Ringwald btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); 262398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: check ds %p with fd %u\n", ds, ds->source.fd); 263398a95ecSMatthias Ringwald if (FD_ISSET(ds->source.fd, &descriptors_read)) { 264398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: process read ds %p with fd %u\n", ds, ds->source.fd); 2657cd5ef95SMatthias Ringwald ds->process(ds, DATA_SOURCE_CALLBACK_READ); 266b7d596c1SMatthias Ringwald } 2674b7565a2SMatthias Ringwald if (data_sources_modified) break; 268398a95ecSMatthias Ringwald if (FD_ISSET(ds->source.fd, &descriptors_write)) { 269398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: process write ds %p with fd %u\n", ds, ds->source.fd); 2709120e843SMatthias Ringwald ds->process(ds, DATA_SOURCE_CALLBACK_WRITE); 2719120e843SMatthias Ringwald } 272b7d596c1SMatthias Ringwald } 273f316a845SMatthias Ringwald log_debug("btstack_run_loop_posix_execute: after ds check\n"); 274b7d596c1SMatthias Ringwald 275b7d596c1SMatthias Ringwald // process timers 27688e0b3b2SMatthias Ringwald now_ms = btstack_run_loop_posix_get_time_ms(); 277b7d596c1SMatthias Ringwald while (timers) { 278ec820d77SMatthias Ringwald ts = (btstack_timer_source_t *) timers; 279b6fc147fSMatthias Ringwald int32_t delta = btstack_time_delta(ts->timeout, now_ms); 280b6fc147fSMatthias Ringwald if (delta > 0) break; 281f316a845SMatthias Ringwald log_debug("btstack_run_loop_posix_execute: process timer %p\n", ts); 282b7d596c1SMatthias Ringwald 283b7d596c1SMatthias Ringwald // remove timer before processing it to allow handler to re-register with run loop 284b7832c7fSMatthias Ringwald btstack_run_loop_posix_remove_timer(ts); 285b7d596c1SMatthias Ringwald ts->process(ts); 286b7d596c1SMatthias Ringwald } 287b7d596c1SMatthias Ringwald } 288b7d596c1SMatthias Ringwald } 289b7d596c1SMatthias Ringwald 290b7d596c1SMatthias Ringwald // set timer 291ec820d77SMatthias Ringwald static void btstack_run_loop_posix_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){ 292f316a845SMatthias Ringwald uint32_t time_ms = btstack_run_loop_posix_get_time_ms(); 293f316a845SMatthias Ringwald a->timeout = time_ms + timeout_in_ms; 294615ae444SMatthias Ringwald log_debug("btstack_run_loop_posix_set_timer to %u ms (now %u, timeout %u)", a->timeout, time_ms, timeout_in_ms); 295b7d596c1SMatthias Ringwald } 296b7d596c1SMatthias Ringwald 297528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_init(void){ 298b7d596c1SMatthias Ringwald data_sources = NULL; 299b7d596c1SMatthias Ringwald timers = NULL; 30092b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 30192b78dd7SMatthias Ringwald clock_gettime(CLOCK_MONOTONIC, &init_ts); 30292b78dd7SMatthias Ringwald init_ts.tv_nsec = 0; 30392b78dd7SMatthias Ringwald #else 304f316a845SMatthias Ringwald // just assume that we started at tv_usec == 0 305b7d596c1SMatthias Ringwald gettimeofday(&init_tv, NULL); 306f316a845SMatthias Ringwald init_tv.tv_usec = 0; 30792b78dd7SMatthias Ringwald #endif 308b7d596c1SMatthias Ringwald } 309b7d596c1SMatthias Ringwald 310b7d596c1SMatthias Ringwald 311528a4a3bSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_posix = { 312528a4a3bSMatthias Ringwald &btstack_run_loop_posix_init, 313528a4a3bSMatthias Ringwald &btstack_run_loop_posix_add_data_source, 314528a4a3bSMatthias Ringwald &btstack_run_loop_posix_remove_data_source, 3159120e843SMatthias Ringwald &btstack_run_loop_posix_enable_data_source_callbacks, 3169120e843SMatthias Ringwald &btstack_run_loop_posix_disable_data_source_callbacks, 317528a4a3bSMatthias Ringwald &btstack_run_loop_posix_set_timer, 318528a4a3bSMatthias Ringwald &btstack_run_loop_posix_add_timer, 319528a4a3bSMatthias Ringwald &btstack_run_loop_posix_remove_timer, 320528a4a3bSMatthias Ringwald &btstack_run_loop_posix_execute, 321528a4a3bSMatthias Ringwald &btstack_run_loop_posix_dump_timer, 322528a4a3bSMatthias Ringwald &btstack_run_loop_posix_get_time_ms, 323b7d596c1SMatthias Ringwald }; 324b7d596c1SMatthias Ringwald 325b7d596c1SMatthias Ringwald /** 326528a4a3bSMatthias Ringwald * Provide btstack_run_loop_posix instance 327b7d596c1SMatthias Ringwald */ 328528a4a3bSMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_posix_get_instance(void){ 329528a4a3bSMatthias Ringwald return &btstack_run_loop_posix; 330b7d596c1SMatthias Ringwald } 331b7d596c1SMatthias Ringwald 332