/******************************************************************************* ** ** Function GKI_isend_event ** ** Description This function is called from ISRs to send events to other ** tasks. The only difference between this function and GKI_send_event ** is that this function assumes interrupts are already disabled. ** ** Parameters: task_id - (input) The destination task Id for the event. ** event - (input) The event flag ** ** Returns GKI_SUCCESS if all OK, else GKI_FAILURE ** ** NOTE This function is NOT called by the Widcomm stack and ** profiles. If you want to use it in your own implementation, ** put your code here, otherwise you can delete the entire ** body of the function. ** *******************************************************************************/ UINT8 GKI_isend_event (UINT8 task_id, UINT16 event) { GKI_TRACE_2("GKI_isend_event %d %x", task_id, event); GKI_TRACE_2("GKI_isend_event %d %x done", task_id, event); return GKI_send_event(task_id, event); }
/******************************************************************************* ** ** Function nfc_hal_main_userial_cback ** ** Description USERIAL callback for NCI transport ** ** Returns nothing ** *******************************************************************************/ static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data) { if (evt == USERIAL_RX_READY_EVT) { /* Notify transport task of serial port event */ GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY); } else if (evt == USERIAL_TX_DONE_EVT) { /* Serial driver has finshed sending data from USERIAL_Write */ /* Currently, no action is needed for this event */ } else if (evt == USERIAL_ERR_EVT) { HAL_TRACE_ERROR0 ("nfc_hal_main_userial_cback: USERIAL_ERR_EVT. Notifying NFC_TASK of transport error"); if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE) { nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); nfc_hal_nci_cmd_timeout_cback ((void *)&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); } else { nfc_hal_main_send_error (HAL_NFC_STATUS_ERR_TRANSPORT); } } else if (evt == USERIAL_WAKEUP_EVT) { HAL_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: USERIAL_WAKEUP_EVT: %d", p_data->sigs); } else { HAL_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: unhandled userial evt: %i", evt); } }
void GKI_destroy_task(UINT8 task_id) { #if ( FALSE == GKI_PTHREAD_JOINABLE ) int i = 0; #else int result; #endif if (gki_cb.com.OSRdyTbl[task_id] != TASK_DEAD) { gki_cb.com.OSRdyTbl[task_id] = TASK_DEAD; /* paranoi settings, make sure that we do not execute any mailbox events */ gki_cb.com.OSWaitEvt[task_id] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); #if (GKI_NUM_TIMERS > 0) gki_cb.com.OSTaskTmr0R[task_id] = 0; gki_cb.com.OSTaskTmr0 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 1) gki_cb.com.OSTaskTmr1R[task_id] = 0; gki_cb.com.OSTaskTmr1 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 2) gki_cb.com.OSTaskTmr2R[task_id] = 0; gki_cb.com.OSTaskTmr2 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 3) gki_cb.com.OSTaskTmr3R[task_id] = 0; gki_cb.com.OSTaskTmr3 [task_id] = 0; #endif GKI_send_event(task_id, EVENT_MASK(GKI_SHUTDOWN_EVT)); #if ( FALSE == GKI_PTHREAD_JOINABLE ) i = 0; while ((gki_cb.com.OSWaitEvt[task_id] != 0) && (++i < 10)) usleep(100 * 1000); #else result = pthread_join( gki_cb.os.thread_id[task_id], NULL ); if ( result < 0 ) { GKI_ERROR_LOG( "pthread_join() FAILED: result: %d", result ); } #endif GKI_exit_task(task_id); GKI_INFO( "GKI_shutdown(): task [%s] terminated\n", gki_cb.com.OSTName[task_id]); } }
/****************************************************************************** ** ** Function preload_cb ** ** Description HOST/CONTROLLER LIB CALLBACK API - This function is called ** when the libbt-hci completed stack preload process ** ** Returns None ** ******************************************************************************/ static void preload_cb(TRANSAC transac, bt_hc_preload_result_t result) { APPL_TRACE_EVENT1("HC preload_cb %d [0:SUCCESS 1:FAIL]", result); if (result == BT_HC_PRELOAD_SUCCESS) { preload_stop_wait_timer(); /* notify BTU task that libbt-hci is ready */ GKI_send_event(BTU_TASK, BT_EVT_PRELOAD_CMPL); } }
/******************************************************************************* ** ** Function GKI_send_msg ** ** Description Called by applications to send a buffer to a task ** ** Returns Nothing ** *******************************************************************************/ void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg) { BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; /* If task non-existant or not started, drop buffer */ if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) { GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest"); GKI_freebuf (msg); return; } #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) if (gki_chk_buf_damage(msg)) { GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted"); return; } #endif p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE); if (p_hdr->status != BUF_STATUS_UNLINKED) { GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked"); return; } GKI_disable(); if (p_cb->OSTaskQFirst[task_id][mbox]) p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr; else p_cb->OSTaskQFirst[task_id][mbox] = p_hdr; p_cb->OSTaskQLast[task_id][mbox] = p_hdr; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_QUEUED; p_hdr->task_id = task_id; GKI_enable(); GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox)); return; }
/******************************************************************************* ** ** Function preload_wait_timeout ** ** Description Timeout thread of preload watchdog timer ** ** Returns None ** *******************************************************************************/ static void preload_wait_timeout(union sigval arg) { APPL_TRACE_ERROR2("...preload_wait_timeout (retried:%d/max-retry:%d)...", preload_retry_cb.retry_counts, PRELOAD_MAX_RETRY_ATTEMPTS); if (preload_retry_cb.retry_counts++ < PRELOAD_MAX_RETRY_ATTEMPTS) { bte_hci_disable(); GKI_delay(100); bte_hci_enable(); } else { /* Notify BTIF_TASK that the init procedure had failed*/ GKI_send_event(BTIF_TASK, BT_EVT_HARDWARE_INIT_FAIL); } }
/******************************************************************************* ** ** Function GKI_timer_update ** ** Description This function is called by an OS to drive the GKI's timers. ** It is typically called at every system tick to ** update the timers for all tasks, and check for timeouts. ** ** Note: It has been designed to also allow for variable tick updates ** so that systems with strict power savings requirements can ** have the update occur at variable intervals. ** ** Parameters: ticks_since_last_update - (input) This is the number of TICKS that have ** occurred since the last time GKI_timer_update was called. ** ** Returns void ** *******************************************************************************/ void GKI_timer_update (INT32 ticks_since_last_update) { UINT8 task_id; long next_expiration; /* Holds the next soonest expiration time after this update */ /* Increment the number of ticks used for time stamps */ gki_cb.com.OSTicks += ticks_since_last_update; /* If any timers are running in any tasks, decrement the remaining time til * the timer updates need to take place (next expiration occurs) */ gki_cb.com.OSTicksTilExp -= ticks_since_last_update; /* Don't allow timer interrupt nesting */ if (gki_cb.com.timer_nesting) return; gki_cb.com.timer_nesting = 1; #if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) /* if inactivity delay timer is set and expired */ if (gki_cb.com.OSTicksTilStop) { if( gki_cb.com.OSTicksTilStop <= (UINT32)ticks_since_last_update ) { if(gki_cb.com.p_tick_cb) { gki_cb.com.system_tick_running = FALSE; (gki_cb.com.p_tick_cb) (FALSE); /* stop system tick */ } gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */ gki_cb.com.timer_nesting = 0; return; } else gki_cb.com.OSTicksTilStop -= ticks_since_last_update; } #endif /* No need to update the ticks if no timeout has occurred */ if (gki_cb.com.OSTicksTilExp > 0) { gki_cb.com.timer_nesting = 0; return; } GKI_disable(); next_expiration = GKI_NO_NEW_TMRS_STARTED; /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks to account for the difference so timer updates below are decremented by the full number of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this value only affects the timer updates below */ gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp; /* Check for OS Task Timers */ for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) { if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */ { gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSWaitTmr[task_id] <= 0) { /* Timer Expired */ gki_cb.com.OSRdyTbl[task_id] = TASK_READY; } } #if (GKI_NUM_TIMERS > 0) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr0[task_id] > 0) { gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr0[task_id] <= 0) { /* Set Timer 0 Expired event mask and reload timer */ #if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) GKI_isend_event (task_id, TIMER_0_EVT_MASK); #else GKI_send_event (task_id, TIMER_0_EVT_MASK); #endif gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr0[task_id]; #endif #if (GKI_NUM_TIMERS > 1) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr1[task_id] > 0) { gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr1[task_id] <= 0) { /* Set Timer 1 Expired event mask and reload timer */ #if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) GKI_isend_event (task_id, TIMER_1_EVT_MASK); #else GKI_send_event (task_id, TIMER_1_EVT_MASK); #endif gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id]; } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr1[task_id]; #endif #if (GKI_NUM_TIMERS > 2) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr2[task_id] > 0) { gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr2[task_id] <= 0) { /* Set Timer 2 Expired event mask and reload timer */ #if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) GKI_isend_event (task_id, TIMER_2_EVT_MASK); #else GKI_send_event (task_id, TIMER_2_EVT_MASK); #endif gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id]; } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr2[task_id]; #endif #if (GKI_NUM_TIMERS > 3) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr3[task_id] > 0) { gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr3[task_id] <= 0) { /* Set Timer 3 Expired event mask and reload timer */ #if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) GKI_isend_event (task_id, TIMER_3_EVT_MASK); #else GKI_send_event (task_id, TIMER_3_EVT_MASK); #endif gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id]; } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr3[task_id]; #endif } /* Set the next timer experation value if there is one to start */ if (next_expiration < GKI_NO_NEW_TMRS_STARTED) { gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration; } else { gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0; } gki_cb.com.timer_nesting = 0; GKI_enable(); return; }
void GKI_shutdown(void) { UINT8 task_id; #if ( FALSE == GKI_PTHREAD_JOINABLE ) int i = 0; #else int result; #endif #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS gki_dealloc_free_queue(); #endif /* release threads and set as TASK_DEAD. going from low to high priority fixes * GKI_exception problem due to btu->hci sleep request events */ for (task_id = GKI_MAX_TASKS; task_id > 0; task_id--) { if (gki_cb.com.OSRdyTbl[task_id - 1] != TASK_DEAD) { gki_cb.com.OSRdyTbl[task_id - 1] = TASK_DEAD; /* paranoi settings, make sure that we do not execute any mailbox events */ gki_cb.com.OSWaitEvt[task_id-1] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); GKI_send_event(task_id - 1, EVENT_MASK(GKI_SHUTDOWN_EVT)); #if ( FALSE == GKI_PTHREAD_JOINABLE ) i = 0; while ((gki_cb.com.OSWaitEvt[task_id - 1] != 0) && (++i < 10)) usleep(100 * 1000); #else result = pthread_join( gki_cb.os.thread_id[task_id-1], NULL ); if ( result < 0 ) { ALOGE( "pthread_join() FAILED: result: %d", result ); } #endif // GKI_ERROR_LOG( "GKI_shutdown(): task %s dead\n", gki_cb.com.OSTName[task_id]); GKI_exit_task(task_id - 1); } } /* Destroy mutex and condition variable objects */ pthread_mutex_destroy(&gki_cb.os.GKI_mutex); /* pthread_mutex_destroy(&GKI_sched_mutex); */ #if (GKI_DEBUG == TRUE) pthread_mutex_destroy(&gki_cb.os.GKI_trace_mutex); #endif /* pthread_mutex_destroy(&thread_delay_mutex); pthread_cond_destroy (&thread_delay_cond); */ #if ( FALSE == GKI_PTHREAD_JOINABLE ) i = 0; #endif #ifdef NO_GKI_RUN_RETURN shutdown_timer = 1; #endif if (g_GkiTimerWakeLockOn) { GKI_TRACE("GKI_shutdown : release_wake_lock(brcm_btld)"); release_wake_lock(WAKE_LOCK_ID); g_GkiTimerWakeLockOn = 0; } }
/******************************************************************************* ** ** Function GKI_timer_update ** ** Description This function is called by an OS to drive the GKI's timers. ** It is typically called at every system tick to ** update the timers for all tasks, and check for timeouts. ** ** Note: It has been designed to also allow for variable tick updates ** so that systems with strict power savings requirements can ** have the update occur at variable intervals. ** ** Parameters: ticks_since_last_update - (input) This is the number of TICKS that have ** occurred since the last time GKI_timer_update was called. ** ** Returns void ** *******************************************************************************/ void GKI_timer_update (INT32 ticks_since_last_update) { UINT8 task_id; long next_expiration; /* Holds the next soonest expiration time after this update */ /* Increment the number of ticks used for time stamps */ gki_cb.com.OSTicks += ticks_since_last_update; /* If any timers are running in any tasks, decrement the remaining time til * the timer updates need to take place (next expiration occurs) */ gki_cb.com.OSTicksTilExp -= ticks_since_last_update; /* Don't allow timer interrupt nesting */ if (gki_cb.com.timer_nesting) return; gki_cb.com.timer_nesting = 1; /* No need to update the ticks if no timeout has occurred */ if (gki_cb.com.OSTicksTilExp > 0) { // When using alarms from AlarmService we should // always have work to be done here. ALOGE("%s no work to be done when expected work", __func__); gki_cb.com.timer_nesting = 0; return; } next_expiration = GKI_NO_NEW_TMRS_STARTED; /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks to account for the difference so timer updates below are decremented by the full number of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this value only affects the timer updates below */ gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp; /* Protect this section because if a GKI_timer_stop happens between: * - gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; * - gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; * then the timer may appear stopped while it is about to be reloaded. */ GKI_disable(); /* Check for OS Task Timers */ for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) { if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */ { gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSWaitTmr[task_id] <= 0) { /* Timer Expired */ gki_cb.com.OSRdyTbl[task_id] = TASK_READY; } } #if (GKI_NUM_TIMERS > 0) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr0[task_id] > 0) { gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr0[task_id] <= 0) { /* Reload timer and set Timer 0 Expired event mask */ gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; GKI_send_event (task_id, TIMER_0_EVT_MASK); } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr0[task_id]; #endif #if (GKI_NUM_TIMERS > 1) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr1[task_id] > 0) { gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr1[task_id] <= 0) { /* Reload timer and set Timer 1 Expired event mask */ gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id]; GKI_send_event (task_id, TIMER_1_EVT_MASK); } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr1[task_id]; #endif #if (GKI_NUM_TIMERS > 2) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr2[task_id] > 0) { gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr2[task_id] <= 0) { /* Reload timer and set Timer 2 Expired event mask */ gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id]; GKI_send_event (task_id, TIMER_2_EVT_MASK); } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr2[task_id]; #endif #if (GKI_NUM_TIMERS > 3) /* If any timer is running, decrement */ if (gki_cb.com.OSTaskTmr3[task_id] > 0) { gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks; if (gki_cb.com.OSTaskTmr3[task_id] <= 0) { /* Reload timer and set Timer 3 Expired event mask */ gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id]; GKI_send_event (task_id, TIMER_3_EVT_MASK); } } /* Check to see if this timer is the next one to expire */ if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration) next_expiration = gki_cb.com.OSTaskTmr3[task_id]; #endif } /* Set the next timer experation value if there is one to start */ if (next_expiration < GKI_NO_NEW_TMRS_STARTED) { gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration; } else { gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0; } // Set alarm service for next alarm. alarm_service_reschedule(); GKI_enable(); gki_cb.com.timer_nesting = 0; return; }
void GKI_shutdown(void) { UINT8 task_id; volatile int *p_run_cond = &gki_cb.os.no_timer_suspend; int oldCOnd = 0; #if ( FALSE == GKI_PTHREAD_JOINABLE ) int i = 0; #else int result; #endif /* release threads and set as TASK_DEAD. going from low to high priority fixes * GKI_exception problem due to btu->hci sleep request events */ for (task_id = GKI_MAX_TASKS; task_id > 0; task_id--) { if (gki_cb.com.OSRdyTbl[task_id - 1] != TASK_DEAD) { gki_cb.com.OSRdyTbl[task_id - 1] = TASK_DEAD; /* paranoi settings, make sure that we do not execute any mailbox events */ gki_cb.com.OSWaitEvt[task_id-1] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); GKI_send_event(task_id - 1, EVENT_MASK(GKI_SHUTDOWN_EVT)); #if ( FALSE == GKI_PTHREAD_JOINABLE ) i = 0; while ((gki_cb.com.OSWaitEvt[task_id - 1] != 0) && (++i < 10)) usleep(100 * 1000); #else /* wait for proper Arnold Schwarzenegger task state */ result = pthread_join( gki_cb.os.thread_id[task_id-1], NULL ); if ( result < 0 ) { GKI_TRACE_1( "pthread_join() FAILED: result: %d", result ); } #endif GKI_TRACE_1( "GKI_shutdown(): task %s dead", gki_cb.com.OSTName[task_id]); GKI_exit_task(task_id - 1); } } /* Destroy mutex and condition variable objects */ pthread_mutex_destroy(&gki_cb.os.GKI_mutex); /* pthread_mutex_destroy(&GKI_sched_mutex); */ #if (GKI_DEBUG == TRUE) pthread_mutex_destroy(&gki_cb.os.GKI_trace_mutex); #endif /* pthread_mutex_destroy(&thread_delay_mutex); pthread_cond_destroy (&thread_delay_cond); */ #if ( FALSE == GKI_PTHREAD_JOINABLE ) i = 0; #endif #ifdef NO_GKI_RUN_RETURN shutdown_timer = 1; #endif if (gki_cb.os.gki_timer_wake_lock_on) { GKI_TRACE_0("GKI_shutdown : release_wake_lock(brcm_btld)"); release_wake_lock(WAKE_LOCK_ID); gki_cb.os.gki_timer_wake_lock_on = 0; } oldCOnd = *p_run_cond; *p_run_cond = GKI_TIMER_TICK_EXIT_COND; if (oldCOnd == GKI_TIMER_TICK_STOP_COND) pthread_cond_signal( &gki_cb.os.gki_timer_cond ); }
/******************************************************************************* ** ** Function btu_task ** ** Description This is the main task of the Bluetooth Upper Layers unit. ** It sits in a loop waiting for messages, and dispatches them ** to the appropiate handlers. ** ** Returns should never return ** *******************************************************************************/ BTU_API UINT32 btu_task (UINT32 param) { UINT16 event; BT_HDR *p_msg; UINT8 i; UINT16 mask; BOOLEAN handled; #if (defined(HCISU_H4_INCLUDED) && HCISU_H4_INCLUDED == TRUE) /* wait an event that HCISU is ready */ GKI_wait(0xFFFF, 0); #endif /* Initialize the mandatory core stack control blocks (BTU, BTM, L2CAP, and SDP) */ btu_init_core(); /* Initialize any optional stack components */ BTE_InitStack(); #if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE) bta_sys_init(); #endif /* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init() * reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL */ #if ( BT_USE_TRACES==TRUE ) BTE_InitTraceLevels(); #endif /* Send a startup evt message to BTIF_TASK to kickstart the init procedure */ GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT); raise_priority_a2dp(TASK_HIGH_BTU); /* Wait for, and process, events */ for (;;) { event = GKI_wait (0xFFFF, 0); if (event & TASK_MBOX_0_EVT_MASK) { /* Process all messages in the queue */ while ((p_msg = (BT_HDR *) GKI_read_mbox (BTU_HCI_RCV_MBOX)) != NULL) { /* Determine the input message type. */ switch (p_msg->event & BT_EVT_MASK) { case BT_EVT_TO_BTU_HCI_ACL: /* All Acl Data goes to L2CAP */ l2c_rcv_acl_data (p_msg); break; case BT_EVT_TO_BTU_L2C_SEG_XMIT: /* L2CAP segment transmit complete */ l2c_link_segments_xmitted (p_msg); break; case BT_EVT_TO_BTU_HCI_SCO: #if BTM_SCO_INCLUDED == TRUE btm_route_sco_data (p_msg); break; #endif case BT_EVT_TO_BTU_HCI_EVT: btu_hcif_process_event ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg); GKI_freebuf(p_msg); #if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE) /* If host receives events which it doesn't response to, */ /* host should start idle timer to enter sleep mode. */ btu_check_bt_sleep (); #endif break; case BT_EVT_TO_BTU_HCI_CMD: btu_hcif_send_cmd ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg); break; #if (defined(OBX_INCLUDED) && OBX_INCLUDED == TRUE) #if (defined(OBX_SERVER_INCLUDED) && OBX_SERVER_INCLUDED == TRUE) case BT_EVT_TO_OBX_SR_MSG: obx_sr_proc_evt((tOBX_PORT_EVT *)(p_msg + 1)); GKI_freebuf (p_msg); break; case BT_EVT_TO_OBX_SR_L2C_MSG: obx_sr_proc_l2c_evt((tOBX_L2C_EVT_MSG *)(p_msg + 1)); GKI_freebuf (p_msg); break; #endif #if (defined(OBX_CLIENT_INCLUDED) && OBX_CLIENT_INCLUDED == TRUE) case BT_EVT_TO_OBX_CL_MSG: obx_cl_proc_evt((tOBX_PORT_EVT *)(p_msg + 1)); GKI_freebuf (p_msg); break; case BT_EVT_TO_OBX_CL_L2C_MSG: obx_cl_proc_l2c_evt((tOBX_L2C_EVT_MSG *)(p_msg + 1)); GKI_freebuf (p_msg); break; #endif #if (defined(BIP_INCLUDED) && BIP_INCLUDED == TRUE) case BT_EVT_TO_BIP_CMDS : bip_proc_btu_event(p_msg); GKI_freebuf (p_msg); break; #endif /* BIP */ #if (BPP_SND_INCLUDED == TRUE || BPP_INCLUDED == TRUE) case BT_EVT_TO_BPP_PR_CMDS: bpp_pr_proc_event(p_msg); GKI_freebuf (p_msg); break; case BT_EVT_TO_BPP_SND_CMDS: bpp_snd_proc_event(p_msg); GKI_freebuf (p_msg); break; #endif /* BPP */ #endif /* OBX */ #if (defined(SAP_SERVER_INCLUDED) && SAP_SERVER_INCLUDED == TRUE) case BT_EVT_TO_BTU_SAP : sap_proc_btu_event(p_msg); GKI_freebuf (p_msg); break; #endif /* SAP */ #if (defined(GAP_CONN_INCLUDED) && GAP_CONN_INCLUDED == TRUE && GAP_CONN_POST_EVT_INCLUDED == TRUE) case BT_EVT_TO_GAP_MSG : gap_proc_btu_event(p_msg); GKI_freebuf (p_msg); break; #endif case BT_EVT_TO_START_TIMER : /* Start free running 1 second timer for list management */ GKI_start_timer (TIMER_0, GKI_SECS_TO_TICKS (1), TRUE); GKI_freebuf (p_msg); break; #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) case BT_EVT_TO_START_QUICK_TIMER : GKI_start_timer (TIMER_2, QUICK_TIMER_TICKS, TRUE); GKI_freebuf (p_msg); break; #endif default: i = 0; mask = (UINT16) (p_msg->event & BT_EVT_MASK); handled = FALSE; for (; !handled && i < BTU_MAX_REG_EVENT; i++) { if (btu_cb.event_reg[i].event_cb == NULL) continue; if (mask == btu_cb.event_reg[i].event_range) { if (btu_cb.event_reg[i].event_cb) { btu_cb.event_reg[i].event_cb(p_msg); handled = TRUE; } } } if (handled == FALSE) GKI_freebuf (p_msg); break; } } } if (event & TIMER_0_EVT_MASK) { TIMER_LIST_ENT *p_tle; GKI_update_timer_list (&btu_cb.timer_queue, 1); while ((btu_cb.timer_queue.p_first) && (!btu_cb.timer_queue.p_first->ticks)) { p_tle = btu_cb.timer_queue.p_first; GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle); switch (p_tle->event) { case BTU_TTYPE_BTM_DEV_CTL: btm_dev_timeout(p_tle); break; case BTU_TTYPE_BTM_ACL: btm_acl_timeout(p_tle); break; case BTU_TTYPE_L2CAP_LINK: case BTU_TTYPE_L2CAP_CHNL: case BTU_TTYPE_L2CAP_HOLD: case BTU_TTYPE_L2CAP_INFO: case BTU_TTYPE_L2CAP_FCR_ACK: l2c_process_timeout (p_tle); break; case BTU_TTYPE_SDP: sdp_conn_timeout ((tCONN_CB *)p_tle->param); break; case BTU_TTYPE_BTM_RMT_NAME: btm_inq_rmt_name_failed(); break; #if (defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE) case BTU_TTYPE_RFCOMM_MFC: case BTU_TTYPE_RFCOMM_PORT: rfcomm_process_timeout (p_tle); break; #endif /* If defined(RFCOMM_INCLUDED) && RFCOMM_INCLUDED == TRUE */ #if ((defined(BNEP_INCLUDED) && BNEP_INCLUDED == TRUE)) case BTU_TTYPE_BNEP: bnep_process_timeout(p_tle); break; #endif #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) case BTU_TTYPE_AVDT_CCB_RET: case BTU_TTYPE_AVDT_CCB_RSP: case BTU_TTYPE_AVDT_CCB_IDLE: case BTU_TTYPE_AVDT_SCB_TC: avdt_process_timeout(p_tle); break; #endif #if (defined(OBX_INCLUDED) && OBX_INCLUDED == TRUE) #if (defined(OBX_CLIENT_INCLUDED) && OBX_CLIENT_INCLUDED == TRUE) case BTU_TTYPE_OBX_CLIENT_TO: obx_cl_timeout(p_tle); break; #endif #if (defined(OBX_SERVER_INCLUDED) && OBX_SERVER_INCLUDED == TRUE) case BTU_TTYPE_OBX_SERVER_TO: obx_sr_timeout(p_tle); break; case BTU_TTYPE_OBX_SVR_SESS_TO: obx_sr_sess_timeout(p_tle); break; #endif #endif #if (defined(SAP_SERVER_INCLUDED) && SAP_SERVER_INCLUDED == TRUE) case BTU_TTYPE_SAP_TO: sap_process_timeout(p_tle); break; #endif case BTU_TTYPE_BTU_CMD_CMPL: btu_hcif_cmd_timeout((UINT8)(p_tle->event - BTU_TTYPE_BTU_CMD_CMPL)); break; #if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE) case BTU_TTYPE_HID_HOST_REPAGE_TO : hidh_proc_repage_timeout(p_tle); break; #endif #if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE) case BTU_TTYPE_BLE_INQUIRY: case BTU_TTYPE_BLE_GAP_LIM_DISC: case BTU_TTYPE_BLE_RANDOM_ADDR: btm_ble_timeout(p_tle); break; case BTU_TTYPE_BLE_SCAN_PARAM_IDLE: btm_ble_scan_param_idle(); break; case BTU_TTYPE_ATT_WAIT_FOR_RSP: gatt_rsp_timeout(p_tle); break; case BTU_TTYPE_ATT_WAIT_FOR_IND_ACK: gatt_ind_ack_timeout(p_tle); break; #if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE) case BTU_TTYPE_SMP_PAIRING_CMD: smp_rsp_timeout(p_tle); break; #endif #endif #if (MCA_INCLUDED == TRUE) case BTU_TTYPE_MCA_CCB_RSP: mca_process_timeout(p_tle); break; #endif case BTU_TTYPE_USER_FUNC: { tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param; (*p_uf)(p_tle); } break; default: i = 0; handled = FALSE; for (; !handled && i < BTU_MAX_REG_TIMER; i++) { if (btu_cb.timer_reg[i].timer_cb == NULL) continue; if (btu_cb.timer_reg[i].p_tle == p_tle) { btu_cb.timer_reg[i].timer_cb(p_tle); handled = TRUE; } } break; } } /* if timer list is empty stop periodic GKI timer */ if (btu_cb.timer_queue.p_first == NULL) { GKI_stop_timer(TIMER_0); } } #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0) if (event & TIMER_2_EVT_MASK) { btu_process_quick_timer_evt(); } #endif #if (RPC_INCLUDED == TRUE) /* if RPC message queue event */ if (event & RPCGEN_MSG_EVT) { if ((p_msg = (BT_HDR *) GKI_read_mbox(RPCGEN_MSG_MBOX)) != NULL) RPCT_RpcgenMsg(p_msg); /* handle RPC message queue */ } #endif #if (defined(BTU_BTA_INCLUDED) && BTU_BTA_INCLUDED == TRUE) if (event & TASK_MBOX_2_EVT_MASK) { while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL) { bta_sys_event(p_msg); } } if (event & TIMER_1_EVT_MASK) { bta_sys_timer_update(); } #endif if (event & EVENT_MASK(APPL_EVT_7)) break; } return(0); }
/******************************************************************************* ** ** Function nfc_hal_main_task ** ** Description NFC HAL NCI transport event processing task ** ** Returns 0 ** *******************************************************************************/ UINT32 nfc_hal_main_task (UINT32 param) { UINT16 event; UINT8 byte; UINT8 num_interfaces; UINT8 *p; NFC_HDR *p_msg; BOOLEAN free_msg; HAL_TRACE_DEBUG0 ("NFC_HAL_TASK started"); /* Main loop */ while (TRUE) { event = GKI_wait (0xFFFF, 0); /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */ if (event & NFC_HAL_TASK_EVT_INITIALIZE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport..."); nfc_hal_main_open_transport (); } /* Check for terminate event */ if (event & NFC_HAL_TASK_EVT_TERMINATE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); if (nfc_hal_cb.p_stack_cback) { nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK); nfc_hal_cb.p_stack_cback = NULL; } continue; } /* Check for power cycle event */ if (event & NFC_HAL_TASK_EVT_POWER_CYCLE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); /* power cycle timeout */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE, (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000); continue; } /* NCI message ready to be sent to NFCC */ if (event & NFC_HAL_TASK_EVT_MBOX) { while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) { free_msg = TRUE; switch (p_msg->event & NFC_EVT_MASK) { case NFC_HAL_EVT_TO_NFC_NCI: nfc_hal_main_send_message (p_msg); /* do not free buffer. NCI VS code may keep it for processing later */ free_msg = FALSE; break; case NFC_HAL_EVT_POST_CORE_RESET: NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE); /* set NCI Control packet size from CORE_INIT_RSP */ p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE; p += 5; STREAM_TO_UINT8 (num_interfaces, p); p += (num_interfaces + 3); nfc_hal_cb.ncit_cb.nci_ctrl_size = *p; /* start post initialization */ nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD; nfc_hal_cb.dev_cb.next_startup_vsc = 1; nfc_hal_dm_config_nfcc (); break; case NFC_HAL_EVT_TO_START_QUICK_TIMER: GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); break; case NFC_HAL_EVT_HCI: nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg); break; case NFC_HAL_EVT_PRE_DISCOVER: NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE); nfa_hal_send_pre_discover_cfg (); break; case NFC_HAL_EVT_CONTROL_GRANTED: nfc_hal_dm_send_pend_cmd (); break; default: break; } if (free_msg) GKI_freebuf (p_msg); } } /* Data waiting to be read from serial port */ if (event & NFC_HAL_TASK_EVT_DATA_RDY) { while (TRUE) { /* Read one byte to see if there is anything waiting to be read */ if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0) { break; } if (nfc_hal_nci_receive_msg (byte)) { /* complete of receiving NCI message */ nfc_hal_nci_assemble_nci_msg (); if (nfc_hal_cb.ncit_cb.p_rcv_msg) { if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg)) { /* Send NCI message to the stack */ nfc_hal_send_nci_msg_to_nfc_task (nfc_hal_cb.ncit_cb.p_rcv_msg); } else { if (nfc_hal_cb.ncit_cb.p_rcv_msg) GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); } nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; #ifdef SWISSKNIFEVERSION GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY); //Try to search for another message after we are done with this one. #endif } } } /* while (TRUE) */ } /* Process quick timer tick */ if (event & NFC_HAL_QUICK_TIMER_EVT_MASK) { nfc_hal_main_process_quick_timer_evt (); } } HAL_TRACE_DEBUG0 ("nfc_hal_main_task terminated"); GKI_exit_task (GKI_get_taskid ()); return 0; }