1 /******************************************************************************
2 *
3 * Copyright (C) 2015 Motorola 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 stream state machine for the BRCM offloaded advanced audio.
22 *
23 ******************************************************************************/
24
25 #define LOG_TAG "bt_vnd_a2dp"
26 #define LOG_NDEBUG 0
27
28 #include <string.h>
29 #include <pthread.h>
30 #include <utils/Log.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <signal.h>
34 #include <time.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <dirent.h>
38 #include <ctype.h>
39 #include <cutils/properties.h>
40 #include <stdlib.h>
41 #include "bt_hci_bdroid.h"
42 #include "bt_vendor_brcm_a2dp.h"
43 #include "a2d_api.h"
44 #include "a2d_sbc.h"
45
46 #if (BTA2DP_DEBUG == TRUE)
47 #define BTA2DPDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
48 #else
49 #define BTA2DPDBG(param, ...) {}
50 #endif
51
52 /*****************************************************************************
53 ** Constants and types
54 *****************************************************************************/
55
56 typedef void (*hci_cback)(void *);
57
58 typedef enum
59 {
60 BRCM_VND_A2DP_OFFLOAD_INIT_REQ,
61 BRCM_VND_A2DP_OFFLOAD_START_REQ,
62 BRCM_VND_A2DP_OFFLOAD_STOP_REQ,
63 BRCM_VND_UIPC_OPEN_RSP,
64 BRCM_VND_L2C_SYNC_TO_LITE_RSP,
65 BRCM_VND_SYNC_TO_BTC_LITE_RSP,
66 BRCM_VND_AUDIO_CODEC_CONFIG_RSP,
67 BRCM_VND_AUDIO_ROUTE_CONFIG_RSP,
68 BRCM_VND_UIPC_CLOSE_RSP,
69 BRCM_VND_L2C_REMOVE_TO_LITE_RSP,
70 BRCM_VND_A2DP_START_RSP,
71 BRCM_VND_A2DP_SUSPEND_RSP,
72 BRCM_VND_STREAM_STOP_RSP,
73 BRCM_VND_A2DP_CLEANUP_RSP,
74 BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT,
75 } tBRCM_VND_A2DP_EVENT;
76
77 /* state machine states */
78 typedef enum
79 {
80 BRCM_VND_A2DP_INVALID_SST = -1,
81 BRCM_VND_A2DP_IDLE_SST,
82 BRCM_VND_A2DP_STARTING_SST,
83 BRCM_VND_A2DP_STREAM_SST,
84 }
85 tBRCM_VND_A2DP_SST_STATES;
86
87 static uint8_t brcm_vnd_a2dp_offload_configure();
88 static uint8_t brcm_vnd_a2dp_offload_cleanup();
89 static uint8_t brcm_vnd_a2dp_offload_suspend();
90 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_idle_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data);
91 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_starting_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data);
92 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_stream_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data);
93 static void brcm_vnd_a2dp_hci_uipc_cback(void *pmem);
94
95 typedef struct {
96 uint8_t fcn;
97 uint32_t pad_conf;
98 }
99 tBRCM_VND_PCM_CONF;
100
101 typedef struct {
102 tBRCM_VND_A2DP_SST_STATES state;
103 tCODEC_INFO_SBC codec_info;
104 tBRCM_VND_PCM_CONF pcmi2s_pinmux;
105 bt_vendor_op_a2dp_offload_t offload_params;
106 }
107 tBRCM_VND_A2DP_PDATA;
108
109 typedef struct {
110 tBRCM_VND_A2DP_SST_STATES (*enter)(tBRCM_VND_A2DP_EVENT event);
111 tBRCM_VND_A2DP_SST_STATES (*process_event)(tBRCM_VND_A2DP_EVENT event, void *ev_data);
112 }
113 tBRCM_VND_A2DP_SST_STATE;
114
115 /* state table */
116 static tBRCM_VND_A2DP_SST_STATE brcm_vnd_a2dp_sst_tbl[] =
117 {
118 {NULL, brcm_vnd_a2dp_sm_idle_process_ev},
119 {NULL, brcm_vnd_a2dp_sm_starting_process_ev},
120 {NULL, brcm_vnd_a2dp_sm_stream_process_ev},
121 };
122
123 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
124 static tBRCM_VND_A2DP_PDATA brcm_vnd_a2dp_pdata = { .state = BRCM_VND_A2DP_INVALID_SST };
125
126
127 /*******************************************************************************
128 ** Local Utility Functions
129 *******************************************************************************/
130
log_bin_to_hexstr(uint8_t * bin,uint8_t binsz,const char * log_tag)131 static void log_bin_to_hexstr(uint8_t *bin, uint8_t binsz, const char *log_tag)
132 {
133 #if (BTA2DP_DEBUG == TRUE)
134 char *str, hex_str[]= "0123456789abcdef";
135 uint8_t i;
136
137 str = (char *)malloc(binsz * 3);
138 if (!binsz) {
139 ALOGE("%s alloc failed", __FUNCTION__);
140 return;
141 }
142
143 for (i = 0; i < binsz; i++) {
144 str[(i * 3) + 0] = hex_str[(bin[i] >> 4) & 0x0F];
145 str[(i * 3) + 1] = hex_str[(bin[i] ) & 0x0F];
146 str[(i * 3) + 2] = ' ';
147 }
148 str[(binsz * 3) - 1] = 0x00;
149 BTA2DPDBG("%s %s", log_tag, str);
150 #endif
151 }
152
brcm_vnd_a2dp_send_hci_vsc(uint16_t cmd,uint8_t * payload,uint8_t len,hci_cback cback)153 static uint8_t brcm_vnd_a2dp_send_hci_vsc(uint16_t cmd, uint8_t *payload, uint8_t len, hci_cback cback)
154 {
155 HC_BT_HDR *p_buf;
156 uint8_t *p, status;
157 uint16_t opcode;
158
159 // Perform Opening configure cmds. //
160 if (bt_vendor_cbacks) {
161 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
162 BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + len);
163 if (p_buf)
164 {
165 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
166 p_buf->offset = 0;
167 p_buf->layer_specific = 0;
168 p_buf->len = HCI_CMD_PREAMBLE_SIZE + len;
169 p = (uint8_t *)(p_buf + 1);
170
171 UINT16_TO_STREAM(p, cmd);
172 *p++ = len;
173 memcpy(p, payload, len);
174
175 //BTA2DPDBG("%s Cmd %04x UIPC Event %02x%02x UIPC Op %02x Len %d", __FUNCTION__, cmd, event, payload[1], payload[0], payload[2], len);
176 log_bin_to_hexstr((uint8_t *)(p_buf + 1), HCI_CMD_PREAMBLE_SIZE + len, __FUNCTION__);
177
178 if (bt_vendor_cbacks->xmit_cb(cmd, p_buf, cback))
179 {
180 return BT_VND_OP_RESULT_SUCCESS;
181 }
182 bt_vendor_cbacks->dealloc(p_buf);
183 }
184 }
185 return BT_VND_OP_RESULT_FAIL;
186 }
187
brcm_vnd_map_a2d_uipc_codec_info(tCODEC_INFO_SBC * codec_info)188 static void brcm_vnd_map_a2d_uipc_codec_info(tCODEC_INFO_SBC *codec_info)
189 {
190 switch(codec_info->sampling_freq) {
191 case A2D_SBC_IE_SAMP_FREQ_16:
192 codec_info->sampling_freq = CODEC_INFO_SBC_SF_16K; break;
193 case A2D_SBC_IE_SAMP_FREQ_32:
194 codec_info->sampling_freq = CODEC_INFO_SBC_SF_32K; break;
195 case A2D_SBC_IE_SAMP_FREQ_44:
196 codec_info->sampling_freq = CODEC_INFO_SBC_SF_44K; break;
197 case A2D_SBC_IE_SAMP_FREQ_48:
198 codec_info->sampling_freq = CODEC_INFO_SBC_SF_48K; break;
199
200 }
201 switch(codec_info->channel_mode) {
202 case A2D_SBC_IE_CH_MD_MONO:
203 codec_info->channel_mode = CODEC_INFO_SBC_CH_MONO; break;
204 case A2D_SBC_IE_CH_MD_DUAL:
205 codec_info->channel_mode = CODEC_INFO_SBC_CH_DUAL; break;
206 case A2D_SBC_IE_CH_MD_STEREO:
207 codec_info->channel_mode = CODEC_INFO_SBC_CH_STEREO; break;
208 case A2D_SBC_IE_CH_MD_JOINT:
209 codec_info->channel_mode = CODEC_INFO_SBC_CH_JS; break;
210 }
211 switch(codec_info->block_length) {
212 case A2D_SBC_IE_BLOCKS_4:
213 codec_info->block_length = CODEC_INFO_SBC_BLOCK_4; break;
214 case A2D_SBC_IE_BLOCKS_8:
215 codec_info->block_length = CODEC_INFO_SBC_BLOCK_8; break;
216 case A2D_SBC_IE_BLOCKS_12:
217 codec_info->block_length = CODEC_INFO_SBC_BLOCK_12; break;
218 case A2D_SBC_IE_BLOCKS_16:
219 codec_info->block_length = CODEC_INFO_SBC_BLOCK_16; break;
220 }
221 switch(codec_info->alloc_method) {
222 case A2D_SBC_IE_ALLOC_MD_S:
223 codec_info->alloc_method = CODEC_INFO_SBC_ALLOC_SNR; break;
224 case A2D_SBC_IE_ALLOC_MD_L:
225 codec_info->alloc_method = CODEC_INFO_SBC_ALLOC_LOUDNESS; break;
226 }
227 switch(codec_info->num_subbands) {
228 case A2D_SBC_IE_SUBBAND_4:
229 codec_info->num_subbands = CODEC_INFO_SBC_SUBBAND_4; break;
230 case A2D_SBC_IE_SUBBAND_8:
231 codec_info->num_subbands = CODEC_INFO_SBC_SUBBAND_8; break;
232 }
233 }
234
bcrm_vnd_a2dp_parse_codec_info(tCODEC_INFO_SBC * parsed_info,uint8_t * codec_info)235 static tA2D_STATUS bcrm_vnd_a2dp_parse_codec_info(tCODEC_INFO_SBC *parsed_info, uint8_t *codec_info)
236 {
237 tA2D_STATUS status = A2D_SUCCESS;
238 UINT8 losc;
239 UINT8 mt;
240
241 BTA2DPDBG("%s", __FUNCTION__);
242
243 if( parsed_info == NULL || codec_info == NULL)
244 status = A2D_FAIL;
245 else
246 {
247 losc = *codec_info++;
248 mt = *codec_info++;
249 /* If the function is called for the wrong Media Type or Media Codec Type */
250 if(losc != A2D_SBC_INFO_LEN || *codec_info != A2D_MEDIA_CT_SBC)
251 status = A2D_WRONG_CODEC;
252 else
253 {
254 codec_info++;
255 parsed_info->sampling_freq = *codec_info & A2D_SBC_IE_SAMP_FREQ_MSK;
256 parsed_info->channel_mode = *codec_info & A2D_SBC_IE_CH_MD_MSK;
257 codec_info++;
258 parsed_info->block_length = *codec_info & A2D_SBC_IE_BLOCKS_MSK;
259 parsed_info->num_subbands = *codec_info & A2D_SBC_IE_SUBBAND_MSK;
260 parsed_info->alloc_method = *codec_info & A2D_SBC_IE_ALLOC_MD_MSK;
261 codec_info += 2; /* MAX Bitpool */
262 parsed_info->bitpool_size = (*codec_info > BRCM_A2DP_OFFLOAD_MAX_BITPOOL) ?
263 BRCM_A2DP_OFFLOAD_MAX_BITPOOL : (*codec_info);
264
265 if(MULTI_BIT_SET(parsed_info->sampling_freq))
266 status = A2D_BAD_SAMP_FREQ;
267 if(MULTI_BIT_SET(parsed_info->channel_mode))
268 status = A2D_BAD_CH_MODE;
269 if(MULTI_BIT_SET(parsed_info->block_length))
270 status = A2D_BAD_BLOCK_LEN;
271 if(MULTI_BIT_SET(parsed_info->num_subbands))
272 status = A2D_BAD_SUBBANDS;
273 if(MULTI_BIT_SET(parsed_info->alloc_method))
274 status = A2D_BAD_ALLOC_MTHD;
275 if(parsed_info->bitpool_size < A2D_SBC_IE_MIN_BITPOOL || parsed_info->bitpool_size > A2D_SBC_IE_MAX_BITPOOL )
276 status = A2D_BAD_MIN_BITPOOL;
277
278 if(status == A2D_SUCCESS)
279 brcm_vnd_map_a2d_uipc_codec_info(parsed_info);
280
281 BTA2DPDBG("%s STATUS %d parsed info : SampF %02x, ChnMode %02x, BlockL %02x, NSubB %02x, alloc %02x, bitpool %02x",
282 __FUNCTION__, status, parsed_info->sampling_freq, parsed_info->channel_mode, parsed_info->block_length,
283 parsed_info->num_subbands, parsed_info->alloc_method, parsed_info->bitpool_size);
284
285 }
286 }
287 return status;
288 }
289
290 /*******************************************************************************
291 ** State Machine Functions
292 *******************************************************************************/
293
294 /*******************************************************************************
295 **
296 ** Function brcm_vnd_a2dp_ssm_execute
297 **
298 ** Description Stream state machine event handling function for AV
299 **
300 **
301 ** Returns void
302 **
303 *******************************************************************************/
brcm_vnd_a2dp_ssm_execute(tBRCM_VND_A2DP_EVENT event,void * ev_data)304 int brcm_vnd_a2dp_ssm_execute(tBRCM_VND_A2DP_EVENT event, void *ev_data)
305 {
306 tBRCM_VND_A2DP_SST_STATE *state_table;
307 tBRCM_VND_A2DP_SST_STATES next_state;
308
309 pthread_mutex_lock(&g_mutex);
310
311 BTA2DPDBG("%s ev %d state %d", __FUNCTION__, event, brcm_vnd_a2dp_pdata.state);
312
313 if (brcm_vnd_a2dp_pdata.state != BRCM_VND_A2DP_INVALID_SST) {
314 state_table = &brcm_vnd_a2dp_sst_tbl[brcm_vnd_a2dp_pdata.state];
315 /* process event */
316 next_state = state_table->process_event(event, ev_data);
317 } else if (BRCM_VND_A2DP_OFFLOAD_INIT_REQ == event) {
318 next_state = BRCM_VND_A2DP_IDLE_SST;
319 }
320 else {
321 pthread_mutex_unlock(&g_mutex);
322 return BT_VND_OP_RESULT_FAIL;
323 }
324
325 /* transition stae */
326 while (next_state != brcm_vnd_a2dp_pdata.state) {
327 brcm_vnd_a2dp_pdata.state = next_state;
328 state_table = &brcm_vnd_a2dp_sst_tbl[next_state];
329 if (state_table->enter)
330 next_state = state_table->enter(event);
331 }
332
333 pthread_mutex_unlock(&g_mutex);
334 return BT_VND_OP_RESULT_SUCCESS;
335 }
336
337 /* state machine actions */
338
brcm_vnd_a2dp_sm_idle_process_ev(tBRCM_VND_A2DP_EVENT event,void * ev_data)339 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_idle_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data)
340 {
341 tBRCM_VND_A2DP_SST_STATES next_state = brcm_vnd_a2dp_pdata.state;
342
343 switch (event) {
344 case BRCM_VND_A2DP_OFFLOAD_START_REQ:
345 brcm_vnd_a2dp_pdata.offload_params = *(bt_vendor_op_a2dp_offload_t*)ev_data;
346 if (A2D_SUCCESS != bcrm_vnd_a2dp_parse_codec_info( &brcm_vnd_a2dp_pdata.codec_info,
347 (uint8_t *)brcm_vnd_a2dp_pdata.offload_params.codec_info)) {
348 ALOGE("%s CodecConfig BT_VND_OP_A2DP_OFFLOAD_START FAILED", __FUNCTION__);
349 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
350 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
351 } else {
352 brcm_vnd_a2dp_offload_configure();
353 next_state = BRCM_VND_A2DP_STARTING_SST;
354 }
355 break;
356
357 default:
358 ALOGV("%s Unexpected Event %d in State %d, IGNORE", __FUNCTION__, event, brcm_vnd_a2dp_pdata.state);
359 break;
360 }
361 return next_state;
362 }
363
brcm_vnd_a2dp_sm_starting_process_ev(tBRCM_VND_A2DP_EVENT event,void * ev_data)364 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_starting_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data)
365 {
366 tBRCM_VND_A2DP_SST_STATES next_state = brcm_vnd_a2dp_pdata.state;
367 uint8_t status, *p;
368
369 switch (event) {
370 case BRCM_VND_A2DP_OFFLOAD_START_REQ:
371 brcm_vnd_a2dp_offload_cleanup();
372 brcm_vnd_a2dp_pdata.offload_params = *(bt_vendor_op_a2dp_offload_t*)ev_data;
373 if (A2D_SUCCESS != bcrm_vnd_a2dp_parse_codec_info(
374 &brcm_vnd_a2dp_pdata.codec_info, (uint8_t *)brcm_vnd_a2dp_pdata.offload_params.codec_info)) {
375 ALOGE("%s CodecConfig BT_VND_OP_A2DP_OFFLOAD_START FAILED", __FUNCTION__);
376 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
377 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
378 next_state = BRCM_VND_A2DP_IDLE_SST;
379 } else {
380 brcm_vnd_a2dp_offload_configure();
381 }
382 break;
383
384 case BRCM_VND_A2DP_OFFLOAD_STOP_REQ:
385 brcm_vnd_a2dp_offload_cleanup();
386 next_state = BRCM_VND_A2DP_IDLE_SST;
387 break;
388
389 case BRCM_VND_UIPC_OPEN_RSP: {
390 uint8_t num_streams;
391 uint16_t maj_ver, min_ver;
392 p = (uint8_t*)ev_data + offsetof(tUIPC_OPEN_RSP, status);
393 STREAM_TO_UINT8(status,p);
394 STREAM_TO_UINT16(maj_ver,p);
395 STREAM_TO_UINT16(min_ver,p);
396 STREAM_TO_UINT8(num_streams,p);
397 // TODO Verify Params //
398 if (status) {
399 ALOGE("%s BRCM_VND_UIPC_OPEN_RSP %02x FAILED", __FUNCTION__, status);
400 brcm_vnd_a2dp_offload_cleanup();
401 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
402 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
403 next_state = BRCM_VND_A2DP_IDLE_SST;
404 }
405 }
406 break;
407
408 case BRCM_VND_L2C_SYNC_TO_LITE_RSP:
409 status = *((uint8_t*)ev_data + offsetof(tL2C_SYNC_TO_LITE_RESP, stream.status));
410 if (status) {
411 ALOGE("%s L2C_SYNC_TO_LITE_RESP %02x FAILED", __FUNCTION__, status);
412 brcm_vnd_a2dp_offload_cleanup();
413 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
414 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
415 next_state = BRCM_VND_A2DP_IDLE_SST;
416 }
417 break;
418
419 case BRCM_VND_SYNC_TO_BTC_LITE_RSP:
420 status = *((uint8_t*)ev_data + offsetof(tAVDT_SYNC_TO_BTC_LITE_RESP, status));
421 if (status) {
422 ALOGE("%s AVDT_SYNC_TO_BTC_LITE_RESP %02x FAILED", __FUNCTION__, status);
423 brcm_vnd_a2dp_offload_cleanup();
424 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
425 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
426 next_state = BRCM_VND_A2DP_IDLE_SST;
427 }
428 break;
429
430 case BRCM_VND_AUDIO_ROUTE_CONFIG_RSP:
431 status = *((uint8_t*)ev_data + offsetof(tAUDIO_ROUTE_CONFIG_RESP, status));
432 if (status) {
433 ALOGE("%s AUDIO_ROUTE_CONFIG_RESP %02x FAILED", __FUNCTION__, status);
434 brcm_vnd_a2dp_offload_cleanup();
435 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
436 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
437 next_state = BRCM_VND_A2DP_IDLE_SST;
438 }
439 break;
440
441 case BRCM_VND_AUDIO_CODEC_CONFIG_RSP:
442 status = *((uint8_t*)ev_data + offsetof(tAUDIO_CODEC_CONFIG_RESP, status));
443 if (status) {
444 ALOGE("%s BRCM_VND_AUDIO_CODEC_CONFIG_RSP %02x FAILED", __FUNCTION__, status);
445 brcm_vnd_a2dp_offload_cleanup();
446 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
447 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
448 next_state = BRCM_VND_A2DP_IDLE_SST;
449 }
450 break;
451
452 case BRCM_VND_A2DP_START_RSP:
453 /* status = *((uint8_t*)ev_data + offsetof(tA2DP_GENERIC_RESP, status)); */
454 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_SUCCESS, BT_VND_OP_A2DP_OFFLOAD_START,
455 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
456 next_state = BRCM_VND_A2DP_STREAM_SST;
457 break;
458
459 case BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT:
460 ALOGE("%s BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT", __FUNCTION__);
461 brcm_vnd_a2dp_offload_cleanup();
462 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
463 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
464 next_state = BRCM_VND_A2DP_IDLE_SST;
465 break;
466
467 default:
468 ALOGE("%s Unexpected Event %d in State %d, IGNORE", __FUNCTION__, event, brcm_vnd_a2dp_pdata.state);
469 break;
470 }
471 return next_state;
472 }
473
brcm_vnd_a2dp_sm_stream_process_ev(tBRCM_VND_A2DP_EVENT event,void * ev_data)474 static tBRCM_VND_A2DP_SST_STATES brcm_vnd_a2dp_sm_stream_process_ev(tBRCM_VND_A2DP_EVENT event, void *ev_data)
475 {
476 tBRCM_VND_A2DP_SST_STATES next_state = brcm_vnd_a2dp_pdata.state;
477 switch (event) {
478 case BRCM_VND_A2DP_OFFLOAD_START_REQ:
479 brcm_vnd_a2dp_offload_cleanup();
480 brcm_vnd_a2dp_pdata.offload_params = *(bt_vendor_op_a2dp_offload_t*)ev_data;
481 if (A2D_SUCCESS != bcrm_vnd_a2dp_parse_codec_info(
482 &brcm_vnd_a2dp_pdata.codec_info, (uint8_t *)brcm_vnd_a2dp_pdata.offload_params.codec_info)) {
483 ALOGE("%s CodecConfig BT_VND_OP_A2DP_OFFLOAD_START FAILED", __FUNCTION__);
484 bt_vendor_cbacks->a2dp_offload_cb(BT_VND_OP_RESULT_FAIL, BT_VND_OP_A2DP_OFFLOAD_START,
485 brcm_vnd_a2dp_pdata.offload_params.bta_av_handle);
486 next_state = BRCM_VND_A2DP_IDLE_SST;
487 } else {
488 brcm_vnd_a2dp_offload_configure();
489 next_state = BRCM_VND_A2DP_STARTING_SST;
490 }
491 break;
492
493 case BRCM_VND_A2DP_OFFLOAD_STOP_REQ:
494 case BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT:
495 ALOGE("%s BRCM_VND_A2DP_OFFLOAD_STOP ABORT %d.", __FUNCTION__,
496 (event == BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT));
497 brcm_vnd_a2dp_offload_cleanup();
498 next_state = BRCM_VND_A2DP_IDLE_SST;
499 break;
500
501 default:
502 ALOGE("%s Unexpected Event %d in State %d, IGNORE", __FUNCTION__, event, brcm_vnd_a2dp_pdata.state);
503 break;
504 }
505 return next_state;
506 }
507
brcm_vnd_a2dp_offload_configure()508 static uint8_t brcm_vnd_a2dp_offload_configure()
509 {
510 uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
511
512 BTA2DPDBG("%s", __FUNCTION__);
513
514 p = msg_req;
515 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_READ_PCM_PINS, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
516
517 p = msg_req;
518 UINT8_TO_STREAM(p, BRCM_A2DP_OFFLOAD_PCM_PIN_FCN);
519 UINT32_TO_STREAM(p, BRCM_A2DP_OFFLOAD_PCM_PIN_PADCNF);
520 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_WRITE_PCM_PINS, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
521
522 p = msg_req;
523 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_MGMT_EVT);
524 UINT8_TO_STREAM(p, UIPC_OPEN_REQ);
525 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
526
527 p = msg_req;
528 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_L2C_EVT);
529 UINT8_TO_STREAM(p, L2C_SYNC_TO_LITE_REQ);
530 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.xmit_quota);
531 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.acl_data_size);
532 UINT16_TO_STREAM(p, !(brcm_vnd_a2dp_pdata.offload_params.is_flushable));
533 UINT8_TO_STREAM(p, 0x02); //multi_av_data_cong_start
534 UINT8_TO_STREAM(p, 0x00); //multi_av_data_cong_end
535 UINT8_TO_STREAM(p, 0x04); //multi_av_data_cong_discard
536 UINT8_TO_STREAM(p, 1); //num_stream
537 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
538 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.remote_cid);
539 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.stream_mtu);
540 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.lm_handle);
541 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.xmit_quota);
542 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.is_flushable);
543 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
544
545 p = msg_req;
546 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_AVDT_EVT);
547 UINT8_TO_STREAM(p, AVDT_SYNC_TO_BTC_LITE_REQ);
548 UINT8_TO_STREAM(p, 1); //num_stream
549 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
550 UINT32_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.stream_source);
551 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
552
553 p = msg_req;
554 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_BTM_EVT);
555 UINT8_TO_STREAM(p, AUDIO_ROUTE_CONFIG_REQ);
556 UINT8_TO_STREAM(p, BRCM_A2DP_OFFLOAD_SRC);
557 UINT8_TO_STREAM(p, BRCM_A2DP_OFFLOAD_SRC_SF);
558 UINT8_TO_STREAM(p, AUDIO_ROUTE_OUT_BTA2DP);
559 UINT8_TO_STREAM(p, BRCM_A2DP_OFFLOAD_SRC_SF);
560 UINT8_TO_STREAM(p, AUDIO_ROUTE_SF_NA);
561 UINT8_TO_STREAM(p, AUDIO_ROUTE_EQ_BYPASS);
562 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
563
564 p = msg_req;
565 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_BTM_EVT);
566 UINT8_TO_STREAM(p, AUDIO_CODEC_CONFIG_REQ);
567 UINT16_TO_STREAM(p, AUDIO_CODEC_SBC_ENC);
568 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.sampling_freq);
569 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.channel_mode);
570 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.block_length);
571 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.num_subbands);
572 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.alloc_method);
573 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.codec_info.bitpool_size);
574 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
575
576 p = msg_req;
577 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_BTM_EVT);
578 UINT8_TO_STREAM(p, A2DP_START_REQ);
579 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
580 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.stream_mtu);
581 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
582
583 return 0;
584 }
585
brcm_vnd_a2dp_offload_cleanup()586 static uint8_t brcm_vnd_a2dp_offload_cleanup()
587 {
588 uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
589
590 BTA2DPDBG("%s", __FUNCTION__);
591
592 p = msg_req;
593 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_BTM_EVT);
594 UINT8_TO_STREAM(p, A2DP_CLEANUP_REQ);
595 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
596 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.stream_mtu);
597 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
598
599 p = msg_req;
600 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_L2C_EVT);
601 UINT8_TO_STREAM(p, L2C_REMOVE_TO_LITE_REQ);
602 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.xmit_quota);
603 UINT8_TO_STREAM(p, 1); //num_stream
604 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
605 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
606
607 p = msg_req;
608 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_MGMT_EVT);
609 UINT8_TO_STREAM(p, UIPC_CLOSE_REQ);
610 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
611
612 if (PCM_PIN_FCN_INVALID != brcm_vnd_a2dp_pdata.pcmi2s_pinmux.fcn) {
613 p = msg_req;
614 UINT8_TO_STREAM(p, brcm_vnd_a2dp_pdata.pcmi2s_pinmux.fcn);
615 UINT32_TO_STREAM(p, brcm_vnd_a2dp_pdata.pcmi2s_pinmux.pad_conf);
616 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_WRITE_PCM_PINS, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
617 brcm_vnd_a2dp_pdata.pcmi2s_pinmux.fcn = PCM_PIN_FCN_INVALID;
618 }
619
620 return 0;
621 }
622
brcm_vnd_a2dp_offload_suspend()623 static uint8_t brcm_vnd_a2dp_offload_suspend()
624 {
625 uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
626
627 BTA2DPDBG("%s", __FUNCTION__);
628
629 p = msg_req;
630 UINT16_TO_STREAM(p, BT_EVT_BTU_IPC_BTM_EVT);
631 UINT8_TO_STREAM(p, A2DP_SUSPEND_REQ);
632 UINT16_TO_STREAM(p, brcm_vnd_a2dp_pdata.offload_params.local_cid);
633 brcm_vnd_a2dp_send_hci_vsc(HCI_VSC_UIPC_OVER_HCI, msg_req, (uint8_t)(p - msg_req), brcm_vnd_a2dp_hci_uipc_cback);
634
635 return 0;
636 }
637
brcm_vnd_a2dp_hci_uipc_cback(void * pmem)638 void brcm_vnd_a2dp_hci_uipc_cback(void *pmem)
639 {
640 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)pmem;
641 uint8_t *p, len, vsc_result, uipc_opcode;
642 uint16_t vsc_opcode, uipc_event;
643 HC_BT_HDR *p_buf = NULL;
644 bt_vendor_op_result_t status = BT_VND_OP_RESULT_SUCCESS;
645 tBRCM_VND_A2DP_EVENT ssm_event;
646
647 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_LEN;
648 len = *p;
649 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_VSC;
650 STREAM_TO_UINT16(vsc_opcode,p);
651 vsc_result = *p++;
652
653 log_bin_to_hexstr(((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_VSC), len-1, __FUNCTION__);
654
655 if (vsc_result != 0) {
656 ALOGE("%s Failed VSC Op %04x", __FUNCTION__, vsc_opcode);
657 status = BT_VND_OP_RESULT_FAIL;
658 }
659 else if (vsc_opcode == HCI_VSC_UIPC_OVER_HCI) {
660 STREAM_TO_UINT16(uipc_event,p);
661 uipc_opcode = *p;
662 BTA2DPDBG("%s UIPC Event %04x UIPC Op %02x", __FUNCTION__, uipc_event, uipc_opcode);
663
664 switch (uipc_event) {
665 case BT_EVT_BTU_IPC_MGMT_EVT :
666 switch (uipc_opcode) {
667 case UIPC_OPEN_RSP : ssm_event = BRCM_VND_UIPC_OPEN_RSP; break;
668 case UIPC_CLOSE_RSP : ssm_event = BRCM_VND_UIPC_CLOSE_RSP; break;
669 default: status = BT_VND_OP_RESULT_FAIL;
670 }
671 break;
672
673 case BT_EVT_BTU_IPC_BTM_EVT :
674 switch (uipc_opcode) {
675 case A2DP_START_RESP: ssm_event = BRCM_VND_A2DP_START_RSP; break;
676 case A2DP_SUSPEND_RESP: ssm_event = BRCM_VND_A2DP_SUSPEND_RSP; break;
677 case A2DP_CLEANUP_RESP: ssm_event = BRCM_VND_A2DP_CLEANUP_RSP; break;
678 case AUDIO_CODEC_CONFIG_RESP: ssm_event = BRCM_VND_AUDIO_CODEC_CONFIG_RSP; break;
679 case AUDIO_ROUTE_CONFIG_RESP: ssm_event = BRCM_VND_AUDIO_ROUTE_CONFIG_RSP; break;
680 default: status = BT_VND_OP_RESULT_FAIL;
681 }
682 break;
683
684 case BT_EVT_BTU_IPC_L2C_EVT :
685 switch (uipc_opcode) {
686 case L2C_REMOVE_TO_LITE_RESP: ssm_event = BRCM_VND_L2C_REMOVE_TO_LITE_RSP; break;
687 case L2C_SYNC_TO_LITE_RESP: ssm_event = BRCM_VND_L2C_SYNC_TO_LITE_RSP; break;
688 default: status = BT_VND_OP_RESULT_FAIL;
689 }
690 break;
691
692 case BT_EVT_BTU_IPC_AVDT_EVT :
693 if (uipc_opcode == AVDT_SYNC_TO_BTC_LITE_RESP) {
694 ssm_event = BRCM_VND_SYNC_TO_BTC_LITE_RSP;
695 break;
696 }
697
698 default:
699 status = BT_VND_OP_RESULT_FAIL;
700 break;
701 }
702 if (status == BT_VND_OP_RESULT_SUCCESS)
703 brcm_vnd_a2dp_ssm_execute(ssm_event, p);
704 }
705 else if (vsc_opcode == HCI_VSC_READ_PCM_PINS) {
706 STREAM_TO_UINT8(brcm_vnd_a2dp_pdata.pcmi2s_pinmux.fcn, p);
707 STREAM_TO_UINT32(brcm_vnd_a2dp_pdata.pcmi2s_pinmux.pad_conf, p);
708 BTA2DPDBG("%s HCI_VSC_READ_PCM_PINS %02x %08x", __FUNCTION__,
709 brcm_vnd_a2dp_pdata.pcmi2s_pinmux.fcn, brcm_vnd_a2dp_pdata.pcmi2s_pinmux.pad_conf);
710 }
711
712 if (status != BT_VND_OP_RESULT_SUCCESS)
713 brcm_vnd_a2dp_ssm_execute(BRCM_VND_A2DP_OFFLOAD_FAILED_ABORT, NULL);
714
715 /* Free the RX event buffer */
716 bt_vendor_cbacks->dealloc(p_evt_buf);
717 }
718
brcm_vnd_a2dp_init()719 void brcm_vnd_a2dp_init()
720 {
721 if (!bt_vendor_cbacks)
722 return;
723
724 ALOGD("%s ", __FUNCTION__);
725 brcm_vnd_a2dp_ssm_execute(BRCM_VND_A2DP_OFFLOAD_INIT_REQ, NULL);
726 }
727
brcm_vnd_a2dp_execute(bt_vendor_opcode_t opcode,void * ev_data)728 int brcm_vnd_a2dp_execute(bt_vendor_opcode_t opcode, void *ev_data)
729 {
730 tBRCM_VND_A2DP_EVENT ssm_event = (opcode == BT_VND_OP_A2DP_OFFLOAD_START)?
731 BRCM_VND_A2DP_OFFLOAD_START_REQ:BRCM_VND_A2DP_OFFLOAD_STOP_REQ;
732
733 ALOGD("%s opcode %d , state %d", __FUNCTION__, opcode, brcm_vnd_a2dp_pdata.state);
734
735 return brcm_vnd_a2dp_ssm_execute(ssm_event, ev_data);
736 }
737
738
739