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