From 98a6a0788e826bf360e283f43f5ffc40815eda25 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 4 Aug 2019 18:45:13 +0200 Subject: [PATCH] btstack_run_loop_base: portable implementation of timer and data source managment as base for platform specific implementations --- CHANGELOG.md | 6 +- src/btstack_run_loop_base.c | 123 ++++++++++++++++++++++++++++++++++++ src/btstack_run_loop_base.h | 118 ++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 src/btstack_run_loop_base.c create mode 100644 src/btstack_run_loop_base.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ccc73568..73457d46c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - RFCOMM: accept incoming L2CAP connection in Basic mode if ERTM is enabled but not requested for this connection ---- +### Added +- btstack_run_loop_base: portable implementation of timer and data source managment as base for platform specific implementations + ## Changes July 2019 @@ -21,8 +23,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - SM: Start encryption upon receiving slave securiy request if bonded -### Added - --- ## Changes June 2019 diff --git a/src/btstack_run_loop_base.c b/src/btstack_run_loop_base.c new file mode 100644 index 000000000..aaee65e21 --- /dev/null +++ b/src/btstack_run_loop_base.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2019 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +#define BTSTACK_FILE__ "btstack_run_loop_base.c" + +/* + * btstack_run_loop_base.h + * + * Portable implementation of timer and data source managment as base for platform specific implementations + */ + +#include "btstack_debug.h" +#include "btstack_config.h" +#include "btstack_util.h" + +#include "btstack_run_loop_base.h" + +// private data (access only by run loop implementations) +btstack_linked_list_t btstack_run_loop_base_timers; +btstack_linked_list_t btstack_run_loop_base_data_sources; + +void btstack_run_loop_base_init(void){ + btstack_run_loop_base_timers = NULL; + btstack_run_loop_base_data_sources = NULL; +} + +void btstack_run_loop_base_add_data_source(btstack_data_source_t *ds){ + btstack_linked_list_add(&btstack_run_loop_base_data_sources, (btstack_linked_item_t *) ds); +} + +int btstack_run_loop_base_remove_data_source(btstack_data_source_t *ds){ + return btstack_linked_list_remove(&btstack_run_loop_base_data_sources, (btstack_linked_item_t *) ds); +} + +void btstack_run_loop_base_enable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){ + ds->flags |= callback_types; +} + +void btstack_run_loop_base_disable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){ + ds->flags &= ~callback_types; +} + + +int btstack_run_loop_base_remove_timer(btstack_timer_source_t *ts){ + return btstack_linked_list_remove(&btstack_run_loop_base_timers, (btstack_linked_item_t *) ts); +} + +void btstack_run_loop_base_add_timer(btstack_timer_source_t *ts){ + btstack_linked_item_t *it; + for (it = (btstack_linked_item_t *) &btstack_run_loop_base_timers; it->next ; it = it->next){ + // don't add timer that's already in there + if ((btstack_timer_source_t *) it->next == ts){ + log_error( "btstack_run_loop_timer_add error: timer to add already in list!"); + return; + } + // exit if list timeout is after new timeout + uint32_t list_timeout = ((btstack_timer_source_t *) it->next)->timeout; + int32_t delta = btstack_time_delta(ts->timeout, list_timeout); + if (delta < 0) break; + } + ts->item.next = it->next; + it->next = (btstack_linked_item_t *) ts; +} + +void btstack_run_loop_base_process_timers(uint32_t now){ + // process timers, exit when timeout is in the future + while (btstack_run_loop_base_timers) { + btstack_timer_source_t * ts = (btstack_timer_source_t *) btstack_run_loop_base_timers; + int32_t delta = btstack_time_delta(ts->timeout, now); + if (delta > 0) break; + btstack_run_loop_base_remove_timer(ts); + ts->process(ts); + } +} + +/** + * @brief Get time until first timer fires + * @returns -1 if no timers, time until next timeout otherwise + */ +int32_t btstack_run_loop_base_get_time_until_timeout(uint32_t now){ + if (btstack_run_loop_base_timers == NULL) return -1; + btstack_timer_source_t * ts = (btstack_timer_source_t *) btstack_run_loop_base_timers; + uint32_t list_timeout = ts->timeout; + int32_t delta = btstack_time_delta(list_timeout, now); + if (delta < 0){ + delta = 0; + } + return delta; +} diff --git a/src/btstack_run_loop_base.h b/src/btstack_run_loop_base.h new file mode 100644 index 000000000..579be731d --- /dev/null +++ b/src/btstack_run_loop_base.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +/* + * btstack_run_loop_base.h + * + * Portable implementation of timer and data source managment as base for platform specific implementations + */ + +#ifndef BTSTACK_RUN_LOOP_BASE_H +#define BTSTACK_RUN_LOOP_BASE_H + +#include "btstack_run_loop.h" + +#include "btstack_linked_list.h" + +#include + +#if defined __cplusplus +extern "C" { +#endif + +// private data (access only by run loop implementations) +extern btstack_linked_list_t btstack_run_loop_base_timers; +extern btstack_linked_list_t btstack_run_loop_base_data_sources; + +/** + * @brief Init + */ +void btstack_run_loop_base_init(void); + +/** + * @brief Add timer source. + */ +void btstack_run_loop_base_add_timer(btstack_timer_source_t * timer); + +/** + * @brief Remove timer source. + */ +int btstack_run_loop_base_remove_timer(btstack_timer_source_t * timer); + +/** + * @brief Process timers: remove expired timers from list and call their process function + * @param now + */ +void btstack_run_loop_base_process_timers(uint32_t now); + +/** + * @brief Get time until first timer fires + * @returns -1 if no timers, time until next timeout otherwise + */ +int32_t btstack_run_loop_base_get_time_until_timeout(uint32_t now); + +/** + * @brief Add data source to run loop + * @param data_source to add + */ +void btstack_run_loop_base_add_data_source(btstack_data_source_t * data_source); + +/** + * @brief Remove data source from run loop + * @param data_source to remove + */ +int btstack_run_loop_base_remove_data_source(btstack_data_source_t * data_source); + +/** + * @brief Enable callbacks for a data source + * @param data_source to remove + * @param callback types to enable + */ +void btstack_run_loop_base_enable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks); + +/** + * @brief Enable callbacks for a data source + * @param data_source to remove + * @param callback types to disable + */ +void btstack_run_loop_base_disable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks); + +#if defined __cplusplus +} +#endif + +#endif // BTSTACK_RUN_LOOP_BASE_H