blob: 9bc57fd61fbb76f7c5b13912792b072aa2c826e5 [file] [log] [blame]
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301/*
2 * Copyright (C) 2015 The Android Open Source Project
The Android Open Source Project5738f832012-12-12 16:00:35 -08003 *
Anubhav Gupta6b84f292015-05-05 13:15:07 +05304 * 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
The Android Open Source Project5738f832012-12-12 16:00:35 -08007 *
Anubhav Gupta6b84f292015-05-05 13:15:07 +05308 * http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project5738f832012-12-12 16:00:35 -08009 *
Anubhav Gupta6b84f292015-05-05 13:15:07 +053010 * 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 */
The Android Open Source Project5738f832012-12-12 16:00:35 -080016
The Android Open Source Project5738f832012-12-12 16:00:35 -080017/*****************************************************************************
18 *
19 * Filename: btif_rc.c
20 *
21 * Description: Bluetooth AVRC implementation
22 *
23 *****************************************************************************/
Marie Janssen49a86702015-07-08 11:48:57 -070024
25#define LOG_TAG "bt_btif_avrc"
26
Pavlin Radoslavov642f2332015-09-16 13:30:26 -070027#include <errno.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080028#include <fcntl.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070029#include <pthread.h>
Ian Coolidgec7503db2015-01-24 02:01:26 -080030#include <string.h>
Pavlin Radoslavov642f2332015-09-16 13:30:26 -070031#include <time.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070032#include <unistd.h>
33
Marie Janssen49a86702015-07-08 11:48:57 -070034#include <hardware/bluetooth.h>
35#include <hardware/bt_rc.h>
36
37#include "avrc_defs.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include "bta_api.h"
39#include "bta_av_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070040#include "btif_av.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080041#include "btif_common.h"
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080042#include "btif_util.h"
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070043#include "bt_common.h"
Andre Eisenbachd0aa6cc2015-12-11 12:32:21 -080044#include "device/include/interop.h"
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080045#include "uinput.h"
Ayan Ghoshbe834072013-12-03 14:52:22 +053046#include "bdaddr.h"
Anubhav Gupta6b84f292015-05-05 13:15:07 +053047#include "osi/include/list.h"
Jakub Pawlowski3eb4a482016-02-24 10:39:46 -080048#include "osi/include/properties.h"
Anubhav Gupta6b84f292015-05-05 13:15:07 +053049#include "btu.h"
50#define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
Ayan Ghoshbe834072013-12-03 14:52:22 +053051
The Android Open Source Project5738f832012-12-12 16:00:35 -080052/*****************************************************************************
53** Constants & Macros
54******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080055
56/* cod value for Headsets */
57#define COD_AV_HEADSETS 0x0404
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080058/* for AVRC 1.4 need to change this */
Anubhav Gupta6b84f292015-05-05 13:15:07 +053059#define MAX_RC_NOTIFICATIONS AVRC_EVT_VOLUME_CHANGE
The Android Open Source Project5738f832012-12-12 16:00:35 -080060
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080061#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
Satya Calloji247c68f2013-08-01 02:14:43 -070069#define MAX_VOLUME 128
70#define MAX_LABEL 16
71#define MAX_TRANSACTIONS_PER_SESSION 16
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080072#define MAX_CMD_QUEUE_LEN 8
Anubhav Gupta9c5d0722013-07-27 14:46:29 +053073#define PLAY_STATUS_PLAYING 1
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080074
75#define CHECK_RC_CONNECTED \
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070076 BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
Anubhav Gupta6b84f292015-05-05 13:15:07 +053077 if (btif_rc_cb.rc_connected == FALSE) \
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080078 { \
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070079 BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080080 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{ \
Anubhav Gupta6b84f292015-05-05 13:15:07 +053092 if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE) \
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080093 { \
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -070094 BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
Ravi Nagarajan9adddf42013-03-06 05:29:48 -080095 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}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800103
104/*****************************************************************************
105** Local type definitions
106******************************************************************************/
107typedef struct {
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800108 UINT8 bNotify;
109 UINT8 label;
110} btif_rc_reg_notifications_t;
111
112typedef struct
113{
114 UINT8 label;
115 UINT8 ctype;
116 BOOLEAN is_rsp_pending;
117} btif_rc_cmd_ctxt_t;
118
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530119/* 2 second timeout to get interim response */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800120#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)
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530123
124
125typedef enum
126{
127 eNOT_REGISTERED,
128 eREGISTERED,
129 eINTERIM
130} btif_rc_nfn_reg_status_t;
131
132typedef struct {
133 UINT8 event_id;
134 UINT8 label;
135 btif_rc_nfn_reg_status_t status;
136} btif_rc_supported_event_t;
137
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530138#define BTIF_RC_STS_TIMEOUT 0xFE
139typedef struct {
140 UINT8 label;
141 UINT8 pdu_id;
142} btif_rc_status_cmd_timer_t;
143
144typedef struct {
145 UINT8 label;
146 UINT8 pdu_id;
147} btif_rc_control_cmd_timer_t;
148
149typedef struct {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530150 union {
151 btif_rc_status_cmd_timer_t rc_status_cmd;
152 btif_rc_control_cmd_timer_t rc_control_cmd;
153 };
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530154} btif_rc_timer_context_t;
155
156typedef 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
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800168/* TODO : Merge btif_rc_reg_notifications_t and btif_rc_cmd_ctxt_t to a single struct */
169typedef struct {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800170 BOOLEAN rc_connected;
171 UINT8 rc_handle;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800172 tBTA_AV_FEAT rc_features;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800173 BD_ADDR rc_addr;
174 UINT16 rc_pending_play;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800175 btif_rc_cmd_ctxt_t rc_pdu_info[MAX_CMD_QUEUE_LEN];
176 btif_rc_reg_notifications_t rc_notif[MAX_RC_NOTIFICATIONS];
Satya Calloji247c68f2013-08-01 02:14:43 -0700177 unsigned int rc_volume;
178 uint8_t rc_vol_label;
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530179 list_t *rc_supported_event_list;
180 btif_rc_player_app_settings_t rc_app_settings;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800181 alarm_t *rc_play_status_timer;
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530182 BOOLEAN rc_features_processed;
183 UINT64 rc_playing_uid;
184 BOOLEAN rc_procedure_complete;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185} btif_rc_cb_t;
186
Satya Calloji247c68f2013-08-01 02:14:43 -0700187typedef struct {
188 BOOLEAN in_use;
189 UINT8 lbl;
190 UINT8 handle;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800191 btif_rc_timer_context_t txn_timer_context;
192 alarm_t *txn_timer;
Satya Calloji247c68f2013-08-01 02:14:43 -0700193} rc_transaction_t;
194
195typedef struct
196{
197 pthread_mutex_t lbllock;
198 rc_transaction_t transaction[MAX_TRANSACTIONS_PER_SESSION];
199} rc_device_t;
200
Satya Calloji247c68f2013-08-01 02:14:43 -0700201rc_device_t device;
202
The Android Open Source Project5738f832012-12-12 16:00:35 -0800203#define MAX_UINPUT_PATHS 3
204static const char* uinput_dev_path[] =
205 {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
206static int uinput_fd = -1;
207
208static int send_event (int fd, uint16_t type, uint16_t code, int32_t value);
209static void send_key (int fd, uint16_t key, int pressed);
210static int uinput_driver_check();
211static int uinput_create(char *name);
212static int init_uinput (void);
213static void close_uinput (void);
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800214static void sleep_ms(period_ms_t timeout_ms);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800215
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800216static const struct {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800217 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 },
John Du98497a52013-06-24 19:18:56 -0700228 { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FAST_FORWARD, 0 },
The Android Open Source Project5738f832012-12-12 16:00:35 -0800229 { NULL, 0, 0, 0 }
230};
The Android Open Source Project5738f832012-12-12 16:00:35 -0800231
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800232static void send_reject_response (UINT8 rc_handle, UINT8 label,
233 UINT8 pdu, UINT8 status);
234static UINT8 opcode_from_pdu(UINT8 pdu);
235static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
236 tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
Prashant Malanif85869d2016-02-25 18:26:13 -0800237#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -0700238static void register_volumechange(UINT8 label);
Prashant Malanif85869d2016-02-25 18:26:13 -0800239#endif
Satya Calloji247c68f2013-08-01 02:14:43 -0700240static void lbl_init();
241static void lbl_destroy();
242static void init_all_transactions();
243static bt_status_t get_transaction(rc_transaction_t **ptransaction);
244static void release_transaction(UINT8 label);
245static rc_transaction_t* get_transaction_by_lbl(UINT8 label);
Prashant Malanif85869d2016-02-25 18:26:13 -0800246#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -0700247static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
Prashant Malanif85869d2016-02-25 18:26:13 -0800248#endif
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530249#if (AVRC_CTLR_INCLUDED == TRUE)
250static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg);
251static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg);
252static void btif_rc_ctrl_upstreams_rsp_cmd(
253 UINT8 event, tAVRC_COMMAND *pavrc_cmd, UINT8 label);
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530254static void rc_ctrl_procedure_complete();
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800255static void rc_stop_play_status_timer();
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530256static void register_for_event_notification (btif_rc_supported_event_t *p_event);
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530257static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp);
258static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp);
259static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp);
260static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp);
261static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
262static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp);
263static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp);
264static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_ELEM_ATTRS_RSP *p_rsp);
265static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
266static bt_status_t get_play_status_cmd(void);
267static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs);
268static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals);
269static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value);
270static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids);
271static bt_status_t getcapabilities_cmd (uint8_t cap_id);
272static bt_status_t list_player_app_setting_attrib_cmd(void);
273static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
274static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
275#endif
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800276static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
Prashant Malanif85869d2016-02-25 18:26:13 -0800277#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -0700278static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
Prashant Malanif85869d2016-02-25 18:26:13 -0800279#endif
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800280static void rc_start_play_status_timer(void);
Andre Eisenbachfeb9e4d2016-02-08 15:37:45 -0800281static bool absolute_volume_disabled(void);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800282
283/*****************************************************************************
284** Static variables
285******************************************************************************/
286static btif_rc_cb_t btif_rc_cb;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800287static btrc_callbacks_t *bt_rc_callbacks = NULL;
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700288static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800289
290/*****************************************************************************
291** Static functions
292******************************************************************************/
293
294/*****************************************************************************
295** Externs
296******************************************************************************/
297extern BOOLEAN btif_hf_call_terminated_recently();
298extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800299
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800300extern fixed_queue_t *btu_general_alarm_queue;
301
The Android Open Source Project5738f832012-12-12 16:00:35 -0800302/*****************************************************************************
303** Functions
304******************************************************************************/
305
The Android Open Source Project5738f832012-12-12 16:00:35 -0800306/*****************************************************************************
307** Local uinput helper functions
308******************************************************************************/
309int send_event (int fd, uint16_t type, uint16_t code, int32_t value)
310{
311 struct uinput_event event;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700312 BTIF_TRACE_DEBUG("%s type:%u code:%u value:%d", __FUNCTION__,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800313 type, code, value);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800314 memset(&event, 0, sizeof(event));
315 event.type = type;
316 event.code = code;
317 event.value = value;
318
319 return write(fd, &event, sizeof(event));
320}
321
322void send_key (int fd, uint16_t key, int pressed)
323{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700324 BTIF_TRACE_DEBUG("%s fd:%d key:%u pressed:%d", __FUNCTION__,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800325 fd, key, pressed);
326
327 if (fd < 0)
328 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800329 return;
330 }
331
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700332 BTIF_TRACE_DEBUG("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800333 send_event(fd, EV_KEY, key, pressed);
334 send_event(fd, EV_SYN, SYN_REPORT, 0);
335}
336
337/************** uinput related functions **************/
338int uinput_driver_check()
339{
340 uint32_t i;
341 for (i=0; i < MAX_UINPUT_PATHS; i++)
342 {
343 if (access(uinput_dev_path[i], O_RDWR) == 0) {
344 return 0;
345 }
346 }
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700347 BTIF_TRACE_ERROR("%s ERROR: uinput device is not in the system", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800348 return -1;
349}
350
351int uinput_create(char *name)
352{
353 struct uinput_dev dev;
Bernhard Rosenkränzer104e3f22014-11-12 21:53:08 +0100354 int fd, x = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800355
356 for(x=0; x < MAX_UINPUT_PATHS; x++)
357 {
358 fd = open(uinput_dev_path[x], O_RDWR);
359 if (fd < 0)
360 continue;
361 break;
362 }
363 if (x == MAX_UINPUT_PATHS) {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700364 BTIF_TRACE_ERROR("%s ERROR: uinput device open failed", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800365 return -1;
366 }
367 memset(&dev, 0, sizeof(dev));
368 if (name)
VenkatRaghavan VijayaRaghavan4540f592015-02-05 04:40:47 -0800369 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800370
371 dev.id.bustype = BUS_BLUETOOTH;
372 dev.id.vendor = 0x0000;
373 dev.id.product = 0x0000;
374 dev.id.version = 0x0000;
375
376 if (write(fd, &dev, sizeof(dev)) < 0) {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700377 BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800378 close(fd);
379 return -1;
380 }
381
382 ioctl(fd, UI_SET_EVBIT, EV_KEY);
383 ioctl(fd, UI_SET_EVBIT, EV_REL);
384 ioctl(fd, UI_SET_EVBIT, EV_SYN);
385
386 for (x = 0; key_map[x].name != NULL; x++)
387 ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id);
388
The Android Open Source Project5738f832012-12-12 16:00:35 -0800389 if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700390 BTIF_TRACE_ERROR("%s Unable to create uinput device", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800391 close(fd);
392 return -1;
393 }
394 return fd;
395}
396
397int init_uinput (void)
398{
399 char *name = "AVRCP";
400
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700401 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800402 uinput_fd = uinput_create(name);
403 if (uinput_fd < 0) {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700404 BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800405 __FUNCTION__, name, uinput_fd);
406 } else {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700407 BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800408 __FUNCTION__, name, uinput_fd);
409 }
410 return uinput_fd;
411}
412
413void close_uinput (void)
414{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700415 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800416 if (uinput_fd > 0) {
417 ioctl(uinput_fd, UI_DEV_DESTROY);
418
419 close(uinput_fd);
420 uinput_fd = -1;
421 }
422}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800423
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530424#if (AVRC_CTLR_INCLUDED == TRUE)
425void rc_cleanup_sent_cmd (void *p_data)
Satya Calloji247c68f2013-08-01 02:14:43 -0700426{
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530427 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
428
429}
430
431void handle_rc_ctrl_features(BD_ADDR bd_addr)
432{
433 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
434 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
435 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
436 {
437 bt_bdaddr_t rc_addr;
438 int rc_features = 0;
439 bdcpy(rc_addr.address,bd_addr);
440
441 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
442 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
443 {
444 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
445 }
446 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
447 (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR)&&
448 (btif_rc_cb.rc_features_processed != TRUE))
449 {
450 rc_features |= BTRC_FEAT_METADATA;
451 /* Mark rc features processed to avoid repeating
452 * the AVRCP procedure every time on receiving this
453 * update.
454 */
455 btif_rc_cb.rc_features_processed = TRUE;
456 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
457 }
458 BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features);
459 HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features);
460 }
461}
462#endif
463
464void handle_rc_features(BD_ADDR bd_addr)
465{
466 if (bt_rc_callbacks != NULL)
467 {
Satya Calloji247c68f2013-08-01 02:14:43 -0700468 btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
469 bt_bdaddr_t rc_addr;
Ayan Ghoshbe834072013-12-03 14:52:22 +0530470
Satya Calloji247c68f2013-08-01 02:14:43 -0700471 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
Ayan Ghoshbe834072013-12-03 14:52:22 +0530472 bt_bdaddr_t avdtp_addr = btif_av_get_addr();
473
474 bdstr_t addr1, addr2;
475 BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
476 bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
477 bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800478
Andre Eisenbach7ee02bd2016-04-11 14:50:41 -0700479 if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
Ayan Ghoshbe834072013-12-03 14:52:22 +0530480 || absolute_volume_disabled()
481 || bdcmp(avdtp_addr.address, rc_addr.address))
Andre Eisenbachd0aa6cc2015-12-11 12:32:21 -0800482 btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
Matthew Xiea7ae4a12013-10-24 01:09:52 -0700483
Satya Calloji247c68f2013-08-01 02:14:43 -0700484 if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
485 {
486 rc_features |= BTRC_FEAT_BROWSE;
487 }
Andre Eisenbach58593a02015-10-19 16:06:20 -0700488
Sharvil Nanavati5bcbaa42015-12-17 06:23:19 -0800489#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -0700490 if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
491 (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
492 {
493 rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
494 }
Sharvil Nanavati5bcbaa42015-12-17 06:23:19 -0800495#endif
Andre Eisenbach58593a02015-10-19 16:06:20 -0700496
Satya Calloji247c68f2013-08-01 02:14:43 -0700497 if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
498 {
499 rc_features |= BTRC_FEAT_METADATA;
500 }
Andre Eisenbach58593a02015-10-19 16:06:20 -0700501
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700502 BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
Satya Calloji247c68f2013-08-01 02:14:43 -0700503 HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
504
505#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530506 BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
507 __FUNCTION__, btif_rc_cb.rc_vol_label);
Satya Calloji247c68f2013-08-01 02:14:43 -0700508 // Register for volume change on connect
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530509 if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
Satya Calloji247c68f2013-08-01 02:14:43 -0700510 btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
511 {
512 rc_transaction_t *p_transaction=NULL;
513 bt_status_t status = BT_STATUS_NOT_READY;
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530514 if (MAX_LABEL==btif_rc_cb.rc_vol_label)
Satya Calloji247c68f2013-08-01 02:14:43 -0700515 {
516 status=get_transaction(&p_transaction);
517 }
518 else
519 {
520 p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530521 if (NULL!=p_transaction)
Satya Calloji247c68f2013-08-01 02:14:43 -0700522 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530523 BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
524 __FUNCTION__, btif_rc_cb.rc_vol_label);
Satya Calloji247c68f2013-08-01 02:14:43 -0700525 return;
526 }
527 else
528 status=get_transaction(&p_transaction);
529 }
530
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530531 if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
Satya Calloji247c68f2013-08-01 02:14:43 -0700532 {
533 btif_rc_cb.rc_vol_label=p_transaction->lbl;
534 register_volumechange(btif_rc_cb.rc_vol_label);
535 }
536 }
537#endif
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530538 }
Satya Calloji247c68f2013-08-01 02:14:43 -0700539}
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800540
The Android Open Source Project5738f832012-12-12 16:00:35 -0800541/***************************************************************************
542 * Function handle_rc_connect
543 *
John Du98497a52013-06-24 19:18:56 -0700544 * - Argument: tBTA_AV_RC_OPEN RC open data structure
The Android Open Source Project5738f832012-12-12 16:00:35 -0800545 *
546 * - Description: RC connection event handler
547 *
548 ***************************************************************************/
549void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
550{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700551 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800552 bt_status_t result = BT_STATUS_SUCCESS;
Mike Lockwood93912472014-06-26 11:08:24 -0700553#if (AVRC_CTLR_INCLUDED == TRUE)
554 bt_bdaddr_t rc_addr;
555#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800556
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530557 if (p_rc_open->status == BTA_AV_SUCCESS)
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800558 {
Anubhav Gupta137bed02014-03-13 19:16:29 +0530559 //check if already some RC is connected
560 if (btif_rc_cb.rc_connected)
561 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530562 BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
563 and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
Anubhav Gupta137bed02014-03-13 19:16:29 +0530564 if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
565 && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
566 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530567 BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
Anubhav Gupta137bed02014-03-13 19:16:29 +0530568 BTA_AvCloseRc(p_rc_open->rc_handle);
569 return;
570 }
571 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800572 memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
573 btif_rc_cb.rc_features = p_rc_open->peer_features;
Satya Calloji247c68f2013-08-01 02:14:43 -0700574 btif_rc_cb.rc_vol_label=MAX_LABEL;
575 btif_rc_cb.rc_volume=MAX_VOLUME;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800577 btif_rc_cb.rc_connected = TRUE;
578 btif_rc_cb.rc_handle = p_rc_open->rc_handle;
579
Satya Calloji247c68f2013-08-01 02:14:43 -0700580 /* on locally initiated connection we will get remote features as part of connect */
581 if (btif_rc_cb.rc_features != 0)
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530582 handle_rc_features(btif_rc_cb.rc_addr);
583 if (bt_rc_callbacks)
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800584 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530585 result = uinput_driver_check();
586 if (result == BT_STATUS_SUCCESS)
587 {
588 init_uinput();
Pavlin Radoslavov3a2fa832015-06-26 14:44:12 -0700589 }
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700590 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530591 else
592 {
593 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
594 __FUNCTION__);
595 }
596 BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
597#if (AVRC_CTLR_INCLUDED == TRUE)
598 btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
599 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
600 if (bt_rc_ctrl_callbacks != NULL)
601 {
602 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
603 }
604 /* report connection state if remote device is AVRCP target */
605 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
606 ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
607 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
608 {
609 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
610 }
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700611#endif
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800612 }
613 else
614 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700615 BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800616 __FUNCTION__, p_rc_open->status);
617 btif_rc_cb.rc_connected = FALSE;
618 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800619}
620
621/***************************************************************************
622 * Function handle_rc_disconnect
623 *
John Du98497a52013-06-24 19:18:56 -0700624 * - Argument: tBTA_AV_RC_CLOSE RC close data structure
The Android Open Source Project5738f832012-12-12 16:00:35 -0800625 *
626 * - Description: RC disconnection event handler
627 *
628 ***************************************************************************/
629void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
630{
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700631#if (AVRC_CTLR_INCLUDED == TRUE)
632 bt_bdaddr_t rc_addr;
633 tBTA_AV_FEAT features;
634#endif
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700635 BTIF_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
Anubhav Gupta137bed02014-03-13 19:16:29 +0530636 if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
637 && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
638 {
639 BTIF_TRACE_ERROR("Got disconnect of unknown device");
640 return;
641 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530642#if (AVRC_CTLR_INCLUDED == TRUE)
643 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
644 features = btif_rc_cb.rc_features;
645 /* Clean up AVRCP procedure flags */
646 memset(&btif_rc_cb.rc_app_settings, 0,
647 sizeof(btif_rc_player_app_settings_t));
648 btif_rc_cb.rc_features_processed = FALSE;
649 btif_rc_cb.rc_procedure_complete = FALSE;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800650 rc_stop_play_status_timer();
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530651 /* Check and clear the notification event list */
652 if (btif_rc_cb.rc_supported_event_list != NULL)
653 {
654 list_clear(btif_rc_cb.rc_supported_event_list);
655 btif_rc_cb.rc_supported_event_list = NULL;
656 }
657#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800658 btif_rc_cb.rc_handle = 0;
659 btif_rc_cb.rc_connected = FALSE;
660 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
Nitin Srivastava68c53de2014-02-13 19:31:40 +0530661 memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530662
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800663 btif_rc_cb.rc_features = 0;
Satya Calloji247c68f2013-08-01 02:14:43 -0700664 btif_rc_cb.rc_vol_label=MAX_LABEL;
665 btif_rc_cb.rc_volume=MAX_VOLUME;
666 init_all_transactions();
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530667 if (bt_rc_callbacks != NULL)
668 {
669 close_uinput();
670 }
671 else
672 {
673 BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
674 }
675
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700676 memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
677#if (AVRC_CTLR_INCLUDED == TRUE)
678 /* report connection state if device is AVRCP target */
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530679 if (bt_rc_ctrl_callbacks != NULL)
680 {
681 HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
682 }
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700683#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800684}
685
686/***************************************************************************
687 * Function handle_rc_passthrough_cmd
688 *
689 * - Argument: tBTA_AV_RC rc_id remote control command ID
690 * tBTA_AV_STATE key_state status of key press
691 *
692 * - Description: Remote control command handler
693 *
694 ***************************************************************************/
695void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
696{
697 const char *status;
698 int pressed, i;
699
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700700 BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
John Du98497a52013-06-24 19:18:56 -0700701
The Android Open Source Project5738f832012-12-12 16:00:35 -0800702 /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
703 if (p_remote_cmd)
704 {
705 /* queue AVRC PLAY if GAVDTP Open notification to app is pending (2 second timer) */
706 if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) && (!btif_av_is_connected()))
707 {
708 if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
709 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700710 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800711 btif_rc_cb.rc_pending_play = TRUE;
712 }
713 return;
714 }
715
716 if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
717 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700718 APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800719 btif_rc_cb.rc_pending_play = FALSE;
720 return;
721 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530722 if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
723 return; // this command is not to be sent to UINPUT, only needed for PTS
The Android Open Source Project5738f832012-12-12 16:00:35 -0800724 }
Anubhav Gupta1f9dfcb2014-11-16 17:02:45 -0800725
726 if ((p_remote_cmd->rc_id == BTA_AV_RC_STOP) && (!btif_av_stream_started_ready()))
727 {
728 APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
729 return;
730 }
731
The Android Open Source Project5738f832012-12-12 16:00:35 -0800732 if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
733 status = "released";
734 pressed = 0;
735 } else {
736 status = "pressed";
737 pressed = 1;
738 }
739
John Du98497a52013-06-24 19:18:56 -0700740 if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
741 HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
742 return;
743 }
744
The Android Open Source Project5738f832012-12-12 16:00:35 -0800745 for (i = 0; key_map[i].name != NULL; i++) {
746 if (p_remote_cmd->rc_id == key_map[i].avrcp) {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700747 BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748
749 /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button
750 * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE
751 * comes 1 second after the press, the MediaPlayer UI goes into a bad state.
752 * The reason for the delay could be sniff mode exit or some AVDTP procedure etc.
753 * The fix is to generate a release right after the press and drown the 'actual'
754 * release.
755 */
756 if ((key_map[i].release_quirk == 1) && (pressed == 0))
757 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700758 BTIF_TRACE_DEBUG("%s: AVRC %s Release Faked earlier, drowned now",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800759 __FUNCTION__, key_map[i].name);
760 return;
761 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800762 send_key(uinput_fd, key_map[i].mapped_id, pressed);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800763 if ((key_map[i].release_quirk == 1) && (pressed == 1))
764 {
Pavlin Radoslavov642f2332015-09-16 13:30:26 -0700765 sleep_ms(30);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700766 BTIF_TRACE_DEBUG("%s: AVRC %s Release quirk enabled, send release now",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800767 __FUNCTION__, key_map[i].name);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800768 send_key(uinput_fd, key_map[i].mapped_id, 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800769 }
770 break;
771 }
772 }
773
774 if (key_map[i].name == NULL)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700775 BTIF_TRACE_ERROR("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800776 p_remote_cmd->rc_id, status);
777}
778
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700779/***************************************************************************
780 * Function handle_rc_passthrough_rsp
781 *
782 * - Argument: tBTA_AV_REMOTE_RSP passthrough command response
783 *
784 * - Description: Remote control passthrough response handler
785 *
786 ***************************************************************************/
787void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
788{
789#if (AVRC_CTLR_INCLUDED == TRUE)
790 const char *status;
791 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
792 {
793 int key_state;
794 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
795 {
796 status = "released";
797 key_state = 1;
798 }
799 else
800 {
801 status = "pressed";
802 key_state = 0;
803 }
804
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700805 BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700806
807 release_transaction(p_remote_rsp->label);
Pavlin Radoslavov3a2fa832015-06-26 14:44:12 -0700808 if (bt_rc_ctrl_callbacks != NULL) {
809 HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
810 }
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700811 }
812 else
813 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700814 BTIF_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700815 }
816#else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700817 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -0700818#endif
819}
820
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530821/***************************************************************************
822 * Function handle_rc_vendorunique_rsp
823 *
824 * - Argument: tBTA_AV_REMOTE_RSP command response
825 *
826 * - Description: Remote control vendor unique response handler
827 *
828 ***************************************************************************/
829void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
830{
831#if (AVRC_CTLR_INCLUDED == TRUE)
832 const char *status;
833 UINT8 vendor_id = 0;
834 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
835 {
836 int key_state;
837 if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
838 {
839 status = "released";
840 key_state = 1;
841 }
842 else
843 {
844 status = "pressed";
845 key_state = 0;
846 }
847
848 if (p_remote_rsp->len > 0)
849 {
850 if (p_remote_rsp->len >= AVRC_PASS_THRU_GROUP_LEN)
851 vendor_id = p_remote_rsp->p_data[AVRC_PASS_THRU_GROUP_LEN -1];
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800852 osi_free_and_reset((void **)&p_remote_rsp->p_data);
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530853 }
854 BTIF_TRACE_DEBUG("%s: vendor_id=%d status=%s", __FUNCTION__, vendor_id, status);
855
856 release_transaction(p_remote_rsp->label);
857 HAL_CBACK(bt_rc_ctrl_callbacks, groupnavigation_rsp_cb, vendor_id, key_state);
858 }
859 else
860 {
861 BTIF_TRACE_ERROR("%s Remote does not support AVRCP TG role", __FUNCTION__);
862 }
863#else
864 BTIF_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
865#endif
866}
867
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800868void handle_uid_changed_notification(tBTA_AV_META_MSG *pmeta_msg, tAVRC_COMMAND *pavrc_command)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800869{
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800870 tAVRC_RESPONSE avrc_rsp = {0};
871 avrc_rsp.rsp.pdu = pavrc_command->pdu;
872 avrc_rsp.rsp.status = AVRC_STS_NO_ERROR;
873 avrc_rsp.rsp.opcode = pavrc_command->cmd.opcode;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800874
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800875 avrc_rsp.reg_notif.event_id = pavrc_command->reg_notif.event_id;
876 avrc_rsp.reg_notif.param.uid_counter = 0;
877
878 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_INTERIM, &avrc_rsp);
879 send_metamsg_rsp(pmeta_msg->rc_handle, pmeta_msg->label, AVRC_RSP_CHANGED, &avrc_rsp);
880
881}
882
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800883/***************************************************************************
884 * Function handle_rc_metamsg_cmd
885 *
886 * - Argument: tBTA_AV_VENDOR Structure containing the received
887 * metamsg command
888 *
889 * - Description: Remote control metamsg command handler (AVRCP 1.3)
890 *
891 ***************************************************************************/
892void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
893{
894 /* Parse the metamsg command and pass it on to BTL-IFS */
895 UINT8 scratch_buf[512] = {0};
896 tAVRC_COMMAND avrc_command = {0};
897 tAVRC_STS status;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800898
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700899 BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800900
901 if (pmeta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR)
902 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700903 BTIF_TRACE_WARNING("Invalid opcode: %x", pmeta_msg->p_msg->hdr.opcode);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800904 return;
905 }
906 if (pmeta_msg->len < 3)
907 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700908 BTIF_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", pmeta_msg->p_msg->hdr.opcode,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800909 pmeta_msg->len);
910 return;
911 }
912
913 if (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)
914 {
Satya Calloji247c68f2013-08-01 02:14:43 -0700915#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
916{
917 rc_transaction_t *transaction=NULL;
918 transaction=get_transaction_by_lbl(pmeta_msg->label);
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530919 if (NULL!=transaction)
Satya Calloji247c68f2013-08-01 02:14:43 -0700920 {
921 handle_rc_metamsg_rsp(pmeta_msg);
922 }
923 else
924 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700925 BTIF_TRACE_DEBUG("%s:Discard vendor dependent rsp. code: %d label:%d.",
Satya Calloji247c68f2013-08-01 02:14:43 -0700926 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
927 }
928 return;
929}
930#else
931{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700932 BTIF_TRACE_DEBUG("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800933 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
934 return;
Satya Calloji247c68f2013-08-01 02:14:43 -0700935}
936#endif
937 }
938
939 status=AVRC_ParsCommand(pmeta_msg->p_msg, &avrc_command, scratch_buf, sizeof(scratch_buf));
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530940 BTIF_TRACE_DEBUG("%s Received vendor command.code,PDU and label: %d, %d,%d",
941 __FUNCTION__, pmeta_msg->code, avrc_command.cmd.pdu, pmeta_msg->label);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800942
943 if (status != AVRC_STS_NO_ERROR)
944 {
945 /* return error */
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700946 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800947 __FUNCTION__, status);
948 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_command.pdu, status);
949 }
950 else
951 {
952 /* if RegisterNotification, add it to our registered queue */
953
954 if (avrc_command.cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
955 {
956 UINT8 event_id = avrc_command.reg_notif.event_id;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700957 BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
Satya Calloji247c68f2013-08-01 02:14:43 -0700958 __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800959 btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
960 btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
961
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530962 if (event_id == AVRC_EVT_UIDS_CHANGE)
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800963 {
964 handle_uid_changed_notification(pmeta_msg, &avrc_command);
965 return;
966 }
967
968 }
969
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700970 BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800971 __FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
972
973 /* Since handle_rc_metamsg_cmd() itself is called from
974 *btif context, no context switching is required. Invoke
975 * btif_rc_upstreams_evt directly from here. */
976 btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
Satya Calloji247c68f2013-08-01 02:14:43 -0700977 pmeta_msg->label);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -0800978 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800979}
980
981/***************************************************************************
982 **
983 ** Function btif_rc_handler
984 **
985 ** Description RC event handler
986 **
987 ***************************************************************************/
988void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
989{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700990 BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800991 switch (event)
992 {
993 case BTA_AV_RC_OPEN_EVT:
994 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +0530995 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_open.peer_features);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800996 handle_rc_connect( &(p_data->rc_open) );
997 }break;
998
999 case BTA_AV_RC_CLOSE_EVT:
1000 {
1001 handle_rc_disconnect( &(p_data->rc_close) );
1002 }break;
1003
1004 case BTA_AV_REMOTE_CMD_EVT:
1005 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301006 if (bt_rc_callbacks != NULL)
1007 {
1008 BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
1009 __FUNCTION__, p_data->remote_cmd.rc_id,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001010 p_data->remote_cmd.key_state);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301011 /** In race conditions just after 2nd AVRCP is connected
1012 * remote might send pass through commands, so check for
1013 * Rc handle before processing pass through commands
1014 **/
1015 if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
1016 {
1017 handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
1018 }
1019 else
1020 {
1021 BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
1022 }
1023 }
1024 else
1025 {
1026 BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
1027 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001028 }
1029 break;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301030
Mike Lockwood93912472014-06-26 11:08:24 -07001031#if (AVRC_CTLR_INCLUDED == TRUE)
1032 case BTA_AV_REMOTE_RSP_EVT:
1033 {
Sanket Agarwal45d296c2016-02-13 10:19:45 -08001034 BTIF_TRACE_DEBUG("%s RSP: rc_id:0x%x key_state:%d",
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301035 __FUNCTION__, p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state);
1036 if (p_data->remote_rsp.rc_id == AVRC_ID_VENDOR)
1037 {
1038 handle_rc_vendorunique_rsp(&p_data->remote_rsp);
1039 }
1040 else
1041 {
1042 handle_rc_passthrough_rsp(&p_data->remote_rsp);
1043 }
Mike Lockwood93912472014-06-26 11:08:24 -07001044 }
1045 break;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301046
Mike Lockwood93912472014-06-26 11:08:24 -07001047#endif
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001048 case BTA_AV_RC_FEAT_EVT:
1049 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301050 BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001051 btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301052 handle_rc_features(p_data->rc_feat.peer_addr);
1053#if (AVRC_CTLR_INCLUDED == TRUE)
1054 if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
1055 {
1056 handle_rc_ctrl_features(btif_rc_cb.rc_addr);
1057 }
1058#endif
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001059 }
1060 break;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301061
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001062 case BTA_AV_META_MSG_EVT:
1063 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301064 if (bt_rc_callbacks != NULL)
1065 {
1066 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1067 __FUNCTION__,
1068 p_data->meta_msg.code,
1069 p_data->meta_msg.label);
1070 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1071 __FUNCTION__,
1072 p_data->meta_msg.company_id,
1073 p_data->meta_msg.len,
1074 p_data->meta_msg.rc_handle);
1075 /* handle the metamsg command */
1076 handle_rc_metamsg_cmd(&(p_data->meta_msg));
1077 /* Free the Memory allocated for tAVRC_MSG */
1078 }
1079#if (AVRC_CTLR_INCLUDED == TRUE)
1080 else if ((bt_rc_callbacks == NULL)&&(bt_rc_ctrl_callbacks != NULL))
1081 {
1082 /* This is case of Sink + CT + TG(for abs vol)) */
1083 BTIF_TRACE_DEBUG("%s BTA_AV_META_MSG_EVT code:%d label:%d",
1084 __FUNCTION__,
1085 p_data->meta_msg.code,
1086 p_data->meta_msg.label);
1087 BTIF_TRACE_DEBUG("%s company_id:0x%x len:%d handle:%d",
1088 __FUNCTION__,
1089 p_data->meta_msg.company_id,
1090 p_data->meta_msg.len,
1091 p_data->meta_msg.rc_handle);
1092 if ((p_data->meta_msg.code >= AVRC_RSP_NOT_IMPL)&&
1093 (p_data->meta_msg.code <= AVRC_RSP_INTERIM))
1094 {
1095 /* Its a response */
1096 handle_avk_rc_metamsg_rsp(&(p_data->meta_msg));
1097 }
1098 else if (p_data->meta_msg.code <= AVRC_CMD_GEN_INQ)
1099 {
1100 /* Its a command */
1101 handle_avk_rc_metamsg_cmd(&(p_data->meta_msg));
1102 }
1103
1104 }
1105#endif
1106 else
1107 {
1108 BTIF_TRACE_ERROR("Neither CTRL, nor TG is up, drop meta commands");
1109 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001110 }
1111 break;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301112
The Android Open Source Project5738f832012-12-12 16:00:35 -08001113 default:
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301114 BTIF_TRACE_DEBUG("%s Unhandled RC event : 0x%x", __FUNCTION__, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001115 }
1116}
1117
1118/***************************************************************************
1119 **
1120 ** Function btif_rc_get_connected_peer
1121 **
1122 ** Description Fetches the connected headset's BD_ADDR if any
1123 **
1124 ***************************************************************************/
1125BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
1126{
1127 if (btif_rc_cb.rc_connected == TRUE) {
1128 bdcpy(peer_addr, btif_rc_cb.rc_addr);
1129 return TRUE;
1130 }
1131 return FALSE;
1132}
1133
1134/***************************************************************************
1135 **
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301136 ** Function btif_rc_get_connected_peer_handle
1137 **
1138 ** Description Fetches the connected headset's handle if any
1139 **
1140 ***************************************************************************/
1141UINT8 btif_rc_get_connected_peer_handle(void)
1142{
1143 return btif_rc_cb.rc_handle;
1144}
1145
1146/***************************************************************************
1147 **
The Android Open Source Project5738f832012-12-12 16:00:35 -08001148 ** Function btif_rc_check_handle_pending_play
1149 **
1150 ** Description Clears the queued PLAY command. if bSend is TRUE, forwards to app
1151 **
1152 ***************************************************************************/
1153
1154/* clear the queued PLAY command. if bSend is TRUE, forward to app */
1155void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
1156{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001157 UNUSED(peer_addr);
1158
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001159 BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001160 if (btif_rc_cb.rc_pending_play)
1161 {
1162 if (bSendToApp)
1163 {
1164 tBTA_AV_REMOTE_CMD remote_cmd;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001165 APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001166
1167 memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
1168 remote_cmd.rc_handle = btif_rc_cb.rc_handle;
1169 remote_cmd.rc_id = AVRC_ID_PLAY;
1170 remote_cmd.hdr.ctype = AVRC_CMD_CTRL;
1171 remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
1172
1173 /* delay sending to app, else there is a timing issue in the framework,
1174 ** which causes the audio to be on th device's speaker. Delay between
1175 ** OPEN & RC_PLAYs
1176 */
Pavlin Radoslavov642f2332015-09-16 13:30:26 -07001177 sleep_ms(200);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001178 /* send to app - both PRESSED & RELEASED */
1179 remote_cmd.key_state = AVRC_STATE_PRESS;
1180 handle_rc_passthrough_cmd( &remote_cmd );
1181
Pavlin Radoslavov642f2332015-09-16 13:30:26 -07001182 sleep_ms(100);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001183
1184 remote_cmd.key_state = AVRC_STATE_RELEASE;
1185 handle_rc_passthrough_cmd( &remote_cmd );
1186 }
1187 btif_rc_cb.rc_pending_play = FALSE;
1188 }
1189}
1190
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001191/* Generic reject response */
1192static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
1193{
1194 UINT8 ctype = AVRC_RSP_REJ;
1195 tAVRC_RESPONSE avrc_rsp;
1196 BT_HDR *p_msg = NULL;
1197 memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
1198
1199 avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
1200 avrc_rsp.rsp.pdu = pdu;
1201 avrc_rsp.rsp.status = status;
1202
1203 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) )
1204 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001205 BTIF_TRACE_DEBUG("%s:Sending error notification to handle:%d. pdu:%s,status:0x%02x",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001206 __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
1207 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1208 }
1209}
1210
1211/***************************************************************************
1212 * Function send_metamsg_rsp
1213 *
1214 * - Argument:
1215 * rc_handle RC handle corresponding to the connected RC
1216 * label Label of the RC response
1217 * code Response type
1218 * pmetamsg_resp Vendor response
1219 *
1220 * - Description: Remote control metamsg response handler (AVRCP 1.3)
1221 *
1222 ***************************************************************************/
1223static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
1224 tAVRC_RESPONSE *pmetamsg_resp)
1225{
1226 UINT8 ctype;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001227
1228 if (!pmetamsg_resp)
1229 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001230 BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001231 return;
1232 }
1233
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001234 BTIF_TRACE_EVENT("+%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %s", __FUNCTION__,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001235 rc_handle, label, code, dump_rc_pdu(pmetamsg_resp->rsp.pdu));
1236
1237 if (pmetamsg_resp->rsp.status != AVRC_STS_NO_ERROR)
1238 {
1239 ctype = AVRC_RSP_REJ;
1240 }
1241 else
1242 {
1243 if ( code < AVRC_RSP_NOT_IMPL)
1244 {
1245 if (code == AVRC_CMD_NOTIF)
1246 {
1247 ctype = AVRC_RSP_INTERIM;
1248 }
1249 else if (code == AVRC_CMD_STATUS)
1250 {
1251 ctype = AVRC_RSP_IMPL_STBL;
1252 }
1253 else
1254 {
1255 ctype = AVRC_RSP_ACCEPT;
1256 }
1257 }
1258 else
1259 {
1260 ctype = code;
1261 }
1262 }
1263 /* if response is for register_notification, make sure the rc has
1264 actually registered for this */
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301265 if ((pmetamsg_resp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED))
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001266 {
1267 BOOLEAN bSent = FALSE;
1268 UINT8 event_id = pmetamsg_resp->reg_notif.event_id;
1269 BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
1270
1271 /* de-register this notification for a CHANGED response */
1272 btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001273 BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001274 btif_rc_cb.rc_handle, event_id, bNotify);
1275 if (bNotify)
1276 {
1277 BT_HDR *p_msg = NULL;
1278 tAVRC_STS status;
1279
1280 if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
1281 pmetamsg_resp, &p_msg)) )
1282 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001283 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001284 __FUNCTION__, btif_rc_cb.rc_handle, event_id);
1285 bSent = TRUE;
1286 BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1287 ctype, p_msg);
1288 }
1289 else
1290 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001291 BTIF_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001292 __FUNCTION__, status);
1293 }
1294
1295 }
1296
1297 if (!bSent)
1298 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001299 BTIF_TRACE_DEBUG("%s: Notification not sent, as there are no RC connections or the \
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001300 CT has not subscribed for event_id: %s", __FUNCTION__, dump_rc_notification_event_id(event_id));
1301 }
1302 }
1303 else
1304 {
1305 /* All other commands go here */
1306
1307 BT_HDR *p_msg = NULL;
1308 tAVRC_STS status;
1309
1310 status = AVRC_BldResponse(rc_handle, pmetamsg_resp, &p_msg);
1311
1312 if (status == AVRC_STS_NO_ERROR)
1313 {
1314 BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
1315 }
1316 else
1317 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001318 BTIF_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001319 __FUNCTION__, status);
1320 }
1321 }
1322}
1323
1324static UINT8 opcode_from_pdu(UINT8 pdu)
1325{
1326 UINT8 opcode = 0;
1327
1328 switch (pdu)
1329 {
1330 case AVRC_PDU_NEXT_GROUP:
1331 case AVRC_PDU_PREV_GROUP: /* pass thru */
1332 opcode = AVRC_OP_PASS_THRU;
1333 break;
1334
1335 default: /* vendor */
1336 opcode = AVRC_OP_VENDOR;
1337 break;
1338 }
1339
1340 return opcode;
1341}
1342
1343/*******************************************************************************
1344**
1345** Function btif_rc_upstreams_evt
1346**
1347** Description Executes AVRC UPSTREAMS events in btif context.
1348**
1349** Returns void
1350**
1351*******************************************************************************/
1352static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
1353{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001354 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001355 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
1356
1357 switch (event)
1358 {
1359 case AVRC_PDU_GET_PLAY_STATUS:
1360 {
1361 FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
1362 HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
1363 }
1364 break;
1365 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
1366 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
1367 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
1368 case AVRC_PDU_SET_PLAYER_APP_VALUE:
1369 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
1370 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
1371 {
1372 /* TODO: Add support for Application Settings */
Zhihai Xu081d6e52013-03-29 17:27:01 -07001373 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001374 }
1375 break;
1376 case AVRC_PDU_GET_ELEMENT_ATTR:
1377 {
1378 btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1379 UINT8 num_attr;
Ravi Nagarajan841e5b52013-03-22 04:16:57 -07001380 memset(&element_attrs, 0, sizeof(element_attrs));
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001381 if (pavrc_cmd->get_elem_attrs.num_attr == 0)
1382 {
1383 /* CT requests for all attributes */
1384 int attr_cnt;
Ravi Nagarajan841e5b52013-03-22 04:16:57 -07001385 num_attr = BTRC_MAX_ELEM_ATTR_SIZE;
1386 for (attr_cnt = 0; attr_cnt < BTRC_MAX_ELEM_ATTR_SIZE; attr_cnt++)
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001387 {
Ravi Nagarajan841e5b52013-03-22 04:16:57 -07001388 element_attrs[attr_cnt] = attr_cnt + 1;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001389 }
1390 }
1391 else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
1392 {
Ravi Nagarajan841e5b52013-03-22 04:16:57 -07001393 /* 0xff indicates, no attributes requested - reject */
1394 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1395 AVRC_STS_BAD_PARAM);
1396 return;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001397 }
1398 else
1399 {
Mallikarjuna GB0d65d4c2013-11-10 13:30:25 +05301400 int attr_cnt, filled_attr_count;
1401
1402 num_attr = 0;
1403 /* Attribute IDs from 1 to AVRC_MAX_NUM_MEDIA_ATTR_ID are only valid,
1404 * hence HAL definition limits the attributes to AVRC_MAX_NUM_MEDIA_ATTR_ID.
1405 * Fill only valid entries.
1406 */
1407 for (attr_cnt = 0; (attr_cnt < pavrc_cmd->get_elem_attrs.num_attr) &&
1408 (num_attr < AVRC_MAX_NUM_MEDIA_ATTR_ID); attr_cnt++)
1409 {
1410 if ((pavrc_cmd->get_elem_attrs.attrs[attr_cnt] > 0) &&
1411 (pavrc_cmd->get_elem_attrs.attrs[attr_cnt] <= AVRC_MAX_NUM_MEDIA_ATTR_ID))
1412 {
1413 /* Skip the duplicate entries : PTS sends duplicate entries for Fragment cases
1414 */
1415 for (filled_attr_count = 0; filled_attr_count < num_attr; filled_attr_count++)
1416 {
1417 if (element_attrs[filled_attr_count] == pavrc_cmd->get_elem_attrs.attrs[attr_cnt])
1418 break;
1419 }
1420 if (filled_attr_count == num_attr)
1421 {
1422 element_attrs[num_attr] = pavrc_cmd->get_elem_attrs.attrs[attr_cnt];
1423 num_attr++;
1424 }
1425 }
1426 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001427 }
1428 FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
1429 HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
1430 }
1431 break;
1432 case AVRC_PDU_REGISTER_NOTIFICATION:
1433 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301434 if (pavrc_cmd->reg_notif.event_id == BTRC_EVT_PLAY_POS_CHANGED &&
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001435 pavrc_cmd->reg_notif.param == 0)
1436 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001437 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001438 __FUNCTION__);
1439 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
1440 /* de-register this notification for a rejected response */
1441 btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
1442 return;
1443 }
1444 HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
1445 pavrc_cmd->reg_notif.param);
1446 }
1447 break;
1448 case AVRC_PDU_INFORM_DISPLAY_CHARSET:
1449 {
1450 tAVRC_RESPONSE avrc_rsp;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001451 BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301452 if (btif_rc_cb.rc_connected == TRUE)
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001453 {
1454 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
1455 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
1456 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
1457 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
1458 send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
1459 }
1460 }
1461 break;
1462 default:
1463 {
1464 send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
1465 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:AVRC_STS_BAD_CMD);
1466 return;
1467 }
1468 break;
1469 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001470}
1471
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301472#if (AVRC_CTLR_INCLUDED == TRUE)
1473/*******************************************************************************
1474**
1475** Function btif_rc_ctrl_upstreams_rsp_cmd
1476**
1477** Description Executes AVRC UPSTREAMS response events in btif context.
1478**
1479** Returns void
1480**
1481*******************************************************************************/
1482static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd,
1483 UINT8 label)
1484{
1485 BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
1486 dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
1487 bt_bdaddr_t rc_addr;
1488 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
1489#if (AVRC_CTLR_INCLUDED == TRUE)
1490 switch (event)
1491 {
1492 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1493 HAL_CBACK(bt_rc_ctrl_callbacks,setabsvol_cmd_cb, &rc_addr,
1494 pavrc_cmd->volume.volume, label);
1495 break;
1496 case AVRC_PDU_REGISTER_NOTIFICATION:
1497 if (pavrc_cmd->reg_notif.event_id == AVRC_EVT_VOLUME_CHANGE)
1498 {
1499 HAL_CBACK(bt_rc_ctrl_callbacks, registernotification_absvol_cb,
1500 &rc_addr, label);
1501 }
1502 break;
1503 }
1504#endif
1505}
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301506#endif
1507
Prashant Malanif85869d2016-02-25 18:26:13 -08001508#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -07001509/*******************************************************************************
1510**
1511** Function btif_rc_upstreams_rsp_evt
1512**
1513** Description Executes AVRC UPSTREAMS response events in btif context.
1514**
1515** Returns void
1516**
1517*******************************************************************************/
1518static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
1519{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001520 BTIF_TRACE_EVENT("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
Satya Calloji247c68f2013-08-01 02:14:43 -07001521 dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
1522
Satya Calloji247c68f2013-08-01 02:14:43 -07001523 switch (event)
1524 {
1525 case AVRC_PDU_REGISTER_NOTIFICATION:
1526 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301527 if (AVRC_RSP_CHANGED==ctype)
Satya Calloji247c68f2013-08-01 02:14:43 -07001528 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
1529 HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
1530 }
1531 break;
1532
1533 case AVRC_PDU_SET_ABSOLUTE_VOLUME:
1534 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301535 BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
1536 __FUNCTION__, pavrc_resp->volume.volume,ctype);
1537 if (AVRC_RSP_ACCEPT==ctype)
Satya Calloji247c68f2013-08-01 02:14:43 -07001538 btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
1539 HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
1540 }
1541 break;
1542
1543 default:
1544 return;
1545 }
Satya Calloji247c68f2013-08-01 02:14:43 -07001546}
Prashant Malanif85869d2016-02-25 18:26:13 -08001547#endif
Satya Calloji247c68f2013-08-01 02:14:43 -07001548
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001549/************************************************************************************
1550** AVRCP API Functions
1551************************************************************************************/
1552
1553/*******************************************************************************
1554**
1555** Function init
1556**
1557** Description Initializes the AVRC interface
1558**
1559** Returns bt_status_t
1560**
1561*******************************************************************************/
1562static bt_status_t init(btrc_callbacks_t* callbacks )
1563{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001564 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001565 bt_status_t result = BT_STATUS_SUCCESS;
1566
1567 if (bt_rc_callbacks)
1568 return BT_STATUS_DONE;
1569
1570 bt_rc_callbacks = callbacks;
1571 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
Satya Calloji247c68f2013-08-01 02:14:43 -07001572 btif_rc_cb.rc_vol_label=MAX_LABEL;
1573 btif_rc_cb.rc_volume=MAX_VOLUME;
1574 lbl_init();
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001575
1576 return result;
1577}
1578
Mike Lockwood4ad470e2014-06-02 16:21:49 -07001579/*******************************************************************************
1580**
1581** Function init_ctrl
1582**
1583** Description Initializes the AVRC interface
1584**
1585** Returns bt_status_t
1586**
1587*******************************************************************************/
1588static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
1589{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001590 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07001591 bt_status_t result = BT_STATUS_SUCCESS;
1592
1593 if (bt_rc_ctrl_callbacks)
1594 return BT_STATUS_DONE;
1595
1596 bt_rc_ctrl_callbacks = callbacks;
1597 memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
1598 btif_rc_cb.rc_vol_label=MAX_LABEL;
1599 btif_rc_cb.rc_volume=MAX_VOLUME;
1600 lbl_init();
1601
1602 return result;
1603}
1604
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301605static void rc_ctrl_procedure_complete ()
1606{
1607 if (btif_rc_cb.rc_procedure_complete == TRUE)
1608 {
1609 return;
1610 }
1611 btif_rc_cb.rc_procedure_complete = TRUE;
1612 UINT32 attr_list[] = {
1613 AVRC_MEDIA_ATTR_ID_TITLE,
1614 AVRC_MEDIA_ATTR_ID_ARTIST,
1615 AVRC_MEDIA_ATTR_ID_ALBUM,
1616 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
1617 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
1618 AVRC_MEDIA_ATTR_ID_GENRE,
1619 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
1620 };
1621 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
1622}
1623
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001624/***************************************************************************
1625**
1626** Function get_play_status_rsp
1627**
1628** Description Returns the current play status.
1629** This method is called in response to
1630** GetPlayStatus request.
1631**
1632** Returns bt_status_t
1633**
1634***************************************************************************/
1635static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
1636 uint32_t song_pos)
1637{
1638 tAVRC_RESPONSE avrc_rsp;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001639 CHECK_RC_CONNECTED
1640 memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
1641 avrc_rsp.get_play_status.song_len = song_len;
1642 avrc_rsp.get_play_status.song_pos = song_pos;
1643 avrc_rsp.get_play_status.play_status = play_status;
1644
1645 avrc_rsp.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
1646 avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
Ravi Nagarajanb88fc6c2013-04-02 07:11:14 -07001647 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001648 /* Send the response */
1649 SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
1650 return BT_STATUS_SUCCESS;
1651}
1652
1653/***************************************************************************
1654**
1655** Function get_element_attr_rsp
1656**
1657** Description Returns the current songs' element attributes
1658** in text.
1659**
1660** Returns bt_status_t
1661**
1662***************************************************************************/
1663static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
1664{
1665 tAVRC_RESPONSE avrc_rsp;
1666 UINT32 i;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001667 tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
1668 CHECK_RC_CONNECTED
1669 memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
1670
1671 if (num_attr == 0)
1672 {
1673 avrc_rsp.get_play_status.status = AVRC_STS_BAD_PARAM;
1674 }
1675 else
1676 {
1677 for (i=0; i<num_attr; i++) {
1678 element_attrs[i].attr_id = p_attrs[i].attr_id;
1679 element_attrs[i].name.charset_id = AVRC_CHARSET_ID_UTF8;
1680 element_attrs[i].name.str_len = (UINT16)strlen((char *)p_attrs[i].text);
1681 element_attrs[i].name.p_str = p_attrs[i].text;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001682 BTIF_TRACE_DEBUG("%s attr_id:0x%x, charset_id:0x%x, str_len:%d, str:%s",
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301683 __FUNCTION__, (unsigned int)element_attrs[i].attr_id,
1684 element_attrs[i].name.charset_id, element_attrs[i].name.str_len,
1685 element_attrs[i].name.p_str);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001686 }
1687 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1688 }
1689 avrc_rsp.get_elem_attrs.num_attr = num_attr;
1690 avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
1691 avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1692 avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
1693 /* Send the response */
1694 SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
1695 return BT_STATUS_SUCCESS;
1696}
1697
1698/***************************************************************************
1699**
1700** Function register_notification_rsp
1701**
1702** Description Response to the register notification request.
1703** in text.
1704**
1705** Returns bt_status_t
1706**
1707***************************************************************************/
1708static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
1709 btrc_notification_type_t type, btrc_register_notification_t *p_param)
1710{
1711 tAVRC_RESPONSE avrc_rsp;
1712 CHECK_RC_CONNECTED
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001713 BTIF_TRACE_EVENT("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
Nitin Srivastava68c53de2014-02-13 19:31:40 +05301714 if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
1715 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001716 BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
Nitin Srivastava68c53de2014-02-13 19:31:40 +05301717 return BT_STATUS_NOT_READY;
1718 }
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001719 memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1720 avrc_rsp.reg_notif.event_id = event_id;
1721
1722 switch(event_id)
1723 {
1724 case BTRC_EVT_PLAY_STATUS_CHANGED:
1725 avrc_rsp.reg_notif.param.play_status = p_param->play_status;
Anubhav Gupta9c5d0722013-07-27 14:46:29 +05301726 if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
1727 btif_av_clear_remote_suspend_flag();
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001728 break;
1729 case BTRC_EVT_TRACK_CHANGE:
1730 memcpy(&(avrc_rsp.reg_notif.param.track), &(p_param->track), sizeof(btrc_uid_t));
1731 break;
Ravi Nagarajanb88fc6c2013-04-02 07:11:14 -07001732 case BTRC_EVT_PLAY_POS_CHANGED:
1733 avrc_rsp.reg_notif.param.play_pos = p_param->song_pos;
1734 break;
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001735 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001736 BTIF_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08001737 return BT_STATUS_UNHANDLED;
1738 }
1739
1740 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1741 avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1742 avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1743
1744 /* Send the response. */
1745 send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
1746 ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
1747 return BT_STATUS_SUCCESS;
1748}
1749
1750/***************************************************************************
1751**
Satya Calloji247c68f2013-08-01 02:14:43 -07001752** Function set_volume
1753**
1754** Description Send current volume setting to remote side.
1755** Support limited to SetAbsoluteVolume
1756** This can be enhanced to support Relative Volume (AVRCP 1.0).
1757** With RelateVolume, we will send VOLUME_UP/VOLUME_DOWN
1758** as opposed to absolute volume level
1759** volume: Should be in the range 0-127. bit7 is reseved and cannot be set
1760**
1761** Returns bt_status_t
1762**
1763***************************************************************************/
1764static bt_status_t set_volume(uint8_t volume)
1765{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001766 BTIF_TRACE_DEBUG("%s", __FUNCTION__);
Satya Calloji247c68f2013-08-01 02:14:43 -07001767 CHECK_RC_CONNECTED
1768 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1769 rc_transaction_t *p_transaction=NULL;
1770
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301771 if (btif_rc_cb.rc_volume==volume)
Satya Calloji247c68f2013-08-01 02:14:43 -07001772 {
1773 status=BT_STATUS_DONE;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001774 BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
Satya Calloji247c68f2013-08-01 02:14:43 -07001775 return status;
1776 }
1777
1778 if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
1779 (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
1780 {
1781 tAVRC_COMMAND avrc_cmd = {0};
1782 BT_HDR *p_msg = NULL;
1783
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001784 BTIF_TRACE_DEBUG("%s: Peer supports absolute volume. newVolume=%d", __FUNCTION__, volume);
Satya Calloji247c68f2013-08-01 02:14:43 -07001785 avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1786 avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1787 avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1788 avrc_cmd.volume.volume = volume;
1789
1790 if (AVRC_BldCommand(&avrc_cmd, &p_msg) == AVRC_STS_NO_ERROR)
1791 {
1792 bt_status_t tran_status=get_transaction(&p_transaction);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301793 if (BT_STATUS_SUCCESS == tran_status && NULL!=p_transaction)
Satya Calloji247c68f2013-08-01 02:14:43 -07001794 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001795 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
Satya Calloji247c68f2013-08-01 02:14:43 -07001796 __FUNCTION__,p_transaction->lbl);
1797 BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
1798 status = BT_STATUS_SUCCESS;
1799 }
1800 else
1801 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001802 osi_free(p_msg);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001803 BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
Satya Calloji247c68f2013-08-01 02:14:43 -07001804 __FUNCTION__, tran_status);
1805 status = BT_STATUS_FAIL;
1806 }
1807 }
1808 else
1809 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001810 BTIF_TRACE_ERROR("%s: failed to build absolute volume command. status: 0x%02x",
Satya Calloji247c68f2013-08-01 02:14:43 -07001811 __FUNCTION__, status);
1812 status = BT_STATUS_FAIL;
1813 }
1814 }
1815 else
1816 status=BT_STATUS_NOT_READY;
1817 return status;
1818}
1819
Prashant Malanif85869d2016-02-25 18:26:13 -08001820#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
Satya Calloji247c68f2013-08-01 02:14:43 -07001821/***************************************************************************
1822**
1823** Function register_volumechange
1824**
1825** Description Register for volume change notification from remote side.
1826**
1827** Returns void
1828**
1829***************************************************************************/
1830
1831static void register_volumechange (UINT8 lbl)
1832{
1833 tAVRC_COMMAND avrc_cmd = {0};
1834 BT_HDR *p_msg = NULL;
1835 tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
Satya Calloji247c68f2013-08-01 02:14:43 -07001836 rc_transaction_t *p_transaction=NULL;
1837
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001838 BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
Satya Calloji247c68f2013-08-01 02:14:43 -07001839
1840 avrc_cmd.cmd.opcode=0x00;
1841 avrc_cmd.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1842 avrc_cmd.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
1843 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301844 avrc_cmd.reg_notif.param = 0;
Satya Calloji247c68f2013-08-01 02:14:43 -07001845
1846 BldResp=AVRC_BldCommand(&avrc_cmd, &p_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08001847 if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
1848 p_transaction = get_transaction_by_lbl(lbl);
1849 if (p_transaction != NULL) {
1850 BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
1851 AVRC_CMD_NOTIF, p_msg);
1852 BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
1853 } else {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001854 osi_free(p_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08001855 BTIF_TRACE_ERROR("%s transaction not obtained with label: %d",
1856 __func__, lbl);
Satya Calloji247c68f2013-08-01 02:14:43 -07001857 }
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08001858 } else {
1859 BTIF_TRACE_ERROR("%s failed to build command:%d", __func__, BldResp);
Satya Calloji247c68f2013-08-01 02:14:43 -07001860 }
Satya Calloji247c68f2013-08-01 02:14:43 -07001861}
1862
Satya Calloji247c68f2013-08-01 02:14:43 -07001863/***************************************************************************
1864**
1865** Function handle_rc_metamsg_rsp
1866**
1867** Description Handle RC metamessage response
1868**
1869** Returns void
1870**
1871***************************************************************************/
1872static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
1873{
1874 tAVRC_RESPONSE avrc_response = {0};
1875 UINT8 scratch_buf[512] = {0};
1876 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1877
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301878 if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
Satya Calloji247c68f2013-08-01 02:14:43 -07001879 || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
1880 || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
1881 {
1882 status=AVRC_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, sizeof(scratch_buf));
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001883 BTIF_TRACE_DEBUG("%s: code %d,event ID %d,PDU %x,parsing status %d, label:%d",
Satya Calloji247c68f2013-08-01 02:14:43 -07001884 __FUNCTION__,pmeta_msg->code,avrc_response.reg_notif.event_id,avrc_response.reg_notif.pdu,
1885 status, pmeta_msg->label);
1886
1887 if (status != AVRC_STS_NO_ERROR)
1888 {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301889 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
Satya Calloji247c68f2013-08-01 02:14:43 -07001890 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1891 && btif_rc_cb.rc_vol_label==pmeta_msg->label)
1892 {
1893 btif_rc_cb.rc_vol_label=MAX_LABEL;
1894 release_transaction(btif_rc_cb.rc_vol_label);
1895 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301896 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
Satya Calloji247c68f2013-08-01 02:14:43 -07001897 {
1898 release_transaction(pmeta_msg->label);
1899 }
1900 return;
1901 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301902 else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
Satya Calloji247c68f2013-08-01 02:14:43 -07001903 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1904 && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
1905 {
1906 // Just discard the message, if the device sends back with an incorrect label
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001907 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
Satya Calloji247c68f2013-08-01 02:14:43 -07001908 __FUNCTION__, pmeta_msg->code, pmeta_msg->label);
1909 return;
1910 }
1911 }
1912 else
1913 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001914 BTIF_TRACE_DEBUG("%s:Received vendor dependent in adv ctrl rsp. code: %d len: %d. Not processing it.",
Satya Calloji247c68f2013-08-01 02:14:43 -07001915 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
1916 return;
1917 }
1918
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301919 if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
Satya Calloji247c68f2013-08-01 02:14:43 -07001920 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
1921 && AVRC_RSP_CHANGED==pmeta_msg->code)
1922 {
1923 /* re-register for volume change notification */
1924 // Do not re-register for rejected case, as it might get into endless loop
1925 register_volumechange(btif_rc_cb.rc_vol_label);
1926 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301927 else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
Satya Calloji247c68f2013-08-01 02:14:43 -07001928 {
1929 /* free up the label here */
1930 release_transaction(pmeta_msg->label);
1931 }
1932
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001933 BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
Satya Calloji247c68f2013-08-01 02:14:43 -07001934 __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
1935 btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
1936 pmeta_msg->label);
1937}
Prashant Malanif85869d2016-02-25 18:26:13 -08001938#endif
Satya Calloji247c68f2013-08-01 02:14:43 -07001939
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301940#if (AVRC_CTLR_INCLUDED == TRUE)
1941/***************************************************************************
1942**
1943** Function iterate_supported_event_list_for_interim_rsp
1944**
1945** Description iterator callback function to match the event and handle
1946** timer cleanup
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001947** Returns true to continue iterating, false to stop
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301948**
1949***************************************************************************/
1950bool iterate_supported_event_list_for_interim_rsp(void *data, void *cb_data)
1951{
1952 UINT8 *p_event_id;
1953 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1954
1955 p_event_id = (UINT8*)cb_data;
1956
1957 if (p_event->event_id == *p_event_id)
1958 {
1959 p_event->status = eINTERIM;
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001960 return false;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301961 }
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001962 return true;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301963}
1964
1965/***************************************************************************
1966**
1967** Function iterate_supported_event_list_for_timeout
1968**
1969** Description Iterator callback function for timeout handling.
1970** As part of the failure handling, it releases the
1971** transaction label and removes the event from list,
1972** this event will not be requested again during
1973** the lifetime of the connection.
1974** Returns false to stop iterating, true to continue
1975**
1976***************************************************************************/
1977bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
1978{
1979 UINT8 label;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301980 btif_rc_supported_event_t *p_event = (btif_rc_supported_event_t *)data;
1981
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001982 label = (*(UINT8*)cb_data) & 0xFF;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301983
1984 if (p_event->label == label)
1985 {
1986 list_remove(btif_rc_cb.rc_supported_event_list, p_event);
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001987 return false;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301988 }
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08001989 return true;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05301990}
1991
1992/***************************************************************************
1993**
1994** Function rc_notification_interim_timout
1995**
1996** Description Interim response timeout handler.
1997** Runs the iterator to check and clear the timed out event.
1998** Proceeds to register for the unregistered events.
1999** Returns None
2000**
2001***************************************************************************/
2002static void rc_notification_interim_timout (UINT8 label)
2003{
2004 list_node_t *node;
2005
2006 list_foreach(btif_rc_cb.rc_supported_event_list,
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08002007 iterate_supported_event_list_for_timeout, &label);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302008 /* Timeout happened for interim response for the registered event,
2009 * check if there are any pending for registration
2010 */
2011 node = list_begin(btif_rc_cb.rc_supported_event_list);
2012 while (node != NULL)
2013 {
2014 btif_rc_supported_event_t *p_event;
2015
2016 p_event = (btif_rc_supported_event_t *)list_node(node);
2017 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2018 {
2019 register_for_event_notification(p_event);
2020 break;
2021 }
2022 node = list_next (node);
2023 }
2024 /* Todo. Need to initiate application settings query if this
2025 * is the last event registration.
2026 */
2027}
2028
2029/***************************************************************************
2030**
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002031** Function btif_rc_status_cmd_timeout_handler
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302032**
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002033** Description RC status command timeout handler (Runs in BTIF context).
2034** Returns None
2035**
2036***************************************************************************/
2037static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2038 char *data)
2039{
2040 btif_rc_timer_context_t *p_context;
2041 tAVRC_RESPONSE avrc_response = {0};
2042 tBTA_AV_META_MSG meta_msg;
2043
2044 p_context = (btif_rc_timer_context_t *)data;
2045 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2046 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2047
2048 switch (p_context->rc_status_cmd.pdu_id) {
2049 case AVRC_PDU_REGISTER_NOTIFICATION:
2050 rc_notification_interim_timout(p_context->rc_status_cmd.label);
2051 break;
2052
2053 case AVRC_PDU_GET_CAPABILITIES:
2054 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2055 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2056 break;
2057
2058 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
2059 avrc_response.list_app_attr.status = BTIF_RC_STS_TIMEOUT;
2060 handle_app_attr_response(&meta_msg, &avrc_response.list_app_attr);
2061 break;
2062
2063 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
2064 avrc_response.list_app_values.status = BTIF_RC_STS_TIMEOUT;
2065 handle_app_val_response(&meta_msg, &avrc_response.list_app_values);
2066 break;
2067
2068 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
2069 avrc_response.get_cur_app_val.status = BTIF_RC_STS_TIMEOUT;
2070 handle_app_cur_val_response(&meta_msg, &avrc_response.get_cur_app_val);
2071 break;
2072
2073 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
2074 avrc_response.get_app_attr_txt.status = BTIF_RC_STS_TIMEOUT;
2075 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_attr_txt);
2076 break;
2077
2078 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
2079 avrc_response.get_app_val_txt.status = BTIF_RC_STS_TIMEOUT;
2080 handle_app_attr_txt_response(&meta_msg, &avrc_response.get_app_val_txt);
2081 break;
2082
2083 case AVRC_PDU_GET_ELEMENT_ATTR:
2084 avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
2085 handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
2086 break;
2087
2088 case AVRC_PDU_GET_PLAY_STATUS:
2089 avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT;
2090 handle_get_capability_response(&meta_msg, &avrc_response.get_caps);
2091 break;
2092 }
2093 release_transaction(p_context->rc_status_cmd.label);
2094}
2095
2096/***************************************************************************
2097**
2098** Function btif_rc_status_cmd_timer_timeout
2099**
2100** Description RC status command timeout callback.
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302101** This is called from BTU context and switches to BTIF
2102** context to handle the timeout events
2103** Returns None
2104**
2105***************************************************************************/
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002106static void btif_rc_status_cmd_timer_timeout(void *data)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302107{
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002108 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302109
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002110 btif_transfer_context(btif_rc_status_cmd_timeout_handler, 0,
2111 (char *)p_data, sizeof(btif_rc_timer_context_t),
2112 NULL);
2113}
2114
2115/***************************************************************************
2116**
2117** Function btif_rc_control_cmd_timeout_handler
2118**
2119** Description RC control command timeout handler (Runs in BTIF context).
2120** Returns None
2121**
2122***************************************************************************/
2123static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
2124 char *data)
2125{
2126 btif_rc_timer_context_t *p_context = (btif_rc_timer_context_t *)data;
2127 tAVRC_RESPONSE avrc_response = {0};
2128 tBTA_AV_META_MSG meta_msg;
2129
2130 memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
2131 meta_msg.rc_handle = btif_rc_cb.rc_handle;
2132
2133 switch (p_context->rc_control_cmd.pdu_id) {
2134 case AVRC_PDU_SET_PLAYER_APP_VALUE:
2135 avrc_response.set_app_val.status = BTIF_RC_STS_TIMEOUT;
2136 handle_set_app_attr_val_response(&meta_msg,
2137 &avrc_response.set_app_val);
2138 break;
2139 }
2140 release_transaction(p_context->rc_control_cmd.label);
2141}
2142
2143/***************************************************************************
2144**
2145** Function btif_rc_control_cmd_timer_timeout
2146**
2147** Description RC control command timeout callback.
2148** This is called from BTU context and switches to BTIF
2149** context to handle the timeout events
2150** Returns None
2151**
2152***************************************************************************/
2153static void btif_rc_control_cmd_timer_timeout(void *data)
2154{
2155 btif_rc_timer_context_t *p_data = (btif_rc_timer_context_t *)data;
2156
2157 btif_transfer_context(btif_rc_control_cmd_timeout_handler, 0,
2158 (char *)p_data, sizeof(btif_rc_timer_context_t),
2159 NULL);
2160}
2161
2162/***************************************************************************
2163**
2164** Function btif_rc_play_status_timeout_handler
2165**
2166** Description RC play status timeout handler (Runs in BTIF context).
2167** Returns None
2168**
2169***************************************************************************/
2170static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
2171 UNUSED_ATTR char *p_data)
2172{
2173 get_play_status_cmd();
2174 rc_start_play_status_timer();
2175}
2176
2177/***************************************************************************
2178**
2179** Function btif_rc_play_status_timer_timeout
2180**
2181** Description RC play status timeout callback.
2182** This is called from BTU context and switches to BTIF
2183** context to handle the timeout events
2184** Returns None
2185**
2186***************************************************************************/
2187static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
2188{
2189 btif_transfer_context(btif_rc_play_status_timeout_handler, 0, 0, 0, NULL);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302190}
2191
2192/***************************************************************************
2193**
2194** Function rc_start_play_status_timer
2195**
2196** Description Helper function to start the timer to fetch play status.
2197** Returns None
2198**
2199***************************************************************************/
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002200static void rc_start_play_status_timer(void)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302201{
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302202 /* Start the Play status timer only if it is not started */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002203 if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
2204 if (btif_rc_cb.rc_play_status_timer == NULL) {
2205 btif_rc_cb.rc_play_status_timer =
2206 alarm_new("btif_rc.rc_play_status_timer");
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302207 }
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002208 alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
2209 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2210 btif_rc_play_status_timer_timeout, NULL,
2211 btu_general_alarm_queue);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302212 }
2213}
2214
2215/***************************************************************************
2216**
2217** Function rc_stop_play_status_timer
2218**
2219** Description Helper function to stop the play status timer.
2220** Returns None
2221**
2222***************************************************************************/
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002223void rc_stop_play_status_timer()
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302224{
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002225 if (btif_rc_cb.rc_play_status_timer != NULL)
2226 alarm_cancel(btif_rc_cb.rc_play_status_timer);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302227}
2228
2229/***************************************************************************
2230**
2231** Function register_for_event_notification
2232**
2233** Description Helper function registering notification events
2234** sets an interim response timeout to handle if the remote
2235** does not respond.
2236** Returns None
2237**
2238***************************************************************************/
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002239static void register_for_event_notification(btif_rc_supported_event_t *p_event)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302240{
2241 bt_status_t status;
2242 rc_transaction_t *p_transaction;
2243
2244 status = get_transaction(&p_transaction);
2245 if (status == BT_STATUS_SUCCESS)
2246 {
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002247 btif_rc_timer_context_t *p_context = &p_transaction->txn_timer_context;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302248
2249 status = register_notification_cmd (p_transaction->lbl, p_event->event_id, 0);
2250 if (status != BT_STATUS_SUCCESS)
2251 {
2252 BTIF_TRACE_ERROR("%s Error in Notification registration %d",
2253 __FUNCTION__, status);
2254 release_transaction (p_transaction->lbl);
2255 return;
2256 }
2257 p_event->label = p_transaction->lbl;
2258 p_event->status = eREGISTERED;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002259 p_context->rc_status_cmd.label = p_transaction->lbl;
2260 p_context->rc_status_cmd.pdu_id = AVRC_PDU_REGISTER_NOTIFICATION;
2261
2262 alarm_free(p_transaction->txn_timer);
2263 p_transaction->txn_timer =
2264 alarm_new("btif_rc.status_command_txn_timer");
2265 alarm_set_on_queue(p_transaction->txn_timer,
2266 BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
2267 btif_rc_status_cmd_timer_timeout, p_context,
2268 btu_general_alarm_queue);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302269 }
2270 else
2271 {
2272 BTIF_TRACE_ERROR("%s Error No more Transaction label %d",
2273 __FUNCTION__, status);
2274 }
2275}
2276
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002277static void start_status_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302278{
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002279 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2280 p_context->rc_status_cmd.label = p_txn->lbl;
2281 p_context->rc_status_cmd.pdu_id = pdu_id;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302282
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002283 alarm_free(p_txn->txn_timer);
2284 p_txn->txn_timer = alarm_new("btif_rc.status_command_txn_timer");
2285 alarm_set_on_queue(p_txn->txn_timer, BTIF_TIMEOUT_RC_STATUS_CMD_MS,
2286 btif_rc_status_cmd_timer_timeout, p_context,
2287 btu_general_alarm_queue);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302288}
2289
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002290static void start_control_command_timer(UINT8 pdu_id, rc_transaction_t *p_txn)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302291{
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002292 btif_rc_timer_context_t *p_context = &p_txn->txn_timer_context;
2293 p_context->rc_control_cmd.label = p_txn->lbl;
2294 p_context->rc_control_cmd.pdu_id = pdu_id;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302295
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002296 alarm_free(p_txn->txn_timer);
2297 p_txn->txn_timer = alarm_new("btif_rc.control_command_txn_timer");
2298 alarm_set_on_queue(p_txn->txn_timer,
2299 BTIF_TIMEOUT_RC_CONTROL_CMD_MS,
2300 btif_rc_control_cmd_timer_timeout, p_context,
2301 btu_general_alarm_queue);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302302}
2303
2304/***************************************************************************
2305**
2306** Function handle_get_capability_response
2307**
2308** Description Handles the get_cap_response to populate company id info
2309** and query the supported events.
2310** Initiates Notification registration for events supported
2311** Returns None
2312**
2313***************************************************************************/
2314static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CAPS_RSP *p_rsp)
2315{
2316 int xx = 0;
2317
2318 /* Todo: Do we need to retry on command timeout */
2319 if (p_rsp->status != AVRC_STS_NO_ERROR)
2320 {
2321 BTIF_TRACE_ERROR("%s Error capability response 0x%02X",
2322 __FUNCTION__, p_rsp->status);
2323 return;
2324 }
2325
2326 if (p_rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED)
2327 {
2328 btif_rc_supported_event_t *p_event;
2329
2330 /* Todo: Check if list can be active when we hit here */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002331 btif_rc_cb.rc_supported_event_list = list_new(osi_free);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302332 for (xx = 0; xx < p_rsp->count; xx++)
2333 {
2334 /* Skip registering for Play position change notification */
2335 if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE)||
2336 (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE)||
2337 (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE))
2338 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002339 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302340 p_event->event_id = p_rsp->param.event_id[xx];
2341 p_event->status = eNOT_REGISTERED;
2342 list_append(btif_rc_cb.rc_supported_event_list, p_event);
2343 }
2344 }
2345 p_event = list_front(btif_rc_cb.rc_supported_event_list);
2346 if (p_event != NULL)
2347 {
2348 register_for_event_notification(p_event);
2349 }
2350 }
2351 else if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID)
2352 {
2353 getcapabilities_cmd (AVRC_CAP_EVENTS_SUPPORTED);
2354 BTIF_TRACE_EVENT("%s AVRC_CAP_COMPANY_ID: ", __FUNCTION__);
2355 for (xx = 0; xx < p_rsp->count; xx++)
2356 {
2357 BTIF_TRACE_EVENT("%s : %d", __FUNCTION__, p_rsp->param.company_id[xx]);
2358 }
2359 }
2360}
2361
2362bool rc_is_track_id_valid (tAVRC_UID uid)
2363{
2364 tAVRC_UID invalid_uid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2365
2366 if (memcmp(uid, invalid_uid, sizeof(tAVRC_UID)) == 0)
2367 {
2368 return false;
2369 }
2370 else
2371 {
2372 return true;
2373 }
2374}
2375
2376/***************************************************************************
2377**
2378** Function handle_notification_response
2379**
2380** Description Main handler for notification responses to registered events
2381** 1. Register for unregistered event(in interim response path)
2382** 2. After registering for all supported events, start
2383** retrieving application settings and values
2384** 3. Reregister for events on getting changed response
2385** 4. Run play status timer for getting position when the
2386** status changes to playing
2387** 5. Get the Media details when the track change happens
2388** or track change interim response is received with
2389** valid track id
2390** 6. HAL callback for play status change and application
2391** setting change
2392** Returns None
2393**
2394***************************************************************************/
2395static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG_NOTIF_RSP *p_rsp)
2396{
2397 bt_bdaddr_t rc_addr;
2398 UINT32 attr_list[] = {
2399 AVRC_MEDIA_ATTR_ID_TITLE,
2400 AVRC_MEDIA_ATTR_ID_ARTIST,
2401 AVRC_MEDIA_ATTR_ID_ALBUM,
2402 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
2403 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
2404 AVRC_MEDIA_ATTR_ID_GENRE,
2405 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
2406 };
2407
2408
2409 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2410
2411 if (pmeta_msg->code == AVRC_RSP_INTERIM)
2412 {
2413 btif_rc_supported_event_t *p_event;
2414 list_node_t *node;
2415
2416 BTIF_TRACE_DEBUG("%s Interim response : 0x%2X ", __FUNCTION__, p_rsp->event_id);
2417 switch (p_rsp->event_id)
2418 {
2419 case AVRC_EVT_PLAY_STATUS_CHANGE:
2420 /* Start timer to get play status periodically
2421 * if the play state is playing.
2422 */
2423 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2424 {
2425 rc_start_play_status_timer();
2426 }
2427 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2428 &rc_addr, p_rsp->param.play_status);
2429 break;
2430
2431 case AVRC_EVT_TRACK_CHANGE:
2432 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2433 {
2434 break;
2435 }
2436 else
2437 {
2438 UINT8 *p_data = p_rsp->param.track;
2439 /* Update the UID for current track
2440 * Attributes will be fetched after the AVRCP procedure
2441 */
2442 BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
2443 }
2444 break;
2445
2446 case AVRC_EVT_APP_SETTING_CHANGE:
2447 break;
2448
2449 case AVRC_EVT_NOW_PLAYING_CHANGE:
2450 break;
2451
2452 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2453 break;
2454
2455 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2456 break;
2457
2458 case AVRC_EVT_UIDS_CHANGE:
2459 break;
2460
2461 case AVRC_EVT_TRACK_REACHED_END:
2462 case AVRC_EVT_TRACK_REACHED_START:
2463 case AVRC_EVT_PLAY_POS_CHANGED:
2464 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2465 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2466 default:
2467 BTIF_TRACE_ERROR("%s Unhandled interim response 0x%2X", __FUNCTION__,
2468 p_rsp->event_id);
2469 return;
2470 }
2471 list_foreach(btif_rc_cb.rc_supported_event_list,
Pavlin Radoslavov69a34362016-01-20 10:41:01 -08002472 iterate_supported_event_list_for_interim_rsp,
2473 &p_rsp->event_id);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302474
2475 node = list_begin(btif_rc_cb.rc_supported_event_list);
2476 while (node != NULL)
2477 {
2478 p_event = (btif_rc_supported_event_t *)list_node(node);
2479 if ((p_event != NULL) && (p_event->status == eNOT_REGISTERED))
2480 {
2481 register_for_event_notification(p_event);
2482 break;
2483 }
2484 node = list_next (node);
2485 p_event = NULL;
2486 }
2487 /* Registered for all events, we can request application settings */
2488 if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
2489 {
2490 /* we need to do this only if remote TG supports
2491 * player application settings
2492 */
2493 btif_rc_cb.rc_app_settings.query_started = TRUE;
2494 if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
2495 {
2496 list_player_app_setting_attrib_cmd();
2497 }
2498 else
2499 {
2500 BTIF_TRACE_DEBUG("%s App setting not supported, complete procedure", __FUNCTION__);
2501 rc_ctrl_procedure_complete();
2502 }
2503 }
2504 }
2505 else if (pmeta_msg->code == AVRC_RSP_CHANGED)
2506 {
2507 btif_rc_supported_event_t *p_event;
2508 list_node_t *node;
2509
2510 BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
2511 p_rsp->event_id);
2512
2513 node = list_begin(btif_rc_cb.rc_supported_event_list);
2514 while (node != NULL)
2515 {
2516 p_event = (btif_rc_supported_event_t *)list_node(node);
2517 if ((p_event != NULL) && (p_event->event_id == p_rsp->event_id))
2518 {
2519 p_event->status = eNOT_REGISTERED;
2520 register_for_event_notification(p_event);
2521 break;
2522 }
2523 node = list_next (node);
2524 }
2525
2526 switch (p_rsp->event_id)
2527 {
2528 case AVRC_EVT_PLAY_STATUS_CHANGE:
2529 /* Start timer to get play status periodically
2530 * if the play state is playing.
2531 */
2532 if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING)
2533 {
2534 rc_start_play_status_timer();
2535 }
2536 else
2537 {
2538 rc_stop_play_status_timer();
2539 }
2540 HAL_CBACK(bt_rc_ctrl_callbacks, play_status_changed_cb,
2541 &rc_addr, p_rsp->param.play_status);
2542 break;
2543
2544 case AVRC_EVT_TRACK_CHANGE:
2545 if (rc_is_track_id_valid (p_rsp->param.track) != true)
2546 {
2547 break;
2548 }
2549 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
2550 break;
2551
2552 case AVRC_EVT_APP_SETTING_CHANGE:
2553 {
2554 btrc_player_settings_t app_settings;
2555 UINT16 xx;
2556
2557 app_settings.num_attr = p_rsp->param.player_setting.num_attr;
2558 for (xx = 0; xx < app_settings.num_attr; xx++)
2559 {
2560 app_settings.attr_ids[xx] = p_rsp->param.player_setting.attr_id[xx];
2561 app_settings.attr_values[xx] = p_rsp->param.player_setting.attr_value[xx];
2562 }
2563 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2564 &rc_addr, &app_settings);
2565 }
2566 break;
2567
2568 case AVRC_EVT_NOW_PLAYING_CHANGE:
2569 break;
2570
2571 case AVRC_EVT_AVAL_PLAYERS_CHANGE:
2572 break;
2573
2574 case AVRC_EVT_ADDR_PLAYER_CHANGE:
2575 break;
2576
2577 case AVRC_EVT_UIDS_CHANGE:
2578 break;
2579
2580 case AVRC_EVT_TRACK_REACHED_END:
2581 case AVRC_EVT_TRACK_REACHED_START:
2582 case AVRC_EVT_PLAY_POS_CHANGED:
2583 case AVRC_EVT_BATTERY_STATUS_CHANGE:
2584 case AVRC_EVT_SYSTEM_STATUS_CHANGE:
2585 default:
2586 BTIF_TRACE_ERROR("%s Unhandled completion response 0x%2X",
2587 __FUNCTION__, p_rsp->event_id);
2588 return;
2589 }
2590 }
2591}
2592
2593/***************************************************************************
2594**
2595** Function handle_app_attr_response
2596**
2597** Description handles the the application attributes response and
2598** initiates procedure to fetch the attribute values
2599** Returns None
2600**
2601***************************************************************************/
2602static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_ATTR_RSP *p_rsp)
2603{
2604 UINT8 xx;
2605
2606 if (p_rsp->status != AVRC_STS_NO_ERROR)
2607 {
2608 BTIF_TRACE_ERROR("%s Error getting Player application settings: 0x%2X",
2609 __FUNCTION__, p_rsp->status);
2610 rc_ctrl_procedure_complete();
2611 return;
2612 }
2613
2614 for (xx = 0; xx < p_rsp->num_attr; xx++)
2615 {
2616 UINT8 st_index;
2617
2618 if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
2619 {
2620 st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
2621 btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
2622 btif_rc_cb.rc_app_settings.num_ext_attrs++;
2623 }
2624 else
2625 {
2626 st_index = btif_rc_cb.rc_app_settings.num_attrs;
2627 btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
2628 btif_rc_cb.rc_app_settings.num_attrs++;
2629 }
2630 }
2631 btif_rc_cb.rc_app_settings.attr_index = 0;
2632 btif_rc_cb.rc_app_settings.ext_attr_index = 0;
2633 btif_rc_cb.rc_app_settings.ext_val_index = 0;
2634 if (p_rsp->num_attr)
2635 {
2636 list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
2637 }
2638 else
2639 {
2640 BTIF_TRACE_ERROR("%s No Player application settings found",
2641 __FUNCTION__);
2642 }
2643}
2644
2645/***************************************************************************
2646**
2647** Function handle_app_val_response
2648**
2649** Description handles the the attributes value response and if extended
2650** menu is available, it initiates query for the attribute
2651** text. If not, it initiates procedure to get the current
2652** attribute values and calls the HAL callback for provding
2653** application settings information.
2654** Returns None
2655**
2656***************************************************************************/
2657static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP_VALUES_RSP *p_rsp)
2658{
2659 UINT8 xx, attr_index;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302660 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2661 btif_rc_player_app_settings_t *p_app_settings;
2662 bt_bdaddr_t rc_addr;
2663
2664 /* Todo: Do we need to retry on command timeout */
2665 if (p_rsp->status != AVRC_STS_NO_ERROR)
2666 {
2667 BTIF_TRACE_ERROR("%s Error fetching attribute values 0x%02X",
2668 __FUNCTION__, p_rsp->status);
2669 return;
2670 }
2671
2672 p_app_settings = &btif_rc_cb.rc_app_settings;
2673 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2674
2675 if (p_app_settings->attr_index < p_app_settings->num_attrs)
2676 {
2677 attr_index = p_app_settings->attr_index;
2678 p_app_settings->attrs[attr_index].num_val = p_rsp->num_val;
2679 for (xx = 0; xx < p_rsp->num_val; xx++)
2680 {
2681 p_app_settings->attrs[attr_index].attr_val[xx] = p_rsp->vals[xx];
2682 }
2683 attr_index++;
2684 p_app_settings->attr_index++;
2685 if (attr_index < p_app_settings->num_attrs)
2686 {
2687 list_player_app_setting_value_cmd (p_app_settings->attrs[p_app_settings->attr_index].attr_id);
2688 }
2689 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2690 {
2691 attr_index = 0;
2692 p_app_settings->ext_attr_index = 0;
2693 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[attr_index].attr_id);
2694 }
2695 else
2696 {
2697 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2698 {
2699 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2700 }
2701 get_player_app_setting_cmd (p_app_settings->num_attrs, attrs);
2702 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
Pavlin Radoslavov43947202016-02-13 08:47:19 -08002703 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302704 }
2705 }
2706 else if (p_app_settings->ext_attr_index < p_app_settings->num_ext_attrs)
2707 {
2708 attr_index = p_app_settings->ext_attr_index;
2709 p_app_settings->ext_attrs[attr_index].num_val = p_rsp->num_val;
2710 for (xx = 0; xx < p_rsp->num_val; xx++)
2711 {
2712 p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val = p_rsp->vals[xx];
2713 }
2714 attr_index++;
2715 p_app_settings->ext_attr_index++;
2716 if (attr_index < p_app_settings->num_ext_attrs)
2717 {
2718 list_player_app_setting_value_cmd (p_app_settings->ext_attrs[p_app_settings->ext_attr_index].attr_id);
2719 }
2720 else
2721 {
2722 UINT8 attr[AVRC_MAX_APP_ATTR_SIZE];
2723 UINT8 xx;
2724
2725 for (xx = 0; xx < p_app_settings->num_ext_attrs; xx++)
2726 {
2727 attr[xx] = p_app_settings->ext_attrs[xx].attr_id;
2728 }
2729 get_player_app_setting_attr_text_cmd(attr, xx);
2730 }
2731 }
2732}
2733
2734/***************************************************************************
2735**
2736** Function handle_app_cur_val_response
2737**
2738** Description handles the the get attributes value response.
2739**
2740** Returns None
2741**
2742***************************************************************************/
2743static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp)
2744{
2745 btrc_player_settings_t app_settings;
2746 bt_bdaddr_t rc_addr;
2747 UINT16 xx;
2748
2749 /* Todo: Do we need to retry on command timeout */
2750 if (p_rsp->status != AVRC_STS_NO_ERROR)
2751 {
2752 BTIF_TRACE_ERROR("%s Error fetching current settings: 0x%02X",
2753 __FUNCTION__, p_rsp->status);
2754 return;
2755 }
2756
2757 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2758
2759 app_settings.num_attr = p_rsp->num_val;
2760 for (xx = 0; xx < app_settings.num_attr; xx++)
2761 {
2762 app_settings.attr_ids[xx] = p_rsp->p_vals[xx].attr_id;
2763 app_settings.attr_values[xx] = p_rsp->p_vals[xx].attr_val;
2764 }
2765 HAL_CBACK(bt_rc_ctrl_callbacks, playerapplicationsetting_changed_cb,
2766 &rc_addr, &app_settings);
2767 /* Application settings are fetched only once for initial values
2768 * initiate anything that follows after RC procedure.
2769 * Defer it if browsing is supported till players query
2770 */
2771 rc_ctrl_procedure_complete ();
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002772 osi_free_and_reset((void **)&p_rsp->p_vals);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302773}
2774
2775/***************************************************************************
2776**
2777** Function handle_app_attr_txt_response
2778**
2779** Description handles the the get attributes text response, if fails
2780** calls HAL callback with just normal settings and initiates
2781** query for current settings else initiates query for value text
2782** Returns None
2783**
2784***************************************************************************/
2785static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2786{
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08002787 UINT8 xx;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302788 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2789 btif_rc_player_app_settings_t *p_app_settings;
2790 bt_bdaddr_t rc_addr;
2791
2792 p_app_settings = &btif_rc_cb.rc_app_settings;
2793 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2794
2795 /* Todo: Do we need to retry on command timeout */
2796 if (p_rsp->status != AVRC_STS_NO_ERROR)
2797 {
2798 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2799
2800 BTIF_TRACE_ERROR("%s Error fetching attribute text: 0x%02X",
2801 __FUNCTION__, p_rsp->status);
2802 /* Not able to fetch Text for extended Menu, skip the process
2803 * and cleanup used memory. Proceed to get the current settings
2804 * for standard attributes.
2805 */
2806 p_app_settings->num_ext_attrs = 0;
2807 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002808 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302809 p_app_settings->ext_attr_index = 0;
2810
2811 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2812 {
2813 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2814 }
2815 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
Pavlin Radoslavov43947202016-02-13 08:47:19 -08002816 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302817
2818 get_player_app_setting_cmd (xx, attrs);
2819 return;
2820 }
2821
2822 for (xx = 0; xx < p_rsp->num_attr; xx++)
2823 {
2824 UINT8 x;
2825 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2826 {
2827 if (p_app_settings->ext_attrs[x].attr_id == p_rsp->p_attrs[xx].attr_id)
2828 {
2829 p_app_settings->ext_attrs[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2830 p_app_settings->ext_attrs[x].str_len = p_rsp->p_attrs[xx].str_len;
2831 p_app_settings->ext_attrs[x].p_str = p_rsp->p_attrs[xx].p_str;
2832 break;
2833 }
2834 }
2835 }
2836
2837 for (xx = 0; xx < p_app_settings->ext_attrs[0].num_val; xx++)
2838 {
2839 vals[xx] = p_app_settings->ext_attrs[0].ext_attr_val[xx].val;
2840 }
2841 get_player_app_setting_value_text_cmd(vals, xx);
2842}
2843
2844
2845/***************************************************************************
2846**
2847** Function handle_app_attr_val_txt_response
2848**
2849** Description handles the the get attributes value text response, if fails
2850** calls HAL callback with just normal settings and initiates
2851** query for current settings
2852** Returns None
2853**
2854***************************************************************************/
2855static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp)
2856{
2857 UINT8 xx, attr_index;
2858 UINT8 vals[AVRC_MAX_APP_ATTR_SIZE];
2859 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2860 btif_rc_player_app_settings_t *p_app_settings;
2861 bt_bdaddr_t rc_addr;
2862
2863 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2864 p_app_settings = &btif_rc_cb.rc_app_settings;
2865
2866 /* Todo: Do we need to retry on command timeout */
2867 if (p_rsp->status != AVRC_STS_NO_ERROR)
2868 {
2869 UINT8 attrs[AVRC_MAX_APP_ATTR_SIZE];
2870
2871 BTIF_TRACE_ERROR("%s Error fetching attribute value text: 0x%02X",
2872 __FUNCTION__, p_rsp->status);
2873
2874 /* Not able to fetch Text for extended Menu, skip the process
2875 * and cleanup used memory. Proceed to get the current settings
2876 * for standard attributes.
2877 */
2878 p_app_settings->num_ext_attrs = 0;
2879 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2880 {
2881 int x;
2882 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2883
2884 for (x = 0; x < p_ext_attr->num_val; x++)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002885 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302886 p_ext_attr->num_val = 0;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002887 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302888 }
2889 p_app_settings->ext_attr_index = 0;
2890
2891 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2892 {
2893 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2894 }
2895 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
Pavlin Radoslavov43947202016-02-13 08:47:19 -08002896 p_app_settings->num_attrs, p_app_settings->attrs, 0, NULL);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302897
2898 get_player_app_setting_cmd (xx, attrs);
2899 return;
2900 }
2901
2902 for (xx = 0; xx < p_rsp->num_attr; xx++)
2903 {
2904 UINT8 x;
2905 btrc_player_app_ext_attr_t *p_ext_attr;
2906 p_ext_attr = &p_app_settings->ext_attrs[p_app_settings->ext_val_index];
2907 for (x = 0; x < p_rsp->num_attr; x++)
2908 {
2909 if (p_ext_attr->ext_attr_val[x].val == p_rsp->p_attrs[xx].attr_id)
2910 {
2911 p_ext_attr->ext_attr_val[x].charset_id = p_rsp->p_attrs[xx].charset_id;
2912 p_ext_attr->ext_attr_val[x].str_len = p_rsp->p_attrs[xx].str_len;
2913 p_ext_attr->ext_attr_val[x].p_str = p_rsp->p_attrs[xx].p_str;
2914 break;
2915 }
2916 }
2917 }
2918 p_app_settings->ext_val_index++;
2919
2920 if (p_app_settings->ext_val_index < p_app_settings->num_ext_attrs)
2921 {
2922 attr_index = p_app_settings->ext_val_index;
2923 for (xx = 0; xx < p_app_settings->ext_attrs[attr_index].num_val; xx++)
2924 {
2925 vals[xx] = p_app_settings->ext_attrs[attr_index].ext_attr_val[xx].val;
2926 }
2927 get_player_app_setting_value_text_cmd(vals, xx);
2928 }
2929 else
2930 {
2931 UINT8 x;
2932
2933 for (xx = 0; xx < p_app_settings->num_attrs; xx++)
2934 {
2935 attrs[xx] = p_app_settings->attrs[xx].attr_id;
2936 }
2937 for (x = 0; x < p_app_settings->num_ext_attrs; x++)
2938 {
2939 attrs[xx+x] = p_app_settings->ext_attrs[x].attr_id;
2940 }
2941 HAL_CBACK (bt_rc_ctrl_callbacks, playerapplicationsetting_cb, &rc_addr,
Pavlin Radoslavov43947202016-02-13 08:47:19 -08002942 p_app_settings->num_attrs, p_app_settings->attrs,
2943 p_app_settings->num_ext_attrs, p_app_settings->ext_attrs);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302944 get_player_app_setting_cmd (xx + x, attrs);
2945
2946 /* Free the application settings information after sending to
2947 * application.
2948 */
2949 for (xx = 0; xx < p_app_settings->ext_attr_index; xx++)
2950 {
2951 int x;
2952 btrc_player_app_ext_attr_t *p_ext_attr = &p_app_settings->ext_attrs[xx];
2953
2954 for (x = 0; x < p_ext_attr->num_val; x++)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002955 osi_free_and_reset((void **)&p_ext_attr->ext_attr_val[x].p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302956 p_ext_attr->num_val = 0;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08002957 osi_free_and_reset((void **)&p_app_settings->ext_attrs[xx].p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05302958 }
2959 p_app_settings->num_attrs = 0;
2960 }
2961}
2962
2963/***************************************************************************
2964**
2965** Function handle_set_app_attr_val_response
2966**
2967** Description handles the the set attributes value response, if fails
2968** calls HAL callback to indicate the failure
2969** Returns None
2970**
2971***************************************************************************/
2972static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp)
2973{
2974 uint8_t accepted = 0;
2975 bt_bdaddr_t rc_addr;
2976
2977 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
2978
2979 /* For timeout pmeta_msg will be NULL, else we need to
2980 * check if this is accepted by TG
2981 */
2982 if (pmeta_msg && (pmeta_msg->code == AVRC_RSP_ACCEPT))
2983 {
2984 accepted = 1;
2985 }
2986 HAL_CBACK(bt_rc_ctrl_callbacks, setplayerappsetting_rsp_cb, &rc_addr, accepted);
2987}
2988
2989/***************************************************************************
2990**
2991** Function handle_get_elem_attr_response
2992**
2993** Description handles the the element attributes response, calls
2994** HAL callback to update track change information.
2995** Returns None
2996**
2997***************************************************************************/
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08002998static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg,
2999 tAVRC_GET_ELEM_ATTRS_RSP *p_rsp)
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303000{
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003001 if (p_rsp->status == AVRC_STS_NO_ERROR) {
3002 bt_bdaddr_t rc_addr;
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003003 size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003004 btrc_element_attr_val_t *p_attr =
3005 (btrc_element_attr_val_t *)osi_calloc(buf_size);
3006
3007 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3008
3009 for (int i = 0; i < p_rsp->num_attr; i++) {
3010 p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003011 /* Todo. Legth limit check to include null */
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003012 if (p_rsp->p_attrs[i].name.str_len &&
3013 p_rsp->p_attrs[i].name.p_str) {
3014 memcpy(p_attr[i].text, p_rsp->p_attrs[i].name.p_str,
3015 p_rsp->p_attrs[i].name.str_len);
3016 osi_free_and_reset((void **)&p_rsp->p_attrs[i].name.p_str);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303017 }
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303018 }
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003019 HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb,
3020 &rc_addr, p_rsp->num_attr, p_attr);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003021 osi_free(p_attr);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003022 } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303023 /* Retry for timeout case, this covers error handling
3024 * for continuation failure also.
3025 */
3026 UINT32 attr_list[] = {
3027 AVRC_MEDIA_ATTR_ID_TITLE,
3028 AVRC_MEDIA_ATTR_ID_ARTIST,
3029 AVRC_MEDIA_ATTR_ID_ALBUM,
3030 AVRC_MEDIA_ATTR_ID_TRACK_NUM,
3031 AVRC_MEDIA_ATTR_ID_NUM_TRACKS,
3032 AVRC_MEDIA_ATTR_ID_GENRE,
3033 AVRC_MEDIA_ATTR_ID_PLAYING_TIME
3034 };
3035 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003036 } else {
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303037 BTIF_TRACE_ERROR("%s: Error in get element attr procedure %d",
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08003038 __func__, p_rsp->status);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303039 }
3040}
3041
3042/***************************************************************************
3043**
3044** Function handle_get_playstatus_response
3045**
3046** Description handles the the play status response, calls
3047** HAL callback to update play position.
3048** Returns None
3049**
3050***************************************************************************/
3051static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_PLAY_STATUS_RSP *p_rsp)
3052{
3053 bt_bdaddr_t rc_addr;
3054
3055 bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
3056
3057 if (p_rsp->status == AVRC_STS_NO_ERROR)
3058 {
3059 HAL_CBACK(bt_rc_ctrl_callbacks, play_position_changed_cb,
3060 &rc_addr, p_rsp->song_len, p_rsp->song_pos);
3061 }
3062 else
3063 {
3064 BTIF_TRACE_ERROR("%s: Error in get play status procedure %d",
3065 __FUNCTION__, p_rsp->status);
3066 }
3067}
3068
3069/***************************************************************************
3070**
3071** Function clear_cmd_timeout
3072**
3073** Description helper function to stop the command timeout timer
3074** Returns None
3075**
3076***************************************************************************/
3077static void clear_cmd_timeout (UINT8 label)
3078{
3079 rc_transaction_t *p_txn;
3080
3081 p_txn = get_transaction_by_lbl (label);
3082 if (p_txn == NULL)
3083 {
3084 BTIF_TRACE_ERROR("%s: Error in transaction label lookup", __FUNCTION__);
3085 return;
3086 }
3087
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003088 if (p_txn->txn_timer != NULL)
3089 alarm_cancel(p_txn->txn_timer);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303090}
3091
3092/***************************************************************************
3093**
3094** Function handle_avk_rc_metamsg_rsp
3095**
3096** Description Handle RC metamessage response
3097**
3098** Returns void
3099**
3100***************************************************************************/
3101static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
3102{
3103 tAVRC_RESPONSE avrc_response = {0};
3104 UINT8 scratch_buf[512] = {0};// this variable is unused
3105 UINT16 buf_len;
3106 tAVRC_STS status;
3107
3108 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ", __FUNCTION__,
3109 pmeta_msg->p_msg->hdr.opcode, pmeta_msg->code);
3110
3111 if ((AVRC_OP_VENDOR == pmeta_msg->p_msg->hdr.opcode)&&
3112 (pmeta_msg->code >= AVRC_RSP_NOT_IMPL)&&
3113 (pmeta_msg->code <= AVRC_RSP_INTERIM))
3114 {
3115 status = AVRC_Ctrl_ParsResponse(pmeta_msg->p_msg, &avrc_response, scratch_buf, &buf_len);
3116 BTIF_TRACE_DEBUG("%s parse status %d pdu = %d rsp_status = %d",
3117 __FUNCTION__, status, avrc_response.pdu,
3118 pmeta_msg->p_msg->vendor.hdr.ctype);
3119
3120 switch (avrc_response.pdu)
3121 {
3122 case AVRC_PDU_REGISTER_NOTIFICATION:
3123 handle_notification_response(pmeta_msg, &avrc_response.reg_notif);
3124 if (pmeta_msg->code == AVRC_RSP_INTERIM)
3125 {
3126 /* Don't free the transaction Id */
3127 clear_cmd_timeout (pmeta_msg->label);
3128 return;
3129 }
3130 break;
3131
3132 case AVRC_PDU_GET_CAPABILITIES:
3133 handle_get_capability_response(pmeta_msg, &avrc_response.get_caps);
3134 break;
3135
3136 case AVRC_PDU_LIST_PLAYER_APP_ATTR:
3137 handle_app_attr_response(pmeta_msg, &avrc_response.list_app_attr);
3138 break;
3139
3140 case AVRC_PDU_LIST_PLAYER_APP_VALUES:
3141 handle_app_val_response(pmeta_msg, &avrc_response.list_app_values);
3142 break;
3143
3144 case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
3145 handle_app_cur_val_response(pmeta_msg, &avrc_response.get_cur_app_val);
3146 break;
3147
3148 case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
3149 handle_app_attr_txt_response(pmeta_msg, &avrc_response.get_app_attr_txt);
3150 break;
3151
3152 case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT:
3153 handle_app_attr_val_txt_response(pmeta_msg, &avrc_response.get_app_val_txt);
3154 break;
3155
3156 case AVRC_PDU_SET_PLAYER_APP_VALUE:
3157 handle_set_app_attr_val_response(pmeta_msg, &avrc_response.set_app_val);
3158 break;
3159
3160 case AVRC_PDU_GET_ELEMENT_ATTR:
3161 handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
3162 break;
3163
3164 case AVRC_PDU_GET_PLAY_STATUS:
3165 handle_get_playstatus_response(pmeta_msg, &avrc_response.get_play_status);
3166 break;
3167 }
3168 release_transaction(pmeta_msg->label);
3169 }
3170 else
3171 {
3172 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3173 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3174 return;
3175 }
3176}
3177
3178/***************************************************************************
3179**
3180** Function handle_avk_rc_metamsg_cmd
3181**
3182** Description Handle RC metamessage response
3183**
3184** Returns void
3185**
3186***************************************************************************/
3187static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG *pmeta_msg)
3188{
3189 tAVRC_COMMAND avrc_cmd = {0};
3190 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3191 BTIF_TRACE_DEBUG("%s opcode = %d rsp_code = %d ",__FUNCTION__,
3192 pmeta_msg->p_msg->hdr.opcode,pmeta_msg->code);
3193 if ((AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode)&&
3194 (pmeta_msg->code <= AVRC_CMD_GEN_INQ))
3195 {
3196 status = AVRC_Ctrl_ParsCommand(pmeta_msg->p_msg, &avrc_cmd);
3197 BTIF_TRACE_DEBUG("%s Received vendor command.code %d, PDU %d label %d",
3198 __FUNCTION__, pmeta_msg->code, avrc_cmd.pdu, pmeta_msg->label);
3199
3200 if (status != AVRC_STS_NO_ERROR)
3201 {
3202 /* return error */
3203 BTIF_TRACE_WARNING("%s: Error in parsing received metamsg command. status: 0x%02x",
3204 __FUNCTION__, status);
3205 send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu, status);
3206 }
3207 else
3208 {
3209 if (avrc_cmd.pdu == AVRC_PDU_REGISTER_NOTIFICATION)
3210 {
3211 UINT8 event_id = avrc_cmd.reg_notif.event_id;
3212 BTIF_TRACE_EVENT("%s:Register notification event_id: %s",
3213 __FUNCTION__, dump_rc_notification_event_id(event_id));
3214 }
3215 else if (avrc_cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME)
3216 {
3217 BTIF_TRACE_EVENT("%s: Abs Volume Cmd Recvd", __FUNCTION__);
3218 }
3219 btif_rc_ctrl_upstreams_rsp_cmd(avrc_cmd.pdu, &avrc_cmd, pmeta_msg->label);
3220 }
3221 }
3222 else
3223 {
3224 BTIF_TRACE_DEBUG("%s:Invalid Vendor Command code: %d len: %d. Not processing it.",
3225 __FUNCTION__, pmeta_msg->code, pmeta_msg->len);
3226 return;
3227 }
3228}
3229#endif
3230
Satya Calloji247c68f2013-08-01 02:14:43 -07003231/***************************************************************************
3232**
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08003233** Function cleanup
3234**
3235** Description Closes the AVRC interface
3236**
3237** Returns void
3238**
3239***************************************************************************/
3240static void cleanup()
3241{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07003242 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08003243 close_uinput();
3244 if (bt_rc_callbacks)
3245 {
3246 bt_rc_callbacks = NULL;
3247 }
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003248 alarm_free(btif_rc_cb.rc_play_status_timer);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08003249 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
Satya Calloji247c68f2013-08-01 02:14:43 -07003250 lbl_destroy();
Anubhav Guptadaddea92014-09-08 16:00:22 +05303251 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08003252}
3253
Anubhav Guptadaddea92014-09-08 16:00:22 +05303254/***************************************************************************
3255**
3256** Function cleanup_ctrl
3257**
3258** Description Closes the AVRC Controller interface
3259**
3260** Returns void
3261**
3262***************************************************************************/
3263static void cleanup_ctrl()
3264{
3265 BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
3266
3267 if (bt_rc_ctrl_callbacks)
3268 {
3269 bt_rc_ctrl_callbacks = NULL;
3270 }
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003271 alarm_free(btif_rc_cb.rc_play_status_timer);
Anubhav Guptadaddea92014-09-08 16:00:22 +05303272 memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
3273 lbl_destroy();
3274 BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
3275}
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08003276
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303277/***************************************************************************
3278**
3279** Function getcapabilities_cmd
3280**
3281** Description GetCapabilties from Remote(Company_ID, Events_Supported)
3282**
3283** Returns void
3284**
3285***************************************************************************/
3286static bt_status_t getcapabilities_cmd (uint8_t cap_id)
3287{
3288 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3289 rc_transaction_t *p_transaction = NULL;
3290#if (AVRC_CTLR_INCLUDED == TRUE)
3291 BTIF_TRACE_DEBUG("%s: cap_id %d", __FUNCTION__, cap_id);
3292 CHECK_RC_CONNECTED
3293 bt_status_t tran_status=get_transaction(&p_transaction);
3294 if (BT_STATUS_SUCCESS != tran_status)
3295 return BT_STATUS_FAIL;
3296
3297 tAVRC_COMMAND avrc_cmd = {0};
3298 BT_HDR *p_msg = NULL;
3299 avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
3300 avrc_cmd.get_caps.capability_id = cap_id;
3301 avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
3302 avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
3303 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3304 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3305 {
3306 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3307 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3308 __FUNCTION__,p_transaction->lbl);
3309 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3310 data_start, p_msg->len);
3311 status = BT_STATUS_SUCCESS;
3312 start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
3313 }
3314 else
3315 {
3316 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3317 __FUNCTION__, status);
3318 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003319 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303320#else
3321 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3322#endif
3323 return status;
3324}
3325
3326/***************************************************************************
3327**
3328** Function list_player_app_setting_attrib_cmd
3329**
3330** Description Get supported List Player Attributes
3331**
3332** Returns void
3333**
3334***************************************************************************/
3335static bt_status_t list_player_app_setting_attrib_cmd(void)
3336{
3337 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3338 rc_transaction_t *p_transaction = NULL;
3339#if (AVRC_CTLR_INCLUDED == TRUE)
3340 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3341 CHECK_RC_CONNECTED
3342 bt_status_t tran_status=get_transaction(&p_transaction);
3343 if (BT_STATUS_SUCCESS != tran_status)
3344 return BT_STATUS_FAIL;
3345
3346 tAVRC_COMMAND avrc_cmd = {0};
3347 BT_HDR *p_msg = NULL;
3348 avrc_cmd.list_app_attr.opcode = AVRC_OP_VENDOR;
3349 avrc_cmd.list_app_attr.pdu = AVRC_PDU_LIST_PLAYER_APP_ATTR;
3350 avrc_cmd.list_app_attr.status = AVRC_STS_NO_ERROR;
3351 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3352 if ((status == AVRC_STS_NO_ERROR)&&(p_msg != NULL))
3353 {
3354 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3355 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3356 __FUNCTION__,p_transaction->lbl);
3357 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3358 data_start, p_msg->len);
3359 status = BT_STATUS_SUCCESS;
3360 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
3361 }
3362 else
3363 {
3364
3365 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3366 __FUNCTION__, status);
3367 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003368 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303369#else
3370 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3371#endif
3372 return status;
3373}
3374
3375/***************************************************************************
3376**
3377** Function list_player_app_setting_value_cmd
3378**
3379** Description Get values of supported Player Attributes
3380**
3381** Returns void
3382**
3383***************************************************************************/
3384static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
3385{
3386 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3387 rc_transaction_t *p_transaction=NULL;
3388#if (AVRC_CTLR_INCLUDED == TRUE)
3389 BTIF_TRACE_DEBUG("%s: attrib_id %d", __FUNCTION__, attrib_id);
3390 CHECK_RC_CONNECTED
3391 bt_status_t tran_status=get_transaction(&p_transaction);
3392 if (BT_STATUS_SUCCESS != tran_status)
3393 return BT_STATUS_FAIL;
3394
3395 tAVRC_COMMAND avrc_cmd = {0};
3396 BT_HDR *p_msg = NULL;
3397 avrc_cmd.list_app_values.attr_id = attrib_id;
3398 avrc_cmd.list_app_values.opcode = AVRC_OP_VENDOR;
3399 avrc_cmd.list_app_values.pdu = AVRC_PDU_LIST_PLAYER_APP_VALUES;
3400 avrc_cmd.list_app_values.status = AVRC_STS_NO_ERROR;
3401 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3402 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3403 {
3404 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3405 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3406 __FUNCTION__,p_transaction->lbl);
3407 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3408 data_start, p_msg->len);
3409 status = BT_STATUS_SUCCESS;
3410 start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
3411 }
3412 else
3413 {
3414 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3415 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003416 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303417#else
3418 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3419#endif
3420 return status;
3421}
3422
3423/***************************************************************************
3424**
3425** Function get_player_app_setting_cmd
3426**
3427** Description Get current values of Player Attributes
3428**
3429** Returns void
3430**
3431***************************************************************************/
3432static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids)
3433{
3434 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3435 rc_transaction_t *p_transaction = NULL;
3436 int count = 0;
3437#if (AVRC_CTLR_INCLUDED == TRUE)
3438 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3439 CHECK_RC_CONNECTED
3440 bt_status_t tran_status=get_transaction(&p_transaction);
3441 if (BT_STATUS_SUCCESS != tran_status)
3442 return BT_STATUS_FAIL;
3443
3444 tAVRC_COMMAND avrc_cmd = {0};
3445 BT_HDR *p_msg = NULL;
3446 avrc_cmd.get_cur_app_val.opcode = AVRC_OP_VENDOR;
3447 avrc_cmd.get_cur_app_val.status = AVRC_STS_NO_ERROR;
3448 avrc_cmd.get_cur_app_val.num_attr = num_attrib;
3449 avrc_cmd.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
3450
3451 for (count = 0; count < num_attrib; count++)
3452 {
3453 avrc_cmd.get_cur_app_val.attrs[count] = attrib_ids[count];
3454 }
3455 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3456 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3457 {
3458 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3459 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3460 __FUNCTION__,p_transaction->lbl);
3461 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
3462 data_start, p_msg->len);
3463 status = BT_STATUS_SUCCESS;
3464 start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
3465 }
3466 else
3467 {
3468 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3469 __FUNCTION__, status);
3470 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003471 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303472#else
3473 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3474#endif
3475 return status;
3476}
3477
3478/***************************************************************************
3479**
3480** Function change_player_app_setting
3481**
3482** Description Set current values of Player Attributes
3483**
3484** Returns void
3485**
3486***************************************************************************/
3487static bt_status_t change_player_app_setting(bt_bdaddr_t *bd_addr, uint8_t num_attrib, uint8_t* attrib_ids, uint8_t* attrib_vals)
3488{
3489 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3490 rc_transaction_t *p_transaction = NULL;
3491 int count = 0;
3492#if (AVRC_CTLR_INCLUDED == TRUE)
3493 BTIF_TRACE_DEBUG("%s: num attrib_id %d", __FUNCTION__, num_attrib);
3494 CHECK_RC_CONNECTED
3495 bt_status_t tran_status=get_transaction(&p_transaction);
3496 if (BT_STATUS_SUCCESS != tran_status)
3497 return BT_STATUS_FAIL;
3498
3499 tAVRC_COMMAND avrc_cmd = {0};
3500 BT_HDR *p_msg = NULL;
3501 avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
3502 avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
3503 avrc_cmd.set_app_val.num_val = num_attrib;
3504 avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
3505 avrc_cmd.set_app_val.p_vals =
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003506 (tAVRC_APP_SETTING *)osi_malloc(sizeof(tAVRC_APP_SETTING) * num_attrib);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303507 for (count = 0; count < num_attrib; count++)
3508 {
3509 avrc_cmd.set_app_val.p_vals[count].attr_id = attrib_ids[count];
3510 avrc_cmd.set_app_val.p_vals[count].attr_val = attrib_vals[count];
3511 }
3512 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3513 if ((status == AVRC_STS_NO_ERROR) && (p_msg != NULL))
3514 {
3515 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3516 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3517 __FUNCTION__,p_transaction->lbl);
3518 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
3519 data_start, p_msg->len);
3520 status = BT_STATUS_SUCCESS;
3521 start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
3522 }
3523 else
3524 {
3525 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3526 __FUNCTION__, status);
3527 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003528 osi_free(p_msg);
3529 osi_free_and_reset((void **)&avrc_cmd.set_app_val.p_vals);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303530#else
3531 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3532#endif
3533 return status;
3534}
3535
3536/***************************************************************************
3537**
3538** Function get_player_app_setting_attr_text_cmd
3539**
3540** Description Get text description for app attribute
3541**
3542** Returns void
3543**
3544***************************************************************************/
3545static bt_status_t get_player_app_setting_attr_text_cmd (UINT8 *attrs, UINT8 num_attrs)
3546{
3547 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3548 rc_transaction_t *p_transaction = NULL;
3549 int count = 0;
3550#if (AVRC_CTLR_INCLUDED == TRUE)
3551 tAVRC_COMMAND avrc_cmd = {0};
3552 BT_HDR *p_msg = NULL;
3553 bt_status_t tran_status;
3554 CHECK_RC_CONNECTED
3555
3556 BTIF_TRACE_DEBUG("%s: num attrs %d", __FUNCTION__, num_attrs);
3557
3558 tran_status = get_transaction(&p_transaction);
3559 if (BT_STATUS_SUCCESS != tran_status)
3560 return BT_STATUS_FAIL;
3561
3562 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
3563 avrc_cmd.get_app_attr_txt.opcode = AVRC_OP_VENDOR;
3564 avrc_cmd.get_app_attr_txt.num_attr = num_attrs;
3565
3566 for (count = 0; count < num_attrs; count++)
3567 {
3568 avrc_cmd.get_app_attr_txt.attrs[count] = attrs[count];
3569 }
3570 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3571 if (status == AVRC_STS_NO_ERROR)
3572 {
3573 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3574 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3575 __FUNCTION__, p_transaction->lbl);
3576 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3577 AVRC_CMD_STATUS, data_start, p_msg->len);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003578 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303579 status = BT_STATUS_SUCCESS;
3580 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT, p_transaction);
3581 }
3582 else
3583 {
3584 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x", __FUNCTION__, status);
3585 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003586 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303587#else
3588 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3589#endif
3590 return status;
3591}
3592
3593/***************************************************************************
3594**
3595** Function get_player_app_setting_val_text_cmd
3596**
3597** Description Get text description for app attribute values
3598**
3599** Returns void
3600**
3601***************************************************************************/
3602static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num_vals)
3603{
3604 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3605 rc_transaction_t *p_transaction = NULL;
3606 int count = 0;
3607#if (AVRC_CTLR_INCLUDED == TRUE)
3608 tAVRC_COMMAND avrc_cmd = {0};
3609 BT_HDR *p_msg = NULL;
3610 bt_status_t tran_status;
3611 CHECK_RC_CONNECTED
3612
3613 BTIF_TRACE_DEBUG("%s: num_vals %d", __FUNCTION__, num_vals);
3614
3615 tran_status = get_transaction(&p_transaction);
3616 if (BT_STATUS_SUCCESS != tran_status)
3617 return BT_STATUS_FAIL;
3618
3619 avrc_cmd.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
3620 avrc_cmd.get_app_val_txt.opcode = AVRC_OP_VENDOR;
3621 avrc_cmd.get_app_val_txt.num_val = num_vals;
3622
3623 for (count = 0; count < num_vals; count++)
3624 {
3625 avrc_cmd.get_app_val_txt.vals[count] = vals[count];
3626 }
3627 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3628 if (status == AVRC_STS_NO_ERROR)
3629 {
3630 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3631 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3632 __FUNCTION__, p_transaction->lbl);
3633 if (p_msg != NULL)
3634 {
3635 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3636 AVRC_CMD_STATUS, data_start, p_msg->len);
3637 status = BT_STATUS_SUCCESS;
3638 start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
3639 }
3640 }
3641 else
3642 {
3643 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3644 __FUNCTION__, status);
3645 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003646 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303647#else
3648 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3649#endif
3650 return status;
3651}
3652
3653/***************************************************************************
3654**
3655** Function register_notification_cmd
3656**
3657** Description Send Command to register for a Notification ID
3658**
3659** Returns void
3660**
3661***************************************************************************/
3662static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT32 event_value)
3663{
3664
3665 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3666#if (AVRC_CTLR_INCLUDED == TRUE)
3667 tAVRC_COMMAND avrc_cmd = {0};
3668 BT_HDR *p_msg = NULL;
3669 CHECK_RC_CONNECTED
3670
3671
3672 BTIF_TRACE_DEBUG("%s: event_id %d event_value", __FUNCTION__, event_id, event_value);
3673
3674 avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
3675 avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
3676 avrc_cmd.reg_notif.event_id = event_id;
3677 avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3678 avrc_cmd.reg_notif.param = event_value;
3679 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3680 if (status == AVRC_STS_NO_ERROR)
3681 {
3682 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3683 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3684 __FUNCTION__, label);
3685 if (p_msg != NULL)
3686 {
3687 BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
3688 data_start, p_msg->len);
3689 status = BT_STATUS_SUCCESS;
3690 }
3691 }
3692 else
3693 {
3694 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3695 __FUNCTION__, status);
3696 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003697 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303698#else
3699 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3700#endif
3701 return status;
3702}
3703
3704/***************************************************************************
3705**
3706** Function get_element_attribute_cmd
3707**
3708** Description Get Element Attribute for attributeIds
3709**
3710** Returns void
3711**
3712***************************************************************************/
3713static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p_attr_ids)
3714{
3715 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3716 rc_transaction_t *p_transaction=NULL;
3717 int count = 0;
3718#if (AVRC_CTLR_INCLUDED == TRUE)
3719 tAVRC_COMMAND avrc_cmd = {0};
3720 BT_HDR *p_msg = NULL;
3721 bt_status_t tran_status;
3722 CHECK_RC_CONNECTED
3723
3724 BTIF_TRACE_DEBUG("%s: num_attribute %d attribute_id %d",
3725 __FUNCTION__, num_attribute, p_attr_ids[0]);
3726
3727 tran_status = get_transaction(&p_transaction);
3728 if (BT_STATUS_SUCCESS != tran_status)
3729 return BT_STATUS_FAIL;
3730
3731 avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
3732 avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
3733 avrc_cmd.get_elem_attrs.num_attr = num_attribute;
3734 avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
3735 for (count = 0; count < num_attribute; count++)
3736 {
3737 avrc_cmd.get_elem_attrs.attrs[count] = p_attr_ids[count];
3738 }
3739
3740 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3741 if (status == AVRC_STS_NO_ERROR)
3742 {
3743 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3744 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3745 __FUNCTION__, p_transaction->lbl);
3746 if (p_msg != NULL)
3747 {
3748 BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3749 AVRC_CMD_STATUS, data_start, p_msg->len);
3750 status = BT_STATUS_SUCCESS;
3751 start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
3752 p_transaction);
3753 }
3754 }
3755 else
3756 {
3757 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3758 __FUNCTION__, status);
3759 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003760 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303761#else
3762 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3763#endif
3764 return status;
3765}
3766
3767/***************************************************************************
3768**
3769** Function get_play_status_cmd
3770**
3771** Description Get Element Attribute for attributeIds
3772**
3773** Returns void
3774**
3775***************************************************************************/
3776static bt_status_t get_play_status_cmd(void)
3777{
3778 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3779 rc_transaction_t *p_transaction = NULL;
3780#if (AVRC_CTLR_INCLUDED == TRUE)
3781 tAVRC_COMMAND avrc_cmd = {0};
3782 BT_HDR *p_msg = NULL;
3783 bt_status_t tran_status;
3784 CHECK_RC_CONNECTED
3785
3786 BTIF_TRACE_DEBUG("%s: ", __FUNCTION__);
3787 tran_status = get_transaction(&p_transaction);
3788 if (BT_STATUS_SUCCESS != tran_status)
3789 return BT_STATUS_FAIL;
3790
3791 avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
3792 avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;
3793 avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
3794 status = AVRC_BldCommand(&avrc_cmd, &p_msg);
3795 if (status == AVRC_STS_NO_ERROR)
3796 {
3797 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3798 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3799 __FUNCTION__, p_transaction->lbl);
3800 if (p_msg != NULL)
3801 {
3802 BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
3803 AVRC_CMD_STATUS, data_start, p_msg->len);
3804 status = BT_STATUS_SUCCESS;
3805 start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
3806 }
3807 }
3808 else
3809 {
3810 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3811 __FUNCTION__, status);
3812 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003813 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303814#else
3815 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3816#endif
3817 return status;
3818
3819}
3820
3821/***************************************************************************
3822**
3823** Function set_volume_rsp
3824**
3825** Description Rsp for SetAbsoluteVolume Command
3826**
3827** Returns void
3828**
3829***************************************************************************/
3830static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t label)
3831{
3832 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3833#if (AVRC_CTLR_INCLUDED == TRUE)
3834 tAVRC_RESPONSE avrc_rsp;
3835 BT_HDR *p_msg = NULL;
3836 CHECK_RC_CONNECTED
3837
3838 BTIF_TRACE_DEBUG("%s: abs_vol %d", __FUNCTION__, abs_vol);
3839
3840 avrc_rsp.volume.opcode = AVRC_OP_VENDOR;
3841 avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
3842 avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
3843 avrc_rsp.volume.volume = abs_vol;
3844 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
3845 if (status == AVRC_STS_NO_ERROR)
3846 {
3847 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3848 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3849 __FUNCTION__, btif_rc_cb.rc_vol_label);
3850 if (p_msg != NULL)
3851 {
3852 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3853 BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
3854 status = BT_STATUS_SUCCESS;
3855 }
3856 }
3857 else
3858 {
3859 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3860 __FUNCTION__, status);
3861 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003862 osi_free(p_msg);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303863#else
3864 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3865#endif
3866 return status;
3867}
3868
3869/***************************************************************************
3870**
3871** Function send_register_abs_vol_rsp
3872**
3873** Description Rsp for Notification of Absolute Volume
3874**
3875** Returns void
3876**
3877***************************************************************************/
3878static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_notification_type_t rsp_type,
3879 uint8_t abs_vol, uint8_t label)
3880{
3881 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3882 tAVRC_RESPONSE avrc_rsp;
3883 BT_HDR *p_msg = NULL;
3884#if (AVRC_CTLR_INCLUDED == TRUE)
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003885 BTIF_TRACE_DEBUG("%s: rsp_type %d abs_vol %d", __func__, rsp_type, abs_vol);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303886 CHECK_RC_CONNECTED
3887
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003888 avrc_rsp.reg_notif.opcode = AVRC_OP_VENDOR;
3889 avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
3890 avrc_rsp.reg_notif.status = AVRC_STS_NO_ERROR;
3891 avrc_rsp.reg_notif.param.volume = abs_vol;
3892 avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303893
3894 status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003895 if (status == AVRC_STS_NO_ERROR) {
3896 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
3897 __func__, label);
3898 UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
3899 BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
3900 (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
3901 AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
3902 data_start, p_msg->len, 0);
3903 status = BT_STATUS_SUCCESS;
3904 } else {
3905 BTIF_TRACE_ERROR("%s: failed to build command. status: 0x%02x",
3906 __func__, status);
3907 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08003908 osi_free(p_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003909
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303910#else
Pavlin Radoslavov20524d32016-02-02 18:12:08 -08003911 BTIF_TRACE_DEBUG("%s: feature not enabled", __func__);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303912#endif
3913 return status;
3914}
3915
3916/***************************************************************************
3917**
3918** Function send_groupnavigation_cmd
3919**
3920** Description Send Pass-Through command
3921**
3922** Returns void
3923**
3924***************************************************************************/
3925static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code,
3926 uint8_t key_state)
3927{
3928 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3929#if (AVRC_CTLR_INCLUDED == TRUE)
3930 rc_transaction_t *p_transaction=NULL;
3931 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
3932 key_code, key_state);
3933 CHECK_RC_CONNECTED
3934 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3935 {
3936 bt_status_t tran_status = get_transaction(&p_transaction);
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003937 if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
Pavlin Radoslavovf94e67c2016-02-02 10:31:44 -08003938 UINT8 buffer[AVRC_PASS_THRU_GROUP_LEN] = {0};
3939 UINT8* start = buffer;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003940 UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
3941 *(start)++ = 0;
3942 UINT8_TO_BE_STREAM(start, key_code);
3943 BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
3944 p_transaction->lbl,
Pavlin Radoslavovf94e67c2016-02-02 10:31:44 -08003945 (tBTA_AV_STATE)key_state, buffer,
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08003946 AVRC_PASS_THRU_GROUP_LEN);
3947 status = BT_STATUS_SUCCESS;
3948 BTIF_TRACE_DEBUG("%s: succesfully sent group_navigation command to BTA",
3949 __FUNCTION__);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303950 }
3951 else
3952 {
3953 status = BT_STATUS_FAIL;
3954 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
3955 }
3956 }
3957 else
3958 {
3959 status = BT_STATUS_FAIL;
3960 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
3961 }
3962#else
3963 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
3964#endif
3965 return status;
3966}
3967
3968/***************************************************************************
3969**
3970** Function send_passthrough_cmd
3971**
3972** Description Send Pass-Through command
3973**
3974** Returns void
3975**
3976***************************************************************************/
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003977static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
3978{
3979 tAVRC_STS status = BT_STATUS_UNSUPPORTED;
3980#if (AVRC_CTLR_INCLUDED == TRUE)
3981 CHECK_RC_CONNECTED
3982 rc_transaction_t *p_transaction=NULL;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07003983 BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003984 key_code, key_state);
3985 if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
3986 {
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003987 bt_status_t tran_status = get_transaction(&p_transaction);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05303988 if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003989 {
3990 BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
3991 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
3992 status = BT_STATUS_SUCCESS;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07003993 BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003994 }
3995 else
3996 {
3997 status = BT_STATUS_FAIL;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07003998 BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07003999 }
4000 }
4001 else
4002 {
4003 status = BT_STATUS_FAIL;
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004004 BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004005 }
4006#else
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004007 BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004008#endif
4009 return status;
4010}
4011
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08004012static const btrc_interface_t bt_rc_interface = {
4013 sizeof(bt_rc_interface),
4014 init,
4015 get_play_status_rsp,
4016 NULL, /* list_player_app_attr_rsp */
4017 NULL, /* list_player_app_value_rsp */
4018 NULL, /* get_player_app_value_rsp */
4019 NULL, /* get_player_app_attr_text_rsp */
4020 NULL, /* get_player_app_value_text_rsp */
4021 get_element_attr_rsp,
4022 NULL, /* set_player_app_value_rsp */
4023 register_notification_rsp,
Satya Calloji247c68f2013-08-01 02:14:43 -07004024 set_volume,
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08004025 cleanup,
4026};
4027
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004028static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
4029 sizeof(bt_rc_ctrl_interface),
4030 init_ctrl,
4031 send_passthrough_cmd,
Anubhav Gupta6b84f292015-05-05 13:15:07 +05304032 send_groupnavigation_cmd,
4033 change_player_app_setting,
4034 set_volume_rsp,
4035 volume_change_notification_rsp,
Anubhav Guptadaddea92014-09-08 16:00:22 +05304036 cleanup_ctrl,
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004037};
4038
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08004039/*******************************************************************************
4040**
4041** Function btif_rc_get_interface
4042**
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004043** Description Get the AVRCP Target callback interface
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08004044**
4045** Returns btav_interface_t
4046**
4047*******************************************************************************/
4048const btrc_interface_t *btif_rc_get_interface(void)
4049{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004050 BTIF_TRACE_EVENT("%s", __FUNCTION__);
Ravi Nagarajan9adddf42013-03-06 05:29:48 -08004051 return &bt_rc_interface;
Satya Calloji247c68f2013-08-01 02:14:43 -07004052}
4053
4054/*******************************************************************************
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004055**
4056** Function btif_rc_ctrl_get_interface
4057**
4058** Description Get the AVRCP Controller callback interface
4059**
4060** Returns btav_interface_t
4061**
4062*******************************************************************************/
4063const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
4064{
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004065 BTIF_TRACE_EVENT("%s", __FUNCTION__);
Mike Lockwood4ad470e2014-06-02 16:21:49 -07004066 return &bt_rc_ctrl_interface;
4067}
4068
4069/*******************************************************************************
Satya Calloji247c68f2013-08-01 02:14:43 -07004070** Function initialize_transaction
4071**
4072** Description Initializes fields of the transaction structure
4073**
4074** Returns void
4075*******************************************************************************/
4076static void initialize_transaction(int lbl)
4077{
4078 pthread_mutex_lock(&device.lbllock);
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08004079 if (lbl < MAX_TRANSACTIONS_PER_SESSION) {
4080 if (alarm_is_scheduled(device.transaction[lbl].txn_timer)) {
4081 clear_cmd_timeout(lbl);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05304082 }
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08004083 device.transaction[lbl].lbl = lbl;
4084 device.transaction[lbl].in_use=FALSE;
4085 device.transaction[lbl].handle=0;
Satya Calloji247c68f2013-08-01 02:14:43 -07004086 }
4087 pthread_mutex_unlock(&device.lbllock);
4088}
4089
4090/*******************************************************************************
4091** Function lbl_init
4092**
4093** Description Initializes label structures and mutexes.
4094**
4095** Returns void
4096*******************************************************************************/
4097void lbl_init()
4098{
4099 memset(&device,0,sizeof(rc_device_t));
4100 pthread_mutexattr_t attr;
4101 pthread_mutexattr_init(&attr);
Anubhav Gupta6b84f292015-05-05 13:15:07 +05304102 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
Satya Calloji247c68f2013-08-01 02:14:43 -07004103 pthread_mutex_init(&(device.lbllock), &attr);
4104 pthread_mutexattr_destroy(&attr);
4105 init_all_transactions();
4106}
4107
4108/*******************************************************************************
4109**
4110** Function init_all_transactions
4111**
4112** Description Initializes all transactions
4113**
4114** Returns void
4115*******************************************************************************/
4116void init_all_transactions()
4117{
4118 UINT8 txn_indx=0;
4119 for(txn_indx=0; txn_indx < MAX_TRANSACTIONS_PER_SESSION; txn_indx++)
4120 {
4121 initialize_transaction(txn_indx);
4122 }
4123}
4124
4125/*******************************************************************************
4126**
4127** Function get_transaction_by_lbl
4128**
4129** Description Will return a transaction based on the label. If not inuse
4130** will return an error.
4131**
4132** Returns bt_status_t
4133*******************************************************************************/
4134rc_transaction_t *get_transaction_by_lbl(UINT8 lbl)
4135{
4136 rc_transaction_t *transaction = NULL;
4137 pthread_mutex_lock(&device.lbllock);
4138
4139 /* Determine if this is a valid label */
4140 if (lbl < MAX_TRANSACTIONS_PER_SESSION)
4141 {
4142 if (FALSE==device.transaction[lbl].in_use)
4143 {
4144 transaction = NULL;
4145 }
4146 else
4147 {
4148 transaction = &(device.transaction[lbl]);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004149 BTIF_TRACE_DEBUG("%s: Got transaction.label: %d",__FUNCTION__,lbl);
Satya Calloji247c68f2013-08-01 02:14:43 -07004150 }
4151 }
4152
4153 pthread_mutex_unlock(&device.lbllock);
4154 return transaction;
4155}
4156
4157/*******************************************************************************
4158**
4159** Function get_transaction
4160**
4161** Description Obtains the transaction details.
4162**
4163** Returns bt_status_t
4164*******************************************************************************/
4165
4166bt_status_t get_transaction(rc_transaction_t **ptransaction)
4167{
4168 bt_status_t result = BT_STATUS_NOMEM;
4169 UINT8 i=0;
4170 pthread_mutex_lock(&device.lbllock);
4171
4172 // Check for unused transactions
4173 for (i=0; i<MAX_TRANSACTIONS_PER_SESSION; i++)
4174 {
4175 if (FALSE==device.transaction[i].in_use)
4176 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004177 BTIF_TRACE_DEBUG("%s:Got transaction.label: %d",__FUNCTION__,device.transaction[i].lbl);
Satya Calloji247c68f2013-08-01 02:14:43 -07004178 device.transaction[i].in_use = TRUE;
4179 *ptransaction = &(device.transaction[i]);
4180 result = BT_STATUS_SUCCESS;
4181 break;
4182 }
4183 }
4184
4185 pthread_mutex_unlock(&device.lbllock);
4186 return result;
4187}
4188
Satya Calloji247c68f2013-08-01 02:14:43 -07004189/*******************************************************************************
4190**
4191** Function release_transaction
4192**
4193** Description Will release a transaction for reuse
4194**
4195** Returns bt_status_t
4196*******************************************************************************/
4197void release_transaction(UINT8 lbl)
4198{
4199 rc_transaction_t *transaction = get_transaction_by_lbl(lbl);
4200
4201 /* If the transaction is in use... */
4202 if (transaction != NULL)
4203 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07004204 BTIF_TRACE_DEBUG("%s: lbl: %d", __FUNCTION__, lbl);
Satya Calloji247c68f2013-08-01 02:14:43 -07004205 initialize_transaction(lbl);
4206 }
4207}
4208
4209/*******************************************************************************
4210**
4211** Function lbl_destroy
4212**
4213** Description Cleanup of the mutex
4214**
4215** Returns void
4216*******************************************************************************/
4217void lbl_destroy()
4218{
4219 pthread_mutex_destroy(&(device.lbllock));
4220}
Matthew Xiea7ae4a12013-10-24 01:09:52 -07004221
4222/*******************************************************************************
Pavlin Radoslavov642f2332015-09-16 13:30:26 -07004223** Function sleep_ms
4224**
4225** Description Sleep the calling thread unconditionally for
4226** |timeout_ms| milliseconds.
4227**
4228** Returns void
4229*******************************************************************************/
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08004230static void sleep_ms(period_ms_t timeout_ms) {
Pavlin Radoslavov642f2332015-09-16 13:30:26 -07004231 struct timespec delay;
4232 delay.tv_sec = timeout_ms / 1000;
4233 delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
4234
4235 int err;
4236 do {
4237 err = nanosleep(&delay, &delay);
4238 } while (err == -1 && errno == EINTR);
4239}
Andre Eisenbachfeb9e4d2016-02-08 15:37:45 -08004240
4241static bool absolute_volume_disabled() {
Andre Eisenbachfeb9e4d2016-02-08 15:37:45 -08004242 char volume_disabled[PROPERTY_VALUE_MAX] = {0};
Jakub Pawlowski3eb4a482016-02-24 10:39:46 -08004243 osi_property_get("persist.bluetooth.disableabsvol", volume_disabled, "false");
Andre Eisenbachfeb9e4d2016-02-08 15:37:45 -08004244 if (strncmp(volume_disabled, "true", 4) == 0) {
4245 BTIF_TRACE_WARNING("%s: Absolute volume disabled by property", __func__);
4246 return true;
4247 }
Andre Eisenbachfeb9e4d2016-02-08 15:37:45 -08004248 return false;
4249}