1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 /** 39 * BTstack Run Loop Abstraction 40 * 41 * Provides generic functionality required by the Bluetooth stack and example applications: 42 * - asynchronous IO for various devices Serial, USB, network sockets, console 43 * - system time in milliseconds 44 * - single shot timers 45 * - integration for threaded environments 46 */ 47 48 #ifndef BTSTACK_RUN_LOOP_H 49 #define BTSTACK_RUN_LOOP_H 50 51 #include "btstack_config.h" 52 53 #include "btstack_bool.h" 54 #include "btstack_linked_list.h" 55 #include "btstack_defines.h" 56 57 #include <stdint.h> 58 59 #if defined __cplusplus 60 extern "C" { 61 #endif 62 63 /** 64 * Callback types for run loop data sources 65 */ 66 typedef enum { 67 DATA_SOURCE_CALLBACK_POLL = 1 << 0, 68 DATA_SOURCE_CALLBACK_READ = 1 << 1, 69 DATA_SOURCE_CALLBACK_WRITE = 1 << 2, 70 } btstack_data_source_callback_type_t; 71 72 typedef struct btstack_data_source { 73 // linked item 74 btstack_linked_item_t item; 75 76 // item to watch in run loop 77 union { 78 // file descriptor for posix systems 79 int fd; 80 // handle on windows 81 void * handle; 82 } source; 83 84 // callback to call for enabled callback types 85 void (*process)(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type); 86 87 // flags storing enabled callback types 88 uint16_t flags; 89 90 } btstack_data_source_t; 91 92 typedef struct btstack_timer_source { 93 btstack_linked_item_t item; 94 // timeout in system ticks (HAVE_EMBEDDED_TICK) or milliseconds (HAVE_EMBEDDED_TIME_MS) 95 uint32_t timeout; 96 // will be called when timer fired 97 void (*process)(struct btstack_timer_source *ts); 98 void * context; 99 } btstack_timer_source_t; 100 101 typedef struct btstack_run_loop { 102 void (*init)(void); 103 void (*add_data_source)(btstack_data_source_t * data_source); 104 bool (*remove_data_source)(btstack_data_source_t * data_source); 105 void (*enable_data_source_callbacks)(btstack_data_source_t * data_source, uint16_t callbacks); 106 void (*disable_data_source_callbacks)(btstack_data_source_t * data_source, uint16_t callbacks); 107 void (*set_timer)(btstack_timer_source_t * timer, uint32_t timeout_in_ms); 108 void (*add_timer)(btstack_timer_source_t *timer); 109 bool (*remove_timer)(btstack_timer_source_t *timer); 110 void (*execute)(void); 111 void (*dump_timer)(void); 112 uint32_t (*get_time_ms)(void); 113 void (*poll_data_sources_from_irq)(void); 114 void (*execute_on_main_thread)(btstack_context_callback_registration_t * callback_registration); 115 void (*trigger_exit)(void); 116 } btstack_run_loop_t; 117 118 119 /* 120 * BTstack Run Loop Base Implementation 121 * Portable implementation of timer and data source management as base for platform specific implementations 122 */ 123 124 // private data (access only by run loop implementations) 125 extern btstack_linked_list_t btstack_run_loop_base_timers; 126 extern btstack_linked_list_t btstack_run_loop_base_data_sources; 127 128 /** 129 * @brief Init 130 */ 131 void btstack_run_loop_base_init(void); 132 133 /** 134 * @brief Add timer source. 135 * @param timer to add 136 */ 137 void btstack_run_loop_base_add_timer(btstack_timer_source_t * timer); 138 139 /** 140 * @brief Remove timer source. 141 * @param timer to remove 142 * @returns true if timer was removed 143 */ 144 bool btstack_run_loop_base_remove_timer(btstack_timer_source_t * timer); 145 146 /** 147 * @brief Process timers: remove expired timers from list and call their process function 148 * @param now 149 */ 150 void btstack_run_loop_base_process_timers(uint32_t now); 151 152 /** 153 * @brief Dump list of timers via log_info 154 */ 155 void btstack_run_loop_base_dump_timer(void); 156 157 /** 158 * @brief Get time until first timer fires 159 * @returns -1 if no timers, time until next timeout otherwise 160 */ 161 int32_t btstack_run_loop_base_get_time_until_timeout(uint32_t now); 162 163 /** 164 * @brief Add data source to run loop 165 * @param data_source to add 166 */ 167 void btstack_run_loop_base_add_data_source(btstack_data_source_t * data_source); 168 169 /** 170 * @brief Remove data source from run loop 171 * @param data_source to remove 172 * @returns true if data srouce was removed 173 */ 174 bool btstack_run_loop_base_remove_data_source(btstack_data_source_t * data_source); 175 176 /** 177 * @brief Enable callbacks for a data source 178 * @param data_source to remove 179 * @param callback_types to enable 180 */ 181 void btstack_run_loop_base_enable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callback_types); 182 183 /** 184 * @brief Enable callbacks for a data source 185 * @param data_source to remove 186 * @param callback_types to disable 187 */ 188 void btstack_run_loop_base_disable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callback_types); 189 190 /** 191 * @brief Poll data sources. It calls the procss function for all data sources where DATA_SOURCE_CALLBACK_POLL is set 192 */ 193 void btstack_run_loop_base_poll_data_sources(void); 194 195 196 /* API_START */ 197 198 /** 199 * @brief Init main run loop. Must be called before any other run loop call. 200 * 201 * Use btstack_run_loop_$(btstack_run_loop_TYPE)_get_instance() from btstack_run_loop_$(btstack_run_loop_TYPE).h to get instance 202 */ 203 void btstack_run_loop_init(const btstack_run_loop_t * run_loop); 204 205 /** 206 * @brief Set timer based on current time in milliseconds. 207 */ 208 void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms); 209 210 /** 211 * @brief Set callback that will be executed when timer expires. 212 */ 213 void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)); 214 215 /** 216 * @brief Set context for this timer 217 */ 218 void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context); 219 220 /** 221 * @brief Get context for this timer 222 */ 223 void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer); 224 225 /** 226 * @brief Add timer source. 227 */ 228 void btstack_run_loop_add_timer(btstack_timer_source_t * timer); 229 230 /** 231 * @brief Remove timer source. 232 */ 233 int btstack_run_loop_remove_timer(btstack_timer_source_t * timer); 234 235 /** 236 * @brief Get current time in ms 237 * @note 32-bit ms counter will overflow after approx. 52 days 238 */ 239 uint32_t btstack_run_loop_get_time_ms(void); 240 241 /** 242 * @brief Dump timers using log_info 243 */ 244 void btstack_run_loop_timer_dump(void); 245 246 247 /** 248 * @brief Set data source callback. 249 */ 250 void btstack_run_loop_set_data_source_handler(btstack_data_source_t * data_source, void (*process)(btstack_data_source_t * _data_source, btstack_data_source_callback_type_t callback_type)); 251 252 /** 253 * @brief Set data source file descriptor. 254 * @param data_source 255 * @param fd file descriptor 256 * @note No effect if port doensn't have file descriptors 257 */ 258 void btstack_run_loop_set_data_source_fd(btstack_data_source_t * data_source, int fd); 259 260 /** 261 * @brief Get data source file descriptor. 262 * @param data_source 263 */ 264 int btstack_run_loop_get_data_source_fd(btstack_data_source_t * data_source); 265 266 /** 267 * @brief Set data source file descriptor. 268 * @param data_source 269 * @param handle 270 * @note No effect if port doensn't have file descriptors 271 */ 272 void btstack_run_loop_set_data_source_handle(btstack_data_source_t * data_source, void * handle); 273 274 /** 275 * @brief Get data source file descriptor. 276 * @param data_source 277 */ 278 void * btstack_run_loop_get_data_source_handle(btstack_data_source_t * data_source); 279 280 /** 281 * @brief Enable callbacks for a data source 282 * @param data_source to remove 283 * @param callback types to enable 284 */ 285 void btstack_run_loop_enable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks); 286 287 /** 288 * @brief Enable callbacks for a data source 289 * @param data_source to remove 290 * @param callback types to disable 291 */ 292 void btstack_run_loop_disable_data_source_callbacks(btstack_data_source_t * data_source, uint16_t callbacks); 293 294 /** 295 * @brief Add data source to run loop 296 * @param data_source to add 297 */ 298 void btstack_run_loop_add_data_source(btstack_data_source_t * data_source); 299 300 /** 301 * @brief Remove data source from run loop 302 * @param data_source to remove 303 */ 304 int btstack_run_loop_remove_data_source(btstack_data_source_t * data_source); 305 306 /** 307 * @brief Poll data sources - called only from IRQ context 308 * @note Can be used to trigger processing of received peripheral data on the main thread 309 * by registering a data source with DATA_SOURCE_CALLBACK_POLL and calling this 310 * function from the IRQ handler. 311 */ 312 void btstack_run_loop_poll_data_sources_from_irq(void); 313 314 315 /** 316 * @brief Execute configured run loop. This function does not return. 317 */ 318 void btstack_run_loop_execute(void); 319 320 /** 321 * @brief Registers callback with run loop and mark main thread as ready 322 * @note Callback can only be registered once 323 * @param callback_registration 324 */ 325 void btstack_run_loop_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration); 326 327 /** 328 * @brief Trigger exit of active run loop (started via btstack_run_loop_execute) if possible 329 * @note This is only supported if there's a loop in the btstack_run_loop_execute function. 330 * It is not supported if timers and data sources are only mapped to RTOS equivalents, e.g. 331 * in the Qt or Core Foundation implementations. 332 */ 333 void btstack_run_loop_trigger_exit(void); 334 335 336 /** 337 * @brief De-Init Run Loop 338 */ 339 void btstack_run_loop_deinit(void); 340 341 /* API_END */ 342 343 344 #if defined __cplusplus 345 } 346 #endif 347 348 #endif // BTSTACK_RUN_LOOP_H 349