1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /*****************************************************************************
16  *
17  *  Filename:      btc_avrc.c
18  *
19  *  Description:   Bluetooth AVRC implementation
20  *
21  *****************************************************************************/
22 #include "common/bt_target.h"
23 #include <string.h>
24 #include "bta/bta_api.h"
25 #include "bta/bta_av_api.h"
26 #include "stack/avrc_defs.h"
27 #include "btc/btc_common.h"
28 #include "btc/btc_util.h"
29 #include "btc_av.h"
30 #include "btc_avrc.h"
31 #include "btc/btc_manage.h"
32 #include "esp_avrc_api.h"
33 #include "osi/mutex.h"
34 #include "osi/allocator.h"
35 
36 #if BTC_AV_INCLUDED
37 
38 static UINT8 opcode_from_pdu(UINT8 pdu);
39 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status);
40 static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open);
41 static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close);
42 static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp);
43 static void handle_rc_metamsg_cmd ( tBTA_AV_META_MSG *p_meta_msg);
44 static void handle_rc_metamsg_rsp ( tBTA_AV_META_MSG *p_remote_rsp);
45 static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label);
46 
47 /*****************************************************************************
48 **  Static variables
49 ******************************************************************************/
50 
51 /* flag indicating wheter TG/CT is initialized */
52 static uint32_t s_rc_ct_init;
53 static uint32_t s_rc_tg_init;
54 
55 #if AVRC_DYNAMIC_MEMORY == FALSE
56 static btc_rc_cb_t btc_rc_cb;
57 #else
58 btc_rc_cb_t *btc_rc_cb_ptr;
59 #endif ///AVRC_DYNAMIC_MEMORY == FALSE
60 
61 const static uint16_t cs_psth_allowed_cmd[8] = {
62     0x0000, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
63                          4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN, 7=LEFT_UP,
64                          8=LEFT_DOWN, 9=ROOT_MENU, 10=SETUP_MENU, 11=CONT_MENU,
65                          12=FAV_MENU, 13=EXIT */
66     0x0000, /* not used */
67     0x1FFF, /* bit mask: 0=0, 1=1, 2=2, 3=3,
68                          4=4, 5=5, 6=6, 7=7,
69                          8=8, 9=9, 10=DOT, 11=ENTER,
70                          12=CLEAR */
71     0x0078, /* bit mask: 0=CHAN_UP, 1=CHAN_DOWN, 2=PREV_CHAN, 3=SOUND_SEL,
72                          4=INPUT_SEL, 5=DISP_INFO, 6=HELP, 7=PAGE_UP,
73                          8=PAGE_DOWN */
74     0x1b7F, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
75                          4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
76                          8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
77                          12=BACKWARD */
78     0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
79     0x0000, /* not used */
80     0x003E  /* bit mask: 0=not used, 1=F1, 2=F2, 3=F3,
81                          4=F4, 5=F5 */
82 };
83 
84 const static uint16_t cs_psth_dft_supported_cmd[8] = {0};
85 static uint16_t s_psth_supported_cmd[8];
86 
87 const static uint16_t cs_rn_allowed_evt = \
88         0x2000; /* bit mask: 0=rsvd, 1=play_status, 2=track_chg, 3=reached_end,
89                              4=reached_start, 5=pos_chg, 6=batt_status, 7=sys_status_chg,
90                              8=player_app_setting, 9=now_playing_content, 10=avail_players, 11=addressed_player,
91                              12=UID, 13=volume_chg */
92 
93 const static uint16_t cs_rn_dft_supported_evt = 0;
94 static uint16_t s_rn_supported_evt;
95 
96 // event ids supported to register as CT
97 const static uint16_t cs_ct_rn_supported_evt = \
98         0x2026; /* bit mask: 0=rsvd, 1=play_status, 2=track_chg, 3=reached_end,
99                              4=reached_start, 5=pos_chg, 6=batt_status, 7=sys_status_chg,
100                              8=player_app_setting, 9=now_playing_content, 10=avail_players, 11=addressed_player,
101                              12=UID, 13=volume_chg */
102 
103 /*****************************************************************************
104 **  Externs
105 ******************************************************************************/
btc_avrc_tg_get_allowed_command(void)106 const uint16_t *btc_avrc_tg_get_allowed_command(void)
107 {
108     return cs_psth_allowed_cmd;
109 }
110 
btc_avrc_tg_get_supported_command(void)111 const uint16_t *btc_avrc_tg_get_supported_command(void)
112 {
113     return s_psth_supported_cmd;
114 }
115 
btc_avrc_tg_check_supported_command(const uint16_t * cmd_set)116 bool btc_avrc_tg_check_supported_command(const uint16_t *cmd_set)
117 {
118     if (cmd_set == NULL) {
119         return false;
120     }
121 
122     // check if cmd_set is a subset of allowed command set
123     bool ret = true;
124     for (int i = 0; i < 8; ++i) {
125         if (cs_psth_allowed_cmd[i] != (cmd_set[i] | cs_psth_allowed_cmd[i])) {
126             ret = false;
127             break;
128         }
129     }
130 
131     return ret;
132 }
133 
btc_avrc_tg_get_rn_allowed_evt(void)134 uint16_t btc_avrc_tg_get_rn_allowed_evt(void)
135 {
136     return cs_rn_allowed_evt;
137 }
138 
btc_avrc_tg_get_rn_supported_evt(void)139 uint16_t btc_avrc_tg_get_rn_supported_evt(void)
140 {
141     return s_rn_supported_evt;
142 }
143 
btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set)144 bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set)
145 {
146     uint16_t evt_super_set = evt_set | cs_rn_allowed_evt;
147     if (evt_super_set == cs_rn_allowed_evt) {
148         return true;
149     } else {
150         return false;
151     }
152 }
153 
btc_avrc_tg_rn_evt_supported(uint8_t event_id)154 bool btc_avrc_tg_rn_evt_supported(uint8_t event_id)
155 {
156     uint16_t event_bits = s_rn_supported_evt;
157     return ((event_bits >> event_id) & 0x0001) ?
158            true : false;
159 }
160 
btc_avrc_ct_rn_evt_supported(uint8_t event_id)161 bool btc_avrc_ct_rn_evt_supported(uint8_t event_id)
162 {
163     uint16_t event_bits = cs_ct_rn_supported_evt;
164     return ((event_bits >> event_id) & 0x0001) ?
165            true : false;
166 }
167 
btc_avrc_tg_init_p(void)168 bool btc_avrc_tg_init_p(void)
169 {
170     return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC);
171 }
172 
btc_avrc_ct_init_p(void)173 bool btc_avrc_ct_init_p(void)
174 {
175     return (s_rc_ct_init == BTC_RC_CT_INIT_MAGIC);
176 }
177 
btc_avrc_tg_connected_p(void)178 bool btc_avrc_tg_connected_p(void)
179 {
180     return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) &&
181            (btc_rc_cb.rc_connected == TRUE) &&
182            (btc_rc_cb.rc_features & BTA_AV_FEAT_RCCT);
183 }
184 
btc_avrc_ct_connected_p(void)185 bool btc_avrc_ct_connected_p(void)
186 {
187     return (s_rc_ct_init == BTC_RC_CT_INIT_MAGIC) &&
188            (btc_rc_cb.rc_connected == TRUE) &&
189            (btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG);
190 }
191 
btc_avrc_tg_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)192 void btc_avrc_tg_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
193 {
194     btc_avrc_tg_args_t *dst = (btc_avrc_tg_args_t *) p_dest;
195     btc_avrc_tg_args_t *src = (btc_avrc_tg_args_t *)p_src;
196     size_t len;
197 
198     switch (msg->act) {
199     case BTC_AVRC_TG_API_SET_PSTH_SUPPORTED_CMD_EVT:
200         len = 8 * sizeof(uint16_t);
201         dst->set_psth_cmd = (uint16_t *)osi_malloc(len);
202         if (dst->set_psth_cmd) {
203             memcpy(dst->set_psth_cmd, src->set_psth_cmd, len);
204         } else {
205             BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act);
206         }
207         break;
208     default:
209         BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __FUNCTION__, msg->act);
210         break;
211     }
212 }
213 
214 /*****************************************************************************
215 **  Static functions
216 ******************************************************************************/
btc_avrc_tg_arg_deep_free(btc_msg_t * msg)217 static void btc_avrc_tg_arg_deep_free(btc_msg_t *msg)
218 {
219     btc_avrc_tg_args_t *arg = (btc_avrc_tg_args_t *)msg->arg;
220 
221     switch (msg->act) {
222     case BTC_AVRC_TG_API_SET_PSTH_SUPPORTED_CMD_EVT:
223         if (arg->set_psth_cmd) {
224             osi_free(arg->set_psth_cmd);
225         }
226         break;
227     default:
228         BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __FUNCTION__, msg->act);
229         break;
230     }
231 }
232 
btc_avrc_tg_set_supported_command(const uint16_t * cmd_set)233 static bool btc_avrc_tg_set_supported_command(const uint16_t *cmd_set)
234 {
235     if (!btc_avrc_tg_init_p()) {
236         BTC_TRACE_WARNING("%s failed: AVRC TG not yet initialized\n", __FUNCTION__);
237         return false;
238     }
239     if (!btc_avrc_tg_check_supported_command(cmd_set)) {
240         return false;
241     } else {
242         memcpy(s_psth_supported_cmd, cmd_set, sizeof(s_psth_supported_cmd));
243         return true;
244     }
245 }
246 
btc_avrc_tg_set_rn_supported_evt(uint16_t evt_set)247 static bool btc_avrc_tg_set_rn_supported_evt(uint16_t evt_set)
248 {
249     if (!btc_avrc_tg_init_p()) {
250         BTC_TRACE_WARNING("%s failed: AVRC TG not yet initialized\n", __FUNCTION__);
251         return false;
252     }
253 
254     if (btc_avrc_tg_check_rn_supported_evt(evt_set)) {
255         s_rn_supported_evt = evt_set;
256         return true;
257     } else {
258         return false;
259     }
260 }
261 
btc_avrc_ct_cb_to_app(esp_avrc_ct_cb_event_t event,esp_avrc_ct_cb_param_t * param)262 static inline void btc_avrc_ct_cb_to_app(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)
263 {
264     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
265         return;
266     }
267 
268     esp_avrc_ct_cb_t btc_avrc_ct_cb = (esp_avrc_ct_cb_t)btc_profile_cb_get(BTC_PID_AVRC_CT);
269     if (btc_avrc_ct_cb) {
270         btc_avrc_ct_cb(event, param);
271     }
272 }
273 
btc_avrc_tg_cb_to_app(esp_avrc_tg_cb_event_t event,esp_avrc_tg_cb_param_t * param)274 static inline void btc_avrc_tg_cb_to_app(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param)
275 {
276     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
277         return;
278     }
279 
280     esp_avrc_tg_cb_t btc_avrc_tg_cb = (esp_avrc_tg_cb_t)btc_profile_cb_get(BTC_PID_AVRC_TG);
281     if (btc_avrc_tg_cb) {
282         btc_avrc_tg_cb(event, param);
283     }
284 }
285 
286 /***************************************************************************
287  *  Function       send_metamsg_rsp
288  *
289  *  - Argument:
290  *                  rc_handle     RC handle corresponding to the connected RC
291  *                  label            Label of the RC response
292  *                  code            Response type
293  *                  p_meta_rsp      Vendor response
294  *
295  *  - Description: Remote control metamsg response handler (AVRCP 1.3)
296  *
297  ***************************************************************************/
send_metamsg_rsp(UINT8 rc_handle,UINT8 label,tBTA_AV_CODE code,tAVRC_RESPONSE * p_meta_rsp)298 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
299                               tAVRC_RESPONSE *p_meta_rsp)
300 {
301     UINT8 ctype;
302 
303     if (!p_meta_rsp) {
304         BTC_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
305         return;
306     }
307 
308     BTC_TRACE_EVENT("%s: rc_handle: %d, label: %d, code: 0x%02x, pdu: %d", __FUNCTION__,
309                     rc_handle, label, code, p_meta_rsp->rsp.pdu);
310 
311     if (p_meta_rsp->rsp.status != AVRC_STS_NO_ERROR) {
312         ctype = AVRC_RSP_REJ;
313     } else {
314         if (code < AVRC_RSP_NOT_IMPL) {
315             if (code == AVRC_CMD_NOTIF) {
316                 ctype = AVRC_RSP_INTERIM;
317             } else if (code == AVRC_CMD_STATUS) {
318                 ctype = AVRC_RSP_IMPL_STBL;
319             } else {
320                 ctype = AVRC_RSP_ACCEPT;
321             }
322         } else {
323             ctype = code;
324         }
325     }
326 
327     /* if response is for register_notification, make sure the rc has actually registered for this */
328     if ((p_meta_rsp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED)) {
329         UINT8   event_id = p_meta_rsp->reg_notif.event_id;
330         BOOLEAN notify = (btc_rc_cb.rc_connected) && (btc_rc_cb.rc_ntf[event_id - 1].registered);
331 
332         /* de-register this notification for a CHANGED response */
333         btc_rc_cb.rc_ntf[event_id - 1].registered = FALSE;
334         BTC_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d deregistered", __FUNCTION__,
335                         btc_rc_cb.rc_handle, event_id);
336         if (notify) {
337             BT_HDR *p_msg = NULL;
338             tAVRC_STS status = AVRC_BldResponse(btc_rc_cb.rc_handle, p_meta_rsp, &p_msg);
339 
340             if (status == AVRC_STS_NO_ERROR) {
341                 BTC_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
342                                 __FUNCTION__, btc_rc_cb.rc_handle, event_id);
343                 BTA_AvMetaRsp(btc_rc_cb.rc_handle, btc_rc_cb.rc_ntf[event_id - 1].label, ctype, p_msg);
344             } else {
345                 BTC_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x",
346                                   __FUNCTION__, status);
347             }
348         }
349     } else {
350         // send response
351         BT_HDR *p_msg = NULL;
352         tAVRC_STS status;
353 
354         status = AVRC_BldResponse(rc_handle, p_meta_rsp, &p_msg);
355 
356         if (status == AVRC_STS_NO_ERROR) {
357             BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
358         } else {
359             BTC_TRACE_ERROR("%s: failed to build metamsg response. status: 0x%02x",
360                             __FUNCTION__, status);
361         }
362     }
363 }
364 
365 
opcode_from_pdu(UINT8 pdu)366 static UINT8 opcode_from_pdu(UINT8 pdu)
367 {
368     UINT8 opcode = 0;
369 
370     switch (pdu) {
371     case AVRC_PDU_NEXT_GROUP:
372     case AVRC_PDU_PREV_GROUP: /* pass thru */
373         opcode  = AVRC_OP_PASS_THRU;
374         break;
375 
376     default: /* vendor */
377         opcode  = AVRC_OP_VENDOR;
378         break;
379     }
380 
381     return opcode;
382 }
383 
384 /* Generic reject response */
send_reject_response(UINT8 rc_handle,UINT8 label,UINT8 pdu,UINT8 status)385 static void send_reject_response (UINT8 rc_handle, UINT8 label, UINT8 pdu, UINT8 status)
386 {
387     UINT8 ctype = AVRC_RSP_REJ;
388     tAVRC_RESPONSE avrc_rsp;
389     BT_HDR *p_msg = NULL;
390     memset (&avrc_rsp, 0, sizeof(tAVRC_RESPONSE));
391 
392     avrc_rsp.rsp.opcode = opcode_from_pdu(pdu);
393     avrc_rsp.rsp.pdu    = pdu;
394     avrc_rsp.rsp.status = status;
395 
396     if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(rc_handle, &avrc_rsp, &p_msg)) ) {
397         BTC_TRACE_DEBUG("%s: Sending error notification to handle:%d. pdu:%s,status:0x%02x",
398                         __FUNCTION__, rc_handle, dump_rc_pdu(pdu), status);
399         BTA_AvMetaRsp(rc_handle, label, ctype, p_msg);
400     }
401 }
402 
handle_rc_features(void)403 static void handle_rc_features(void)
404 {
405     if ((btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
406         (btc_rc_cb.rc_tg_features != 0)) {
407         esp_avrc_ct_cb_param_t param;
408         memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
409         param.rmt_feats.feat_mask = btc_rc_cb.rc_features;
410         param.rmt_feats.tg_feat_flag = btc_rc_cb.rc_tg_features;
411         memcpy(param.rmt_feats.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
412         btc_avrc_ct_cb_to_app(ESP_AVRC_CT_REMOTE_FEATURES_EVT, &param);
413     }
414 
415     if ((btc_rc_cb.rc_features & BTA_AV_FEAT_RCCT) &&
416         (btc_rc_cb.rc_ct_features != 0)) {
417         esp_avrc_tg_cb_param_t param;
418         memset(&param, 0, sizeof(esp_avrc_tg_cb_param_t));
419         param.rmt_feats.feat_mask = btc_rc_cb.rc_features;
420         param.rmt_feats.ct_feat_flag = btc_rc_cb.rc_ct_features;
421         memcpy(param.rmt_feats.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
422         btc_avrc_tg_cb_to_app(ESP_AVRC_TG_REMOTE_FEATURES_EVT, &param);
423     }
424 }
425 
426 
427 /***************************************************************************
428  *  Function       handle_rc_connect
429  *
430  *  - Argument:    tBTA_AV_RC_OPEN  RC open data structure
431  *
432  *  - Description: RC connection event handler
433  *
434  ***************************************************************************/
handle_rc_connect(tBTA_AV_RC_OPEN * p_rc_open)435 static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
436 {
437     BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
438     bt_bdaddr_t rc_addr;
439 
440     if (p_rc_open->status == BTA_AV_SUCCESS) {
441         //check if already some RC is connected
442         if (btc_rc_cb.rc_connected) {
443             BTC_TRACE_ERROR("Got RC OPEN in connected state, Connected RC: %d \
444                 and Current RC: %d", btc_rc_cb.rc_handle, p_rc_open->rc_handle );
445             if ((btc_rc_cb.rc_handle != p_rc_open->rc_handle)
446                     && (bdcmp(btc_rc_cb.rc_addr, p_rc_open->peer_addr))) {
447                 BTC_TRACE_DEBUG("Got RC connected for some other handle");
448                 BTA_AvCloseRc(p_rc_open->rc_handle);
449                 return;
450             }
451         }
452         memcpy(btc_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
453         btc_rc_cb.rc_features = p_rc_open->peer_features;
454         btc_rc_cb.rc_connected = TRUE;
455         btc_rc_cb.rc_handle = p_rc_open->rc_handle;
456 
457         bdcpy(rc_addr.address, btc_rc_cb.rc_addr);
458         // callback to application
459         if (p_rc_open->peer_features & BTA_AV_FEAT_RCTG) {
460             esp_avrc_ct_cb_param_t param;
461             memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
462             param.conn_stat.connected = true;
463             memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
464             btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
465         }
466 
467         if (p_rc_open->peer_features & BTA_AV_FEAT_RCCT) {
468             esp_avrc_tg_cb_param_t param;
469             memset(&param, 0, sizeof(esp_avrc_tg_cb_param_t));
470             param.conn_stat.connected = true;
471             memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
472             btc_avrc_tg_cb_to_app(ESP_AVRC_TG_CONNECTION_STATE_EVT, &param);
473         }
474 
475         /* on locally initiated connection we will get remote features as part of connect */
476         if (p_rc_open->sdp_disc_done == TRUE) {
477             btc_rc_cb.rc_ct_features = p_rc_open->peer_ct_features;
478             btc_rc_cb.rc_tg_features = p_rc_open->peer_tg_features;
479             handle_rc_features();
480         }
481     } else {
482         BTC_TRACE_ERROR("%s Connect failed with error code: %d",
483                         __FUNCTION__, p_rc_open->status);
484         btc_rc_cb.rc_connected = FALSE;
485     }
486 }
487 
488 /***************************************************************************
489  *  Function       handle_rc_disconnect
490  *
491  *  - Argument:    tBTA_AV_RC_CLOSE     RC close data structure
492  *
493  *  - Description: RC disconnection event handler
494  *
495  ***************************************************************************/
handle_rc_disconnect(tBTA_AV_RC_CLOSE * p_rc_close)496 static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
497 {
498     BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
499     if ((p_rc_close->rc_handle != btc_rc_cb.rc_handle)
500             && (bdcmp(btc_rc_cb.rc_addr, p_rc_close->peer_addr))) {
501         BTC_TRACE_ERROR("Got disconnect of unknown device");
502         return;
503     }
504 
505     tBTA_AV_FEAT rc_features = btc_rc_cb.rc_features;
506 
507     // clean up the state
508     btc_rc_cb.rc_handle = 0;
509     btc_rc_cb.rc_connected = FALSE;
510 
511     btc_rc_cb.rc_features = 0;
512     btc_rc_cb.rc_ct_features = 0;
513     btc_rc_cb.rc_tg_features = 0;
514     memset(btc_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
515     memset(btc_rc_cb.rc_ntf, 0, sizeof(btc_rc_cb.rc_ntf));
516 
517     /* report connection state */
518     if (rc_features & BTA_AV_FEAT_RCTG) {
519         esp_avrc_ct_cb_param_t param;
520         memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
521         param.conn_stat.connected = false;
522         memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
523         btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
524     }
525 
526     if (rc_features & BTA_AV_FEAT_RCCT) {
527         esp_avrc_tg_cb_param_t param;
528         memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
529         param.conn_stat.connected = false;
530         memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
531         btc_avrc_tg_cb_to_app(ESP_AVRC_TG_CONNECTION_STATE_EVT, &param);
532     }
533 }
534 
handle_rc_attributes_rsp(tAVRC_MSG_VENDOR * vendor_msg)535 static void handle_rc_attributes_rsp (tAVRC_MSG_VENDOR *vendor_msg)
536 {
537     uint8_t attr_count = vendor_msg->p_vendor_data[4];
538     int attr_index = 5;
539     int attr_length = 0;
540     uint32_t attr_id = 0;
541 
542     //Check if there are any attributes
543     if (attr_count < 1) {
544         return;
545     }
546 
547     esp_avrc_ct_cb_param_t param[attr_count];
548     memset(&param[0], 0, sizeof(esp_avrc_ct_cb_param_t) * attr_count);
549 
550     for (int i = 0; i < attr_count; i++) {
551         attr_length = (int) vendor_msg->p_vendor_data[7 + attr_index] | vendor_msg->p_vendor_data[6 + attr_index] << 8;
552 
553         //Received attribute text is not null terminated, so it's useful to know it's length
554         param[i].meta_rsp.attr_length = attr_length;
555         param[i].meta_rsp.attr_text = &vendor_msg->p_vendor_data[8 + attr_index];
556 
557         attr_id = vendor_msg->p_vendor_data[3 + attr_index] |
558                   vendor_msg->p_vendor_data[2 + attr_index] << 8 | vendor_msg->p_vendor_data[1 + attr_index] << 16 |
559                   vendor_msg->p_vendor_data[attr_index] << 24;
560 
561         //Convert to mask id
562         param[i].meta_rsp.attr_id = (1 << (attr_id - 1));
563 
564         btc_avrc_ct_cb_to_app(ESP_AVRC_CT_METADATA_RSP_EVT, &param[i]);
565 
566         attr_index += attr_length + 8;
567     }
568 }
569 
handle_rc_notification_rsp(tAVRC_MSG_VENDOR * vendor_msg)570 static void handle_rc_notification_rsp (tAVRC_MSG_VENDOR *vendor_msg)
571 {
572     esp_avrc_ct_cb_param_t param;
573     memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
574 
575     param.change_ntf.event_id = vendor_msg->p_vendor_data[4];
576 
577     uint8_t *data = &vendor_msg->p_vendor_data[5];
578     if (!btc_avrc_ct_rn_evt_supported(param.change_ntf.event_id)) {
579         BTC_TRACE_WARNING("%s unsupported notification on CT, event id 0x%x", __FUNCTION__,
580                           param.change_ntf.event_id);
581         return;
582     }
583 
584     switch (param.change_ntf.event_id) {
585     case ESP_AVRC_RN_PLAY_STATUS_CHANGE:
586         BE_STREAM_TO_UINT8(param.change_ntf.event_parameter.playback, data);
587         break;
588     case ESP_AVRC_RN_TRACK_CHANGE:
589         memcpy(param.change_ntf.event_parameter.elm_id, data, 8);
590         break;
591     case ESP_AVRC_RN_PLAY_POS_CHANGED:
592         BE_STREAM_TO_UINT32(param.change_ntf.event_parameter.play_pos, data);
593         break;
594     case ESP_AVRC_RN_BATTERY_STATUS_CHANGE:
595         BE_STREAM_TO_UINT8(param.change_ntf.event_parameter.batt, data);
596         break;
597     case ESP_AVRC_RN_VOLUME_CHANGE:
598         BE_STREAM_TO_UINT8(param.change_ntf.event_parameter.volume, data);
599         break;
600     // for non-parameter event response
601     case ESP_AVRC_RN_TRACK_REACHED_END:
602     case ESP_AVRC_RN_TRACK_REACHED_START:
603         break;
604     // for other unsupported event:
605     case ESP_AVRC_RN_SYSTEM_STATUS_CHANGE:
606     case ESP_AVRC_RN_APP_SETTING_CHANGE:
607     case ESP_AVRC_RN_NOW_PLAYING_CHANGE:
608     case ESP_AVRC_RN_AVAILABLE_PLAYERS_CHANGE:
609     case ESP_AVRC_RN_ADDRESSED_PLAYER_CHANGE:
610     case ESP_AVRC_RN_UIDS_CHANGE:
611     default:
612         BTC_TRACE_WARNING("%s RC unhandled notification response, event id 0x%x", __FUNCTION__,
613                           param.change_ntf.event_id);
614         break;
615     }
616     btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CHANGE_NOTIFY_EVT, &param);
617 }
618 
handle_rc_get_caps_rsp(tAVRC_GET_CAPS_RSP * rsp)619 static void handle_rc_get_caps_rsp (tAVRC_GET_CAPS_RSP *rsp)
620 {
621     if (rsp->capability_id == AVRC_CAP_EVENTS_SUPPORTED) {
622         esp_avrc_ct_cb_param_t param;
623         memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
624         param.get_rn_caps_rsp.cap_count = rsp->count;
625         for (int i = 0; i < rsp->count; ++i) {
626             esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &param.get_rn_caps_rsp.evt_set,
627                                                rsp->param.event_id[i]);
628         }
629         btc_avrc_ct_cb_to_app(ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT, &param);
630     } else {
631         // ignore other capability_id
632         BTC_TRACE_WARNING("AVRC unhandled event, CapabilityID: 0x%x", rsp->capability_id);
633         return;
634     }
635 }
636 
handle_rc_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP * rsp)637 static void handle_rc_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *rsp)
638 {
639     esp_avrc_ct_cb_param_t param;
640     memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
641 
642     param.set_volume_rsp.volume = rsp->volume;
643 
644     btc_avrc_ct_cb_to_app(ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT, &param);
645 }
646 
647 /***************************************************************************
648  *  Function       handle_rc_metamsg_cmd
649  *
650  *  - Argument:    tBTA_AV_VENDOR Structure containing the received
651  *                          metamsg command
652  *
653  *  - Description: Remote control metamsg command handler (AVRCP 1.3)
654  *
655  ***************************************************************************/
handle_rc_metamsg_cmd(tBTA_AV_META_MSG * p_meta_msg)656 static void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *p_meta_msg)
657 {
658     BTC_TRACE_DEBUG("%s, opcode 0x%x, len %d, code %d", __FUNCTION__, p_meta_msg->p_msg->hdr.opcode, p_meta_msg->len, p_meta_msg->code);
659 
660     if (p_meta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR) {
661         BTC_TRACE_WARNING("Invalid opcode: %x", p_meta_msg->p_msg->hdr.opcode);
662         return;
663     }
664     if (p_meta_msg->len < 3) {
665         BTC_TRACE_WARNING("Invalid length.Opcode: 0x%x, len: 0x%x", p_meta_msg->p_msg->hdr.opcode,
666                           p_meta_msg->len);
667         return;
668     }
669 
670     if (p_meta_msg->code >= AVRC_RSP_NOT_IMPL) {
671 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
672         handle_rc_metamsg_rsp(p_meta_msg);
673 #else
674         BTC_TRACE_WARNING("%s:Received vendor dependent rsp. code: %d len: %d. Not processing it.",
675                           __FUNCTION__, p_meta_msg->code, p_meta_msg->len);
676 #endif
677         return;
678     }
679 
680 #define RC_CMD_PRS_BUF_LEN  (512)
681     uint8_t *buf = (uint8_t *)osi_calloc(RC_CMD_PRS_BUF_LEN);
682     tAVRC_COMMAND avrc_command = {0};
683     tAVRC_STS status;
684 
685     status = AVRC_ParsCommand(p_meta_msg->p_msg, &avrc_command, buf, RC_CMD_PRS_BUF_LEN);
686     BTC_TRACE_DEBUG("Rcv vendor cmd: code %d, PDU 0x%x, label %d", p_meta_msg->code,
687                     avrc_command.cmd.pdu, p_meta_msg->label);
688 
689     if (status != AVRC_STS_NO_ERROR) {
690         /* return error */
691         BTC_TRACE_WARNING("%s: Error in parsing vendor command. status: 0x%02x",
692                           __FUNCTION__, status);
693         send_reject_response(p_meta_msg->rc_handle, p_meta_msg->label, avrc_command.pdu, status);
694     } else {
695         btc_rc_upstreams_evt(avrc_command.cmd.pdu, &avrc_command, p_meta_msg->code, p_meta_msg->label);
696     }
697     osi_free(buf);
698 }
699 
700 /*******************************************************************************
701 **
702 ** Function         btc_rc_upstreams_evt
703 **
704 ** Description      Executes AVRC UPSTREAMS events in btc context.
705 **
706 ** Returns          void
707 **
708 *******************************************************************************/
btc_rc_upstreams_evt(UINT16 event,tAVRC_COMMAND * pavrc_cmd,UINT8 ctype,UINT8 label)709 static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
710 {
711     BTC_TRACE_EVENT("%s pdu: 0x%x handle: 0x%x ctype:%x label:%x", __FUNCTION__,
712                     pavrc_cmd->pdu, btc_rc_cb.rc_handle, ctype, label);
713 
714     switch (event) {
715     case AVRC_PDU_SET_ABSOLUTE_VOLUME: {
716         // set up response
717         tAVRC_RESPONSE avrc_rsp;
718         BTC_TRACE_EVENT("%s() AVRC_PDU_SET_ABSOLUTE_VOLUME", __FUNCTION__);
719         memset(&(avrc_rsp.volume), 0, sizeof(tAVRC_RSP));
720         avrc_rsp.volume.opcode = opcode_from_pdu(AVRC_PDU_SET_ABSOLUTE_VOLUME);
721         avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
722         avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
723         avrc_rsp.volume.volume = pavrc_cmd->volume.volume;
724         send_metamsg_rsp(btc_rc_cb.rc_handle, label, ctype, &avrc_rsp);
725 
726         // set up callback
727         esp_avrc_tg_cb_param_t param;
728         memset(&param, 0, sizeof(esp_avrc_tg_cb_param_t));
729         param.set_abs_vol.volume = pavrc_cmd->volume.volume;
730         btc_avrc_tg_cb_to_app(ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT, &param);
731     }
732     break;
733     case AVRC_PDU_SET_PLAYER_APP_VALUE: {
734         // set up callback
735         esp_avrc_tg_cb_param_t param;
736         param.set_app_value.num_val = pavrc_cmd->set_app_val.num_val;
737         param.set_app_value.p_vals = (esp_avrc_set_app_value_param_t *)pavrc_cmd->set_app_val.p_vals;
738         btc_avrc_tg_cb_to_app(ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT, &param);
739     }
740     break;
741     case AVRC_PDU_GET_PLAY_STATUS:
742     case AVRC_PDU_GET_ELEMENT_ATTR:
743     case AVRC_PDU_INFORM_DISPLAY_CHARSET:
744     //todo: check the valid response for these PDUs
745     case AVRC_PDU_LIST_PLAYER_APP_ATTR:
746     case AVRC_PDU_LIST_PLAYER_APP_VALUES:
747     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
748     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT:
749     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: {
750         send_reject_response (btc_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_CMD);
751     }
752     break;
753     case AVRC_PDU_REGISTER_NOTIFICATION: {
754         UINT8 event_id = pavrc_cmd->reg_notif.event_id;
755         if (event_id > MAX_RC_NOTIFICATIONS) {
756             BTC_TRACE_WARNING("Invalid event_id: 0x%x", event_id);
757             break;
758         }
759 
760         btc_rc_cb.rc_ntf[event_id - 1].registered = TRUE;
761         btc_rc_cb.rc_ntf[event_id - 1].label = label;
762         BTC_TRACE_EVENT("%s: New registerd notification: event_id:0x%x, label:0x%x",
763                         __FUNCTION__, event_id, label);
764 
765         // set up callback
766         esp_avrc_tg_cb_param_t param;
767         memset(&param, 0, sizeof(esp_avrc_tg_cb_param_t));
768         param.reg_ntf.event_id = pavrc_cmd->reg_notif.event_id;
769         param.reg_ntf.event_parameter = pavrc_cmd->reg_notif.param;
770         btc_avrc_tg_cb_to_app(ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT, &param);
771     }
772     break;
773     default: {
774         send_reject_response (btc_rc_cb.rc_handle, label, pavrc_cmd->pdu,
775                               (pavrc_cmd->pdu == AVRC_PDU_SEARCH) ? AVRC_STS_SEARCH_NOT_SUP : AVRC_STS_BAD_CMD);
776     }
777     break;
778     }
779     return;
780 }
781 
782 /***************************************************************************
783  *  Function       handle_rc_metamsg_rsp
784  *
785  *  - Argument:    tBTA_AV_META_MSG metadata command response
786  *
787  *  - Description: Vendor metadata response handler
788  *
789  ***************************************************************************/
handle_rc_metamsg_rsp(tBTA_AV_META_MSG * p_meta_msg)790 static void handle_rc_metamsg_rsp (tBTA_AV_META_MSG *p_meta_msg)
791 {
792     tAVRC_RESPONSE avrc_response = {0};
793     tAVRC_STS status;
794     tAVRC_MSG_VENDOR *vendor_msg = &p_meta_msg->p_msg->vendor;
795     BTC_TRACE_DEBUG("%s: opcode %d, pdu 0x%x, code %d", __FUNCTION__, p_meta_msg->p_msg->hdr.opcode, vendor_msg->p_vendor_data[0],
796                     p_meta_msg->code);
797     if ( p_meta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR) {
798         return;
799     }
800     if (p_meta_msg->code != AVRC_RSP_CHANGED &&
801             p_meta_msg->code != AVRC_RSP_INTERIM &&
802             p_meta_msg->code != AVRC_RSP_ACCEPT &&
803             p_meta_msg->code != AVRC_RSP_REJ &&
804             p_meta_msg->code != AVRC_RSP_NOT_IMPL &&
805             p_meta_msg->code != AVRC_RSP_IMPL_STBL) {
806         return;
807     }
808 
809     // handle GET_ELEMENT_ATTR response
810     if (p_meta_msg->code == AVRC_RSP_IMPL_STBL &&
811             vendor_msg->p_vendor_data[0] == AVRC_PDU_GET_ELEMENT_ATTR) {
812         handle_rc_attributes_rsp(vendor_msg);
813         return;
814     }
815 
816     status = AVRC_ParsResponse(p_meta_msg->p_msg, &avrc_response);
817     if (status != AVRC_STS_NO_ERROR) {
818         BTC_TRACE_WARNING("%s: code %d error 0x%x", __FUNCTION__, p_meta_msg->code, status);
819         return;
820     }
821 
822     tAVRC_MSG *avrc_msg = p_meta_msg->p_msg;
823     vendor_msg = &avrc_msg->vendor;
824     switch (avrc_response.rsp.pdu) {
825     case AVRC_PDU_REGISTER_NOTIFICATION:
826         if (vendor_msg->hdr.ctype == AVRC_RSP_CHANGED) {
827             handle_rc_notification_rsp(vendor_msg);
828         } else if (vendor_msg->hdr.ctype == AVRC_RSP_INTERIM) {
829             // ignore this response
830         }
831         break;
832     case AVRC_PDU_GET_ELEMENT_ATTR:
833         // todo: handle this PDU here
834         break;
835     case AVRC_PDU_GET_CAPABILITIES:
836         if (vendor_msg->hdr.ctype == AVRC_RSP_IMPL_STBL) {
837             handle_rc_get_caps_rsp(&avrc_response.get_caps);
838         }
839         break;
840     case AVRC_PDU_SET_ABSOLUTE_VOLUME:
841         if (vendor_msg->hdr.ctype == AVRC_RSP_ACCEPT) {
842             handle_rc_set_absolute_volume_rsp(&avrc_response.volume);
843         }
844         break;
845     default:
846         BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu);
847     }
848 }
849 
850 /***************************************************************************
851  *  Function       handle_rc_passthrough_rsp
852  *
853  *  - Argument:    tBTA_AV_REMOTE_RSP passthrough command response
854  *
855  *  - Description: Remote control passthrough response handler
856  *
857  ***************************************************************************/
handle_rc_passthrough_rsp(tBTA_AV_REMOTE_RSP * p_remote_rsp)858 static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
859 {
860 #if (AVRC_CTLR_INCLUDED == TRUE)
861     const char *status;
862     if (btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG) {
863         int key_state;
864         if (p_remote_rsp->key_state == AVRC_STATE_RELEASE) {
865             status = "released";
866             key_state = 1;
867         } else {
868             status = "pressed";
869             key_state = 0;
870         }
871 
872         BTC_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
873 
874         do {
875             esp_avrc_ct_cb_param_t param;
876             memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
877             param.psth_rsp.tl = p_remote_rsp->label;
878             param.psth_rsp.key_code = p_remote_rsp->rc_id;
879             param.psth_rsp.key_state = key_state;
880             btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PASSTHROUGH_RSP_EVT, &param);
881         } while (0);
882     } else {
883         BTC_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__);
884     }
885 
886     UNUSED(status);
887 #else
888     BTC_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__);
889 #endif
890 }
891 
892 /***************************************************************************
893  *  Function       handle_rc_passthrough_cmd
894  *
895  *  - Argument:    tBTA_AV_RC rc_id   remote control command ID
896  *                 tBTA_AV_STATE key_state status of key press
897  *
898  *  - Description: Remote control command handler
899  *
900  ***************************************************************************/
handle_rc_passthrough_cmd(tBTA_AV_REMOTE_CMD * p_remote_cmd)901 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
902 {
903     esp_avrc_tg_cb_param_t param;
904     memset(&param, 0, sizeof(esp_avrc_tg_cb_param_t));
905     param.psth_cmd.key_code = p_remote_cmd->rc_id;
906     param.psth_cmd.key_state = p_remote_cmd->key_state;
907     btc_avrc_tg_cb_to_app(ESP_AVRC_TG_PASSTHROUGH_CMD_EVT, &param);
908 }
909 
910 /***************************************************************************
911  **
912  ** Function       btc_rc_handler
913  **
914  ** Description    RC event handler
915  **
916  ***************************************************************************/
btc_rc_handler(tBTA_AV_EVT event,tBTA_AV * p_data)917 void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
918 {
919     BTC_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
920     switch (event) {
921     case BTA_AV_RC_OPEN_EVT: {
922         BTC_TRACE_DEBUG("RC open, peer_features:%x", p_data->rc_open.peer_features);
923         handle_rc_connect( &(p_data->rc_open) );
924     } break;
925 
926     case BTA_AV_RC_CLOSE_EVT: {
927         handle_rc_disconnect( &(p_data->rc_close) );
928     } break;
929 
930 #if (AVRC_CTLR_INCLUDED == TRUE)
931     case BTA_AV_REMOTE_RSP_EVT: {
932         BTC_TRACE_DEBUG("RSP: rc_id:0x%x key_state:%d", p_data->remote_rsp.rc_id,
933                         p_data->remote_rsp.key_state);
934         handle_rc_passthrough_rsp( (&p_data->remote_rsp) );
935     }
936     break;
937 #endif
938     case BTA_AV_RC_FEAT_EVT: {
939         BTC_TRACE_DEBUG("Peer_features:%x", p_data->rc_feat.peer_features);
940         do {
941             // report connection state if connection state wasn't reported on BTA_AV_RC_OPEN_EVT
942             tBTA_AV_FEAT old_feats = btc_rc_cb.rc_features;
943             if ((p_data->rc_feat.peer_features & BTA_AV_FEAT_RCTG) &&
944                 !(old_feats & BTA_AV_FEAT_RCTG)) {
945                 esp_avrc_ct_cb_param_t param;
946                 memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
947                 param.conn_stat.connected = true;
948                 memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
949                 btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
950             }
951             if ((p_data->rc_feat.peer_features & BTA_AV_FEAT_RCCT) &&
952                 !(old_feats & BTA_AV_FEAT_RCCT)) {
953                 esp_avrc_tg_cb_param_t param;
954                 memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
955                 param.conn_stat.connected = true;
956                 memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t));
957                 btc_avrc_tg_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
958             }
959         } while (0);
960         btc_rc_cb.rc_features = p_data->rc_feat.peer_features;
961         btc_rc_cb.rc_ct_features = p_data->rc_feat.peer_ct_features;
962         btc_rc_cb.rc_tg_features = p_data->rc_feat.peer_tg_features;
963         handle_rc_features();
964     }
965     break;
966 
967     case BTA_AV_META_MSG_EVT: {
968         handle_rc_metamsg_cmd(&(p_data->meta_msg));
969     }
970     break;
971     case BTA_AV_REMOTE_CMD_EVT: {
972         BTC_TRACE_DEBUG("rc_id:0x%x key_state:%d", p_data->remote_cmd.rc_id,
973                         p_data->remote_cmd.key_state);
974         handle_rc_passthrough_cmd(&p_data->remote_cmd);
975     }
976     break;
977     default:
978         BTC_TRACE_DEBUG("Unhandled RC event : 0x%x", event);
979     }
980 }
981 
982 /***************************************************************************
983  **
984  ** Function       btc_rc_get_connected_peer
985  **
986  ** Description    Fetches the connected headset's BD_ADDR if any
987  **
988  ***************************************************************************/
btc_rc_get_connected_peer(BD_ADDR peer_addr)989 BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr)
990 {
991     if (btc_rc_cb.rc_connected == TRUE) {
992         bdcpy(peer_addr, btc_rc_cb.rc_addr);
993         return TRUE;
994     }
995     return FALSE;
996 }
997 
998 /************************************************************************************
999 **  AVRCP API Functions
1000 ************************************************************************************/
1001 
1002 /*******************************************************************************
1003 **
1004 ** Function         btc_avrc_ct_init
1005 **
1006 ** Description      Initializes the AVRC Controller interface
1007 **
1008 ** Returns          esp_err_t
1009 **
1010 *******************************************************************************/
btc_avrc_ct_init(void)1011 static void btc_avrc_ct_init(void)
1012 {
1013     BTC_TRACE_DEBUG("## %s ##", __FUNCTION__);
1014     if (s_rc_ct_init == BTC_RC_CT_INIT_MAGIC) {
1015         BTC_TRACE_WARNING("%s already initialized", __FUNCTION__);
1016         return;
1017     }
1018 
1019     /// initialize CT-specific resources
1020     s_rc_ct_init = BTC_RC_CT_INIT_MAGIC;
1021 
1022     /// initialize CT-TG shared resources
1023     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
1024         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
1025 
1026         if (!g_av_with_rc) {
1027             g_av_with_rc = true;
1028         }
1029 
1030         if (g_a2dp_on_init) {
1031             BTC_TRACE_WARNING("AVRC Controller is expected to be initialized in advance of A2DP !!!");
1032         }
1033     }
1034 }
1035 
1036 
1037 /***************************************************************************
1038 **
1039 ** Function         btc_avrc_ct_deinit
1040 **
1041 ** Description      Closes the AVRC Controller interface
1042 **
1043 ** Returns          void
1044 **
1045 ***************************************************************************/
btc_avrc_ct_deinit(void)1046 static void btc_avrc_ct_deinit(void)
1047 {
1048     BTC_TRACE_API("## %s ##", __FUNCTION__);
1049 
1050     if (g_a2dp_on_deinit) {
1051         BTC_TRACE_WARNING("A2DP already deinit, AVRC CT shuold deinit in advance of A2DP !!!");
1052     }
1053 
1054     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
1055         BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
1056         return;
1057     }
1058 
1059     /// deinit CT-specific resources
1060     s_rc_ct_init = 0;
1061 
1062     /// deinit CT-TG shared resources
1063     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
1064         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t));
1065         if (g_av_with_rc) {
1066             g_av_with_rc = false;
1067         }
1068     }
1069 
1070     BTC_TRACE_API("## %s ## completed", __FUNCTION__);
1071 }
1072 
btc_avrc_ct_send_set_player_value_cmd(uint8_t tl,uint8_t attr_id,uint8_t value_id)1073 static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id)
1074 {
1075     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1076 
1077 #if (AVRC_METADATA_INCLUDED == TRUE)
1078     CHECK_ESP_RC_CONNECTED;
1079 
1080     tAVRC_COMMAND avrc_cmd = {0};
1081     BT_HDR *p_msg = NULL;
1082     tAVRC_APP_SETTING values = {0};
1083 
1084     values.attr_id = attr_id;
1085     values.attr_val = value_id;
1086 
1087     avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
1088     avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
1089     avrc_cmd.set_app_val.num_val = 1;
1090     avrc_cmd.set_app_val.p_vals = &values;
1091     avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
1092 
1093     if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
1094         status = AVRC_BldCommand(&avrc_cmd, &p_msg);
1095         if (status == AVRC_STS_NO_ERROR) {
1096             BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, BTA_AV_CMD_CTRL, p_msg);
1097             status = BT_STATUS_SUCCESS;
1098         }
1099     } else {
1100         status = BT_STATUS_FAIL;
1101         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1102     }
1103 
1104 #else
1105     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1106 #endif
1107 
1108     return status;
1109 }
1110 
btc_avrc_ct_send_get_rn_caps_cmd(uint8_t tl)1111 static bt_status_t btc_avrc_ct_send_get_rn_caps_cmd(uint8_t tl)
1112 {
1113     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1114 
1115 #if (AVRC_METADATA_INCLUDED == TRUE)
1116     CHECK_ESP_RC_CONNECTED;
1117 
1118     tAVRC_COMMAND avrc_cmd = {0};
1119     BT_HDR *p_msg = NULL;
1120 
1121     avrc_cmd.get_caps.opcode = AVRC_OP_VENDOR;
1122     avrc_cmd.get_caps.status = AVRC_STS_NO_ERROR;
1123     avrc_cmd.get_caps.pdu = AVRC_PDU_GET_CAPABILITIES;
1124     avrc_cmd.get_caps.capability_id = AVRC_CAP_EVENTS_SUPPORTED;
1125 
1126     if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
1127         status = AVRC_BldCommand(&avrc_cmd, &p_msg);
1128         if (status == AVRC_STS_NO_ERROR) {
1129             BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg);
1130             status = BT_STATUS_SUCCESS;
1131         }
1132     } else {
1133         status = BT_STATUS_FAIL;
1134         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1135     }
1136 
1137 #else
1138     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1139 #endif
1140 
1141     return status;
1142 }
1143 
btc_avrc_ct_send_register_notification_cmd(uint8_t tl,uint8_t event_id,uint32_t event_parameter)1144 static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_t event_id, uint32_t event_parameter)
1145 {
1146     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1147 
1148 #if (AVRC_METADATA_INCLUDED == TRUE)
1149     CHECK_ESP_RC_CONNECTED;
1150 
1151     tAVRC_COMMAND avrc_cmd = {0};
1152     BT_HDR *p_msg = NULL;
1153 
1154     avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
1155     avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
1156     avrc_cmd.reg_notif.event_id = event_id;
1157     avrc_cmd.reg_notif.param = event_parameter;
1158     avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1159 
1160     if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
1161         status = AVRC_BldCommand(&avrc_cmd, &p_msg);
1162         if (status == AVRC_STS_NO_ERROR) {
1163             BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_NOTIF, p_msg);
1164             status = BT_STATUS_SUCCESS;
1165         }
1166     } else {
1167         status = BT_STATUS_FAIL;
1168         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1169     }
1170 
1171 #else
1172     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1173 #endif
1174 
1175     return status;
1176 }
1177 
btc_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl,uint8_t volume)1178 static bt_status_t btc_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl, uint8_t volume)
1179 {
1180     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1181 
1182 #if (AVRC_METADATA_INCLUDED == TRUE)
1183     CHECK_ESP_RC_CONNECTED;
1184 
1185     tAVRC_COMMAND avrc_cmd = {0};
1186     BT_HDR *p_msg = NULL;
1187 
1188     avrc_cmd.volume.opcode = AVRC_OP_VENDOR;
1189     avrc_cmd.volume.status = AVRC_STS_NO_ERROR;
1190     avrc_cmd.volume.volume = volume;
1191     avrc_cmd.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
1192 
1193     if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
1194         status = AVRC_BldCommand(&avrc_cmd, &p_msg);
1195         if (status == AVRC_STS_NO_ERROR) {
1196             BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_CTRL, p_msg);
1197             status = BT_STATUS_SUCCESS;
1198         }
1199     } else {
1200         status = BT_STATUS_FAIL;
1201         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1202     }
1203 
1204 #else
1205     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1206 #endif
1207 
1208     return status;
1209 }
1210 
btc_avrc_ct_send_metadata_cmd(uint8_t tl,uint8_t attr_mask)1211 static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask)
1212 {
1213     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1214 
1215 #if (AVRC_METADATA_INCLUDED == TRUE)
1216     CHECK_ESP_RC_CONNECTED;
1217     uint32_t index = 0;
1218 
1219     tAVRC_COMMAND avrc_cmd = {0};
1220     BT_HDR *p_msg = NULL;
1221 
1222     avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
1223     avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
1224     avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
1225 
1226     for (int count = 0; count < AVRC_MAX_ELEM_ATTR_SIZE; count++) {
1227         if ((attr_mask & (1 << count)) > 0) {
1228             avrc_cmd.get_elem_attrs.attrs[index] = count + 1;
1229             index++;
1230         }
1231     }
1232 
1233     avrc_cmd.get_elem_attrs.num_attr = index;
1234 
1235     if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
1236         status = AVRC_BldCommand(&avrc_cmd, &p_msg);
1237         if (status == AVRC_STS_NO_ERROR) {
1238             BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg);
1239             status = BT_STATUS_SUCCESS;
1240         }
1241     } else {
1242         status = BT_STATUS_FAIL;
1243         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1244     }
1245 
1246 #else
1247     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1248 #endif
1249 
1250     return status;
1251 }
1252 
btc_avrc_ct_send_passthrough_cmd(uint8_t tl,uint8_t key_code,uint8_t key_state)1253 static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state)
1254 {
1255     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
1256 
1257 #if (AVRC_CTLR_INCLUDED == TRUE)
1258     CHECK_ESP_RC_CONNECTED;
1259     BTC_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
1260                     key_code, key_state);
1261     if (btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG) {
1262         BTA_AvRemoteCmd(btc_rc_cb.rc_handle, tl,
1263                         (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
1264         status =  BT_STATUS_SUCCESS;
1265         BTC_TRACE_API("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
1266     } else {
1267         status = BT_STATUS_FAIL;
1268         BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
1269     }
1270 #else
1271     BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
1272 #endif
1273 
1274     return status;
1275 }
1276 
1277 
1278 /*******************************************************************************
1279 **
1280 ** Function         btc_avrc_tg_init
1281 **
1282 ** Description      Initializes the AVRC Target interface
1283 **
1284 ** Returns          esp_err_t
1285 **
1286 *******************************************************************************/
btc_avrc_tg_init(void)1287 static void btc_avrc_tg_init(void)
1288 {
1289     BTC_TRACE_DEBUG("## %s ##", __FUNCTION__);
1290     if (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) {
1291         BTC_TRACE_WARNING("%s already initialized", __FUNCTION__);
1292         return;
1293     }
1294 
1295     /// initialize TG-specific resources
1296     memcpy(s_psth_supported_cmd, cs_psth_dft_supported_cmd, sizeof(s_psth_supported_cmd));
1297     s_rn_supported_evt = cs_rn_dft_supported_evt;
1298 
1299     /// initialize CT-TG shared resources
1300     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
1301         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
1302 
1303         if (!g_av_with_rc) {
1304             g_av_with_rc = true;
1305         }
1306 
1307         if (g_a2dp_on_init) {
1308             BTC_TRACE_WARNING("AVRC Taget is expected to be initialized in advance of A2DP !!!");
1309         }
1310     }
1311 
1312     s_rc_tg_init = BTC_RC_TG_INIT_MAGIC;
1313 }
1314 
1315 
1316 /***************************************************************************
1317 **
1318 ** Function         btc_avrc_tg_deinit
1319 **
1320 ** Description      Closes the AVRC Target interface
1321 **
1322 ** Returns          void
1323 **
1324 ***************************************************************************/
btc_avrc_tg_deinit(void)1325 static void btc_avrc_tg_deinit(void)
1326 {
1327     BTC_TRACE_API("## %s ##", __FUNCTION__);
1328 
1329     if (g_a2dp_on_deinit) {
1330         BTC_TRACE_WARNING("A2DP already deinit, AVRC TG shuold deinit in advance of A2DP !!!");
1331     }
1332 
1333     if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
1334         BTC_TRACE_WARNING("%s not initialized", __FUNCTION__);
1335         return;
1336     }
1337 
1338     /// deinit TG-specific resources
1339     memset(s_psth_supported_cmd, 0, sizeof(s_psth_supported_cmd));
1340     s_rn_supported_evt = 0;
1341     s_rc_tg_init = 0;
1342 
1343     /// deinit CT-TG shared resources
1344     if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
1345         memset (&btc_rc_cb, 0, sizeof(btc_rc_cb));
1346         if (g_av_with_rc) {
1347             g_av_with_rc = false;
1348         }
1349     }
1350 
1351     BTC_TRACE_API("## %s ## completed", __FUNCTION__);
1352 }
1353 
btc_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id,esp_avrc_rn_rsp_t rsp,const esp_avrc_rn_param_t * param)1354 static void btc_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp, const esp_avrc_rn_param_t *param)
1355 {
1356     tAVRC_RESPONSE avrc_rsp;
1357     if (! btc_avrc_tg_connected_p()) {
1358         BTC_TRACE_WARNING("%s, RC unconnected, operation fail, event_id 0x%x", __FUNCTION__, event_id);
1359         return;
1360     }
1361 
1362     if (btc_rc_cb.rc_ntf[event_id - 1].registered == FALSE) {
1363         BTC_TRACE_ERROR("Event id not registered: event_id = %x", event_id);
1364         return;
1365     }
1366     memset(&(avrc_rsp.reg_notif), 0, sizeof(tAVRC_REG_NOTIF_RSP));
1367     avrc_rsp.reg_notif.event_id = event_id;
1368 
1369     switch (event_id) {
1370     case ESP_AVRC_RN_VOLUME_CHANGE:
1371         avrc_rsp.reg_notif.param.volume = param->volume;
1372         break;
1373     // todo: implement other event notifications
1374     default:
1375         BTC_TRACE_WARNING("%s : Unhandled event ID : 0x%x", __FUNCTION__, event_id);
1376         return;
1377     }
1378 
1379     avrc_rsp.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
1380     avrc_rsp.reg_notif.opcode = opcode_from_pdu(AVRC_PDU_REGISTER_NOTIFICATION);
1381     avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
1382 
1383     /* Send the response. */
1384     send_metamsg_rsp(btc_rc_cb.rc_handle, btc_rc_cb.rc_ntf[event_id - 1].label,
1385                      ((rsp == ESP_AVRC_RN_RSP_INTERIM) ? AVRC_CMD_NOTIF : AVRC_RSP_CHANGED), &avrc_rsp);
1386     return;
1387 }
1388 
btc_avrc_ct_call_handler(btc_msg_t * msg)1389 void btc_avrc_ct_call_handler(btc_msg_t *msg)
1390 {
1391     btc_avrc_args_t *arg = (btc_avrc_args_t *)(msg->arg);
1392     switch (msg->act) {
1393     case BTC_AVRC_CT_API_INIT_EVT: {
1394         btc_avrc_ct_init();
1395         // todo: callback to application
1396         break;
1397     }
1398     case BTC_AVRC_CT_API_DEINIT_EVT: {
1399         btc_avrc_ct_deinit();
1400         // todo: callback to application
1401         break;
1402     }
1403     case BTC_AVRC_CTRL_API_SND_PTCMD_EVT: {
1404         btc_avrc_ct_send_passthrough_cmd(arg->pt_cmd.tl, arg->pt_cmd.key_code, arg->pt_cmd.key_state);
1405         // todo: callback to application
1406         break;
1407     }
1408     case BTC_AVRC_STATUS_API_SND_META_EVT: {
1409         btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask);
1410         break;
1411     }
1412     case BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT: {
1413         btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl);
1414         break;
1415     }
1416     case BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT: {
1417         btc_avrc_ct_send_register_notification_cmd(arg->rn_cmd.tl, arg->rn_cmd.event_id, arg->rn_cmd.event_parameter);
1418         break;
1419     }
1420     case BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT: {
1421         btc_avrc_ct_send_set_player_value_cmd(arg->ps_cmd.tl, arg->ps_cmd.attr_id, arg->ps_cmd.value_id);
1422         break;
1423     }
1424     case BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT: {
1425         btc_avrc_ct_send_set_absolute_volume_cmd(arg->set_abs_vol_cmd.tl, arg->set_abs_vol_cmd.volume);
1426         break;
1427     }
1428     default:
1429         BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
1430     }
1431 }
1432 
btc_avrc_tg_call_handler(btc_msg_t * msg)1433 void btc_avrc_tg_call_handler(btc_msg_t *msg)
1434 {
1435     btc_avrc_tg_args_t *arg = (btc_avrc_tg_args_t *)(msg->arg);
1436     switch (msg->act) {
1437     case BTC_AVRC_TG_API_INIT_EVT: {
1438         btc_avrc_tg_init();
1439         break;
1440     }
1441     case BTC_AVRC_TG_API_DEINIT_EVT: {
1442         btc_avrc_tg_deinit();
1443         break;
1444     }
1445     case BTC_AVRC_TG_API_SET_RN_SUPPORTED_EVT: {
1446         btc_avrc_tg_set_rn_supported_evt(arg->set_rn_evt);
1447         break;
1448     }
1449     case BTC_AVRC_TG_API_SET_PSTH_SUPPORTED_CMD_EVT: {
1450         btc_avrc_tg_set_supported_command(arg->set_psth_cmd);
1451         break;
1452     }
1453     case BTC_AVRC_TG_API_SEND_RN_RSP_EVT: {
1454         btc_avrc_tg_send_rn_rsp(arg->rn_rsp.event_id, arg->rn_rsp.rsp,
1455                                 &arg->rn_rsp.param);
1456         break;
1457     }
1458     default:
1459         BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
1460     }
1461 
1462     btc_avrc_tg_arg_deep_free(msg);
1463 }
1464 
1465 #endif /* #if BTC_AV_INCLUDED */
1466