1e25b4a2fSMatthias Ringwald /* 2e25b4a2fSMatthias Ringwald * Copyright (C) 2015 BlueKitchen GmbH 3e25b4a2fSMatthias Ringwald * 4e25b4a2fSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5e25b4a2fSMatthias Ringwald * modification, are permitted provided that the following conditions 6e25b4a2fSMatthias Ringwald * are met: 7e25b4a2fSMatthias Ringwald * 8e25b4a2fSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9e25b4a2fSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10e25b4a2fSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11e25b4a2fSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12e25b4a2fSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13e25b4a2fSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14e25b4a2fSMatthias Ringwald * contributors may be used to endorse or promote products derived 15e25b4a2fSMatthias Ringwald * from this software without specific prior written permission. 16e25b4a2fSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17e25b4a2fSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18e25b4a2fSMatthias Ringwald * monetary gain. 19e25b4a2fSMatthias Ringwald * 20e25b4a2fSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21e25b4a2fSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22e25b4a2fSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23e25b4a2fSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24e25b4a2fSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25e25b4a2fSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26e25b4a2fSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27e25b4a2fSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28e25b4a2fSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29e25b4a2fSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30e25b4a2fSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31e25b4a2fSMatthias Ringwald * SUCH DAMAGE. 32e25b4a2fSMatthias Ringwald * 33e25b4a2fSMatthias Ringwald * Please inquire about commercial licensing options at 34e25b4a2fSMatthias Ringwald * [email protected] 35e25b4a2fSMatthias Ringwald * 36e25b4a2fSMatthias Ringwald */ 37e25b4a2fSMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_run_loop_wiced.c" 39e25b4a2fSMatthias Ringwald 40e25b4a2fSMatthias Ringwald /* 41e25b4a2fSMatthias Ringwald * btstack_run_loop_wiced.c 42e25b4a2fSMatthias Ringwald * 43e25b4a2fSMatthias Ringwald * Run loop for Broadcom WICED SDK which currently supports FreeRTOS and ThreadX 44e25b4a2fSMatthias Ringwald * WICED 3.3.1 does not support Event Flags on FreeRTOS so a queue is used instead 45e25b4a2fSMatthias Ringwald */ 46e25b4a2fSMatthias Ringwald 47e25b4a2fSMatthias Ringwald #include "wiced.h" 48e25b4a2fSMatthias Ringwald 4985ce275aSMatthias Ringwald #include "btstack_run_loop_wiced.h" 50e25b4a2fSMatthias Ringwald 51e25b4a2fSMatthias Ringwald #include "btstack_linked_list.h" 52e25b4a2fSMatthias Ringwald #include "btstack_debug.h" 5385ce275aSMatthias Ringwald #include "btstack_util.h" 54e25b4a2fSMatthias Ringwald #include "btstack_run_loop.h" 5585ce275aSMatthias Ringwald 5685ce275aSMatthias Ringwald #include <stddef.h> // NULL 57e25b4a2fSMatthias Ringwald 58e25b4a2fSMatthias Ringwald typedef struct function_call { 59e25b4a2fSMatthias Ringwald wiced_result_t (*fn)(void * arg); 60e25b4a2fSMatthias Ringwald void * arg; 61e25b4a2fSMatthias Ringwald } function_call_t; 62e25b4a2fSMatthias Ringwald 63e25b4a2fSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_wiced; 64e25b4a2fSMatthias Ringwald 65e25b4a2fSMatthias Ringwald static wiced_queue_t btstack_run_loop_queue; 66e25b4a2fSMatthias Ringwald 67e25b4a2fSMatthias Ringwald // the run loop 68e25b4a2fSMatthias Ringwald static btstack_linked_list_t timers; 69e25b4a2fSMatthias Ringwald 70e25b4a2fSMatthias Ringwald static uint32_t btstack_run_loop_wiced_get_time_ms(void){ 71e25b4a2fSMatthias Ringwald wiced_time_t time; 72e25b4a2fSMatthias Ringwald wiced_time_get_time(&time); 73e25b4a2fSMatthias Ringwald return time; 74e25b4a2fSMatthias Ringwald } 75e25b4a2fSMatthias Ringwald 76e25b4a2fSMatthias Ringwald // set timer 77e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){ 78e25b4a2fSMatthias Ringwald ts->timeout = btstack_run_loop_wiced_get_time_ms() + timeout_in_ms + 1; 79e25b4a2fSMatthias Ringwald } 80e25b4a2fSMatthias Ringwald 81e25b4a2fSMatthias Ringwald /** 82e25b4a2fSMatthias Ringwald * Add timer to run_loop (keep list sorted) 83e25b4a2fSMatthias Ringwald */ 84e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_add_timer(btstack_timer_source_t *ts){ 85e25b4a2fSMatthias Ringwald btstack_linked_item_t *it; 86e25b4a2fSMatthias Ringwald for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){ 87e25b4a2fSMatthias Ringwald // don't add timer that's already in there 888291be95SMatthias Ringwald btstack_timer_source_t * next = (btstack_timer_source_t *) it->next; 898291be95SMatthias Ringwald if (next == ts){ 90e25b4a2fSMatthias Ringwald log_error( "btstack_run_loop_timer_add error: timer to add already in list!"); 91e25b4a2fSMatthias Ringwald return; 92e25b4a2fSMatthias Ringwald } 9385ce275aSMatthias Ringwald // exit if new timeout before list timeout 9485ce275aSMatthias Ringwald int32_t delta = btstack_time_delta(ts->timeout, next->timeout); 9585ce275aSMatthias Ringwald if (delta < 0) break; 96e25b4a2fSMatthias Ringwald } 97e25b4a2fSMatthias Ringwald ts->item.next = it->next; 98e25b4a2fSMatthias Ringwald it->next = (btstack_linked_item_t *) ts; 99e25b4a2fSMatthias Ringwald } 100e25b4a2fSMatthias Ringwald 101e25b4a2fSMatthias Ringwald /** 102e25b4a2fSMatthias Ringwald * Remove timer from run loop 103e25b4a2fSMatthias Ringwald */ 104d58a1b5fSMatthias Ringwald static bool btstack_run_loop_wiced_remove_timer(btstack_timer_source_t *ts){ 105e25b4a2fSMatthias Ringwald return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts); 106e25b4a2fSMatthias Ringwald } 107e25b4a2fSMatthias Ringwald 108e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_dump_timer(void){ 109e25b4a2fSMatthias Ringwald #ifdef ENABLE_LOG_INFO 110e25b4a2fSMatthias Ringwald btstack_linked_item_t *it; 111e25b4a2fSMatthias Ringwald int i = 0; 112e25b4a2fSMatthias Ringwald for (it = (btstack_linked_item_t *) timers; it ; it = it->next){ 113e25b4a2fSMatthias Ringwald btstack_timer_source_t *ts = (btstack_timer_source_t*) it; 114e25b4a2fSMatthias Ringwald log_info("timer %u, timeout %u\n", i, (unsigned int) ts->timeout); 115e25b4a2fSMatthias Ringwald } 116e25b4a2fSMatthias Ringwald #endif 117e25b4a2fSMatthias Ringwald } 118e25b4a2fSMatthias Ringwald 119e25b4a2fSMatthias Ringwald // schedules execution similar to wiced_rtos_send_asynchronous_event for worker threads 120e25b4a2fSMatthias Ringwald void btstack_run_loop_wiced_execute_code_on_main_thread(wiced_result_t (*fn)(void *arg), void * arg){ 121e25b4a2fSMatthias Ringwald function_call_t message; 122e25b4a2fSMatthias Ringwald message.fn = fn; 123e25b4a2fSMatthias Ringwald message.arg = arg; 124e25b4a2fSMatthias Ringwald wiced_rtos_push_to_queue(&btstack_run_loop_queue, &message, WICED_NEVER_TIMEOUT); 125e25b4a2fSMatthias Ringwald } 126e25b4a2fSMatthias Ringwald 127e25b4a2fSMatthias Ringwald /** 128e25b4a2fSMatthias Ringwald * Execute run_loop 129e25b4a2fSMatthias Ringwald */ 130e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_execute(void) { 131*ff3cc4a5SMatthias Ringwald while (true) { 132e25b4a2fSMatthias Ringwald // get next timeout 133e25b4a2fSMatthias Ringwald uint32_t timeout_ms = WICED_NEVER_TIMEOUT; 134e25b4a2fSMatthias Ringwald if (timers) { 135e25b4a2fSMatthias Ringwald btstack_timer_source_t * ts = (btstack_timer_source_t *) timers; 136e25b4a2fSMatthias Ringwald uint32_t now = btstack_run_loop_wiced_get_time_ms(); 13785ce275aSMatthias Ringwald int32_t delta_ms = btstack_time_delta(ts->timeout, now); 13885ce275aSMatthias Ringwald if (delta_ms <= 0){ 139e25b4a2fSMatthias Ringwald // remove timer before processing it to allow handler to re-register with run loop 140b7832c7fSMatthias Ringwald btstack_run_loop_wiced_remove_timer(ts); 141e25b4a2fSMatthias Ringwald ts->process(ts); 142e25b4a2fSMatthias Ringwald continue; 143e25b4a2fSMatthias Ringwald } 14485ce275aSMatthias Ringwald timeout_ms = delta_ms; 145e25b4a2fSMatthias Ringwald } 146e25b4a2fSMatthias Ringwald 147e25b4a2fSMatthias Ringwald // pop function call 148e25b4a2fSMatthias Ringwald function_call_t message = { NULL, NULL }; 149e25b4a2fSMatthias Ringwald wiced_rtos_pop_from_queue( &btstack_run_loop_queue, &message, timeout_ms); 150e25b4a2fSMatthias Ringwald if (message.fn){ 151e25b4a2fSMatthias Ringwald // execute code on run loop 152e25b4a2fSMatthias Ringwald message.fn(message.arg); 153e25b4a2fSMatthias Ringwald } 154e25b4a2fSMatthias Ringwald } 155e25b4a2fSMatthias Ringwald } 156e25b4a2fSMatthias Ringwald 157e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_btstack_run_loop_init(void){ 158e25b4a2fSMatthias Ringwald timers = NULL; 159e25b4a2fSMatthias Ringwald 160e25b4a2fSMatthias Ringwald // queue to receive events: up to 2 calls from transport, up to 3 for app 161e25b4a2fSMatthias Ringwald wiced_rtos_init_queue(&btstack_run_loop_queue, "BTstack Run Loop", sizeof(function_call_t), 5); 162e25b4a2fSMatthias Ringwald } 163e25b4a2fSMatthias Ringwald 164e25b4a2fSMatthias Ringwald /** 165e25b4a2fSMatthias Ringwald * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init 166e25b4a2fSMatthias Ringwald */ 167e25b4a2fSMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_wiced_get_instance(void){ 168e25b4a2fSMatthias Ringwald return &btstack_run_loop_wiced; 169e25b4a2fSMatthias Ringwald } 170e25b4a2fSMatthias Ringwald 171e25b4a2fSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_wiced = { 172e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_btstack_run_loop_init, 173e25b4a2fSMatthias Ringwald NULL, 174e25b4a2fSMatthias Ringwald NULL, 175e25b4a2fSMatthias Ringwald NULL, 176e25b4a2fSMatthias Ringwald NULL, 177e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_set_timer, 178e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_add_timer, 179e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_remove_timer, 180e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_execute, 181e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_dump_timer, 182e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_get_time_ms, 183e25b4a2fSMatthias Ringwald }; 184