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