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 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH 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> 58*c663093bSMatthias Ringwald #include <sys/errno.h> 59b6fc147fSMatthias Ringwald #include <sys/select.h> 60f316a845SMatthias Ringwald #include <sys/time.h> 6192b78dd7SMatthias Ringwald #include <time.h> 6292b78dd7SMatthias Ringwald #include <unistd.h> 6341158b74SMatthias Ringwald #include <pthread.h> 64b7d596c1SMatthias Ringwald 65b7d596c1SMatthias Ringwald // the run loop 6690d4f186SMatthias Ringwald static int btstack_run_loop_posix_data_sources_modified; 6792b78dd7SMatthias Ringwald 6890d4f186SMatthias Ringwald static bool btstack_run_loop_posix_exit_requested; 692e357f7aSMatthias Ringwald 7090d4f186SMatthias Ringwald // to trigger process callbacks other thread 7190d4f186SMatthias Ringwald static pthread_mutex_t btstack_run_loop_posix_callbacks_mutex = PTHREAD_MUTEX_INITIALIZER; 7290d4f186SMatthias Ringwald static int btstack_run_loop_posix_process_callbacks_fd; 7390d4f186SMatthias Ringwald static btstack_data_source_t btstack_run_loop_posix_process_callbacks_ds; 7490d4f186SMatthias Ringwald 7590d4f186SMatthias Ringwald // to trigger poll data sources from irq 7690d4f186SMatthias Ringwald static int btstack_run_loop_posix_poll_data_sources_fd; 7790d4f186SMatthias Ringwald static btstack_data_source_t btstack_run_loop_posix_poll_data_sources_ds; 7841158b74SMatthias Ringwald 7992b78dd7SMatthias Ringwald // start time. tv_usec/tv_nsec = 0 8092b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 8192b78dd7SMatthias Ringwald // use monotonic clock if available 8292b78dd7SMatthias Ringwald static struct timespec init_ts; 8392b78dd7SMatthias Ringwald #else 8492b78dd7SMatthias Ringwald // fallback to gettimeofday 85b7d596c1SMatthias Ringwald static struct timeval init_tv; 8692b78dd7SMatthias Ringwald #endif 87b7d596c1SMatthias Ringwald 88b7d596c1SMatthias Ringwald /** 89b7d596c1SMatthias Ringwald * Add data_source to run_loop 90b7d596c1SMatthias Ringwald */ 91ec820d77SMatthias Ringwald static void btstack_run_loop_posix_add_data_source(btstack_data_source_t *ds){ 9290d4f186SMatthias Ringwald btstack_run_loop_posix_data_sources_modified = 1; 93075edf12SMatthias Ringwald btstack_run_loop_base_add_data_source(ds); 94b7d596c1SMatthias Ringwald } 95b7d596c1SMatthias Ringwald 96b7d596c1SMatthias Ringwald /** 97b7d596c1SMatthias Ringwald * Remove data_source from run loop 98b7d596c1SMatthias Ringwald */ 99d58a1b5fSMatthias Ringwald static bool btstack_run_loop_posix_remove_data_source(btstack_data_source_t *ds){ 10090d4f186SMatthias Ringwald btstack_run_loop_posix_data_sources_modified = 1; 101075edf12SMatthias Ringwald return btstack_run_loop_base_remove_data_source(ds); 1029120e843SMatthias Ringwald } 1039120e843SMatthias Ringwald 10492b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 10592b78dd7SMatthias Ringwald /** 10692b78dd7SMatthias Ringwald * @brief Returns the timespec which represents the time(stop - start). It might be negative 10792b78dd7SMatthias Ringwald */ 10892b78dd7SMatthias Ringwald static void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result){ 10992b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec; 11092b78dd7SMatthias Ringwald if ((stop->tv_nsec - start->tv_nsec) < 0) { 11192b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec - 1; 11292b78dd7SMatthias Ringwald result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000; 11392b78dd7SMatthias Ringwald } else { 11492b78dd7SMatthias Ringwald result->tv_sec = stop->tv_sec - start->tv_sec; 11592b78dd7SMatthias Ringwald result->tv_nsec = stop->tv_nsec - start->tv_nsec; 11692b78dd7SMatthias Ringwald } 11792b78dd7SMatthias Ringwald } 11892b78dd7SMatthias Ringwald 11992b78dd7SMatthias Ringwald /** 12092b78dd7SMatthias Ringwald * @brief Convert timespec to miliseconds, might overflow 12192b78dd7SMatthias Ringwald */ 12292b78dd7SMatthias Ringwald static uint64_t timespec_to_milliseconds(struct timespec *a){ 12392b78dd7SMatthias Ringwald uint64_t ret = 0; 12492b78dd7SMatthias Ringwald uint64_t sec_val = (uint64_t)(a->tv_sec); 12592b78dd7SMatthias Ringwald uint64_t nsec_val = (uint64_t)(a->tv_nsec); 12692b78dd7SMatthias Ringwald ret = (sec_val*1000) + (nsec_val/1000000); 12792b78dd7SMatthias Ringwald return ret; 12892b78dd7SMatthias Ringwald } 12992b78dd7SMatthias Ringwald 13092b78dd7SMatthias Ringwald /** 13192b78dd7SMatthias Ringwald * @brief Returns the milisecond value of (stop - start). Might overflow 13292b78dd7SMatthias Ringwald */ 13392b78dd7SMatthias Ringwald static uint64_t timespec_diff_milis(struct timespec* start, struct timespec* stop){ 13492b78dd7SMatthias Ringwald struct timespec diff_ts; 13592b78dd7SMatthias Ringwald timespec_diff(start, stop, &diff_ts); 13692b78dd7SMatthias Ringwald return timespec_to_milliseconds(&diff_ts); 13792b78dd7SMatthias Ringwald } 13892b78dd7SMatthias Ringwald #endif 13992b78dd7SMatthias Ringwald 140b7d596c1SMatthias Ringwald /** 141f316a845SMatthias Ringwald * @brief Queries the current time in ms since start 142f316a845SMatthias Ringwald */ 143f316a845SMatthias Ringwald static uint32_t btstack_run_loop_posix_get_time_ms(void){ 14492b78dd7SMatthias Ringwald uint32_t time_ms; 14592b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 14692b78dd7SMatthias Ringwald struct timespec now_ts; 14792b78dd7SMatthias Ringwald clock_gettime(CLOCK_MONOTONIC, &now_ts); 14892b78dd7SMatthias Ringwald time_ms = (uint32_t) timespec_diff_milis(&init_ts, &now_ts); 14992b78dd7SMatthias Ringwald #else 150f316a845SMatthias Ringwald struct timeval tv; 151f316a845SMatthias Ringwald gettimeofday(&tv, NULL); 15292b78dd7SMatthias Ringwald time_ms = (uint32_t) ((tv.tv_sec - init_tv.tv_sec) * 1000) + (tv.tv_usec / 1000); 15392b78dd7SMatthias Ringwald #endif 154f316a845SMatthias Ringwald return time_ms; 155f316a845SMatthias Ringwald } 156f316a845SMatthias Ringwald 157f316a845SMatthias Ringwald /** 158b7d596c1SMatthias Ringwald * Execute run_loop 159b7d596c1SMatthias Ringwald */ 160528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_execute(void) { 1619120e843SMatthias Ringwald fd_set descriptors_read; 1629120e843SMatthias Ringwald fd_set descriptors_write; 163b7d596c1SMatthias Ringwald 164b7d596c1SMatthias Ringwald btstack_linked_list_iterator_t it; 165f316a845SMatthias Ringwald struct timeval * timeout; 166f316a845SMatthias Ringwald struct timeval tv; 167f316a845SMatthias Ringwald uint32_t now_ms; 168b7d596c1SMatthias Ringwald 16992b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 17092b78dd7SMatthias Ringwald log_info("POSIX run loop with monotonic clock"); 17192b78dd7SMatthias Ringwald #else 17292b78dd7SMatthias Ringwald log_info("POSIX run loop using ettimeofday fallback."); 17392b78dd7SMatthias Ringwald #endif 17492b78dd7SMatthias Ringwald 17590d4f186SMatthias Ringwald while (btstack_run_loop_posix_exit_requested == false) { 176b7d596c1SMatthias Ringwald // collect FDs 1779120e843SMatthias Ringwald FD_ZERO(&descriptors_read); 1789120e843SMatthias Ringwald FD_ZERO(&descriptors_write); 179f316a845SMatthias Ringwald int highest_fd = -1; 180075edf12SMatthias Ringwald btstack_linked_list_iterator_init(&it, &btstack_run_loop_base_data_sources); 181b7d596c1SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 182ec820d77SMatthias Ringwald btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); 183398a95ecSMatthias Ringwald if (ds->source.fd < 0) continue; 1849120e843SMatthias Ringwald if (ds->flags & DATA_SOURCE_CALLBACK_READ){ 185398a95ecSMatthias Ringwald FD_SET(ds->source.fd, &descriptors_read); 186398a95ecSMatthias Ringwald if (ds->source.fd > highest_fd) { 187398a95ecSMatthias Ringwald highest_fd = ds->source.fd; 1889120e843SMatthias Ringwald } 189398a95ecSMatthias Ringwald log_debug("btstack_run_loop_execute adding fd %u for read", ds->source.fd); 1909120e843SMatthias Ringwald } 1919120e843SMatthias Ringwald if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){ 192398a95ecSMatthias Ringwald FD_SET(ds->source.fd, &descriptors_write); 193398a95ecSMatthias Ringwald if (ds->source.fd > highest_fd) { 194398a95ecSMatthias Ringwald highest_fd = ds->source.fd; 195b7d596c1SMatthias Ringwald } 196398a95ecSMatthias Ringwald log_debug("btstack_run_loop_execute adding fd %u for write", ds->source.fd); 197b7d596c1SMatthias Ringwald } 198b7d596c1SMatthias Ringwald } 199b7d596c1SMatthias Ringwald 200b7d596c1SMatthias Ringwald // get next timeout 201b7d596c1SMatthias Ringwald timeout = NULL; 202f316a845SMatthias Ringwald now_ms = btstack_run_loop_posix_get_time_ms(); 203075edf12SMatthias Ringwald int32_t delta_ms = btstack_run_loop_base_get_time_until_timeout(now_ms); 204075edf12SMatthias Ringwald if (delta_ms >= 0) { 205075edf12SMatthias Ringwald timeout = &tv; 206075edf12SMatthias Ringwald tv.tv_sec = delta_ms / 1000; 207075edf12SMatthias Ringwald tv.tv_usec = (int) (delta_ms - (tv.tv_sec * 1000)) * 1000; 208075edf12SMatthias Ringwald log_debug("btstack_run_loop_execute next timeout in %u ms", delta_ms); 209b7d596c1SMatthias Ringwald } 210b7d596c1SMatthias Ringwald 211b7d596c1SMatthias Ringwald // wait for ready FDs 212*c663093bSMatthias Ringwald int res = select( highest_fd+1 , &descriptors_read, &descriptors_write, NULL, timeout); 213*c663093bSMatthias Ringwald if (res < 0){ 214*c663093bSMatthias Ringwald log_error("btstack_run_loop_posix_execute: select -> errno %u", errno); 215*c663093bSMatthias Ringwald } 216*c663093bSMatthias Ringwald if (res > 0){ 21790d4f186SMatthias Ringwald btstack_run_loop_posix_data_sources_modified = 0; 218075edf12SMatthias Ringwald btstack_linked_list_iterator_init(&it, &btstack_run_loop_base_data_sources); 21990d4f186SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it) && !btstack_run_loop_posix_data_sources_modified){ 220ec820d77SMatthias Ringwald btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it); 221398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: check ds %p with fd %u\n", ds, ds->source.fd); 222398a95ecSMatthias Ringwald if (FD_ISSET(ds->source.fd, &descriptors_read)) { 223398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: process read ds %p with fd %u\n", ds, ds->source.fd); 2247cd5ef95SMatthias Ringwald ds->process(ds, DATA_SOURCE_CALLBACK_READ); 225b7d596c1SMatthias Ringwald } 22690d4f186SMatthias Ringwald if (btstack_run_loop_posix_data_sources_modified) break; 227398a95ecSMatthias Ringwald if (FD_ISSET(ds->source.fd, &descriptors_write)) { 228398a95ecSMatthias Ringwald log_debug("btstack_run_loop_posix_execute: process write ds %p with fd %u\n", ds, ds->source.fd); 2299120e843SMatthias Ringwald ds->process(ds, DATA_SOURCE_CALLBACK_WRITE); 2309120e843SMatthias Ringwald } 231b7d596c1SMatthias Ringwald } 232*c663093bSMatthias Ringwald } 233f316a845SMatthias Ringwald log_debug("btstack_run_loop_posix_execute: after ds check\n"); 234b7d596c1SMatthias Ringwald 235b7d596c1SMatthias Ringwald // process timers 23688e0b3b2SMatthias Ringwald now_ms = btstack_run_loop_posix_get_time_ms(); 237075edf12SMatthias Ringwald btstack_run_loop_base_process_timers(now_ms); 238b7d596c1SMatthias Ringwald } 239b7d596c1SMatthias Ringwald } 240b7d596c1SMatthias Ringwald 2412e357f7aSMatthias Ringwald static void btstack_run_loop_posix_trigger_exit(void){ 24290d4f186SMatthias Ringwald btstack_run_loop_posix_exit_requested = true; 2432e357f7aSMatthias Ringwald } 2442e357f7aSMatthias Ringwald 245b7d596c1SMatthias Ringwald // set timer 246ec820d77SMatthias Ringwald static void btstack_run_loop_posix_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){ 247f316a845SMatthias Ringwald uint32_t time_ms = btstack_run_loop_posix_get_time_ms(); 248f316a845SMatthias Ringwald a->timeout = time_ms + timeout_in_ms; 249615ae444SMatthias Ringwald log_debug("btstack_run_loop_posix_set_timer to %u ms (now %u, timeout %u)", a->timeout, time_ms, timeout_in_ms); 250b7d596c1SMatthias Ringwald } 251b7d596c1SMatthias Ringwald 25290d4f186SMatthias Ringwald // trigger pipe 25390d4f186SMatthias Ringwald static void btstack_run_loop_posix_trigger_pipe(int fd){ 25490d4f186SMatthias Ringwald if (fd < 0) return; 25590d4f186SMatthias Ringwald const uint8_t x = (uint8_t) 'x'; 2569e6ecc42SMatthias Ringwald ssize_t bytes_written = write(fd, &x, 1); 2579e6ecc42SMatthias Ringwald UNUSED(bytes_written); 25890d4f186SMatthias Ringwald } 25990d4f186SMatthias Ringwald 26090d4f186SMatthias Ringwald // poll data sources from irq 26190d4f186SMatthias Ringwald 26290d4f186SMatthias Ringwald static void btstack_run_loop_posix_poll_data_sources_handler(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){ 26341158b74SMatthias Ringwald UNUSED(callback_type); 26490d4f186SMatthias Ringwald uint8_t buffer[1]; 2659e6ecc42SMatthias Ringwald ssize_t bytes_read = read(ds->source.fd, buffer, 1); 2669e6ecc42SMatthias Ringwald UNUSED(bytes_read); 26790d4f186SMatthias Ringwald // poll data sources 26890d4f186SMatthias Ringwald btstack_run_loop_base_poll_data_sources(); 26990d4f186SMatthias Ringwald } 27090d4f186SMatthias Ringwald 27190d4f186SMatthias Ringwald static void btstack_run_loop_posix_poll_data_sources_from_irq(void){ 27290d4f186SMatthias Ringwald // trigger run loop 27390d4f186SMatthias Ringwald btstack_run_loop_posix_trigger_pipe(btstack_run_loop_posix_poll_data_sources_fd); 27490d4f186SMatthias Ringwald } 27590d4f186SMatthias Ringwald 27690d4f186SMatthias Ringwald // execute on main thread from same or different thread 27790d4f186SMatthias Ringwald 27890d4f186SMatthias Ringwald static void btstack_run_loop_posix_process_callbacks_handler(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){ 27990d4f186SMatthias Ringwald UNUSED(callback_type); 28041158b74SMatthias Ringwald uint8_t buffer[1]; 2819e6ecc42SMatthias Ringwald ssize_t bytes_read = read(ds->source.fd, buffer, 1); 2829e6ecc42SMatthias Ringwald UNUSED(bytes_read); 28341158b74SMatthias Ringwald // execute callbacks - protect list with mutex 28441158b74SMatthias Ringwald while (1){ 28590d4f186SMatthias Ringwald pthread_mutex_lock(&btstack_run_loop_posix_callbacks_mutex); 28641158b74SMatthias Ringwald btstack_context_callback_registration_t * callback_registration = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&btstack_run_loop_base_callbacks); 28790d4f186SMatthias Ringwald pthread_mutex_unlock(&btstack_run_loop_posix_callbacks_mutex); 28841158b74SMatthias Ringwald if (callback_registration == NULL){ 28941158b74SMatthias Ringwald break; 29041158b74SMatthias Ringwald } 29141158b74SMatthias Ringwald (*callback_registration->callback)(callback_registration->context); 29241158b74SMatthias Ringwald } 29341158b74SMatthias Ringwald } 29441158b74SMatthias Ringwald 29541158b74SMatthias Ringwald static void btstack_run_loop_posix_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration){ 29641158b74SMatthias Ringwald // protect list with mutex 29790d4f186SMatthias Ringwald pthread_mutex_lock(&btstack_run_loop_posix_callbacks_mutex); 29841158b74SMatthias Ringwald btstack_run_loop_base_add_callback(callback_registration); 29990d4f186SMatthias Ringwald pthread_mutex_unlock(&btstack_run_loop_posix_callbacks_mutex); 30041158b74SMatthias Ringwald // trigger run loop 30190d4f186SMatthias Ringwald btstack_run_loop_posix_trigger_pipe(btstack_run_loop_posix_process_callbacks_fd); 30241158b74SMatthias Ringwald } 30390d4f186SMatthias Ringwald 30490d4f186SMatthias Ringwald //init 30590d4f186SMatthias Ringwald 30690d4f186SMatthias Ringwald // @return fd >= 0 on success 30790d4f186SMatthias Ringwald static int btstack_run_loop_posix_register_pipe_datasource(btstack_data_source_t * data_source){ 30890d4f186SMatthias Ringwald int fildes[2]; // 0 = read, 1 = write 30990d4f186SMatthias Ringwald int status = pipe(fildes); 31090d4f186SMatthias Ringwald if (status != 0){ 31190d4f186SMatthias Ringwald log_error("pipe() failed"); 31290d4f186SMatthias Ringwald return -1; 31390d4f186SMatthias Ringwald } 31490d4f186SMatthias Ringwald data_source->source.fd = fildes[0]; 31590d4f186SMatthias Ringwald data_source->flags = DATA_SOURCE_CALLBACK_READ; 31690d4f186SMatthias Ringwald btstack_run_loop_base_add_data_source(data_source); 31790d4f186SMatthias Ringwald log_info("Pipe: in %u, out %u", fildes[1], fildes[0]); 31890d4f186SMatthias Ringwald return fildes[1]; 31941158b74SMatthias Ringwald } 32041158b74SMatthias Ringwald 321528a4a3bSMatthias Ringwald static void btstack_run_loop_posix_init(void){ 322075edf12SMatthias Ringwald btstack_run_loop_base_init(); 323075edf12SMatthias Ringwald 32492b78dd7SMatthias Ringwald #ifdef _POSIX_MONOTONIC_CLOCK 32592b78dd7SMatthias Ringwald clock_gettime(CLOCK_MONOTONIC, &init_ts); 32692b78dd7SMatthias Ringwald init_ts.tv_nsec = 0; 32792b78dd7SMatthias Ringwald #else 328f316a845SMatthias Ringwald // just assume that we started at tv_usec == 0 329b7d596c1SMatthias Ringwald gettimeofday(&init_tv, NULL); 330f316a845SMatthias Ringwald init_tv.tv_usec = 0; 33192b78dd7SMatthias Ringwald #endif 332b7d596c1SMatthias Ringwald 33390d4f186SMatthias Ringwald // setup pipe to trigger process callbacks 33490d4f186SMatthias Ringwald btstack_run_loop_posix_process_callbacks_ds.process = &btstack_run_loop_posix_process_callbacks_handler; 33590d4f186SMatthias Ringwald btstack_run_loop_posix_process_callbacks_fd = btstack_run_loop_posix_register_pipe_datasource(&btstack_run_loop_posix_process_callbacks_ds); 33690d4f186SMatthias Ringwald 33790d4f186SMatthias Ringwald // setup pipe to poll data sources 33890d4f186SMatthias Ringwald btstack_run_loop_posix_poll_data_sources_ds.process = &btstack_run_loop_posix_poll_data_sources_handler; 33990d4f186SMatthias Ringwald btstack_run_loop_posix_poll_data_sources_fd = btstack_run_loop_posix_register_pipe_datasource(&btstack_run_loop_posix_poll_data_sources_ds); 34041158b74SMatthias Ringwald } 341b7d596c1SMatthias Ringwald 342528a4a3bSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_posix = { 343528a4a3bSMatthias Ringwald &btstack_run_loop_posix_init, 344528a4a3bSMatthias Ringwald &btstack_run_loop_posix_add_data_source, 345528a4a3bSMatthias Ringwald &btstack_run_loop_posix_remove_data_source, 346075edf12SMatthias Ringwald &btstack_run_loop_base_enable_data_source_callbacks, 347075edf12SMatthias Ringwald &btstack_run_loop_base_disable_data_source_callbacks, 348528a4a3bSMatthias Ringwald &btstack_run_loop_posix_set_timer, 349075edf12SMatthias Ringwald &btstack_run_loop_base_add_timer, 350075edf12SMatthias Ringwald &btstack_run_loop_base_remove_timer, 351528a4a3bSMatthias Ringwald &btstack_run_loop_posix_execute, 352075edf12SMatthias Ringwald &btstack_run_loop_base_dump_timer, 353528a4a3bSMatthias Ringwald &btstack_run_loop_posix_get_time_ms, 35490d4f186SMatthias Ringwald &btstack_run_loop_posix_poll_data_sources_from_irq, 35590d4f186SMatthias Ringwald &btstack_run_loop_posix_execute_on_main_thread, 3562e357f7aSMatthias Ringwald &btstack_run_loop_posix_trigger_exit, 357b7d596c1SMatthias Ringwald }; 358b7d596c1SMatthias Ringwald 359b7d596c1SMatthias Ringwald /** 360528a4a3bSMatthias Ringwald * Provide btstack_run_loop_posix instance 361b7d596c1SMatthias Ringwald */ 362528a4a3bSMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_posix_get_instance(void){ 363528a4a3bSMatthias Ringwald return &btstack_run_loop_posix; 364b7d596c1SMatthias Ringwald } 365b7d596c1SMatthias Ringwald 366