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 38*e501bae0SMatthias 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 49e25b4a2fSMatthias Ringwald #include <stddef.h> // NULL 50e25b4a2fSMatthias Ringwald 51e25b4a2fSMatthias Ringwald #include "btstack_linked_list.h" 52e25b4a2fSMatthias Ringwald #include "btstack_debug.h" 53e25b4a2fSMatthias Ringwald #include "btstack_run_loop.h" 54e25b4a2fSMatthias Ringwald #include "btstack_run_loop_wiced.h" 55e25b4a2fSMatthias Ringwald 56e25b4a2fSMatthias Ringwald typedef struct function_call { 57e25b4a2fSMatthias Ringwald wiced_result_t (*fn)(void * arg); 58e25b4a2fSMatthias Ringwald void * arg; 59e25b4a2fSMatthias Ringwald } function_call_t; 60e25b4a2fSMatthias Ringwald 61e25b4a2fSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_wiced; 62e25b4a2fSMatthias Ringwald 63e25b4a2fSMatthias Ringwald static wiced_queue_t btstack_run_loop_queue; 64e25b4a2fSMatthias Ringwald 65e25b4a2fSMatthias Ringwald // the run loop 66e25b4a2fSMatthias Ringwald static btstack_linked_list_t timers; 67e25b4a2fSMatthias Ringwald 68e25b4a2fSMatthias Ringwald static uint32_t btstack_run_loop_wiced_get_time_ms(void){ 69e25b4a2fSMatthias Ringwald wiced_time_t time; 70e25b4a2fSMatthias Ringwald wiced_time_get_time(&time); 71e25b4a2fSMatthias Ringwald return time; 72e25b4a2fSMatthias Ringwald } 73e25b4a2fSMatthias Ringwald 74e25b4a2fSMatthias Ringwald // set timer 75e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){ 76e25b4a2fSMatthias Ringwald ts->timeout = btstack_run_loop_wiced_get_time_ms() + timeout_in_ms + 1; 77e25b4a2fSMatthias Ringwald } 78e25b4a2fSMatthias Ringwald 79e25b4a2fSMatthias Ringwald /** 80e25b4a2fSMatthias Ringwald * Add timer to run_loop (keep list sorted) 81e25b4a2fSMatthias Ringwald */ 82e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_add_timer(btstack_timer_source_t *ts){ 83e25b4a2fSMatthias Ringwald btstack_linked_item_t *it; 84e25b4a2fSMatthias Ringwald for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){ 85e25b4a2fSMatthias Ringwald // don't add timer that's already in there 86e25b4a2fSMatthias Ringwald if ((btstack_timer_source_t *) it->next == ts){ 87e25b4a2fSMatthias Ringwald log_error( "btstack_run_loop_timer_add error: timer to add already in list!"); 88e25b4a2fSMatthias Ringwald return; 89e25b4a2fSMatthias Ringwald } 90e25b4a2fSMatthias Ringwald if (ts->timeout < ((btstack_timer_source_t *) it->next)->timeout) { 91e25b4a2fSMatthias Ringwald break; 92e25b4a2fSMatthias Ringwald } 93e25b4a2fSMatthias Ringwald } 94e25b4a2fSMatthias Ringwald ts->item.next = it->next; 95e25b4a2fSMatthias Ringwald it->next = (btstack_linked_item_t *) ts; 96e25b4a2fSMatthias Ringwald } 97e25b4a2fSMatthias Ringwald 98e25b4a2fSMatthias Ringwald /** 99e25b4a2fSMatthias Ringwald * Remove timer from run loop 100e25b4a2fSMatthias Ringwald */ 101e25b4a2fSMatthias Ringwald static int btstack_run_loop_wiced_remove_timer(btstack_timer_source_t *ts){ 102e25b4a2fSMatthias Ringwald return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts); 103e25b4a2fSMatthias Ringwald } 104e25b4a2fSMatthias Ringwald 105e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_dump_timer(void){ 106e25b4a2fSMatthias Ringwald #ifdef ENABLE_LOG_INFO 107e25b4a2fSMatthias Ringwald btstack_linked_item_t *it; 108e25b4a2fSMatthias Ringwald int i = 0; 109e25b4a2fSMatthias Ringwald for (it = (btstack_linked_item_t *) timers; it ; it = it->next){ 110e25b4a2fSMatthias Ringwald btstack_timer_source_t *ts = (btstack_timer_source_t*) it; 111e25b4a2fSMatthias Ringwald log_info("timer %u, timeout %u\n", i, (unsigned int) ts->timeout); 112e25b4a2fSMatthias Ringwald } 113e25b4a2fSMatthias Ringwald #endif 114e25b4a2fSMatthias Ringwald } 115e25b4a2fSMatthias Ringwald 116e25b4a2fSMatthias Ringwald // schedules execution similar to wiced_rtos_send_asynchronous_event for worker threads 117e25b4a2fSMatthias Ringwald void btstack_run_loop_wiced_execute_code_on_main_thread(wiced_result_t (*fn)(void *arg), void * arg){ 118e25b4a2fSMatthias Ringwald function_call_t message; 119e25b4a2fSMatthias Ringwald message.fn = fn; 120e25b4a2fSMatthias Ringwald message.arg = arg; 121e25b4a2fSMatthias Ringwald wiced_rtos_push_to_queue(&btstack_run_loop_queue, &message, WICED_NEVER_TIMEOUT); 122e25b4a2fSMatthias Ringwald } 123e25b4a2fSMatthias Ringwald 124e25b4a2fSMatthias Ringwald /** 125e25b4a2fSMatthias Ringwald * Execute run_loop 126e25b4a2fSMatthias Ringwald */ 127e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_execute(void) { 128e25b4a2fSMatthias Ringwald while (1) { 129e25b4a2fSMatthias Ringwald // get next timeout 130e25b4a2fSMatthias Ringwald uint32_t timeout_ms = WICED_NEVER_TIMEOUT; 131e25b4a2fSMatthias Ringwald if (timers) { 132e25b4a2fSMatthias Ringwald btstack_timer_source_t * ts = (btstack_timer_source_t *) timers; 133e25b4a2fSMatthias Ringwald uint32_t now = btstack_run_loop_wiced_get_time_ms(); 134e25b4a2fSMatthias Ringwald if (ts->timeout < now){ 135e25b4a2fSMatthias Ringwald // remove timer before processing it to allow handler to re-register with run loop 136b7832c7fSMatthias Ringwald btstack_run_loop_wiced_remove_timer(ts); 137e25b4a2fSMatthias Ringwald // printf("RL: timer %p\n", ts->process); 138e25b4a2fSMatthias Ringwald ts->process(ts); 139e25b4a2fSMatthias Ringwald continue; 140e25b4a2fSMatthias Ringwald } 141e25b4a2fSMatthias Ringwald timeout_ms = ts->timeout - now; 142e25b4a2fSMatthias Ringwald } 143e25b4a2fSMatthias Ringwald 144e25b4a2fSMatthias Ringwald // pop function call 145e25b4a2fSMatthias Ringwald function_call_t message = { NULL, NULL }; 146e25b4a2fSMatthias Ringwald wiced_rtos_pop_from_queue( &btstack_run_loop_queue, &message, timeout_ms); 147e25b4a2fSMatthias Ringwald if (message.fn){ 148e25b4a2fSMatthias Ringwald // execute code on run loop 149e25b4a2fSMatthias Ringwald // printf("RL: execute %p\n", message.fn); 150e25b4a2fSMatthias Ringwald message.fn(message.arg); 151e25b4a2fSMatthias Ringwald } 152e25b4a2fSMatthias Ringwald } 153e25b4a2fSMatthias Ringwald } 154e25b4a2fSMatthias Ringwald 155e25b4a2fSMatthias Ringwald static void btstack_run_loop_wiced_btstack_run_loop_init(void){ 156e25b4a2fSMatthias Ringwald timers = NULL; 157e25b4a2fSMatthias Ringwald 158e25b4a2fSMatthias Ringwald // queue to receive events: up to 2 calls from transport, up to 3 for app 159e25b4a2fSMatthias Ringwald wiced_rtos_init_queue(&btstack_run_loop_queue, "BTstack Run Loop", sizeof(function_call_t), 5); 160e25b4a2fSMatthias Ringwald } 161e25b4a2fSMatthias Ringwald 162e25b4a2fSMatthias Ringwald /** 163e25b4a2fSMatthias Ringwald * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init 164e25b4a2fSMatthias Ringwald */ 165e25b4a2fSMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_wiced_get_instance(void){ 166e25b4a2fSMatthias Ringwald return &btstack_run_loop_wiced; 167e25b4a2fSMatthias Ringwald } 168e25b4a2fSMatthias Ringwald 169e25b4a2fSMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_wiced = { 170e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_btstack_run_loop_init, 171e25b4a2fSMatthias Ringwald NULL, 172e25b4a2fSMatthias Ringwald NULL, 173e25b4a2fSMatthias Ringwald NULL, 174e25b4a2fSMatthias Ringwald NULL, 175e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_set_timer, 176e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_add_timer, 177e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_remove_timer, 178e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_execute, 179e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_dump_timer, 180e25b4a2fSMatthias Ringwald &btstack_run_loop_wiced_get_time_ms, 181e25b4a2fSMatthias Ringwald }; 182