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