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