/****************************************************************************** * * Copyright (C) 2019-2021 Aicsemi Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /****************************************************************************** * * Filename: poll.c * * Description: Contains host & controller handshake implementation * ******************************************************************************/ #define LOG_TAG "bt_poll" #include #include #include #include #include "bt_hci_bdroid.h" //#include "bt_utils.h" #include "aic_poll.h" /****************************************************************************** ** Constants & Macros ******************************************************************************/ #ifndef BTPOLL_DBG #define BTPOLL_DBG false #endif #if (BTPOLL_DBG == true) #define BTPOLLDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} #else #define BTPOLLDBG(param, ...) {} #endif #ifndef ENABLE_BT_POLL_IN_ACTIVE_MODE #define ENABLE_BT_POLL_IN_ACTIVE_MODE false #endif #ifndef DEFAULT_POLL_IDLE_TIMEOUT #define DEFAULT_POLL_IDLE_TIMEOUT 2500 #endif volatile uint32_t aicbt_heartbeat_noack_num = 0; volatile uint32_t aicbt_heartbeat_evt_seqno = 0xffffffff; timed_out poll_idle_timeout; /****************************************************************************** ** Externs ******************************************************************************/ /****************************************************************************** ** Local type definitions ******************************************************************************/ /* Poll state */ enum { POLL_DISABLED = 0, /* initial state */ POLL_ENABLED, }; /* poll control block */ typedef struct { uint8_t state; /* poll state */ uint8_t timer_created; timer_t timer_id; uint32_t timeout_ms; } bt_poll_cb_t; extern int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid); extern int timer_delete(timer_t timerid); int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec * old_value); /****************************************************************************** ** Static variables ******************************************************************************/ static bt_poll_cb_t bt_poll_cb; /****************************************************************************** ** Poll Static Functions ******************************************************************************/ /******************************************************************************* ** ** Function poll_timer_stop ** ** Description stop timer if allowed ** ** Returns None ** *******************************************************************************/ static void poll_timer_stop(void) { int status; struct itimerspec ts; ALOGI("poll_timer_stop: timer_created %d", bt_poll_cb.timer_created); if (bt_poll_cb.timer_created == true) { ts.it_value.tv_sec = 0; ts.it_value.tv_nsec = 0; ts.it_interval.tv_sec = 0; ts.it_interval.tv_nsec = 0; status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0); if (status == -1) ALOGE("[STOP] Failed to set poll idle timeout"); } } /***************************************************************************** ** POLL Interface Functions *****************************************************************************/ /******************************************************************************* ** ** Function poll_init ** ** Description Init bt poll ** ** Returns None ** *******************************************************************************/ void poll_init(timed_out ptr_timeout, uint32_t timeout) { memset((void*)&bt_poll_cb, 0, sizeof(bt_poll_cb_t)); poll_idle_timeout = ptr_timeout; bt_poll_cb.state = POLL_DISABLED; bt_poll_cb.timeout_ms = timeout; ALOGI("poll_init: state %d, timeout %d ms,timeout=%d", bt_poll_cb.state, bt_poll_cb.timeout_ms,timeout); } /******************************************************************************* ** ** Function poll_cleanup ** ** Description Poll clean up ** ** Returns None ** *******************************************************************************/ void poll_cleanup(void) { ALOGI("poll_cleanup: timer_created %d", bt_poll_cb.timer_created); if (bt_poll_cb.timer_created == true) { timer_delete(bt_poll_cb.timer_id); } } /******************************************************************************* ** ** Function poll_enable ** ** Description Enalbe/Disable poll ** ** Returns None ** *******************************************************************************/ void poll_enable(uint8_t turn_on) { ALOGI("poll_enable: turn_on %d, state %d", turn_on, bt_poll_cb.state); if ((turn_on == true) && (bt_poll_cb.state == POLL_ENABLED)) { ALOGI("poll_enable: poll is already on!!!"); return; } else if ((turn_on == false) && (bt_poll_cb.state == POLL_DISABLED)) { ALOGI("poll_enable: poll is already off!!!"); return; } if (turn_on == false) { poll_timer_stop(); bt_poll_cb.state = POLL_DISABLED; } else { /* start poll timer when poll_timer_flush invoked first time */ bt_poll_cb.state = POLL_ENABLED; } } /******************************************************************************* ** ** Function poll_timer_flush ** ** Description Called to delay notifying Bluetooth chip. ** Normally this is called when there is data to be sent ** over HCI. ** ** Returns None ** *******************************************************************************/ void poll_timer_flush(void) { int status; struct itimerspec ts; struct sigevent se; memset(&se, 0, sizeof(struct sigevent)); BTPOLLDBG("poll_timer_flush: state %d", bt_poll_cb.state); if (bt_poll_cb.state != POLL_ENABLED) return; if (bt_poll_cb.timer_created == false) { se.sigev_notify = SIGEV_THREAD; se.sigev_value.sival_ptr = &bt_poll_cb.timer_id; se.sigev_notify_function = poll_idle_timeout; se.sigev_notify_attributes = NULL; status = timer_create(CLOCK_MONOTONIC, &se, &bt_poll_cb.timer_id); if (status == 0) bt_poll_cb.timer_created = true; } #if (defined(ENABLE_BT_POLL_IN_ACTIVE_MODE) && (ENABLE_BT_POLL_IN_ACTIVE_MODE == false)) if (bt_poll_cb.timer_created == true) { ts.it_value.tv_sec = bt_poll_cb.timeout_ms / 1000; ts.it_value.tv_nsec = 1000 * 1000 * (bt_poll_cb.timeout_ms % 1000); ts.it_interval.tv_sec = 0; ts.it_interval.tv_nsec = 0; status = timer_settime(bt_poll_cb.timer_id, 0, &ts, 0); if (status == -1) ALOGE("[Flush] Failed to set poll idle timeout"); } #endif }