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