The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * Copyright (C) 2004-2012 Broadcom Corporation |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at: |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | ******************************************************************************/ |
| 18 | |
| 19 | /****************************************************************************** |
| 20 | * |
| 21 | * This is the advanced audio/video call-out function implementation for |
| 22 | * BTIF. |
| 23 | * |
| 24 | ******************************************************************************/ |
| 25 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 26 | #include <string.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 27 | #include "a2d_api.h" |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 28 | #include "bt_target.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 29 | #include "bta_sys.h" |
| 30 | #include "bta_av_api.h" |
| 31 | #include "bta_av_co.h" |
| 32 | #include "bta_av_ci.h" |
| 33 | #include "bta_av_sbc.h" |
| 34 | |
| 35 | #include "btif_media.h" |
| 36 | #include "sbc_encoder.h" |
| 37 | #include "btif_av_co.h" |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 38 | #include "btif_util.h" |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 39 | #include "osi/include/mutex.h" |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 40 | #include "osi/include/osi.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 41 | |
| 42 | |
| 43 | /***************************************************************************** |
| 44 | ** Constants |
| 45 | *****************************************************************************/ |
| 46 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 47 | /* Macro to retrieve the number of elements in a statically allocated array */ |
| 48 | #define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a)/sizeof((__a)[0])) |
| 49 | |
| 50 | /* MIN and MAX macros */ |
| 51 | #define BTA_AV_CO_MIN(X,Y) ((X) < (Y) ? (X) : (Y)) |
| 52 | #define BTA_AV_CO_MAX(X,Y) ((X) > (Y) ? (X) : (Y)) |
| 53 | |
| 54 | /* Macro to convert audio handle to index and vice versa */ |
| 55 | #define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1) |
| 56 | #define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO) |
| 57 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 58 | /* SCMS-T protect info */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 59 | const uint8_t bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = {0x02, 0x02, 0x00}; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 60 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 61 | |
| 62 | /***************************************************************************** |
| 63 | ** Local data |
| 64 | *****************************************************************************/ |
| 65 | typedef struct |
| 66 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 67 | uint8_t sep_info_idx; /* local SEP index (in BTA tables) */ |
| 68 | uint8_t seid; /* peer SEP index (in peer tables) */ |
| 69 | uint8_t codec_type; /* peer SEP codec type */ |
| 70 | uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */ |
| 71 | uint8_t num_protect; /* peer SEP number of CP elements */ |
| 72 | uint8_t protect_info[BTA_AV_CP_INFO_LEN]; /* peer SEP content protection info */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 73 | } tBTA_AV_CO_SINK; |
| 74 | |
| 75 | typedef struct |
| 76 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 77 | BD_ADDR addr; /* address of audio/video peer */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 78 | tBTA_AV_CO_SINK sinks[A2D_CODEC_SEP_INDEX_MAX]; /* array of supported sinks */ |
| 79 | tBTA_AV_CO_SINK srcs[A2D_CODEC_SEP_INDEX_MAX]; /* array of supported srcs */ |
| 80 | uint8_t num_sinks; /* total number of sinks at peer */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 81 | uint8_t num_srcs; /* total number of srcs at peer */ |
| 82 | uint8_t num_seps; /* total number of seids at peer */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 83 | uint8_t num_rx_sinks; /* number of received sinks */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 84 | uint8_t num_rx_srcs; /* number of received srcs */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 85 | uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 86 | uint8_t num_sup_srcs; /* number of supported srcs in the srcs array */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 87 | const tBTA_AV_CO_SINK *p_sink; /* currently selected sink */ |
| 88 | const tBTA_AV_CO_SINK *p_src; /* currently selected src */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 89 | uint8_t codec_cfg[AVDT_CODEC_SIZE]; /* current codec configuration */ |
| 90 | bool cp_active; /* current CP configuration */ |
| 91 | bool acp; /* acceptor */ |
| 92 | bool recfg_needed; /* reconfiguration is needed */ |
| 93 | bool opened; /* opened */ |
| 94 | uint16_t mtu; /* maximum transmit unit size */ |
| 95 | uint16_t uuid_to_connect; /* uuid of peer device */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 96 | } tBTA_AV_CO_PEER; |
| 97 | |
| 98 | typedef struct |
| 99 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 100 | bool active; |
| 101 | uint8_t flag; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 102 | } tBTA_AV_CO_CP; |
| 103 | |
| 104 | typedef struct |
| 105 | { |
| 106 | /* Connected peer information */ |
| 107 | tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS]; |
| 108 | /* Current codec configuration - access to this variable must be protected */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 109 | uint8_t codec_cfg[AVDT_CODEC_SIZE]; |
| 110 | uint8_t codec_cfg_setconfig[AVDT_CODEC_SIZE]; /* remote peer setconfig preference */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 111 | |
| 112 | tBTA_AV_CO_CP cp; |
| 113 | } tBTA_AV_CO_CB; |
| 114 | |
| 115 | /* Control block instance */ |
| 116 | static tBTA_AV_CO_CB bta_av_co_cb; |
| 117 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 118 | static bool bta_av_co_cp_is_scmst(const uint8_t *p_protectinfo); |
| 119 | static bool bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 120 | static const tBTA_AV_CO_SINK* bta_av_co_find_peer_sink_supports_codec( |
| 121 | const tBTA_AV_CO_PEER *p_peer); |
| 122 | static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( |
| 123 | const tBTA_AV_CO_PEER *p_peer); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 124 | |
| 125 | /******************************************************************************* |
| 126 | ** |
| 127 | ** Function bta_av_co_cp_get_flag |
| 128 | ** |
| 129 | ** Description Get content protection flag |
| 130 | ** BTA_AV_CP_SCMS_COPY_NEVER |
| 131 | ** BTA_AV_CP_SCMS_COPY_ONCE |
| 132 | ** BTA_AV_CP_SCMS_COPY_FREE |
| 133 | ** |
| 134 | ** Returns The current flag value |
| 135 | ** |
| 136 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 137 | static uint8_t bta_av_co_cp_get_flag(void) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 138 | { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 139 | return bta_av_co_cb.cp.flag; |
| 140 | } |
| 141 | |
| 142 | /******************************************************************************* |
| 143 | ** |
| 144 | ** Function bta_av_co_cp_set_flag |
| 145 | ** |
| 146 | ** Description Set content protection flag |
| 147 | ** BTA_AV_CP_SCMS_COPY_NEVER |
| 148 | ** BTA_AV_CP_SCMS_COPY_ONCE |
| 149 | ** BTA_AV_CP_SCMS_COPY_FREE |
| 150 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 151 | ** Returns true if setting the SCMS flag is supported else false |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 152 | ** |
| 153 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 154 | static bool bta_av_co_cp_set_flag(uint8_t cp_flag) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 155 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 156 | APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 157 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 158 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 159 | #else |
| 160 | if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE) |
| 161 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 162 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 163 | } |
| 164 | #endif |
| 165 | bta_av_co_cb.cp.flag = cp_flag; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 166 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | /******************************************************************************* |
| 170 | ** |
| 171 | ** Function bta_av_co_get_peer |
| 172 | ** |
| 173 | ** Description find the peer entry for a given handle |
| 174 | ** |
| 175 | ** Returns the control block |
| 176 | ** |
| 177 | *******************************************************************************/ |
| 178 | static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl) |
| 179 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 180 | uint8_t index; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 181 | |
| 182 | index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl); |
| 183 | |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 184 | APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index); |
| 185 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 186 | /* Sanity check */ |
| 187 | if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) |
| 188 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 189 | APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 190 | return NULL; |
| 191 | } |
| 192 | |
| 193 | return &bta_av_co_cb.peers[index]; |
| 194 | } |
| 195 | |
| 196 | /******************************************************************************* |
| 197 | ** |
| 198 | ** Function bta_av_co_audio_init |
| 199 | ** |
| 200 | ** Description This callout function is executed by AV when it is |
| 201 | ** started by calling BTA_AvRegister(). This function can be |
| 202 | ** used by the phone to initialize audio paths or for other |
| 203 | ** initialization purposes. |
| 204 | ** |
| 205 | ** |
| 206 | ** Returns Stream codec and content protection capabilities info. |
| 207 | ** |
| 208 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 209 | bool bta_av_co_audio_init(tA2D_CODEC_SEP_INDEX codec_sep_index, |
| 210 | tAVDT_CFG *p_cfg) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 211 | { |
Anubhav Gupta | d81bd01 | 2014-06-19 16:50:11 +0530 | [diff] [blame] | 212 | /* reset remote preference through setconfig */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 213 | memset(bta_av_co_cb.codec_cfg_setconfig, 0, |
| 214 | sizeof(bta_av_co_cb.codec_cfg_setconfig)); |
Anubhav Gupta | d81bd01 | 2014-06-19 16:50:11 +0530 | [diff] [blame] | 215 | |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 216 | return A2D_InitCodecConfig(codec_sep_index, p_cfg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 217 | } |
| 218 | |
| 219 | /******************************************************************************* |
| 220 | ** |
| 221 | ** Function bta_av_co_audio_disc_res |
| 222 | ** |
| 223 | ** Description This callout function is executed by AV to report the |
| 224 | ** number of stream end points (SEP) were found during the |
| 225 | ** AVDT stream discovery process. |
| 226 | ** |
| 227 | ** |
| 228 | ** Returns void. |
| 229 | ** |
| 230 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 231 | void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps, |
| 232 | uint8_t num_sink, uint8_t num_src, BD_ADDR addr, |
| 233 | uint16_t uuid_local) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 234 | { |
| 235 | tBTA_AV_CO_PEER *p_peer; |
| 236 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 237 | APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d", |
| 238 | __func__, hndl, num_seps, num_sink, num_src); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 239 | |
| 240 | /* Find the peer info */ |
| 241 | p_peer = bta_av_co_get_peer(hndl); |
| 242 | if (p_peer == NULL) |
| 243 | { |
Pavlin Radoslavov | 89330a3 | 2016-08-24 11:46:58 -0700 | [diff] [blame] | 244 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 245 | return; |
| 246 | } |
| 247 | |
| 248 | /* Sanity check : this should never happen */ |
| 249 | if (p_peer->opened) |
| 250 | { |
Pavlin Radoslavov | 89330a3 | 2016-08-24 11:46:58 -0700 | [diff] [blame] | 251 | APPL_TRACE_ERROR("%s: peer already opened", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | /* Copy the discovery results */ |
| 255 | bdcpy(p_peer->addr, addr); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 256 | p_peer->num_sinks = num_sink; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 257 | p_peer->num_srcs = num_src; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 258 | p_peer->num_seps = num_seps; |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 259 | p_peer->num_rx_sinks = 0; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 260 | p_peer->num_rx_srcs = 0; |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 261 | p_peer->num_sup_sinks = 0; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 262 | if (uuid_local == UUID_SERVCLASS_AUDIO_SINK) |
| 263 | p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE; |
| 264 | else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE) |
| 265 | p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | /******************************************************************************* |
| 269 | ** |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 270 | ** Function bta_av_audio_sink_getconfig |
| 271 | ** |
| 272 | ** Description This callout function is executed by AV to retrieve the |
| 273 | ** desired codec and content protection configuration for the |
| 274 | ** A2DP Sink audio stream in Initiator. |
| 275 | ** |
| 276 | ** |
| 277 | ** Returns Pass or Fail for current getconfig. |
| 278 | ** |
| 279 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 280 | static tA2D_STATUS bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl, |
| 281 | tA2D_CODEC_TYPE codec_type, |
| 282 | uint8_t *p_codec_info, |
| 283 | uint8_t *p_sep_info_idx, |
| 284 | uint8_t seid, |
| 285 | uint8_t *p_num_protect, |
| 286 | uint8_t *p_protect_info) |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 287 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 288 | tA2D_STATUS result = A2D_FAIL; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 289 | bool supported; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 290 | tBTA_AV_CO_PEER *p_peer; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 291 | uint8_t pref_cfg[AVDT_CODEC_SIZE]; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 292 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 293 | APPL_TRACE_DEBUG("%s: handle:0x%x codec_type:%d seid:%d", |
| 294 | __func__, hndl, codec_type, seid); |
| 295 | APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", |
| 296 | __func__, *p_num_protect, p_protect_info[0], |
| 297 | p_protect_info[1], p_protect_info[2]); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 298 | |
| 299 | /* Retrieve the peer info */ |
| 300 | p_peer = bta_av_co_get_peer(hndl); |
| 301 | if (p_peer == NULL) |
| 302 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 303 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 304 | return A2D_FAIL; |
| 305 | } |
| 306 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 307 | APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)", |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 308 | __func__, p_peer->opened, p_peer->num_srcs, |
| 309 | p_peer->num_rx_srcs, p_peer->num_sup_srcs); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 310 | |
| 311 | p_peer->num_rx_srcs++; |
| 312 | |
| 313 | /* Check if this is a supported configuration */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 314 | supported = false; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 315 | switch (codec_type) |
| 316 | { |
Pavlin Radoslavov | 89330a3 | 2016-08-24 11:46:58 -0700 | [diff] [blame] | 317 | case A2D_MEDIA_CT_SBC: |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 318 | supported = true; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 319 | break; |
| 320 | |
| 321 | default: |
| 322 | break; |
| 323 | } |
| 324 | |
| 325 | if (supported) |
| 326 | { |
| 327 | /* If there is room for a new one */ |
| 328 | if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) |
| 329 | { |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 330 | tBTA_AV_CO_SINK *p_src = &p_peer->srcs[p_peer->num_sup_srcs++]; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 331 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 332 | APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", |
| 333 | __func__, p_codec_info[1], p_codec_info[2], |
| 334 | p_codec_info[3], p_codec_info[4], p_codec_info[5], |
| 335 | p_codec_info[6]); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 336 | |
| 337 | memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE); |
| 338 | p_src->codec_type = codec_type; |
| 339 | p_src->sep_info_idx = *p_sep_info_idx; |
| 340 | p_src->seid = seid; |
| 341 | p_src->num_protect = *p_num_protect; |
| 342 | memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN); |
| 343 | } |
| 344 | else |
| 345 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 346 | APPL_TRACE_ERROR("%s: no more room for SRC info", __func__); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 347 | } |
| 348 | } |
| 349 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 350 | /* If last SINK get capabilities or all supported codec caps retrieved */ |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 351 | if ((p_peer->num_rx_srcs == p_peer->num_srcs) || |
| 352 | (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) |
| 353 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 354 | APPL_TRACE_DEBUG("%s: last SRC reached", __func__); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 355 | |
| 356 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 357 | mutex_global_lock(); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 358 | |
| 359 | /* Find a src that matches the codec config */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 360 | const tBTA_AV_CO_SINK *p_src = |
| 361 | bta_av_co_find_peer_src_supports_codec(p_peer); |
| 362 | if (p_src != NULL) { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 363 | APPL_TRACE_DEBUG("%s: codec supported", __func__); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 364 | |
| 365 | /* Build the codec configuration for this sink */ |
| 366 | { |
| 367 | /* Save the new configuration */ |
| 368 | p_peer->p_src = p_src; |
| 369 | /* get preferred config from src_caps */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 370 | if (A2D_BuildSrc2SinkConfig(p_src->codec_caps, pref_cfg) != |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 371 | A2D_SUCCESS) { |
| 372 | mutex_global_unlock(); |
| 373 | return A2D_FAIL; |
| 374 | } |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 375 | memcpy(p_peer->codec_cfg, pref_cfg, AVDT_CODEC_SIZE); |
| 376 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 377 | APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", |
| 378 | __func__, p_peer->codec_cfg[1], |
| 379 | p_peer->codec_cfg[2], p_peer->codec_cfg[3], |
| 380 | p_peer->codec_cfg[4], p_peer->codec_cfg[5], |
| 381 | p_peer->codec_cfg[6]); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 382 | /* By default, no content protection */ |
| 383 | *p_num_protect = 0; |
| 384 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 385 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
| 386 | p_peer->cp_active = false; |
| 387 | bta_av_co_cb.cp.active = false; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 388 | #endif |
| 389 | |
| 390 | *p_sep_info_idx = p_src->sep_info_idx; |
| 391 | memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE); |
| 392 | result = A2D_SUCCESS; |
| 393 | } |
| 394 | } |
| 395 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 396 | mutex_global_unlock(); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 397 | } |
| 398 | return result; |
| 399 | } |
| 400 | /******************************************************************************* |
| 401 | ** |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 402 | ** Function bta_av_co_audio_getconfig |
| 403 | ** |
| 404 | ** Description This callout function is executed by AV to retrieve the |
| 405 | ** desired codec and content protection configuration for the |
| 406 | ** audio stream. |
| 407 | ** |
| 408 | ** |
| 409 | ** Returns Stream codec and content protection configuration info. |
| 410 | ** |
| 411 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 412 | tA2D_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, |
| 413 | tA2D_CODEC_TYPE codec_type, |
| 414 | uint8_t *p_codec_info, |
| 415 | uint8_t *p_sep_info_idx, uint8_t seid, |
| 416 | uint8_t *p_num_protect, |
| 417 | uint8_t *p_protect_info) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 418 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 419 | tA2D_STATUS result = A2D_FAIL; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 420 | bool supported; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 421 | tBTA_AV_CO_PEER *p_peer; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 422 | uint8_t codec_cfg[AVDT_CODEC_SIZE]; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 423 | |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 424 | APPL_TRACE_DEBUG("%s: codec_type = %d", __func__, codec_type); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 425 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 426 | /* Retrieve the peer info */ |
| 427 | p_peer = bta_av_co_get_peer(hndl); |
| 428 | if (p_peer == NULL) |
| 429 | { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 430 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 431 | return A2D_FAIL; |
| 432 | } |
| 433 | |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 434 | if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) |
| 435 | { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 436 | result = bta_av_audio_sink_getconfig(hndl, codec_type, p_codec_info, |
| 437 | p_sep_info_idx, seid, |
| 438 | p_num_protect, p_protect_info); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 439 | return result; |
| 440 | } |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 441 | APPL_TRACE_DEBUG("%s: handle:0x%x codec_type:%d seid:%d", |
| 442 | __func__, hndl, codec_type, seid); |
| 443 | APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", |
| 444 | __func__, *p_num_protect, p_protect_info[0], |
| 445 | p_protect_info[1], p_protect_info[2]); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 446 | APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", |
| 447 | __func__, p_peer->opened, p_peer->num_sinks, |
| 448 | p_peer->num_rx_sinks, p_peer->num_sup_sinks); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 449 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 450 | p_peer->num_rx_sinks++; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 451 | |
| 452 | /* Check if this is a supported configuration */ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 453 | supported = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 454 | switch (codec_type) |
| 455 | { |
Pavlin Radoslavov | 89330a3 | 2016-08-24 11:46:58 -0700 | [diff] [blame] | 456 | case A2D_MEDIA_CT_SBC: |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 457 | supported = true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 458 | break; |
| 459 | |
| 460 | default: |
| 461 | break; |
| 462 | } |
| 463 | |
| 464 | if (supported) |
| 465 | { |
| 466 | /* If there is room for a new one */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 467 | if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) { |
| 468 | tBTA_AV_CO_SINK *p_sink = &p_peer->sinks[p_peer->num_sup_sinks++]; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 469 | |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 470 | APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__, |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 471 | p_codec_info[1], p_codec_info[2], p_codec_info[3], |
| 472 | p_codec_info[4], p_codec_info[5], p_codec_info[6]); |
| 473 | |
| 474 | memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); |
| 475 | p_sink->codec_type = codec_type; |
| 476 | p_sink->sep_info_idx = *p_sep_info_idx; |
| 477 | p_sink->seid = seid; |
| 478 | p_sink->num_protect = *p_num_protect; |
| 479 | memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN); |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 480 | } else { |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 481 | APPL_TRACE_ERROR("%s: no more room for SINK info", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 482 | } |
| 483 | } |
| 484 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 485 | /* If last SINK get capabilities or all supported codec capa retrieved */ |
| 486 | if ((p_peer->num_rx_sinks == p_peer->num_sinks) || |
| 487 | (p_peer->num_sup_sinks == BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 488 | APPL_TRACE_DEBUG("%s: last sink reached", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 489 | |
| 490 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 491 | mutex_global_lock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 492 | |
| 493 | /* Find a sink that matches the codec config */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 494 | const tBTA_AV_CO_SINK *p_sink = |
| 495 | bta_av_co_find_peer_sink_supports_codec(p_peer); |
| 496 | if (p_sink != NULL) { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 497 | /* stop fetching caps once we retrieved a supported codec */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 498 | if (p_peer->acp) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 499 | APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 500 | *p_sep_info_idx = p_peer->num_seps; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 501 | } |
| 502 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 503 | /* Build the codec configuration for this sink */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 504 | memset(codec_cfg, 0, AVDT_CODEC_SIZE); |
| 505 | if (A2D_BuildSinkConfig(bta_av_co_cb.codec_cfg, |
| 506 | p_sink->codec_caps, codec_cfg) == |
| 507 | A2D_SUCCESS) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 508 | APPL_TRACE_DEBUG("%s: reconfig codec_cfg[%x:%x:%x:%x:%x:%x]", |
| 509 | __func__, |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 510 | codec_cfg[1], codec_cfg[2], codec_cfg[3], |
| 511 | codec_cfg[4], codec_cfg[5], codec_cfg[6]); |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 512 | for (int i = 0; i < AVDT_CODEC_SIZE; i++) { |
| 513 | APPL_TRACE_DEBUG("%s: p_codec_info[%d]: %x", |
| 514 | __func__, i, p_codec_info[i]); |
| 515 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 516 | |
| 517 | /* Save the new configuration */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 518 | p_peer->p_sink = p_sink; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 519 | memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); |
| 520 | |
| 521 | /* By default, no content protection */ |
| 522 | *p_num_protect = 0; |
| 523 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 524 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 525 | /* Check if this sink supports SCMS */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 526 | p_peer->cp_active = bta_av_co_audio_sink_has_scmst(p_sink); |
| 527 | bta_av_co_cb.cp.active = p_peer->cp_active; |
| 528 | if (p_peer->cp_active) { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 529 | *p_num_protect = BTA_AV_CP_INFO_LEN; |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 530 | memcpy(p_protect_info, bta_av_co_cp_scmst, |
| 531 | BTA_AV_CP_INFO_LEN); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 532 | } |
| 533 | #endif |
| 534 | |
| 535 | /* If acceptor -> reconfig otherwise reply for configuration */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 536 | if (p_peer->acp) { |
| 537 | if (p_peer->recfg_needed) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 538 | APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", |
| 539 | __func__, hndl); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 540 | BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, |
| 541 | p_peer->codec_cfg, *p_num_protect, |
| 542 | bta_av_co_cp_scmst); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 543 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 544 | } else { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 545 | *p_sep_info_idx = p_sink->sep_info_idx; |
| 546 | memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE); |
| 547 | } |
| 548 | result = A2D_SUCCESS; |
| 549 | } |
| 550 | } |
| 551 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 552 | mutex_global_unlock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 553 | } |
| 554 | return result; |
| 555 | } |
| 556 | |
| 557 | /******************************************************************************* |
| 558 | ** |
| 559 | ** Function bta_av_co_audio_setconfig |
| 560 | ** |
| 561 | ** Description This callout function is executed by AV to set the codec and |
| 562 | ** content protection configuration of the audio stream. |
| 563 | ** |
| 564 | ** |
| 565 | ** Returns void |
| 566 | ** |
| 567 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 568 | void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type, |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 569 | uint8_t *p_codec_info, UNUSED_ATTR uint8_t seid, |
| 570 | UNUSED_ATTR BD_ADDR addr, uint8_t num_protect, |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 571 | uint8_t *p_protect_info, uint8_t t_local_sep, |
| 572 | uint8_t avdt_handle) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 573 | { |
| 574 | tBTA_AV_CO_PEER *p_peer; |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 575 | tA2D_STATUS status = A2D_SUCCESS; |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 576 | uint8_t category = A2D_SUCCESS; |
| 577 | bool recfg_needed = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 578 | |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 579 | APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", |
| 580 | __func__, |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 581 | p_codec_info[1], p_codec_info[2], p_codec_info[3], |
| 582 | p_codec_info[4], p_codec_info[5], p_codec_info[6]); |
Sharvil Nanavati | e8c3d75 | 2014-05-04 10:12:26 -0700 | [diff] [blame] | 583 | APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 584 | num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]); |
| 585 | |
| 586 | /* Retrieve the peer info */ |
| 587 | p_peer = bta_av_co_get_peer(hndl); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 588 | if (p_peer == NULL) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 589 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 590 | /* Call call-in rejecting the configuration */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 591 | bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, false, |
| 592 | avdt_handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 593 | return; |
| 594 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 595 | |
| 596 | APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", |
| 597 | __func__, p_peer->opened, p_peer->num_sinks, |
| 598 | p_peer->num_rx_sinks, p_peer->num_sup_sinks); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 599 | |
| 600 | /* Sanity check: should not be opened at this point */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 601 | if (p_peer->opened) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 602 | APPL_TRACE_ERROR("%s: peer already in use", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 603 | } |
| 604 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 605 | if (num_protect != 0) { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 606 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 607 | /* If CP is supported */ |
| 608 | if ((num_protect != 1) || |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 609 | (bta_av_co_cp_is_scmst(p_protect_info) == false)) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 610 | APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 611 | status = A2D_BAD_CP_TYPE; |
| 612 | category = AVDT_ASC_PROTECT; |
| 613 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 614 | #else |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 615 | /* Do not support content protection for the time being */ |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 616 | APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 617 | status = A2D_BAD_CP_TYPE; |
| 618 | category = AVDT_ASC_PROTECT; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 619 | #endif |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 620 | } |
| 621 | |
| 622 | if (status == A2D_SUCCESS) { |
| 623 | bool codec_cfg_supported = false; |
| 624 | if (t_local_sep == AVDT_TSEP_SNK) { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 625 | APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 626 | codec_cfg_supported = A2D_IsSinkCodecSupported(p_codec_info); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 627 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 628 | if (t_local_sep == AVDT_TSEP_SRC) { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 629 | APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 630 | codec_cfg_supported = A2D_IsSourceCodecSupported(p_codec_info); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 631 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 632 | |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 633 | /* Check if codec configuration is supported */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 634 | if (codec_cfg_supported) { |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 635 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 636 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 637 | mutex_global_lock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 638 | |
| 639 | /* Check if the configuration matches the current codec config */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 640 | if (A2D_CodecRequiresReconfig(p_codec_info, |
| 641 | bta_av_co_cb.codec_cfg)) { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 642 | recfg_needed = true; |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 643 | } else if ((num_protect == 1) && (!bta_av_co_cb.cp.active)) { |
| 644 | recfg_needed = true; |
| 645 | } |
| 646 | memcpy(bta_av_co_cb.codec_cfg_setconfig, p_codec_info, |
| 647 | AVDT_CODEC_SIZE); |
| 648 | if (t_local_sep == AVDT_TSEP_SNK) { |
| 649 | /* |
| 650 | * If Peer is SRC, and our cfg subset matches with what is |
| 651 | * requested by peer, then just accept what peer wants. |
| 652 | */ |
| 653 | memcpy(bta_av_co_cb.codec_cfg, p_codec_info, AVDT_CODEC_SIZE); |
| 654 | recfg_needed = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 655 | } |
| 656 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 657 | mutex_global_unlock(); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 658 | } else { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 659 | category = AVDT_ASC_CODEC; |
| 660 | status = A2D_WRONG_CODEC; |
| 661 | } |
| 662 | } |
| 663 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 664 | if (status != A2D_SUCCESS) { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 665 | APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 666 | /* Call call-in rejecting the configuration */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 667 | bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, |
| 668 | avdt_handle); |
| 669 | return; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 670 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 671 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 672 | /* Mark that this is an acceptor peer */ |
| 673 | p_peer->acp = true; |
| 674 | p_peer->recfg_needed = recfg_needed; |
| 675 | APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, recfg_needed); |
| 676 | /* Call call-in accepting the configuration */ |
| 677 | bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed, |
| 678 | avdt_handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 679 | } |
| 680 | |
| 681 | /******************************************************************************* |
| 682 | ** |
| 683 | ** Function bta_av_co_audio_open |
| 684 | ** |
| 685 | ** Description This function is called by AV when the audio stream connection |
| 686 | ** is opened. |
| 687 | ** |
| 688 | ** |
| 689 | ** Returns void |
| 690 | ** |
| 691 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 692 | void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type, |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 693 | uint8_t *p_codec_info, uint16_t mtu) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 694 | { |
| 695 | tBTA_AV_CO_PEER *p_peer; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 696 | UNUSED(p_codec_info); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 697 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 698 | APPL_TRACE_DEBUG("%s: mtu:%d codec_type:%d", __func__, mtu, codec_type); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 699 | |
| 700 | /* Retrieve the peer info */ |
| 701 | p_peer = bta_av_co_get_peer(hndl); |
| 702 | if (p_peer == NULL) |
| 703 | { |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 704 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 705 | } |
| 706 | else |
| 707 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 708 | p_peer->opened = true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 709 | p_peer->mtu = mtu; |
| 710 | } |
| 711 | } |
| 712 | |
| 713 | /******************************************************************************* |
| 714 | ** |
| 715 | ** Function bta_av_co_audio_close |
| 716 | ** |
| 717 | ** Description This function is called by AV when the audio stream connection |
| 718 | ** is closed. |
| 719 | ** |
| 720 | ** |
| 721 | ** Returns void |
| 722 | ** |
| 723 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 724 | void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type, |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 725 | uint16_t mtu) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 726 | |
| 727 | { |
| 728 | tBTA_AV_CO_PEER *p_peer; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 729 | UNUSED(codec_type); |
| 730 | UNUSED(mtu); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 731 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 732 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 733 | |
| 734 | /* Retrieve the peer info */ |
| 735 | p_peer = bta_av_co_get_peer(hndl); |
| 736 | if (p_peer) |
| 737 | { |
| 738 | /* Mark the peer closed and clean the peer info */ |
| 739 | memset(p_peer, 0, sizeof(*p_peer)); |
| 740 | } |
| 741 | else |
| 742 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 743 | APPL_TRACE_ERROR("%s: could not find peer entry", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 744 | } |
| 745 | |
| 746 | /* reset remote preference through setconfig */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 747 | memset(bta_av_co_cb.codec_cfg_setconfig, 0, |
| 748 | sizeof(bta_av_co_cb.codec_cfg_setconfig)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 749 | } |
| 750 | |
| 751 | /******************************************************************************* |
| 752 | ** |
| 753 | ** Function bta_av_co_audio_start |
| 754 | ** |
| 755 | ** Description This function is called by AV when the audio streaming data |
| 756 | ** transfer is started. |
| 757 | ** |
| 758 | ** |
| 759 | ** Returns void |
| 760 | ** |
| 761 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 762 | void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type, |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 763 | uint8_t *p_codec_info, bool *p_no_rtp_hdr) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 764 | { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 765 | UNUSED(hndl); |
| 766 | UNUSED(codec_type); |
| 767 | UNUSED(p_codec_info); |
| 768 | UNUSED(p_no_rtp_hdr); |
| 769 | |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 770 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 771 | } |
| 772 | |
| 773 | /******************************************************************************* |
| 774 | ** |
| 775 | ** Function bta_av_co_audio_stop |
| 776 | ** |
| 777 | ** Description This function is called by AV when the audio streaming data |
| 778 | ** transfer is stopped. |
| 779 | ** |
| 780 | ** |
| 781 | ** Returns void |
| 782 | ** |
| 783 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 784 | void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 785 | { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 786 | UNUSED(hndl); |
| 787 | UNUSED(codec_type); |
| 788 | |
Pavlin Radoslavov | 7aaf7c6 | 2016-08-23 12:24:03 -0700 | [diff] [blame] | 789 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 790 | } |
| 791 | |
| 792 | /******************************************************************************* |
| 793 | ** |
| 794 | ** Function bta_av_co_audio_src_data_path |
| 795 | ** |
| 796 | ** Description This function is called to manage data transfer from |
| 797 | ** the audio codec to AVDTP. |
| 798 | ** |
| 799 | ** Returns Pointer to the GKI buffer to send, NULL if no buffer to send |
| 800 | ** |
| 801 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 802 | void * bta_av_co_audio_src_data_path(tA2D_CODEC_TYPE codec_type, |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 803 | UNUSED_ATTR uint32_t *p_len, |
| 804 | uint32_t *p_timestamp) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 805 | { |
| 806 | BT_HDR *p_buf; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 807 | |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 808 | APPL_TRACE_DEBUG("%s: codec_type = %d", __func__, codec_type); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 809 | |
| 810 | p_buf = btif_media_aa_readbuf(); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 811 | if (p_buf == NULL) |
| 812 | return NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 813 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 814 | switch (codec_type) { |
| 815 | case A2D_MEDIA_CT_SBC: |
| 816 | /* In media packet SBC, the following information is available: |
| 817 | * p_buf->layer_specific : number of SBC frames in the packet |
| 818 | * p_buf->word[0] : timestamp |
| 819 | */ |
| 820 | /* Retrieve the timestamp information from the media packet */ |
| 821 | *p_timestamp = *((uint32_t *) (p_buf + 1)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 822 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 823 | /* Set up packet header */ |
| 824 | bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific); |
| 825 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 826 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 827 | default: |
| 828 | APPL_TRACE_ERROR("%s: unsupported codec type (%d)", __func__, |
| 829 | codec_type); |
| 830 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 831 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 832 | |
| 833 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
| 834 | if (bta_av_co_cb.cp.active) { |
| 835 | p_buf->len++; |
| 836 | p_buf->offset--; |
| 837 | uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset; |
| 838 | *p = bta_av_co_cp_get_flag(); |
| 839 | } |
| 840 | #endif |
| 841 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 842 | return p_buf; |
| 843 | } |
| 844 | |
| 845 | /******************************************************************************* |
| 846 | ** |
| 847 | ** Function bta_av_co_audio_drop |
| 848 | ** |
| 849 | ** Description An Audio packet is dropped. . |
| 850 | ** It's very likely that the connected headset with this handle |
| 851 | ** is moved far away. The implementation may want to reduce |
| 852 | ** the encoder bit rate setting to reduce the packet size. |
| 853 | ** |
| 854 | ** Returns void |
| 855 | ** |
| 856 | *******************************************************************************/ |
| 857 | void bta_av_co_audio_drop(tBTA_AV_HNDL hndl) |
| 858 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 859 | APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", |
| 860 | __func__, hndl); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 861 | } |
| 862 | |
| 863 | /******************************************************************************* |
| 864 | ** |
| 865 | ** Function bta_av_co_audio_delay |
| 866 | ** |
| 867 | ** Description This function is called by AV when the audio stream connection |
| 868 | ** needs to send the initial delay report to the connected SRC. |
| 869 | ** |
| 870 | ** |
| 871 | ** Returns void |
| 872 | ** |
| 873 | *******************************************************************************/ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 874 | void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 875 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 876 | APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 877 | } |
| 878 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 879 | /******************************************************************************* |
| 880 | ** |
| 881 | ** Function bta_av_co_cp_is_scmst |
| 882 | ** |
| 883 | ** Description Check if a content protection service is SCMS-T |
| 884 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 885 | ** Returns true if this CP is SCMS-T, false otherwise |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 886 | ** |
| 887 | *******************************************************************************/ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 888 | static bool bta_av_co_cp_is_scmst(const uint8_t *p_protectinfo) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 889 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 890 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 891 | |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 892 | if (*p_protectinfo >= BTA_AV_CP_LOSC) { |
| 893 | uint16_t cp_id; |
| 894 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 895 | p_protectinfo++; |
| 896 | STREAM_TO_UINT16(cp_id, p_protectinfo); |
| 897 | if (cp_id == BTA_AV_CP_SCMS_T_ID) |
| 898 | { |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 899 | APPL_TRACE_DEBUG("%s: SCMS-T found", __func__); |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 900 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 901 | } |
| 902 | } |
| 903 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 904 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 905 | } |
| 906 | |
| 907 | /******************************************************************************* |
| 908 | ** |
| 909 | ** Function bta_av_co_audio_sink_has_scmst |
| 910 | ** |
| 911 | ** Description Check if a sink supports SCMS-T |
| 912 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 913 | ** Returns true if the sink supports this CP, false otherwise |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 914 | ** |
| 915 | *******************************************************************************/ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 916 | static bool bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 917 | { |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 918 | uint8_t index; |
| 919 | const uint8_t *p; |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 920 | |
| 921 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 922 | |
| 923 | /* Check if sink supports SCMS-T */ |
| 924 | index = p_sink->num_protect; |
| 925 | p = &p_sink->protect_info[0]; |
| 926 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 927 | while (index) { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 928 | if (bta_av_co_cp_is_scmst(p)) |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 929 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 930 | /* Move to the next SC */ |
| 931 | p += *p + 1; |
| 932 | /* Decrement the SC counter */ |
| 933 | index--; |
| 934 | } |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 935 | APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__); |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 936 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 937 | } |
| 938 | |
| 939 | /******************************************************************************* |
| 940 | ** |
| 941 | ** Function bta_av_co_audio_sink_supports_cp |
| 942 | ** |
| 943 | ** Description Check if a sink supports the current content protection |
| 944 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 945 | ** Returns true if the sink supports this CP, false otherwise |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 946 | ** |
| 947 | *******************************************************************************/ |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 948 | static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 949 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 950 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 951 | |
| 952 | /* Check if content protection is enabled for this stream */ |
| 953 | if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 954 | return bta_av_co_audio_sink_has_scmst(p_sink); |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 955 | |
| 956 | APPL_TRACE_DEBUG("%s: not required", __func__); |
| 957 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 958 | } |
| 959 | |
| 960 | /******************************************************************************* |
| 961 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 962 | ** Function bta_av_co_find_peer_sink_supports_codec |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 963 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 964 | ** Description Find a peer acting as a sink that suppors codec config |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 965 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 966 | ** Returns The peer sink that supports the codec, otherwise NULL. |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 967 | ** |
| 968 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 969 | static const tBTA_AV_CO_SINK* bta_av_co_find_peer_sink_supports_codec( |
| 970 | const tBTA_AV_CO_PEER *p_peer) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 971 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 972 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 973 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 974 | for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { |
| 975 | if (A2D_CodecConfigMatchesCapabilities(bta_av_co_cb.codec_cfg, |
| 976 | p_peer->sinks[index].codec_caps)) { |
| 977 | return &p_peer->sinks[index]; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 978 | } |
| 979 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 980 | return NULL; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 981 | } |
| 982 | |
| 983 | /******************************************************************************* |
| 984 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 985 | ** Function bta_av_co_find_peer_src_supports_codec |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 986 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 987 | ** Description Find a peer acting as src that supports codec config |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 988 | ** |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 989 | ** Returns The peer source that supports the codec, otherwise NULL. |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 990 | ** |
| 991 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 992 | static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( |
| 993 | const tBTA_AV_CO_PEER *p_peer) |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 994 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 995 | APPL_TRACE_DEBUG("%s", __func__); |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 996 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 997 | for (size_t index = 0; index < p_peer->num_sup_srcs; index++) { |
| 998 | const uint8_t *p_codec_caps = p_peer->srcs[index].codec_caps; |
| 999 | if (A2D_CodecTypeEquals(bta_av_co_cb.codec_cfg, p_codec_caps) && |
| 1000 | A2D_IsPeerSourceCodecSupported(p_codec_caps)) { |
| 1001 | return &p_peer->srcs[index]; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 1002 | } |
| 1003 | } |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1004 | return NULL; |
Hemant Gupta | cc35559 | 2013-10-24 15:37:17 +0530 | [diff] [blame] | 1005 | } |
| 1006 | |
| 1007 | /******************************************************************************* |
| 1008 | ** |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1009 | ** Function bta_av_co_audio_codec_supported |
| 1010 | ** |
| 1011 | ** Description Check if all opened connections are compatible with a codec |
| 1012 | ** configuration and content protection |
| 1013 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1014 | ** Returns true if all opened devices support this codec, false otherwise |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1015 | ** |
| 1016 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1017 | static bool bta_av_co_audio_codec_supported(void) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1018 | { |
Pavlin Radoslavov | 89330a3 | 2016-08-24 11:46:58 -0700 | [diff] [blame] | 1019 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1020 | |
| 1021 | /* Check AV feeding is supported */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1022 | for (uint8_t index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); |
| 1023 | index++) { |
| 1024 | uint8_t codec_cfg[AVDT_CODEC_SIZE]; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1025 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1026 | tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[index]; |
| 1027 | if (!p_peer->opened) |
| 1028 | continue; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1029 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1030 | const tBTA_AV_CO_SINK *p_sink = |
| 1031 | bta_av_co_find_peer_sink_supports_codec(p_peer); |
| 1032 | if (p_sink == NULL) { |
| 1033 | APPL_TRACE_DEBUG("%s: index %d doesn't support codec", |
| 1034 | __func__, index); |
| 1035 | return false; |
| 1036 | } |
| 1037 | |
| 1038 | /* Check that this sink is compatible with the CP */ |
| 1039 | if (!bta_av_co_audio_sink_supports_cp(p_sink)) { |
| 1040 | APPL_TRACE_DEBUG("%s: sink of peer %d doesn't support cp", |
| 1041 | __func__, index); |
| 1042 | return false; |
| 1043 | } |
| 1044 | |
| 1045 | /* Build the codec configuration for this sink */ |
| 1046 | memset(codec_cfg, 0, AVDT_CODEC_SIZE); |
| 1047 | if (A2D_BuildSinkConfig(bta_av_co_cb.codec_cfg, p_sink->codec_caps, |
| 1048 | codec_cfg) != A2D_SUCCESS) { |
| 1049 | continue; |
| 1050 | } |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1051 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1052 | /* Check if this sink supports SCMS */ |
| 1053 | bool cp_active = bta_av_co_audio_sink_has_scmst(p_sink); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1054 | #endif |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1055 | /* Check if this is a new configuration (new sink or new config) */ |
| 1056 | if ((p_sink != p_peer->p_sink) || |
| 1057 | (!A2D_CodecEquals(codec_cfg, p_peer->codec_cfg)) |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1058 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1059 | || (p_peer->cp_active != cp_active) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1060 | #endif |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1061 | ) { |
| 1062 | uint8_t num_protect = 0; |
| 1063 | |
| 1064 | /* Save the new configuration */ |
| 1065 | p_peer->p_sink = p_sink; |
| 1066 | memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE); |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1067 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1068 | bta_av_co_cb.cp.active = cp_active; |
| 1069 | p_peer->cp_active = cp_active; |
| 1070 | if (p_peer->cp_active) |
| 1071 | num_protect = BTA_AV_CP_INFO_LEN; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1072 | #endif |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1073 | APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__, |
| 1074 | BTA_AV_CO_AUDIO_INDX_TO_HNDL(index)); |
| 1075 | BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), true, |
| 1076 | p_sink->sep_info_idx, p_peer->codec_cfg, |
| 1077 | num_protect, bta_av_co_cp_scmst); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1078 | } |
| 1079 | } |
| 1080 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1081 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1082 | } |
| 1083 | |
| 1084 | /******************************************************************************* |
| 1085 | ** |
| 1086 | ** Function bta_av_co_audio_codec_reset |
| 1087 | ** |
| 1088 | ** Description Reset the current codec configuration |
| 1089 | ** |
| 1090 | ** Returns void |
| 1091 | ** |
| 1092 | *******************************************************************************/ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1093 | static void bta_av_co_audio_codec_reset(void) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1094 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 1095 | APPL_TRACE_DEBUG("%s", __func__); |
| 1096 | |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 1097 | mutex_global_lock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1098 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1099 | /* Reset the current configuration to the default codec */ |
| 1100 | A2D_InitDefaultCodec(bta_av_co_cb.codec_cfg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1101 | |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 1102 | mutex_global_unlock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1103 | } |
| 1104 | |
| 1105 | /******************************************************************************* |
| 1106 | ** |
| 1107 | ** Function bta_av_co_audio_set_codec |
| 1108 | ** |
| 1109 | ** Description Set the current codec configuration from the feeding type. |
| 1110 | ** This function is starting to modify the configuration, it |
| 1111 | ** should be protected. |
| 1112 | ** |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1113 | ** Returns true if successful, false otherwise |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1114 | ** |
| 1115 | *******************************************************************************/ |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 1116 | bool bta_av_co_audio_set_codec(const tA2D_AV_MEDIA_FEEDINGS *p_feeding) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1117 | { |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1118 | uint8_t new_cfg[AVDT_CODEC_SIZE]; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1119 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1120 | if (!A2D_SetCodec(p_feeding, new_cfg)) |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1121 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1122 | |
| 1123 | /* The new config was correctly built */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1124 | memcpy(bta_av_co_cb.codec_cfg, new_cfg, sizeof(new_cfg)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1125 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1126 | /* Check all devices support it */ |
Pavlin Radoslavov | a62c5a3 | 2016-08-25 15:34:57 -0700 | [diff] [blame] | 1127 | return bta_av_co_audio_codec_supported(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1128 | } |
| 1129 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1130 | void bta_av_co_audio_encoder_init(tBTIF_MEDIA_INIT_AUDIO *msg) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1131 | { |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1132 | uint16_t min_mtu = 0xFFFF; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1133 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1134 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1135 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1136 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 1137 | mutex_global_lock(); |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1138 | |
| 1139 | /* Compute the MTU */ |
| 1140 | for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { |
| 1141 | const tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[i]; |
| 1142 | if (!p_peer->opened) |
| 1143 | continue; |
| 1144 | if (p_peer->mtu < min_mtu) |
| 1145 | min_mtu = p_peer->mtu; |
| 1146 | } |
| 1147 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1148 | const uint8_t *p_codec_info = bta_av_co_cb.codec_cfg; |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1149 | msg->NumOfSubBands = A2D_GetNumberOfSubbands(p_codec_info); |
| 1150 | msg->NumOfBlocks = A2D_GetNumberOfBlocks(p_codec_info); |
| 1151 | msg->AllocationMethod = A2D_GetAllocationMethodCode(p_codec_info); |
| 1152 | msg->ChannelMode = A2D_GetChannelModeCode(p_codec_info); |
| 1153 | msg->SamplingFreq = A2D_GetSamplingFrequencyCode(p_codec_info); |
| 1154 | msg->MtuSize = min_mtu; |
| 1155 | |
| 1156 | /* Protect access to bta_av_co_cb.codec_cfg */ |
| 1157 | mutex_global_unlock(); |
| 1158 | } |
| 1159 | |
| 1160 | void bta_av_co_audio_encoder_update(tBTIF_MEDIA_UPDATE_AUDIO *msg) |
| 1161 | { |
| 1162 | uint16_t min_mtu = 0xFFFF; |
| 1163 | |
| 1164 | APPL_TRACE_DEBUG("%s", __func__); |
| 1165 | |
| 1166 | /* Protect access to bta_av_co_cb.codec_cfg */ |
| 1167 | mutex_global_lock(); |
| 1168 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1169 | const uint8_t *p_codec_info = bta_av_co_cb.codec_cfg; |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1170 | int min_bitpool = A2D_GetMinBitpool(p_codec_info); |
| 1171 | int max_bitpool = A2D_GetMaxBitpool(p_codec_info); |
| 1172 | |
| 1173 | if ((min_bitpool < 0) || (max_bitpool < 0)) { |
| 1174 | APPL_TRACE_ERROR("%s: Invalid min/max bitpool: [%d, %d]", |
| 1175 | __func__, min_bitpool, max_bitpool); |
| 1176 | mutex_global_unlock(); |
| 1177 | return; |
| 1178 | } |
| 1179 | |
| 1180 | for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { |
| 1181 | const tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[i]; |
| 1182 | if (!p_peer->opened) |
| 1183 | continue; |
| 1184 | |
| 1185 | if (p_peer->mtu < min_mtu) |
| 1186 | min_mtu = p_peer->mtu; |
| 1187 | |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1188 | for (int j = 0; j < p_peer->num_sup_sinks; j++) { |
| 1189 | const tBTA_AV_CO_SINK *p_sink = &p_peer->sinks[j]; |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1190 | if (!A2D_CodecTypeEquals(p_codec_info, p_sink->codec_caps)) |
| 1191 | continue; |
| 1192 | /* Update the bitpool boundaries of the current config */ |
| 1193 | int peer_min_bitpool = A2D_GetMinBitpool(p_sink->codec_caps); |
| 1194 | int peer_max_bitpool = A2D_GetMaxBitpool(p_sink->codec_caps); |
| 1195 | if (peer_min_bitpool >= 0) |
| 1196 | min_bitpool = BTA_AV_CO_MAX(min_bitpool, peer_min_bitpool); |
| 1197 | if (peer_max_bitpool >= 0) |
| 1198 | max_bitpool = BTA_AV_CO_MIN(max_bitpool, peer_max_bitpool); |
| 1199 | APPL_TRACE_EVENT("%s: sink bitpool min %d, max %d", |
| 1200 | __func__, min_bitpool, max_bitpool); |
| 1201 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1202 | } |
| 1203 | } |
| 1204 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1205 | /* |
| 1206 | * Check if the remote Sink has a preferred bitpool range. |
| 1207 | * Adjust our preferred bitpool with the remote preference if within |
| 1208 | * our capable range. |
| 1209 | */ |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1210 | if (A2D_IsValidCodec(bta_av_co_cb.codec_cfg_setconfig) && |
| 1211 | A2D_CodecTypeEquals(p_codec_info, bta_av_co_cb.codec_cfg_setconfig)) { |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1212 | int setconfig_min_bitpool = |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1213 | A2D_GetMinBitpool(bta_av_co_cb.codec_cfg_setconfig); |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1214 | int setconfig_max_bitpool = |
Pavlin Radoslavov | c66edf3 | 2016-09-15 17:50:18 -0700 | [diff] [blame^] | 1215 | A2D_GetMaxBitpool(bta_av_co_cb.codec_cfg_setconfig); |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1216 | if (setconfig_min_bitpool >= 0) |
| 1217 | min_bitpool = BTA_AV_CO_MAX(min_bitpool, setconfig_min_bitpool); |
| 1218 | if (setconfig_max_bitpool >= 0) |
| 1219 | max_bitpool = BTA_AV_CO_MIN(max_bitpool, setconfig_max_bitpool); |
| 1220 | APPL_TRACE_EVENT("%s: sink adjusted bitpool min %d, max %d", |
| 1221 | __func__, min_bitpool, max_bitpool); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1222 | } |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1223 | |
| 1224 | /* Protect access to bta_av_co_cb.codec_cfg */ |
Pavlin Radoslavov | 1eb1ea0 | 2015-09-24 22:07:53 -0700 | [diff] [blame] | 1225 | mutex_global_unlock(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1226 | |
Pavlin Radoslavov | b18f03e | 2016-09-13 15:02:52 -0700 | [diff] [blame] | 1227 | if (min_bitpool > max_bitpool) { |
| 1228 | APPL_TRACE_ERROR("%s: Irrational min/max bitpool: [%d, %d]", |
| 1229 | __func__, min_bitpool, max_bitpool); |
| 1230 | return; |
| 1231 | } |
| 1232 | |
| 1233 | msg->MinMtuSize = min_mtu; |
| 1234 | msg->MinBitPool = min_bitpool; |
| 1235 | msg->MaxBitPool = max_bitpool; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1236 | } |
| 1237 | |
| 1238 | /******************************************************************************* |
| 1239 | ** |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1240 | ** Function bta_av_co_init |
| 1241 | ** |
| 1242 | ** Description Initialization |
| 1243 | ** |
| 1244 | ** Returns Nothing |
| 1245 | ** |
| 1246 | *******************************************************************************/ |
| 1247 | void bta_av_co_init(void) |
| 1248 | { |
Pavlin Radoslavov | 79506e8 | 2016-09-07 21:57:47 -0700 | [diff] [blame] | 1249 | APPL_TRACE_DEBUG("%s", __func__); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1250 | |
| 1251 | /* Reset the control block */ |
| 1252 | memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb)); |
| 1253 | |
Marie Janssen | b7f64bc | 2016-06-22 12:52:19 -0700 | [diff] [blame] | 1254 | #if (BTA_AV_CO_CP_SCMS_T == TRUE) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1255 | bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER); |
| 1256 | #else |
| 1257 | bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE); |
| 1258 | #endif |
| 1259 | |
| 1260 | /* Reset the current config */ |
| 1261 | bta_av_co_audio_codec_reset(); |
| 1262 | } |