1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*****************************************************************************
18 *
19 * Filename: btif_rc.cc
20 *
21 * Description: Bluetooth AVRC implementation
22 *
23 *****************************************************************************/
24
25 #define LOG_TAG "bt_btif_avrc"
26
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <pthread.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33
34 #include <mutex>
35
36 #include <hardware/bluetooth.h>
37 #include <hardware/bt_rc.h>
38
39 #include "avrc_defs.h"
40 #include "bdaddr.h"
41 #include "bt_common.h"
42 #include "bta_api.h"
43 #include "bta_av_api.h"
44 #include "btif_av.h"
45 #include "btif_common.h"
46 #include "btif_util.h"
47 #include "btu.h"
48 #include "device/include/interop.h"
49 #include "osi/include/list.h"
50 #include "osi/include/osi.h"
51 #include "osi/include/properties.h"
52 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
53
54 /*****************************************************************************
55 * Constants & Macros
56 *****************************************************************************/
57
58 /* cod value for Headsets */
59 #define COD_AV_HEADSETS 0x0404
60 /* for AVRC 1.4 need to change this */
61 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
62
63 #define IDX_GET_PLAY_STATUS_RSP 0
64 #define IDX_LIST_APP_ATTR_RSP 1
65 #define IDX_LIST_APP_VALUE_RSP 2
66 #define IDX_GET_CURR_APP_VAL_RSP 3
67 #define IDX_SET_APP_VAL_RSP 4
68 #define IDX_GET_APP_ATTR_TXT_RSP 5
69 #define IDX_GET_APP_VAL_TXT_RSP 6
70 #define IDX_GET_ELEMENT_ATTR_RSP 7
71 #define IDX_SET_ADDR_PLAYER_RSP 8
72 #define IDX_SET_BROWSED_PLAYER_RSP 9
73 #define IDX_GET_FOLDER_ITEMS_RSP 10
74 #define IDX_CHG_PATH_RSP 11
75 #define IDX_GET_ITEM_ATTR_RSP 12
76 #define IDX_PLAY_ITEM_RSP 13
77 #define IDX_GET_TOTAL_NUM_OF_ITEMS_RSP 14
78 #define IDX_SEARCH_RSP 15
79 #define IDX_ADD_TO_NOW_PLAYING_RSP 16
80
81 /* Update MAX value whenever IDX will be changed */
82 #define MAX_CMD_QUEUE_LEN 17
83
84 #define MAX_VOLUME 128
85 #define MAX_LABEL 16
86 #define MAX_TRANSACTIONS_PER_SESSION 16
87 #define PLAY_STATUS_PLAYING 1
88 #define BTIF_RC_NUM_CONN BT_RC_NUM_APP
89
90 #define CHECK_RC_CONNECTED(p_dev) \
91 do { \
92 if ((p_dev) == NULL || (p_dev)->rc_connected == false) { \
93 BTIF_TRACE_WARNING("%s: called when RC is not connected", __func__); \
94 return BT_STATUS_NOT_READY; \
95 } \
96 } while (0)
97
98 #define CHECK_BR_CONNECTED(p_dev) \
99 do { \
100 if ((p_dev) == NULL || (p_dev)->br_connected == false) { \
101 BTIF_TRACE_WARNING("%s: called when BR is not connected", __func__); \
102 return BT_STATUS_NOT_READY; \
103 } \
104 } while (0)
105
106 /*****************************************************************************
107 * Local type definitions
108 *****************************************************************************/
109 typedef struct {
110 uint8_t bNotify;
111 uint8_t label;
112 } btif_rc_reg_notifications_t;
113
114 typedef struct {
115 uint8_t label;
116 uint8_t ctype;
117 bool is_rsp_pending;
118 } btif_rc_cmd_ctxt_t;
119
120 /* 2 second timeout to get interim response */
121 #define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000)
122 #define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000)
123 #define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000)
124
125 typedef enum {
126 eNOT_REGISTERED,
127 eREGISTERED,
128 eINTERIM
129 } btif_rc_nfn_reg_status_t;
130
131 typedef struct {
132 uint8_t event_id;
133 uint8_t label;
134 btif_rc_nfn_reg_status_t status;
135 } btif_rc_supported_event_t;
136
137 #define BTIF_RC_STS_TIMEOUT 0xFE
138 typedef struct {
139 uint8_t label;
140 uint8_t pdu_id;
141 } btif_rc_status_cmd_timer_t;
142
143 typedef struct {
144 uint8_t label;
145 uint8_t pdu_id;
146 } btif_rc_control_cmd_timer_t;
147
148 typedef struct {
149 union {
150 btif_rc_status_cmd_timer_t rc_status_cmd;
151 btif_rc_control_cmd_timer_t rc_control_cmd;
152 };
153 BD_ADDR rc_addr;
154 } btif_rc_timer_context_t;
155
156 typedef struct {
157 bool query_started;
158 uint8_t num_attrs;
159 uint8_t num_ext_attrs;
160
161 uint8_t attr_index;
162 uint8_t ext_attr_index;
163 uint8_t ext_val_index;
164 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE];
165 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE];
166 } btif_rc_player_app_settings_t;
167
168 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single
169 * struct */
170 typedef struct {
171 bool rc_connected;
172 bool br_connected; // Browsing channel.
173 uint8_t rc_handle;
174 tBTA_AV_FEAT rc_features;
175 btrc_connection_state_t rc_state;
176 BD_ADDR rc_addr;
177 uint16_t rc_pending_play;
178 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
179 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
180 unsigned int rc_volume;
181 uint8_t rc_vol_label;
182 list_t* rc_supported_event_list;
183 btif_rc_player_app_settings_t rc_app_settings;
184 alarm_t* rc_play_status_timer;
185 bool rc_features_processed;
186 uint64_t rc_playing_uid;
187 bool rc_procedure_complete;
188 } btif_rc_device_cb_t;
189
190 typedef struct {
191 std::mutex lock;
192 btif_rc_device_cb_t rc_multi_cb[BTIF_RC_NUM_CONN];
193 } rc_cb_t;
194
195 typedef struct {
196 bool in_use;
197 uint8_t lbl;
198 uint8_t handle;
199 btif_rc_timer_context_t txn_timer_context;
200 alarm_t* txn_timer;
201 } rc_transaction_t;
202
203 typedef struct {
204 std::recursive_mutex lbllock;
205 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
206 } rc_device_t;
207
208 typedef struct {
209 uint8_t label;
210 BD_ADDR rc_addr;
211 } rc_context_t;
212
213 typedef struct { uint8_t handle; } btif_rc_handle_t;
214
215 rc_device_t device;
216
217 static void sleep_ms(period_ms_t timeout_ms);
218
219 /* Response status code - Unknown Error - this is changed to "reserved" */
220 #define BTIF_STS_GEN_ERROR 0x06
221
222 /* Utility table to map hal status codes to bta status codes for the response
223 * status */
224 static const uint8_t status_code_map[] = {
225 /* BTA_Status codes HAL_Status codes */
226 AVRC_STS_BAD_CMD, /* BTRC_STS_BAD_CMD */
227 AVRC_STS_BAD_PARAM, /* BTRC_STS_BAD_PARAM */
228 AVRC_STS_NOT_FOUND, /* BTRC_STS_NOT_FOUND */
229 AVRC_STS_INTERNAL_ERR, /* BTRC_STS_INTERNAL_ERR */
230 AVRC_STS_NO_ERROR, /* BTRC_STS_NO_ERROR */
231 AVRC_STS_UID_CHANGED, /* BTRC_STS_UID_CHANGED */
232 BTIF_STS_GEN_ERROR, /* BTRC_STS_RESERVED */
233 AVRC_STS_BAD_DIR, /* BTRC_STS_INV_DIRN */
234 AVRC_STS_NOT_DIR, /* BTRC_STS_INV_DIRECTORY */
235 AVRC_STS_NOT_EXIST, /* BTRC_STS_INV_ITEM */
236 AVRC_STS_BAD_SCOPE, /* BTRC_STS_INV_SCOPE */
237 AVRC_STS_BAD_RANGE, /* BTRC_STS_INV_RANGE */
238 AVRC_STS_UID_IS_DIR, /* BTRC_STS_DIRECTORY */
239 AVRC_STS_IN_USE, /* BTRC_STS_MEDIA_IN_USE */
240 AVRC_STS_NOW_LIST_FULL, /* BTRC_STS_PLAY_LIST_FULL */
241 AVRC_STS_SEARCH_NOT_SUP, /* BTRC_STS_SRCH_NOT_SPRTD */
242 AVRC_STS_SEARCH_BUSY, /* BTRC_STS_SRCH_IN_PROG */
243 AVRC_STS_BAD_PLAYER_ID, /* BTRC_STS_INV_PLAYER */
244 AVRC_STS_PLAYER_N_BR, /* BTRC_STS_PLAY_NOT_BROW */
245 AVRC_STS_PLAYER_N_ADDR, /* BTRC_STS_PLAY_NOT_ADDR */
246 AVRC_STS_BAD_SEARCH_RES, /* BTRC_STS_INV_RESULTS */
247 AVRC_STS_NO_AVAL_PLAYER, /* BTRC_STS_NO_AVBL_PLAY */
248 AVRC_STS_ADDR_PLAYER_CHG, /* BTRC_STS_ADDR_PLAY_CHGD */
249 };
250
251 static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu,
252 uint8_t status, uint8_t opcode);
253 static uint8_t opcode_from_pdu(uint8_t pdu);
254 static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index,
255 uint8_t label, tBTA_AV_CODE code,
256 tAVRC_RESPONSE* pmetamsg_resp);
257 static void register_volumechange(uint8_t label, btif_rc_device_cb_t* p_dev);
258 static void lbl_init();
259 static void init_all_transactions();
260 static bt_status_t get_transaction(rc_transaction_t** ptransaction);
261 static void release_transaction(uint8_t label);
262 static rc_transaction_t* get_transaction_by_lbl(uint8_t label);
263 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg,
264 btif_rc_device_cb_t* p_dev);
265
266 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg);
267 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg);
268 static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,
269 tAVRC_COMMAND* pavrc_cmd,
270 uint8_t label,
271 btif_rc_device_cb_t* p_dev);
272 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev);
273 static void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev);
274 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
275 btif_rc_device_cb_t* p_dev);
276 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg,
277 tAVRC_GET_CAPS_RSP* p_rsp);
278 static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg,
279 tAVRC_LIST_APP_ATTR_RSP* p_rsp);
280 static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg,
281 tAVRC_LIST_APP_VALUES_RSP* p_rsp);
282 static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg,
283 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp);
284 static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg,
285 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
286 static void handle_app_attr_val_txt_response(tBTA_AV_META_MSG* pmeta_msg,
287 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp);
288 static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
289 tAVRC_GET_PLAY_STATUS_RSP* p_rsp);
290 static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg,
291 tAVRC_RSP* p_rsp);
292 static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
293 tAVRC_GET_ATTRS_RSP* p_rsp);
294 static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
295 tAVRC_RSP* p_rsp);
296 static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev);
297 static bt_status_t get_player_app_setting_attr_text_cmd(
298 uint8_t* attrs, uint8_t num_attrs, btif_rc_device_cb_t* p_dev);
299 static bt_status_t get_player_app_setting_value_text_cmd(
300 uint8_t* vals, uint8_t num_vals, btif_rc_device_cb_t* p_dev);
301 static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id,
302 uint32_t event_value,
303 btif_rc_device_cb_t* p_dev);
304 static bt_status_t get_element_attribute_cmd(uint8_t num_attribute,
305 uint32_t* p_attr_ids,
306 btif_rc_device_cb_t* p_dev);
307 static bt_status_t getcapabilities_cmd(uint8_t cap_id,
308 btif_rc_device_cb_t* p_dev);
309 static bt_status_t list_player_app_setting_attrib_cmd(
310 btif_rc_device_cb_t* p_dev);
311 static bt_status_t list_player_app_setting_value_cmd(
312 uint8_t attrib_id, btif_rc_device_cb_t* p_dev);
313 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib,
314 uint8_t* attrib_ids,
315 btif_rc_device_cb_t* p_dev);
316 void get_folder_item_type_media(const tAVRC_ITEM* avrc_item,
317 btrc_folder_items_t* btrc_item);
318 void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
319 btrc_folder_items_t* btrc_item);
320 void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
321 btrc_folder_items_t* btrc_item);
322 static bt_status_t get_folder_items_cmd(bt_bdaddr_t* bd_addr, uint8_t scope,
323 uint8_t start_item, uint8_t num_items);
324
325 static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* p_param,
326 uint8_t ctype, uint8_t label,
327 btif_rc_device_cb_t* p_dev);
328
329 static void btif_rc_upstreams_rsp_evt(uint16_t event,
330 tAVRC_RESPONSE* pavrc_resp, uint8_t ctype,
331 uint8_t label,
332 btif_rc_device_cb_t* p_dev);
333
334 static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev);
335 static bool absolute_volume_disabled(void);
336
337 /*****************************************************************************
338 * Static variables
339 *****************************************************************************/
340 static rc_cb_t btif_rc_cb;
341 static btrc_callbacks_t* bt_rc_callbacks = NULL;
342 static btrc_ctrl_callbacks_t* bt_rc_ctrl_callbacks = NULL;
343
344 /*****************************************************************************
345 * Static functions
346 *****************************************************************************/
347
348 /*****************************************************************************
349 * Externs
350 *****************************************************************************/
351 extern bool btif_hf_call_terminated_recently();
352 extern bool check_cod(const bt_bdaddr_t* remote_bdaddr, uint32_t cod);
353
354 extern fixed_queue_t* btu_general_alarm_queue;
355
356 /*****************************************************************************
357 * Functions
358 *****************************************************************************/
alloc_device()359 static btif_rc_device_cb_t* alloc_device() {
360 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
361 if (btif_rc_cb.rc_multi_cb[idx].rc_state ==
362 BTRC_CONNECTION_STATE_DISCONNECTED) {
363 return (&btif_rc_cb.rc_multi_cb[idx]);
364 }
365 }
366 return NULL;
367 }
368
get_connected_device(int index)369 static btif_rc_device_cb_t* get_connected_device(int index) {
370 BTIF_TRACE_DEBUG("%s: index: %d", __func__, index);
371 if (index > BTIF_RC_NUM_CONN) {
372 BTIF_TRACE_ERROR("%s: can't support more than %d connections", __func__,
373 BTIF_RC_NUM_CONN);
374 return NULL;
375 }
376 if (btif_rc_cb.rc_multi_cb[index].rc_state !=
377 BTRC_CONNECTION_STATE_CONNECTED) {
378 BTIF_TRACE_ERROR("%s: returning NULL", __func__);
379 return NULL;
380 }
381 return (&btif_rc_cb.rc_multi_cb[index]);
382 }
383
get_num_connected_devices()384 static int get_num_connected_devices() {
385 int connected_devices = 0;
386 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
387 if (btif_rc_cb.rc_multi_cb[idx].rc_state ==
388 BTRC_CONNECTION_STATE_CONNECTED) {
389 connected_devices++;
390 }
391 }
392 BTIF_TRACE_DEBUG("%s: returning connected_devices: %d", __func__,
393 connected_devices);
394 return connected_devices;
395 }
396
btif_rc_get_device_by_bda(bt_bdaddr_t * bd_addr)397 btif_rc_device_cb_t* btif_rc_get_device_by_bda(bt_bdaddr_t* bd_addr) {
398 BTIF_TRACE_DEBUG("%s: bd_addr: %02x-%02x-%02x-%02x-%02x-%02x", __func__,
399 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4],
400 bd_addr[5]);
401
402 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
403 if ((btif_rc_cb.rc_multi_cb[idx].rc_state !=
404 BTRC_CONNECTION_STATE_DISCONNECTED) &&
405 (bdcmp(btif_rc_cb.rc_multi_cb[idx].rc_addr, bd_addr->address) == 0)) {
406 return (&btif_rc_cb.rc_multi_cb[idx]);
407 }
408 }
409 BTIF_TRACE_ERROR("%s: device not found, returning NULL!", __func__);
410 return NULL;
411 }
412
btif_rc_get_device_by_handle(uint8_t handle)413 btif_rc_device_cb_t* btif_rc_get_device_by_handle(uint8_t handle) {
414 BTIF_TRACE_DEBUG("%s: handle: 0x%x", __func__, handle);
415 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
416 if ((btif_rc_cb.rc_multi_cb[idx].rc_state !=
417 BTRC_CONNECTION_STATE_DISCONNECTED) &&
418 (btif_rc_cb.rc_multi_cb[idx].rc_handle == handle)) {
419 BTIF_TRACE_DEBUG("%s: btif_rc_cb.rc_multi_cb[idx].rc_handle: 0x%x",
420 __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle);
421 return (&btif_rc_cb.rc_multi_cb[idx]);
422 }
423 }
424 BTIF_TRACE_ERROR("%s: returning NULL", __func__);
425 return NULL;
426 }
427
fill_pdu_queue(int index,uint8_t ctype,uint8_t label,bool pending,btif_rc_device_cb_t * p_dev)428 void fill_pdu_queue(int index, uint8_t ctype, uint8_t label, bool pending,
429 btif_rc_device_cb_t* p_dev) {
430 p_dev->rc_pdu_info[index].ctype = ctype;
431 p_dev->rc_pdu_info[index].label = label;
432 p_dev->rc_pdu_info[index].is_rsp_pending = pending;
433 }
434
fill_avrc_attr_entry(tAVRC_ATTR_ENTRY * attr_vals,int num_attrs,btrc_element_attr_val_t * p_attrs)435 void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs,
436 btrc_element_attr_val_t* p_attrs) {
437 for (int attr_cnt = 0; attr_cnt < num_attrs; attr_cnt++) {
438 attr_vals[attr_cnt].attr_id = p_attrs[attr_cnt].attr_id;
439 attr_vals[attr_cnt].name.charset_id = AVRC_CHARSET_ID_UTF8;
440 attr_vals[attr_cnt].name.str_len =
441 (uint16_t)strlen((char*)p_attrs[attr_cnt].text);
442 attr_vals[attr_cnt].name.p_str = p_attrs[attr_cnt].text;
443 BTIF_TRACE_DEBUG(
444 "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__,
445 (unsigned int)attr_vals[attr_cnt].attr_id,
446 attr_vals[attr_cnt].name.charset_id, attr_vals[attr_cnt].name.str_len,
447 attr_vals[attr_cnt].name.p_str);
448 }
449 }
450
rc_cleanup_sent_cmd(void * p_data)451 void rc_cleanup_sent_cmd(void* p_data) { BTIF_TRACE_DEBUG("%s: ", __func__); }
452
handle_rc_ctrl_features(btif_rc_device_cb_t * p_dev)453 void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) {
454 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG) &&
455 (!(p_dev->rc_features & BTA_AV_FEAT_RCCT) ||
456 !(p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL))) {
457 return;
458 }
459
460 bt_bdaddr_t rc_addr;
461 int rc_features = 0;
462 bdcpy(rc_addr.address, p_dev->rc_addr);
463
464 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) &&
465 (p_dev->rc_features & BTA_AV_FEAT_RCCT)) {
466 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
467 }
468
469 if ((p_dev->rc_features & BTA_AV_FEAT_METADATA) &&
470 (p_dev->rc_features & BTA_AV_FEAT_VENDOR) &&
471 (p_dev->rc_features_processed != true)) {
472 rc_features |= BTRC_FEAT_METADATA;
473
474 /* Mark rc features processed to avoid repeating
475 * the AVRCP procedure every time on receiving this
476 * update.
477 */
478 p_dev->rc_features_processed = true;
479 if (btif_av_is_sink_enabled()) {
480 getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
481 }
482 }
483
484 /* Add browsing feature capability */
485 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) {
486 rc_features |= BTRC_FEAT_BROWSE;
487 }
488
489 BTIF_TRACE_DEBUG("%s: Update rc features to CTRL: %d", __func__, rc_features);
490 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
491 }
492
handle_rc_features(btif_rc_device_cb_t * p_dev)493 void handle_rc_features(btif_rc_device_cb_t* p_dev) {
494 bt_bdaddr_t rc_addr;
495 bdcpy(rc_addr.address, p_dev->rc_addr);
496 bdstr_t addr1, addr2;
497
498 CHECK(bt_rc_callbacks);
499
500 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
501 bt_bdaddr_t avdtp_addr = btif_av_get_addr();
502
503 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
504 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
505 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
506
507 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) ||
508 absolute_volume_disabled() ||
509 bdcmp(avdtp_addr.address, rc_addr.address)) {
510 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
511 }
512
513 if (p_dev->rc_features & BTA_AV_FEAT_BROWSE) {
514 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_BROWSE);
515 }
516
517 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
518 if ((p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL) &&
519 (p_dev->rc_features & BTA_AV_FEAT_RCTG)) {
520 rc_features =
521 (btrc_remote_features_t)(rc_features | BTRC_FEAT_ABSOLUTE_VOLUME);
522 }
523 #endif
524
525 if (p_dev->rc_features & BTA_AV_FEAT_METADATA) {
526 rc_features = (btrc_remote_features_t)(rc_features | BTRC_FEAT_METADATA);
527 }
528
529 BTIF_TRACE_DEBUG("%s: rc_features: 0x%x", __func__, rc_features);
530 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features);
531
532 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
533 BTIF_TRACE_DEBUG(
534 "%s: Checking for feature flags in btif_rc_handler with label: %d",
535 __func__, p_dev->rc_vol_label);
536 // Register for volume change on connect
537 if (p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL &&
538 p_dev->rc_features & BTA_AV_FEAT_RCTG) {
539 rc_transaction_t* p_transaction = NULL;
540 bt_status_t status = BT_STATUS_NOT_READY;
541 if (MAX_LABEL == p_dev->rc_vol_label) {
542 status = get_transaction(&p_transaction);
543 } else {
544 p_transaction = get_transaction_by_lbl(p_dev->rc_vol_label);
545 if (NULL != p_transaction) {
546 BTIF_TRACE_DEBUG(
547 "%s: register_volumechange already in progress for label: %d",
548 __func__, p_dev->rc_vol_label);
549 return;
550 }
551 status = get_transaction(&p_transaction);
552 }
553 if (BT_STATUS_SUCCESS == status && NULL != p_transaction) {
554 p_dev->rc_vol_label = p_transaction->lbl;
555 register_volumechange(p_dev->rc_vol_label, p_dev);
556 }
557 }
558 #endif
559 }
560
561 /***************************************************************************
562 * Function handle_rc_connect
563 *
564 * - Argument: tBTA_AV_RC_OPEN browse RC open data structure
565 *
566 * - Description: browse RC connection event handler
567 *
568 ***************************************************************************/
handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN * p_rc_br_open)569 void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) {
570 BTIF_TRACE_DEBUG("%s: rc_handle %d status %d", __func__,
571 p_rc_br_open->rc_handle, p_rc_br_open->status);
572 btif_rc_device_cb_t* p_dev =
573 btif_rc_get_device_by_handle(p_rc_br_open->rc_handle);
574
575 if (!p_dev) {
576 BTIF_TRACE_ERROR("%s p_dev is null", __func__);
577 return;
578 }
579
580 /* check that we are already connected to this address since being connected
581 * to a browse when not connected to the control channel over AVRCP is
582 * probably not preferred anyways. */
583 if (p_rc_br_open->status == BTA_AV_SUCCESS) {
584 bt_bdaddr_t rc_addr;
585 bdcpy(rc_addr.address, p_dev->rc_addr);
586 p_dev->br_connected = true;
587 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, true, &rc_addr);
588 }
589 }
590
591 /***************************************************************************
592 * Function handle_rc_connect
593 *
594 * - Argument: tBTA_AV_RC_OPEN RC open data structure
595 *
596 * - Description: RC connection event handler
597 *
598 ***************************************************************************/
handle_rc_connect(tBTA_AV_RC_OPEN * p_rc_open)599 void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
600 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __func__, p_rc_open->rc_handle);
601
602 btif_rc_device_cb_t* p_dev = alloc_device();
603 if (p_dev == NULL) {
604 BTIF_TRACE_ERROR("%s: p_dev is NULL", __func__);
605 return;
606 }
607
608 if (!(p_rc_open->status == BTA_AV_SUCCESS)) {
609 BTIF_TRACE_ERROR("%s: Connect failed with error code: %d", __func__,
610 p_rc_open->status);
611 p_dev->rc_connected = false;
612 }
613
614 // check if already some RC is connected
615 if (p_dev->rc_connected) {
616 BTIF_TRACE_ERROR(
617 "%s: Got RC OPEN in connected state, Connected RC: %d \
618 and Current RC: %d",
619 __func__, p_dev->rc_handle, p_rc_open->rc_handle);
620 if ((p_dev->rc_handle != p_rc_open->rc_handle) &&
621 (bdcmp(p_dev->rc_addr, p_rc_open->peer_addr))) {
622 BTIF_TRACE_DEBUG("%s: Got RC connected for some other handle", __func__);
623 BTA_AvCloseRc(p_rc_open->rc_handle);
624 return;
625 }
626 }
627 memcpy(p_dev->rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
628 p_dev->rc_features = p_rc_open->peer_features;
629 BTIF_TRACE_DEBUG("%s: handle_rc_connect in features: 0x%x out features 0x%x",
630 __func__, p_rc_open->peer_features, p_dev->rc_features);
631 p_dev->rc_vol_label = MAX_LABEL;
632 p_dev->rc_volume = MAX_VOLUME;
633
634 p_dev->rc_connected = true;
635 p_dev->rc_handle = p_rc_open->rc_handle;
636 p_dev->rc_state = BTRC_CONNECTION_STATE_CONNECTED;
637 /* on locally initiated connection we will get remote features as part of
638 * connect */
639 if (p_dev->rc_features != 0 && bt_rc_callbacks != NULL) {
640 handle_rc_features(p_dev);
641 }
642
643 p_dev->rc_playing_uid = RC_INVALID_TRACK_ID;
644 bt_bdaddr_t rc_addr;
645 bdcpy(rc_addr.address, p_dev->rc_addr);
646 if (bt_rc_ctrl_callbacks != NULL) {
647 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, true, false, &rc_addr);
648 }
649 /* report connection state if remote device is AVRCP target */
650 handle_rc_ctrl_features(p_dev);
651 }
652
653 /***************************************************************************
654 * Function handle_rc_disconnect
655 *
656 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
657 *
658 * - Description: RC disconnection event handler
659 *
660 ***************************************************************************/
handle_rc_disconnect(tBTA_AV_RC_CLOSE * p_rc_close)661 void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) {
662 btif_rc_device_cb_t* p_dev = NULL;
663 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __func__, p_rc_close->rc_handle);
664
665 p_dev = btif_rc_get_device_by_handle(p_rc_close->rc_handle);
666 if (p_dev == NULL) {
667 BTIF_TRACE_ERROR("%s: Got disconnect from invalid rc handle", __func__);
668 return;
669 }
670
671 if ((p_rc_close->rc_handle != p_dev->rc_handle) &&
672 (bdcmp(p_dev->rc_addr, p_rc_close->peer_addr))) {
673 BTIF_TRACE_ERROR("Got disconnect of unknown device");
674 return;
675 }
676 bt_bdaddr_t rc_addr;
677 bdcpy(rc_addr.address, p_dev->rc_addr);
678 /* Clean up AVRCP procedure flags */
679 memset(&p_dev->rc_app_settings, 0, sizeof(btif_rc_player_app_settings_t));
680 p_dev->rc_features_processed = false;
681 p_dev->rc_procedure_complete = false;
682 rc_stop_play_status_timer(p_dev);
683 /* Check and clear the notification event list */
684 if (p_dev->rc_supported_event_list != NULL) {
685 list_clear(p_dev->rc_supported_event_list);
686 p_dev->rc_supported_event_list = NULL;
687 }
688
689 /* check if there is another device connected */
690 if (p_dev->rc_state == BTRC_CONNECTION_STATE_CONNECTED) {
691 p_dev->rc_handle = 0;
692 p_dev->rc_connected = false;
693 p_dev->rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
694
695 memset(p_dev->rc_notif, 0, sizeof(p_dev->rc_notif));
696
697 p_dev->rc_features = 0;
698 p_dev->rc_vol_label = MAX_LABEL;
699 p_dev->rc_volume = MAX_VOLUME;
700
701 memset(p_dev->rc_addr, 0, sizeof(BD_ADDR));
702 }
703 if (get_num_connected_devices() == 0) {
704 BTIF_TRACE_DEBUG("%s: Closing all handles", __func__);
705 init_all_transactions();
706 }
707
708 memset(p_dev->rc_addr, 0, sizeof(BD_ADDR));
709 /* report connection state if device is AVRCP target */
710 if (bt_rc_ctrl_callbacks != NULL) {
711 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, false, false,
712 &rc_addr);
713 }
714 }
715
716 /***************************************************************************
717 * Function handle_rc_passthrough_cmd
718 *
719 * - Argument: tBTA_AV_RC rc_id remote control command ID
720 * tBTA_AV_STATE key_state status of key press
721 *
722 * - Description: Remote control command handler
723 *
724 ***************************************************************************/
handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD * p_remote_cmd)725 void handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD* p_remote_cmd) {
726 if (p_remote_cmd == NULL) {
727 BTIF_TRACE_ERROR("%s: No remote command!", __func__);
728 return;
729 }
730
731 btif_rc_device_cb_t* p_dev =
732 btif_rc_get_device_by_handle(p_remote_cmd->rc_handle);
733 if (p_dev == NULL) {
734 BTIF_TRACE_ERROR("%s: Got passthrough command from invalid rc handle",
735 __func__);
736 return;
737 }
738
739 bt_bdaddr_t rc_addr;
740 bdcpy(rc_addr.address, p_dev->rc_addr);
741
742 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id: %d", __func__,
743 p_remote_cmd->rc_id);
744
745 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up
746 * this PLAY */
747 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected())) {
748 if (p_remote_cmd->key_state == AVRC_STATE_PRESS) {
749 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command",
750 __func__);
751 p_dev->rc_pending_play = true;
752 }
753 return;
754 }
755
756 /* If we previously queued a play and we get a PAUSE, clear it. */
757 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (p_dev->rc_pending_play)) {
758 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received",
759 __func__);
760 p_dev->rc_pending_play = false;
761 return;
762 }
763
764 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) &&
765 (!btif_av_stream_started_ready())) {
766 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd", __func__);
767 return;
768 }
769
770 int pressed = (p_remote_cmd->key_state == AVRC_STATE_PRESS) ? 1 : 0;
771
772 /* pass all commands up */
773 BTIF_TRACE_DEBUG("%s: rc_features: %d, cmd->rc_id: %d, pressed: %d", __func__,
774 p_dev->rc_features, p_remote_cmd->rc_id, pressed);
775 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed,
776 &rc_addr);
777 }
778
779 /***************************************************************************
780 * Function handle_rc_passthrough_rsp
781 *
782 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
783 *
784 * - Description: Remote control passthrough response handler
785 *
786 ***************************************************************************/
handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)787 void handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) {
788 btif_rc_device_cb_t* p_dev = NULL;
789 bt_bdaddr_t rc_addr;
790
791 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle);
792 if (p_dev == NULL) {
793 BTIF_TRACE_ERROR("%s: passthrough response for Invalid rc handle",
794 __func__);
795 return;
796 }
797
798 bdcpy(rc_addr.address, p_dev->rc_addr);
799
800 if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG)) {
801 BTIF_TRACE_ERROR("%s: DUT does not support AVRCP controller role",
802 __func__);
803 return;
804 }
805
806 const char* status = (p_remote_rsp->key_state == 1) ? "released" : "pressed";
807 BTIF_TRACE_DEBUG("%s: rc_id: %d state: %s", __func__, p_remote_rsp->rc_id,
808 status);
809
810 release_transaction(p_remote_rsp->label);
811 if (bt_rc_ctrl_callbacks != NULL) {
812 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, &rc_addr,
813 p_remote_rsp->rc_id, p_remote_rsp->key_state);
814 }
815 }
816
817 /***************************************************************************
818 * Function handle_rc_vendorunique_rsp
819 *
820 * - Argument: tBTA_AV_REMOTE_RSP command response
821 *
822 * - Description: Remote control vendor unique response handler
823 *
824 ***************************************************************************/
handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)825 void handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP* p_remote_rsp) {
826 btif_rc_device_cb_t* p_dev = NULL;
827 const char* status;
828 uint8_t vendor_id = 0;
829
830 p_dev = btif_rc_get_device_by_handle(p_remote_rsp->rc_handle);
831 if (p_dev == NULL) {
832 BTIF_TRACE_ERROR("%s: Got vendorunique rsp from invalid rc handle",
833 __func__);
834 return;
835 }
836
837 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
838 int key_state;
839 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE) {
840 status = "released";
841 key_state = 1;
842 } else {
843 status = "pressed";
844 key_state = 0;
845 }
846
847 if (p_remote_rsp->len > 0) {
848 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
849 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN - 1];
850 osi_free_and_reset((void**)&p_remote_rsp->p_data);
851 }
852 BTIF_TRACE_DEBUG("%s: vendor_id: %d status: %s", __func__, vendor_id,
853 status);
854
855 release_transaction(p_remote_rsp->label);
856 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id,
857 key_state);
858 } else {
859 BTIF_TRACE_ERROR("%s: Remote does not support AVRCP TG role", __func__);
860 }
861 }
862
863 /***************************************************************************
864 * Function handle_rc_metamsg_cmd
865 *
866 * - Argument: tBTA_AV_VENDOR Structure containing the received
867 * metamsg command
868 *
869 * - Description: Remote control metamsg command handler (AVRCP 1.3)
870 *
871 ***************************************************************************/
handle_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)872 void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
873 /* Parse the metamsg command and pass it on to BTL-IFS */
874 uint8_t scratch_buf[512] = {0};
875 tAVRC_COMMAND avrc_command = {0};
876 tAVRC_STS status;
877 btif_rc_device_cb_t* p_dev = NULL;
878
879 if (NULL == pmeta_msg) {
880 BTIF_TRACE_EVENT("%s: Exiting as pmeta_msg is NULL", __func__);
881 return;
882 }
883
884 if (NULL == pmeta_msg->p_msg) {
885 BTIF_TRACE_EVENT("%s: Exiting as pmeta_msg->p_msg is NULL", __func__);
886 return;
887 }
888
889 BTIF_TRACE_EVENT("%s: pmeta_msg: opcode: %x, code: %x", __func__,
890 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
891
892 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
893 if (p_dev == NULL) {
894 BTIF_TRACE_ERROR("%s: Meta msg event for Invalid rc handle", __func__);
895 return;
896 }
897
898 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR &&
899 pmeta_msg->p_msg->hdr.opcode != AVRC_OP_BROWSE) {
900 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
901 return;
902 }
903
904 if (pmeta_msg->len < 3) {
905 BTIF_TRACE_WARNING("%s: Invalid length. opcode: 0x%x, len: 0x%x", __func__,
906 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->len);
907 return;
908 }
909
910 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) {
911 {
912 rc_transaction_t* transaction = NULL;
913 transaction = get_transaction_by_lbl(pmeta_msg->label);
914 if (transaction != NULL) {
915 handle_rc_metamsg_rsp(pmeta_msg, p_dev);
916 } else {
917 BTIF_TRACE_DEBUG(
918 "%s: Discard vendor dependent rsp. code: %d label: %d.", __func__,
919 pmeta_msg->code, pmeta_msg->label);
920 }
921 return;
922 }
923 }
924
925 status = AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf,
926 sizeof(scratch_buf));
927 BTIF_TRACE_DEBUG("%s: Received vendor command.code,PDU and label: %d, %d, %d",
928 __func__, pmeta_msg->code, avrc_command.cmd.pdu,
929 pmeta_msg->label);
930
931 if (status != AVRC_STS_NO_ERROR) {
932 /* return error */
933 BTIF_TRACE_WARNING(
934 "%s: Error in parsing received metamsg command. status: 0x%02x",
935 __func__, status);
936 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label,
937 avrc_command.pdu, status,
938 pmeta_msg->p_msg->hdr.opcode);
939 } else {
940 /* if RegisterNotification, add it to our registered queue */
941
942 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
943 uint8_t event_id = avrc_command.reg_notif.event_id;
944
945 BTIF_TRACE_EVENT(
946 "%s: New register notification received.event_id: %s, label: 0x%x, "
947 "code: %x",
948 __func__, dump_rc_notification_event_id(event_id), pmeta_msg->label,
949 pmeta_msg->code);
950 p_dev->rc_notif[event_id - 1].bNotify = true;
951 p_dev->rc_notif[event_id - 1].label = pmeta_msg->label;
952 }
953
954 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
955 __func__, dump_rc_pdu(avrc_command.cmd.pdu));
956
957 /* Since handle_rc_metamsg_cmd() itself is called from
958 *btif context, no context switching is required. Invoke
959 * btif_rc_upstreams_evt directly from here. */
960 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command,
961 pmeta_msg->code, pmeta_msg->label, p_dev);
962 }
963 }
964
965 /***************************************************************************
966 **
967 ** Function btif_rc_handler
968 **
969 ** Description RC event handler
970 **
971 ***************************************************************************/
btif_rc_handler(tBTA_AV_EVT event,tBTA_AV * p_data)972 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) {
973 BTIF_TRACE_DEBUG("%s: event: %s", __func__, dump_rc_event(event));
974 btif_rc_device_cb_t* p_dev = NULL;
975 switch (event) {
976 case BTA_AV_RC_OPEN_EVT: {
977 BTIF_TRACE_DEBUG("%s: Peer_features: %x", __func__,
978 p_data->rc_open.peer_features);
979 handle_rc_connect(&(p_data->rc_open));
980 } break;
981
982 case BTA_AV_RC_BROWSE_OPEN_EVT: {
983 /* tell the UL that we have connection to browse channel and that
984 * browse commands can be directed accordingly. */
985 handle_rc_browse_connect(&p_data->rc_browse_open);
986 } break;
987
988 case BTA_AV_RC_CLOSE_EVT: {
989 handle_rc_disconnect(&(p_data->rc_close));
990 } break;
991
992 case BTA_AV_RC_BROWSE_CLOSE_EVT: {
993 BTIF_TRACE_DEBUG("%s: BTA_AV_RC_BROWSE_CLOSE_EVT", __func__);
994 } break;
995
996 case BTA_AV_REMOTE_CMD_EVT: {
997 if (bt_rc_callbacks != NULL) {
998 BTIF_TRACE_DEBUG("%s: rc_id: 0x%x key_state: %d", __func__,
999 p_data->remote_cmd.rc_id,
1000 p_data->remote_cmd.key_state);
1001 handle_rc_passthrough_cmd((&p_data->remote_cmd));
1002 } else {
1003 BTIF_TRACE_ERROR("%s: AVRCP TG role not up, drop passthrough commands",
1004 __func__);
1005 }
1006 } break;
1007
1008 case BTA_AV_REMOTE_RSP_EVT: {
1009 BTIF_TRACE_DEBUG("%s: RSP: rc_id: 0x%x key_state: %d", __func__,
1010 p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1011
1012 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR) {
1013 handle_rc_vendorunique_rsp((&p_data->remote_rsp));
1014 } else {
1015 handle_rc_passthrough_rsp((&p_data->remote_rsp));
1016 }
1017 } break;
1018
1019 case BTA_AV_RC_FEAT_EVT: {
1020 BTIF_TRACE_DEBUG("%s: Peer_features: %x", __func__,
1021 p_data->rc_feat.peer_features);
1022 p_dev = btif_rc_get_device_by_handle(p_data->rc_feat.rc_handle);
1023 if (p_dev == NULL) {
1024 BTIF_TRACE_ERROR("%s: RC Feature event for Invalid rc handle",
1025 __func__);
1026 break;
1027 }
1028
1029 p_dev->rc_features = p_data->rc_feat.peer_features;
1030 if (bt_rc_callbacks != NULL) {
1031 handle_rc_features(p_dev);
1032 }
1033
1034 if ((p_dev->rc_connected) && (bt_rc_ctrl_callbacks != NULL)) {
1035 handle_rc_ctrl_features(p_dev);
1036 }
1037 } break;
1038
1039 case BTA_AV_META_MSG_EVT: {
1040 if (bt_rc_callbacks != NULL) {
1041 BTIF_TRACE_DEBUG("%s: BTA_AV_META_MSG_EVT code: %d label: %d", __func__,
1042 p_data->meta_msg.code, p_data->meta_msg.label);
1043 BTIF_TRACE_DEBUG("%s: company_id: 0x%x len: %d handle: %d", __func__,
1044 p_data->meta_msg.company_id, p_data->meta_msg.len,
1045 p_data->meta_msg.rc_handle);
1046
1047 /* handle the metamsg command */
1048 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1049
1050 /* Free the Memory allocated for tAVRC_MSG */
1051 } else if (bt_rc_ctrl_callbacks != NULL) {
1052 /* This is case of Sink + CT + TG(for abs vol)) */
1053 BTIF_TRACE_DEBUG(
1054 "%s BTA_AV_META_MSG_EVT code:%d label:%d opcode %d ctype %d",
1055 __func__, p_data->meta_msg.code, p_data->meta_msg.label,
1056 p_data->meta_msg.p_msg->hdr.opcode,
1057 p_data->meta_msg.p_msg->hdr.ctype);
1058 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d", __func__,
1059 p_data->meta_msg.company_id, p_data->meta_msg.len,
1060 p_data->meta_msg.rc_handle);
1061 switch (p_data->meta_msg.p_msg->hdr.opcode) {
1062 case AVRC_OP_VENDOR:
1063 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL) &&
1064 (p_data->meta_msg.code <= AVRC_RSP_INTERIM)) {
1065 /* Its a response */
1066 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1067 } else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ) {
1068 /* Its a command */
1069 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1070 }
1071 break;
1072
1073 case AVRC_OP_BROWSE:
1074 if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_CMD) {
1075 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1076 } else if (p_data->meta_msg.p_msg->hdr.ctype == AVRC_RSP) {
1077 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1078 }
1079 break;
1080 }
1081 } else {
1082 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1083 }
1084 } break;
1085
1086 default:
1087 BTIF_TRACE_DEBUG("%s: Unhandled RC event : 0x%x", __func__, event);
1088 }
1089 }
1090
1091 /***************************************************************************
1092 **
1093 ** Function btif_rc_get_connected_peer
1094 **
1095 ** Description Fetches the connected headset's BD_ADDR if any
1096 **
1097 ***************************************************************************/
btif_rc_get_connected_peer(BD_ADDR peer_addr)1098 bool btif_rc_get_connected_peer(BD_ADDR peer_addr) {
1099 bt_bdaddr_t rc_addr;
1100 bdcpy(rc_addr.address, peer_addr);
1101 btif_rc_device_cb_t* p_dev = NULL;
1102
1103 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1104 p_dev = get_connected_device(idx);
1105 if (p_dev != NULL && (p_dev->rc_connected == TRUE)) {
1106 bdcpy(peer_addr, p_dev->rc_addr);
1107 return true;
1108 }
1109 }
1110 return false;
1111 }
1112
1113 /***************************************************************************
1114 **
1115 ** Function btif_rc_get_connected_peer_handle
1116 **
1117 ** Description Fetches the connected headset's handle if any
1118 **
1119 ***************************************************************************/
btif_rc_get_connected_peer_handle(BD_ADDR peer_addr)1120 uint8_t btif_rc_get_connected_peer_handle(BD_ADDR peer_addr) {
1121 bt_bdaddr_t rc_addr;
1122 bdcpy(rc_addr.address, peer_addr);
1123
1124 btif_rc_device_cb_t* p_dev = NULL;
1125 p_dev = btif_rc_get_device_by_bda(&rc_addr);
1126
1127 if (p_dev == NULL) {
1128 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
1129 return BTRC_HANDLE_NONE;
1130 }
1131 return p_dev->rc_handle;
1132 }
1133
1134 /***************************************************************************
1135 **
1136 ** Function btif_rc_check_handle_pending_play
1137 **
1138 ** Description Clears the queued PLAY command. if |bSendToApp| is true,
1139 ** forwards to app
1140 **
1141 ***************************************************************************/
1142
1143 /* clear the queued PLAY command. if |bSendToApp| is true, forward to app */
btif_rc_check_handle_pending_play(BD_ADDR peer_addr,bool bSendToApp)1144 void btif_rc_check_handle_pending_play(BD_ADDR peer_addr, bool bSendToApp) {
1145 bt_bdaddr_t rc_addr;
1146 bdcpy(rc_addr.address, peer_addr);
1147
1148 btif_rc_device_cb_t* p_dev = NULL;
1149 p_dev = btif_rc_get_device_by_bda(&rc_addr);
1150
1151 if (p_dev == NULL) {
1152 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
1153 return;
1154 }
1155
1156 BTIF_TRACE_DEBUG("%s: bSendToApp: %d", __func__, bSendToApp);
1157 if (p_dev->rc_pending_play) {
1158 if (bSendToApp) {
1159 tBTA_AV_REMOTE_CMD remote_cmd;
1160 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __func__);
1161
1162 memset(&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1163 remote_cmd.rc_handle = p_dev->rc_handle;
1164 remote_cmd.rc_id = AVRC_ID_PLAY;
1165 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1166 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1167
1168 /* delay sending to app, else there is a timing issue in the framework,
1169 ** which causes the audio to be on th device's speaker. Delay between
1170 ** OPEN & RC_PLAYs
1171 */
1172 sleep_ms(200);
1173 /* send to app - both PRESSED & RELEASED */
1174 remote_cmd.key_state = AVRC_STATE_PRESS;
1175 handle_rc_passthrough_cmd(&remote_cmd);
1176
1177 sleep_ms(100);
1178
1179 remote_cmd.key_state = AVRC_STATE_RELEASE;
1180 handle_rc_passthrough_cmd(&remote_cmd);
1181 }
1182 p_dev->rc_pending_play = false;
1183 }
1184 }
1185
1186 /* Generic reject response */
send_reject_response(uint8_t rc_handle,uint8_t label,uint8_t pdu,uint8_t status,uint8_t opcode)1187 static void send_reject_response(uint8_t rc_handle, uint8_t label, uint8_t pdu,
1188 uint8_t status, uint8_t opcode) {
1189 uint8_t ctype = AVRC_RSP_REJ;
1190 tAVRC_RESPONSE avrc_rsp;
1191 BT_HDR* p_msg = NULL;
1192 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1193
1194 avrc_rsp.rsp.opcode = opcode;
1195 avrc_rsp.rsp.pdu = pdu;
1196 avrc_rsp.rsp.status = status;
1197
1198 status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg);
1199
1200 if (status != AVRC_STS_NO_ERROR) {
1201 BTIF_TRACE_ERROR("%s: status not AVRC_STS_NO_ERROR", __func__);
1202 return;
1203 }
1204
1205 BTIF_TRACE_DEBUG(
1206 "%s: Sending error notification to handle: %d. pdu: %s,status: 0x%02x",
1207 __func__, rc_handle, dump_rc_pdu(pdu), status);
1208 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1209 }
1210
1211 /***************************************************************************
1212 * Function get_rsp_type_code
1213 *
1214 * - Argument: status
1215 * - Description: Returns response type codes for particular command code and
1216 * status.
1217 *
1218 ***************************************************************************/
get_rsp_type_code(tAVRC_STS status,tBTA_AV_CODE code)1219 static tBTA_AV_CODE get_rsp_type_code(tAVRC_STS status, tBTA_AV_CODE code) {
1220 if (status != AVRC_STS_NO_ERROR) {
1221 return AVRC_RSP_REJ;
1222 }
1223
1224 if (code < AVRC_RSP_NOT_IMPL) {
1225 if (code == AVRC_CMD_NOTIF) return AVRC_RSP_INTERIM;
1226
1227 if (code == AVRC_CMD_STATUS) return AVRC_RSP_IMPL_STBL;
1228
1229 return AVRC_RSP_ACCEPT;
1230 }
1231
1232 return code;
1233 }
1234
1235 /***************************************************************************
1236 * Function send_metamsg_rsp
1237 *
1238 * - Argument:
1239 * p_dev Dev pointer
1240 * index Command index (= -1 if not used)
1241 * label Label of the RC response
1242 * code Response type
1243 * pmetamsg_resp Vendor response
1244 *
1245 * - Description: Remote control metamsg response handler
1246 *
1247 ***************************************************************************/
send_metamsg_rsp(btif_rc_device_cb_t * p_dev,int index,uint8_t label,tBTA_AV_CODE code,tAVRC_RESPONSE * pmetamsg_resp)1248 static void send_metamsg_rsp(btif_rc_device_cb_t* p_dev, int index,
1249 uint8_t label, tBTA_AV_CODE code,
1250 tAVRC_RESPONSE* pmetamsg_resp) {
1251 uint8_t ctype;
1252
1253 if (p_dev == NULL) {
1254 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
1255 return;
1256 }
1257
1258 if (pmetamsg_resp == NULL) {
1259 BTIF_TRACE_WARNING("%s: Invalid response received from application",
1260 __func__);
1261 return;
1262 }
1263
1264 BTIF_TRACE_EVENT(
1265 "%s: rc_handle: %d, index: %d, label: %d, code: 0x%02x, pdu: %s",
1266 __func__, p_dev->rc_handle, index, label, code,
1267 dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1268
1269 if (index >= 0 && p_dev->rc_pdu_info[index].is_rsp_pending == false) {
1270 BTIF_TRACE_ERROR("%s: is_rsp_pending false, returning", __func__);
1271 return;
1272 }
1273
1274 ctype = get_rsp_type_code(pmetamsg_resp->rsp.status, code);
1275
1276 /* if response is for register_notification, make sure the rc has
1277 actually registered for this */
1278 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) &&
1279 ((code == AVRC_RSP_CHANGED) || (code == AVRC_RSP_INTERIM))) {
1280 bool bSent = false;
1281 uint8_t event_id = pmetamsg_resp->reg_notif.event_id;
1282 bool bNotify =
1283 (p_dev->rc_connected) && (p_dev->rc_notif[event_id - 1].bNotify);
1284
1285 /* de-register this notification for a CHANGED response */
1286 p_dev->rc_notif[event_id - 1].bNotify = false;
1287 BTIF_TRACE_DEBUG("%s: rc_handle: %d. event_id: 0x%02d bNotify: %u",
1288 __func__, p_dev->rc_handle, event_id, bNotify);
1289 if (bNotify) {
1290 BT_HDR* p_msg = NULL;
1291 tAVRC_STS status;
1292
1293 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(
1294 p_dev->rc_handle, pmetamsg_resp, &p_msg))) {
1295 BTIF_TRACE_DEBUG(
1296 "%s: Sending notification to rc_handle: %d. event_id: 0x%02d",
1297 __func__, p_dev->rc_handle, event_id);
1298 bSent = true;
1299 BTA_AvMetaRsp(p_dev->rc_handle, p_dev->rc_notif[event_id - 1].label,
1300 ctype, p_msg);
1301 } else {
1302 BTIF_TRACE_WARNING(
1303 "%s: failed to build metamsg response. status: 0x%02x", __func__,
1304 status);
1305 }
1306 }
1307
1308 if (!bSent) {
1309 BTIF_TRACE_DEBUG(
1310 "%s: Notification not sent, as there are no RC connections or the \
1311 CT has not subscribed for event_id: %s",
1312 __func__, dump_rc_notification_event_id(event_id));
1313 }
1314 } else {
1315 /* All other commands go here */
1316
1317 BT_HDR* p_msg = NULL;
1318 tAVRC_STS status;
1319
1320 status = AVRC_BldResponse(p_dev->rc_handle, pmetamsg_resp, &p_msg);
1321
1322 if (status == AVRC_STS_NO_ERROR) {
1323 BTA_AvMetaRsp(p_dev->rc_handle, label, ctype, p_msg);
1324 } else {
1325 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1326 __func__, status);
1327 }
1328 }
1329
1330 if (index >= 0) {
1331 p_dev->rc_pdu_info[index].ctype = 0;
1332 p_dev->rc_pdu_info[index].label = 0;
1333 p_dev->rc_pdu_info[index].is_rsp_pending = false;
1334 }
1335 }
1336
opcode_from_pdu(uint8_t pdu)1337 static uint8_t opcode_from_pdu(uint8_t pdu) {
1338 uint8_t opcode = 0;
1339
1340 switch (pdu) {
1341 case AVRC_PDU_SET_BROWSED_PLAYER:
1342 case AVRC_PDU_GET_FOLDER_ITEMS:
1343 case AVRC_PDU_CHANGE_PATH:
1344 case AVRC_PDU_GET_ITEM_ATTRIBUTES:
1345 case AVRC_PDU_ADD_TO_NOW_PLAYING:
1346 case AVRC_PDU_SEARCH:
1347 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
1348 case AVRC_PDU_GENERAL_REJECT:
1349 opcode = AVRC_OP_BROWSE;
1350 break;
1351
1352 case AVRC_PDU_NEXT_GROUP:
1353 case AVRC_PDU_PREV_GROUP: /* pass thru */
1354 opcode = AVRC_OP_PASS_THRU;
1355 break;
1356
1357 default: /* vendor */
1358 opcode = AVRC_OP_VENDOR;
1359 break;
1360 }
1361
1362 return opcode;
1363 }
1364
1365 /***************************************************************************
1366 * Function: fill_attribute_id_array
1367 *
1368 * - Argument:
1369 * cmd_attribute_number input attribute number from AVRCP command
1370 * cmd_attribute_id_array input attribute list from AVRCP command
1371 * out_array_size allocated size of out attribute id array
1372 * out_attribute_id_array output attribute list resolved here
1373 *
1374 * - Description:
1375 * Resolve attribute id array as defined by the AVRCP specification.
1376 *
1377 * - Returns:
1378 * The number of attributes filled in
1379 *
1380 ***************************************************************************/
fill_attribute_id_array(uint8_t cmd_attribute_number,btrc_media_attr_t * cmd_attribute_id_array,size_t out_array_size,btrc_media_attr_t * out_attribute_id_array)1381 static uint8_t fill_attribute_id_array(
1382 uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array,
1383 size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) {
1384 /* Reset attribute array */
1385 memset(out_attribute_id_array, 0, out_array_size);
1386 /* Default case for cmd_attribute_number == 0xFF, No attribute */
1387 uint8_t out_attribute_number = 0;
1388 if (cmd_attribute_number == 0) {
1389 /* All attributes */
1390 out_attribute_number = out_array_size < AVRC_MAX_NUM_MEDIA_ATTR_ID
1391 ? out_array_size
1392 : AVRC_MAX_NUM_MEDIA_ATTR_ID;
1393 for (int i = 0; i < out_attribute_number; i++) {
1394 out_attribute_id_array[i] = (btrc_media_attr_t)(i + 1);
1395 }
1396 } else if (cmd_attribute_number != 0xFF) {
1397 /* Attribute List */
1398 out_attribute_number = 0;
1399 int filled_id_count = 0;
1400 for (int i = 0; (i < cmd_attribute_number) &&
1401 (out_attribute_number < out_array_size) &&
1402 (out_attribute_number < AVRC_MAX_NUM_MEDIA_ATTR_ID);
1403 i++) {
1404 /* Fill only valid entries */
1405 if (AVRC_IS_VALID_MEDIA_ATTRIBUTE(cmd_attribute_id_array[i])) {
1406 /* Skip the duplicate entries */
1407 for (filled_id_count = 0; filled_id_count < out_attribute_number;
1408 filled_id_count++) {
1409 if (out_attribute_id_array[filled_id_count] ==
1410 cmd_attribute_id_array[i])
1411 break;
1412 }
1413 /* New ID */
1414 if (filled_id_count == out_attribute_number) {
1415 out_attribute_id_array[out_attribute_number] =
1416 (btrc_media_attr_t)cmd_attribute_id_array[i];
1417 out_attribute_number++;
1418 }
1419 }
1420 }
1421 }
1422 return out_attribute_number;
1423 }
1424
1425 /*******************************************************************************
1426 *
1427 * Function btif_rc_upstreams_evt
1428 *
1429 * Description Executes AVRC UPSTREAMS events in btif context.
1430 *
1431 * Returns void
1432 *
1433 ******************************************************************************/
btif_rc_upstreams_evt(uint16_t event,tAVRC_COMMAND * pavrc_cmd,uint8_t ctype,uint8_t label,btif_rc_device_cb_t * p_dev)1434 static void btif_rc_upstreams_evt(uint16_t event, tAVRC_COMMAND* pavrc_cmd,
1435 uint8_t ctype, uint8_t label,
1436 btif_rc_device_cb_t* p_dev) {
1437 BTIF_TRACE_EVENT("%s: pdu: %s handle: 0x%x ctype: %x label: %x event ID: %x",
1438 __func__, dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle,
1439 ctype, label, pavrc_cmd->reg_notif.event_id);
1440 bt_bdaddr_t rc_addr;
1441
1442 bdcpy(rc_addr.address, p_dev->rc_addr);
1443
1444 switch (event) {
1445 case AVRC_PDU_GET_PLAY_STATUS: {
1446 fill_pdu_queue(IDX_GET_PLAY_STATUS_RSP, ctype, label, true, p_dev);
1447 HAL_CBACK(bt_rc_callbacks, get_play_status_cb, &rc_addr);
1448 } break;
1449 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1450 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1451 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1452 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1453 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1454 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
1455 /* TODO: Add support for Application Settings */
1456 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1457 AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode);
1458 } break;
1459 case AVRC_PDU_GET_ELEMENT_ATTR: {
1460 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1461 uint8_t num_attr = fill_attribute_id_array(
1462 pavrc_cmd->get_elem_attrs.num_attr,
1463 (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs,
1464 BTRC_MAX_ELEM_ATTR_SIZE, element_attrs);
1465 if (num_attr == 0) {
1466 BTIF_TRACE_ERROR(
1467 "%s: No valid attributes requested in GET_ELEMENT_ATTRIBUTES",
1468 __func__);
1469 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1470 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1471 return;
1472 }
1473 fill_pdu_queue(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, true, p_dev);
1474 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs,
1475 &rc_addr);
1476 } break;
1477 case AVRC_PDU_REGISTER_NOTIFICATION: {
1478 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1479 pavrc_cmd->reg_notif.param == 0) {
1480 BTIF_TRACE_WARNING(
1481 "%s: Device registering position changed with illegal param 0.",
1482 __func__);
1483 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1484 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1485 /* de-register this notification for a rejected response */
1486 p_dev->rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = false;
1487 return;
1488 }
1489 HAL_CBACK(bt_rc_callbacks, register_notification_cb,
1490 (btrc_event_id_t)pavrc_cmd->reg_notif.event_id,
1491 pavrc_cmd->reg_notif.param, &rc_addr);
1492 } break;
1493 case AVRC_PDU_INFORM_DISPLAY_CHARSET: {
1494 tAVRC_RESPONSE avrc_rsp;
1495 BTIF_TRACE_EVENT("%s: AVRC_PDU_INFORM_DISPLAY_CHARSET", __func__);
1496 if (p_dev->rc_connected == true) {
1497 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1498 avrc_rsp.inform_charset.opcode =
1499 opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1500 avrc_rsp.inform_charset.pdu = AVRC_PDU_INFORM_DISPLAY_CHARSET;
1501 avrc_rsp.inform_charset.status = AVRC_STS_NO_ERROR;
1502 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1503 }
1504 } break;
1505
1506 case AVRC_PDU_GET_FOLDER_ITEMS: {
1507 uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE];
1508 uint8_t num_attr;
1509 num_attr = pavrc_cmd->get_items.attr_count;
1510
1511 BTIF_TRACE_EVENT(
1512 "%s: AVRC_PDU_GET_FOLDER_ITEMS num_attr: %d, start_item [%d] \
1513 end_item [%d]",
1514 __func__, num_attr, pavrc_cmd->get_items.start_item,
1515 pavrc_cmd->get_items.end_item);
1516
1517 /* num_attr requested:
1518 * 0x00: All attributes requested
1519 * 0xFF: No Attributes requested
1520 * 0x01 to 0x07: Specified number of attributes
1521 */
1522 if ((num_attr != 0xFF && num_attr > BTRC_MAX_ELEM_ATTR_SIZE)) {
1523 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1524 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1525 return;
1526 }
1527
1528 /* Except num_attr is None(0xff) / All(0x00), request follows with an
1529 * Attribute List */
1530 if ((num_attr != 0xFF) && (num_attr != 0x00)) {
1531 memcpy(attr_ids, pavrc_cmd->get_items.p_attr_list,
1532 sizeof(uint32_t) * num_attr);
1533 }
1534
1535 fill_pdu_queue(IDX_GET_FOLDER_ITEMS_RSP, ctype, label, true, p_dev);
1536 HAL_CBACK(bt_rc_callbacks, get_folder_items_cb,
1537 pavrc_cmd->get_items.scope, pavrc_cmd->get_items.start_item,
1538 pavrc_cmd->get_items.end_item, num_attr, attr_ids, &rc_addr);
1539 } break;
1540
1541 case AVRC_PDU_SET_ADDRESSED_PLAYER: {
1542 fill_pdu_queue(IDX_SET_ADDR_PLAYER_RSP, ctype, label, true, p_dev);
1543 HAL_CBACK(bt_rc_callbacks, set_addressed_player_cb,
1544 pavrc_cmd->addr_player.player_id, &rc_addr);
1545 } break;
1546
1547 case AVRC_PDU_SET_BROWSED_PLAYER: {
1548 fill_pdu_queue(IDX_SET_BROWSED_PLAYER_RSP, ctype, label, true, p_dev);
1549 HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb,
1550 pavrc_cmd->br_player.player_id, &rc_addr);
1551 } break;
1552
1553 case AVRC_PDU_REQUEST_CONTINUATION_RSP: {
1554 BTIF_TRACE_EVENT("%s() REQUEST CONTINUATION: target_pdu: 0x%02d",
1555 __func__, pavrc_cmd->continu.target_pdu);
1556 tAVRC_RESPONSE avrc_rsp;
1557 if (p_dev->rc_connected == TRUE) {
1558 memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP));
1559 avrc_rsp.continu.opcode =
1560 opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP);
1561 avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
1562 avrc_rsp.continu.status = AVRC_STS_NO_ERROR;
1563 avrc_rsp.continu.target_pdu = pavrc_cmd->continu.target_pdu;
1564 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1565 }
1566 } break;
1567
1568 case AVRC_PDU_ABORT_CONTINUATION_RSP: {
1569 BTIF_TRACE_EVENT("%s() ABORT CONTINUATION: target_pdu: 0x%02d", __func__,
1570 pavrc_cmd->abort.target_pdu);
1571 tAVRC_RESPONSE avrc_rsp;
1572 if (p_dev->rc_connected == TRUE) {
1573 memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP));
1574 avrc_rsp.abort.opcode =
1575 opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP);
1576 avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP;
1577 avrc_rsp.abort.status = AVRC_STS_NO_ERROR;
1578 avrc_rsp.abort.target_pdu = pavrc_cmd->continu.target_pdu;
1579 send_metamsg_rsp(p_dev, -1, label, ctype, &avrc_rsp);
1580 }
1581 } break;
1582
1583 case AVRC_PDU_CHANGE_PATH: {
1584 fill_pdu_queue(IDX_CHG_PATH_RSP, ctype, label, true, p_dev);
1585 HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction,
1586 pavrc_cmd->chg_path.folder_uid, &rc_addr);
1587 } break;
1588
1589 case AVRC_PDU_SEARCH: {
1590 fill_pdu_queue(IDX_SEARCH_RSP, ctype, label, true, p_dev);
1591 HAL_CBACK(bt_rc_callbacks, search_cb, pavrc_cmd->search.string.charset_id,
1592 pavrc_cmd->search.string.str_len,
1593 pavrc_cmd->search.string.p_str, &rc_addr);
1594 } break;
1595
1596 case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
1597 btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1598 uint8_t num_attr = fill_attribute_id_array(
1599 pavrc_cmd->get_attrs.attr_count,
1600 (btrc_media_attr_t*)pavrc_cmd->get_attrs.p_attr_list,
1601 BTRC_MAX_ELEM_ATTR_SIZE, item_attrs);
1602 if (num_attr == 0) {
1603 BTIF_TRACE_ERROR(
1604 "%s: No valid attributes requested in GET_ITEM_ATTRIBUTES",
1605 __func__);
1606 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1607 AVRC_STS_BAD_PARAM, pavrc_cmd->cmd.opcode);
1608 return;
1609 }
1610 fill_pdu_queue(IDX_GET_ITEM_ATTR_RSP, ctype, label, true, p_dev);
1611 BTIF_TRACE_DEBUG("%s: GET_ITEM_ATTRIBUTES: num_attr: %d", __func__,
1612 num_attr);
1613 HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
1614 pavrc_cmd->get_attrs.uid, pavrc_cmd->get_attrs.uid_counter,
1615 num_attr, item_attrs, &rc_addr);
1616 } break;
1617
1618 case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS: {
1619 fill_pdu_queue(IDX_GET_TOTAL_NUM_OF_ITEMS_RSP, ctype, label, true, p_dev);
1620 HAL_CBACK(bt_rc_callbacks, get_total_num_of_items_cb,
1621 pavrc_cmd->get_num_of_items.scope, &rc_addr);
1622 } break;
1623
1624 case AVRC_PDU_ADD_TO_NOW_PLAYING: {
1625 fill_pdu_queue(IDX_ADD_TO_NOW_PLAYING_RSP, ctype, label, true, p_dev);
1626 HAL_CBACK(bt_rc_callbacks, add_to_now_playing_cb,
1627 pavrc_cmd->add_to_play.scope, pavrc_cmd->add_to_play.uid,
1628 pavrc_cmd->add_to_play.uid_counter, &rc_addr);
1629 } break;
1630
1631 case AVRC_PDU_PLAY_ITEM: {
1632 fill_pdu_queue(IDX_PLAY_ITEM_RSP, ctype, label, true, p_dev);
1633 HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
1634 pavrc_cmd->play_item.uid_counter, pavrc_cmd->play_item.uid,
1635 &rc_addr);
1636 } break;
1637
1638 default: {
1639 send_reject_response(p_dev->rc_handle, label, pavrc_cmd->pdu,
1640 AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode);
1641 return;
1642 } break;
1643 }
1644 }
1645
1646 /*******************************************************************************
1647 *
1648 * Function btif_rc_ctrl_upstreams_rsp_cmd
1649 *
1650 * Description Executes AVRC UPSTREAMS response events in btif context.
1651 *
1652 * Returns void
1653 *
1654 ******************************************************************************/
btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,tAVRC_COMMAND * pavrc_cmd,uint8_t label,btif_rc_device_cb_t * p_dev)1655 static void btif_rc_ctrl_upstreams_rsp_cmd(uint8_t event,
1656 tAVRC_COMMAND* pavrc_cmd,
1657 uint8_t label,
1658 btif_rc_device_cb_t* p_dev) {
1659 BTIF_TRACE_DEBUG("%s: pdu: %s: handle: 0x%x", __func__,
1660 dump_rc_pdu(pavrc_cmd->pdu), p_dev->rc_handle);
1661 bt_bdaddr_t rc_addr;
1662 bdcpy(rc_addr.address, p_dev->rc_addr);
1663 switch (event) {
1664 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1665 HAL_CBACK(bt_rc_ctrl_callbacks, setabsvol_cmd_cb, &rc_addr,
1666 pavrc_cmd->volume.volume, label);
1667 break;
1668 case AVRC_PDU_REGISTER_NOTIFICATION:
1669 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE) {
1670 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1671 &rc_addr, label);
1672 }
1673 break;
1674 }
1675 }
1676
1677 /*******************************************************************************
1678 *
1679 * Function btif_rc_upstreams_rsp_evt
1680 *
1681 * Description Executes AVRC UPSTREAMS response events in btif context.
1682 *
1683 * Returns void
1684 *
1685 ******************************************************************************/
btif_rc_upstreams_rsp_evt(uint16_t event,tAVRC_RESPONSE * pavrc_resp,uint8_t ctype,uint8_t label,btif_rc_device_cb_t * p_dev)1686 static void btif_rc_upstreams_rsp_evt(uint16_t event,
1687 tAVRC_RESPONSE* pavrc_resp, uint8_t ctype,
1688 uint8_t label,
1689 btif_rc_device_cb_t* p_dev) {
1690 BTIF_TRACE_EVENT("%s: pdu: %s: handle: 0x%x ctype: %x label: %x", __func__,
1691 dump_rc_pdu(pavrc_resp->pdu), p_dev->rc_handle, ctype,
1692 label);
1693 bt_bdaddr_t rc_addr;
1694 bdcpy(rc_addr.address, p_dev->rc_addr);
1695
1696 switch (event) {
1697 case AVRC_PDU_REGISTER_NOTIFICATION: {
1698 if (AVRC_RSP_CHANGED == ctype)
1699 p_dev->rc_volume = pavrc_resp->reg_notif.param.volume;
1700 HAL_CBACK(bt_rc_callbacks, volume_change_cb,
1701 pavrc_resp->reg_notif.param.volume, ctype, &rc_addr);
1702 } break;
1703
1704 case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
1705 BTIF_TRACE_DEBUG(
1706 "%s: Set absolute volume change event received: volume: %d, ctype: "
1707 "%d",
1708 __func__, pavrc_resp->volume.volume, ctype);
1709 if (AVRC_RSP_ACCEPT == ctype)
1710 p_dev->rc_volume = pavrc_resp->volume.volume;
1711 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->volume.volume,
1712 ctype, &rc_addr);
1713 } break;
1714
1715 default:
1716 return;
1717 }
1718 }
1719
1720 /*******************************************************************************
1721 * AVRCP API Functions
1722 ******************************************************************************/
1723
1724 /*******************************************************************************
1725 *
1726 * Function init
1727 *
1728 * Description Initializes the AVRC interface
1729 *
1730 * Returns bt_status_t
1731 *
1732 ******************************************************************************/
init(btrc_callbacks_t * callbacks)1733 static bt_status_t init(btrc_callbacks_t* callbacks) {
1734 BTIF_TRACE_EVENT("%s: ", __func__);
1735 bt_status_t result = BT_STATUS_SUCCESS;
1736
1737 if (bt_rc_callbacks) return BT_STATUS_DONE;
1738
1739 bt_rc_callbacks = callbacks;
1740 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1741 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
1742 sizeof(btif_rc_cb.rc_multi_cb[idx]));
1743 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL;
1744 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME;
1745 btif_rc_cb.rc_multi_cb[idx].rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
1746 }
1747 lbl_init();
1748
1749 return result;
1750 }
1751
1752 /*******************************************************************************
1753 *
1754 * Function init_ctrl
1755 *
1756 * Description Initializes the AVRC interface
1757 *
1758 * Returns bt_status_t
1759 *
1760 ******************************************************************************/
init_ctrl(btrc_ctrl_callbacks_t * callbacks)1761 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks) {
1762 BTIF_TRACE_EVENT("%s: ", __func__);
1763 bt_status_t result = BT_STATUS_SUCCESS;
1764
1765 if (bt_rc_ctrl_callbacks) return BT_STATUS_DONE;
1766
1767 bt_rc_ctrl_callbacks = callbacks;
1768 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1769 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
1770 sizeof(btif_rc_cb.rc_multi_cb[idx]));
1771 btif_rc_cb.rc_multi_cb[idx].rc_vol_label = MAX_LABEL;
1772 btif_rc_cb.rc_multi_cb[idx].rc_volume = MAX_VOLUME;
1773 }
1774 lbl_init();
1775
1776 return result;
1777 }
1778
rc_ctrl_procedure_complete(btif_rc_device_cb_t * p_dev)1779 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev) {
1780 if (p_dev == NULL) {
1781 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
1782 return;
1783 }
1784
1785 if (p_dev->rc_procedure_complete == true) {
1786 return;
1787 }
1788 p_dev->rc_procedure_complete = true;
1789 uint32_t attr_list[] = {
1790 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST,
1791 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1792 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE,
1793 AVRC_MEDIA_ATTR_ID_PLAYING_TIME};
1794 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev);
1795 }
1796
1797 /***************************************************************************
1798 *
1799 * Function get_play_status_rsp
1800 *
1801 * Description Returns the current play status.
1802 * This method is called in response to
1803 * GetPlayStatus request.
1804 *
1805 * Returns bt_status_t
1806 *
1807 **************************************************************************/
get_play_status_rsp(bt_bdaddr_t * bd_addr,btrc_play_status_t play_status,uint32_t song_len,uint32_t song_pos)1808 static bt_status_t get_play_status_rsp(bt_bdaddr_t* bd_addr,
1809 btrc_play_status_t play_status,
1810 uint32_t song_len, uint32_t song_pos) {
1811 tAVRC_RESPONSE avrc_rsp;
1812 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1813
1814 BTIF_TRACE_DEBUG("%s: song len %d song pos %d", __func__, song_len, song_pos);
1815 CHECK_RC_CONNECTED(p_dev);
1816
1817 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1818
1819 avrc_rsp.get_play_status.song_len = song_len;
1820 avrc_rsp.get_play_status.song_pos = song_pos;
1821 avrc_rsp.get_play_status.play_status = play_status;
1822
1823 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1824 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1825 avrc_rsp.get_play_status.status =
1826 ((play_status != BTRC_PLAYSTATE_ERROR) ? AVRC_STS_NO_ERROR
1827 : AVRC_STS_BAD_PARAM);
1828
1829 /* Send the response */
1830 send_metamsg_rsp(p_dev, IDX_GET_PLAY_STATUS_RSP,
1831 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].label,
1832 p_dev->rc_pdu_info[IDX_GET_PLAY_STATUS_RSP].ctype,
1833 &avrc_rsp);
1834
1835 return BT_STATUS_SUCCESS;
1836 }
1837
1838 /***************************************************************************
1839 *
1840 * Function get_element_attr_rsp
1841 *
1842 * Description Returns the current songs' element attributes
1843 * in text.
1844 *
1845 * Returns bt_status_t
1846 *
1847 **************************************************************************/
get_element_attr_rsp(bt_bdaddr_t * bd_addr,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)1848 static bt_status_t get_element_attr_rsp(bt_bdaddr_t* bd_addr, uint8_t num_attr,
1849 btrc_element_attr_val_t* p_attrs) {
1850 tAVRC_RESPONSE avrc_rsp;
1851 uint32_t i;
1852 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1853 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
1854
1855 BTIF_TRACE_DEBUG("%s", __func__);
1856 CHECK_RC_CONNECTED(p_dev);
1857
1858 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1859
1860 if (num_attr == 0) {
1861 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1862 } else {
1863 for (i = 0; i < num_attr; i++) {
1864 element_attrs[i].attr_id = p_attrs[i].attr_id;
1865 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1866 element_attrs[i].name.str_len = (uint16_t)strlen((char*)p_attrs[i].text);
1867 element_attrs[i].name.p_str = p_attrs[i].text;
1868 BTIF_TRACE_DEBUG(
1869 "%s: attr_id: 0x%x, charset_id: 0x%x, str_len: %d, str: %s", __func__,
1870 (unsigned int)element_attrs[i].attr_id,
1871 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1872 element_attrs[i].name.p_str);
1873 }
1874 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1875 }
1876 avrc_rsp.get_attrs.num_attrs = num_attr;
1877 avrc_rsp.get_attrs.p_attrs = element_attrs;
1878 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1879 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1880
1881 /* Send the response */
1882 send_metamsg_rsp(p_dev, IDX_GET_ELEMENT_ATTR_RSP,
1883 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].label,
1884 p_dev->rc_pdu_info[IDX_GET_ELEMENT_ATTR_RSP].ctype,
1885 &avrc_rsp);
1886
1887 return BT_STATUS_SUCCESS;
1888 }
1889
1890 /***************************************************************************
1891 *
1892 * Function reject_pending_notification
1893 *
1894 * Description Utility function to reject a pending notification. When
1895 * AddressedPlayer change is received, all pending
1896 * notifications should be completed.
1897 *
1898 * Returns void
1899 *
1900 **************************************************************************/
reject_pending_notification(btrc_event_id_t event_id,int idx)1901 static void reject_pending_notification(btrc_event_id_t event_id, int idx) {
1902 tAVRC_RESPONSE avrc_rsp;
1903 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1904
1905 avrc_rsp.reg_notif.event_id = event_id;
1906 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1907 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1908 avrc_rsp.reg_notif.status = AVRC_STS_ADDR_PLAYER_CHG;
1909 BTIF_TRACE_WARNING("%s: Handling event ID: 0x%x", __func__, event_id);
1910
1911 send_metamsg_rsp(&btif_rc_cb.rc_multi_cb[idx], -1,
1912 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label,
1913 AVRC_RSP_REJ, &avrc_rsp);
1914 }
1915
1916 /***************************************************************************
1917 *
1918 * Function register_notification_rsp
1919 *
1920 * Description Response to the register notification request.
1921 *
1922 * Returns bt_status_t
1923 *
1924 **************************************************************************/
register_notification_rsp(btrc_event_id_t event_id,btrc_notification_type_t type,btrc_register_notification_t * p_param)1925 static bt_status_t register_notification_rsp(
1926 btrc_event_id_t event_id, btrc_notification_type_t type,
1927 btrc_register_notification_t* p_param) {
1928 tAVRC_RESPONSE avrc_rsp;
1929 BTIF_TRACE_EVENT("%s: event_id: %s", __func__,
1930 dump_rc_notification_event_id(event_id));
1931 std::unique_lock<std::mutex> lock(btif_rc_cb.lock);
1932
1933 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1934
1935 avrc_rsp.reg_notif.event_id = event_id;
1936 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1937 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1938 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1939
1940 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
1941 memset(&(avrc_rsp.reg_notif.param), 0, sizeof(tAVRC_NOTIF_RSP_PARAM));
1942
1943 if (!(btif_rc_cb.rc_multi_cb[idx].rc_connected)) {
1944 BTIF_TRACE_ERROR("%s: Avrcp device is not connected, handle: 0x%x",
1945 __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1946 continue;
1947 }
1948
1949 if (btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].bNotify == false) {
1950 BTIF_TRACE_WARNING(
1951 "%s: Avrcp Event id is not registered: event_id: %x, handle: 0x%x",
1952 __func__, event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1953 continue;
1954 }
1955
1956 BTIF_TRACE_DEBUG(
1957 "%s: Avrcp Event id is registered: event_id: %x handle: 0x%x", __func__,
1958 event_id, btif_rc_cb.rc_multi_cb[idx].rc_handle);
1959
1960 switch (event_id) {
1961 case BTRC_EVT_PLAY_STATUS_CHANGED:
1962 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1963 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1964 btif_av_clear_remote_suspend_flag();
1965 break;
1966 case BTRC_EVT_TRACK_CHANGE:
1967 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track),
1968 sizeof(btrc_uid_t));
1969 break;
1970 case BTRC_EVT_PLAY_POS_CHANGED:
1971 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1972 break;
1973 case BTRC_EVT_AVAL_PLAYER_CHANGE:
1974 break;
1975 case BTRC_EVT_ADDR_PLAYER_CHANGE:
1976 avrc_rsp.reg_notif.param.addr_player.player_id =
1977 p_param->addr_player_changed.player_id;
1978 avrc_rsp.reg_notif.param.addr_player.uid_counter =
1979 p_param->addr_player_changed.uid_counter;
1980 break;
1981 case BTRC_EVT_UIDS_CHANGED:
1982 avrc_rsp.reg_notif.param.uid_counter =
1983 p_param->uids_changed.uid_counter;
1984 break;
1985 case BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED:
1986 break;
1987
1988 default:
1989 BTIF_TRACE_WARNING("%s: Unhandled event ID: 0x%x", __func__, event_id);
1990 return BT_STATUS_UNHANDLED;
1991 }
1992
1993 /* Send the response. */
1994 send_metamsg_rsp(
1995 &btif_rc_cb.rc_multi_cb[idx], -1,
1996 btif_rc_cb.rc_multi_cb[idx].rc_notif[event_id - 1].label,
1997 ((type == BTRC_NOTIFICATION_TYPE_INTERIM) ? AVRC_CMD_NOTIF
1998 : AVRC_RSP_CHANGED),
1999 &avrc_rsp);
2000
2001 /* if notification type is address player changed, then complete all player
2002 * specific
2003 * notifications with AV/C C-Type REJECTED with error code Addressed Player
2004 * Changed. */
2005 if (event_id == BTRC_EVT_ADDR_PLAYER_CHANGE &&
2006 type == BTRC_NOTIFICATION_TYPE_CHANGED) {
2007 /* array includes notifications to be completed on addressed player change
2008 */
2009 btrc_event_id_t evt_id[] = {
2010 BTRC_EVT_PLAY_STATUS_CHANGED, BTRC_EVT_TRACK_CHANGE,
2011 BTRC_EVT_PLAY_POS_CHANGED, BTRC_EVT_NOW_PLAYING_CONTENT_CHANGED};
2012 for (uint8_t id = 0; id < sizeof(evt_id) / sizeof((evt_id)[0]); id++) {
2013 reject_pending_notification(evt_id[id], idx);
2014 }
2015 }
2016 }
2017 return BT_STATUS_SUCCESS;
2018 }
2019
2020 /***************************************************************************
2021 *
2022 * Function get_folder_items_list_rsp
2023 *
2024 * Description Returns the list of media items in current folder along with
2025 * requested attributes. This is called in response to
2026 * GetFolderItems request.
2027 *
2028 * Returns bt_status_t
2029 * BT_STATUS_NOT_READY - when RC is not connected.
2030 * BT_STATUS_SUCCESS - always if RC is connected
2031 * BT_STATUS_UNHANDLED - when rsp is not pending for
2032 * get_folder_items_list PDU
2033 *
2034 **************************************************************************/
get_folder_items_list_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint16_t uid_counter,uint8_t num_items,btrc_folder_items_t * p_items)2035 static bt_status_t get_folder_items_list_rsp(bt_bdaddr_t* bd_addr,
2036 btrc_status_t rsp_status,
2037 uint16_t uid_counter,
2038 uint8_t num_items,
2039 btrc_folder_items_t* p_items) {
2040 tAVRC_RESPONSE avrc_rsp;
2041 tAVRC_ITEM item;
2042 tBTA_AV_CODE code = 0, ctype = 0;
2043 BT_HDR* p_msg = NULL;
2044 int item_cnt;
2045 tAVRC_STS status = AVRC_STS_NO_ERROR;
2046 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2047 btrc_folder_items_t* cur_item = NULL;
2048
2049 BTIF_TRACE_DEBUG("%s: uid_counter %d num_items %d", __func__, uid_counter,
2050 num_items);
2051 CHECK_RC_CONNECTED(p_dev);
2052
2053 /* check if rsp to previous cmd was completed */
2054 if (p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending == false) {
2055 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
2056 __func__);
2057 return BT_STATUS_UNHANDLED;
2058 }
2059
2060 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2061 memset(&item, 0, sizeof(tAVRC_ITEM));
2062
2063 avrc_rsp.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
2064 avrc_rsp.get_items.opcode = opcode_from_pdu(AVRC_PDU_GET_FOLDER_ITEMS);
2065 avrc_rsp.get_items.status = status_code_map[rsp_status];
2066
2067 if (avrc_rsp.get_items.status != AVRC_STS_NO_ERROR) {
2068 BTIF_TRACE_WARNING(
2069 "%s: Error in parsing the received getfolderitems cmd. status: 0x%02x",
2070 __func__, avrc_rsp.get_items.status);
2071 status = avrc_rsp.get_items.status;
2072 } else {
2073 avrc_rsp.get_items.uid_counter = uid_counter;
2074 avrc_rsp.get_items.item_count = 1;
2075
2076 /* create single item and build response iteratively for all num_items */
2077 for (item_cnt = 0; item_cnt < num_items; item_cnt++) {
2078 cur_item = &p_items[item_cnt];
2079 item.item_type = p_items->item_type;
2080 /* build respective item based on item_type. All items should be of same
2081 * type within
2082 * a response */
2083 switch (p_items->item_type) {
2084 case AVRC_ITEM_PLAYER: {
2085 item.u.player.name.charset_id = cur_item->player.charset_id;
2086 memcpy(&(item.u.player.features), &(cur_item->player.features),
2087 sizeof(cur_item->player.features));
2088 item.u.player.major_type = cur_item->player.major_type;
2089 item.u.player.sub_type = cur_item->player.sub_type;
2090 item.u.player.play_status = cur_item->player.play_status;
2091 item.u.player.player_id = cur_item->player.player_id;
2092 item.u.player.name.p_str = cur_item->player.name;
2093 item.u.player.name.str_len =
2094 (uint16_t)strlen((char*)(cur_item->player.name));
2095 } break;
2096
2097 case AVRC_ITEM_FOLDER: {
2098 memcpy(item.u.folder.uid, cur_item->folder.uid, sizeof(tAVRC_UID));
2099 item.u.folder.type = cur_item->folder.type;
2100 item.u.folder.playable = cur_item->folder.playable;
2101 item.u.folder.name.charset_id = AVRC_CHARSET_ID_UTF8;
2102 item.u.folder.name.str_len = strlen((char*)cur_item->folder.name);
2103 item.u.folder.name.p_str = cur_item->folder.name;
2104 } break;
2105
2106 case AVRC_ITEM_MEDIA: {
2107 tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE];
2108
2109 memcpy(item.u.media.uid, cur_item->media.uid, sizeof(tAVRC_UID));
2110 item.u.media.type = cur_item->media.type;
2111 item.u.media.name.charset_id = cur_item->media.charset_id;
2112 item.u.media.name.str_len = strlen((char*)cur_item->media.name);
2113 item.u.media.name.p_str = cur_item->media.name;
2114 item.u.media.attr_count = cur_item->media.num_attrs;
2115
2116 /* Handle attributes of given item */
2117 if (item.u.media.attr_count == 0) {
2118 item.u.media.p_attr_list = NULL;
2119 } else {
2120 memset(&attr_vals, 0,
2121 sizeof(tAVRC_ATTR_ENTRY) * BTRC_MAX_ELEM_ATTR_SIZE);
2122 fill_avrc_attr_entry(attr_vals, item.u.media.attr_count,
2123 cur_item->media.p_attrs);
2124 item.u.media.p_attr_list = attr_vals;
2125 }
2126 } break;
2127
2128 default: {
2129 BTIF_TRACE_ERROR("%s: Unknown item_type: %d. Internal Error",
2130 __func__, p_items->item_type);
2131 status = AVRC_STS_INTERNAL_ERR;
2132 } break;
2133 }
2134
2135 avrc_rsp.get_items.p_item_list = &item;
2136
2137 /* Add current item to buffer and build response if no error in item type
2138 */
2139 if (status != AVRC_STS_NO_ERROR) {
2140 /* Reject response due to error occured for unknown item_type, break the
2141 * loop */
2142 break;
2143 }
2144
2145 int len_before = p_msg ? p_msg->len : 0;
2146 BTIF_TRACE_DEBUG("%s: item_cnt: %d len: %d", __func__, item_cnt,
2147 len_before);
2148 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2149 BTIF_TRACE_DEBUG("%s: Build rsp status: %d len: %d", __func__, status,
2150 (p_msg ? p_msg->len : 0));
2151 int len_after = p_msg ? p_msg->len : 0;
2152 if (status != AVRC_STS_NO_ERROR || len_before == len_after) {
2153 /* Error occured in build response or we ran out of buffer so break the
2154 * loop */
2155 break;
2156 }
2157 }
2158
2159 /* setting the error status */
2160 avrc_rsp.get_items.status = status;
2161 }
2162
2163 /* if packet built successfully, send the built items to BTA layer */
2164 if (status == AVRC_STS_NO_ERROR) {
2165 code = p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype;
2166 ctype = get_rsp_type_code(avrc_rsp.get_items.status, code);
2167 BTA_AvMetaRsp(p_dev->rc_handle,
2168 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label, ctype,
2169 p_msg);
2170 } else /* Error occured, send reject response */
2171 {
2172 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__,
2173 avrc_rsp.rsp.status);
2174 send_reject_response(
2175 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label,
2176 avrc_rsp.pdu, avrc_rsp.get_items.status, avrc_rsp.get_items.opcode);
2177 }
2178
2179 /* Reset values for current pdu. */
2180 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].ctype = 0;
2181 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].label = 0;
2182 p_dev->rc_pdu_info[IDX_GET_FOLDER_ITEMS_RSP].is_rsp_pending = false;
2183
2184 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2185 }
2186
2187 /***************************************************************************
2188 *
2189 * Function set_addressed_player_rsp
2190 *
2191 * Description Response to set the addressed player for specified media
2192 * player based on id in the media player list.
2193 *
2194 * Returns bt_status_t
2195 * BT_STATUS_NOT_READY - when RC is not connected.
2196 * BT_STATUS_SUCCESS - always if RC is connected
2197 *
2198 **************************************************************************/
set_addressed_player_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status)2199 static bt_status_t set_addressed_player_rsp(bt_bdaddr_t* bd_addr,
2200 btrc_status_t rsp_status) {
2201 tAVRC_RESPONSE avrc_rsp;
2202 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2203
2204 BTIF_TRACE_DEBUG("%s", __func__);
2205 CHECK_RC_CONNECTED(p_dev);
2206
2207 avrc_rsp.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
2208 avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER);
2209 avrc_rsp.addr_player.status = status_code_map[rsp_status];
2210
2211 /* Send the response. */
2212 send_metamsg_rsp(p_dev, IDX_SET_ADDR_PLAYER_RSP,
2213 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].label,
2214 p_dev->rc_pdu_info[IDX_SET_ADDR_PLAYER_RSP].ctype,
2215 &avrc_rsp);
2216
2217 return BT_STATUS_SUCCESS;
2218 }
2219
2220 /***************************************************************************
2221 *
2222 * Function set_browsed_player_rsp
2223 *
2224 * Description Response to set the browsed player command which contains
2225 * current browsed path of the media player. By default,
2226 * current_path = root and folder_depth = 0 for
2227 * every set_browsed_player request.
2228 *
2229 * Returns bt_status_t
2230 * BT_STATUS_NOT_READY - when RC is not connected.
2231 * BT_STATUS_SUCCESS - if RC is connected and reponse
2232 * sent successfully
2233 * BT_STATUS_UNHANDLED - when rsp is not pending for
2234 * set_browsed_player PDU
2235 *
2236 **************************************************************************/
set_browsed_player_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint32_t num_items,uint16_t charset_id,uint8_t folder_depth,btrc_br_folder_name_t * p_folders)2237 static bt_status_t set_browsed_player_rsp(bt_bdaddr_t* bd_addr,
2238 btrc_status_t rsp_status,
2239 uint32_t num_items,
2240 uint16_t charset_id,
2241 uint8_t folder_depth,
2242 btrc_br_folder_name_t* p_folders) {
2243 tAVRC_RESPONSE avrc_rsp;
2244 tAVRC_NAME item;
2245 BT_HDR* p_msg = NULL;
2246 tBTA_AV_CODE code = 0;
2247 tBTA_AV_CODE ctype = 0;
2248 unsigned int item_cnt;
2249 tAVRC_STS status = AVRC_STS_NO_ERROR;
2250 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2251
2252 CHECK_RC_CONNECTED(p_dev);
2253
2254 memset(&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
2255 memset(&item, 0, sizeof(tAVRC_NAME));
2256
2257 avrc_rsp.br_player.status = status_code_map[rsp_status];
2258 avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
2259 avrc_rsp.br_player.opcode = opcode_from_pdu(AVRC_PDU_SET_BROWSED_PLAYER);
2260
2261 BTIF_TRACE_DEBUG("%s: rsp_status: 0x%02X avrc_rsp.br_player.status: 0x%02X",
2262 __func__, rsp_status, avrc_rsp.br_player.status);
2263
2264 /* check if rsp to previous cmd was completed */
2265 if (p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending == false) {
2266 BTIF_TRACE_WARNING("%s: Not sending response as no PDU was registered",
2267 __func__);
2268 return BT_STATUS_UNHANDLED;
2269 }
2270
2271 if (AVRC_STS_NO_ERROR == avrc_rsp.get_items.status) {
2272 avrc_rsp.br_player.num_items = num_items;
2273 avrc_rsp.br_player.charset_id = charset_id;
2274 avrc_rsp.br_player.folder_depth = folder_depth;
2275 avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_folders;
2276
2277 BTIF_TRACE_DEBUG("%s: folder_depth: 0x%02X num_items: %d", __func__,
2278 folder_depth, num_items);
2279
2280 if (folder_depth > 0) {
2281 /* Iteratively build response for all folders across folder depth upto
2282 * current path */
2283 avrc_rsp.br_player.folder_depth = 1;
2284 for (item_cnt = 0; item_cnt < folder_depth; item_cnt++) {
2285 BTIF_TRACE_DEBUG("%s: iteration: %d", __func__, item_cnt);
2286 item.str_len = p_folders[item_cnt].str_len;
2287 item.p_str = p_folders[item_cnt].p_str;
2288 avrc_rsp.br_player.p_folders = &item;
2289
2290 /* Add current item to buffer and build response */
2291 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2292 if (AVRC_STS_NO_ERROR != status) {
2293 BTIF_TRACE_WARNING("%s: Build rsp status: %d", __func__, status);
2294 /* if the build fails, it is likely that we ran out of buffer. so if
2295 * we have
2296 * some items to send, reset this error to no error for sending what we
2297 * have */
2298 if (item_cnt > 0) status = AVRC_STS_NO_ERROR;
2299
2300 /* Error occured in build response so break the loop */
2301 break;
2302 }
2303 }
2304 } else /* current path is root folder, no folders navigated yet */
2305 {
2306 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
2307 }
2308
2309 /* setting the error status */
2310 avrc_rsp.br_player.status = status;
2311 } else /* error received from above layer */
2312 {
2313 BTIF_TRACE_WARNING(
2314 "%s: Error in parsing the received setbrowsed command. status: 0x%02x",
2315 __func__, avrc_rsp.br_player.status);
2316 status = avrc_rsp.br_player.status;
2317 }
2318
2319 /* if packet built successfully, send the built items to BTA layer */
2320 if (status == AVRC_STS_NO_ERROR) {
2321 code = p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype;
2322 ctype = get_rsp_type_code(avrc_rsp.br_player.status, code);
2323 BTA_AvMetaRsp(p_dev->rc_handle,
2324 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label, ctype,
2325 p_msg);
2326 } else /* Error occured, send reject response */
2327 {
2328 BTIF_TRACE_ERROR("%s: Error status: 0x%02X. Sending reject rsp", __func__,
2329 avrc_rsp.br_player.status);
2330 send_reject_response(
2331 p_dev->rc_handle, p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label,
2332 avrc_rsp.pdu, avrc_rsp.br_player.status, avrc_rsp.get_items.opcode);
2333 }
2334
2335 /* Reset values for set_browsed_player pdu.*/
2336 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].ctype = 0;
2337 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].label = 0;
2338 p_dev->rc_pdu_info[IDX_SET_BROWSED_PLAYER_RSP].is_rsp_pending = false;
2339
2340 return status == AVRC_STS_NO_ERROR ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
2341 }
2342
2343 /*******************************************************************************
2344 *
2345 * Function change_path_rsp
2346 *
2347 * Description Response to the change path command which
2348 * contains number of items in the changed path.
2349 *
2350 * Returns bt_status_t
2351 * BT_STATUS_NOT_READY - when RC is not connected.
2352 * BT_STATUS_SUCCESS - always if RC is connected
2353 *
2354 **************************************************************************/
change_path_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint32_t num_items)2355 static bt_status_t change_path_rsp(bt_bdaddr_t* bd_addr,
2356 btrc_status_t rsp_status,
2357 uint32_t num_items) {
2358 tAVRC_RESPONSE avrc_rsp;
2359 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2360
2361 BTIF_TRACE_DEBUG("%s", __func__);
2362 CHECK_RC_CONNECTED(p_dev);
2363
2364 avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
2365 avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH);
2366 avrc_rsp.chg_path.num_items = num_items;
2367 avrc_rsp.chg_path.status = status_code_map[rsp_status];
2368
2369 /* Send the response. */
2370 send_metamsg_rsp(p_dev, IDX_CHG_PATH_RSP,
2371 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].label,
2372 p_dev->rc_pdu_info[IDX_CHG_PATH_RSP].ctype, &avrc_rsp);
2373
2374 return BT_STATUS_SUCCESS;
2375 }
2376
2377 /***************************************************************************
2378 *
2379 * Function search_rsp
2380 *
2381 * Description Response to search a string from media content command.
2382 *
2383 * Returns bt_status_t
2384 * BT_STATUS_NOT_READY - when RC is not connected.
2385 * BT_STATUS_SUCCESS - always if RC is connected
2386 *
2387 **************************************************************************/
search_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2388 static bt_status_t search_rsp(bt_bdaddr_t* bd_addr, btrc_status_t rsp_status,
2389 uint32_t uid_counter, uint32_t num_items) {
2390 tAVRC_RESPONSE avrc_rsp;
2391 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2392
2393 BTIF_TRACE_DEBUG("%s", __func__);
2394 CHECK_RC_CONNECTED(p_dev);
2395
2396 avrc_rsp.search.pdu = AVRC_PDU_SEARCH;
2397 avrc_rsp.search.opcode = opcode_from_pdu(AVRC_PDU_SEARCH);
2398 avrc_rsp.search.num_items = num_items;
2399 avrc_rsp.search.uid_counter = uid_counter;
2400 avrc_rsp.search.status = status_code_map[rsp_status];
2401
2402 /* Send the response. */
2403 send_metamsg_rsp(p_dev, IDX_SEARCH_RSP,
2404 p_dev->rc_pdu_info[IDX_SEARCH_RSP].label,
2405 p_dev->rc_pdu_info[IDX_SEARCH_RSP].ctype, &avrc_rsp);
2406
2407 return BT_STATUS_SUCCESS;
2408 }
2409 /***************************************************************************
2410 *
2411 * Function get_item_attr_rsp
2412 *
2413 * Description Response to the get item's attributes command which
2414 * contains number of attributes and values list in text.
2415 *
2416 * Returns bt_status_t
2417 * BT_STATUS_NOT_READY - when RC is not connected.
2418 * BT_STATUS_SUCCESS - always if RC is connected
2419 *
2420 **************************************************************************/
get_item_attr_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)2421 static bt_status_t get_item_attr_rsp(bt_bdaddr_t* bd_addr,
2422 btrc_status_t rsp_status, uint8_t num_attr,
2423 btrc_element_attr_val_t* p_attrs) {
2424 tAVRC_RESPONSE avrc_rsp;
2425 tAVRC_ATTR_ENTRY item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
2426 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2427
2428 BTIF_TRACE_DEBUG("%s", __func__);
2429 CHECK_RC_CONNECTED(p_dev);
2430
2431 memset(item_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
2432
2433 avrc_rsp.get_attrs.status = status_code_map[rsp_status];
2434 if (rsp_status == BTRC_STS_NO_ERROR) {
2435 fill_avrc_attr_entry(item_attrs, num_attr, p_attrs);
2436 }
2437
2438 avrc_rsp.get_attrs.num_attrs = num_attr;
2439 avrc_rsp.get_attrs.p_attrs = item_attrs;
2440 avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
2441 avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);
2442
2443 /* Send the response. */
2444 send_metamsg_rsp(p_dev, IDX_GET_ITEM_ATTR_RSP,
2445 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].label,
2446 p_dev->rc_pdu_info[IDX_GET_ITEM_ATTR_RSP].ctype, &avrc_rsp);
2447
2448 return BT_STATUS_SUCCESS;
2449 }
2450
2451 /***************************************************************************
2452 *
2453 * Function add_to_now_playing_rsp
2454 *
2455 * Description Response to command for adding speciafied media item
2456 * to Now Playing queue.
2457 *
2458 * Returns bt_status_t
2459 * BT_STATUS_NOT_READY - when RC is not connected.
2460 * BT_STATUS_SUCCESS - always if RC is connected
2461 *
2462 **************************************************************************/
add_to_now_playing_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status)2463 static bt_status_t add_to_now_playing_rsp(bt_bdaddr_t* bd_addr,
2464 btrc_status_t rsp_status) {
2465 tAVRC_RESPONSE avrc_rsp;
2466 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2467
2468 BTIF_TRACE_DEBUG("%s", __func__);
2469 CHECK_RC_CONNECTED(p_dev);
2470
2471 avrc_rsp.add_to_play.pdu = AVRC_PDU_ADD_TO_NOW_PLAYING;
2472 avrc_rsp.add_to_play.opcode = opcode_from_pdu(AVRC_PDU_ADD_TO_NOW_PLAYING);
2473 avrc_rsp.add_to_play.status = status_code_map[rsp_status];
2474
2475 /* Send the response. */
2476 send_metamsg_rsp(p_dev, IDX_ADD_TO_NOW_PLAYING_RSP,
2477 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].label,
2478 p_dev->rc_pdu_info[IDX_ADD_TO_NOW_PLAYING_RSP].ctype,
2479 &avrc_rsp);
2480
2481 return BT_STATUS_SUCCESS;
2482 }
2483
2484 /***************************************************************************
2485 *
2486 * Function play_item_rsp
2487 *
2488 * Description Response to command for playing the specified media item.
2489 *
2490 * Returns bt_status_t
2491 * BT_STATUS_NOT_READY - when RC is not connected.
2492 * BT_STATUS_SUCCESS - always if RC is connected
2493 *
2494 **************************************************************************/
play_item_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status)2495 static bt_status_t play_item_rsp(bt_bdaddr_t* bd_addr,
2496 btrc_status_t rsp_status) {
2497 tAVRC_RESPONSE avrc_rsp;
2498 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2499
2500 BTIF_TRACE_DEBUG("%s", __func__);
2501 CHECK_RC_CONNECTED(p_dev);
2502
2503 avrc_rsp.play_item.pdu = AVRC_PDU_PLAY_ITEM;
2504 avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM);
2505 avrc_rsp.play_item.status = status_code_map[rsp_status];
2506
2507 /* Send the response. */
2508 send_metamsg_rsp(p_dev, IDX_PLAY_ITEM_RSP,
2509 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].label,
2510 p_dev->rc_pdu_info[IDX_PLAY_ITEM_RSP].ctype, &avrc_rsp);
2511
2512 return BT_STATUS_SUCCESS;
2513 }
2514
2515 /***************************************************************************
2516 *
2517 * Function get_total_num_of_items_rsp
2518 *
2519 * Description response to command to get the Number of Items
2520 * in the selected folder at the selected scope
2521 *
2522 * Returns bt_status_t
2523 * BT_STATUS_NOT_READY - when RC is not connected.
2524 * BT_STATUS_SUCCESS - always if RC is connected
2525 *
2526 **************************************************************************/
get_total_num_of_items_rsp(bt_bdaddr_t * bd_addr,btrc_status_t rsp_status,uint32_t uid_counter,uint32_t num_items)2527 static bt_status_t get_total_num_of_items_rsp(bt_bdaddr_t* bd_addr,
2528 btrc_status_t rsp_status,
2529 uint32_t uid_counter,
2530 uint32_t num_items) {
2531 tAVRC_RESPONSE avrc_rsp;
2532 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
2533
2534 BTIF_TRACE_DEBUG("%s", __func__);
2535 CHECK_RC_CONNECTED(p_dev);
2536
2537 avrc_rsp.get_num_of_items.pdu = AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS;
2538 avrc_rsp.get_num_of_items.opcode =
2539 opcode_from_pdu(AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS);
2540 avrc_rsp.get_num_of_items.num_items = num_items;
2541 avrc_rsp.get_num_of_items.uid_counter = uid_counter;
2542 avrc_rsp.get_num_of_items.status = status_code_map[rsp_status];
2543
2544 /* Send the response. */
2545 send_metamsg_rsp(p_dev, IDX_GET_TOTAL_NUM_OF_ITEMS_RSP,
2546 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].label,
2547 p_dev->rc_pdu_info[IDX_GET_TOTAL_NUM_OF_ITEMS_RSP].ctype,
2548 &avrc_rsp);
2549
2550 return BT_STATUS_SUCCESS;
2551 }
2552
2553 /***************************************************************************
2554 *
2555 * Function set_volume
2556 *
2557 * Description Send current volume setting to remote side.
2558 * Support limited to SetAbsoluteVolume
2559 * This can be enhanced to support Relative Volume (AVRCP 1.0).
2560 * With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
2561 * as opposed to absolute volume level
2562 * volume: Should be in the range 0-127. bit7 is reseved and cannot be set
2563 *
2564 * Returns bt_status_t
2565 *
2566 **************************************************************************/
set_volume(uint8_t volume)2567 static bt_status_t set_volume(uint8_t volume) {
2568 BTIF_TRACE_DEBUG("%s: volume: %d", __func__, volume);
2569 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2570 rc_transaction_t* p_transaction = NULL;
2571
2572 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
2573 if (!btif_rc_cb.rc_multi_cb[idx].rc_connected) {
2574 status = BT_STATUS_NOT_READY;
2575 BTIF_TRACE_ERROR("%s: RC is not connected for device: 0x%x", __func__,
2576 btif_rc_cb.rc_multi_cb[idx].rc_addr);
2577 continue;
2578 }
2579
2580 if (btif_rc_cb.rc_multi_cb[idx].rc_volume == volume) {
2581 status = BT_STATUS_DONE;
2582 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x", __func__,
2583 volume);
2584 continue;
2585 }
2586
2587 if ((btif_rc_cb.rc_multi_cb[idx].rc_volume != volume) &&
2588 btif_rc_cb.rc_multi_cb[idx].rc_state ==
2589 BTRC_CONNECTION_STATE_CONNECTED) {
2590 if ((btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_RCTG) == 0) {
2591 status = BT_STATUS_NOT_READY;
2592 continue;
2593 } else {
2594 tAVRC_COMMAND avrc_cmd = {0};
2595 BT_HDR* p_msg = NULL;
2596
2597 if (btif_rc_cb.rc_multi_cb[idx].rc_features & BTA_AV_FEAT_ADV_CTRL) {
2598 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume: %d",
2599 __func__, volume);
2600 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
2601 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
2602 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
2603 avrc_cmd.volume.volume = volume;
2604
2605 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR) {
2606 bt_status_t tran_status = get_transaction(&p_transaction);
2607
2608 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) {
2609 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d",
2610 __func__, p_transaction->lbl);
2611 BTA_AvMetaCmd(btif_rc_cb.rc_multi_cb[idx].rc_handle,
2612 p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
2613 status = BT_STATUS_SUCCESS;
2614 } else {
2615 osi_free_and_reset((void**)&p_msg);
2616 BTIF_TRACE_ERROR(
2617 "%s: failed to obtain transaction details. status: 0x%02x",
2618 __func__, tran_status);
2619 status = BT_STATUS_FAIL;
2620 }
2621 } else {
2622 BTIF_TRACE_ERROR(
2623 "%s: failed to build absolute volume command. status: 0x%02x",
2624 __func__, status);
2625 status = BT_STATUS_FAIL;
2626 }
2627 }
2628 }
2629 }
2630 }
2631 return (bt_status_t)status;
2632 }
2633
2634 /***************************************************************************
2635 *
2636 * Function register_volumechange
2637 *
2638 * Description Register for volume change notification from remote side.
2639 *
2640 * Returns void
2641 *
2642 **************************************************************************/
2643
register_volumechange(uint8_t lbl,btif_rc_device_cb_t * p_dev)2644 static void register_volumechange(uint8_t lbl, btif_rc_device_cb_t* p_dev) {
2645 tAVRC_COMMAND avrc_cmd = {0};
2646 BT_HDR* p_msg = NULL;
2647 tAVRC_STS BldResp = AVRC_STS_BAD_CMD;
2648 rc_transaction_t* p_transaction = NULL;
2649
2650 BTIF_TRACE_DEBUG("%s: label: %d", __func__, lbl);
2651
2652 avrc_cmd.cmd.opcode = 0x00;
2653 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
2654 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
2655 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
2656 avrc_cmd.reg_notif.param = 0;
2657
2658 BldResp = AVRC_BldCommand(&avrc_cmd, &p_msg);
2659 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
2660 p_transaction = get_transaction_by_lbl(lbl);
2661 if (p_transaction != NULL) {
2662 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_NOTIF,
2663 p_msg);
2664 BTIF_TRACE_DEBUG("%s: BTA_AvMetaCmd called", __func__);
2665 } else {
2666 osi_free(p_msg);
2667 BTIF_TRACE_ERROR("%s: transaction not obtained with label: %d", __func__,
2668 lbl);
2669 }
2670 } else {
2671 BTIF_TRACE_ERROR("%s: failed to build command: %d", __func__, BldResp);
2672 }
2673 }
2674
2675 /***************************************************************************
2676 *
2677 * Function handle_rc_metamsg_rsp
2678 *
2679 * Description Handle RC metamessage response
2680 *
2681 * Returns void
2682 *
2683 **************************************************************************/
handle_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg,btif_rc_device_cb_t * p_dev)2684 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg,
2685 btif_rc_device_cb_t* p_dev) {
2686 tAVRC_RESPONSE avrc_response = {0};
2687 uint8_t scratch_buf[512] = {0};
2688 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
2689
2690 BTIF_TRACE_DEBUG("%s: ", __func__);
2691
2692 if (AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode &&
2693 (AVRC_RSP_CHANGED == pmeta_msg->code ||
2694 AVRC_RSP_INTERIM == pmeta_msg->code ||
2695 AVRC_RSP_ACCEPT == pmeta_msg->code || AVRC_RSP_REJ == pmeta_msg->code ||
2696 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2697 status = AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf,
2698 sizeof(scratch_buf));
2699 BTIF_TRACE_DEBUG(
2700 "%s: code:%d, event ID: %d, PDU: %x, parsing status: %d, label: %d",
2701 __func__, pmeta_msg->code, avrc_response.reg_notif.event_id,
2702 avrc_response.reg_notif.pdu, status, pmeta_msg->label);
2703
2704 if (status != AVRC_STS_NO_ERROR) {
2705 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2706 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2707 p_dev->rc_vol_label == pmeta_msg->label) {
2708 p_dev->rc_vol_label = MAX_LABEL;
2709 release_transaction(p_dev->rc_vol_label);
2710 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2711 release_transaction(pmeta_msg->label);
2712 }
2713 return;
2714 }
2715
2716 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2717 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2718 p_dev->rc_vol_label != pmeta_msg->label) {
2719 // Just discard the message, if the device sends back with an incorrect
2720 // label
2721 BTIF_TRACE_DEBUG(
2722 "%s: Discarding register notification in rsp.code: %d and label: %d",
2723 __func__, pmeta_msg->code, pmeta_msg->label);
2724 return;
2725 }
2726
2727 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2728 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2729 (AVRC_RSP_REJ == pmeta_msg->code ||
2730 AVRC_RSP_NOT_IMPL == pmeta_msg->code)) {
2731 BTIF_TRACE_DEBUG("%s remove AbsoluteVolume feature flag.", __func__);
2732 p_dev->rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
2733 handle_rc_features(p_dev);
2734 return;
2735 }
2736 } else {
2737 BTIF_TRACE_DEBUG(
2738 "%s: Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not "
2739 "processing it.",
2740 __func__, pmeta_msg->code, pmeta_msg->len);
2741 return;
2742 }
2743
2744 if (AVRC_PDU_REGISTER_NOTIFICATION == avrc_response.rsp.pdu &&
2745 AVRC_EVT_VOLUME_CHANGE == avrc_response.reg_notif.event_id &&
2746 AVRC_RSP_CHANGED == pmeta_msg->code) {
2747 /* re-register for volume change notification */
2748 // Do not re-register for rejected case, as it might get into endless loop
2749 register_volumechange(p_dev->rc_vol_label, p_dev);
2750 } else if (AVRC_PDU_SET_ABSOLUTE_VOLUME == avrc_response.rsp.pdu) {
2751 /* free up the label here */
2752 release_transaction(pmeta_msg->label);
2753 }
2754
2755 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
2756 __func__, dump_rc_pdu(avrc_response.pdu));
2757 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response,
2758 pmeta_msg->code, pmeta_msg->label, p_dev);
2759 }
2760
2761 /***************************************************************************
2762 *
2763 * Function iterate_supported_event_list_for_interim_rsp
2764 *
2765 * Description iterator callback function to match the event and handle
2766 * timer cleanup
2767 * Returns true to continue iterating, false to stop
2768 *
2769 **************************************************************************/
iterate_supported_event_list_for_interim_rsp(void * data,void * cb_data)2770 bool iterate_supported_event_list_for_interim_rsp(void* data, void* cb_data) {
2771 uint8_t* p_event_id;
2772 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
2773
2774 p_event_id = (uint8_t*)cb_data;
2775
2776 if (p_event->event_id == *p_event_id) {
2777 p_event->status = eINTERIM;
2778 return false;
2779 }
2780 return true;
2781 }
2782
2783 /***************************************************************************
2784 *
2785 * Function iterate_supported_event_list_for_timeout
2786 *
2787 * Description Iterator callback function for timeout handling.
2788 * As part of the failure handling, it releases the
2789 * transaction label and removes the event from list,
2790 * this event will not be requested again during
2791 * the lifetime of the connection.
2792 * Returns false to stop iterating, true to continue
2793 *
2794 **************************************************************************/
iterate_supported_event_list_for_timeout(void * data,void * cb_data)2795 bool iterate_supported_event_list_for_timeout(void* data, void* cb_data) {
2796 bt_bdaddr_t bd_addr;
2797 rc_context_t* cntxt = (rc_context_t*)cb_data;
2798 uint8_t label = cntxt->label & 0xFF;
2799 bdcpy(bd_addr.address, cntxt->rc_addr);
2800 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&bd_addr);
2801 btif_rc_supported_event_t* p_event = (btif_rc_supported_event_t*)data;
2802
2803 if (p_event->label == label) {
2804 list_remove(p_dev->rc_supported_event_list, p_event);
2805 return false;
2806 }
2807 return true;
2808 }
2809
2810 /***************************************************************************
2811 *
2812 * Function rc_notification_interim_timout
2813 *
2814 * Description Interim response timeout handler.
2815 * Runs the iterator to check and clear the timed out event.
2816 * Proceeds to register for the unregistered events.
2817 * Returns None
2818 *
2819 **************************************************************************/
rc_notification_interim_timout(uint8_t label,btif_rc_device_cb_t * p_dev)2820 static void rc_notification_interim_timout(uint8_t label,
2821 btif_rc_device_cb_t* p_dev) {
2822 list_node_t* node;
2823 rc_context_t cntxt;
2824 memset(&cntxt, 0, sizeof(rc_context_t));
2825 cntxt.label = label;
2826 bdcpy(cntxt.rc_addr, p_dev->rc_addr);
2827
2828 list_foreach(p_dev->rc_supported_event_list,
2829 iterate_supported_event_list_for_timeout, &cntxt);
2830 /* Timeout happened for interim response for the registered event,
2831 * check if there are any pending for registration
2832 */
2833 node = list_begin(p_dev->rc_supported_event_list);
2834 while (node != NULL) {
2835 btif_rc_supported_event_t* p_event;
2836
2837 p_event = (btif_rc_supported_event_t*)list_node(node);
2838 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
2839 register_for_event_notification(p_event, p_dev);
2840 break;
2841 }
2842 node = list_next(node);
2843 }
2844 /* Todo. Need to initiate application settings query if this
2845 * is the last event registration.
2846 */
2847 }
2848
2849 /***************************************************************************
2850 *
2851 * Function btif_rc_status_cmd_timeout_handler
2852 *
2853 * Description RC status command timeout handler (Runs in BTIF context).
2854 * Returns None
2855 *
2856 **************************************************************************/
btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2857 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2858 char* data) {
2859 btif_rc_timer_context_t* p_context;
2860 tAVRC_RESPONSE avrc_response = {0};
2861 tBTA_AV_META_MSG meta_msg;
2862 btif_rc_device_cb_t* p_dev = NULL;
2863 bt_bdaddr_t bd_addr;
2864
2865 p_context = (btif_rc_timer_context_t*)data;
2866 bdcpy(bd_addr.address, p_context->rc_addr);
2867 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2868 p_dev = btif_rc_get_device_by_bda(&bd_addr);
2869 if (p_dev == NULL) {
2870 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
2871 return;
2872 }
2873 meta_msg.rc_handle = p_dev->rc_handle;
2874
2875 switch (p_context->rc_status_cmd.pdu_id) {
2876 case AVRC_PDU_REGISTER_NOTIFICATION:
2877 rc_notification_interim_timout(p_context->rc_status_cmd.label, p_dev);
2878 break;
2879
2880 case AVRC_PDU_GET_CAPABILITIES:
2881 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2882 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2883 break;
2884
2885 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2886 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2887 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2888 break;
2889
2890 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2891 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2892 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2893 break;
2894
2895 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2896 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2897 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2898 break;
2899
2900 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2901 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2902 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2903 break;
2904
2905 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2906 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2907 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2908 break;
2909
2910 case AVRC_PDU_GET_ELEMENT_ATTR:
2911 avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT;
2912 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_attrs);
2913 break;
2914
2915 case AVRC_PDU_GET_PLAY_STATUS:
2916 avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT;
2917 handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status);
2918 break;
2919 }
2920 release_transaction(p_context->rc_status_cmd.label);
2921 }
2922
2923 /***************************************************************************
2924 *
2925 * Function btif_rc_status_cmd_timer_timeout
2926 *
2927 * Description RC status command timeout callback.
2928 * This is called from BTU context and switches to BTIF
2929 * context to handle the timeout events
2930 * Returns None
2931 *
2932 **************************************************************************/
btif_rc_status_cmd_timer_timeout(void * data)2933 static void btif_rc_status_cmd_timer_timeout(void* data) {
2934 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data;
2935
2936 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0, (char*)p_data,
2937 sizeof(btif_rc_timer_context_t), NULL);
2938 }
2939
2940 /***************************************************************************
2941 *
2942 * Function btif_rc_control_cmd_timeout_handler
2943 *
2944 * Description RC control command timeout handler (Runs in BTIF context).
2945 * Returns None
2946 *
2947 **************************************************************************/
btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2948 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2949 char* data) {
2950 btif_rc_timer_context_t* p_context = (btif_rc_timer_context_t*)data;
2951 tAVRC_RESPONSE avrc_response = {0};
2952 tBTA_AV_META_MSG meta_msg;
2953 bt_bdaddr_t bd_addr;
2954 bdcpy(bd_addr.address, p_context->rc_addr);
2955 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(&bd_addr);
2956 if (p_dev == NULL) {
2957 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
2958 return;
2959 }
2960
2961 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2962 meta_msg.rc_handle = p_dev->rc_handle;
2963
2964 switch (p_context->rc_control_cmd.pdu_id) {
2965 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2966 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2967 handle_set_app_attr_val_response(&meta_msg, &avrc_response.set_app_val);
2968 break;
2969 }
2970 release_transaction(p_context->rc_control_cmd.label);
2971 }
2972
2973 /***************************************************************************
2974 *
2975 * Function btif_rc_control_cmd_timer_timeout
2976 *
2977 * Description RC control command timeout callback.
2978 * This is called from BTU context and switches to BTIF
2979 * context to handle the timeout events
2980 * Returns None
2981 *
2982 **************************************************************************/
btif_rc_control_cmd_timer_timeout(void * data)2983 static void btif_rc_control_cmd_timer_timeout(void* data) {
2984 btif_rc_timer_context_t* p_data = (btif_rc_timer_context_t*)data;
2985
2986 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0, (char*)p_data,
2987 sizeof(btif_rc_timer_context_t), NULL);
2988 }
2989
2990 /***************************************************************************
2991 *
2992 * Function btif_rc_play_status_timeout_handler
2993 *
2994 * Description RC play status timeout handler (Runs in BTIF context).
2995 * Returns None
2996 *
2997 **************************************************************************/
btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,char * p_data)2998 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2999 char* p_data) {
3000 btif_rc_handle_t* rc_handle = (btif_rc_handle_t*)p_data;
3001 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(rc_handle->handle);
3002 if (p_dev == NULL) {
3003 BTIF_TRACE_ERROR("%s timeout handler but no device found for handle %d",
3004 __func__, rc_handle->handle);
3005 return;
3006 }
3007 get_play_status_cmd(p_dev);
3008 rc_start_play_status_timer(p_dev);
3009 }
3010
3011 /***************************************************************************
3012 *
3013 * Function btif_rc_play_status_timer_timeout
3014 *
3015 * Description RC play status timeout callback.
3016 * This is called from BTU context and switches to BTIF
3017 * context to handle the timeout events
3018 * Returns None
3019 *
3020 **************************************************************************/
btif_rc_play_status_timer_timeout(void * data)3021 static void btif_rc_play_status_timer_timeout(void* data) {
3022 btif_rc_handle_t rc_handle;
3023 rc_handle.handle = PTR_TO_UINT(data);
3024 BTIF_TRACE_DEBUG("%s called with handle: %d", __func__, rc_handle);
3025 btif_transfer_context(btif_rc_play_status_timeout_handler, 0,
3026 (char*)(&rc_handle), sizeof(btif_rc_handle_t), NULL);
3027 }
3028
3029 /***************************************************************************
3030 *
3031 * Function rc_start_play_status_timer
3032 *
3033 * Description Helper function to start the timer to fetch play status.
3034 * Returns None
3035 *
3036 **************************************************************************/
rc_start_play_status_timer(btif_rc_device_cb_t * p_dev)3037 static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev) {
3038 /* Start the Play status timer only if it is not started */
3039 if (!alarm_is_scheduled(p_dev->rc_play_status_timer)) {
3040 if (p_dev->rc_play_status_timer == NULL) {
3041 p_dev->rc_play_status_timer = alarm_new("p_dev->rc_play_status_timer");
3042 }
3043 alarm_set_on_queue(p_dev->rc_play_status_timer,
3044 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
3045 btif_rc_play_status_timer_timeout,
3046 UINT_TO_PTR(p_dev->rc_handle), btu_general_alarm_queue);
3047 }
3048 }
3049
3050 /***************************************************************************
3051 *
3052 * Function rc_stop_play_status_timer
3053 *
3054 * Description Helper function to stop the play status timer.
3055 * Returns None
3056 *
3057 **************************************************************************/
rc_stop_play_status_timer(btif_rc_device_cb_t * p_dev)3058 void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev) {
3059 alarm_cancel(p_dev->rc_play_status_timer);
3060 }
3061
3062 /***************************************************************************
3063 *
3064 * Function register_for_event_notification
3065 *
3066 * Description Helper function registering notification events
3067 * sets an interim response timeout to handle if the remote
3068 * does not respond.
3069 * Returns None
3070 *
3071 **************************************************************************/
register_for_event_notification(btif_rc_supported_event_t * p_event,btif_rc_device_cb_t * p_dev)3072 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
3073 btif_rc_device_cb_t* p_dev) {
3074 rc_transaction_t* p_transaction = NULL;
3075 bt_status_t status = get_transaction(&p_transaction);
3076 if (status != BT_STATUS_SUCCESS) {
3077 BTIF_TRACE_ERROR("%s: no more transaction labels: %d", __func__, status);
3078 return;
3079 }
3080
3081 status = register_notification_cmd(p_transaction->lbl, p_event->event_id, 0,
3082 p_dev);
3083 if (status != BT_STATUS_SUCCESS) {
3084 BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__,
3085 status);
3086 release_transaction(p_transaction->lbl);
3087 return;
3088 }
3089
3090 btif_rc_timer_context_t* p_context = &p_transaction->txn_timer_context;
3091 p_event->label = p_transaction->lbl;
3092 p_event->status = eREGISTERED;
3093 p_context->rc_status_cmd.label = p_transaction->lbl;
3094 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
3095 bdcpy(p_context->rc_addr, p_dev->rc_addr);
3096
3097 alarm_free(p_transaction->txn_timer);
3098 p_transaction->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
3099 alarm_set_on_queue(p_transaction->txn_timer, BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
3100 btif_rc_status_cmd_timer_timeout, p_context,
3101 btu_general_alarm_queue);
3102 }
3103
start_status_command_timer(uint8_t pdu_id,rc_transaction_t * p_txn,btif_rc_device_cb_t * p_dev)3104 static void start_status_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn,
3105 btif_rc_device_cb_t* p_dev) {
3106 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context;
3107 p_context->rc_status_cmd.label = p_txn->lbl;
3108 p_context->rc_status_cmd.pdu_id = pdu_id;
3109 bdcpy(p_context->rc_addr, p_dev->rc_addr);
3110
3111 alarm_free(p_txn->txn_timer);
3112 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
3113 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
3114 btif_rc_status_cmd_timer_timeout, p_context,
3115 btu_general_alarm_queue);
3116 }
3117
start_control_command_timer(uint8_t pdu_id,rc_transaction_t * p_txn,btif_rc_device_cb_t * p_dev)3118 static void start_control_command_timer(uint8_t pdu_id, rc_transaction_t* p_txn,
3119 btif_rc_device_cb_t* p_dev) {
3120 btif_rc_timer_context_t* p_context = &p_txn->txn_timer_context;
3121 p_context->rc_control_cmd.label = p_txn->lbl;
3122 p_context->rc_control_cmd.pdu_id = pdu_id;
3123 bdcpy(p_context->rc_addr, p_dev->rc_addr);
3124
3125 alarm_free(p_txn->txn_timer);
3126 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
3127 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
3128 btif_rc_control_cmd_timer_timeout, p_context,
3129 btu_general_alarm_queue);
3130 }
3131
build_and_send_vendor_cmd(tAVRC_COMMAND * avrc_cmd,tBTA_AV_CODE cmd_code,btif_rc_device_cb_t * p_dev)3132 bt_status_t build_and_send_vendor_cmd(tAVRC_COMMAND* avrc_cmd,
3133 tBTA_AV_CODE cmd_code,
3134 btif_rc_device_cb_t* p_dev) {
3135 rc_transaction_t* p_transaction = NULL;
3136 bt_status_t tran_status = get_transaction(&p_transaction);
3137 if (BT_STATUS_SUCCESS != tran_status) return BT_STATUS_FAIL;
3138
3139 BT_HDR* p_msg = NULL;
3140 tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
3141 if (status == AVRC_STS_NO_ERROR && p_msg != NULL) {
3142 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
3143 BTIF_TRACE_DEBUG("%s: %s msgreq being sent out with label: %d", __func__,
3144 dump_rc_pdu(avrc_cmd->pdu), p_transaction->lbl);
3145 BTA_AvVendorCmd(p_dev->rc_handle, p_transaction->lbl, cmd_code, data_start,
3146 p_msg->len);
3147 status = BT_STATUS_SUCCESS;
3148 if (cmd_code == AVRC_CMD_STATUS) {
3149 start_status_command_timer(avrc_cmd->pdu, p_transaction, p_dev);
3150 } else if (cmd_code == AVRC_CMD_CTRL) {
3151 start_control_command_timer(avrc_cmd->pdu, p_transaction, p_dev);
3152 }
3153 } else {
3154 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
3155 status);
3156 }
3157 osi_free(p_msg);
3158 return (bt_status_t)status;
3159 }
3160
3161 /***************************************************************************
3162 *
3163 * Function handle_get_capability_response
3164 *
3165 * Description Handles the get_cap_response to populate company id info
3166 * and query the supported events.
3167 * Initiates Notification registration for events supported
3168 * Returns None
3169 *
3170 **************************************************************************/
handle_get_capability_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CAPS_RSP * p_rsp)3171 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg,
3172 tAVRC_GET_CAPS_RSP* p_rsp) {
3173 int xx = 0;
3174 btif_rc_device_cb_t* p_dev =
3175 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3176
3177 /* Todo: Do we need to retry on command timeout */
3178 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3179 BTIF_TRACE_ERROR("%s: Error capability response: 0x%02X", __func__,
3180 p_rsp->status);
3181 return;
3182 }
3183
3184 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
3185 btif_rc_supported_event_t* p_event;
3186
3187 /* Todo: Check if list can be active when we hit here */
3188 p_dev->rc_supported_event_list = list_new(osi_free);
3189 for (xx = 0; xx < p_rsp->count; xx++) {
3190 /* Skip registering for Play position change notification */
3191 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) ||
3192 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) ||
3193 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) ||
3194 (p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE)) {
3195 p_event = (btif_rc_supported_event_t*)osi_malloc(
3196 sizeof(btif_rc_supported_event_t));
3197 p_event->event_id = p_rsp->param.event_id[xx];
3198 p_event->status = eNOT_REGISTERED;
3199 list_append(p_dev->rc_supported_event_list, p_event);
3200 }
3201 }
3202 p_event =
3203 (btif_rc_supported_event_t*)list_front(p_dev->rc_supported_event_list);
3204 if (p_event != NULL) {
3205 register_for_event_notification(p_event, p_dev);
3206 }
3207 } else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) {
3208 getcapabilities_cmd(AVRC_CAP_EVENTS_SUPPORTED, p_dev);
3209 BTIF_TRACE_EVENT("%s: AVRC_CAP_COMPANY_ID: ", __func__);
3210 for (xx = 0; xx < p_rsp->count; xx++) {
3211 BTIF_TRACE_EVENT("%s: company_id: %d", __func__,
3212 p_rsp->param.company_id[xx]);
3213 }
3214 }
3215 }
3216
rc_is_track_id_valid(tAVRC_UID uid)3217 bool rc_is_track_id_valid(tAVRC_UID uid) {
3218 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3219
3220 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0) {
3221 return false;
3222 } else {
3223 return true;
3224 }
3225 }
3226
3227 /***************************************************************************
3228 *
3229 * Function handle_notification_response
3230 *
3231 * Description Main handler for notification responses to registered events
3232 * 1. Register for unregistered event(in interim response path)
3233 * 2. After registering for all supported events, start
3234 * retrieving application settings and values
3235 * 3. Reregister for events on getting changed response
3236 * 4. Run play status timer for getting position when the
3237 * status changes to playing
3238 * 5. Get the Media details when the track change happens
3239 * or track change interim response is received with
3240 * valid track id
3241 * 6. HAL callback for play status change and application
3242 * setting change
3243 * Returns None
3244 *
3245 **************************************************************************/
handle_notification_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_REG_NOTIF_RSP * p_rsp)3246 static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
3247 tAVRC_REG_NOTIF_RSP* p_rsp) {
3248 bt_bdaddr_t rc_addr;
3249 btif_rc_device_cb_t* p_dev =
3250 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3251 uint32_t attr_list[] = {
3252 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST,
3253 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3254 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE,
3255 AVRC_MEDIA_ATTR_ID_PLAYING_TIME};
3256
3257 if (p_dev == NULL) {
3258 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3259 return;
3260 }
3261
3262 bdcpy(rc_addr.address, p_dev->rc_addr);
3263
3264 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
3265 btif_rc_supported_event_t* p_event;
3266 list_node_t* node;
3267
3268 BTIF_TRACE_DEBUG("%s: Interim response: 0x%2X ", __func__, p_rsp->event_id);
3269 switch (p_rsp->event_id) {
3270 case AVRC_EVT_PLAY_STATUS_CHANGE:
3271 /* Start timer to get play status periodically
3272 * if the play state is playing.
3273 */
3274 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) {
3275 rc_start_play_status_timer(p_dev);
3276 }
3277 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr,
3278 (btrc_play_status_t)p_rsp->param.play_status);
3279 break;
3280
3281 case AVRC_EVT_TRACK_CHANGE:
3282 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3283 break;
3284 } else {
3285 uint8_t* p_data = p_rsp->param.track;
3286 /* Update the UID for current track
3287 * Attributes will be fetched after the AVRCP procedure
3288 */
3289 BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
3290 }
3291 break;
3292
3293 case AVRC_EVT_APP_SETTING_CHANGE:
3294 break;
3295
3296 case AVRC_EVT_NOW_PLAYING_CHANGE:
3297 break;
3298
3299 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3300 break;
3301
3302 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3303 break;
3304
3305 case AVRC_EVT_UIDS_CHANGE:
3306 break;
3307
3308 case AVRC_EVT_TRACK_REACHED_END:
3309 case AVRC_EVT_TRACK_REACHED_START:
3310 case AVRC_EVT_PLAY_POS_CHANGED:
3311 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3312 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3313 default:
3314 BTIF_TRACE_ERROR("%s: Unhandled interim response: 0x%2X", __func__,
3315 p_rsp->event_id);
3316 return;
3317 }
3318
3319 list_foreach(p_dev->rc_supported_event_list,
3320 iterate_supported_event_list_for_interim_rsp,
3321 &p_rsp->event_id);
3322
3323 node = list_begin(p_dev->rc_supported_event_list);
3324
3325 while (node != NULL) {
3326 p_event = (btif_rc_supported_event_t*)list_node(node);
3327 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED)) {
3328 register_for_event_notification(p_event, p_dev);
3329 break;
3330 }
3331 node = list_next(node);
3332 p_event = NULL;
3333 }
3334 /* Registered for all events, we can request application settings */
3335 if (p_event == NULL && p_dev->rc_app_settings.query_started == false) {
3336 /* we need to do this only if remote TG supports
3337 * player application settings
3338 */
3339 p_dev->rc_app_settings.query_started = true;
3340 if (p_dev->rc_features & BTA_AV_FEAT_APP_SETTING) {
3341 list_player_app_setting_attrib_cmd(p_dev);
3342 } else {
3343 BTIF_TRACE_DEBUG("%s: App setting not supported, complete procedure",
3344 __func__);
3345 rc_ctrl_procedure_complete(p_dev);
3346 }
3347 }
3348 } else if (pmeta_msg->code == AVRC_RSP_CHANGED) {
3349 btif_rc_supported_event_t* p_event;
3350 list_node_t* node;
3351
3352 BTIF_TRACE_DEBUG("%s: Notification completed: 0x%2X ", __func__,
3353 p_rsp->event_id);
3354
3355 node = list_begin(p_dev->rc_supported_event_list);
3356
3357 while (node != NULL) {
3358 p_event = (btif_rc_supported_event_t*)list_node(node);
3359 if (p_event != NULL && p_event->event_id == p_rsp->event_id) {
3360 p_event->status = eNOT_REGISTERED;
3361 register_for_event_notification(p_event, p_dev);
3362 break;
3363 }
3364 node = list_next(node);
3365 }
3366
3367 switch (p_rsp->event_id) {
3368 case AVRC_EVT_PLAY_STATUS_CHANGE:
3369 /* Start timer to get play status periodically
3370 * if the play state is playing.
3371 */
3372 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) {
3373 rc_start_play_status_timer(p_dev);
3374 } else {
3375 rc_stop_play_status_timer(p_dev);
3376 }
3377 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb, &rc_addr,
3378 (btrc_play_status_t)p_rsp->param.play_status);
3379
3380 break;
3381
3382 case AVRC_EVT_TRACK_CHANGE:
3383 if (rc_is_track_id_valid(p_rsp->param.track) != true) {
3384 break;
3385 }
3386 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev);
3387 break;
3388
3389 case AVRC_EVT_APP_SETTING_CHANGE: {
3390 btrc_player_settings_t app_settings;
3391 uint16_t xx;
3392
3393 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
3394 for (xx = 0; xx < app_settings.num_attr; xx++) {
3395 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
3396 app_settings.attr_values[xx] =
3397 p_rsp->param.player_setting.attr_value[xx];
3398 }
3399 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
3400 &rc_addr, &app_settings);
3401 } break;
3402
3403 case AVRC_EVT_NOW_PLAYING_CHANGE:
3404 break;
3405
3406 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
3407 break;
3408
3409 case AVRC_EVT_ADDR_PLAYER_CHANGE:
3410 break;
3411
3412 case AVRC_EVT_UIDS_CHANGE:
3413 break;
3414
3415 case AVRC_EVT_TRACK_REACHED_END:
3416 case AVRC_EVT_TRACK_REACHED_START:
3417 case AVRC_EVT_PLAY_POS_CHANGED:
3418 case AVRC_EVT_BATTERY_STATUS_CHANGE:
3419 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
3420 default:
3421 BTIF_TRACE_ERROR("%s: Unhandled completion response: 0x%2X", __func__,
3422 p_rsp->event_id);
3423 return;
3424 }
3425 }
3426 }
3427
3428 /***************************************************************************
3429 *
3430 * Function handle_app_attr_response
3431 *
3432 * Description handles the the application attributes response and
3433 * initiates procedure to fetch the attribute values
3434 * Returns None
3435 *
3436 **************************************************************************/
handle_app_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_ATTR_RSP * p_rsp)3437 static void handle_app_attr_response(tBTA_AV_META_MSG* pmeta_msg,
3438 tAVRC_LIST_APP_ATTR_RSP* p_rsp) {
3439 uint8_t xx;
3440 btif_rc_device_cb_t* p_dev =
3441 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3442
3443 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3444 BTIF_TRACE_ERROR("%s: Error getting Player application settings: 0x%2X",
3445 __func__, p_rsp->status);
3446 rc_ctrl_procedure_complete(p_dev);
3447 return;
3448 }
3449
3450 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3451 uint8_t st_index;
3452
3453 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT) {
3454 st_index = p_dev->rc_app_settings.num_ext_attrs;
3455 p_dev->rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
3456 p_dev->rc_app_settings.num_ext_attrs++;
3457 } else {
3458 st_index = p_dev->rc_app_settings.num_attrs;
3459 p_dev->rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
3460 p_dev->rc_app_settings.num_attrs++;
3461 }
3462 }
3463 p_dev->rc_app_settings.attr_index = 0;
3464 p_dev->rc_app_settings.ext_attr_index = 0;
3465 p_dev->rc_app_settings.ext_val_index = 0;
3466 if (p_rsp->num_attr) {
3467 list_player_app_setting_value_cmd(p_dev->rc_app_settings.attrs[0].attr_id,
3468 p_dev);
3469 } else {
3470 BTIF_TRACE_ERROR("%s: No Player application settings found", __func__);
3471 }
3472 }
3473
3474 /***************************************************************************
3475 *
3476 * Function handle_app_val_response
3477 *
3478 * Description handles the the attributes value response and if extended
3479 * menu is available, it initiates query for the attribute
3480 * text. If not, it initiates procedure to get the current
3481 * attribute values and calls the HAL callback for provding
3482 * application settings information.
3483 * Returns None
3484 *
3485 **************************************************************************/
handle_app_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_VALUES_RSP * p_rsp)3486 static void handle_app_val_response(tBTA_AV_META_MSG* pmeta_msg,
3487 tAVRC_LIST_APP_VALUES_RSP* p_rsp) {
3488 uint8_t xx, attr_index;
3489 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3490 btif_rc_player_app_settings_t* p_app_settings;
3491 bt_bdaddr_t rc_addr;
3492 btif_rc_device_cb_t* p_dev =
3493 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3494
3495 /* Todo: Do we need to retry on command timeout */
3496 if (p_dev == NULL || p_rsp->status != AVRC_STS_NO_ERROR) {
3497 BTIF_TRACE_ERROR("%s: Error fetching attribute values: 0x%02X", __func__,
3498 p_rsp->status);
3499 return;
3500 }
3501
3502 p_app_settings = &p_dev->rc_app_settings;
3503 bdcpy(rc_addr.address, p_dev->rc_addr);
3504
3505 if (p_app_settings->attr_index < p_app_settings->num_attrs) {
3506 attr_index = p_app_settings->attr_index;
3507 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
3508 for (xx = 0; xx < p_rsp->num_val; xx++) {
3509 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
3510 }
3511 attr_index++;
3512 p_app_settings->attr_index++;
3513 if (attr_index < p_app_settings->num_attrs) {
3514 list_player_app_setting_value_cmd(
3515 p_app_settings->attrs[p_app_settings->attr_index].attr_id, p_dev);
3516 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3517 attr_index = 0;
3518 p_app_settings->ext_attr_index = 0;
3519 list_player_app_setting_value_cmd(
3520 p_app_settings->ext_attrs[attr_index].attr_id, p_dev);
3521 } else {
3522 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3523 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3524 }
3525 get_player_app_setting_cmd(p_app_settings->num_attrs, attrs, p_dev);
3526 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
3527 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
3528 }
3529 } else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs) {
3530 attr_index = p_app_settings->ext_attr_index;
3531 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
3532 for (xx = 0; xx < p_rsp->num_val; xx++) {
3533 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val =
3534 p_rsp->vals[xx];
3535 }
3536 attr_index++;
3537 p_app_settings->ext_attr_index++;
3538 if (attr_index < p_app_settings->num_ext_attrs) {
3539 list_player_app_setting_value_cmd(
3540 p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id,
3541 p_dev);
3542 } else {
3543 uint8_t attr[AVRC_MAX_APP_ATTR_SIZE];
3544
3545 for (uint8_t xx = 0; xx < p_app_settings->num_ext_attrs; xx++) {
3546 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
3547 }
3548 get_player_app_setting_attr_text_cmd(attr, p_app_settings->num_ext_attrs,
3549 p_dev);
3550 }
3551 }
3552 }
3553
3554 /***************************************************************************
3555 *
3556 * Function handle_app_cur_val_response
3557 *
3558 * Description handles the the get attributes value response.
3559 *
3560 * Returns None
3561 *
3562 **************************************************************************/
handle_app_cur_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp)3563 static void handle_app_cur_val_response(tBTA_AV_META_MSG* pmeta_msg,
3564 tAVRC_GET_CUR_APP_VALUE_RSP* p_rsp) {
3565 btrc_player_settings_t app_settings;
3566 bt_bdaddr_t rc_addr;
3567 uint16_t xx;
3568 btif_rc_device_cb_t* p_dev = NULL;
3569
3570 /* Todo: Do we need to retry on command timeout */
3571 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3572 BTIF_TRACE_ERROR("%s: Error fetching current settings: 0x%02X", __func__,
3573 p_rsp->status);
3574 return;
3575 }
3576 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3577 if (p_dev == NULL) {
3578 BTIF_TRACE_ERROR("%s: Error in getting Device Address", __func__);
3579 osi_free_and_reset((void**)&p_rsp->p_vals);
3580 return;
3581 }
3582
3583 bdcpy(rc_addr.address, p_dev->rc_addr);
3584
3585 app_settings.num_attr = p_rsp->num_val;
3586 for (xx = 0; xx < app_settings.num_attr; xx++) {
3587 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
3588 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
3589 }
3590
3591 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb, &rc_addr,
3592 &app_settings);
3593 /* Application settings are fetched only once for initial values
3594 * initiate anything that follows after RC procedure.
3595 * Defer it if browsing is supported till players query
3596 */
3597 rc_ctrl_procedure_complete(p_dev);
3598 osi_free_and_reset((void**)&p_rsp->p_vals);
3599 }
3600
3601 /***************************************************************************
3602 *
3603 * Function handle_app_attr_txt_response
3604 *
3605 * Description handles the the get attributes text response, if fails
3606 * calls HAL callback with just normal settings and initiates
3607 * query for current settings else initiates query for value
3608 * text
3609 * Returns None
3610 *
3611 **************************************************************************/
handle_app_attr_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3612 static void handle_app_attr_txt_response(tBTA_AV_META_MSG* pmeta_msg,
3613 tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3614 uint8_t xx;
3615 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3616 btif_rc_player_app_settings_t* p_app_settings;
3617 bt_bdaddr_t rc_addr;
3618 btif_rc_device_cb_t* p_dev =
3619 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3620
3621 if (p_dev == NULL) {
3622 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3623 return;
3624 }
3625
3626 bdcpy(rc_addr.address, p_dev->rc_addr);
3627 p_app_settings = &p_dev->rc_app_settings;
3628
3629 /* Todo: Do we need to retry on command timeout */
3630 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3631 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3632
3633 BTIF_TRACE_ERROR("%s: Error fetching attribute text: 0x%02X", __func__,
3634 p_rsp->status);
3635 /* Not able to fetch Text for extended Menu, skip the process
3636 * and cleanup used memory. Proceed to get the current settings
3637 * for standard attributes.
3638 */
3639 p_app_settings->num_ext_attrs = 0;
3640 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3641 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3642 }
3643 p_app_settings->ext_attr_index = 0;
3644
3645 if (p_dev) {
3646 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3647 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3648 }
3649
3650 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
3651 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
3652 get_player_app_setting_cmd(xx, attrs, p_dev);
3653 }
3654 return;
3655 }
3656
3657 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3658 uint8_t x;
3659 for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
3660 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id) {
3661 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3662 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
3663 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
3664 break;
3665 }
3666 }
3667 }
3668
3669 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++) {
3670 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
3671 }
3672 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3673 }
3674
3675 /***************************************************************************
3676 *
3677 * Function handle_app_attr_val_txt_response
3678 *
3679 * Description handles the the get attributes value text response, if fails
3680 * calls HAL callback with just normal settings and initiates
3681 * query for current settings
3682 * Returns None
3683 *
3684 **************************************************************************/
handle_app_attr_val_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)3685 static void handle_app_attr_val_txt_response(
3686 tBTA_AV_META_MSG* pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP* p_rsp) {
3687 uint8_t xx, attr_index;
3688 uint8_t vals[AVRC_MAX_APP_ATTR_SIZE];
3689 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3690 btif_rc_player_app_settings_t* p_app_settings;
3691 bt_bdaddr_t rc_addr;
3692 btif_rc_device_cb_t* p_dev =
3693 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3694
3695 if (p_dev == NULL) {
3696 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3697 return;
3698 }
3699
3700 bdcpy(rc_addr.address, p_dev->rc_addr);
3701 p_app_settings = &p_dev->rc_app_settings;
3702
3703 /* Todo: Do we need to retry on command timeout */
3704 if (p_rsp->status != AVRC_STS_NO_ERROR) {
3705 uint8_t attrs[AVRC_MAX_APP_ATTR_SIZE];
3706
3707 BTIF_TRACE_ERROR("%s: Error fetching attribute value text: 0x%02X",
3708 __func__, p_rsp->status);
3709
3710 /* Not able to fetch Text for extended Menu, skip the process
3711 * and cleanup used memory. Proceed to get the current settings
3712 * for standard attributes.
3713 */
3714 p_app_settings->num_ext_attrs = 0;
3715 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3716 int x;
3717 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3718
3719 for (x = 0; x < p_ext_attr->num_val; x++)
3720 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3721 p_ext_attr->num_val = 0;
3722 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3723 }
3724 p_app_settings->ext_attr_index = 0;
3725
3726 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3727 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3728 }
3729 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
3730 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
3731
3732 get_player_app_setting_cmd(xx, attrs, p_dev);
3733 return;
3734 }
3735
3736 for (xx = 0; xx < p_rsp->num_attr; xx++) {
3737 uint8_t x;
3738 btrc_player_app_ext_attr_t* p_ext_attr;
3739 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
3740 for (x = 0; x < p_rsp->num_attr; x++) {
3741 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id) {
3742 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
3743 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
3744 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
3745 break;
3746 }
3747 }
3748 }
3749 p_app_settings->ext_val_index++;
3750
3751 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs) {
3752 attr_index = p_app_settings->ext_val_index;
3753 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++) {
3754 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
3755 }
3756 get_player_app_setting_value_text_cmd(vals, xx, p_dev);
3757 } else {
3758 uint8_t x;
3759
3760 for (xx = 0; xx < p_app_settings->num_attrs; xx++) {
3761 attrs[xx] = p_app_settings->attrs[xx].attr_id;
3762 }
3763 for (x = 0; x < p_app_settings->num_ext_attrs; x++) {
3764 attrs[xx + x] = p_app_settings->ext_attrs[x].attr_id;
3765 }
3766 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
3767 p_app_settings->num_attrs, p_app_settings->attrs,
3768 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
3769 get_player_app_setting_cmd(xx + x, attrs, p_dev);
3770
3771 /* Free the application settings information after sending to
3772 * application.
3773 */
3774 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++) {
3775 int x;
3776 btrc_player_app_ext_attr_t* p_ext_attr = &p_app_settings->ext_attrs[xx];
3777
3778 for (x = 0; x < p_ext_attr->num_val; x++)
3779 osi_free_and_reset((void**)&p_ext_attr->ext_attr_val[x].p_str);
3780 p_ext_attr->num_val = 0;
3781 osi_free_and_reset((void**)&p_app_settings->ext_attrs[xx].p_str);
3782 }
3783 p_app_settings->num_attrs = 0;
3784 }
3785 }
3786
3787 /***************************************************************************
3788 *
3789 * Function handle_set_app_attr_val_response
3790 *
3791 * Description handles the the set attributes value response, if fails
3792 * calls HAL callback to indicate the failure
3793 * Returns None
3794 *
3795 **************************************************************************/
handle_set_app_attr_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)3796 static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
3797 tAVRC_RSP* p_rsp) {
3798 uint8_t accepted = 0;
3799 bt_bdaddr_t rc_addr;
3800 btif_rc_device_cb_t* p_dev =
3801 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3802
3803 if (p_dev == NULL) {
3804 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3805 return;
3806 }
3807
3808 bdcpy(rc_addr.address, p_dev->rc_addr);
3809
3810 /* For timeout pmeta_msg will be NULL, else we need to
3811 * check if this is accepted by TG
3812 */
3813 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT)) {
3814 accepted = 1;
3815 }
3816 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr,
3817 accepted);
3818 }
3819
3820 /***************************************************************************
3821 *
3822 * Function handle_get_elem_attr_response
3823 *
3824 * Description handles the the element attributes response, calls
3825 * HAL callback to update track change information.
3826 * Returns None
3827 *
3828 **************************************************************************/
handle_get_elem_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ATTRS_RSP * p_rsp)3829 static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
3830 tAVRC_GET_ATTRS_RSP* p_rsp) {
3831 btif_rc_device_cb_t* p_dev =
3832 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3833
3834 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3835 bt_bdaddr_t rc_addr;
3836 size_t buf_size = p_rsp->num_attrs * sizeof(btrc_element_attr_val_t);
3837 btrc_element_attr_val_t* p_attr =
3838 (btrc_element_attr_val_t*)osi_calloc(buf_size);
3839
3840 if (p_dev == NULL) {
3841 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3842 return;
3843 }
3844
3845 bdcpy(rc_addr.address, p_dev->rc_addr);
3846
3847 for (int i = 0; i < p_rsp->num_attrs; i++) {
3848 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3849 /* Todo. Legth limit check to include null */
3850 if (p_rsp->p_attrs[i].name.str_len && p_rsp->p_attrs[i].name.p_str) {
3851 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3852 p_rsp->p_attrs[i].name.str_len);
3853 osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str);
3854 }
3855 }
3856 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb, &rc_addr,
3857 p_rsp->num_attrs, p_attr);
3858 osi_free(p_attr);
3859 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3860 /* Retry for timeout case, this covers error handling
3861 * for continuation failure also.
3862 */
3863 uint32_t attr_list[] = {
3864 AVRC_MEDIA_ATTR_ID_TITLE, AVRC_MEDIA_ATTR_ID_ARTIST,
3865 AVRC_MEDIA_ATTR_ID_ALBUM, AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3866 AVRC_MEDIA_ATTR_ID_NUM_TRACKS, AVRC_MEDIA_ATTR_ID_GENRE,
3867 AVRC_MEDIA_ATTR_ID_PLAYING_TIME};
3868 get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list, p_dev);
3869 } else {
3870 BTIF_TRACE_ERROR("%s: Error in get element attr procedure: %d", __func__,
3871 p_rsp->status);
3872 }
3873 }
3874
3875 /***************************************************************************
3876 *
3877 * Function handle_get_playstatus_response
3878 *
3879 * Description handles the the play status response, calls
3880 * HAL callback to update play position.
3881 * Returns None
3882 *
3883 **************************************************************************/
handle_get_playstatus_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_PLAY_STATUS_RSP * p_rsp)3884 static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
3885 tAVRC_GET_PLAY_STATUS_RSP* p_rsp) {
3886 bt_bdaddr_t rc_addr;
3887
3888 btif_rc_device_cb_t* p_dev =
3889 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3890
3891 if (p_dev == NULL) {
3892 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3893 return;
3894 }
3895
3896 bdcpy(rc_addr.address, p_dev->rc_addr);
3897
3898 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3899 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb, &rc_addr,
3900 p_rsp->song_len, p_rsp->song_pos);
3901 } else {
3902 BTIF_TRACE_ERROR("%s: Error in get play status procedure: %d", __func__,
3903 p_rsp->status);
3904 }
3905 }
3906
3907 /***************************************************************************
3908 *
3909 * Function handle_set_addressed_player_response
3910 *
3911 * Description handles the the set addressed player response, calls
3912 * HAL callback
3913 * Returns None
3914 *
3915 **************************************************************************/
handle_set_addressed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)3916 static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg,
3917 tAVRC_RSP* p_rsp) {
3918 bt_bdaddr_t rc_addr;
3919
3920 btif_rc_device_cb_t* p_dev =
3921 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3922
3923 if (p_dev == NULL) {
3924 BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
3925 return;
3926 }
3927
3928 bdcpy(rc_addr.address, p_dev->rc_addr);
3929
3930 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3931 HAL_CBACK(bt_rc_ctrl_callbacks, set_addressed_player_cb, &rc_addr,
3932 p_rsp->status);
3933 } else {
3934 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d", __func__,
3935 p_rsp->status);
3936 }
3937 }
3938
3939 /***************************************************************************
3940 *
3941 * Function handle_get_folder_items_response
3942 *
3943 * Description handles the the get folder items response, calls
3944 * HAL callback to send the folder items.
3945 * Returns None
3946 *
3947 **************************************************************************/
handle_get_folder_items_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ITEMS_RSP * p_rsp)3948 static void handle_get_folder_items_response(tBTA_AV_META_MSG* pmeta_msg,
3949 tAVRC_GET_ITEMS_RSP* p_rsp) {
3950 btif_rc_device_cb_t* p_dev =
3951 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
3952 bt_bdaddr_t rc_addr;
3953 bdcpy(rc_addr.address, p_dev->rc_addr);
3954
3955 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3956 /* Convert the internal folder listing into a response that can
3957 * be passed onto JNI via HAL_CBACK
3958 */
3959 uint8_t item_count = p_rsp->item_count;
3960 btrc_folder_items_t* btrc_items = (btrc_folder_items_t*)osi_malloc(
3961 sizeof(btrc_folder_items_t) * item_count);
3962 for (uint8_t i = 0; i < item_count; i++) {
3963 const tAVRC_ITEM* avrc_item = &(p_rsp->p_item_list[i]);
3964 btrc_folder_items_t* btrc_item = &(btrc_items[i]);
3965 BTIF_TRACE_DEBUG("%s folder item type %d", __func__,
3966 avrc_item->item_type);
3967 switch (avrc_item->item_type) {
3968 case AVRC_ITEM_MEDIA:
3969 BTIF_TRACE_DEBUG("%s setting type to %d", __func__, BTRC_ITEM_MEDIA);
3970 get_folder_item_type_media(avrc_item, btrc_item);
3971 break;
3972
3973 case AVRC_ITEM_FOLDER:
3974 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_FOLDER", __func__);
3975 get_folder_item_type_folder(avrc_item, btrc_item);
3976 break;
3977
3978 case AVRC_ITEM_PLAYER:
3979 BTIF_TRACE_DEBUG("%s setting type to BTRC_ITEM_PLAYER", __func__);
3980 get_folder_item_type_player(avrc_item, btrc_item);
3981 break;
3982
3983 default:
3984 BTIF_TRACE_ERROR("%s cannot understand folder item type %d", __func__,
3985 avrc_item->item_type);
3986 }
3987 }
3988
3989 HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr,
3990 BTRC_STS_NO_ERROR,
3991 /* We want to make the ownership explicit in native */
3992 (const btrc_folder_items_t*)btrc_items, item_count);
3993 BTIF_TRACE_DEBUG("%s HAL CBACK get_folder_items_cb finished", __func__);
3994
3995 /* Release the memory block for items since we OWN the object */
3996 osi_free(btrc_items);
3997 } else {
3998 BTIF_TRACE_ERROR("%s: Error %d", __func__, p_rsp->status);
3999 HAL_CBACK(bt_rc_ctrl_callbacks, get_folder_items_cb, &rc_addr,
4000 (btrc_status_t)p_rsp->status, NULL, 0);
4001 }
4002 }
4003
4004 /***************************************************************************
4005 *
4006 * Function get_folder_item_type_media
4007 *
4008 * Description Converts the AVRC representation of a folder item with
4009 * TYPE media to BTIF representation.
4010 * Returns None
4011 *
4012 **************************************************************************/
get_folder_item_type_media(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4013 void get_folder_item_type_media(const tAVRC_ITEM* avrc_item,
4014 btrc_folder_items_t* btrc_item) {
4015 btrc_item->item_type = BTRC_ITEM_MEDIA;
4016 const tAVRC_ITEM_MEDIA* avrc_item_media = &(avrc_item->u.media);
4017 btrc_item_media_t* btrc_item_media = &(btrc_item->media);
4018 /* UID */
4019 memset(btrc_item_media->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
4020 memcpy(btrc_item_media->uid, avrc_item_media->uid,
4021 sizeof(uint8_t) * BTRC_UID_SIZE);
4022
4023 /* Audio/Video type */
4024 switch (avrc_item_media->type) {
4025 case AVRC_MEDIA_TYPE_AUDIO:
4026 btrc_item_media->type = BTRC_MEDIA_TYPE_AUDIO;
4027 break;
4028 case AVRC_MEDIA_TYPE_VIDEO:
4029 btrc_item_media->type = BTRC_MEDIA_TYPE_VIDEO;
4030 break;
4031 }
4032
4033 /* Charset ID */
4034 btrc_item_media->charset_id = avrc_item_media->name.charset_id;
4035
4036 /* Copy the name */
4037 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN,
4038 avrc_item_media->name.str_len);
4039 memset(btrc_item_media->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4040 memcpy(btrc_item_media->name, avrc_item_media->name.p_str,
4041 sizeof(uint8_t) * (avrc_item_media->name.str_len));
4042
4043 /* Copy the parameters */
4044 btrc_item_media->num_attrs = avrc_item_media->attr_count;
4045 btrc_item_media->p_attrs = (btrc_element_attr_val_t*)osi_malloc(
4046 btrc_item_media->num_attrs * sizeof(btrc_element_attr_val_t));
4047
4048 /* Extract each attribute */
4049 for (int i = 0; i < avrc_item_media->attr_count; i++) {
4050 btrc_element_attr_val_t* btrc_attr_pair = &(btrc_item_media->p_attrs[i]);
4051 tAVRC_ATTR_ENTRY* avrc_attr_pair = &(avrc_item_media->p_attr_list[i]);
4052
4053 BTIF_TRACE_DEBUG("%s media attr id 0x%x", __func__,
4054 avrc_attr_pair->attr_id);
4055
4056 switch (avrc_attr_pair->attr_id) {
4057 case AVRC_MEDIA_ATTR_ID_TITLE:
4058 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TITLE;
4059 break;
4060 case AVRC_MEDIA_ATTR_ID_ARTIST:
4061 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ARTIST;
4062 break;
4063 case AVRC_MEDIA_ATTR_ID_ALBUM:
4064 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_ALBUM;
4065 break;
4066 case AVRC_MEDIA_ATTR_ID_TRACK_NUM:
4067 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_TRACK_NUM;
4068 break;
4069 case AVRC_MEDIA_ATTR_ID_NUM_TRACKS:
4070 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_NUM_TRACKS;
4071 break;
4072 case AVRC_MEDIA_ATTR_ID_GENRE:
4073 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_GENRE;
4074 break;
4075 case AVRC_MEDIA_ATTR_ID_PLAYING_TIME:
4076 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_PLAYING_TIME;
4077 break;
4078 default:
4079 BTIF_TRACE_ERROR("%s invalid media attr id: 0x%x", __func__,
4080 avrc_attr_pair->attr_id);
4081 btrc_attr_pair->attr_id = BTRC_MEDIA_ATTR_ID_INVALID;
4082 }
4083
4084 memset(btrc_attr_pair->text, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4085 memcpy(btrc_attr_pair->text, avrc_attr_pair->name.p_str,
4086 avrc_attr_pair->name.str_len);
4087 }
4088 }
4089
4090 /***************************************************************************
4091 *
4092 * Function get_folder_item_type_folder
4093 *
4094 * Description Converts the AVRC representation of a folder item with
4095 * TYPE folder to BTIF representation.
4096 * Returns None
4097 *
4098 **************************************************************************/
get_folder_item_type_folder(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4099 void get_folder_item_type_folder(const tAVRC_ITEM* avrc_item,
4100 btrc_folder_items_t* btrc_item) {
4101 btrc_item->item_type = BTRC_ITEM_FOLDER;
4102 const tAVRC_ITEM_FOLDER* avrc_item_folder = &(avrc_item->u.folder);
4103 btrc_item_folder_t* btrc_item_folder = &(btrc_item->folder);
4104 /* Copy the UID */
4105 memset(btrc_item_folder->uid, 0, BTRC_UID_SIZE * sizeof(uint8_t));
4106 memcpy(btrc_item_folder->uid, avrc_item_folder->uid,
4107 sizeof(uint8_t) * BTRC_UID_SIZE);
4108
4109 /* Copy the type */
4110 switch (avrc_item_folder->type) {
4111 case AVRC_FOLDER_TYPE_MIXED:
4112 btrc_item_folder->type = BTRC_FOLDER_TYPE_MIXED;
4113 break;
4114 case AVRC_FOLDER_TYPE_TITLES:
4115 btrc_item_folder->type = BTRC_FOLDER_TYPE_TITLES;
4116 break;
4117 case AVRC_FOLDER_TYPE_ALNUMS:
4118 btrc_item_folder->type = BTRC_FOLDER_TYPE_ALBUMS;
4119 break;
4120 case AVRC_FOLDER_TYPE_ARTISTS:
4121 btrc_item_folder->type = BTRC_FOLDER_TYPE_ARTISTS;
4122 break;
4123 case AVRC_FOLDER_TYPE_GENRES:
4124 btrc_item_folder->type = BTRC_FOLDER_TYPE_GENRES;
4125 break;
4126 case AVRC_FOLDER_TYPE_PLAYLISTS:
4127 btrc_item_folder->type = BTRC_FOLDER_TYPE_PLAYLISTS;
4128 break;
4129 case AVRC_FOLDER_TYPE_YEARS:
4130 btrc_item_folder->type = BTRC_FOLDER_TYPE_YEARS;
4131 break;
4132 }
4133
4134 /* Copy if playable */
4135 btrc_item_folder->playable = avrc_item_folder->playable;
4136
4137 /* Copy name */
4138 BTIF_TRACE_DEBUG("%s max len %d str len %d", __func__, BTRC_MAX_ATTR_STR_LEN,
4139 avrc_item_folder->name.str_len);
4140 memset(btrc_item_folder->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4141 memcpy(btrc_item_folder->name, avrc_item_folder->name.p_str,
4142 avrc_item_folder->name.str_len * sizeof(uint8_t));
4143
4144 /* Copy charset */
4145 btrc_item_folder->charset_id = avrc_item_folder->name.charset_id;
4146 }
4147
4148 /***************************************************************************
4149 *
4150 * Function get_folder_item_type_player
4151 *
4152 * Description Converts the AVRC representation of a folder item with
4153 * TYPE player to BTIF representation.
4154 * Returns None
4155 *
4156 **************************************************************************/
get_folder_item_type_player(const tAVRC_ITEM * avrc_item,btrc_folder_items_t * btrc_item)4157 void get_folder_item_type_player(const tAVRC_ITEM* avrc_item,
4158 btrc_folder_items_t* btrc_item) {
4159 btrc_item->item_type = BTRC_ITEM_PLAYER;
4160 const tAVRC_ITEM_PLAYER* avrc_item_player = &(avrc_item->u.player);
4161 btrc_item_player_t* btrc_item_player = &(btrc_item->player);
4162 /* Player ID */
4163 btrc_item_player->player_id = avrc_item_player->player_id;
4164 /* Major type */
4165 btrc_item_player->major_type = avrc_item_player->major_type;
4166 /* Sub type */
4167 btrc_item_player->sub_type = avrc_item_player->sub_type;
4168 /* Features */
4169 memcpy(btrc_item_player->features, avrc_item_player->features,
4170 BTRC_FEATURE_BIT_MASK_SIZE);
4171
4172 memset(btrc_item_player->name, 0, BTRC_MAX_ATTR_STR_LEN * sizeof(uint8_t));
4173 memcpy(btrc_item_player->name, avrc_item_player->name.p_str,
4174 avrc_item_player->name.str_len);
4175 }
4176
4177 /***************************************************************************
4178 *
4179 * Function handle_change_path_response
4180 *
4181 * Description handles the the change path response, calls
4182 * HAL callback to send the updated folder
4183 * Returns None
4184 *
4185 **************************************************************************/
handle_change_path_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_CHG_PATH_RSP * p_rsp)4186 static void handle_change_path_response(tBTA_AV_META_MSG* pmeta_msg,
4187 tAVRC_CHG_PATH_RSP* p_rsp) {
4188 btif_rc_device_cb_t* p_dev =
4189 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4190 bt_bdaddr_t rc_addr;
4191 bdcpy(rc_addr.address, p_dev->rc_addr);
4192
4193 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4194 HAL_CBACK(bt_rc_ctrl_callbacks, change_folder_path_cb, &rc_addr,
4195 p_rsp->num_items);
4196 } else {
4197 BTIF_TRACE_ERROR("%s error in handle_change_path_response %d", __func__,
4198 p_rsp->status);
4199 }
4200 }
4201
4202 /***************************************************************************
4203 *
4204 * Function handle_set_browsed_player_response
4205 *
4206 * Description handles the the change path response, calls
4207 * HAL callback to send the updated folder
4208 * Returns None
4209 *
4210 **************************************************************************/
handle_set_browsed_player_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_SET_BR_PLAYER_RSP * p_rsp)4211 static void handle_set_browsed_player_response(tBTA_AV_META_MSG* pmeta_msg,
4212 tAVRC_SET_BR_PLAYER_RSP* p_rsp) {
4213 btif_rc_device_cb_t* p_dev =
4214 btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4215 bt_bdaddr_t rc_addr;
4216 bdcpy(rc_addr.address, p_dev->rc_addr);
4217
4218 if (p_rsp->status == AVRC_STS_NO_ERROR) {
4219 HAL_CBACK(bt_rc_ctrl_callbacks, set_browsed_player_cb, &rc_addr,
4220 p_rsp->num_items, p_rsp->folder_depth);
4221 } else {
4222 BTIF_TRACE_ERROR("%s error %d", __func__, p_rsp->status);
4223 }
4224 }
4225
4226 /***************************************************************************
4227 *
4228 * Function clear_cmd_timeout
4229 *
4230 * Description helper function to stop the command timeout timer
4231 * Returns None
4232 *
4233 **************************************************************************/
clear_cmd_timeout(uint8_t label)4234 static void clear_cmd_timeout(uint8_t label) {
4235 rc_transaction_t* p_txn;
4236
4237 p_txn = get_transaction_by_lbl(label);
4238 if (p_txn == NULL) {
4239 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __func__);
4240 return;
4241 }
4242
4243 if (p_txn->txn_timer != NULL) alarm_cancel(p_txn->txn_timer);
4244 }
4245
4246 /***************************************************************************
4247 *
4248 * Function handle_avk_rc_metamsg_rsp
4249 *
4250 * Description Handle RC metamessage response
4251 *
4252 * Returns void
4253 *
4254 **************************************************************************/
handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg)4255 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) {
4256 tAVRC_RESPONSE avrc_response = {0};
4257 uint8_t scratch_buf[512] = {0}; // this variable is unused
4258 uint16_t buf_len;
4259 tAVRC_STS status;
4260
4261 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d ", __func__,
4262 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4263
4264 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf,
4265 &buf_len);
4266 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) &&
4267 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL) &&
4268 (pmeta_msg->code <= AVRC_RSP_INTERIM)) {
4269 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d", __func__,
4270 status, avrc_response.pdu,
4271 pmeta_msg->p_msg->vendor.hdr.ctype);
4272
4273 switch (avrc_response.pdu) {
4274 case AVRC_PDU_REGISTER_NOTIFICATION:
4275 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
4276 if (pmeta_msg->code == AVRC_RSP_INTERIM) {
4277 /* Don't free the transaction Id */
4278 clear_cmd_timeout(pmeta_msg->label);
4279 return;
4280 }
4281 break;
4282
4283 case AVRC_PDU_GET_CAPABILITIES:
4284 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
4285 break;
4286
4287 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
4288 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
4289 break;
4290
4291 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
4292 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
4293 break;
4294
4295 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
4296 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
4297 break;
4298
4299 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
4300 handle_app_attr_txt_response(pmeta_msg,
4301 &avrc_response.get_app_attr_txt);
4302 break;
4303
4304 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
4305 handle_app_attr_val_txt_response(pmeta_msg,
4306 &avrc_response.get_app_val_txt);
4307 break;
4308
4309 case AVRC_PDU_SET_PLAYER_APP_VALUE:
4310 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
4311 break;
4312
4313 case AVRC_PDU_GET_ELEMENT_ATTR:
4314 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_attrs);
4315 break;
4316
4317 case AVRC_PDU_GET_PLAY_STATUS:
4318 handle_get_playstatus_response(pmeta_msg,
4319 &avrc_response.get_play_status);
4320 break;
4321
4322 case AVRC_PDU_SET_ADDRESSED_PLAYER:
4323 handle_set_addressed_player_response(pmeta_msg, &avrc_response.rsp);
4324 break;
4325 }
4326 } else if (AVRC_OP_BROWSE == pmeta_msg->p_msg->hdr.opcode) {
4327 BTIF_TRACE_DEBUG("%s AVRC_OP_BROWSE pdu %d", __func__, avrc_response.pdu);
4328 /* check what kind of command it is for browsing */
4329 switch (avrc_response.pdu) {
4330 case AVRC_PDU_GET_FOLDER_ITEMS:
4331 handle_get_folder_items_response(pmeta_msg, &avrc_response.get_items);
4332 break;
4333 case AVRC_PDU_CHANGE_PATH:
4334 handle_change_path_response(pmeta_msg, &avrc_response.chg_path);
4335 break;
4336 case AVRC_PDU_SET_BROWSED_PLAYER:
4337 handle_set_browsed_player_response(pmeta_msg, &avrc_response.br_player);
4338 break;
4339 default:
4340 BTIF_TRACE_ERROR("%s cannot handle browse pdu %d", __func__,
4341 pmeta_msg->p_msg->hdr.opcode);
4342 }
4343 } else {
4344 BTIF_TRACE_DEBUG(
4345 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.",
4346 __func__, pmeta_msg->code, pmeta_msg->len);
4347 return;
4348 }
4349 BTIF_TRACE_DEBUG("XX __func__ release transaction %d", pmeta_msg->label);
4350 release_transaction(pmeta_msg->label);
4351 }
4352
4353 /***************************************************************************
4354 *
4355 * Function handle_avk_rc_metamsg_cmd
4356 *
4357 * Description Handle RC metamessage response
4358 *
4359 * Returns void
4360 *
4361 **************************************************************************/
handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)4362 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
4363 tAVRC_COMMAND avrc_cmd = {0};
4364 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
4365 btif_rc_device_cb_t* p_dev = NULL;
4366
4367 BTIF_TRACE_DEBUG("%s: opcode: %d rsp_code: %d", __func__,
4368 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
4369 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
4370 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode) &&
4371 (pmeta_msg->code <= AVRC_CMD_GEN_INQ)) {
4372 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
4373 __func__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
4374
4375 if (status != AVRC_STS_NO_ERROR) {
4376 /* return error */
4377 BTIF_TRACE_WARNING(
4378 "%s: Error in parsing received metamsg command. status: 0x%02x",
4379 __func__, status);
4380 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu,
4381 status, pmeta_msg->p_msg->hdr.opcode);
4382 } else {
4383 p_dev = btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
4384 if (p_dev == NULL) {
4385 BTIF_TRACE_ERROR("%s: avk rc meta msg cmd for Invalid rc handle",
4386 __func__);
4387 return;
4388 }
4389
4390 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION) {
4391 uint8_t event_id = avrc_cmd.reg_notif.event_id;
4392 BTIF_TRACE_EVENT("%s: Register notification event_id: %s", __func__,
4393 dump_rc_notification_event_id(event_id));
4394 } else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) {
4395 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __func__);
4396 }
4397
4398 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label,
4399 p_dev);
4400 }
4401 } else {
4402 BTIF_TRACE_DEBUG(
4403 "%s: Invalid Vendor Command code: %d len: %d. Not processing it.",
4404 __func__, pmeta_msg->code, pmeta_msg->len);
4405 return;
4406 }
4407 }
4408
4409 /***************************************************************************
4410 *
4411 * Function cleanup
4412 *
4413 * Description Closes the AVRC interface
4414 *
4415 * Returns void
4416 *
4417 **************************************************************************/
cleanup()4418 static void cleanup() {
4419 BTIF_TRACE_EVENT("%s: ", __func__);
4420 if (bt_rc_callbacks) {
4421 bt_rc_callbacks = NULL;
4422 }
4423
4424 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4425 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4426 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
4427 sizeof(btif_rc_cb.rc_multi_cb[idx]));
4428 }
4429
4430 BTIF_TRACE_EVENT("%s: completed", __func__);
4431 }
4432
4433 /***************************************************************************
4434 *
4435 * Function cleanup_ctrl
4436 *
4437 * Description Closes the AVRC Controller interface
4438 *
4439 * Returns void
4440 *
4441 **************************************************************************/
cleanup_ctrl()4442 static void cleanup_ctrl() {
4443 BTIF_TRACE_EVENT("%s: ", __func__);
4444
4445 if (bt_rc_ctrl_callbacks) {
4446 bt_rc_ctrl_callbacks = NULL;
4447 }
4448
4449 for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
4450 alarm_free(btif_rc_cb.rc_multi_cb[idx].rc_play_status_timer);
4451 memset(&btif_rc_cb.rc_multi_cb[idx], 0,
4452 sizeof(btif_rc_cb.rc_multi_cb[idx]));
4453 }
4454
4455 memset(&btif_rc_cb.rc_multi_cb, 0, sizeof(btif_rc_cb.rc_multi_cb));
4456 BTIF_TRACE_EVENT("%s: completed", __func__);
4457 }
4458
4459 /***************************************************************************
4460 *
4461 * Function getcapabilities_cmd
4462 *
4463 * Description GetCapabilties from Remote(Company_ID, Events_Supported)
4464 *
4465 * Returns void
4466 *
4467 **************************************************************************/
getcapabilities_cmd(uint8_t cap_id,btif_rc_device_cb_t * p_dev)4468 static bt_status_t getcapabilities_cmd(uint8_t cap_id,
4469 btif_rc_device_cb_t* p_dev) {
4470 BTIF_TRACE_DEBUG("%s: cap_id: %d", __func__, cap_id);
4471 CHECK_RC_CONNECTED(p_dev);
4472
4473 tAVRC_COMMAND avrc_cmd = {0};
4474 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
4475 avrc_cmd.get_caps.capability_id = cap_id;
4476 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
4477 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
4478
4479 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4480 }
4481
4482 /***************************************************************************
4483 *
4484 * Function list_player_app_setting_attrib_cmd
4485 *
4486 * Description Get supported List Player Attributes
4487 *
4488 * Returns void
4489 *
4490 **************************************************************************/
list_player_app_setting_attrib_cmd(btif_rc_device_cb_t * p_dev)4491 static bt_status_t list_player_app_setting_attrib_cmd(
4492 btif_rc_device_cb_t* p_dev) {
4493 BTIF_TRACE_DEBUG("%s", __func__);
4494 CHECK_RC_CONNECTED(p_dev);
4495
4496 tAVRC_COMMAND avrc_cmd = {0};
4497 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
4498 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
4499 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
4500
4501 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4502 }
4503
4504 /***************************************************************************
4505 *
4506 * Function list_player_app_setting_value_cmd
4507 *
4508 * Description Get values of supported Player Attributes
4509 *
4510 * Returns void
4511 *
4512 **************************************************************************/
list_player_app_setting_value_cmd(uint8_t attrib_id,btif_rc_device_cb_t * p_dev)4513 static bt_status_t list_player_app_setting_value_cmd(
4514 uint8_t attrib_id, btif_rc_device_cb_t* p_dev) {
4515 BTIF_TRACE_DEBUG("%s: attrib_id: %d", __func__, attrib_id);
4516 CHECK_RC_CONNECTED(p_dev);
4517
4518 tAVRC_COMMAND avrc_cmd = {0};
4519 avrc_cmd.list_app_values.attr_id = attrib_id;
4520 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
4521 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
4522 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
4523
4524 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4525 }
4526
4527 /***************************************************************************
4528 *
4529 * Function get_player_app_setting_cmd
4530 *
4531 * Description Get current values of Player Attributes
4532 *
4533 * Returns void
4534 *
4535 **************************************************************************/
get_player_app_setting_cmd(uint8_t num_attrib,uint8_t * attrib_ids,btif_rc_device_cb_t * p_dev)4536 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib,
4537 uint8_t* attrib_ids,
4538 btif_rc_device_cb_t* p_dev) {
4539 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib);
4540 CHECK_RC_CONNECTED(p_dev);
4541
4542 tAVRC_COMMAND avrc_cmd = {0};
4543 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
4544 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
4545 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
4546 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
4547
4548 for (int count = 0; count < num_attrib; count++) {
4549 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
4550 }
4551
4552 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4553 }
4554
4555 /***************************************************************************
4556 *
4557 * Function get_playback_state_cmd
4558 *
4559 * Description Fetch the current playback state for the device
4560 *
4561 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4562 * BT_STATUS_FAIL.
4563 *
4564 **************************************************************************/
get_playback_state_cmd(bt_bdaddr_t * bd_addr)4565 static bt_status_t get_playback_state_cmd(bt_bdaddr_t* bd_addr) {
4566 BTIF_TRACE_DEBUG("%s", __func__);
4567 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4568 return get_play_status_cmd(p_dev);
4569 }
4570
4571 /***************************************************************************
4572 *
4573 * Function get_now_playing_list_cmd
4574 *
4575 * Description Fetch the now playing list
4576 *
4577 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4578 * end_item: Last item to fetch (0xff to fetch until end)
4579 *
4580 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4581 * BT_STATUS_FAIL.
4582 *
4583 **************************************************************************/
get_now_playing_list_cmd(bt_bdaddr_t * bd_addr,uint8_t start_item,uint8_t num_items)4584 static bt_status_t get_now_playing_list_cmd(bt_bdaddr_t* bd_addr,
4585 uint8_t start_item,
4586 uint8_t num_items) {
4587 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
4588 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_NOW_PLAYING, start_item,
4589 num_items);
4590 }
4591
4592 /***************************************************************************
4593 *
4594 * Function get_folder_list_cmd
4595 *
4596 * Description Fetch the currently selected folder list
4597 *
4598 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4599 * end_item: Last item to fetch (0xff to fetch until end)
4600 *
4601 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4602 * BT_STATUS_FAIL.
4603 *
4604 **************************************************************************/
get_folder_list_cmd(bt_bdaddr_t * bd_addr,uint8_t start_item,uint8_t num_items)4605 static bt_status_t get_folder_list_cmd(bt_bdaddr_t* bd_addr, uint8_t start_item,
4606 uint8_t num_items) {
4607 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
4608 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_FILE_SYSTEM, start_item,
4609 num_items);
4610 }
4611
4612 /***************************************************************************
4613 *
4614 * Function get_player_list_cmd
4615 *
4616 * Description Fetch the player list
4617 *
4618 * Paramters start_item: First item to fetch (0 to fetch from beganning)
4619 * end_item: Last item to fetch (0xff to fetch until end)
4620 *
4621 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4622 * BT_STATUS_FAIL.
4623 *
4624 **************************************************************************/
get_player_list_cmd(bt_bdaddr_t * bd_addr,uint8_t start_item,uint8_t num_items)4625 static bt_status_t get_player_list_cmd(bt_bdaddr_t* bd_addr, uint8_t start_item,
4626 uint8_t num_items) {
4627 BTIF_TRACE_DEBUG("%s start, end: (%d, %d)", __func__, start_item, num_items);
4628 return get_folder_items_cmd(bd_addr, AVRC_SCOPE_PLAYER_LIST, start_item,
4629 num_items);
4630 }
4631
4632 /***************************************************************************
4633 *
4634 * Function change_folder_path_cmd
4635 *
4636 * Description Change the folder.
4637 *
4638 * Paramters direction: Direction (Up/Down) to change folder
4639 * uid: The UID of folder to move to
4640 * start_item: First item to fetch (0 to fetch from beganning)
4641 * end_item: Last item to fetch (0xff to fetch until end)
4642 *
4643 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4644 * BT_STATUS_FAIL.
4645 *
4646 **************************************************************************/
change_folder_path_cmd(bt_bdaddr_t * bd_addr,uint8_t direction,uint8_t * uid)4647 static bt_status_t change_folder_path_cmd(bt_bdaddr_t* bd_addr,
4648 uint8_t direction, uint8_t* uid) {
4649 BTIF_TRACE_DEBUG("%s: direction %d", __func__, direction);
4650 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4651 CHECK_RC_CONNECTED(p_dev);
4652 CHECK_BR_CONNECTED(p_dev);
4653
4654 tAVRC_COMMAND avrc_cmd = {0};
4655
4656 avrc_cmd.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
4657 avrc_cmd.chg_path.status = AVRC_STS_NO_ERROR;
4658 // TODO(sanketa): Improve for database aware clients.
4659 avrc_cmd.chg_path.uid_counter = 0;
4660 avrc_cmd.chg_path.direction = direction;
4661
4662 memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t));
4663 memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t));
4664
4665 BT_HDR* p_msg = NULL;
4666 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
4667 if (status != AVRC_STS_NO_ERROR) {
4668 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
4669 return BT_STATUS_FAIL;
4670 }
4671
4672 rc_transaction_t* p_transaction = NULL;
4673 bt_status_t tran_status = get_transaction(&p_transaction);
4674 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
4675 osi_free(p_msg);
4676 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
4677 __func__, tran_status);
4678 return BT_STATUS_FAIL;
4679 }
4680
4681 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
4682 p_transaction->lbl);
4683 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
4684 return BT_STATUS_SUCCESS;
4685 }
4686
4687 /***************************************************************************
4688 *
4689 * Function set_browsed_player_cmd
4690 *
4691 * Description Change the browsed player.
4692 *
4693 * Paramters id: The UID of player to move to
4694 *
4695 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4696 * BT_STATUS_FAIL.
4697 *
4698 **************************************************************************/
set_browsed_player_cmd(bt_bdaddr_t * bd_addr,uint16_t id)4699 static bt_status_t set_browsed_player_cmd(bt_bdaddr_t* bd_addr, uint16_t id) {
4700 BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
4701 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4702 CHECK_RC_CONNECTED(p_dev);
4703 CHECK_BR_CONNECTED(p_dev);
4704
4705 rc_transaction_t* p_transaction = NULL;
4706
4707 tAVRC_COMMAND avrc_cmd = {0};
4708 avrc_cmd.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
4709 avrc_cmd.br_player.status = AVRC_STS_NO_ERROR;
4710 // TODO(sanketa): Improve for database aware clients.
4711 avrc_cmd.br_player.player_id = id;
4712
4713 BT_HDR* p_msg = NULL;
4714 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
4715 if (status != AVRC_STS_NO_ERROR) {
4716 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
4717 return BT_STATUS_FAIL;
4718 }
4719
4720 bt_status_t tran_status = get_transaction(&p_transaction);
4721 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
4722 osi_free(p_msg);
4723 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
4724 __func__, tran_status);
4725 return BT_STATUS_FAIL;
4726 }
4727
4728 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
4729 p_transaction->lbl);
4730 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
4731 return BT_STATUS_SUCCESS;
4732 }
4733
4734 /***************************************************************************
4735 **
4736 ** Function set_addressed_player_cmd
4737 **
4738 ** Description Change the addressed player.
4739 **
4740 ** Paramters id: The UID of player to move to
4741 **
4742 ** Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4743 ** BT_STATUS_FAIL.
4744 **
4745 ***************************************************************************/
set_addressed_player_cmd(bt_bdaddr_t * bd_addr,uint16_t id)4746 static bt_status_t set_addressed_player_cmd(bt_bdaddr_t* bd_addr, uint16_t id) {
4747 BTIF_TRACE_DEBUG("%s: id %d", __func__, id);
4748
4749 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4750 CHECK_RC_CONNECTED(p_dev);
4751 CHECK_BR_CONNECTED(p_dev);
4752
4753 tAVRC_COMMAND avrc_cmd = {0};
4754 BT_HDR* p_msg = NULL;
4755
4756 avrc_cmd.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
4757 avrc_cmd.addr_player.status = AVRC_STS_NO_ERROR;
4758 // TODO(sanketa): Improve for database aware clients.
4759 avrc_cmd.addr_player.player_id = id;
4760
4761 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
4762 if (status != AVRC_STS_NO_ERROR) {
4763 BTIF_TRACE_ERROR("%s: failed to build command status %d", __func__, status);
4764 return BT_STATUS_FAIL;
4765 }
4766
4767 rc_transaction_t* p_transaction = NULL;
4768 bt_status_t tran_status = get_transaction(&p_transaction);
4769
4770 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
4771 osi_free(p_msg);
4772 BTIF_TRACE_ERROR("%s: failed to obtain txn details. status: 0x%02x",
4773 __func__, tran_status);
4774 return BT_STATUS_FAIL;
4775 }
4776
4777 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
4778 p_transaction->lbl);
4779 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
4780 return BT_STATUS_SUCCESS;
4781 }
4782
4783 /***************************************************************************
4784 *
4785 * Function get_folder_items_cmd
4786 *
4787 * Description Helper function to browse the content hierarchy of the
4788 * TG device.
4789 *
4790 * Paramters scope: AVRC_SCOPE_NOW_PLAYING (etc) for various browseable
4791 * content
4792 * start_item: First item to fetch (0 to fetch from beganning)
4793 * end_item: Last item to fetch (0xff to fetch until end)
4794 *
4795 * Returns BT_STATUS_SUCCESS if command issued successfully otherwise
4796 * BT_STATUS_FAIL.
4797 *
4798 **************************************************************************/
get_folder_items_cmd(bt_bdaddr_t * bd_addr,uint8_t scope,uint8_t start_item,uint8_t end_item)4799 static bt_status_t get_folder_items_cmd(bt_bdaddr_t* bd_addr, uint8_t scope,
4800 uint8_t start_item, uint8_t end_item) {
4801 /* Check that both avrcp and browse channel are connected. */
4802 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4803 BTIF_TRACE_DEBUG("%s", __func__);
4804 CHECK_RC_CONNECTED(p_dev);
4805 CHECK_BR_CONNECTED(p_dev);
4806
4807 tAVRC_COMMAND avrc_cmd = {0};
4808
4809 /* Set the layer specific to point to browse although this should really
4810 * be done by lower layers and looking at the PDU
4811 */
4812 avrc_cmd.get_items.pdu = AVRC_PDU_GET_FOLDER_ITEMS;
4813 avrc_cmd.get_items.status = AVRC_STS_NO_ERROR;
4814 avrc_cmd.get_items.scope = scope;
4815 avrc_cmd.get_items.start_item = start_item;
4816 avrc_cmd.get_items.end_item = end_item;
4817 avrc_cmd.get_items.attr_count = 0; /* p_attr_list does not matter hence */
4818
4819 BT_HDR* p_msg = NULL;
4820 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
4821 if (status != AVRC_STS_NO_ERROR) {
4822 BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
4823 return BT_STATUS_FAIL;
4824 }
4825
4826 rc_transaction_t* p_transaction = NULL;
4827 bt_status_t tran_status = get_transaction(&p_transaction);
4828 if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
4829 osi_free(p_msg);
4830 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
4831 __func__, tran_status);
4832 return BT_STATUS_FAIL;
4833 }
4834
4835 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
4836 p_transaction->lbl);
4837 BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
4838 return BT_STATUS_SUCCESS;
4839 }
4840
4841 /***************************************************************************
4842 *
4843 * Function change_player_app_setting
4844 *
4845 * Description Set current values of Player Attributes
4846 *
4847 * Returns void
4848 *
4849 **************************************************************************/
change_player_app_setting(bt_bdaddr_t * bd_addr,uint8_t num_attrib,uint8_t * attrib_ids,uint8_t * attrib_vals)4850 static bt_status_t change_player_app_setting(bt_bdaddr_t* bd_addr,
4851 uint8_t num_attrib,
4852 uint8_t* attrib_ids,
4853 uint8_t* attrib_vals) {
4854 BTIF_TRACE_DEBUG("%s: num_attrib: %d", __func__, num_attrib);
4855 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4856 CHECK_RC_CONNECTED(p_dev);
4857
4858 tAVRC_COMMAND avrc_cmd = {0};
4859 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
4860 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
4861 avrc_cmd.set_app_val.num_val = num_attrib;
4862 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
4863 avrc_cmd.set_app_val.p_vals =
4864 (tAVRC_APP_SETTING*)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
4865 for (int count = 0; count < num_attrib; count++) {
4866 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
4867 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
4868 }
4869
4870 bt_status_t st = build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4871 osi_free_and_reset((void**)&avrc_cmd.set_app_val.p_vals);
4872 return st;
4873 }
4874
4875 /***************************************************************************
4876 *
4877 * Function play_item_cmd
4878 *
4879 * Description Play the item specified by UID & scope
4880 *
4881 * Returns void
4882 *
4883 **************************************************************************/
play_item_cmd(bt_bdaddr_t * bd_addr,uint8_t scope,uint8_t * uid,uint16_t uid_counter)4884 static bt_status_t play_item_cmd(bt_bdaddr_t* bd_addr, uint8_t scope,
4885 uint8_t* uid, uint16_t uid_counter) {
4886 BTIF_TRACE_DEBUG("%s: scope %d uid_counter %d", __func__, scope, uid_counter);
4887 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
4888 CHECK_RC_CONNECTED(p_dev);
4889 CHECK_BR_CONNECTED(p_dev);
4890
4891 tAVRC_COMMAND avrc_cmd = {0};
4892 avrc_cmd.pdu = AVRC_PDU_PLAY_ITEM;
4893 avrc_cmd.play_item.opcode = AVRC_OP_VENDOR;
4894 avrc_cmd.play_item.status = AVRC_STS_NO_ERROR;
4895 avrc_cmd.play_item.scope = scope;
4896 memcpy(avrc_cmd.play_item.uid, uid, AVRC_UID_SIZE);
4897 avrc_cmd.play_item.uid_counter = uid_counter;
4898
4899 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
4900 }
4901
4902 /***************************************************************************
4903 *
4904 * Function get_player_app_setting_attr_text_cmd
4905 *
4906 * Description Get text description for app attribute
4907 *
4908 * Returns void
4909 *
4910 **************************************************************************/
get_player_app_setting_attr_text_cmd(uint8_t * attrs,uint8_t num_attrs,btif_rc_device_cb_t * p_dev)4911 static bt_status_t get_player_app_setting_attr_text_cmd(
4912 uint8_t* attrs, uint8_t num_attrs, btif_rc_device_cb_t* p_dev) {
4913 BTIF_TRACE_DEBUG("%s: num attrs: %d", __func__, num_attrs);
4914 CHECK_RC_CONNECTED(p_dev);
4915
4916 tAVRC_COMMAND avrc_cmd = {0};
4917 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
4918 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
4919 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
4920
4921 for (int count = 0; count < num_attrs; count++) {
4922 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
4923 }
4924
4925 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4926 }
4927
4928 /***************************************************************************
4929 *
4930 * Function get_player_app_setting_val_text_cmd
4931 *
4932 * Description Get text description for app attribute values
4933 *
4934 * Returns void
4935 *
4936 **************************************************************************/
get_player_app_setting_value_text_cmd(uint8_t * vals,uint8_t num_vals,btif_rc_device_cb_t * p_dev)4937 static bt_status_t get_player_app_setting_value_text_cmd(
4938 uint8_t* vals, uint8_t num_vals, btif_rc_device_cb_t* p_dev) {
4939 BTIF_TRACE_DEBUG("%s: num_vals: %d", __func__, num_vals);
4940 CHECK_RC_CONNECTED(p_dev);
4941
4942 tAVRC_COMMAND avrc_cmd = {0};
4943 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
4944 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
4945 avrc_cmd.get_app_val_txt.num_val = num_vals;
4946
4947 for (int count = 0; count < num_vals; count++) {
4948 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
4949 }
4950
4951 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
4952 }
4953
4954 /***************************************************************************
4955 *
4956 * Function register_notification_cmd
4957 *
4958 * Description Send Command to register for a Notification ID
4959 *
4960 * Returns void
4961 *
4962 **************************************************************************/
register_notification_cmd(uint8_t label,uint8_t event_id,uint32_t event_value,btif_rc_device_cb_t * p_dev)4963 static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id,
4964 uint32_t event_value,
4965 btif_rc_device_cb_t* p_dev) {
4966 BTIF_TRACE_DEBUG("%s: event_id: %d event_value %d", __func__, event_id,
4967 event_value);
4968 CHECK_RC_CONNECTED(p_dev);
4969
4970 tAVRC_COMMAND avrc_cmd = {0};
4971 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
4972 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
4973 avrc_cmd.reg_notif.event_id = event_id;
4974 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
4975 avrc_cmd.reg_notif.param = event_value;
4976
4977 BT_HDR* p_msg = NULL;
4978 tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
4979 if (status == AVRC_STS_NO_ERROR) {
4980 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
4981 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
4982 label);
4983 if (p_msg != NULL) {
4984 BTA_AvVendorCmd(p_dev->rc_handle, label, AVRC_CMD_NOTIF, data_start,
4985 p_msg->len);
4986 status = BT_STATUS_SUCCESS;
4987 }
4988 } else {
4989 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
4990 status);
4991 }
4992 osi_free(p_msg);
4993 return (bt_status_t)status;
4994 }
4995
4996 /***************************************************************************
4997 *
4998 * Function get_element_attribute_cmd
4999 *
5000 * Description Get Element Attribute for attributeIds
5001 *
5002 * Returns void
5003 *
5004 **************************************************************************/
get_element_attribute_cmd(uint8_t num_attribute,uint32_t * p_attr_ids,btif_rc_device_cb_t * p_dev)5005 static bt_status_t get_element_attribute_cmd(uint8_t num_attribute,
5006 uint32_t* p_attr_ids,
5007 btif_rc_device_cb_t* p_dev) {
5008 BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__,
5009 num_attribute, p_attr_ids[0]);
5010 CHECK_RC_CONNECTED(p_dev);
5011
5012 tAVRC_COMMAND avrc_cmd = {0};
5013 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
5014 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
5015 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
5016 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
5017 for (int count = 0; count < num_attribute; count++) {
5018 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
5019 }
5020
5021 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
5022 }
5023
5024 /***************************************************************************
5025 *
5026 * Function get_play_status_cmd
5027 *
5028 * Description Get Playing Status of a Device
5029 *
5030 * Returns bt_status_t
5031 *
5032 **************************************************************************/
get_play_status_cmd(btif_rc_device_cb_t * p_dev)5033 static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev) {
5034 BTIF_TRACE_DEBUG("%s", __func__);
5035 CHECK_RC_CONNECTED(p_dev);
5036
5037 tAVRC_COMMAND avrc_cmd = {0};
5038 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
5039 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
5040 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
5041
5042 return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_STATUS, p_dev);
5043 }
5044
5045 /***************************************************************************
5046 *
5047 * Function set_volume_rsp
5048 *
5049 * Description Rsp for SetAbsoluteVolume Command
5050 *
5051 * Returns void
5052 *
5053 **************************************************************************/
set_volume_rsp(bt_bdaddr_t * bd_addr,uint8_t abs_vol,uint8_t label)5054 static bt_status_t set_volume_rsp(bt_bdaddr_t* bd_addr, uint8_t abs_vol,
5055 uint8_t label) {
5056 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5057 tAVRC_RESPONSE avrc_rsp;
5058 BT_HDR* p_msg = NULL;
5059 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5060
5061 CHECK_RC_CONNECTED(p_dev);
5062
5063 BTIF_TRACE_DEBUG("%s: abs_vol: %d", __func__, abs_vol);
5064
5065 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
5066 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
5067 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
5068 avrc_rsp.volume.volume = abs_vol;
5069 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
5070 if (status == AVRC_STS_NO_ERROR) {
5071 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
5072 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
5073 p_dev->rc_vol_label);
5074 if (p_msg != NULL) {
5075 BTA_AvVendorRsp(p_dev->rc_handle, label, BTA_AV_RSP_ACCEPT, data_start,
5076 p_msg->len, 0);
5077 status = BT_STATUS_SUCCESS;
5078 }
5079 } else {
5080 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
5081 status);
5082 }
5083 osi_free(p_msg);
5084 return (bt_status_t)status;
5085 }
5086
5087 /***************************************************************************
5088 *
5089 * Function send_register_abs_vol_rsp
5090 *
5091 * Description Rsp for Notification of Absolute Volume
5092 *
5093 * Returns void
5094 *
5095 **************************************************************************/
volume_change_notification_rsp(bt_bdaddr_t * bd_addr,btrc_notification_type_t rsp_type,uint8_t abs_vol,uint8_t label)5096 static bt_status_t volume_change_notification_rsp(
5097 bt_bdaddr_t* bd_addr, btrc_notification_type_t rsp_type, uint8_t abs_vol,
5098 uint8_t label) {
5099 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5100 tAVRC_RESPONSE avrc_rsp;
5101 BT_HDR* p_msg = NULL;
5102 BTIF_TRACE_DEBUG("%s: rsp_type: %d abs_vol: %d", __func__, rsp_type, abs_vol);
5103
5104 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5105
5106 CHECK_RC_CONNECTED(p_dev);
5107
5108 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
5109 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
5110 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
5111 avrc_rsp.reg_notif.param.volume = abs_vol;
5112 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
5113
5114 status = AVRC_BldResponse(p_dev->rc_handle, &avrc_rsp, &p_msg);
5115 if (status == AVRC_STS_NO_ERROR) {
5116 BTIF_TRACE_DEBUG("%s: msgreq being sent out with label: %d", __func__,
5117 label);
5118 uint8_t* data_start = (uint8_t*)(p_msg + 1) + p_msg->offset;
5119 BTA_AvVendorRsp(p_dev->rc_handle, label,
5120 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM)
5121 ? AVRC_RSP_INTERIM
5122 : AVRC_RSP_CHANGED,
5123 data_start, p_msg->len, 0);
5124 status = BT_STATUS_SUCCESS;
5125 } else {
5126 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __func__,
5127 status);
5128 }
5129 osi_free(p_msg);
5130
5131 return (bt_status_t)status;
5132 }
5133
5134 /***************************************************************************
5135 *
5136 * Function send_groupnavigation_cmd
5137 *
5138 * Description Send Pass-Through command
5139 *
5140 * Returns void
5141 *
5142 **************************************************************************/
send_groupnavigation_cmd(bt_bdaddr_t * bd_addr,uint8_t key_code,uint8_t key_state)5143 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t* bd_addr,
5144 uint8_t key_code,
5145 uint8_t key_state) {
5146 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5147 rc_transaction_t* p_transaction = NULL;
5148 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code,
5149 key_state);
5150 btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_bda(bd_addr);
5151
5152 CHECK_RC_CONNECTED(p_dev);
5153
5154 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
5155 bt_status_t tran_status = get_transaction(&p_transaction);
5156 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
5157 uint8_t buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
5158 uint8_t* start = buffer;
5159 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
5160 *(start)++ = 0;
5161 UINT8_TO_BE_STREAM(start, key_code);
5162 BTA_AvRemoteVendorUniqueCmd(p_dev->rc_handle, p_transaction->lbl,
5163 (tBTA_AV_STATE)key_state, buffer,
5164 AVRC_PASS_THRU_GROUP_LEN);
5165 status = BT_STATUS_SUCCESS;
5166 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
5167 __func__);
5168 } else {
5169 status = BT_STATUS_FAIL;
5170 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__);
5171 }
5172 } else {
5173 status = BT_STATUS_FAIL;
5174 BTIF_TRACE_DEBUG("%s: feature not supported", __func__);
5175 }
5176 return (bt_status_t)status;
5177 }
5178
5179 /***************************************************************************
5180 *
5181 * Function send_passthrough_cmd
5182 *
5183 * Description Send Pass-Through command
5184 *
5185 * Returns void
5186 *
5187 **************************************************************************/
send_passthrough_cmd(bt_bdaddr_t * bd_addr,uint8_t key_code,uint8_t key_state)5188 static bt_status_t send_passthrough_cmd(bt_bdaddr_t* bd_addr, uint8_t key_code,
5189 uint8_t key_state) {
5190 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
5191 btif_rc_device_cb_t* p_dev = NULL;
5192 BTIF_TRACE_ERROR("%s: calling btif_rc_get_device_by_bda", __func__);
5193 p_dev = btif_rc_get_device_by_bda(bd_addr);
5194
5195 CHECK_RC_CONNECTED(p_dev);
5196
5197 rc_transaction_t* p_transaction = NULL;
5198 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __func__, key_code,
5199 key_state);
5200 if (p_dev->rc_features & BTA_AV_FEAT_RCTG) {
5201 bt_status_t tran_status = get_transaction(&p_transaction);
5202 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction) {
5203 BTA_AvRemoteCmd(p_dev->rc_handle, p_transaction->lbl,
5204 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
5205 status = BT_STATUS_SUCCESS;
5206 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA",
5207 __func__);
5208 } else {
5209 status = BT_STATUS_FAIL;
5210 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __func__);
5211 }
5212 } else {
5213 status = BT_STATUS_FAIL;
5214 BTIF_TRACE_DEBUG("%s: feature not supported", __func__);
5215 }
5216 return (bt_status_t)status;
5217 }
5218
5219 static const btrc_interface_t bt_rc_interface = {
5220 sizeof(bt_rc_interface),
5221 init,
5222 get_play_status_rsp,
5223 NULL, /* list_player_app_attr_rsp */
5224 NULL, /* list_player_app_value_rsp */
5225 NULL, /* get_player_app_value_rsp */
5226 NULL, /* get_player_app_attr_text_rsp */
5227 NULL, /* get_player_app_value_text_rsp */
5228 get_element_attr_rsp,
5229 NULL, /* set_player_app_value_rsp */
5230 register_notification_rsp,
5231 set_volume,
5232 set_addressed_player_rsp,
5233 set_browsed_player_rsp,
5234 get_folder_items_list_rsp,
5235 change_path_rsp,
5236 get_item_attr_rsp,
5237 play_item_rsp,
5238 get_total_num_of_items_rsp,
5239 search_rsp,
5240 add_to_now_playing_rsp,
5241 cleanup,
5242 };
5243
5244 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
5245 sizeof(bt_rc_ctrl_interface),
5246 init_ctrl,
5247 send_passthrough_cmd,
5248 send_groupnavigation_cmd,
5249 change_player_app_setting,
5250 play_item_cmd,
5251 get_playback_state_cmd,
5252 get_now_playing_list_cmd,
5253 get_folder_list_cmd,
5254 get_player_list_cmd,
5255 change_folder_path_cmd,
5256 set_browsed_player_cmd,
5257 set_addressed_player_cmd,
5258 set_volume_rsp,
5259 volume_change_notification_rsp,
5260 cleanup_ctrl,
5261 };
5262
5263 /*******************************************************************************
5264 *
5265 * Function btif_rc_get_interface
5266 *
5267 * Description Get the AVRCP Target callback interface
5268 *
5269 * Returns btrc_interface_t
5270 *
5271 ******************************************************************************/
btif_rc_get_interface(void)5272 const btrc_interface_t* btif_rc_get_interface(void) {
5273 BTIF_TRACE_EVENT("%s: ", __func__);
5274 return &bt_rc_interface;
5275 }
5276
5277 /*******************************************************************************
5278 *
5279 * Function btif_rc_ctrl_get_interface
5280 *
5281 * Description Get the AVRCP Controller callback interface
5282 *
5283 * Returns btrc_ctrl_interface_t
5284 *
5285 ******************************************************************************/
btif_rc_ctrl_get_interface(void)5286 const btrc_ctrl_interface_t* btif_rc_ctrl_get_interface(void) {
5287 BTIF_TRACE_EVENT("%s: ", __func__);
5288 return &bt_rc_ctrl_interface;
5289 }
5290
5291 /*******************************************************************************
5292 * Function initialize_transaction
5293 *
5294 * Description Initializes fields of the transaction structure
5295 *
5296 * Returns void
5297 ******************************************************************************/
initialize_transaction(int lbl)5298 static void initialize_transaction(int lbl) {
5299 std::unique_lock<std::recursive_mutex>(device.lbllock);
5300 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5301 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
5302 clear_cmd_timeout(lbl);
5303 }
5304 device.transaction[lbl].lbl = lbl;
5305 device.transaction[lbl].in_use = false;
5306 device.transaction[lbl].handle = 0;
5307 }
5308 }
5309
5310 /*******************************************************************************
5311 * Function lbl_init
5312 *
5313 * Description Initializes label structures and mutexes.
5314 *
5315 * Returns void
5316 ******************************************************************************/
lbl_init()5317 void lbl_init() {
5318 memset(&device.transaction, 0, sizeof(device.transaction));
5319 init_all_transactions();
5320 }
5321
5322 /*******************************************************************************
5323 *
5324 * Function init_all_transactions
5325 *
5326 * Description Initializes all transactions
5327 *
5328 * Returns void
5329 ******************************************************************************/
init_all_transactions()5330 void init_all_transactions() {
5331 uint8_t txn_indx = 0;
5332 for (txn_indx = 0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++) {
5333 initialize_transaction(txn_indx);
5334 }
5335 }
5336
5337 /*******************************************************************************
5338 *
5339 * Function get_transaction_by_lbl
5340 *
5341 * Description Will return a transaction based on the label. If not inuse
5342 * will return an error.
5343 *
5344 * Returns bt_status_t
5345 ******************************************************************************/
get_transaction_by_lbl(uint8_t lbl)5346 rc_transaction_t* get_transaction_by_lbl(uint8_t lbl) {
5347 rc_transaction_t* transaction = NULL;
5348 std::unique_lock<std::recursive_mutex> lock(device.lbllock);
5349
5350 /* Determine if this is a valid label */
5351 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
5352 if (false == device.transaction[lbl].in_use) {
5353 transaction = NULL;
5354 } else {
5355 transaction = &(device.transaction[lbl]);
5356 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__, lbl);
5357 }
5358 }
5359
5360 return transaction;
5361 }
5362
5363 /*******************************************************************************
5364 *
5365 * Function get_transaction
5366 *
5367 * Description Obtains the transaction details.
5368 *
5369 * Returns bt_status_t
5370 ******************************************************************************/
5371
get_transaction(rc_transaction_t ** ptransaction)5372 static bt_status_t get_transaction(rc_transaction_t** ptransaction) {
5373 std::unique_lock<std::recursive_mutex> lock(device.lbllock);
5374
5375 // Check for unused transactions
5376 for (uint8_t i = 0; i < MAX_TRANSACTIONS_PER_SESSION; i++) {
5377 if (false == device.transaction[i].in_use) {
5378 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d", __func__,
5379 device.transaction[i].lbl);
5380 device.transaction[i].in_use = true;
5381 *ptransaction = &(device.transaction[i]);
5382 return BT_STATUS_SUCCESS;
5383 }
5384 }
5385 return BT_STATUS_NOMEM;
5386 }
5387
5388 /*******************************************************************************
5389 *
5390 * Function release_transaction
5391 *
5392 * Description Will release a transaction for reuse
5393 *
5394 * Returns bt_status_t
5395 ******************************************************************************/
release_transaction(uint8_t lbl)5396 void release_transaction(uint8_t lbl) {
5397 BTIF_TRACE_DEBUG("%s %d", __func__, lbl);
5398 rc_transaction_t* transaction = get_transaction_by_lbl(lbl);
5399
5400 /* If the transaction is in use... */
5401 if (transaction != NULL) {
5402 BTIF_TRACE_DEBUG("%s: lbl: %d", __func__, lbl);
5403 initialize_transaction(lbl);
5404 }
5405 }
5406
5407 /*******************************************************************************
5408 * Function sleep_ms
5409 *
5410 * Description Sleep the calling thread unconditionally for
5411 * |timeout_ms| milliseconds.
5412 *
5413 * Returns void
5414 ******************************************************************************/
sleep_ms(period_ms_t timeout_ms)5415 static void sleep_ms(period_ms_t timeout_ms) {
5416 struct timespec delay;
5417 delay.tv_sec = timeout_ms / 1000;
5418 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
5419
5420 OSI_NO_INTR(nanosleep(&delay, &delay));
5421 }
5422
absolute_volume_disabled()5423 static bool absolute_volume_disabled() {
5424 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
5425 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
5426 if (strncmp(volume_disabled, "true", 4) == 0) {
5427 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);
5428 return true;
5429 }
5430 return false;
5431 }
5432