1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*****************************************************************************
18 *
19 * Filename: btif_rc.c
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 <hardware/bluetooth.h>
35 #include <hardware/bt_rc.h>
36
37 #include "avrc_defs.h"
38 #include "bta_api.h"
39 #include "bta_av_api.h"
40 #include "btif_av.h"
41 #include "btif_common.h"
42 #include "btif_util.h"
43 #include "bt_common.h"
44 #include "device/include/interop.h"
45 #include "uinput.h"
46 #include "bdaddr.h"
47 #include "osi/include/list.h"
48 #include "osi/include/properties.h"
49 #include "btu.h"
50 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
51
52 /*****************************************************************************
53 ** Constants & Macros
54 ******************************************************************************/
55
56 /* cod value for Headsets */
57 #define COD_AV_HEADSETS 0x0404
58 /* for AVRC 1.4 need to change this */
59 #define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
60
61 #define IDX_GET_PLAY_STATUS_RSP 0
62 #define IDX_LIST_APP_ATTR_RSP 1
63 #define IDX_LIST_APP_VALUE_RSP 2
64 #define IDX_GET_CURR_APP_VAL_RSP 3
65 #define IDX_SET_APP_VAL_RSP 4
66 #define IDX_GET_APP_ATTR_TXT_RSP 5
67 #define IDX_GET_APP_VAL_TXT_RSP 6
68 #define IDX_GET_ELEMENT_ATTR_RSP 7
69 #define MAX_VOLUME 128
70 #define MAX_LABEL 16
71 #define MAX_TRANSACTIONS_PER_SESSION 16
72 #define MAX_CMD_QUEUE_LEN 8
73 #define PLAY_STATUS_PLAYING 1
74
75 #define CHECK_RC_CONNECTED \
76 BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
77 if (btif_rc_cb.rc_connected == FALSE) \
78 { \
79 BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
80 return BT_STATUS_NOT_READY; \
81 }
82
83 #define FILL_PDU_QUEUE(index, ctype, label, pending) \
84 { \
85 btif_rc_cb.rc_pdu_info[index].ctype = ctype; \
86 btif_rc_cb.rc_pdu_info[index].label = label; \
87 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
88 }
89
90 #define SEND_METAMSG_RSP(index, avrc_rsp) \
91 { \
92 if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE) \
93 { \
94 BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
95 return BT_STATUS_UNHANDLED; \
96 } \
97 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label, \
98 btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp); \
99 btif_rc_cb.rc_pdu_info[index].ctype = 0; \
100 btif_rc_cb.rc_pdu_info[index].label = 0; \
101 btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE; \
102 }
103
104 /*****************************************************************************
105 ** Local type definitions
106 ******************************************************************************/
107 typedef struct {
108 UINT8 bNotify;
109 UINT8 label;
110 } btif_rc_reg_notifications_t;
111
112 typedef struct
113 {
114 UINT8 label;
115 UINT8 ctype;
116 BOOLEAN is_rsp_pending;
117 } btif_rc_cmd_ctxt_t;
118
119 /* 2 second timeout to get interim response */
120 #define BTIF_TIMEOUT_RC_INTERIM_RSP_MS (2 * 1000)
121 #define BTIF_TIMEOUT_RC_STATUS_CMD_MS (2 * 1000)
122 #define BTIF_TIMEOUT_RC_CONTROL_CMD_MS (2 * 1000)
123
124
125 typedef enum
126 {
127 eNOT_REGISTERED,
128 eREGISTERED,
129 eINTERIM
130 } btif_rc_nfn_reg_status_t;
131
132 typedef struct {
133 UINT8 event_id;
134 UINT8 label;
135 btif_rc_nfn_reg_status_t status;
136 } btif_rc_supported_event_t;
137
138 #define BTIF_RC_STS_TIMEOUT 0xFE
139 typedef struct {
140 UINT8 label;
141 UINT8 pdu_id;
142 } btif_rc_status_cmd_timer_t;
143
144 typedef struct {
145 UINT8 label;
146 UINT8 pdu_id;
147 } btif_rc_control_cmd_timer_t;
148
149 typedef struct {
150 union {
151 btif_rc_status_cmd_timer_t rc_status_cmd;
152 btif_rc_control_cmd_timer_t rc_control_cmd;
153 };
154 } btif_rc_timer_context_t;
155
156 typedef struct {
157 BOOLEAN query_started;
158 UINT8 num_attrs;
159 UINT8 num_ext_attrs;
160
161 UINT8 attr_index;
162 UINT8 ext_attr_index;
163 UINT8 ext_val_index;
164 btrc_player_app_attr_t attrs[AVRC_MAX_APP_ATTR_SIZE];
165 btrc_player_app_ext_attr_t ext_attrs[AVRC_MAX_APP_ATTR_SIZE];
166 } btif_rc_player_app_settings_t;
167
168 /* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single struct */
169 typedef struct {
170 BOOLEAN rc_connected;
171 UINT8 rc_handle;
172 tBTA_AV_FEAT rc_features;
173 BD_ADDR rc_addr;
174 UINT16 rc_pending_play;
175 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
176 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
177 unsigned int rc_volume;
178 uint8_t rc_vol_label;
179 list_t *rc_supported_event_list;
180 btif_rc_player_app_settings_t rc_app_settings;
181 alarm_t *rc_play_status_timer;
182 BOOLEAN rc_features_processed;
183 UINT64 rc_playing_uid;
184 BOOLEAN rc_procedure_complete;
185 } btif_rc_cb_t;
186
187 typedef struct {
188 BOOLEAN in_use;
189 UINT8 lbl;
190 UINT8 handle;
191 btif_rc_timer_context_t txn_timer_context;
192 alarm_t *txn_timer;
193 } rc_transaction_t;
194
195 typedef struct
196 {
197 pthread_mutex_t lbllock;
198 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
199 } rc_device_t;
200
201 rc_device_t device;
202
203 #define MAX_UINPUT_PATHS 3
204 static const char* uinput_dev_path[] =
205 {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
206 static int uinput_fd = -1;
207
208 static int send_event (int fd, uint16_t type, uint16_t code, int32_t value);
209 static void send_key (int fd, uint16_t key, int pressed);
210 static int uinput_driver_check();
211 static int uinput_create(char *name);
212 static int init_uinput (void);
213 static void close_uinput (void);
214 static void sleep_ms(period_ms_t timeout_ms);
215
216 static const struct {
217 const char *name;
218 uint8_t avrcp;
219 uint16_t mapped_id;
220 uint8_t release_quirk;
221 } key_map[] = {
222 { "PLAY", AVRC_ID_PLAY, KEY_PLAYCD, 1 },
223 { "STOP", AVRC_ID_STOP, KEY_STOPCD, 0 },
224 { "PAUSE", AVRC_ID_PAUSE, KEY_PAUSECD, 1 },
225 { "FORWARD", AVRC_ID_FORWARD, KEY_NEXTSONG, 0 },
226 { "BACKWARD", AVRC_ID_BACKWARD, KEY_PREVIOUSSONG, 0 },
227 { "REWIND", AVRC_ID_REWIND, KEY_REWIND, 0 },
228 { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FAST_FORWARD, 0 },
229 { NULL, 0, 0, 0 }
230 };
231
232 static void send_reject_response (UINT8 rc_handle, UINT8 label,
233 UINT8 pdu, UINT8 status);
234 static UINT8 opcode_from_pdu(UINT8 pdu);
235 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
236 tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
237 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
238 static void register_volumechange(UINT8 label);
239 #endif
240 static void lbl_init();
241 static void lbl_destroy();
242 static void init_all_transactions();
243 static bt_status_t get_transaction(rc_transaction_t **ptransaction);
244 static void release_transaction(UINT8 label);
245 static rc_transaction_t* get_transaction_by_lbl(UINT8 label);
246 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
247 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
248 #endif
249 #if (AVRC_CTLR_INCLUDED == TRUE)
250 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg);
251 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
252 static void btif_rc_ctrl_upstreams_rsp_cmd(
253 UINT8 event, tAVRC_COMMAND *pavrc_cmd, UINT8 label);
254 static void rc_ctrl_procedure_complete();
255 static void rc_stop_play_status_timer();
256 static void register_for_event_notification (btif_rc_supported_event_t *p_event);
257 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp);
258 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp);
259 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp);
260 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp);
261 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
262 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
263 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp);
264 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
265 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
266 static bt_status_t get_play_status_cmd(void);
267 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
268 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
269 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
270 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
271 static bt_status_t getcapabilities_cmd (uint8_t cap_id);
272 static bt_status_t list_player_app_setting_attrib_cmd(void);
273 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
274 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
275 #endif
276 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
277 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
278 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
279 #endif
280 static void rc_start_play_status_timer(void);
281 static bool absolute_volume_disabled(void);
282
283 /*****************************************************************************
284 ** Static variables
285 ******************************************************************************/
286 static btif_rc_cb_t btif_rc_cb;
287 static btrc_callbacks_t *bt_rc_callbacks = NULL;
288 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
289
290 /*****************************************************************************
291 ** Static functions
292 ******************************************************************************/
293
294 /*****************************************************************************
295 ** Externs
296 ******************************************************************************/
297 extern BOOLEAN btif_hf_call_terminated_recently();
298 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
299
300 extern fixed_queue_t *btu_general_alarm_queue;
301
302 /*****************************************************************************
303 ** Functions
304 ******************************************************************************/
305
306 /*****************************************************************************
307 ** Local uinput helper functions
308 ******************************************************************************/
send_event(int fd,uint16_t type,uint16_t code,int32_t value)309 int send_event (int fd, uint16_t type, uint16_t code, int32_t value)
310 {
311 struct uinput_event event;
312 BTIF_TRACE_DEBUG("%s type:%u code:%u value:%d", __FUNCTION__,
313 type, code, value);
314 memset(&event, 0, sizeof(event));
315 event.type = type;
316 event.code = code;
317 event.value = value;
318
319 ssize_t ret;
320 OSI_NO_INTR(ret = write(fd, &event, sizeof(event)));
321 return (int)ret;
322 }
323
send_key(int fd,uint16_t key,int pressed)324 void send_key (int fd, uint16_t key, int pressed)
325 {
326 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
327 fd, key, pressed);
328
329 if (fd < 0)
330 {
331 return;
332 }
333
334 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
335 send_event(fd, EV_KEY, key, pressed);
336 send_event(fd, EV_SYN, SYN_REPORT, 0);
337 }
338
339 /************** uinput related functions **************/
uinput_driver_check()340 int uinput_driver_check()
341 {
342 uint32_t i;
343 for (i=0; i < MAX_UINPUT_PATHS; i++)
344 {
345 if (access(uinput_dev_path[i], O_RDWR) == 0) {
346 return 0;
347 }
348 }
349 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
350 return -1;
351 }
352
uinput_create(char * name)353 int uinput_create(char *name)
354 {
355 struct uinput_dev dev;
356 int fd, x = 0;
357
358 for(x=0; x < MAX_UINPUT_PATHS; x++)
359 {
360 fd = open(uinput_dev_path[x], O_RDWR);
361 if (fd < 0)
362 continue;
363 break;
364 }
365 if (x == MAX_UINPUT_PATHS) {
366 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
367 return -1;
368 }
369 memset(&dev, 0, sizeof(dev));
370 if (name)
371 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
372
373 dev.id.bustype = BUS_BLUETOOTH;
374 dev.id.vendor = 0x0000;
375 dev.id.product = 0x0000;
376 dev.id.version = 0x0000;
377
378 ssize_t ret;
379 OSI_NO_INTR(ret = write(fd, &dev, sizeof(dev)));
380 if (ret < 0) {
381 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
382 close(fd);
383 return -1;
384 }
385
386 ioctl(fd, UI_SET_EVBIT, EV_KEY);
387 ioctl(fd, UI_SET_EVBIT, EV_REL);
388 ioctl(fd, UI_SET_EVBIT, EV_SYN);
389
390 for (x = 0; key_map[x].name != NULL; x++)
391 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
392
393 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
394 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
395 close(fd);
396 return -1;
397 }
398 return fd;
399 }
400
init_uinput(void)401 int init_uinput (void)
402 {
403 char *name = "AVRCP";
404
405 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
406 uinput_fd = uinput_create(name);
407 if (uinput_fd < 0) {
408 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
409 __FUNCTION__, name, uinput_fd);
410 } else {
411 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
412 __FUNCTION__, name, uinput_fd);
413 }
414 return uinput_fd;
415 }
416
close_uinput(void)417 void close_uinput (void)
418 {
419 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
420 if (uinput_fd > 0) {
421 ioctl(uinput_fd, UI_DEV_DESTROY);
422
423 close(uinput_fd);
424 uinput_fd = -1;
425 }
426 }
427
428 #if (AVRC_CTLR_INCLUDED == TRUE)
rc_cleanup_sent_cmd(void * p_data)429 void rc_cleanup_sent_cmd (void *p_data)
430 {
431 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
432
433 }
434
handle_rc_ctrl_features(BD_ADDR bd_addr)435 void handle_rc_ctrl_features(BD_ADDR bd_addr)
436 {
437 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
438 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
439 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
440 {
441 bt_bdaddr_t rc_addr;
442 int rc_features = 0;
443 bdcpy(rc_addr.address,bd_addr);
444
445 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
446 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
447 {
448 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
449 }
450 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
451 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
452 (btif_rc_cb.rc_features_processed != TRUE))
453 {
454 rc_features |= BTRC_FEAT_METADATA;
455 /* Mark rc features processed to avoid repeating
456 * the AVRCP procedure every time on receiving this
457 * update.
458 */
459 btif_rc_cb.rc_features_processed = TRUE;
460
461 if (btif_av_is_sink_enabled())
462 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
463 }
464 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
465 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
466 }
467 }
468 #endif
469
handle_rc_features(BD_ADDR bd_addr)470 void handle_rc_features(BD_ADDR bd_addr)
471 {
472 if (bt_rc_callbacks != NULL)
473 {
474 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
475 bt_bdaddr_t rc_addr;
476
477 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
478 bt_bdaddr_t avdtp_addr = btif_av_get_addr();
479
480 bdstr_t addr1, addr2;
481 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
482 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
483 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
484
485 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
486 || absolute_volume_disabled()
487 || bdcmp(avdtp_addr.address, rc_addr.address))
488 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
489
490 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
491 {
492 rc_features |= BTRC_FEAT_BROWSE;
493 }
494
495 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
496 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
497 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
498 {
499 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
500 }
501 #endif
502
503 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
504 {
505 rc_features |= BTRC_FEAT_METADATA;
506 }
507
508 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
509 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
510
511 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
512 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
513 __FUNCTION__, btif_rc_cb.rc_vol_label);
514 // Register for volume change on connect
515 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
516 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
517 {
518 rc_transaction_t *p_transaction=NULL;
519 bt_status_t status = BT_STATUS_NOT_READY;
520 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
521 {
522 status=get_transaction(&p_transaction);
523 }
524 else
525 {
526 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
527 if (NULL!=p_transaction)
528 {
529 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
530 __FUNCTION__, btif_rc_cb.rc_vol_label);
531 return;
532 }
533 else
534 status=get_transaction(&p_transaction);
535 }
536
537 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
538 {
539 btif_rc_cb.rc_vol_label=p_transaction->lbl;
540 register_volumechange(btif_rc_cb.rc_vol_label);
541 }
542 }
543 #endif
544 }
545 }
546
547 /***************************************************************************
548 * Function handle_rc_connect
549 *
550 * - Argument: tBTA_AV_RC_OPEN RC open data structure
551 *
552 * - Description: RC connection event handler
553 *
554 ***************************************************************************/
handle_rc_connect(tBTA_AV_RC_OPEN * p_rc_open)555 void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
556 {
557 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
558 bt_status_t result = BT_STATUS_SUCCESS;
559 #if (AVRC_CTLR_INCLUDED == TRUE)
560 bt_bdaddr_t rc_addr;
561 #endif
562
563 if (p_rc_open->status == BTA_AV_SUCCESS)
564 {
565 //check if already some RC is connected
566 if (btif_rc_cb.rc_connected)
567 {
568 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
569 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
570 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
571 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
572 {
573 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
574 BTA_AvCloseRc(p_rc_open->rc_handle);
575 return;
576 }
577 }
578 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
579 btif_rc_cb.rc_features = p_rc_open->peer_features;
580 btif_rc_cb.rc_vol_label=MAX_LABEL;
581 btif_rc_cb.rc_volume=MAX_VOLUME;
582
583 btif_rc_cb.rc_connected = TRUE;
584 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
585
586 /* on locally initiated connection we will get remote features as part of connect */
587 if (btif_rc_cb.rc_features != 0)
588 handle_rc_features(btif_rc_cb.rc_addr);
589 if (bt_rc_callbacks)
590 {
591 result = uinput_driver_check();
592 if (result == BT_STATUS_SUCCESS)
593 {
594 init_uinput();
595 }
596 }
597 else
598 {
599 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
600 __FUNCTION__);
601 }
602 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
603 #if (AVRC_CTLR_INCLUDED == TRUE)
604 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
605 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
606 if (bt_rc_ctrl_callbacks != NULL)
607 {
608 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
609 }
610 /* report connection state if remote device is AVRCP target */
611 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
612 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
613 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
614 {
615 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
616 }
617 #endif
618 }
619 else
620 {
621 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
622 __FUNCTION__, p_rc_open->status);
623 btif_rc_cb.rc_connected = FALSE;
624 }
625 }
626
627 /***************************************************************************
628 * Function handle_rc_disconnect
629 *
630 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
631 *
632 * - Description: RC disconnection event handler
633 *
634 ***************************************************************************/
handle_rc_disconnect(tBTA_AV_RC_CLOSE * p_rc_close)635 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
636 {
637 #if (AVRC_CTLR_INCLUDED == TRUE)
638 bt_bdaddr_t rc_addr;
639 tBTA_AV_FEAT features;
640 #endif
641 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
642 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
643 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
644 {
645 BTIF_TRACE_ERROR("Got disconnect of unknown device");
646 return;
647 }
648 #if (AVRC_CTLR_INCLUDED == TRUE)
649 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
650 features = btif_rc_cb.rc_features;
651 /* Clean up AVRCP procedure flags */
652 memset(&btif_rc_cb.rc_app_settings, 0,
653 sizeof(btif_rc_player_app_settings_t));
654 btif_rc_cb.rc_features_processed = FALSE;
655 btif_rc_cb.rc_procedure_complete = FALSE;
656 rc_stop_play_status_timer();
657 /* Check and clear the notification event list */
658 if (btif_rc_cb.rc_supported_event_list != NULL)
659 {
660 list_clear(btif_rc_cb.rc_supported_event_list);
661 btif_rc_cb.rc_supported_event_list = NULL;
662 }
663 #endif
664 btif_rc_cb.rc_handle = 0;
665 btif_rc_cb.rc_connected = FALSE;
666 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
667 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
668
669 btif_rc_cb.rc_features = 0;
670 btif_rc_cb.rc_vol_label=MAX_LABEL;
671 btif_rc_cb.rc_volume=MAX_VOLUME;
672 init_all_transactions();
673 if (bt_rc_callbacks != NULL)
674 {
675 close_uinput();
676 }
677 else
678 {
679 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
680 }
681
682 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
683 #if (AVRC_CTLR_INCLUDED == TRUE)
684 /* report connection state if device is AVRCP target */
685 if (bt_rc_ctrl_callbacks != NULL)
686 {
687 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
688 }
689 #endif
690 }
691
692 /***************************************************************************
693 * Function handle_rc_passthrough_cmd
694 *
695 * - Argument: tBTA_AV_RC rc_id remote control command ID
696 * tBTA_AV_STATE key_state status of key press
697 *
698 * - Description: Remote control command handler
699 *
700 ***************************************************************************/
handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD * p_remote_cmd)701 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
702 {
703 const char *status;
704 int pressed, i;
705
706 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
707
708 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
709 if (p_remote_cmd)
710 {
711 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
712 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
713 {
714 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
715 {
716 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
717 btif_rc_cb.rc_pending_play = TRUE;
718 }
719 return;
720 }
721
722 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
723 {
724 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
725 btif_rc_cb.rc_pending_play = FALSE;
726 return;
727 }
728 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
729 return; // this command is not to be sent to UINPUT, only needed for PTS
730 }
731
732 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
733 {
734 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
735 return;
736 }
737
738 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
739 status = "released";
740 pressed = 0;
741 } else {
742 status = "pressed";
743 pressed = 1;
744 }
745
746 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
747 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
748 return;
749 }
750
751 for (i = 0; key_map[i].name != NULL; i++) {
752 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
753 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
754
755 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
756 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
757 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
758 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
759 * The fix is to generate a release right after the press and drown the 'actual'
760 * release.
761 */
762 if ((key_map[i].release_quirk == 1) && (pressed == 0))
763 {
764 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
765 __FUNCTION__, key_map[i].name);
766 return;
767 }
768 send_key(uinput_fd, key_map[i].mapped_id, pressed);
769 if ((key_map[i].release_quirk == 1) && (pressed == 1))
770 {
771 sleep_ms(30);
772 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
773 __FUNCTION__, key_map[i].name);
774 send_key(uinput_fd, key_map[i].mapped_id, 0);
775 }
776 break;
777 }
778 }
779
780 if (key_map[i].name == NULL)
781 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
782 p_remote_cmd->rc_id, status);
783 }
784
785 /***************************************************************************
786 * Function handle_rc_passthrough_rsp
787 *
788 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
789 *
790 * - Description: Remote control passthrough response handler
791 *
792 ***************************************************************************/
handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)793 void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
794 {
795 #if (AVRC_CTLR_INCLUDED == TRUE)
796 const char *status;
797 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
798 {
799 int key_state;
800 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
801 {
802 status = "released";
803 key_state = 1;
804 }
805 else
806 {
807 status = "pressed";
808 key_state = 0;
809 }
810
811 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
812
813 release_transaction(p_remote_rsp->label);
814 if (bt_rc_ctrl_callbacks != NULL) {
815 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
816 }
817 }
818 else
819 {
820 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
821 }
822 #else
823 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
824 #endif
825 }
826
827 /***************************************************************************
828 * Function handle_rc_vendorunique_rsp
829 *
830 * - Argument: tBTA_AV_REMOTE_RSP command response
831 *
832 * - Description: Remote control vendor unique response handler
833 *
834 ***************************************************************************/
handle_rc_vendorunique_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)835 void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
836 {
837 #if (AVRC_CTLR_INCLUDED == TRUE)
838 const char *status;
839 UINT8 vendor_id = 0;
840 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
841 {
842 int key_state;
843 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
844 {
845 status = "released";
846 key_state = 1;
847 }
848 else
849 {
850 status = "pressed";
851 key_state = 0;
852 }
853
854 if (p_remote_rsp->len > 0)
855 {
856 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
857 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
858 osi_free_and_reset((void **)&p_remote_rsp->p_data);
859 }
860 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
861
862 release_transaction(p_remote_rsp->label);
863 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
864 }
865 else
866 {
867 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
868 }
869 #else
870 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
871 #endif
872 }
873
handle_uid_changed_notification(tBTA_AV_META_MSG * pmeta_msg,tAVRC_COMMAND * pavrc_command)874 void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
875 {
876 tAVRC_RESPONSE avrc_rsp = {0};
877 avrc_rsp.rsp.pdu = pavrc_command->pdu;
878 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
879 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
880
881 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
882 avrc_rsp.reg_notif.param.uid_counter = 0;
883
884 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
885 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
886
887 }
888
889 /***************************************************************************
890 * Function handle_rc_metamsg_cmd
891 *
892 * - Argument: tBTA_AV_VENDOR Structure containing the received
893 * metamsg command
894 *
895 * - Description: Remote control metamsg command handler (AVRCP 1.3)
896 *
897 ***************************************************************************/
handle_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)898 void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
899 {
900 /* Parse the metamsg command and pass it on to BTL-IFS */
901 UINT8 scratch_buf[512] = {0};
902 tAVRC_COMMAND avrc_command = {0};
903 tAVRC_STS status;
904
905 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
906
907 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
908 {
909 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
910 return;
911 }
912 if (pmeta_msg->len < 3)
913 {
914 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
915 pmeta_msg->len);
916 return;
917 }
918
919 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
920 {
921 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
922 {
923 rc_transaction_t *transaction=NULL;
924 transaction=get_transaction_by_lbl(pmeta_msg->label);
925 if (NULL!=transaction)
926 {
927 handle_rc_metamsg_rsp(pmeta_msg);
928 }
929 else
930 {
931 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
932 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
933 }
934 return;
935 }
936 #else
937 {
938 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
939 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
940 return;
941 }
942 #endif
943 }
944
945 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
946 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
947 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
948
949 if (status != AVRC_STS_NO_ERROR)
950 {
951 /* return error */
952 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
953 __FUNCTION__, status);
954 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
955 }
956 else
957 {
958 /* if RegisterNotification, add it to our registered queue */
959
960 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
961 {
962 UINT8 event_id = avrc_command.reg_notif.event_id;
963 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
964 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
965 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
966 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
967
968 if (event_id == AVRC_EVT_UIDS_CHANGE)
969 {
970 handle_uid_changed_notification(pmeta_msg, &avrc_command);
971 return;
972 }
973
974 }
975
976 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
977 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
978
979 /* Since handle_rc_metamsg_cmd() itself is called from
980 *btif context, no context switching is required. Invoke
981 * btif_rc_upstreams_evt directly from here. */
982 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
983 pmeta_msg->label);
984 }
985 }
986
987 /***************************************************************************
988 **
989 ** Function btif_rc_handler
990 **
991 ** Description RC event handler
992 **
993 ***************************************************************************/
btif_rc_handler(tBTA_AV_EVT event,tBTA_AV * p_data)994 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
995 {
996 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
997 switch (event)
998 {
999 case BTA_AV_RC_OPEN_EVT:
1000 {
1001 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
1002 handle_rc_connect( &(p_data->rc_open) );
1003 }break;
1004
1005 case BTA_AV_RC_CLOSE_EVT:
1006 {
1007 handle_rc_disconnect( &(p_data->rc_close) );
1008 }break;
1009
1010 case BTA_AV_REMOTE_CMD_EVT:
1011 {
1012 if (bt_rc_callbacks != NULL)
1013 {
1014 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1015 __FUNCTION__, p_data->remote_cmd.rc_id,
1016 p_data->remote_cmd.key_state);
1017 /** In race conditions just after 2nd AVRCP is connected
1018 * remote might send pass through commands, so check for
1019 * Rc handle before processing pass through commands
1020 **/
1021 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1022 {
1023 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1024 }
1025 else
1026 {
1027 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1028 }
1029 }
1030 else
1031 {
1032 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1033 }
1034 }
1035 break;
1036
1037 #if (AVRC_CTLR_INCLUDED == TRUE)
1038 case BTA_AV_REMOTE_RSP_EVT:
1039 {
1040 BTIF_TRACE_DEBUG("%s RSP: rc_id:0x%x key_state:%d",
1041 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1042 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1043 {
1044 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1045 }
1046 else
1047 {
1048 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1049 }
1050 }
1051 break;
1052
1053 #endif
1054 case BTA_AV_RC_FEAT_EVT:
1055 {
1056 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
1057 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
1058 handle_rc_features(p_data->rc_feat.peer_addr);
1059 #if (AVRC_CTLR_INCLUDED == TRUE)
1060 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1061 {
1062 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1063 }
1064 #endif
1065 }
1066 break;
1067
1068 case BTA_AV_META_MSG_EVT:
1069 {
1070 if (bt_rc_callbacks != NULL)
1071 {
1072 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1073 __FUNCTION__,
1074 p_data->meta_msg.code,
1075 p_data->meta_msg.label);
1076 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1077 __FUNCTION__,
1078 p_data->meta_msg.company_id,
1079 p_data->meta_msg.len,
1080 p_data->meta_msg.rc_handle);
1081 /* handle the metamsg command */
1082 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1083 /* Free the Memory allocated for tAVRC_MSG */
1084 }
1085 #if (AVRC_CTLR_INCLUDED == TRUE)
1086 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1087 {
1088 /* This is case of Sink + CT + TG(for abs vol)) */
1089 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1090 __FUNCTION__,
1091 p_data->meta_msg.code,
1092 p_data->meta_msg.label);
1093 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1094 __FUNCTION__,
1095 p_data->meta_msg.company_id,
1096 p_data->meta_msg.len,
1097 p_data->meta_msg.rc_handle);
1098 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1099 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1100 {
1101 /* Its a response */
1102 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1103 }
1104 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1105 {
1106 /* Its a command */
1107 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1108 }
1109
1110 }
1111 #endif
1112 else
1113 {
1114 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1115 }
1116 }
1117 break;
1118
1119 default:
1120 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
1121 }
1122 }
1123
1124 /***************************************************************************
1125 **
1126 ** Function btif_rc_get_connected_peer
1127 **
1128 ** Description Fetches the connected headset's BD_ADDR if any
1129 **
1130 ***************************************************************************/
btif_rc_get_connected_peer(BD_ADDR peer_addr)1131 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1132 {
1133 if (btif_rc_cb.rc_connected == TRUE) {
1134 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1135 return TRUE;
1136 }
1137 return FALSE;
1138 }
1139
1140 /***************************************************************************
1141 **
1142 ** Function btif_rc_get_connected_peer_handle
1143 **
1144 ** Description Fetches the connected headset's handle if any
1145 **
1146 ***************************************************************************/
btif_rc_get_connected_peer_handle(void)1147 UINT8 btif_rc_get_connected_peer_handle(void)
1148 {
1149 return btif_rc_cb.rc_handle;
1150 }
1151
1152 /***************************************************************************
1153 **
1154 ** Function btif_rc_check_handle_pending_play
1155 **
1156 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1157 **
1158 ***************************************************************************/
1159
1160 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
btif_rc_check_handle_pending_play(BD_ADDR peer_addr,BOOLEAN bSendToApp)1161 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1162 {
1163 UNUSED(peer_addr);
1164
1165 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
1166 if (btif_rc_cb.rc_pending_play)
1167 {
1168 if (bSendToApp)
1169 {
1170 tBTA_AV_REMOTE_CMD remote_cmd;
1171 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
1172
1173 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1174 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1175 remote_cmd.rc_id = AVRC_ID_PLAY;
1176 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1177 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1178
1179 /* delay sending to app, else there is a timing issue in the framework,
1180 ** which causes the audio to be on th device's speaker. Delay between
1181 ** OPEN & RC_PLAYs
1182 */
1183 sleep_ms(200);
1184 /* send to app - both PRESSED & RELEASED */
1185 remote_cmd.key_state = AVRC_STATE_PRESS;
1186 handle_rc_passthrough_cmd( &remote_cmd );
1187
1188 sleep_ms(100);
1189
1190 remote_cmd.key_state = AVRC_STATE_RELEASE;
1191 handle_rc_passthrough_cmd( &remote_cmd );
1192 }
1193 btif_rc_cb.rc_pending_play = FALSE;
1194 }
1195 }
1196
1197 /* Generic reject response */
send_reject_response(UINT8 rc_handle,UINT8 label,UINT8 pdu,UINT8 status)1198 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1199 {
1200 UINT8 ctype = AVRC_RSP_REJ;
1201 tAVRC_RESPONSE avrc_rsp;
1202 BT_HDR *p_msg = NULL;
1203 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1204
1205 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1206 avrc_rsp.rsp.pdu = pdu;
1207 avrc_rsp.rsp.status = status;
1208
1209 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1210 {
1211 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
1212 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1213 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1214 }
1215 }
1216
1217 /***************************************************************************
1218 * Function send_metamsg_rsp
1219 *
1220 * - Argument:
1221 * rc_handle RC handle corresponding to the connected RC
1222 * label Label of the RC response
1223 * code Response type
1224 * pmetamsg_resp Vendor response
1225 *
1226 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1227 *
1228 ***************************************************************************/
send_metamsg_rsp(UINT8 rc_handle,UINT8 label,tBTA_AV_CODE code,tAVRC_RESPONSE * pmetamsg_resp)1229 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1230 tAVRC_RESPONSE *pmetamsg_resp)
1231 {
1232 UINT8 ctype;
1233
1234 if (!pmetamsg_resp)
1235 {
1236 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
1237 return;
1238 }
1239
1240 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
1241 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1242
1243 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1244 {
1245 ctype = AVRC_RSP_REJ;
1246 }
1247 else
1248 {
1249 if ( code < AVRC_RSP_NOT_IMPL)
1250 {
1251 if (code == AVRC_CMD_NOTIF)
1252 {
1253 ctype = AVRC_RSP_INTERIM;
1254 }
1255 else if (code == AVRC_CMD_STATUS)
1256 {
1257 ctype = AVRC_RSP_IMPL_STBL;
1258 }
1259 else
1260 {
1261 ctype = AVRC_RSP_ACCEPT;
1262 }
1263 }
1264 else
1265 {
1266 ctype = code;
1267 }
1268 }
1269 /* if response is for register_notification, make sure the rc has
1270 actually registered for this */
1271 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
1272 {
1273 BOOLEAN bSent = FALSE;
1274 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1275 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1276
1277 /* de-register this notification for a CHANGED response */
1278 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
1279 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
1280 btif_rc_cb.rc_handle, event_id, bNotify);
1281 if (bNotify)
1282 {
1283 BT_HDR *p_msg = NULL;
1284 tAVRC_STS status;
1285
1286 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1287 pmetamsg_resp, &p_msg)) )
1288 {
1289 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
1290 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1291 bSent = TRUE;
1292 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1293 ctype, p_msg);
1294 }
1295 else
1296 {
1297 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
1298 __FUNCTION__, status);
1299 }
1300
1301 }
1302
1303 if (!bSent)
1304 {
1305 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
1306 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1307 }
1308 }
1309 else
1310 {
1311 /* All other commands go here */
1312
1313 BT_HDR *p_msg = NULL;
1314 tAVRC_STS status;
1315
1316 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1317
1318 if (status == AVRC_STS_NO_ERROR)
1319 {
1320 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1321 }
1322 else
1323 {
1324 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
1325 __FUNCTION__, status);
1326 }
1327 }
1328 }
1329
opcode_from_pdu(UINT8 pdu)1330 static UINT8 opcode_from_pdu(UINT8 pdu)
1331 {
1332 UINT8 opcode = 0;
1333
1334 switch (pdu)
1335 {
1336 case AVRC_PDU_NEXT_GROUP:
1337 case AVRC_PDU_PREV_GROUP: /* pass thru */
1338 opcode = AVRC_OP_PASS_THRU;
1339 break;
1340
1341 default: /* vendor */
1342 opcode = AVRC_OP_VENDOR;
1343 break;
1344 }
1345
1346 return opcode;
1347 }
1348
1349 /*******************************************************************************
1350 **
1351 ** Function btif_rc_upstreams_evt
1352 **
1353 ** Description Executes AVRC UPSTREAMS events in btif context.
1354 **
1355 ** Returns void
1356 **
1357 *******************************************************************************/
btif_rc_upstreams_evt(UINT16 event,tAVRC_COMMAND * pavrc_cmd,UINT8 ctype,UINT8 label)1358 static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1359 {
1360 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1361 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1362
1363 switch (event)
1364 {
1365 case AVRC_PDU_GET_PLAY_STATUS:
1366 {
1367 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1368 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1369 }
1370 break;
1371 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1372 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1373 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1374 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1375 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1376 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1377 {
1378 /* TODO: Add support for Application Settings */
1379 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
1380 }
1381 break;
1382 case AVRC_PDU_GET_ELEMENT_ATTR:
1383 {
1384 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1385 UINT8 num_attr;
1386 memset(&element_attrs, 0, sizeof(element_attrs));
1387 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1388 {
1389 /* CT requests for all attributes */
1390 int attr_cnt;
1391 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1392 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
1393 {
1394 element_attrs[attr_cnt] = attr_cnt + 1;
1395 }
1396 }
1397 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1398 {
1399 /* 0xff indicates, no attributes requested - reject */
1400 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1401 AVRC_STS_BAD_PARAM);
1402 return;
1403 }
1404 else
1405 {
1406 int attr_cnt, filled_attr_count;
1407
1408 num_attr = 0;
1409 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1410 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1411 * Fill only valid entries.
1412 */
1413 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1414 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1415 {
1416 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1417 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1418 {
1419 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1420 */
1421 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1422 {
1423 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1424 break;
1425 }
1426 if (filled_attr_count == num_attr)
1427 {
1428 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1429 num_attr++;
1430 }
1431 }
1432 }
1433 }
1434 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1435 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1436 }
1437 break;
1438 case AVRC_PDU_REGISTER_NOTIFICATION:
1439 {
1440 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
1441 pavrc_cmd->reg_notif.param == 0)
1442 {
1443 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
1444 __FUNCTION__);
1445 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1446 /* de-register this notification for a rejected response */
1447 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1448 return;
1449 }
1450 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1451 pavrc_cmd->reg_notif.param);
1452 }
1453 break;
1454 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1455 {
1456 tAVRC_RESPONSE avrc_rsp;
1457 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
1458 if (btif_rc_cb.rc_connected == TRUE)
1459 {
1460 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1461 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1462 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1463 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1464 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1465 }
1466 }
1467 break;
1468 default:
1469 {
1470 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1471 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1472 return;
1473 }
1474 break;
1475 }
1476 }
1477
1478 #if (AVRC_CTLR_INCLUDED == TRUE)
1479 /*******************************************************************************
1480 **
1481 ** Function btif_rc_ctrl_upstreams_rsp_cmd
1482 **
1483 ** Description Executes AVRC UPSTREAMS response events in btif context.
1484 **
1485 ** Returns void
1486 **
1487 *******************************************************************************/
btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event,tAVRC_COMMAND * pavrc_cmd,UINT8 label)1488 static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1489 UINT8 label)
1490 {
1491 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1492 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1493 bt_bdaddr_t rc_addr;
1494 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1495 #if (AVRC_CTLR_INCLUDED == TRUE)
1496 switch (event)
1497 {
1498 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1499 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1500 pavrc_cmd->volume.volume, label);
1501 break;
1502 case AVRC_PDU_REGISTER_NOTIFICATION:
1503 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1504 {
1505 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1506 &rc_addr, label);
1507 }
1508 break;
1509 }
1510 #endif
1511 }
1512 #endif
1513
1514 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1515 /*******************************************************************************
1516 **
1517 ** Function btif_rc_upstreams_rsp_evt
1518 **
1519 ** Description Executes AVRC UPSTREAMS response events in btif context.
1520 **
1521 ** Returns void
1522 **
1523 *******************************************************************************/
btif_rc_upstreams_rsp_evt(UINT16 event,tAVRC_RESPONSE * pavrc_resp,UINT8 ctype,UINT8 label)1524 static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1525 {
1526 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
1527 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1528
1529 switch (event)
1530 {
1531 case AVRC_PDU_REGISTER_NOTIFICATION:
1532 {
1533 if (AVRC_RSP_CHANGED==ctype)
1534 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1535 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1536 }
1537 break;
1538
1539 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1540 {
1541 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1542 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1543 if (AVRC_RSP_ACCEPT==ctype)
1544 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1545 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1546 }
1547 break;
1548
1549 default:
1550 return;
1551 }
1552 }
1553 #endif
1554
1555 /************************************************************************************
1556 ** AVRCP API Functions
1557 ************************************************************************************/
1558
1559 /*******************************************************************************
1560 **
1561 ** Function init
1562 **
1563 ** Description Initializes the AVRC interface
1564 **
1565 ** Returns bt_status_t
1566 **
1567 *******************************************************************************/
init(btrc_callbacks_t * callbacks)1568 static bt_status_t init(btrc_callbacks_t* callbacks )
1569 {
1570 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1571 bt_status_t result = BT_STATUS_SUCCESS;
1572
1573 if (bt_rc_callbacks)
1574 return BT_STATUS_DONE;
1575
1576 bt_rc_callbacks = callbacks;
1577 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1578 btif_rc_cb.rc_vol_label=MAX_LABEL;
1579 btif_rc_cb.rc_volume=MAX_VOLUME;
1580 lbl_init();
1581
1582 return result;
1583 }
1584
1585 /*******************************************************************************
1586 **
1587 ** Function init_ctrl
1588 **
1589 ** Description Initializes the AVRC interface
1590 **
1591 ** Returns bt_status_t
1592 **
1593 *******************************************************************************/
init_ctrl(btrc_ctrl_callbacks_t * callbacks)1594 static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1595 {
1596 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
1597 bt_status_t result = BT_STATUS_SUCCESS;
1598
1599 if (bt_rc_ctrl_callbacks)
1600 return BT_STATUS_DONE;
1601
1602 bt_rc_ctrl_callbacks = callbacks;
1603 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1604 btif_rc_cb.rc_vol_label=MAX_LABEL;
1605 btif_rc_cb.rc_volume=MAX_VOLUME;
1606 lbl_init();
1607
1608 return result;
1609 }
1610
rc_ctrl_procedure_complete()1611 static void rc_ctrl_procedure_complete ()
1612 {
1613 if (btif_rc_cb.rc_procedure_complete == TRUE)
1614 {
1615 return;
1616 }
1617 btif_rc_cb.rc_procedure_complete = TRUE;
1618 UINT32 attr_list[] = {
1619 AVRC_MEDIA_ATTR_ID_TITLE,
1620 AVRC_MEDIA_ATTR_ID_ARTIST,
1621 AVRC_MEDIA_ATTR_ID_ALBUM,
1622 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1623 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1624 AVRC_MEDIA_ATTR_ID_GENRE,
1625 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1626 };
1627 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1628 }
1629
1630 /***************************************************************************
1631 **
1632 ** Function get_play_status_rsp
1633 **
1634 ** Description Returns the current play status.
1635 ** This method is called in response to
1636 ** GetPlayStatus request.
1637 **
1638 ** Returns bt_status_t
1639 **
1640 ***************************************************************************/
get_play_status_rsp(btrc_play_status_t play_status,uint32_t song_len,uint32_t song_pos)1641 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1642 uint32_t song_pos)
1643 {
1644 tAVRC_RESPONSE avrc_rsp;
1645 CHECK_RC_CONNECTED
1646 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1647 avrc_rsp.get_play_status.song_len = song_len;
1648 avrc_rsp.get_play_status.song_pos = song_pos;
1649 avrc_rsp.get_play_status.play_status = play_status;
1650
1651 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1652 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
1653 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1654 /* Send the response */
1655 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1656 return BT_STATUS_SUCCESS;
1657 }
1658
1659 /***************************************************************************
1660 **
1661 ** Function get_element_attr_rsp
1662 **
1663 ** Description Returns the current songs' element attributes
1664 ** in text.
1665 **
1666 ** Returns bt_status_t
1667 **
1668 ***************************************************************************/
get_element_attr_rsp(uint8_t num_attr,btrc_element_attr_val_t * p_attrs)1669 static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1670 {
1671 tAVRC_RESPONSE avrc_rsp;
1672 UINT32 i;
1673 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1674 CHECK_RC_CONNECTED
1675 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1676
1677 if (num_attr == 0)
1678 {
1679 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1680 }
1681 else
1682 {
1683 for (i=0; i<num_attr; i++) {
1684 element_attrs[i].attr_id = p_attrs[i].attr_id;
1685 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1686 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1687 element_attrs[i].name.p_str = p_attrs[i].text;
1688 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
1689 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1690 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1691 element_attrs[i].name.p_str);
1692 }
1693 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1694 }
1695 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1696 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1697 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1698 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1699 /* Send the response */
1700 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1701 return BT_STATUS_SUCCESS;
1702 }
1703
1704 /***************************************************************************
1705 **
1706 ** Function register_notification_rsp
1707 **
1708 ** Description Response to the register notification request.
1709 ** in text.
1710 **
1711 ** Returns bt_status_t
1712 **
1713 ***************************************************************************/
register_notification_rsp(btrc_event_id_t event_id,btrc_notification_type_t type,btrc_register_notification_t * p_param)1714 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1715 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1716 {
1717 tAVRC_RESPONSE avrc_rsp;
1718 CHECK_RC_CONNECTED
1719 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1720 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1721 {
1722 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
1723 return BT_STATUS_NOT_READY;
1724 }
1725 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1726 avrc_rsp.reg_notif.event_id = event_id;
1727
1728 switch(event_id)
1729 {
1730 case BTRC_EVT_PLAY_STATUS_CHANGED:
1731 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
1732 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1733 btif_av_clear_remote_suspend_flag();
1734 break;
1735 case BTRC_EVT_TRACK_CHANGE:
1736 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1737 break;
1738 case BTRC_EVT_PLAY_POS_CHANGED:
1739 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1740 break;
1741 default:
1742 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1743 return BT_STATUS_UNHANDLED;
1744 }
1745
1746 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1747 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1748 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1749
1750 /* Send the response. */
1751 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1752 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1753 return BT_STATUS_SUCCESS;
1754 }
1755
1756 /***************************************************************************
1757 **
1758 ** Function set_volume
1759 **
1760 ** Description Send current volume setting to remote side.
1761 ** Support limited to SetAbsoluteVolume
1762 ** This can be enhanced to support Relative Volume (AVRCP 1.0).
1763 ** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1764 ** as opposed to absolute volume level
1765 ** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1766 **
1767 ** Returns bt_status_t
1768 **
1769 ***************************************************************************/
set_volume(uint8_t volume)1770 static bt_status_t set_volume(uint8_t volume)
1771 {
1772 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1773 CHECK_RC_CONNECTED
1774 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1775 rc_transaction_t *p_transaction=NULL;
1776
1777 if (btif_rc_cb.rc_volume==volume)
1778 {
1779 status=BT_STATUS_DONE;
1780 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
1781 return status;
1782 }
1783
1784 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1785 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1786 {
1787 tAVRC_COMMAND avrc_cmd = {0};
1788 BT_HDR *p_msg = NULL;
1789
1790 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
1791 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1792 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1793 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1794 avrc_cmd.volume.volume = volume;
1795
1796 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1797 {
1798 bt_status_t tran_status=get_transaction(&p_transaction);
1799 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
1800 {
1801 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
1802 __FUNCTION__,p_transaction->lbl);
1803 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1804 status = BT_STATUS_SUCCESS;
1805 }
1806 else
1807 {
1808 osi_free(p_msg);
1809 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
1810 __FUNCTION__, tran_status);
1811 status = BT_STATUS_FAIL;
1812 }
1813 }
1814 else
1815 {
1816 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
1817 __FUNCTION__, status);
1818 status = BT_STATUS_FAIL;
1819 }
1820 }
1821 else
1822 status=BT_STATUS_NOT_READY;
1823 return status;
1824 }
1825
1826 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1827 /***************************************************************************
1828 **
1829 ** Function register_volumechange
1830 **
1831 ** Description Register for volume change notification from remote side.
1832 **
1833 ** Returns void
1834 **
1835 ***************************************************************************/
1836
register_volumechange(UINT8 lbl)1837 static void register_volumechange (UINT8 lbl)
1838 {
1839 tAVRC_COMMAND avrc_cmd = {0};
1840 BT_HDR *p_msg = NULL;
1841 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
1842 rc_transaction_t *p_transaction=NULL;
1843
1844 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
1845
1846 avrc_cmd.cmd.opcode=0x00;
1847 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1848 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1849 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1850 avrc_cmd.reg_notif.param = 0;
1851
1852 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
1853 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1854 p_transaction = get_transaction_by_lbl(lbl);
1855 if (p_transaction != NULL) {
1856 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1857 AVRC_CMD_NOTIF, p_msg);
1858 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1859 } else {
1860 osi_free(p_msg);
1861 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1862 __func__, lbl);
1863 }
1864 } else {
1865 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
1866 }
1867 }
1868
1869 /***************************************************************************
1870 **
1871 ** Function handle_rc_metamsg_rsp
1872 **
1873 ** Description Handle RC metamessage response
1874 **
1875 ** Returns void
1876 **
1877 ***************************************************************************/
handle_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg)1878 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1879 {
1880 tAVRC_RESPONSE avrc_response = {0};
1881 UINT8 scratch_buf[512] = {0};
1882 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1883
1884 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
1885 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1886 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1887 {
1888 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
1889 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
1890 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1891 status, pmeta_msg->label);
1892
1893 if (status != AVRC_STS_NO_ERROR)
1894 {
1895 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1896 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1897 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1898 {
1899 btif_rc_cb.rc_vol_label=MAX_LABEL;
1900 release_transaction(btif_rc_cb.rc_vol_label);
1901 }
1902 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1903 {
1904 release_transaction(pmeta_msg->label);
1905 }
1906 return;
1907 }
1908 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1909 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1910 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1911 {
1912 // Just discard the message, if the device sends back with an incorrect label
1913 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
1914 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1915 return;
1916 }
1917 }
1918 else
1919 {
1920 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
1921 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1922 return;
1923 }
1924
1925 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
1926 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1927 && AVRC_RSP_CHANGED==pmeta_msg->code)
1928 {
1929 /* re-register for volume change notification */
1930 // Do not re-register for rejected case, as it might get into endless loop
1931 register_volumechange(btif_rc_cb.rc_vol_label);
1932 }
1933 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
1934 {
1935 /* free up the label here */
1936 release_transaction(pmeta_msg->label);
1937 }
1938
1939 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
1940 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1941 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1942 pmeta_msg->label);
1943 }
1944 #endif
1945
1946 #if (AVRC_CTLR_INCLUDED == TRUE)
1947 /***************************************************************************
1948 **
1949 ** Function iterate_supported_event_list_for_interim_rsp
1950 **
1951 ** Description iterator callback function to match the event and handle
1952 ** timer cleanup
1953 ** Returns true to continue iterating, false to stop
1954 **
1955 ***************************************************************************/
iterate_supported_event_list_for_interim_rsp(void * data,void * cb_data)1956 bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1957 {
1958 UINT8 *p_event_id;
1959 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1960
1961 p_event_id = (UINT8*)cb_data;
1962
1963 if (p_event->event_id == *p_event_id)
1964 {
1965 p_event->status = eINTERIM;
1966 return false;
1967 }
1968 return true;
1969 }
1970
1971 /***************************************************************************
1972 **
1973 ** Function iterate_supported_event_list_for_timeout
1974 **
1975 ** Description Iterator callback function for timeout handling.
1976 ** As part of the failure handling, it releases the
1977 ** transaction label and removes the event from list,
1978 ** this event will not be requested again during
1979 ** the lifetime of the connection.
1980 ** Returns false to stop iterating, true to continue
1981 **
1982 ***************************************************************************/
iterate_supported_event_list_for_timeout(void * data,void * cb_data)1983 bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1984 {
1985 UINT8 label;
1986 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1987
1988 label = (*(UINT8*)cb_data) & 0xFF;
1989
1990 if (p_event->label == label)
1991 {
1992 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
1993 return false;
1994 }
1995 return true;
1996 }
1997
1998 /***************************************************************************
1999 **
2000 ** Function rc_notification_interim_timout
2001 **
2002 ** Description Interim response timeout handler.
2003 ** Runs the iterator to check and clear the timed out event.
2004 ** Proceeds to register for the unregistered events.
2005 ** Returns None
2006 **
2007 ***************************************************************************/
rc_notification_interim_timout(UINT8 label)2008 static void rc_notification_interim_timout (UINT8 label)
2009 {
2010 list_node_t *node;
2011
2012 list_foreach(btif_rc_cb.rc_supported_event_list,
2013 iterate_supported_event_list_for_timeout, &label);
2014 /* Timeout happened for interim response for the registered event,
2015 * check if there are any pending for registration
2016 */
2017 node = list_begin(btif_rc_cb.rc_supported_event_list);
2018 while (node != NULL)
2019 {
2020 btif_rc_supported_event_t *p_event;
2021
2022 p_event = (btif_rc_supported_event_t *)list_node(node);
2023 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2024 {
2025 register_for_event_notification(p_event);
2026 break;
2027 }
2028 node = list_next (node);
2029 }
2030 /* Todo. Need to initiate application settings query if this
2031 * is the last event registration.
2032 */
2033 }
2034
2035 /***************************************************************************
2036 **
2037 ** Function btif_rc_status_cmd_timeout_handler
2038 **
2039 ** Description RC status command timeout handler (Runs in BTIF context).
2040 ** Returns None
2041 **
2042 ***************************************************************************/
btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2043 static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2044 char *data)
2045 {
2046 btif_rc_timer_context_t *p_context;
2047 tAVRC_RESPONSE avrc_response = {0};
2048 tBTA_AV_META_MSG meta_msg;
2049
2050 p_context = (btif_rc_timer_context_t *)data;
2051 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2052 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2053
2054 switch (p_context->rc_status_cmd.pdu_id) {
2055 case AVRC_PDU_REGISTER_NOTIFICATION:
2056 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2057 break;
2058
2059 case AVRC_PDU_GET_CAPABILITIES:
2060 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2061 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2062 break;
2063
2064 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2065 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2066 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2067 break;
2068
2069 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2070 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2071 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2072 break;
2073
2074 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2075 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2076 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2077 break;
2078
2079 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2080 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2081 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2082 break;
2083
2084 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2085 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2086 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2087 break;
2088
2089 case AVRC_PDU_GET_ELEMENT_ATTR:
2090 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2091 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2092 break;
2093
2094 case AVRC_PDU_GET_PLAY_STATUS:
2095 avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT;
2096 handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status);
2097 break;
2098 }
2099 release_transaction(p_context->rc_status_cmd.label);
2100 }
2101
2102 /***************************************************************************
2103 **
2104 ** Function btif_rc_status_cmd_timer_timeout
2105 **
2106 ** Description RC status command timeout callback.
2107 ** This is called from BTU context and switches to BTIF
2108 ** context to handle the timeout events
2109 ** Returns None
2110 **
2111 ***************************************************************************/
btif_rc_status_cmd_timer_timeout(void * data)2112 static void btif_rc_status_cmd_timer_timeout(void *data)
2113 {
2114 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2115
2116 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2117 (char *)p_data, sizeof(btif_rc_timer_context_t),
2118 NULL);
2119 }
2120
2121 /***************************************************************************
2122 **
2123 ** Function btif_rc_control_cmd_timeout_handler
2124 **
2125 ** Description RC control command timeout handler (Runs in BTIF context).
2126 ** Returns None
2127 **
2128 ***************************************************************************/
btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,char * data)2129 static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2130 char *data)
2131 {
2132 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2133 tAVRC_RESPONSE avrc_response = {0};
2134 tBTA_AV_META_MSG meta_msg;
2135
2136 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2137 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2138
2139 switch (p_context->rc_control_cmd.pdu_id) {
2140 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2141 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2142 handle_set_app_attr_val_response(&meta_msg,
2143 &avrc_response.set_app_val);
2144 break;
2145 }
2146 release_transaction(p_context->rc_control_cmd.label);
2147 }
2148
2149 /***************************************************************************
2150 **
2151 ** Function btif_rc_control_cmd_timer_timeout
2152 **
2153 ** Description RC control command timeout callback.
2154 ** This is called from BTU context and switches to BTIF
2155 ** context to handle the timeout events
2156 ** Returns None
2157 **
2158 ***************************************************************************/
btif_rc_control_cmd_timer_timeout(void * data)2159 static void btif_rc_control_cmd_timer_timeout(void *data)
2160 {
2161 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2162
2163 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2164 (char *)p_data, sizeof(btif_rc_timer_context_t),
2165 NULL);
2166 }
2167
2168 /***************************************************************************
2169 **
2170 ** Function btif_rc_play_status_timeout_handler
2171 **
2172 ** Description RC play status timeout handler (Runs in BTIF context).
2173 ** Returns None
2174 **
2175 ***************************************************************************/
btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,UNUSED_ATTR char * p_data)2176 static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2177 UNUSED_ATTR char *p_data)
2178 {
2179 get_play_status_cmd();
2180 rc_start_play_status_timer();
2181 }
2182
2183 /***************************************************************************
2184 **
2185 ** Function btif_rc_play_status_timer_timeout
2186 **
2187 ** Description RC play status timeout callback.
2188 ** This is called from BTU context and switches to BTIF
2189 ** context to handle the timeout events
2190 ** Returns None
2191 **
2192 ***************************************************************************/
btif_rc_play_status_timer_timeout(UNUSED_ATTR void * data)2193 static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2194 {
2195 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
2196 }
2197
2198 /***************************************************************************
2199 **
2200 ** Function rc_start_play_status_timer
2201 **
2202 ** Description Helper function to start the timer to fetch play status.
2203 ** Returns None
2204 **
2205 ***************************************************************************/
rc_start_play_status_timer(void)2206 static void rc_start_play_status_timer(void)
2207 {
2208 /* Start the Play status timer only if it is not started */
2209 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2210 if (btif_rc_cb.rc_play_status_timer == NULL) {
2211 btif_rc_cb.rc_play_status_timer =
2212 alarm_new("btif_rc.rc_play_status_timer");
2213 }
2214 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2215 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2216 btif_rc_play_status_timer_timeout, NULL,
2217 btu_general_alarm_queue);
2218 }
2219 }
2220
2221 /***************************************************************************
2222 **
2223 ** Function rc_stop_play_status_timer
2224 **
2225 ** Description Helper function to stop the play status timer.
2226 ** Returns None
2227 **
2228 ***************************************************************************/
rc_stop_play_status_timer()2229 void rc_stop_play_status_timer()
2230 {
2231 if (btif_rc_cb.rc_play_status_timer != NULL)
2232 alarm_cancel(btif_rc_cb.rc_play_status_timer);
2233 }
2234
2235 /***************************************************************************
2236 **
2237 ** Function register_for_event_notification
2238 **
2239 ** Description Helper function registering notification events
2240 ** sets an interim response timeout to handle if the remote
2241 ** does not respond.
2242 ** Returns None
2243 **
2244 ***************************************************************************/
register_for_event_notification(btif_rc_supported_event_t * p_event)2245 static void register_for_event_notification(btif_rc_supported_event_t *p_event)
2246 {
2247 bt_status_t status;
2248 rc_transaction_t *p_transaction;
2249
2250 status = get_transaction(&p_transaction);
2251 if (status == BT_STATUS_SUCCESS)
2252 {
2253 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
2254
2255 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2256 if (status != BT_STATUS_SUCCESS)
2257 {
2258 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2259 __FUNCTION__, status);
2260 release_transaction (p_transaction->lbl);
2261 return;
2262 }
2263 p_event->label = p_transaction->lbl;
2264 p_event->status = eREGISTERED;
2265 p_context->rc_status_cmd.label = p_transaction->lbl;
2266 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2267
2268 alarm_free(p_transaction->txn_timer);
2269 p_transaction->txn_timer =
2270 alarm_new("btif_rc.status_command_txn_timer");
2271 alarm_set_on_queue(p_transaction->txn_timer,
2272 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2273 btif_rc_status_cmd_timer_timeout, p_context,
2274 btu_general_alarm_queue);
2275 }
2276 else
2277 {
2278 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2279 __FUNCTION__, status);
2280 }
2281 }
2282
start_status_command_timer(UINT8 pdu_id,rc_transaction_t * p_txn)2283 static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2284 {
2285 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2286 p_context->rc_status_cmd.label = p_txn->lbl;
2287 p_context->rc_status_cmd.pdu_id = pdu_id;
2288
2289 alarm_free(p_txn->txn_timer);
2290 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2291 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2292 btif_rc_status_cmd_timer_timeout, p_context,
2293 btu_general_alarm_queue);
2294 }
2295
start_control_command_timer(UINT8 pdu_id,rc_transaction_t * p_txn)2296 static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
2297 {
2298 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2299 p_context->rc_control_cmd.label = p_txn->lbl;
2300 p_context->rc_control_cmd.pdu_id = pdu_id;
2301
2302 alarm_free(p_txn->txn_timer);
2303 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2304 alarm_set_on_queue(p_txn->txn_timer,
2305 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2306 btif_rc_control_cmd_timer_timeout, p_context,
2307 btu_general_alarm_queue);
2308 }
2309
2310 /***************************************************************************
2311 **
2312 ** Function handle_get_capability_response
2313 **
2314 ** Description Handles the get_cap_response to populate company id info
2315 ** and query the supported events.
2316 ** Initiates Notification registration for events supported
2317 ** Returns None
2318 **
2319 ***************************************************************************/
handle_get_capability_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CAPS_RSP * p_rsp)2320 static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2321 {
2322 int xx = 0;
2323
2324 /* Todo: Do we need to retry on command timeout */
2325 if (p_rsp->status != AVRC_STS_NO_ERROR)
2326 {
2327 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2328 __FUNCTION__, p_rsp->status);
2329 return;
2330 }
2331
2332 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2333 {
2334 btif_rc_supported_event_t *p_event;
2335
2336 /* Todo: Check if list can be active when we hit here */
2337 btif_rc_cb.rc_supported_event_list = list_new(osi_free);
2338 for (xx = 0; xx < p_rsp->count; xx++)
2339 {
2340 /* Skip registering for Play position change notification */
2341 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2342 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2343 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2344 {
2345 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
2346 p_event->event_id = p_rsp->param.event_id[xx];
2347 p_event->status = eNOT_REGISTERED;
2348 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2349 }
2350 }
2351 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2352 if (p_event != NULL)
2353 {
2354 register_for_event_notification(p_event);
2355 }
2356 }
2357 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2358 {
2359 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2360 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2361 for (xx = 0; xx < p_rsp->count; xx++)
2362 {
2363 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2364 }
2365 }
2366 }
2367
rc_is_track_id_valid(tAVRC_UID uid)2368 bool rc_is_track_id_valid (tAVRC_UID uid)
2369 {
2370 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2371
2372 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2373 {
2374 return false;
2375 }
2376 else
2377 {
2378 return true;
2379 }
2380 }
2381
2382 /***************************************************************************
2383 **
2384 ** Function handle_notification_response
2385 **
2386 ** Description Main handler for notification responses to registered events
2387 ** 1. Register for unregistered event(in interim response path)
2388 ** 2. After registering for all supported events, start
2389 ** retrieving application settings and values
2390 ** 3. Reregister for events on getting changed response
2391 ** 4. Run play status timer for getting position when the
2392 ** status changes to playing
2393 ** 5. Get the Media details when the track change happens
2394 ** or track change interim response is received with
2395 ** valid track id
2396 ** 6. HAL callback for play status change and application
2397 ** setting change
2398 ** Returns None
2399 **
2400 ***************************************************************************/
handle_notification_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_REG_NOTIF_RSP * p_rsp)2401 static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2402 {
2403 bt_bdaddr_t rc_addr;
2404 UINT32 attr_list[] = {
2405 AVRC_MEDIA_ATTR_ID_TITLE,
2406 AVRC_MEDIA_ATTR_ID_ARTIST,
2407 AVRC_MEDIA_ATTR_ID_ALBUM,
2408 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2409 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2410 AVRC_MEDIA_ATTR_ID_GENRE,
2411 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2412 };
2413
2414
2415 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2416
2417 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2418 {
2419 btif_rc_supported_event_t *p_event;
2420 list_node_t *node;
2421
2422 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2423 switch (p_rsp->event_id)
2424 {
2425 case AVRC_EVT_PLAY_STATUS_CHANGE:
2426 /* Start timer to get play status periodically
2427 * if the play state is playing.
2428 */
2429 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2430 {
2431 rc_start_play_status_timer();
2432 }
2433 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2434 &rc_addr, p_rsp->param.play_status);
2435 break;
2436
2437 case AVRC_EVT_TRACK_CHANGE:
2438 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2439 {
2440 break;
2441 }
2442 else
2443 {
2444 UINT8 *p_data = p_rsp->param.track;
2445 /* Update the UID for current track
2446 * Attributes will be fetched after the AVRCP procedure
2447 */
2448 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2449 }
2450 break;
2451
2452 case AVRC_EVT_APP_SETTING_CHANGE:
2453 break;
2454
2455 case AVRC_EVT_NOW_PLAYING_CHANGE:
2456 break;
2457
2458 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2459 break;
2460
2461 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2462 break;
2463
2464 case AVRC_EVT_UIDS_CHANGE:
2465 break;
2466
2467 case AVRC_EVT_TRACK_REACHED_END:
2468 case AVRC_EVT_TRACK_REACHED_START:
2469 case AVRC_EVT_PLAY_POS_CHANGED:
2470 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2471 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2472 default:
2473 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2474 p_rsp->event_id);
2475 return;
2476 }
2477 list_foreach(btif_rc_cb.rc_supported_event_list,
2478 iterate_supported_event_list_for_interim_rsp,
2479 &p_rsp->event_id);
2480
2481 node = list_begin(btif_rc_cb.rc_supported_event_list);
2482 while (node != NULL)
2483 {
2484 p_event = (btif_rc_supported_event_t *)list_node(node);
2485 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2486 {
2487 register_for_event_notification(p_event);
2488 break;
2489 }
2490 node = list_next (node);
2491 p_event = NULL;
2492 }
2493 /* Registered for all events, we can request application settings */
2494 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2495 {
2496 /* we need to do this only if remote TG supports
2497 * player application settings
2498 */
2499 btif_rc_cb.rc_app_settings.query_started = TRUE;
2500 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2501 {
2502 list_player_app_setting_attrib_cmd();
2503 }
2504 else
2505 {
2506 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2507 rc_ctrl_procedure_complete();
2508 }
2509 }
2510 }
2511 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2512 {
2513 btif_rc_supported_event_t *p_event;
2514 list_node_t *node;
2515
2516 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2517 p_rsp->event_id);
2518
2519 node = list_begin(btif_rc_cb.rc_supported_event_list);
2520 while (node != NULL)
2521 {
2522 p_event = (btif_rc_supported_event_t *)list_node(node);
2523 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2524 {
2525 p_event->status = eNOT_REGISTERED;
2526 register_for_event_notification(p_event);
2527 break;
2528 }
2529 node = list_next (node);
2530 }
2531
2532 switch (p_rsp->event_id)
2533 {
2534 case AVRC_EVT_PLAY_STATUS_CHANGE:
2535 /* Start timer to get play status periodically
2536 * if the play state is playing.
2537 */
2538 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2539 {
2540 rc_start_play_status_timer();
2541 }
2542 else
2543 {
2544 rc_stop_play_status_timer();
2545 }
2546 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2547 &rc_addr, p_rsp->param.play_status);
2548 break;
2549
2550 case AVRC_EVT_TRACK_CHANGE:
2551 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2552 {
2553 break;
2554 }
2555 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2556 break;
2557
2558 case AVRC_EVT_APP_SETTING_CHANGE:
2559 {
2560 btrc_player_settings_t app_settings;
2561 UINT16 xx;
2562
2563 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2564 for (xx = 0; xx < app_settings.num_attr; xx++)
2565 {
2566 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2567 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2568 }
2569 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2570 &rc_addr, &app_settings);
2571 }
2572 break;
2573
2574 case AVRC_EVT_NOW_PLAYING_CHANGE:
2575 break;
2576
2577 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2578 break;
2579
2580 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2581 break;
2582
2583 case AVRC_EVT_UIDS_CHANGE:
2584 break;
2585
2586 case AVRC_EVT_TRACK_REACHED_END:
2587 case AVRC_EVT_TRACK_REACHED_START:
2588 case AVRC_EVT_PLAY_POS_CHANGED:
2589 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2590 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2591 default:
2592 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2593 __FUNCTION__, p_rsp->event_id);
2594 return;
2595 }
2596 }
2597 }
2598
2599 /***************************************************************************
2600 **
2601 ** Function handle_app_attr_response
2602 **
2603 ** Description handles the the application attributes response and
2604 ** initiates procedure to fetch the attribute values
2605 ** Returns None
2606 **
2607 ***************************************************************************/
handle_app_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_ATTR_RSP * p_rsp)2608 static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2609 {
2610 UINT8 xx;
2611
2612 if (p_rsp->status != AVRC_STS_NO_ERROR)
2613 {
2614 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2615 __FUNCTION__, p_rsp->status);
2616 rc_ctrl_procedure_complete();
2617 return;
2618 }
2619
2620 for (xx = 0; xx < p_rsp->num_attr; xx++)
2621 {
2622 UINT8 st_index;
2623
2624 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2625 {
2626 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2627 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2628 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2629 }
2630 else
2631 {
2632 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2633 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2634 btif_rc_cb.rc_app_settings.num_attrs++;
2635 }
2636 }
2637 btif_rc_cb.rc_app_settings.attr_index = 0;
2638 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2639 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2640 if (p_rsp->num_attr)
2641 {
2642 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2643 }
2644 else
2645 {
2646 BTIF_TRACE_ERROR("%s No Player application settings found",
2647 __FUNCTION__);
2648 }
2649 }
2650
2651 /***************************************************************************
2652 **
2653 ** Function handle_app_val_response
2654 **
2655 ** Description handles the the attributes value response and if extended
2656 ** menu is available, it initiates query for the attribute
2657 ** text. If not, it initiates procedure to get the current
2658 ** attribute values and calls the HAL callback for provding
2659 ** application settings information.
2660 ** Returns None
2661 **
2662 ***************************************************************************/
handle_app_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_LIST_APP_VALUES_RSP * p_rsp)2663 static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2664 {
2665 UINT8 xx, attr_index;
2666 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2667 btif_rc_player_app_settings_t *p_app_settings;
2668 bt_bdaddr_t rc_addr;
2669
2670 /* Todo: Do we need to retry on command timeout */
2671 if (p_rsp->status != AVRC_STS_NO_ERROR)
2672 {
2673 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2674 __FUNCTION__, p_rsp->status);
2675 return;
2676 }
2677
2678 p_app_settings = &btif_rc_cb.rc_app_settings;
2679 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2680
2681 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2682 {
2683 attr_index = p_app_settings->attr_index;
2684 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2685 for (xx = 0; xx < p_rsp->num_val; xx++)
2686 {
2687 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2688 }
2689 attr_index++;
2690 p_app_settings->attr_index++;
2691 if (attr_index < p_app_settings->num_attrs)
2692 {
2693 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2694 }
2695 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2696 {
2697 attr_index = 0;
2698 p_app_settings->ext_attr_index = 0;
2699 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2700 }
2701 else
2702 {
2703 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2704 {
2705 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2706 }
2707 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2708 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2709 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2710 }
2711 }
2712 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2713 {
2714 attr_index = p_app_settings->ext_attr_index;
2715 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2716 for (xx = 0; xx < p_rsp->num_val; xx++)
2717 {
2718 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2719 }
2720 attr_index++;
2721 p_app_settings->ext_attr_index++;
2722 if (attr_index < p_app_settings->num_ext_attrs)
2723 {
2724 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2725 }
2726 else
2727 {
2728 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2729 UINT8 xx;
2730
2731 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2732 {
2733 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2734 }
2735 get_player_app_setting_attr_text_cmd(attr, xx);
2736 }
2737 }
2738 }
2739
2740 /***************************************************************************
2741 **
2742 ** Function handle_app_cur_val_response
2743 **
2744 ** Description handles the the get attributes value response.
2745 **
2746 ** Returns None
2747 **
2748 ***************************************************************************/
handle_app_cur_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_CUR_APP_VALUE_RSP * p_rsp)2749 static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2750 {
2751 btrc_player_settings_t app_settings;
2752 bt_bdaddr_t rc_addr;
2753 UINT16 xx;
2754
2755 /* Todo: Do we need to retry on command timeout */
2756 if (p_rsp->status != AVRC_STS_NO_ERROR)
2757 {
2758 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2759 __FUNCTION__, p_rsp->status);
2760 return;
2761 }
2762
2763 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2764
2765 app_settings.num_attr = p_rsp->num_val;
2766 for (xx = 0; xx < app_settings.num_attr; xx++)
2767 {
2768 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2769 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2770 }
2771 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2772 &rc_addr, &app_settings);
2773 /* Application settings are fetched only once for initial values
2774 * initiate anything that follows after RC procedure.
2775 * Defer it if browsing is supported till players query
2776 */
2777 rc_ctrl_procedure_complete ();
2778 osi_free_and_reset((void **)&p_rsp->p_vals);
2779 }
2780
2781 /***************************************************************************
2782 **
2783 ** Function handle_app_attr_txt_response
2784 **
2785 ** Description handles the the get attributes text response, if fails
2786 ** calls HAL callback with just normal settings and initiates
2787 ** query for current settings else initiates query for value text
2788 ** Returns None
2789 **
2790 ***************************************************************************/
handle_app_attr_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)2791 static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2792 {
2793 UINT8 xx;
2794 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2795 btif_rc_player_app_settings_t *p_app_settings;
2796 bt_bdaddr_t rc_addr;
2797
2798 p_app_settings = &btif_rc_cb.rc_app_settings;
2799 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2800
2801 /* Todo: Do we need to retry on command timeout */
2802 if (p_rsp->status != AVRC_STS_NO_ERROR)
2803 {
2804 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2805
2806 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2807 __FUNCTION__, p_rsp->status);
2808 /* Not able to fetch Text for extended Menu, skip the process
2809 * and cleanup used memory. Proceed to get the current settings
2810 * for standard attributes.
2811 */
2812 p_app_settings->num_ext_attrs = 0;
2813 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2814 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2815 p_app_settings->ext_attr_index = 0;
2816
2817 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2818 {
2819 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2820 }
2821 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2822 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2823
2824 get_player_app_setting_cmd (xx, attrs);
2825 return;
2826 }
2827
2828 for (xx = 0; xx < p_rsp->num_attr; xx++)
2829 {
2830 UINT8 x;
2831 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2832 {
2833 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2834 {
2835 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2836 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2837 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2838 break;
2839 }
2840 }
2841 }
2842
2843 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2844 {
2845 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2846 }
2847 get_player_app_setting_value_text_cmd(vals, xx);
2848 }
2849
2850
2851 /***************************************************************************
2852 **
2853 ** Function handle_app_attr_val_txt_response
2854 **
2855 ** Description handles the the get attributes value text response, if fails
2856 ** calls HAL callback with just normal settings and initiates
2857 ** query for current settings
2858 ** Returns None
2859 **
2860 ***************************************************************************/
handle_app_attr_val_txt_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_APP_ATTR_TXT_RSP * p_rsp)2861 static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2862 {
2863 UINT8 xx, attr_index;
2864 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2865 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2866 btif_rc_player_app_settings_t *p_app_settings;
2867 bt_bdaddr_t rc_addr;
2868
2869 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2870 p_app_settings = &btif_rc_cb.rc_app_settings;
2871
2872 /* Todo: Do we need to retry on command timeout */
2873 if (p_rsp->status != AVRC_STS_NO_ERROR)
2874 {
2875 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2876
2877 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2878 __FUNCTION__, p_rsp->status);
2879
2880 /* Not able to fetch Text for extended Menu, skip the process
2881 * and cleanup used memory. Proceed to get the current settings
2882 * for standard attributes.
2883 */
2884 p_app_settings->num_ext_attrs = 0;
2885 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2886 {
2887 int x;
2888 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2889
2890 for (x = 0; x < p_ext_attr->num_val; x++)
2891 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2892 p_ext_attr->num_val = 0;
2893 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2894 }
2895 p_app_settings->ext_attr_index = 0;
2896
2897 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2898 {
2899 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2900 }
2901 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2902 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
2903
2904 get_player_app_setting_cmd (xx, attrs);
2905 return;
2906 }
2907
2908 for (xx = 0; xx < p_rsp->num_attr; xx++)
2909 {
2910 UINT8 x;
2911 btrc_player_app_ext_attr_t *p_ext_attr;
2912 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2913 for (x = 0; x < p_rsp->num_attr; x++)
2914 {
2915 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2916 {
2917 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2918 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2919 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2920 break;
2921 }
2922 }
2923 }
2924 p_app_settings->ext_val_index++;
2925
2926 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2927 {
2928 attr_index = p_app_settings->ext_val_index;
2929 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2930 {
2931 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2932 }
2933 get_player_app_setting_value_text_cmd(vals, xx);
2934 }
2935 else
2936 {
2937 UINT8 x;
2938
2939 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2940 {
2941 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2942 }
2943 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2944 {
2945 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2946 }
2947 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
2948 p_app_settings->num_attrs, p_app_settings->attrs,
2949 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
2950 get_player_app_setting_cmd (xx + x, attrs);
2951
2952 /* Free the application settings information after sending to
2953 * application.
2954 */
2955 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2956 {
2957 int x;
2958 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2959
2960 for (x = 0; x < p_ext_attr->num_val; x++)
2961 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
2962 p_ext_attr->num_val = 0;
2963 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
2964 }
2965 p_app_settings->num_attrs = 0;
2966 }
2967 }
2968
2969 /***************************************************************************
2970 **
2971 ** Function handle_set_app_attr_val_response
2972 **
2973 ** Description handles the the set attributes value response, if fails
2974 ** calls HAL callback to indicate the failure
2975 ** Returns None
2976 **
2977 ***************************************************************************/
handle_set_app_attr_val_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_RSP * p_rsp)2978 static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2979 {
2980 uint8_t accepted = 0;
2981 bt_bdaddr_t rc_addr;
2982
2983 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2984
2985 /* For timeout pmeta_msg will be NULL, else we need to
2986 * check if this is accepted by TG
2987 */
2988 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2989 {
2990 accepted = 1;
2991 }
2992 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2993 }
2994
2995 /***************************************************************************
2996 **
2997 ** Function handle_get_elem_attr_response
2998 **
2999 ** Description handles the the element attributes response, calls
3000 ** HAL callback to update track change information.
3001 ** Returns None
3002 **
3003 ***************************************************************************/
handle_get_elem_attr_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_ELEM_ATTRS_RSP * p_rsp)3004 static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg,
3005 tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
3006 {
3007 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3008 bt_bdaddr_t rc_addr;
3009 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
3010 btrc_element_attr_val_t *p_attr =
3011 (btrc_element_attr_val_t *)osi_calloc(buf_size);
3012
3013 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3014
3015 for (int i = 0; i < p_rsp->num_attr; i++) {
3016 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
3017 /* Todo. Legth limit check to include null */
3018 if (p_rsp->p_attrs[i].name.str_len &&
3019 p_rsp->p_attrs[i].name.p_str) {
3020 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3021 p_rsp->p_attrs[i].name.str_len);
3022 osi_free_and_reset((void **)&p_rsp->p_attrs[i].name.p_str);
3023 }
3024 }
3025 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3026 &rc_addr, p_rsp->num_attr, p_attr);
3027 osi_free(p_attr);
3028 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
3029 /* Retry for timeout case, this covers error handling
3030 * for continuation failure also.
3031 */
3032 UINT32 attr_list[] = {
3033 AVRC_MEDIA_ATTR_ID_TITLE,
3034 AVRC_MEDIA_ATTR_ID_ARTIST,
3035 AVRC_MEDIA_ATTR_ID_ALBUM,
3036 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3037 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3038 AVRC_MEDIA_ATTR_ID_GENRE,
3039 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3040 };
3041 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
3042 } else {
3043 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
3044 __func__, p_rsp->status);
3045 }
3046 }
3047
3048 /***************************************************************************
3049 **
3050 ** Function handle_get_playstatus_response
3051 **
3052 ** Description handles the the play status response, calls
3053 ** HAL callback to update play position.
3054 ** Returns None
3055 **
3056 ***************************************************************************/
handle_get_playstatus_response(tBTA_AV_META_MSG * pmeta_msg,tAVRC_GET_PLAY_STATUS_RSP * p_rsp)3057 static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3058 {
3059 bt_bdaddr_t rc_addr;
3060
3061 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3062
3063 if (p_rsp->status == AVRC_STS_NO_ERROR)
3064 {
3065 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3066 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3067 }
3068 else
3069 {
3070 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3071 __FUNCTION__, p_rsp->status);
3072 }
3073 }
3074
3075 /***************************************************************************
3076 **
3077 ** Function clear_cmd_timeout
3078 **
3079 ** Description helper function to stop the command timeout timer
3080 ** Returns None
3081 **
3082 ***************************************************************************/
clear_cmd_timeout(UINT8 label)3083 static void clear_cmd_timeout (UINT8 label)
3084 {
3085 rc_transaction_t *p_txn;
3086
3087 p_txn = get_transaction_by_lbl (label);
3088 if (p_txn == NULL)
3089 {
3090 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3091 return;
3092 }
3093
3094 if (p_txn->txn_timer != NULL)
3095 alarm_cancel(p_txn->txn_timer);
3096 }
3097
3098 /***************************************************************************
3099 **
3100 ** Function handle_avk_rc_metamsg_rsp
3101 **
3102 ** Description Handle RC metamessage response
3103 **
3104 ** Returns void
3105 **
3106 ***************************************************************************/
handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG * pmeta_msg)3107 static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3108 {
3109 tAVRC_RESPONSE avrc_response = {0};
3110 UINT8 scratch_buf[512] = {0};// this variable is unused
3111 UINT16 buf_len;
3112 tAVRC_STS status;
3113
3114 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3115 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3116
3117 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3118 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3119 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3120 {
3121 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3122 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3123 __FUNCTION__, status, avrc_response.pdu,
3124 pmeta_msg->p_msg->vendor.hdr.ctype);
3125
3126 switch (avrc_response.pdu)
3127 {
3128 case AVRC_PDU_REGISTER_NOTIFICATION:
3129 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3130 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3131 {
3132 /* Don't free the transaction Id */
3133 clear_cmd_timeout (pmeta_msg->label);
3134 return;
3135 }
3136 break;
3137
3138 case AVRC_PDU_GET_CAPABILITIES:
3139 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3140 break;
3141
3142 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3143 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3144 break;
3145
3146 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3147 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3148 break;
3149
3150 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3151 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3152 break;
3153
3154 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3155 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3156 break;
3157
3158 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3159 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3160 break;
3161
3162 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3163 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3164 break;
3165
3166 case AVRC_PDU_GET_ELEMENT_ATTR:
3167 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3168 break;
3169
3170 case AVRC_PDU_GET_PLAY_STATUS:
3171 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3172 break;
3173 }
3174 release_transaction(pmeta_msg->label);
3175 }
3176 else
3177 {
3178 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3179 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3180 return;
3181 }
3182 }
3183
3184 /***************************************************************************
3185 **
3186 ** Function handle_avk_rc_metamsg_cmd
3187 **
3188 ** Description Handle RC metamessage response
3189 **
3190 ** Returns void
3191 **
3192 ***************************************************************************/
handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG * pmeta_msg)3193 static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3194 {
3195 tAVRC_COMMAND avrc_cmd = {0};
3196 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3197 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3198 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3199 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3200 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3201 {
3202 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3203 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3204 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3205
3206 if (status != AVRC_STS_NO_ERROR)
3207 {
3208 /* return error */
3209 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3210 __FUNCTION__, status);
3211 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3212 }
3213 else
3214 {
3215 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3216 {
3217 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3218 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3219 __FUNCTION__, dump_rc_notification_event_id(event_id));
3220 }
3221 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3222 {
3223 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3224 }
3225 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3226 }
3227 }
3228 else
3229 {
3230 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3231 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3232 return;
3233 }
3234 }
3235 #endif
3236
3237 /***************************************************************************
3238 **
3239 ** Function cleanup
3240 **
3241 ** Description Closes the AVRC interface
3242 **
3243 ** Returns void
3244 **
3245 ***************************************************************************/
cleanup()3246 static void cleanup()
3247 {
3248 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3249 close_uinput();
3250 if (bt_rc_callbacks)
3251 {
3252 bt_rc_callbacks = NULL;
3253 }
3254 alarm_free(btif_rc_cb.rc_play_status_timer);
3255 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3256 lbl_destroy();
3257 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3258 }
3259
3260 /***************************************************************************
3261 **
3262 ** Function cleanup_ctrl
3263 **
3264 ** Description Closes the AVRC Controller interface
3265 **
3266 ** Returns void
3267 **
3268 ***************************************************************************/
cleanup_ctrl()3269 static void cleanup_ctrl()
3270 {
3271 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3272
3273 if (bt_rc_ctrl_callbacks)
3274 {
3275 bt_rc_ctrl_callbacks = NULL;
3276 }
3277 alarm_free(btif_rc_cb.rc_play_status_timer);
3278 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3279 lbl_destroy();
3280 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3281 }
3282
3283 /***************************************************************************
3284 **
3285 ** Function getcapabilities_cmd
3286 **
3287 ** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3288 **
3289 ** Returns void
3290 **
3291 ***************************************************************************/
getcapabilities_cmd(uint8_t cap_id)3292 static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3293 {
3294 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3295 rc_transaction_t *p_transaction = NULL;
3296 #if (AVRC_CTLR_INCLUDED == TRUE)
3297 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3298 CHECK_RC_CONNECTED
3299 bt_status_t tran_status=get_transaction(&p_transaction);
3300 if (BT_STATUS_SUCCESS != tran_status)
3301 return BT_STATUS_FAIL;
3302
3303 tAVRC_COMMAND avrc_cmd = {0};
3304 BT_HDR *p_msg = NULL;
3305 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3306 avrc_cmd.get_caps.capability_id = cap_id;
3307 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3308 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3309 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3310 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3311 {
3312 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3313 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3314 __FUNCTION__,p_transaction->lbl);
3315 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3316 data_start, p_msg->len);
3317 status = BT_STATUS_SUCCESS;
3318 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3319 }
3320 else
3321 {
3322 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3323 __FUNCTION__, status);
3324 }
3325 osi_free(p_msg);
3326 #else
3327 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3328 #endif
3329 return status;
3330 }
3331
3332 /***************************************************************************
3333 **
3334 ** Function list_player_app_setting_attrib_cmd
3335 **
3336 ** Description Get supported List Player Attributes
3337 **
3338 ** Returns void
3339 **
3340 ***************************************************************************/
list_player_app_setting_attrib_cmd(void)3341 static bt_status_t list_player_app_setting_attrib_cmd(void)
3342 {
3343 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3344 rc_transaction_t *p_transaction = NULL;
3345 #if (AVRC_CTLR_INCLUDED == TRUE)
3346 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3347 CHECK_RC_CONNECTED
3348 bt_status_t tran_status=get_transaction(&p_transaction);
3349 if (BT_STATUS_SUCCESS != tran_status)
3350 return BT_STATUS_FAIL;
3351
3352 tAVRC_COMMAND avrc_cmd = {0};
3353 BT_HDR *p_msg = NULL;
3354 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3355 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3356 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3357 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3358 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3359 {
3360 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3361 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3362 __FUNCTION__,p_transaction->lbl);
3363 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3364 data_start, p_msg->len);
3365 status = BT_STATUS_SUCCESS;
3366 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3367 }
3368 else
3369 {
3370
3371 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3372 __FUNCTION__, status);
3373 }
3374 osi_free(p_msg);
3375 #else
3376 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3377 #endif
3378 return status;
3379 }
3380
3381 /***************************************************************************
3382 **
3383 ** Function list_player_app_setting_value_cmd
3384 **
3385 ** Description Get values of supported Player Attributes
3386 **
3387 ** Returns void
3388 **
3389 ***************************************************************************/
list_player_app_setting_value_cmd(uint8_t attrib_id)3390 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3391 {
3392 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3393 rc_transaction_t *p_transaction=NULL;
3394 #if (AVRC_CTLR_INCLUDED == TRUE)
3395 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3396 CHECK_RC_CONNECTED
3397 bt_status_t tran_status=get_transaction(&p_transaction);
3398 if (BT_STATUS_SUCCESS != tran_status)
3399 return BT_STATUS_FAIL;
3400
3401 tAVRC_COMMAND avrc_cmd = {0};
3402 BT_HDR *p_msg = NULL;
3403 avrc_cmd.list_app_values.attr_id = attrib_id;
3404 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3405 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3406 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3407 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3408 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3409 {
3410 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3411 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3412 __FUNCTION__,p_transaction->lbl);
3413 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3414 data_start, p_msg->len);
3415 status = BT_STATUS_SUCCESS;
3416 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3417 }
3418 else
3419 {
3420 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3421 }
3422 osi_free(p_msg);
3423 #else
3424 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3425 #endif
3426 return status;
3427 }
3428
3429 /***************************************************************************
3430 **
3431 ** Function get_player_app_setting_cmd
3432 **
3433 ** Description Get current values of Player Attributes
3434 **
3435 ** Returns void
3436 **
3437 ***************************************************************************/
get_player_app_setting_cmd(uint8_t num_attrib,uint8_t * attrib_ids)3438 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3439 {
3440 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3441 rc_transaction_t *p_transaction = NULL;
3442 int count = 0;
3443 #if (AVRC_CTLR_INCLUDED == TRUE)
3444 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3445 CHECK_RC_CONNECTED
3446 bt_status_t tran_status=get_transaction(&p_transaction);
3447 if (BT_STATUS_SUCCESS != tran_status)
3448 return BT_STATUS_FAIL;
3449
3450 tAVRC_COMMAND avrc_cmd = {0};
3451 BT_HDR *p_msg = NULL;
3452 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3453 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3454 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3455 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3456
3457 for (count = 0; count < num_attrib; count++)
3458 {
3459 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3460 }
3461 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3462 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3463 {
3464 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3465 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3466 __FUNCTION__,p_transaction->lbl);
3467 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3468 data_start, p_msg->len);
3469 status = BT_STATUS_SUCCESS;
3470 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3471 }
3472 else
3473 {
3474 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3475 __FUNCTION__, status);
3476 }
3477 osi_free(p_msg);
3478 #else
3479 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3480 #endif
3481 return status;
3482 }
3483
3484 /***************************************************************************
3485 **
3486 ** Function change_player_app_setting
3487 **
3488 ** Description Set current values of Player Attributes
3489 **
3490 ** Returns void
3491 **
3492 ***************************************************************************/
change_player_app_setting(bt_bdaddr_t * bd_addr,uint8_t num_attrib,uint8_t * attrib_ids,uint8_t * attrib_vals)3493 static bt_status_t change_player_app_setting(bt_bdaddr_t *bd_addr, uint8_t num_attrib, uint8_t* attrib_ids, uint8_t* attrib_vals)
3494 {
3495 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3496 rc_transaction_t *p_transaction = NULL;
3497 int count = 0;
3498 #if (AVRC_CTLR_INCLUDED == TRUE)
3499 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3500 CHECK_RC_CONNECTED
3501 bt_status_t tran_status=get_transaction(&p_transaction);
3502 if (BT_STATUS_SUCCESS != tran_status)
3503 return BT_STATUS_FAIL;
3504
3505 tAVRC_COMMAND avrc_cmd = {0};
3506 BT_HDR *p_msg = NULL;
3507 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3508 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3509 avrc_cmd.set_app_val.num_val = num_attrib;
3510 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3511 avrc_cmd.set_app_val.p_vals =
3512 (tAVRC_APP_SETTING *)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
3513 for (count = 0; count < num_attrib; count++)
3514 {
3515 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3516 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3517 }
3518 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3519 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3520 {
3521 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3522 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3523 __FUNCTION__,p_transaction->lbl);
3524 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3525 data_start, p_msg->len);
3526 status = BT_STATUS_SUCCESS;
3527 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3528 }
3529 else
3530 {
3531 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3532 __FUNCTION__, status);
3533 }
3534 osi_free(p_msg);
3535 osi_free_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
3536 #else
3537 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3538 #endif
3539 return status;
3540 }
3541
3542 /***************************************************************************
3543 **
3544 ** Function get_player_app_setting_attr_text_cmd
3545 **
3546 ** Description Get text description for app attribute
3547 **
3548 ** Returns void
3549 **
3550 ***************************************************************************/
get_player_app_setting_attr_text_cmd(UINT8 * attrs,UINT8 num_attrs)3551 static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3552 {
3553 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3554 rc_transaction_t *p_transaction = NULL;
3555 int count = 0;
3556 #if (AVRC_CTLR_INCLUDED == TRUE)
3557 tAVRC_COMMAND avrc_cmd = {0};
3558 BT_HDR *p_msg = NULL;
3559 bt_status_t tran_status;
3560 CHECK_RC_CONNECTED
3561
3562 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3563
3564 tran_status = get_transaction(&p_transaction);
3565 if (BT_STATUS_SUCCESS != tran_status)
3566 return BT_STATUS_FAIL;
3567
3568 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3569 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3570 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3571
3572 for (count = 0; count < num_attrs; count++)
3573 {
3574 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3575 }
3576 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3577 if (status == AVRC_STS_NO_ERROR)
3578 {
3579 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3580 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3581 __FUNCTION__, p_transaction->lbl);
3582 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3583 AVRC_CMD_STATUS, data_start, p_msg->len);
3584 osi_free(p_msg);
3585 status = BT_STATUS_SUCCESS;
3586 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3587 }
3588 else
3589 {
3590 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3591 }
3592 osi_free(p_msg);
3593 #else
3594 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3595 #endif
3596 return status;
3597 }
3598
3599 /***************************************************************************
3600 **
3601 ** Function get_player_app_setting_val_text_cmd
3602 **
3603 ** Description Get text description for app attribute values
3604 **
3605 ** Returns void
3606 **
3607 ***************************************************************************/
get_player_app_setting_value_text_cmd(UINT8 * vals,UINT8 num_vals)3608 static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3609 {
3610 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3611 rc_transaction_t *p_transaction = NULL;
3612 int count = 0;
3613 #if (AVRC_CTLR_INCLUDED == TRUE)
3614 tAVRC_COMMAND avrc_cmd = {0};
3615 BT_HDR *p_msg = NULL;
3616 bt_status_t tran_status;
3617 CHECK_RC_CONNECTED
3618
3619 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3620
3621 tran_status = get_transaction(&p_transaction);
3622 if (BT_STATUS_SUCCESS != tran_status)
3623 return BT_STATUS_FAIL;
3624
3625 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3626 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3627 avrc_cmd.get_app_val_txt.num_val = num_vals;
3628
3629 for (count = 0; count < num_vals; count++)
3630 {
3631 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3632 }
3633 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3634 if (status == AVRC_STS_NO_ERROR)
3635 {
3636 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3637 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3638 __FUNCTION__, p_transaction->lbl);
3639 if (p_msg != NULL)
3640 {
3641 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3642 AVRC_CMD_STATUS, data_start, p_msg->len);
3643 status = BT_STATUS_SUCCESS;
3644 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3645 }
3646 }
3647 else
3648 {
3649 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3650 __FUNCTION__, status);
3651 }
3652 osi_free(p_msg);
3653 #else
3654 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3655 #endif
3656 return status;
3657 }
3658
3659 /***************************************************************************
3660 **
3661 ** Function register_notification_cmd
3662 **
3663 ** Description Send Command to register for a Notification ID
3664 **
3665 ** Returns void
3666 **
3667 ***************************************************************************/
register_notification_cmd(UINT8 label,UINT8 event_id,UINT32 event_value)3668 static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3669 {
3670
3671 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3672 #if (AVRC_CTLR_INCLUDED == TRUE)
3673 tAVRC_COMMAND avrc_cmd = {0};
3674 BT_HDR *p_msg = NULL;
3675 CHECK_RC_CONNECTED
3676
3677
3678 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3679
3680 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3681 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3682 avrc_cmd.reg_notif.event_id = event_id;
3683 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3684 avrc_cmd.reg_notif.param = event_value;
3685 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3686 if (status == AVRC_STS_NO_ERROR)
3687 {
3688 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3689 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3690 __FUNCTION__, label);
3691 if (p_msg != NULL)
3692 {
3693 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3694 data_start, p_msg->len);
3695 status = BT_STATUS_SUCCESS;
3696 }
3697 }
3698 else
3699 {
3700 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3701 __FUNCTION__, status);
3702 }
3703 osi_free(p_msg);
3704 #else
3705 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3706 #endif
3707 return status;
3708 }
3709
3710 /***************************************************************************
3711 **
3712 ** Function get_element_attribute_cmd
3713 **
3714 ** Description Get Element Attribute for attributeIds
3715 **
3716 ** Returns void
3717 **
3718 ***************************************************************************/
get_element_attribute_cmd(uint8_t num_attribute,uint32_t * p_attr_ids)3719 static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3720 {
3721 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3722 rc_transaction_t *p_transaction=NULL;
3723 int count = 0;
3724 #if (AVRC_CTLR_INCLUDED == TRUE)
3725 tAVRC_COMMAND avrc_cmd = {0};
3726 BT_HDR *p_msg = NULL;
3727 bt_status_t tran_status;
3728 CHECK_RC_CONNECTED
3729
3730 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3731 __FUNCTION__, num_attribute, p_attr_ids[0]);
3732
3733 tran_status = get_transaction(&p_transaction);
3734 if (BT_STATUS_SUCCESS != tran_status)
3735 return BT_STATUS_FAIL;
3736
3737 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3738 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3739 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3740 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3741 for (count = 0; count < num_attribute; count++)
3742 {
3743 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3744 }
3745
3746 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3747 if (status == AVRC_STS_NO_ERROR)
3748 {
3749 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3750 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3751 __FUNCTION__, p_transaction->lbl);
3752 if (p_msg != NULL)
3753 {
3754 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3755 AVRC_CMD_STATUS, data_start, p_msg->len);
3756 status = BT_STATUS_SUCCESS;
3757 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3758 p_transaction);
3759 }
3760 }
3761 else
3762 {
3763 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3764 __FUNCTION__, status);
3765 }
3766 osi_free(p_msg);
3767 #else
3768 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3769 #endif
3770 return status;
3771 }
3772
3773 /***************************************************************************
3774 **
3775 ** Function get_play_status_cmd
3776 **
3777 ** Description Get Element Attribute for attributeIds
3778 **
3779 ** Returns void
3780 **
3781 ***************************************************************************/
get_play_status_cmd(void)3782 static bt_status_t get_play_status_cmd(void)
3783 {
3784 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3785 rc_transaction_t *p_transaction = NULL;
3786 #if (AVRC_CTLR_INCLUDED == TRUE)
3787 tAVRC_COMMAND avrc_cmd = {0};
3788 BT_HDR *p_msg = NULL;
3789 bt_status_t tran_status;
3790 CHECK_RC_CONNECTED
3791
3792 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3793 tran_status = get_transaction(&p_transaction);
3794 if (BT_STATUS_SUCCESS != tran_status)
3795 return BT_STATUS_FAIL;
3796
3797 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3798 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3799 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3800 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3801 if (status == AVRC_STS_NO_ERROR)
3802 {
3803 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3804 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3805 __FUNCTION__, p_transaction->lbl);
3806 if (p_msg != NULL)
3807 {
3808 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3809 AVRC_CMD_STATUS, data_start, p_msg->len);
3810 status = BT_STATUS_SUCCESS;
3811 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3812 }
3813 }
3814 else
3815 {
3816 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3817 __FUNCTION__, status);
3818 }
3819 osi_free(p_msg);
3820 #else
3821 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3822 #endif
3823 return status;
3824
3825 }
3826
3827 /***************************************************************************
3828 **
3829 ** Function set_volume_rsp
3830 **
3831 ** Description Rsp for SetAbsoluteVolume Command
3832 **
3833 ** Returns void
3834 **
3835 ***************************************************************************/
set_volume_rsp(bt_bdaddr_t * bd_addr,uint8_t abs_vol,uint8_t label)3836 static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3837 {
3838 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3839 #if (AVRC_CTLR_INCLUDED == TRUE)
3840 tAVRC_RESPONSE avrc_rsp;
3841 BT_HDR *p_msg = NULL;
3842 CHECK_RC_CONNECTED
3843
3844 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3845
3846 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3847 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3848 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3849 avrc_rsp.volume.volume = abs_vol;
3850 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3851 if (status == AVRC_STS_NO_ERROR)
3852 {
3853 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3854 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3855 __FUNCTION__, btif_rc_cb.rc_vol_label);
3856 if (p_msg != NULL)
3857 {
3858 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3859 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3860 status = BT_STATUS_SUCCESS;
3861 }
3862 }
3863 else
3864 {
3865 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3866 __FUNCTION__, status);
3867 }
3868 osi_free(p_msg);
3869 #else
3870 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3871 #endif
3872 return status;
3873 }
3874
3875 /***************************************************************************
3876 **
3877 ** Function send_register_abs_vol_rsp
3878 **
3879 ** Description Rsp for Notification of Absolute Volume
3880 **
3881 ** Returns void
3882 **
3883 ***************************************************************************/
volume_change_notification_rsp(bt_bdaddr_t * bd_addr,btrc_notification_type_t rsp_type,uint8_t abs_vol,uint8_t label)3884 static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3885 uint8_t abs_vol, uint8_t label)
3886 {
3887 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3888 tAVRC_RESPONSE avrc_rsp;
3889 BT_HDR *p_msg = NULL;
3890 #if (AVRC_CTLR_INCLUDED == TRUE)
3891 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
3892 CHECK_RC_CONNECTED
3893
3894 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3895 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3896 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3897 avrc_rsp.reg_notif.param.volume = abs_vol;
3898 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
3899
3900 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3901 if (status == AVRC_STS_NO_ERROR) {
3902 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3903 __func__, label);
3904 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3905 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3906 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3907 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3908 data_start, p_msg->len, 0);
3909 status = BT_STATUS_SUCCESS;
3910 } else {
3911 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3912 __func__, status);
3913 }
3914 osi_free(p_msg);
3915
3916 #else
3917 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
3918 #endif
3919 return status;
3920 }
3921
3922 /***************************************************************************
3923 **
3924 ** Function send_groupnavigation_cmd
3925 **
3926 ** Description Send Pass-Through command
3927 **
3928 ** Returns void
3929 **
3930 ***************************************************************************/
send_groupnavigation_cmd(bt_bdaddr_t * bd_addr,uint8_t key_code,uint8_t key_state)3931 static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3932 uint8_t key_state)
3933 {
3934 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3935 #if (AVRC_CTLR_INCLUDED == TRUE)
3936 rc_transaction_t *p_transaction=NULL;
3937 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3938 key_code, key_state);
3939 CHECK_RC_CONNECTED
3940 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3941 {
3942 bt_status_t tran_status = get_transaction(&p_transaction);
3943 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
3944 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3945 UINT8* start = buffer;
3946 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3947 *(start)++ = 0;
3948 UINT8_TO_BE_STREAM(start, key_code);
3949 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3950 p_transaction->lbl,
3951 (tBTA_AV_STATE)key_state, buffer,
3952 AVRC_PASS_THRU_GROUP_LEN);
3953 status = BT_STATUS_SUCCESS;
3954 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3955 __FUNCTION__);
3956 }
3957 else
3958 {
3959 status = BT_STATUS_FAIL;
3960 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3961 }
3962 }
3963 else
3964 {
3965 status = BT_STATUS_FAIL;
3966 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3967 }
3968 #else
3969 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3970 #endif
3971 return status;
3972 }
3973
3974 /***************************************************************************
3975 **
3976 ** Function send_passthrough_cmd
3977 **
3978 ** Description Send Pass-Through command
3979 **
3980 ** Returns void
3981 **
3982 ***************************************************************************/
send_passthrough_cmd(bt_bdaddr_t * bd_addr,uint8_t key_code,uint8_t key_state)3983 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3984 {
3985 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3986 #if (AVRC_CTLR_INCLUDED == TRUE)
3987 CHECK_RC_CONNECTED
3988 rc_transaction_t *p_transaction=NULL;
3989 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3990 key_code, key_state);
3991 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3992 {
3993 bt_status_t tran_status = get_transaction(&p_transaction);
3994 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
3995 {
3996 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3997 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
3998 status = BT_STATUS_SUCCESS;
3999 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
4000 }
4001 else
4002 {
4003 status = BT_STATUS_FAIL;
4004 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
4005 }
4006 }
4007 else
4008 {
4009 status = BT_STATUS_FAIL;
4010 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
4011 }
4012 #else
4013 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
4014 #endif
4015 return status;
4016 }
4017
4018 static const btrc_interface_t bt_rc_interface = {
4019 sizeof(bt_rc_interface),
4020 init,
4021 get_play_status_rsp,
4022 NULL, /* list_player_app_attr_rsp */
4023 NULL, /* list_player_app_value_rsp */
4024 NULL, /* get_player_app_value_rsp */
4025 NULL, /* get_player_app_attr_text_rsp */
4026 NULL, /* get_player_app_value_text_rsp */
4027 get_element_attr_rsp,
4028 NULL, /* set_player_app_value_rsp */
4029 register_notification_rsp,
4030 set_volume,
4031 cleanup,
4032 };
4033
4034 static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4035 sizeof(bt_rc_ctrl_interface),
4036 init_ctrl,
4037 send_passthrough_cmd,
4038 send_groupnavigation_cmd,
4039 change_player_app_setting,
4040 set_volume_rsp,
4041 volume_change_notification_rsp,
4042 cleanup_ctrl,
4043 };
4044
4045 /*******************************************************************************
4046 **
4047 ** Function btif_rc_get_interface
4048 **
4049 ** Description Get the AVRCP Target callback interface
4050 **
4051 ** Returns btav_interface_t
4052 **
4053 *******************************************************************************/
btif_rc_get_interface(void)4054 const btrc_interface_t *btif_rc_get_interface(void)
4055 {
4056 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4057 return &bt_rc_interface;
4058 }
4059
4060 /*******************************************************************************
4061 **
4062 ** Function btif_rc_ctrl_get_interface
4063 **
4064 ** Description Get the AVRCP Controller callback interface
4065 **
4066 ** Returns btav_interface_t
4067 **
4068 *******************************************************************************/
btif_rc_ctrl_get_interface(void)4069 const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4070 {
4071 BTIF_TRACE_EVENT("%s", __FUNCTION__);
4072 return &bt_rc_ctrl_interface;
4073 }
4074
4075 /*******************************************************************************
4076 ** Function initialize_transaction
4077 **
4078 ** Description Initializes fields of the transaction structure
4079 **
4080 ** Returns void
4081 *******************************************************************************/
initialize_transaction(int lbl)4082 static void initialize_transaction(int lbl)
4083 {
4084 pthread_mutex_lock(&device.lbllock);
4085 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4086 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4087 clear_cmd_timeout(lbl);
4088 }
4089 device.transaction[lbl].lbl = lbl;
4090 device.transaction[lbl].in_use=FALSE;
4091 device.transaction[lbl].handle=0;
4092 }
4093 pthread_mutex_unlock(&device.lbllock);
4094 }
4095
4096 /*******************************************************************************
4097 ** Function lbl_init
4098 **
4099 ** Description Initializes label structures and mutexes.
4100 **
4101 ** Returns void
4102 *******************************************************************************/
lbl_init()4103 void lbl_init()
4104 {
4105 memset(&device,0,sizeof(rc_device_t));
4106 pthread_mutexattr_t attr;
4107 pthread_mutexattr_init(&attr);
4108 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4109 pthread_mutex_init(&(device.lbllock), &attr);
4110 pthread_mutexattr_destroy(&attr);
4111 init_all_transactions();
4112 }
4113
4114 /*******************************************************************************
4115 **
4116 ** Function init_all_transactions
4117 **
4118 ** Description Initializes all transactions
4119 **
4120 ** Returns void
4121 *******************************************************************************/
init_all_transactions()4122 void init_all_transactions()
4123 {
4124 UINT8 txn_indx=0;
4125 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4126 {
4127 initialize_transaction(txn_indx);
4128 }
4129 }
4130
4131 /*******************************************************************************
4132 **
4133 ** Function get_transaction_by_lbl
4134 **
4135 ** Description Will return a transaction based on the label. If not inuse
4136 ** will return an error.
4137 **
4138 ** Returns bt_status_t
4139 *******************************************************************************/
get_transaction_by_lbl(UINT8 lbl)4140 rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4141 {
4142 rc_transaction_t *transaction = NULL;
4143 pthread_mutex_lock(&device.lbllock);
4144
4145 /* Determine if this is a valid label */
4146 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4147 {
4148 if (FALSE==device.transaction[lbl].in_use)
4149 {
4150 transaction = NULL;
4151 }
4152 else
4153 {
4154 transaction = &(device.transaction[lbl]);
4155 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
4156 }
4157 }
4158
4159 pthread_mutex_unlock(&device.lbllock);
4160 return transaction;
4161 }
4162
4163 /*******************************************************************************
4164 **
4165 ** Function get_transaction
4166 **
4167 ** Description Obtains the transaction details.
4168 **
4169 ** Returns bt_status_t
4170 *******************************************************************************/
4171
get_transaction(rc_transaction_t ** ptransaction)4172 bt_status_t get_transaction(rc_transaction_t **ptransaction)
4173 {
4174 bt_status_t result = BT_STATUS_NOMEM;
4175 UINT8 i=0;
4176 pthread_mutex_lock(&device.lbllock);
4177
4178 // Check for unused transactions
4179 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4180 {
4181 if (FALSE==device.transaction[i].in_use)
4182 {
4183 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
4184 device.transaction[i].in_use = TRUE;
4185 *ptransaction = &(device.transaction[i]);
4186 result = BT_STATUS_SUCCESS;
4187 break;
4188 }
4189 }
4190
4191 pthread_mutex_unlock(&device.lbllock);
4192 return result;
4193 }
4194
4195 /*******************************************************************************
4196 **
4197 ** Function release_transaction
4198 **
4199 ** Description Will release a transaction for reuse
4200 **
4201 ** Returns bt_status_t
4202 *******************************************************************************/
release_transaction(UINT8 lbl)4203 void release_transaction(UINT8 lbl)
4204 {
4205 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4206
4207 /* If the transaction is in use... */
4208 if (transaction != NULL)
4209 {
4210 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
4211 initialize_transaction(lbl);
4212 }
4213 }
4214
4215 /*******************************************************************************
4216 **
4217 ** Function lbl_destroy
4218 **
4219 ** Description Cleanup of the mutex
4220 **
4221 ** Returns void
4222 *******************************************************************************/
lbl_destroy()4223 void lbl_destroy()
4224 {
4225 pthread_mutex_destroy(&(device.lbllock));
4226 }
4227
4228 /*******************************************************************************
4229 ** Function sleep_ms
4230 **
4231 ** Description Sleep the calling thread unconditionally for
4232 ** |timeout_ms| milliseconds.
4233 **
4234 ** Returns void
4235 *******************************************************************************/
sleep_ms(period_ms_t timeout_ms)4236 static void sleep_ms(period_ms_t timeout_ms) {
4237 struct timespec delay;
4238 delay.tv_sec = timeout_ms / 1000;
4239 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4240
4241 OSI_NO_INTR(nanosleep(&delay, &delay));
4242 }
4243
absolute_volume_disabled()4244 static bool absolute_volume_disabled() {
4245 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
4246 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
4247 if (strncmp(volume_disabled, "true", 4) == 0) {
4248 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);
4249 return true;
4250 }
4251 return false;
4252 }
4253