/******************************************************************************
|
*
|
* 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 <utils/Log.h>
|
#include <signal.h>
|
#include <stdlib.h>
|
#include <time.h>
|
#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
|
}
|