summaryrefslogtreecommitdiffstats
path: root/btif
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-01-08 21:11:45 -0800
committerSteve Kondik <steve@cyngn.com>2016-01-08 21:11:45 -0800
commit80a7a7dc3125e463d06e7215feb3f5a27c4f3352 (patch)
treeb0e0e41e0aa6d4c8da964f168fd1fe5a75ae2b60 /btif
parent8c41c59ce1517fc1b32d6f2cee23689453be4870 (diff)
parent67687e5306dda16a919e75b2093c6812f7255d6f (diff)
downloadandroid_system_bt-80a7a7dc3125e463d06e7215feb3f5a27c4f3352.tar.gz
android_system_bt-80a7a7dc3125e463d06e7215feb3f5a27c4f3352.tar.bz2
android_system_bt-80a7a7dc3125e463d06e7215feb3f5a27c4f3352.zip
Merge branch 'LA.BF.1.1.3_rb1.7' of git://codeaurora.org/platform/system/bt into cm-13.0
Change-Id: Ic7851f38b6ca4b82ab9a0b96e7e494849944e5c6
Diffstat (limited to 'btif')
-rw-r--r--btif/co/bta_av_co.c8
-rw-r--r--btif/co/bta_hh_co.c1
-rw-r--r--btif/include/btif_av.h22
-rw-r--r--btif/include/btif_media.h1
-rw-r--r--btif/src/btif_av.c128
-rw-r--r--btif/src/btif_media_task.c538
-rw-r--r--btif/src/btif_rc.c70
-rw-r--r--btif/src/btif_storage.c23
8 files changed, 754 insertions, 37 deletions
diff --git a/btif/co/bta_av_co.c b/btif/co/bta_av_co.c
index 89a0f4c19..0e9b66a03 100644
--- a/btif/co/bta_av_co.c
+++ b/btif/co/bta_av_co.c
@@ -63,7 +63,11 @@
#define BTA_AV_CO_SBC_MIN_BITPOOL_OFF 5
#define BTA_AV_CO_SBC_MAX_BITPOOL_OFF 6
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+#define BTA_AV_CO_SBC_MAX_BITPOOL 51
+#else
#define BTA_AV_CO_SBC_MAX_BITPOOL 53
+#endif
/* SCMS-T protect info */
const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
@@ -71,7 +75,7 @@ const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
/* SBC SRC codec capabilities */
const tA2D_SBC_CIE bta_av_co_sbc_caps =
{
-#ifdef SAMPLE_RATE_48K
+#if defined(SAMPLE_RATE_48K) || defined (BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ)
(A2D_SBC_IE_SAMP_FREQ_48), /* samp_freq */
#else
(A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
@@ -97,7 +101,7 @@ const tA2D_SBC_CIE bta_av_co_sbc_sink_caps =
};
#if !defined(BTIF_AV_SBC_DEFAULT_SAMP_FREQ)
-#ifdef SAMPLE_RATE_48K
+#if defined(SAMPLE_RATE_48K) || defined (BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ)
#define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_48
#else
#define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index d1bda7d3f..b42310b7c 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -43,7 +43,6 @@ const char *dev_path = "/dev/uhid";
static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
#endif
-
#define REPORT_DESC_REPORT_ID 0x05
#define REPORT_DESC_DIGITIZER_PAGE 0x0D
#define REPORT_DESC_START_COLLECTION 0xA1
diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h
index 37caf6610..5d7ac0107 100644
--- a/btif/include/btif_av.h
+++ b/btif/include/btif_av.h
@@ -207,5 +207,27 @@ BOOLEAN btif_av_any_br_peer(void);
*******************************************************************************/
BOOLEAN btif_av_peer_supports_3mbps(void);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/******************************************************************************
+**
+** Function btif_av_get_streaming_channel_id
+**
+** Description Returns streaming channel id
+**
+** Returns channel id
+********************************************************************************/
+UINT16 btif_av_get_streaming_channel_id(void);
+
+/******************************************************************************
+**
+** Function btif_av_get_peer_addr
+**
+** Description Returns peer device address
+**
+** Returns peer address
+********************************************************************************/
+void btif_av_get_peer_addr(bt_bdaddr_t *peer_bda);
+
+#endif
#endif /* BTIF_AV_H */
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h
index 023e03cde..a9323f066 100644
--- a/btif/include/btif_media.h
+++ b/btif/include/btif_media.h
@@ -280,6 +280,7 @@ tBTIF_STATUS btif_a2dp_setup_codec(void);
void btif_a2dp_on_idle(void);
void btif_a2dp_on_open(void);
BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start);
+void btif_media_on_stop_vendor_command();
void btif_a2dp_ack_fail(void);
void btif_a2dp_on_stop_req(void);
void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index ef9ee51a2..5b8a1da9e 100644
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -34,6 +34,7 @@
#include <system/audio.h>
#include "hardware/bt_av.h"
#include "osi/include/allocator.h"
+#include <cutils/properties.h>
#define LOG_TAG "bt_btif_av"
@@ -101,6 +102,9 @@ typedef struct
int service;
BOOLEAN is_slave;
BOOLEAN is_device_playing;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ UINT16 channel_id;
+#endif
} btif_av_cb_t;
typedef struct
@@ -363,6 +367,8 @@ static void btif_report_audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_ad
static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, int index)
{
+ char a2dp_role[PROPERTY_VALUE_MAX] = "false";
+
BTIF_TRACE_IMP("%s event:%s flags %x on Index = %d", __FUNCTION__,
dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
@@ -382,6 +388,17 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, i
{
btif_av_cb[i].dual_handoff = FALSE;
}
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_av_cb[index].channel_id = 0;
+#endif
+ property_get("persist.service.bt.a2dp.sink", a2dp_role, "false");
+ if (!strncmp("false", a2dp_role, 5)) {
+ btif_av_cb[index].peer_sep = AVDT_TSEP_SNK;
+ btif_a2dp_set_peer_sep(AVDT_TSEP_SNK);
+ } else {
+ btif_av_cb[index].peer_sep = AVDT_TSEP_SRC;
+ btif_a2dp_set_peer_sep(AVDT_TSEP_SRC);
+ }
/* This API will be called twice at initialization
** Idle can be moved when device is disconnected too.
** Take care of other connected device here.*/
@@ -535,6 +552,11 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, i
}
bdcpy(btif_av_cb[index].peer_bda.address, ((tBTA_AV*)p_data)->open.bd_addr);
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_av_cb[index].channel_id = p_bta_data->open.stream_chnl_id;
+ BTIF_TRACE_DEBUG("streaming channel id updated as : 0x%x",
+ btif_av_cb[index].channel_id);
+#endif
}
else
{
@@ -663,6 +685,11 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
BTIF_TRACE_DEBUG("remote supports 3 mbps");
btif_av_cb[index].edr_3mbps = TRUE;
}
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_av_cb[index].channel_id = p_bta_data->open.stream_chnl_id;
+ BTIF_TRACE_DEBUG("streaming channel id updated as : 0x%x",
+ btif_av_cb[index].channel_id);
+#endif
}
else
{
@@ -1086,7 +1113,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data,
else
{
BTIF_TRACE_DEBUG("%s: trigger suspend as remote initiated!!",
- __FUNCTION__);
+ __FUNCTION__);
btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
}
}
@@ -1589,12 +1616,33 @@ static void btif_av_handle_event(UINT16 event, char* p_param)
tBTA_AV *p_bta_data = (tBTA_AV*)p_param;
bt_bdaddr_t * bt_addr;
UINT8 role;
+ int uuid;
switch (event)
{
/*events from Upper layer and Media Task*/
case BTIF_AV_CLEANUP_REQ_EVT: /*Clean up to be called on default index*/
BTIF_TRACE_EVENT("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
+ uuid = (int)*p_param;
+ if (uuid == BTA_A2DP_SOURCE_SERVICE_ID)
+ {
+ if (bt_av_src_callbacks)
+ {
+ bt_av_src_callbacks = NULL;
+ if (bt_av_sink_callbacks != NULL)
+ break;
+ }
+ }
+ else
+ {
+ if (bt_av_sink_callbacks)
+ {
+ bt_av_sink_callbacks = NULL;
+ if (bt_av_src_callbacks != NULL)
+ break;
+ }
+ }
+
btif_a2dp_stop_media_task();
return;
case BTIF_AV_CONNECT_REQ_EVT:
@@ -1616,6 +1664,9 @@ static void btif_av_handle_event(UINT16 event, char* p_param)
case BTIF_AV_STOP_STREAM_REQ_EVT:
case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
/*Should be handled by current STARTED*/
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_media_on_stop_vendor_command();
+#endif
index = btif_get_latest_playing_device_idx();
break;
/*Events from the stack, BTA*/
@@ -2375,7 +2426,8 @@ static void cleanup(int service_uuid)
int i;
BTIF_TRACE_IMP("AV %s", __FUNCTION__);
- btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, NULL, 0, NULL);
+ btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT,
+ (char*)&service_uuid, sizeof(int), NULL);
btif_disable_service(service_uuid);
@@ -2389,24 +2441,12 @@ static void cleanup(int service_uuid)
static void cleanup_src(void) {
BTIF_TRACE_EVENT("%s", __FUNCTION__);
-
- if (bt_av_src_callbacks)
- {
- bt_av_src_callbacks = NULL;
- if (bt_av_sink_callbacks == NULL)
- cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
- }
+ cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
}
static void cleanup_sink(void) {
BTIF_TRACE_EVENT("%s", __FUNCTION__);
-
- if (bt_av_sink_callbacks)
- {
- bt_av_sink_callbacks = NULL;
- if (bt_av_src_callbacks == NULL)
- cleanup(BTA_A2DP_SINK_SERVICE_ID);
- }
+ cleanup(BTA_A2DP_SINK_SERVICE_ID);
}
static void allow_connection(int is_valid, bt_bdaddr_t *bd_addr)
@@ -3178,3 +3218,59 @@ BOOLEAN btif_av_get_ongoing_multicast()
return FALSE;
}
}
+
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/******************************************************************************
+**
+** Function btif_av_get_streaming_channel_id
+**
+** Description Returns streaming channel id
+**
+** Returns channel id
+********************************************************************************/
+UINT16 btif_av_get_streaming_channel_id(void)
+{
+ btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+ int i;
+ for (i = 0; i < btif_max_av_clients; i++)
+ {
+ state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+ if ((state == BTIF_AV_STATE_OPENED) ||
+ (state == BTIF_AV_STATE_STARTED))
+ {
+ BTIF_TRACE_DEBUG("btif_av_get_streaming_channel_id: %u",
+ btif_av_cb[i].channel_id);
+ return btif_av_cb[i].channel_id;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+**
+** Function btif_av_get_peer_addr
+**
+** Description Returns peer device address
+**
+** Returns peer address
+********************************************************************************/
+void btif_av_get_peer_addr(bt_bdaddr_t *peer_bda)
+{
+ btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+ int i;
+ memset(peer_bda, 0, sizeof(bt_bdaddr_t));
+ for (i = 0; i < btif_max_av_clients; i++)
+ {
+ state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+ if ((state == BTIF_AV_STATE_OPENED) ||
+ (state == BTIF_AV_STATE_STARTED))
+ {
+ BTIF_TRACE_DEBUG("btif_av_get_peer_addr: %u",
+ btif_av_cb[i].peer_bda);
+ memcpy(peer_bda, &btif_av_cb[i].peer_bda,
+ sizeof(bt_bdaddr_t));
+ }
+ }
+}
+#endif
+
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 0b1d8bb3a..07aec5bd3 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -98,6 +98,11 @@ OI_INT16 pcmData[15*SBC_MAX_SAMPLES_PER_FRAME*SBC_MAX_CHANNELS];
#define PERF_SYSTRACE 1
#endif
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+#include "bta_api.h"
+#endif
+
+
/*****************************************************************************
** Constants
*****************************************************************************/
@@ -130,6 +135,18 @@ enum
#ifdef USE_AUDIO_TRACK
,BTIF_MEDIA_AUDIO_SINK_SET_FOCUS_STATE
#endif
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ ,BTIF_MEDIA_START_VS_CMD,
+ BTIF_MEDIA_STOP_VS_CMD,
+ BTIF_MEDIA_RESET_VS_STATE,
+ BTIF_MEDIA_VS_A2DP_START_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_STOP_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS,
+ BTIF_MEDIA_VS_A2DP_STOP_FAILURE
+#endif
};
enum {
@@ -167,12 +184,19 @@ enum {
#define BTIF_MEDIA_BITRATE_STEP 5
#endif
-/* Middle quality quality setting @ 44.1 khz */
+#ifdef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ
+#define DEFAULT_SBC_BITRATE 345
+
+#ifndef BTIF_A2DP_NON_EDR_MAX_RATE
+#define BTIF_A2DP_NON_EDR_MAX_RATE 237
+#endif
+#else
#define DEFAULT_SBC_BITRATE 328
#ifndef BTIF_A2DP_NON_EDR_MAX_RATE
#define BTIF_A2DP_NON_EDR_MAX_RATE 229
#endif
+#endif
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
/* A2DP header will contain a CP header of size 1 */
@@ -274,6 +298,14 @@ typedef struct
alarm_t *media_alarm;
alarm_t *decode_alarm;
UINT8 TxNumSBCFrames;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ UINT8 max_bitpool;
+ UINT8 min_bitpool;
+ BOOLEAN vs_configs_exchanged;
+ BOOLEAN tx_started;
+ BOOLEAN tx_stop_initiated;
+#endif
+
#endif
} tBTIF_MEDIA_CB;
@@ -341,6 +373,19 @@ static void btif_media_task_aa_handle_timer(UNUSED_ATTR void *context);
static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context);
extern BOOLEAN btif_hf_is_call_idle();
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+void btif_media_send_reset_vendor_state();
+void btif_media_on_start_vendor_command();
+void btif_media_start_vendor_command();
+void btif_media_on_stop_vendor_command();
+BOOLEAN btif_media_send_vendor_pref_bit_rate();
+BOOLEAN btif_media_send_vendor_write_sbc_cfg();
+BOOLEAN btif_media_send_vendor_media_chn_cfg();
+BOOLEAN btif_media_send_vendor_stop();
+BOOLEAN btif_media_send_vendor_start();
+#endif
+
+
static tBTIF_MEDIA_CB btif_media_cb;
static int media_task_running = MEDIA_TASK_STATE_OFF;
@@ -525,17 +570,27 @@ static void btif_recv_ctrl_data(void)
* and ACK the audio HAL.*/
if (btif_av_stream_started_ready())
{
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
/* already started, setup audio data channel listener
* and ack back immediately */
UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
-
+#else
+ APPL_TRACE_DEBUG("Av stream alreday started");
+ if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+ btif_a2dp_encoder_update();
+#endif
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
}
else if (btif_av_stream_ready() == TRUE)
{
/* setup audio data channel listener */
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
+ /* already started, setup audio data channel listener
+ * and ack back immediately */
UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
-
+#else
+ APPL_TRACE_DEBUG("Av stream ready");
+#endif
/* post start event and wait for audio path to open */
btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
@@ -552,14 +607,20 @@ static void btif_recv_ctrl_data(void)
break;
case A2DP_CTRL_CMD_STOP:
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
if (btif_media_cb.peer_sep == AVDT_TSEP_SNK && btif_media_cb.is_tx_timer == FALSE)
+#else
+ if (btif_media_cb.peer_sep == AVDT_TSEP_SNK && btif_media_cb.tx_started == FALSE)
+#endif
{
/* we are already stopped, just ack back */
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
break;
}
+ APPL_TRACE_DEBUG("Stop stream request to Av");
btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
+
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
break;
@@ -567,6 +628,7 @@ static void btif_recv_ctrl_data(void)
/* local suspend */
if (btif_av_stream_started_ready())
{
+ APPL_TRACE_DEBUG("Suspend stream request to Av");
btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
}
else
@@ -769,6 +831,13 @@ static void btif_a2dp_encoder_update(void)
msg.MinMtuSize = minmtu;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_media_cb.max_bitpool = msg.MaxBitPool;
+ btif_media_cb.min_bitpool = msg.MinBitPool;
+ APPL_TRACE_DEBUG("Updated min_bitpool: 0x%x max_bitpool: 0x%x",
+ btif_media_cb.min_bitpool, btif_media_cb.max_bitpool);
+#endif
+
/* Update the media task to encode SBC properly */
btif_media_task_enc_update_req(&msg);
}
@@ -859,10 +928,11 @@ tBTIF_STATUS btif_a2dp_setup_codec(void)
GKI_disable();
+#if defined(SAMPLE_RATE_48K) || defined (BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ)
/* for now hardcode 44/48 khz 16 bit stereo */
-#ifdef SAMPLE_RATE_48K
media_feeding.cfg.pcm.sampling_freq = 48000;
#else
+ /* for now hardcode 44.1 khz 16 bit stereo PCM format */
media_feeding.cfg.pcm.sampling_freq = 44100;
#endif
media_feeding.cfg.pcm.bit_per_sample = 16;
@@ -909,6 +979,9 @@ void btif_a2dp_on_idle(void)
/* Make sure media task is stopped */
btif_media_task_stop_aa_req();
}
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ btif_media_send_reset_vendor_state();
+#endif
bta_av_co_init();
#if (BTA_AV_SINK_INCLUDED == TRUE)
@@ -940,8 +1013,10 @@ void btif_a2dp_on_open(void)
{
APPL_TRACE_EVENT("## ON A2DP OPEN ##");
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
/* always use callback to notify socket events */
UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+#endif
}
/*******************************************************************************
@@ -964,7 +1039,8 @@ BOOLEAN btif_media_task_clear_track(void)
p_buf->event = BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -995,7 +1071,8 @@ void btif_reset_decoder(UINT8 *p_av)
memcpy(p_buf->codec_info,p_av, AVDT_CODEC_SIZE);
p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
}
/*****************************************************************************
@@ -1016,8 +1093,15 @@ BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start)
if (p_av == NULL)
{
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+ {
+ btif_media_on_start_vendor_command();
+ }
+#else
/* ack back a local start request */
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+#endif
return TRUE;
}
@@ -1028,7 +1112,14 @@ BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start)
if (p_av->initiator)
{
if (pending_start) {
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+ {
+ btif_media_on_start_vendor_command();
+ }
+#else
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+#endif
ack = TRUE;
}
}
@@ -1036,7 +1127,15 @@ BOOLEAN btif_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start)
{
/* we were remotely started, make sure codec
is setup before datapath is started */
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ if (btif_media_cb.peer_sep == AVDT_TSEP_SNK)
+ {
+ APPL_TRACE_IMP("start VS command exchange on remote start");
+ btif_media_on_start_vendor_command();
+ }
+#else
btif_a2dp_setup_codec();
+#endif
}
/* media task is autostarted upon a2dp audiopath connection */
@@ -1108,7 +1207,9 @@ void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av)
btif_media_cb.tx_flush = 1;
/* request to stop media task */
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
btif_media_task_aa_tx_flush_req();
+#endif
btif_media_task_stop_aa_req();
/* once stream is fully stopped we will ack back */
@@ -1181,7 +1282,8 @@ void btif_a2dp_set_audio_focus_state(btif_media_audio_focus_state state)
p_buf->focus_state = state;
p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_SET_FOCUS_STATE;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
}
#endif
#if (BTA_AV_SINK_INCLUDED == TRUE)
@@ -1336,7 +1438,8 @@ BOOLEAN btif_media_task_send_cmd_evt(UINT16 Evt)
p_buf->event = Evt;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1408,6 +1511,55 @@ static void btif_media_thread_handle_cmd(fixed_queue_t *queue, UNUSED_ATTR void
case BTIF_MEDIA_FLUSH_AA_RX:
btif_media_task_aa_rx_flush();
break;
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+ case BTIF_MEDIA_RESET_VS_STATE:
+ btif_media_cb.tx_started = FALSE;
+ btif_media_cb.tx_stop_initiated = FALSE;
+ btif_media_cb.vs_configs_exchanged = FALSE;
+ break;
+ case BTIF_MEDIA_START_VS_CMD:
+ btif_a2dp_encoder_update();
+ btif_media_start_vendor_command();
+ break;
+ case BTIF_MEDIA_STOP_VS_CMD:
+ btif_media_send_vendor_stop();
+ break;
+ case BTIF_MEDIA_VS_A2DP_START_SUCCESS:
+ btif_media_cb.tx_started = TRUE;
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+ break;
+ case BTIF_MEDIA_VS_A2DP_STOP_SUCCESS:
+ btif_media_cb.tx_started = FALSE;
+ btif_media_cb.tx_stop_initiated = FALSE;
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+ break;
+ case BTIF_MEDIA_VS_A2DP_STOP_FAILURE:
+ btif_media_cb.tx_stop_initiated = FALSE;
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ break;
+ case BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS:
+ btif_media_send_vendor_pref_bit_rate();
+ break;
+ case BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS:
+ btif_media_send_vendor_media_chn_cfg();
+ break;
+ case BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS:
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+ btif_media_send_vendor_scmst_hdr();
+#else
+ if (!btif_media_cb.vs_configs_exchanged)
+ btif_media_cb.vs_configs_exchanged = TRUE;
+ btif_media_send_vendor_start();
+#endif
+ break;
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+ case BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS:
+ if (!btif_media_cb.vs_configs_exchanged)
+ btif_media_cb.vs_configs_exchanged = TRUE;
+ btif_media_send_vendor_start();
+ break;
+#endif
+#endif
#endif
default:
APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event);
@@ -1502,7 +1654,8 @@ BOOLEAN btif_media_task_enc_init_req(tBTIF_MEDIA_INIT_AUDIO *p_msg)
memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO));
p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_INIT;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1526,7 +1679,8 @@ BOOLEAN btif_media_task_enc_update_req(tBTIF_MEDIA_UPDATE_AUDIO *p_msg)
memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_UPDATE_AUDIO));
p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_UPDATE;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1550,7 +1704,8 @@ BOOLEAN btif_media_task_audio_feeding_init_req(tBTIF_MEDIA_INIT_AUDIO_FEEDING *p
memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO_FEEDING));
p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_INIT;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1574,7 +1729,8 @@ BOOLEAN btif_media_task_start_aa_req(void)
p_buf->event = BTIF_MEDIA_START_AA_TX;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1635,7 +1791,8 @@ BOOLEAN btif_media_task_aa_rx_flush_req(void)
p_buf->event = BTIF_MEDIA_FLUSH_AA_RX;
- fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ if (btif_media_cmd_msg_queue != NULL)
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
return TRUE;
}
@@ -1754,8 +1911,10 @@ static void btif_media_task_enc_init(BT_HDR *p_msg)
btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate,
btif_media_cb.encoder.s16SamplingFreq);
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
/* Reset entirely the SBC encoder */
SBC_Encoder_Init(&(btif_media_cb.encoder));
+#endif
btif_media_cb.TxNumSBCFrames = check_for_max_number_of_frames_per_packet();
APPL_TRACE_DEBUG("btif_media_task_enc_init bit pool %d", btif_media_cb.encoder.s16BitPool);
}
@@ -1920,8 +2079,10 @@ static void btif_media_task_enc_update(BT_HDR *p_msg)
APPL_TRACE_DEBUG("btif_media_task_enc_update final bit rate %d, final bit pool %d",
btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16BitPool);
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
/* make sure we reinitialize encoder with new settings */
SBC_Encoder_Init(&(btif_media_cb.encoder));
+#endif
btif_media_cb.TxNumSBCFrames = check_for_max_number_of_frames_per_packet();
}
}
@@ -1996,8 +2157,9 @@ static void btif_media_task_pcm2sbc_init(tBTIF_MEDIA_INIT_AUDIO_FEEDING * p_feed
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);
-
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
SBC_Encoder_Init(&(btif_media_cb.encoder));
+#endif
}
else
{
@@ -2336,6 +2498,8 @@ static void btif_media_task_aa_start_tx(void)
/* Reset the media feeding state */
btif_media_task_feeding_state_reset();
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
+
APPL_TRACE_EVENT("starting timer %dms", BTIF_MEDIA_TIME_TICK);
assert(btif_media_cb.media_alarm == NULL);
@@ -2347,6 +2511,7 @@ static void btif_media_task_aa_start_tx(void)
}
alarm_set_periodic(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK, btif_media_task_alarm_cb, NULL);
+#endif
}
/*******************************************************************************
@@ -2360,9 +2525,9 @@ static void btif_media_task_aa_start_tx(void)
*******************************************************************************/
static void btif_media_task_aa_stop_tx(void)
{
- APPL_TRACE_DEBUG("%s is_tx_timer: %d", __func__, btif_media_cb.is_tx_timer);
-
+#ifndef BTA_AV_SPLIT_A2DP_ENABLED
const bool send_ack = (btif_media_cb.is_tx_timer != FALSE);
+ APPL_TRACE_DEBUG("%s is_tx_timer: %d", __func__, btif_media_cb.is_tx_timer);
/* Stop the timer first */
alarm_free(btif_media_cb.media_alarm);
@@ -2391,6 +2556,14 @@ static void btif_media_task_aa_stop_tx(void)
/* Reset the media feeding state */
btif_media_task_feeding_state_reset();
+#else
+ APPL_TRACE_IMP("%s tx_started: %d, tx_stop_initiated: %d",
+ __func__, btif_media_cb.tx_started, btif_media_cb.tx_stop_initiated);
+ if (btif_media_cb.tx_started && !btif_media_cb.tx_stop_initiated)
+ btif_media_send_vendor_stop();
+ else
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+#endif
}
static UINT32 get_frame_length()
@@ -3079,6 +3252,339 @@ static void btif_media_send_aa_frame(void)
bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
}
+#ifdef BTA_AV_SPLIT_A2DP_ENABLED
+/*******************************************************************************
+ **
+ ** Function bta_av_co_send_vendor_start
+ **
+ ** Description Send Vendor Specific A2dp START command to controller
+ **
+ ** Returns TRUE if command succeeds, FALSE otherwize
+ **
+ *******************************************************************************/
+
+#define HCI_VSQC_CONTROLLER_A2DP_OPCODE 0x000A
+
+#define VS_QHCI_READ_A2DP_CFG 0x01
+#define VS_QHCI_WRITE_SBC_CFG 0x02
+#define VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG 0x03
+#define VS_QHCI_START_A2DP_MEDIA 0x04
+#define VS_QHCI_STOP_A2DP_MEDIA 0x05
+#define VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE 0x06
+#define VS_QHCI_A2DP_TRANSPORT_CONFIGURATION 0x07
+#define VS_QHCI_A2DP_WRITE_SCMS_T_CP 0x08
+
+void btif_media_send_reset_vendor_state()
+{
+ BT_HDR *p_buf;
+ if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+ {
+ APPL_TRACE_EVENT("GKI alloc failed");
+ return;
+ }
+ p_buf->event = BTIF_MEDIA_RESET_VS_STATE;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_start_vendor_command()
+{
+ APPL_TRACE_IMP("btif_media_start_vendor_command_exchange:\
+ vs_configs_exchanged:%u", btif_media_cb.vs_configs_exchanged);
+ if(btif_media_cb.vs_configs_exchanged)
+ {
+ btif_media_send_vendor_start();
+ }
+ else
+ {
+ btif_media_send_vendor_write_sbc_cfg();
+ }
+}
+
+void btif_media_on_start_vendor_command()
+{
+ BT_HDR *p_buf;
+ if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+ {
+ APPL_TRACE_EVENT("GKI alloc failed: ACK failure");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ return;
+ }
+ p_buf->event = BTIF_MEDIA_START_VS_CMD;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_on_stop_vendor_command()
+{
+ BT_HDR *p_buf;
+ if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+ {
+ APPL_TRACE_EVENT("GKI alloc failed: ACK failure");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ return;
+ }
+ APPL_TRACE_IMP("btif_media_on_stop_vendor_command");
+ p_buf->event = BTIF_MEDIA_STOP_VS_CMD;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+void btif_media_a2dp_start_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_START_A2DP_MEDIA sent with error code: %u", status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ {
+ p_buf->event = BTIF_MEDIA_VS_A2DP_START_SUCCESS;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR("Error in processing Vendor command response");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ }
+}
+
+BOOLEAN btif_media_send_vendor_start()
+{
+ UINT8 param[2];
+
+ APPL_TRACE_IMP("btif_media_send_vendor_start");
+
+ param[0] = VS_QHCI_START_A2DP_MEDIA;
+ param[1] = 0; /*needs to send index for multi A2dp*/
+
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+ param, btif_media_a2dp_start_cb);
+}
+
+void btif_media_a2dp_stop_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_STOP_A2DP_MEDIA sent with error code: %u", status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ p_buf->event = BTIF_MEDIA_VS_A2DP_STOP_SUCCESS;
+ else
+ p_buf->event = BTIF_MEDIA_VS_A2DP_STOP_FAILURE;
+
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+}
+
+BOOLEAN btif_media_send_vendor_stop()
+{
+ UINT8 param[2];
+
+ APPL_TRACE_IMP("btif_media_send_vendor_stop");
+
+ btif_media_cb.tx_stop_initiated = TRUE;
+
+ param[0] = VS_QHCI_STOP_A2DP_MEDIA;
+ param[1] = 0; /*needs to send index for multi A2dp*/
+
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+ param, btif_media_a2dp_stop_cb);
+}
+
+void btif_media_a2dp_media_chn_cfg_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG sent with error code: %u",
+ status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ {
+ p_buf->event = BTIF_MEDIA_VS_A2DP_MEDIA_CHNL_CFG_SUCCESS;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR("Error in processing Vendor command response");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ }
+}
+
+BOOLEAN btif_media_send_vendor_media_chn_cfg()
+{
+ UINT8 param[8];
+ bt_bdaddr_t bd_addr;
+ BD_ADDR addr;
+ btif_av_get_peer_addr(&bd_addr);
+ memcpy(addr, bd_addr.address, sizeof(BD_ADDR));
+ UINT16 acl_hdl = BTM_GetHCIConnHandle(addr, BT_TRANSPORT_BR_EDR);
+ APPL_TRACE_IMP("btif_media_send_vendor_media_chn_cfg");
+ APPL_TRACE_IMP("AVDTP mtu: %u, hdl: %u", btif_media_cb.TxAaMtuSize, acl_hdl);
+
+ param[0] = VS_QHCI_WRITE_A2DP_MEDIA_CHANNEL_CFG;
+ param[1] = 0; /*needs to send index for multi A2dp*/
+ param[2] = (UINT8)(acl_hdl & 0x00ff);
+ param[3] = (UINT8)(((acl_hdl & 0xff00) >> 8) & 0x00ff);
+ param[4] = (UINT8)(btif_av_get_streaming_channel_id()& 0x00ff);
+ param[5] = (UINT8)(((btif_av_get_streaming_channel_id() & 0xff00)
+ >> 8) & 0x00ff);
+ param[6] = (UINT8)(btif_media_cb.TxAaMtuSize & 0x00ff);
+ param[7] = (UINT8)(((btif_media_cb.TxAaMtuSize & 0xff00) >> 8) & 0x00ff);
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 8,
+ param, btif_media_a2dp_media_chn_cfg_cb);
+}
+
+void btif_media_a2dp_write_sbc_cfg_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_WRITE_SBC_CFG sent with error code: %u", status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ {
+ p_buf->event = BTIF_MEDIA_VS_A2DP_WRITE_SBC_CFG_SUCCESS;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR("Error in processing Vendor command response");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ }
+}
+
+BOOLEAN btif_media_send_vendor_write_sbc_cfg()
+{
+ UINT8 param[12];
+ bt_bdaddr_t bd_addr;
+ BD_ADDR addr;
+ btif_av_get_peer_addr(&bd_addr);
+ memcpy(addr, bd_addr.address, sizeof(BD_ADDR));
+ UINT16 acl_hdl = BTM_GetHCIConnHandle(addr, BT_TRANSPORT_BR_EDR);
+ APPL_TRACE_IMP("btif_media_send_vendor_write_sbc_cfg");
+ APPL_TRACE_IMP("acl hdl: %u", acl_hdl);
+ APPL_TRACE_IMP("channel mode: %u", btif_media_cb.encoder.s16ChannelMode);
+ APPL_TRACE_IMP("sampling frequency: %u", btif_media_cb.encoder.s16SamplingFreq);
+ APPL_TRACE_IMP("allocation method: %u", btif_media_cb.encoder.s16AllocationMethod);
+ APPL_TRACE_IMP("subbands: %u", btif_media_cb.encoder.s16NumOfSubBands);
+ APPL_TRACE_IMP("num of blocks: %u", btif_media_cb.encoder.s16NumOfBlocks);
+ APPL_TRACE_IMP("bitpool: <%u>,<%u>", btif_media_cb.min_bitpool, btif_media_cb.max_bitpool);
+ APPL_TRACE_IMP("Scmst flag: %u", bta_av_co_cp_get_flag());
+
+ param[0] = VS_QHCI_WRITE_SBC_CFG;
+ param[1] = (UINT8)((1 << (3 - btif_media_cb.encoder.s16ChannelMode)) |
+ (1 << (7 - btif_media_cb.encoder.s16SamplingFreq)));
+ param[2] = (UINT8)((1 << btif_media_cb.encoder.s16AllocationMethod) |
+ (1 << (3 - (btif_media_cb.encoder.s16NumOfSubBands >> 3))) |
+ (1 << (7 - ((btif_media_cb.encoder.s16NumOfBlocks - 4) >> 2))));
+ param[3] = btif_media_cb.min_bitpool;
+ param[4] = btif_media_cb.max_bitpool;
+ param[5] = 0; // Not in use as latency calculation will now be taken care of in SOC
+ param[6] = 0; // Not in use as latency calculation will now be taken care of in SOC
+ param[7] = 0; // Not in use as latency calculation will now be taken care of in SOC
+ param[8] = 0; // Not in use as latency calculation will now be taken care of in SOC
+ param[9] = 0; // 0 as delayed report not supported
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+ param[10] = 1;
+#else
+ param[10] = 0;
+#endif
+ param[11] = bta_av_co_cp_get_flag();
+
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 12,
+ param, btif_media_a2dp_write_sbc_cfg_cb);
+}
+
+void btif_media_pref_bit_rate_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE sent with error code: %u", status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ {
+ p_buf->event = BTIF_MEDIA_VS_A2DP_PREF_BIT_RATE_SUCCESS;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR("Error in processing Vendor command response");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ }
+}
+
+BOOLEAN btif_media_send_vendor_pref_bit_rate()
+{
+ UINT8 param[3];
+
+ APPL_TRACE_IMP("btif_media_send_vendor_pref_bit_rate: bitrate: %d", btif_media_cb.encoder.u16BitRate);
+
+ param[0] = VS_QHCI_A2DP_WRITE_SUGGESTED_BITRATE;
+ param[1] = (UINT8)(btif_media_cb.encoder.u16BitRate & 0x00ff);
+ param[2] = (UINT8)((btif_media_cb.encoder.u16BitRate & 0xff00) >> 8);
+
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 3,
+ param, btif_media_pref_bit_rate_cb);
+}
+
+void btif_media_scmst_cb(tBTM_VSC_CMPL *param)
+{
+ unsigned char status = 0;
+ BT_HDR *p_buf;
+
+ if (param->param_len)
+ {
+ status = param->p_param_buf[0];
+ }
+ APPL_TRACE_IMP("VS_QHCI_A2DP_WRITE_SCMS_T_CP sent with error code: %u", status);
+
+ if ((!status) && (NULL != (p_buf = GKI_getbuf(sizeof(BT_HDR)))))
+ {
+ p_buf->event = BTIF_MEDIA_VS_A2DP_SET_SCMST_HDR_SUCCESS;
+ fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR("Error in processing Vendor command response");
+ a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+ }
+}
+
+BOOLEAN btif_media_send_vendor_scmst_hdr()
+{
+ UINT8 param[3];
+
+ APPL_TRACE_IMP("btif_media_send_vendor_pref_bit_rate");
+
+ param[0] = VS_QHCI_A2DP_WRITE_SCMS_T_CP;
+ param[1] = bta_av_co_cp_get_flag();
+
+ return BTA_DmVendorSpecificCommand(HCI_VSQC_CONTROLLER_A2DP_OPCODE, 2,
+ param, btif_media_pref_bit_rate_cb);
+}
+
+#endif
+
#endif /* BTA_AV_INCLUDED == TRUE */
/*******************************************************************************
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
index 5b0d3c930..2bc4af767 100644
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -189,6 +189,7 @@ static int uinput_driver_check();
static int uinput_create(char *name);
static int init_uinput (void);
static void close_uinput (void);
+static BOOLEAN dev_blacklisted_for_absolute_volume(BD_ADDR peer_dev);
#if (AVRC_CTLR_INCLUDED == TRUE)
static BOOLEAN conn_status = FALSE;
#endif
@@ -209,6 +210,35 @@ static const struct {
{ NULL, 0, 0, 0 }
};
+/* the rc_black_addr_prefix and rc_white_addr_prefix are used to correct
+ * IOP issues of absolute volume feature
+ * We encoutered A2DP headsets/carkits advertising absolute volume but buggy.
+ * We would like to blacklist those devices.
+ * But we donot have a full list of the bad devices. So as a temp fix, we
+ * are blacklisting all the devices except the devices we have well tested,
+ * the ones in the whitelist.
+ *
+ * For now, only the rc_white_addr_prefix is used in the code while
+ * rc_black_addr_prefix is kept here for future long term solution.
+ */
+static const UINT8 rc_white_addr_prefix[][3] = {
+ {0x94, 0xCE, 0x2C}, // Sony SBH50
+ {0x30, 0x17, 0xC8}, // Sony wm600
+ {0x00, 0x15, 0x83}, // BlueSoleil dongle
+ {0x00, 0x80, 0x98}, // PTS dongle
+ {0x48, 0xC1, 0xAC}, // Plantronics Backbeat Go
+ {0x00, 0x1B, 0xDC}, // PTS dongle 2
+ {0x00, 0x19, 0x8E}, // Demant
+ {0x04, 0x88, 0xE2}, // Apple
+ {0x00, 0x0C, 0x8A}, // Bose
+ {0x1C, 0x48, 0xF9} // Jabra Pulse
+};
+
+static const char* rc_white_name[] = {
+ "SBH50",
+ "MW600"
+};
+
static void send_reject_response (UINT8 rc_handle, UINT8 label,
UINT8 pdu, UINT8 status);
static UINT8 opcode_from_pdu(UINT8 pdu);
@@ -4761,3 +4791,43 @@ void lbl_destroy()
BTIF_TRACE_EVENT(" %s: lbllock destroy success ", __FUNCTION__);
}
}
+
+/*******************************************************************************
+** Function dev_blacklisted_for_absolute_volume
+**
+** Description Blacklist Devices that donot handle absolute volume well
+** We are blacklisting all the devices that are not in whitelist
+**
+** Returns True if the device is in the list
+*******************************************************************************/
+static BOOLEAN dev_blacklisted_for_absolute_volume(BD_ADDR peer_dev)
+{
+ int i;
+ char *dev_name_str = NULL;
+ int whitelist_size = sizeof(rc_white_addr_prefix)/sizeof(rc_white_addr_prefix[0]);
+
+ for (i = 0; i < whitelist_size; i++) {
+ if (rc_white_addr_prefix[i][0] == peer_dev[0] &&
+ rc_white_addr_prefix[i][1] == peer_dev[1] &&
+ rc_white_addr_prefix[i][2] == peer_dev[2]) {
+ BTIF_TRACE_DEBUG("whitelist absolute volume for %02x:%02x:%02x",
+ peer_dev[0], peer_dev[1], peer_dev[2]);
+ return FALSE;
+ }
+ }
+
+ dev_name_str = BTM_SecReadDevName(peer_dev);
+ whitelist_size = sizeof(rc_white_name)/sizeof(char*);
+ if (dev_name_str != NULL) {
+ for (i = 0; i < whitelist_size; i++) {
+ if (strcmp(dev_name_str, rc_white_name[i]) == 0) {
+ BTIF_TRACE_DEBUG("whitelist absolute volume for %s", dev_name_str);
+ return FALSE;
+ }
+ }
+ }
+
+ BTIF_TRACE_WARNING("blacklist absolute volume for %02x:%02x:%02x, name = %s",
+ peer_dev[0], peer_dev[1], peer_dev[2], dev_name_str);
+ return TRUE;
+}
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index 44ccf33e4..895631194 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -187,6 +187,7 @@ bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr,int add,
btif_bonded_devices_t *p_bonded_devices);
bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
int *addr_type);
+bt_status_t btif_storage_check_ble_keys(bt_bdaddr_t *remote_bd_addr);
/************************************************************************************
** Static functions
@@ -404,6 +405,11 @@ static int cfg2prop(bt_bdaddr_t *remote_bd_addr, bt_property_t *prop)
{
bt_uuid_t *p_uuid = (bt_uuid_t*)prop->val;
uint32_t num_uuids = 0;
+ if( strlen(value) < 1279)
+ {
+ value[strlen(value)] = ' ';
+ value[strlen(value)+1] = '\0';
+ }
btif_in_split_uuids_string_to_list(value, p_uuid, &num_uuids);
prop->len = num_uuids * sizeof(bt_uuid_t);
ret = TRUE;
@@ -1241,6 +1247,18 @@ bt_status_t btif_storage_remove_ble_local_keys(void)
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
+bt_status_t btif_storage_check_ble_keys(bt_bdaddr_t *remote_bd_addr)
+{
+ bdstr_t bdstr;
+ int ret = BT_STATUS_FAIL;
+
+ bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+ BTIF_TRACE_DEBUG(" %s in bd addr:%s",__FUNCTION__, bdstr);
+ if(btif_config_exist(bdstr, "LE_KEY_PENC"))
+ ret = BT_STATUS_SUCCESS;
+ return ret;
+}
+
bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add, btif_bonded_devices_t *p_bonded_devices)
{
int device_type;
@@ -1254,11 +1272,12 @@ bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr, int add,
if (!btif_config_get_int(remote_bd_addr, "DevType", &device_type))
return BT_STATUS_FAIL;
- if ((device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
+ string_to_bdaddr(remote_bd_addr, &bd_addr);
+ if (((device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) ||
+ ((device_type == BT_DEVICE_TYPE_BREDR) && (btif_storage_check_ble_keys(&bd_addr) == BT_STATUS_SUCCESS)))
{
BTIF_TRACE_DEBUG("%s Found a LE device: %s", __func__, remote_bd_addr);
- string_to_bdaddr(remote_bd_addr, &bd_addr);
bdcpy(bta_bd_addr, bd_addr.address);
if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS)