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