A2DP_TWS:BT IPC initial changes
- Add aptx dual mono support for TWSP.
change-Id: I63d719db205799388225ba7d43b894a8b7b54ef2
Broadcast_Audio: add support for Broadcast_Audio
- add support for broadcast audio
change-Id: I5c8d90f6ef440baad55bf8c98d91d0b6d2284707
FR 48725: Support for additional rules related to vendor
- Renamed the properties according to new P treble rules.
Change-Id: Ieb193230d3fc021538831d0cfcd3954b4b2fed88
CRs-Fixed: 2251843
diff --git a/bthost_ipc/bthost_ipc.c b/bthost_ipc/bthost_ipc.c
index a6e66f3..f0a2897 100644
--- a/bthost_ipc/bthost_ipc.c
+++ b/bthost_ipc/bthost_ipc.c
@@ -1,6 +1,27 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (C) 2016-2017, The Linux Foundation. All rights reserved.
*
* Not a Contribution
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*****************************************************************************/
/*****************************************************************************
* Copyright (C) 2009-2012 Broadcom Corporation
@@ -86,8 +107,10 @@
audio_sbc_encoder_config_t sbc_codec;
audio_aptx_encoder_config_t aptx_codec;
+audio_aptx_tws_encoder_config_t aptx_tws_codec;
audio_aac_encoder_config_t aac_codec;
audio_ldac_encoder_config_t ldac_codec;
+audio_celt_encoder_config_t celt_codec;
/*****************************************************************************
** Functions
******************************************************************************/
@@ -397,6 +420,13 @@
if (sample_freq) *sample_freq = ldac_codec.sampling_rate;
return ((void *)&ldac_codec);
}
+ if (codec_cfg[VENDOR_ID_OFFSET] == VENDOR_APTX_HD &&
+ codec_cfg[CODEC_ID_OFFSET] == APTX_TWS_CODEC_ID)
+ {
+ ALOGW("AptX-TWS codec");
+ *codec_type = ENC_CODEC_TYPE_APTX_DUAL_MONO;
+ //aptx_codec.sync_mode = 0x01;
+ }
memset(&aptx_codec,0,sizeof(audio_aptx_encoder_config_t));
p_cfg++; //skip dev_idx
len = *p_cfg++;//LOSC
@@ -424,6 +454,7 @@
switch (byte & A2D_APTX_CHAN_MASK)
{
case A2D_APTX_CHAN_STEREO:
+ case A2D_APTX_TWS_CHAN_MODE:
aptx_codec.channels = 2;
break;
case A2D_APTX_CHAN_MONO:
@@ -449,8 +480,86 @@
if(sample_freq) *sample_freq = aptx_codec.sampling_rate;
ALOGW("APTx: Done copying full codec config");
+ if (*codec_type == ENC_CODEC_TYPE_APTX_DUAL_MONO)
+ {
+ memset(&aptx_tws_codec, 0, sizeof(audio_aptx_tws_encoder_config_t));
+ memcpy(&aptx_tws_codec, &aptx_codec, sizeof(aptx_codec));
+ aptx_tws_codec.sync_mode = 0x02;
+ return ((void *)&aptx_tws_codec);
+ }
return ((void *)&aptx_codec);
}
+ else if (codec_cfg[CODEC_OFFSET] == CODEC_TYPE_CELT)
+ {
+ uint8_t celt_samp_freq = 0;
+ uint32_t celt_bit_rate = 0;
+ memset(&celt_codec,0,sizeof(audio_celt_encoder_config_t));
+ switch(codec_cfg[4] & A2D_CELT_SAMP_FREQ_MASK)
+ {
+ case A2D_CELT_SAMP_FREQ_48:
+ celt_codec.sampling_rate = 48000;
+ break;
+ case A2D_CELT_SAMP_FREQ_44:
+ celt_codec.sampling_rate = 44100;
+ break;
+ case A2D_CELT_SAMP_FREQ_32:
+ celt_codec.sampling_rate = 32000;
+ break;
+ default:
+ ALOGE("CELT: unknown sampl freq");
+ }
+ switch(codec_cfg[4] & A2D_CELT_CHANNEL_MASK)
+ {
+ case A2D_CELT_CH_MONO:
+ celt_codec.channels = 1;
+ break;
+ case A2D_CELT_CH_STEREO:
+ celt_codec.channels = 2;
+ break;
+ default:
+ ALOGE("CELT: unknown channel");
+ }
+ switch(codec_cfg[5] & A2D_CELT_FRAME_SIZE_MASK)
+ {
+ case A2D_CELT_FRAME_SIZE_64:
+ celt_codec.frame_size = 64;
+ break;
+ case A2D_CELT_FRAME_SIZE_128:
+ celt_codec.frame_size = 128;
+ break;
+ case A2D_CELT_FRAME_SIZE_256:
+ celt_codec.frame_size = 256;
+ break;
+ case A2D_CELT_FRAME_SIZE_512:
+ celt_codec.frame_size = 512;
+ break;
+ default:
+ ALOGE("CELT: unknown frame size");
+ }
+ celt_codec.complexity = codec_cfg[5] & A2D_CELT_COMPLEXITY_MASK;
+ celt_codec.prediction_mode =
+ (codec_cfg[6] & A2D_CELT_PREDICTION_MODE_MASK) >> 4;
+ celt_codec.vbr_flag = codec_cfg[6] & A2D_CELT_VBR_MASK;
+
+ celt_codec.bitrate |= codec_cfg[7];
+ celt_codec.bitrate = celt_codec.bitrate << 8;
+ celt_codec.bitrate |= codec_cfg[8];
+ celt_codec.bitrate = celt_codec.bitrate << 8;
+ celt_codec.bitrate |= codec_cfg[9];
+ celt_codec.bitrate = celt_codec.bitrate << 8;
+ celt_codec.bitrate |= codec_cfg[10];
+ *codec_type = AUDIO_CODEC_TYPE_CELT;
+
+ ALOGE("CELT Bitrate: 0%x", celt_codec.bitrate);
+ ALOGE("CELT channel: 0%x", celt_codec.channels);
+ ALOGE("CELT complexity: 0%x", celt_codec.complexity);
+ ALOGE("CELT frame_size: 0%x", celt_codec.frame_size);
+ ALOGE("CELT prediction_mode: 0%x", celt_codec.prediction_mode);
+ ALOGE("CELT sampl_freq: 0%x", celt_codec.sampling_rate);
+ ALOGE("CELT vbr_flag: 0%x", celt_codec.vbr_flag);
+ ALOGE("CELT codec_type: 0%x", codec_type);
+ return ((void *)(&celt_codec));
+ }
return NULL;
}
@@ -553,6 +662,14 @@
pthread_mutex_unlock(&audio_stream.ack_lock);
return retry;
}
+ // in race condition, ack_status is updated as SUCCESS
+ // without ack_recvd made 0.
+ if (audio_stream.ack_status == A2DP_CTRL_ACK_SUCCESS)
+ {
+ ALOGE("ACK Success, no need to wait");
+ pthread_mutex_unlock(&audio_stream.ack_lock);
+ return retry;
+ }
while (retry < CTRL_CHAN_RETRY_COUNT &&
ack_recvd == 0)
{
@@ -605,7 +722,12 @@
{
ALOGW("bt_stack_on_stream_started: status = %d",status);
pthread_mutex_lock(&audio_stream.ack_lock);
- audio_stream.ack_status = status;
+ if ((audio_stream.ack_status != A2DP_CTRL_ACK_UNKNOWN) && (status == A2DP_CTRL_ACK_PENDING)) {
+ ALOGW("status already changed to = %d, don't update pending",audio_stream.ack_status);
+ }
+ else {
+ audio_stream.ack_status = status;
+ }
resp_received = true;
if (!ack_recvd)
{
@@ -617,23 +739,36 @@
void bt_stack_on_stream_suspended(tA2DP_CTRL_ACK status)
{
- ALOGW("bt_stack_on_stream_suspended");
+ ALOGW("bt_stack_on_stream_suspended status = %d, ack_status = %d ", status, audio_stream.ack_status);
pthread_mutex_lock(&audio_stream.ack_lock);
- audio_stream.ack_status = status;
+ if ((audio_stream.ack_status != A2DP_CTRL_ACK_UNKNOWN) && (status == A2DP_CTRL_ACK_PENDING)) {
+ ALOGW("status already changed to = %d, don't update pending",audio_stream.ack_status);
+ }
+ else {
+ audio_stream.ack_status = status;
+ ALOGW("bt_stack_on_stream_suspended updating ack_status = %d ", audio_stream.ack_status);
+ }
resp_received = true;
if (!ack_recvd)
{
ack_recvd = 1;
+ ALOGW("bt_stack_on_stream_suspended signalling pthread ");
pthread_cond_signal(&ack_cond);
}
pthread_mutex_unlock(&audio_stream.ack_lock);
+ ALOGW("bt_stack_on_stream_suspended mutex unlocked ");
}
void bt_stack_on_stream_stopped(tA2DP_CTRL_ACK status)
{
ALOGW("bt_stack_on_stream_stopped");
pthread_mutex_lock(&audio_stream.ack_lock);
- audio_stream.ack_status = status;
+ if ((audio_stream.ack_status != A2DP_CTRL_ACK_UNKNOWN) && (status == A2DP_CTRL_ACK_PENDING)) {
+ ALOGW("status already changed to = %d, don't update pending",audio_stream.ack_status);
+ }
+ else {
+ audio_stream.ack_status = status;
+ }
resp_received = true;
if (!ack_recvd)
{
@@ -1255,22 +1390,11 @@
ALOGW("audio_is_scrambling_enabled returned false due to stack deinit");
return false;
}
- if( property_get("persist.vendor.bt.splita2dp.44_1_war", value, "true"))
- {
- if(!strcmp(value, "false"))
- {
- ALOGW("persist.vendor.bt.splita2dp.44_1_war is not set");
- return false;
- }
- }
- else
- {
- ALOGE("Error in fetching persist.vendor.bt.splita2dp.44_1_war property");
- return false;
- }
- if( property_get("persist.vendor.bt.soc.scram_freqs", value, "false"))
+ if( property_get("persist.vendor.bluetooth.soc.scram_freqs", value, "false") &&
+ !strcmp(value, "false"))
{
+ property_get("persist.vendor.bt.soc.scram_freqs", value, "false");
if(!strcmp(value, "false"))
{
ALOGW("persist.vendor.bt.soc.scram_freqs is not set");
@@ -1279,7 +1403,7 @@
}
else
{
- ALOGE("Error in fetching persist.vendor.bt.soc.scram_freqs property");
+ ALOGE("Error in fetching persist.vendor.bluetooth.soc.scram_freqs property");
return false;
}
@@ -1298,7 +1422,19 @@
INFO("%s: a2dp stream not configured,wait 100mse & retry", __func__);
usleep(100000);
}
+ if (codec_type == ENC_CODEC_TYPE_APTX_DUAL_MONO) {
+ INFO("%s:TWSP codec, return false",__func__);
+ pthread_mutex_unlock(&audio_stream.lock);
+ return false;
+ }
if(status == A2DP_CTRL_ACK_SUCCESS) {
+
+ if (codec_type == CODEC_TYPE_CELT) {
+ INFO("%s: BA going on,return false", __func__);
+ pthread_mutex_unlock(&audio_stream.lock);
+ return false;
+ }
+
ALOGW("audio_is_scrambling_enabled sample_freq %ld",sample_freq);
switch (sample_freq) {
case 44100:
diff --git a/bthost_ipc/bthost_ipc.h b/bthost_ipc/bthost_ipc.h
index 96e1b7c..a962c0d 100644
--- a/bthost_ipc/bthost_ipc.h
+++ b/bthost_ipc/bthost_ipc.h
@@ -1,7 +1,28 @@
/******************************************************************************
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2016-2017, The Linux Foundation. All rights reserved.
*
* Not a Contribution
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*****************************************************************************/
/*****************************************************************************
* Copyright (C) 2009-2012 Broadcom Corporation
@@ -101,8 +122,11 @@
/*
codec specific definitions
*/
+#define AUDIO_CODEC_TYPE_CELT 603979776u // 0x24000000UL
+#define ENC_CODEC_TYPE_APTX_DUAL_MONO 570425344u // 0x22000000UL
#define CODEC_TYPE_SBC 0x00
#define CODEC_TYPE_AAC 0x02
+#define CODEC_TYPE_CELT 0xEF
#define NON_A2DP_CODEC_TYPE 0xFF
#define CODEC_OFFSET 3
#define VENDOR_ID_OFFSET 4
@@ -124,6 +148,9 @@
#ifndef APTX_HD_CODEC_ID
#define APTX_HD_CODEC_ID 0x24
#endif
+#ifndef APTX_TWS_CODEC_ID
+#define APTX_TWS_CODEC_ID 0x25
+#endif
#ifndef VENDOR_LDAC
#define VENDOR_LDAC 0x12D
@@ -163,6 +190,7 @@
#define A2D_APTX_CHAN_MASK 0x0F
#define A2D_APTX_CHAN_STEREO 0x02
#define A2D_APTX_CHAN_MONO 0x01
+#define A2D_APTX_TWS_CHAN_MODE 0x08
/* LDAC bitmask helper */
@@ -195,6 +223,32 @@
#define A2DP_DEFAULT_SINK_LATENCY 0
+
+// CELT Codec config in order.
+// 7-4 bits of first byte of codec_info element
+#define A2D_CELT_SAMP_FREQ_MASK 0xF0
+#define A2D_CELT_SAMP_FREQ_48 0x10
+#define A2D_CELT_SAMP_FREQ_44 0x20
+#define A2D_CELT_SAMP_FREQ_32 0x40
+// 0-3 bits of first byte of codec_info element
+#define A2D_CELT_CHANNEL_MASK 0x0F
+#define A2D_CELT_CH_MONO 0x01
+#define A2D_CELT_CH_STEREO 0x02
+// 7-4 bits of second byte: frame size
+#define A2D_CELT_FRAME_SIZE_MASK 0xF0
+#define A2D_CELT_FRAME_SIZE_64 0x10
+#define A2D_CELT_FRAME_SIZE_128 0x20
+#define A2D_CELT_FRAME_SIZE_256 0x40
+#define A2D_CELT_FRAME_SIZE_512 0x80
+//0-3 bits of second byte: actual value of complexity
+#define A2D_CELT_COMPLEXITY_MASK 0x0F
+// 7-4 bits of third byte: prediction mode
+#define A2D_CELT_PREDICTION_MODE_MASK 0xF0
+// 0th bit of third byte: vbr flag
+#define A2D_CELT_VBR_MASK 0x01
+
+// next 2 bytes is actual frame size
+// next 1 bytes is actual complexity
typedef struct {
uint32_t subband; /* 4, 8 */
uint32_t blk_len; /* 4, 8, 12, 16 */
@@ -226,6 +280,16 @@
uint32_t num_levels;
struct bit_rate_level_map_t bit_rate_level_map[MAX_LEVELS];
};
+/* Information about BT APTX encoder configuration
+ * This data is used between audio HAL module and
+ * BT IPC library to configure DSP encoder
+ */
+typedef struct {
+ uint16_t sampling_rate;
+ uint8_t channels;
+ uint32_t bitrate;
+ uint8_t sync_mode;
+} audio_aptx_tws_encoder_config_t;
/* Information about BT LDAC encoder configuration
* This data is used between audio HAL module and
@@ -252,6 +316,16 @@
uint32_t bitrate;
} audio_aac_encoder_config_t;
+typedef struct {
+ uint32_t sampling_rate; /* 32000 - 48000, 48000 */
+ uint16_t channels; /* 1-Mono, 2-Stereo, 2*/
+ uint16_t frame_size; /* 64-128-256-512, 512 */
+ uint16_t complexity; /* 0-10, 1 */
+ uint16_t prediction_mode; /* 0-1-2, 0 */
+ uint16_t vbr_flag; /* 0-1, 0*/
+ uint32_t bitrate; /*32000 - 1536000, 139500*/
+} audio_celt_encoder_config_t;
+
//HIDL callbacks to invoke callback to BT stack
typedef void (*bt_ipc_start_stream_req_cb)(void);
typedef void (*bt_ipc_suspend_stream_req_cb)(void);