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