merge in jb-mr2-release history after reset to jb-mr2-dev
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
old mode 100644
new mode 100755
index b3b72e7..55c88d5
--- a/btif/include/btif_media.h
+++ b/btif/include/btif_media.h
@@ -237,6 +237,7 @@
void btif_a2dp_on_idle(void);
void btif_a2dp_on_open(void);
void btif_a2dp_on_started(tBTA_AV_START *p_av);
+void btif_a2dp_ack_fail(void);
void btif_a2dp_on_stop_req(void);
void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
void btif_a2dp_on_suspend(void);
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index 074164d..fbbd564 100755
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -62,6 +62,8 @@
#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
#define BTIF_AV_FLAG_REMOTE_SUSPEND 0x2
+#define BTIF_AV_FLAG_PENDING_START 0x4
+#define BTIF_AV_FLAG_PENDING_STOP 0x8
/*****************************************************************************
** Local type definitions
@@ -401,6 +403,7 @@
/* wait for audioflinger to stop a2dp */
break;
+ case BTA_AV_STOP_EVT:
case BTIF_AV_STOP_STREAM_REQ_EVT:
/* immediately flush any pending tx frames while suspend is pending */
btif_a2dp_set_tx_flush(TRUE);
@@ -462,15 +465,19 @@
switch (event)
{
case BTIF_SM_ENTER_EVT:
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
btif_media_check_iop_exceptions(btif_av_cb.peer_bda.address);
- break;
+ break;
case BTIF_SM_EXIT_EVT:
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
break;
case BTIF_AV_START_STREAM_REQ_EVT:
btif_a2dp_setup_codec();
BTA_AvStart();
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
break;
case BTA_AV_START_EVT:
@@ -478,6 +485,7 @@
BTIF_TRACE_EVENT3("BTA_AV_START_EVT status %d, suspending %d, init %d",
p_av->start.status, p_av->start.suspending, p_av->start.initiator);
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
return TRUE;
@@ -502,6 +510,9 @@
case BTA_AV_CLOSE_EVT:
+ /* avdtp link is closed */
+ btif_a2dp_on_stopped(NULL);
+
/* inform the application that we are disconnected */
HAL_CBACK(bt_av_callbacks, connection_state_cb,
BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
@@ -509,6 +520,20 @@
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
break;
+ case BTA_AV_RECONFIG_EVT:
+ if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
+ (p_av->reconfig.status == BTA_AV_SUCCESS))
+ {
+ APPL_TRACE_WARNING0("reconfig done BTA_AVstart()");
+ BTA_AvStart();
+ }
+ else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)
+ {
+ btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+ btif_a2dp_ack_fail();
+ }
+ break;
+
CHECK_RC_EVENT(event, p_data);
default:
@@ -551,6 +576,11 @@
case BTIF_SM_EXIT_EVT:
break;
+ case BTIF_AV_START_STREAM_REQ_EVT:
+ /* we were remotely started, just ack back the local request */
+ btif_a2dp_on_started(NULL);
+ break;
+
/* fixme -- use suspend = true always to work around issue with BTA AV */
case BTIF_AV_STOP_STREAM_REQ_EVT:
case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
@@ -627,6 +657,8 @@
case BTA_AV_STOP_EVT:
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
btif_a2dp_on_stopped(&p_av->suspend);
HAL_CBACK(bt_av_callbacks, audio_state_cb,
@@ -640,6 +672,8 @@
case BTA_AV_CLOSE_EVT:
+ btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+
/* avdtp link is closed */
btif_a2dp_on_stopped(NULL);
@@ -854,8 +888,8 @@
return FALSE;
}
- /* check if we are remotely suspended */
- if (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND)
+ /* check if we are remotely suspended or stop is pending */
+ if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
return FALSE;
return (state == BTIF_AV_STATE_OPENED);
@@ -878,9 +912,9 @@
BTIF_TRACE_DEBUG3("btif_av_stream_started : sm hdl %d, state %d, flags %x",
btif_av_cb.sm_handle, state, btif_av_cb.flags);
- /* don't allow media task to start if we are suspending or
- remotely suspended (not yet changed state) */
- if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND))
+ /* disallow media task to start if we have pending actions */
+ if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
+ | BTIF_AV_FLAG_PENDING_STOP))
return FALSE;
return (state == BTIF_AV_STATE_STARTED);
@@ -958,11 +992,11 @@
/*******************************************************************************
**
-** Function btif_av_is_rc_open_without_a2dp
+** Function btif_av_is_connected
**
-** Description Checks if GAVDTP Open notification to app is pending (2 second timer)
+** Description Checks if av has a connected sink
**
-** Returns boolean
+** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN btif_av_is_connected(void)
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 200cf06..3c15b27 100755
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -35,6 +35,7 @@
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
+#include <errno.h>
#include "bt_target.h"
#include "gki.h"
@@ -51,11 +52,9 @@
#include "bta_av_ci.h"
#include "l2c_api.h"
-
#include "btif_av_co.h"
#include "btif_media.h"
-
#if (BTA_AV_INCLUDED == TRUE)
#include "sbc_encoder.h"
#endif
@@ -166,7 +165,7 @@
#define BT_MEDIA_TASK A2DP_MEDIA_TASK
#define USEC_PER_SEC 1000000L
-#define TPUT_STATS_INTERVAL_US (1000*1000)
+#define TPUT_STATS_INTERVAL_US (3000*1000)
/*
* CONGESTION COMPENSATION CTRL ::
@@ -234,11 +233,11 @@
} tBTIF_MEDIA_CB;
typedef struct {
- int rx;
- int rx_tot;
- int tx;
- int tx_tot;
- int ts_prev_us;
+ long long rx;
+ long long rx_tot;
+ long long tx;
+ long long tx_tot;
+ long long ts_prev_us;
} t_stat;
/*****************************************************************************
@@ -256,6 +255,7 @@
static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
static void btif_a2dp_encoder_update(void);
+const char* dump_media_event(UINT16 event);
/*****************************************************************************
** Externs
@@ -286,8 +286,8 @@
/* only monitor one connection at a time for now */
static t_stat cur_stat;
struct timespec now;
- unsigned int prev_us;
- unsigned int now_us;
+ unsigned long long prev_us;
+ unsigned long long now_us;
if (reset == TRUE)
{
@@ -309,14 +309,12 @@
now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
- //APPL_TRACE_DEBUG1("%d us", now_us - cur_stat.ts_prev_us);
-
if ((now_us - cur_stat.ts_prev_us) < TPUT_STATS_INTERVAL_US)
return;
- APPL_TRACE_WARNING4("tput rx:%d, tx:%d (kB/s) (tot : rx %d, tx %d bytes)",
- (cur_stat.rx)/((now_us - cur_stat.ts_prev_us)/1000),
- (cur_stat.tx)/((now_us - cur_stat.ts_prev_us)/1000),
+ APPL_TRACE_WARNING4("tput rx:%d, tx:%d (bytes/s) (tot : rx %d, tx %d bytes)",
+ (cur_stat.rx*1000000)/((now_us - cur_stat.ts_prev_us)),
+ (cur_stat.tx*1000000)/((now_us - cur_stat.ts_prev_us)),
cur_stat.rx_tot, cur_stat.tx_tot);
/* stats dumped. now reset stats for next interval */
@@ -401,7 +399,8 @@
{
UINT8 ack = status;
- APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##", dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
+ APPL_TRACE_EVENT2("## a2dp ack : %s, status %d ##",
+ dump_a2dp_ctrl_event(btif_media_cb.a2dp_cmd_pending), status);
/* sanity check */
if (btif_media_cb.a2dp_cmd_pending == A2DP_CTRL_CMD_NONE)
@@ -838,11 +837,17 @@
void btif_a2dp_on_started(tBTA_AV_START *p_av)
{
- tBTIF_AV_MEDIA_FEEDINGS media_feeding;
tBTIF_STATUS status;
APPL_TRACE_EVENT0("## ON A2DP STARTED ##");
+ if (p_av == NULL)
+ {
+ /* ack back a local start request */
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+ return;
+ }
+
if (p_av->status == BTA_AV_SUCCESS)
{
if (p_av->suspending == FALSE)
@@ -870,6 +875,24 @@
/*****************************************************************************
**
+** Function btif_a2dp_ack_fail
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+void btif_a2dp_ack_fail(void)
+{
+ tBTIF_STATUS status;
+
+ APPL_TRACE_EVENT0("## A2DP_CTRL_ACK_FAILURE ##");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+}
+
+/*****************************************************************************
+**
** Function btif_a2dp_on_stopped
**
** Description
@@ -1182,7 +1205,8 @@
*******************************************************************************/
static void btif_media_task_handle_cmd(BT_HDR *p_msg)
{
- VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event, dump_media_event(p_msg->event));
+ VERBOSE("btif_media_task_handle_cmd : %d %s", p_msg->event,
+ dump_media_event(p_msg->event));
switch (p_msg->event)
{
@@ -1467,7 +1491,8 @@
/* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */
//if (btif_media_cb.is_tx_timer)
{
- btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
+ btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE -
+ BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
< pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET
- sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
@@ -1533,11 +1558,13 @@
s16BitPool = 0;
}
- APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)", s16BitPool, pstrEncParams->u16BitRate);
+ APPL_TRACE_EVENT2("bitpool candidate : %d (%d kbps)",
+ s16BitPool, pstrEncParams->u16BitRate);
if (s16BitPool > pUpdateAudio->MaxBitPool)
{
- APPL_TRACE_WARNING1("btif_media_task_enc_update computed bitpool too large (%d)", s16BitPool);
+ APPL_TRACE_DEBUG1("btif_media_task_enc_update computed bitpool too large (%d)",
+ s16BitPool);
/* Decrease bitrate */
btif_media_cb.encoder.u16BitRate -= BTIF_MEDIA_BITRATE_STEP;
/* Record that we have decreased the bitrate */
@@ -1592,7 +1619,6 @@
APPL_TRACE_DEBUG1("num_channel:%d", p_feeding->feeding.cfg.pcm.num_channel);
APPL_TRACE_DEBUG1("bit_per_sample:%d", p_feeding->feeding.cfg.pcm.bit_per_sample);
-
/* Check the PCM feeding sampling_freq */
switch (p_feeding->feeding.cfg.pcm.sampling_freq)
{
@@ -1639,11 +1665,13 @@
if (reconfig_needed != FALSE)
{
- APPL_TRACE_DEBUG0("btif_media_task_pcm2sbc_init calls SBC_Encoder_Init");
- APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init mtu %d", btif_media_cb.TxAaMtuSize);
- APPL_TRACE_DEBUG6("btif_media_task_pcm2sbc_init ch mode %d, nbsubd %d, nb blk %d, alloc method %d, bit rate %d, Smp freq %d",
- btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
- btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16SamplingFreq);
+ APPL_TRACE_DEBUG1("btif_media_task_pcm2sbc_init :: mtu %d", btif_media_cb.TxAaMtuSize);
+ APPL_TRACE_DEBUG6("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d",
+ btif_media_cb.encoder.s16ChannelMode,
+ btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks,
+ btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
+ btif_media_cb.encoder.s16SamplingFreq);
+
SBC_Encoder_Init(&(btif_media_cb.encoder));
}
else
@@ -1740,8 +1768,7 @@
static void btif_media_task_aa_start_tx(void)
{
APPL_TRACE_DEBUG2("btif_media_task_aa_start_tx is timer %d, feeding mode %d",
- btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
-
+ btif_media_cb.is_tx_timer, btif_media_cb.feeding_mode);
/* Use a timer to poll the UIPC, get rid of the UIPC call back */
// UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REG_CBACK, NULL);
@@ -1751,7 +1778,9 @@
/* Reset the media feeding state */
btif_media_task_feeding_state_reset();
- APPL_TRACE_EVENT2("starting timer %d ticks (%d)", GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+ APPL_TRACE_EVENT2("starting timer %d ticks (%d)",
+ GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TICKS_PER_SEC);
+
GKI_start_timer(BTIF_MEDIA_AA_TASK_TIMER_ID, GKI_MS_TO_TICKS(BTIF_MEDIA_TIME_TICK), TRUE);
}
@@ -1790,8 +1819,6 @@
** Returns The number of media frames in this time slice
**
*******************************************************************************/
-
-
static UINT8 btif_get_num_aa_frame(void)
{
UINT8 result=0;
@@ -1886,12 +1913,13 @@
BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id)
{
UINT16 event;
- /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
- UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * \
+ btif_media_cb.encoder.s16NumOfBlocks;
UINT32 read_size;
UINT16 sbc_sampling = 48000;
UINT32 src_samples;
- UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * sizeof(SINT16);
+ UINT16 bytes_needed = blocm_x_subband * btif_media_cb.encoder.s16NumOfChannels * \
+ sizeof(SINT16);
static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
* SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
@@ -1992,7 +2020,7 @@
btif_media_cb.media_feeding.cfg.pcm.num_channel);
/* re-sample read buffer */
- /* The output PCM buffer will be stereo, 16 bit per sec */
+ /* The output PCM buffer will be stereo, 16 bit per sample */
dst_size_used = bta_av_sbc_up_sample((UINT8 *)read_buffer,
(UINT8 *)up_sampled_buffer + btif_media_cb.media_feeding_state.pcm.aa_feed_residue,
nb_byte_read,
@@ -2000,7 +2028,7 @@
&src_size_used);
#if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
- APPL_TRACE_DEBUG3("btif_media_aa_read_feeding read_size:%d src_size_used:%d dst_size_used:%d",
+ APPL_TRACE_DEBUG3("btif_media_aa_read_feeding readsz:%d src_size_used:%d dst_size_used:%d",
read_size, src_size_used, dst_size_used);
#endif
@@ -2046,16 +2074,19 @@
static void btif_media_aa_prep_sbc_2_send(UINT8 nb_frame)
{
BT_HDR * p_buf;
- UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands * btif_media_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btif_media_cb.encoder.s16NumOfSubBands *
+ btif_media_cb.encoder.s16NumOfBlocks;
#if (defined(DEBUG_MEDIA_AV_FLOW) && (DEBUG_MEDIA_AV_FLOW == TRUE))
- APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d", nb_frame, btif_media_cb.TxAaQ.count);
+ APPL_TRACE_DEBUG2("btif_media_aa_prep_sbc_2_send nb_frame %d, TxAaQ %d",
+ nb_frame, btif_media_cb.TxAaQ.count);
#endif
while (nb_frame)
{
if (NULL == (p_buf = GKI_getpoolbuf(BTIF_MEDIA_AA_POOL_ID)))
{
- APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ", btif_media_cb.TxAaQ.count);
+ APPL_TRACE_ERROR1 ("ERROR btif_media_aa_prep_sbc_2_send no buffer TxCnt %d ",
+ btif_media_cb.TxAaQ.count);
return;
}
@@ -2069,7 +2100,6 @@
/* Write @ of allocated buffer in encoder.pu8Packet */
btif_media_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
/* Fill allocated buffer with 0 */
- /* coverity[SIGN_EXTENSION] False-positive: Parameter are always in range avoiding sign extension*/
memset(btif_media_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
* btif_media_cb.encoder.s16NumOfChannels);
@@ -2100,11 +2130,12 @@
if(p_buf->len)
{
- btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
-
- /* store the time stamp in the buffer to send */
+ /* timestamp of the media packet header represent the TS of the first SBC frame
+ i.e the timestamp before including this frame */
*((UINT32 *) (p_buf + 1)) = btif_media_cb.timestamp;
+ btif_media_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
+
VERBOSE("TX QUEUE NOW %d", btif_media_cb.TxAaQ.count);
if (btif_media_cb.tx_flush)
diff --git a/hci/include/bt_hci_bdroid.h b/hci/include/bt_hci_bdroid.h
index 5681e85..7b23851 100644
--- a/hci/include/bt_hci_bdroid.h
+++ b/hci/include/bt_hci_bdroid.h
@@ -86,6 +86,7 @@
#define HC_EVENT_LPM_ALLOW_SLEEP 0x0080
#define HC_EVENT_LPM_IDLE_TIMEOUT 0x0100
#define HC_EVENT_EXIT 0x0200
+#define HC_EVENT_EPILOG 0x0400
/* Message event mask across Host/Controller lib and stack */
#define MSG_EVT_MASK 0xFF00 /* eq. BT_EVT_MASK */
diff --git a/hci/include/bt_vendor_lib.h b/hci/include/bt_vendor_lib.h
index 054e317..f774a14 100644
--- a/hci/include/bt_vendor_lib.h
+++ b/hci/include/bt_vendor_lib.h
@@ -80,10 +80,10 @@
* Typecasting conversion: (int (*)[]) param.
* [return]
* Numbers of opened file descriptors.
- * Valid number:
- * 1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
- * 2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
- * 4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+ * Valid number:
+ * 1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+ * 2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+ * 4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
* [callback]
* None.
*/
@@ -141,6 +141,20 @@
* None.
*/
BT_VND_OP_LPM_WAKE_SET_STATE,
+
+/* [operation]
+ * The epilog call to the vendor module so that it can perform any
+ * vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
+ * before the caller calls for cleanup().
+ * [input param]
+ * None.
+ * [return]
+ * 0 - default, don't care.
+ * [callback]
+ * Must call epilog_cb to notify the stack of the completion of vendor
+ * specific epilog process once it has been done.
+ */
+ BT_VND_OP_EPILOG,
} bt_vendor_opcode_t;
/** Power on/off control states */
@@ -280,6 +294,9 @@
/* hci command packet transmit request */
cmd_xmit_cb xmit_cb;
+
+ /* notifies caller completion of epilog process */
+ cfg_result_cb epilog_cb;
} bt_vendor_callbacks_t;
/*
diff --git a/hci/src/bt_hci_bdroid.c b/hci/src/bt_hci_bdroid.c
index 8a04d47..90249aa 100644
--- a/hci/src/bt_hci_bdroid.c
+++ b/hci/src/bt_hci_bdroid.c
@@ -47,6 +47,11 @@
#define BTHCDBG(param, ...) {}
#endif
+/* Vendor epilog process timeout period */
+#ifndef EPILOG_TIMEOUT_MS
+#define EPILOG_TIMEOUT_MS 3000 // 3 seconds
+#endif
+
/******************************************************************************
** Externs
******************************************************************************/
@@ -81,6 +86,8 @@
pthread_t worker_thread;
pthread_mutex_t mutex;
pthread_cond_t cond;
+ uint8_t epilog_timer_created;
+ timer_t epilog_timer_id;
} bt_hc_cb_t;
/******************************************************************************
@@ -106,6 +113,63 @@
pthread_mutex_unlock(&hc_cb.mutex);
}
+/*******************************************************************************
+**
+** Function epilog_wait_timeout
+**
+** Description Timeout thread of epilog watchdog timer
+**
+** Returns None
+**
+*******************************************************************************/
+static void epilog_wait_timeout(union sigval arg)
+{
+ ALOGI("...epilog_wait_timeout...");
+ bthc_signal_event(HC_EVENT_EXIT);
+}
+
+/*******************************************************************************
+**
+** Function epilog_wait_timer
+**
+** Description Launch epilog watchdog timer
+**
+** Returns None
+**
+*******************************************************************************/
+static void epilog_wait_timer(void)
+{
+ int status;
+ struct itimerspec ts;
+ struct sigevent se;
+ uint32_t timeout_ms = EPILOG_TIMEOUT_MS;
+
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_value.sival_ptr = &hc_cb.epilog_timer_id;
+ se.sigev_notify_function = epilog_wait_timeout;
+ se.sigev_notify_attributes = NULL;
+
+ status = timer_create(CLOCK_MONOTONIC, &se, &hc_cb.epilog_timer_id);
+
+ if (status == 0)
+ {
+ hc_cb.epilog_timer_created = 1;
+ ts.it_value.tv_sec = timeout_ms/1000;
+ ts.it_value.tv_nsec = 1000000*(timeout_ms%1000);
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+
+ status = timer_settime(hc_cb.epilog_timer_id, 0, &ts, 0);
+ if (status == -1)
+ ALOGE("Failed to fire epilog watchdog timer");
+ }
+ else
+ {
+ ALOGE("Failed to create epilog watchdog timer");
+ hc_cb.epilog_timer_created = 0;
+ }
+}
+
/*****************************************************************************
**
** BLUETOOTH HOST/CONTROLLER INTERFACE LIBRARY FUNCTIONS
@@ -126,6 +190,8 @@
return BT_HC_STATUS_FAIL;
}
+ hc_cb.epilog_timer_created = 0;
+
/* store reference to user callbacks */
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
@@ -295,11 +361,20 @@
if (lib_running)
{
- lib_running = 0;
- bthc_signal_event(HC_EVENT_EXIT);
+ epilog_wait_timer();
+
+ bthc_signal_event(HC_EVENT_EPILOG);
pthread_join(hc_cb.worker_thread, NULL);
+
+ if (hc_cb.epilog_timer_created == 1)
+ {
+ timer_delete(hc_cb.epilog_timer_id);
+ hc_cb.epilog_timer_created = 0;
+ }
}
+ lib_running = 0;
+
lpm_cleanup();
userial_close();
p_hci_if->cleanup();
@@ -480,11 +555,21 @@
lpm_wake_assert();
}
+ if (events & HC_EVENT_EPILOG)
+ {
+ /* Calling vendor-specific part */
+ if (bt_vnd_if)
+ bt_vnd_if->op(BT_VND_OP_EPILOG, NULL);
+ else
+ break; // equivalent to HC_EVENT_EXIT
+ }
+
if (events & HC_EVENT_EXIT)
break;
}
ALOGI("bt_hc_worker_thread exiting");
+ lib_running = 0;
pthread_exit(NULL);
diff --git a/hci/src/bt_hw.c b/hci/src/bt_hw.c
index b2a099f..fae296b 100644
--- a/hci/src/bt_hw.c
+++ b/hci/src/bt_hw.c
@@ -162,6 +162,22 @@
return p_hci_if->send_int_cmd(opcode, (HC_BT_HDR *)p_buf, p_cback);
}
+/******************************************************************************
+**
+** Function epilog_cb
+**
+** Description HOST/CONTROLLER VENDOR LIB CALLBACK API - This function is
+** called back from the libbt-vendor to indicate the result of
+** previous epilog call.
+**
+** Returns None
+**
+******************************************************************************/
+static void epilog_cb(bt_vendor_op_result_t result)
+{
+ bthc_signal_event(HC_EVENT_EXIT);
+}
+
/*****************************************************************************
** The libbt-vendor Callback Functions Table
*****************************************************************************/
@@ -172,7 +188,8 @@
lpm_vnd_cb,
alloc,
dealloc,
- xmit_cb
+ xmit_cb,
+ epilog_cb
};
/******************************************************************************