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