1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "common/bt_target.h"
8 #include <string.h>
9 #include "esp_err.h"
10 #include "esp_avrc_api.h"
11 #include "esp_bt_main.h"
12 #include "btc/btc_manage.h"
13 #include "btc_avrc.h"
14
15 #if BTC_AV_INCLUDED
16
esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback)17 esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback)
18 {
19 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
20 return ESP_ERR_INVALID_STATE;
21 }
22
23 if (callback == NULL) {
24 return ESP_ERR_INVALID_ARG;
25 }
26
27 btc_profile_cb_set(BTC_PID_AVRC_CT, callback);
28 return ESP_OK;
29 }
30
esp_avrc_ct_init(void)31 esp_err_t esp_avrc_ct_init(void)
32 {
33 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
34 return ESP_ERR_INVALID_STATE;
35 }
36
37 btc_msg_t msg;
38
39 msg.sig = BTC_SIG_API_CALL;
40 msg.pid = BTC_PID_AVRC_CT;
41 msg.act = BTC_AVRC_CT_API_INIT_EVT;
42
43 /* Switch to BTC context */
44 bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL);
45 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
46 }
47
esp_avrc_ct_deinit(void)48 esp_err_t esp_avrc_ct_deinit(void)
49 {
50 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
51 return ESP_ERR_INVALID_STATE;
52 }
53
54 btc_msg_t msg;
55
56 msg.sig = BTC_SIG_API_CALL;
57 msg.pid = BTC_PID_AVRC_CT;
58 msg.act = BTC_AVRC_CT_API_DEINIT_EVT;
59
60 /* Switch to BTC context */
61 bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL);
62 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
63 }
64
esp_avrc_ct_send_set_player_value_cmd(uint8_t tl,uint8_t attr_id,uint8_t value_id)65 esp_err_t esp_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id)
66 {
67 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
68 return ESP_ERR_INVALID_STATE;
69 }
70
71 if (tl > ESP_AVRC_TRANS_LABEL_MAX || attr_id > ESP_AVRC_PS_MAX_ATTR - 1) {
72 return ESP_ERR_INVALID_ARG;
73 }
74
75 btc_msg_t msg;
76 msg.sig = BTC_SIG_API_CALL;
77 msg.pid = BTC_PID_AVRC_CT;
78 msg.act = BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT;
79
80 btc_avrc_args_t arg;
81 memset(&arg, 0, sizeof(btc_avrc_args_t));
82
83 arg.ps_cmd.tl = tl;
84 arg.ps_cmd.attr_id = attr_id;
85 arg.ps_cmd.value_id = value_id;
86
87 /* Switch to BTC context */
88 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
89 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
90 }
91
esp_avrc_ct_send_get_rn_capabilities_cmd(uint8_t tl)92 esp_err_t esp_avrc_ct_send_get_rn_capabilities_cmd(uint8_t tl)
93 {
94 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
95 return ESP_ERR_INVALID_STATE;
96 }
97
98 if (tl > ESP_AVRC_TRANS_LABEL_MAX) {
99 return ESP_ERR_INVALID_ARG;
100 }
101
102 btc_msg_t msg;
103 msg.sig = BTC_SIG_API_CALL;
104 msg.pid = BTC_PID_AVRC_CT;
105 msg.act = BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT;
106
107 btc_avrc_args_t arg;
108 memset(&arg, 0, sizeof(btc_avrc_args_t));
109
110 arg.get_caps_cmd.tl = tl;
111
112 /* Switch to BTC context */
113 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
114 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
115 }
116
esp_avrc_ct_send_register_notification_cmd(uint8_t tl,uint8_t event_id,uint32_t event_parameter)117 esp_err_t esp_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_t event_id, uint32_t event_parameter)
118 {
119 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
120 return ESP_ERR_INVALID_STATE;
121 }
122
123 if (tl > ESP_AVRC_TRANS_LABEL_MAX || event_id > ESP_AVRC_RN_MAX_EVT - 1) {
124 return ESP_ERR_INVALID_ARG;
125 }
126
127 if (!btc_avrc_ct_rn_evt_supported(event_id)) {
128 return ESP_ERR_NOT_SUPPORTED;
129 }
130
131 btc_msg_t msg;
132 msg.sig = BTC_SIG_API_CALL;
133 msg.pid = BTC_PID_AVRC_CT;
134 msg.act = BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT;
135
136 btc_avrc_args_t arg;
137 memset(&arg, 0, sizeof(btc_avrc_args_t));
138
139 arg.rn_cmd.tl = tl;
140 arg.rn_cmd.event_id = event_id;
141 arg.rn_cmd.event_parameter = event_parameter;
142
143 /* Switch to BTC context */
144 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
145 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
146 }
147
esp_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl,uint8_t volume)148 esp_err_t esp_avrc_ct_send_set_absolute_volume_cmd(uint8_t tl, uint8_t volume)
149 {
150 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
151 return ESP_ERR_INVALID_STATE;
152 }
153
154 if (tl > ESP_AVRC_TRANS_LABEL_MAX) {
155 return ESP_ERR_INVALID_ARG;
156 }
157
158 if (volume > BTC_AVRC_MAX_VOLUME) {
159 return ESP_ERR_INVALID_ARG;
160 }
161
162 if (!btc_avrc_ct_rn_evt_supported(ESP_AVRC_RN_VOLUME_CHANGE)) {
163 return ESP_ERR_NOT_SUPPORTED;
164 }
165
166 btc_msg_t msg;
167 msg.sig = BTC_SIG_API_CALL;
168 msg.pid = BTC_PID_AVRC_CT;
169 msg.act = BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT;
170
171 btc_avrc_args_t arg;
172 memset(&arg, 0, sizeof(btc_avrc_args_t));
173
174 arg.set_abs_vol_cmd.tl = tl;
175 arg.set_abs_vol_cmd.volume = volume;
176
177 /* Switch to BTC context */
178 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
179 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
180 }
181
esp_avrc_ct_send_metadata_cmd(uint8_t tl,uint8_t attr_mask)182 esp_err_t esp_avrc_ct_send_metadata_cmd(uint8_t tl, uint8_t attr_mask)
183 {
184 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
185 return ESP_ERR_INVALID_STATE;
186 }
187
188 if (tl > ESP_AVRC_TRANS_LABEL_MAX) {
189 return ESP_ERR_INVALID_ARG;
190 }
191
192 btc_msg_t msg;
193 msg.sig = BTC_SIG_API_CALL;
194 msg.pid = BTC_PID_AVRC_CT;
195 msg.act = BTC_AVRC_STATUS_API_SND_META_EVT;
196
197 btc_avrc_args_t arg;
198 memset(&arg, 0, sizeof(btc_avrc_args_t));
199
200 arg.md_cmd.tl = tl;
201 arg.md_cmd.attr_mask = attr_mask;
202
203 /* Switch to BTC context */
204 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
205 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
206 }
207
esp_avrc_ct_send_passthrough_cmd(uint8_t tl,uint8_t key_code,uint8_t key_state)208 esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state)
209 {
210 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
211 return ESP_ERR_INVALID_STATE;
212 }
213
214 if (tl > ESP_AVRC_TRANS_LABEL_MAX || key_state > ESP_AVRC_PT_CMD_STATE_RELEASED) {
215 return ESP_ERR_INVALID_ARG;
216 }
217
218 btc_msg_t msg;
219 msg.sig = BTC_SIG_API_CALL;
220 msg.pid = BTC_PID_AVRC_CT;
221 msg.act = BTC_AVRC_CTRL_API_SND_PTCMD_EVT;
222
223 btc_avrc_args_t arg;
224 memset(&arg, 0, sizeof(btc_avrc_args_t));
225
226 arg.pt_cmd.tl = tl;
227 arg.pt_cmd.key_code = key_code;
228 arg.pt_cmd.key_state = key_state;
229
230 /* Switch to BTC context */
231 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
232 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
233 }
234
235 /*********************************************************************************************/
236 /** following is the API of AVRCP target role **/
237 /*********************************************************************************************/
238
esp_avrc_tg_register_callback(esp_avrc_tg_cb_t callback)239 esp_err_t esp_avrc_tg_register_callback(esp_avrc_tg_cb_t callback)
240 {
241 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
242 return ESP_ERR_INVALID_STATE;
243 }
244
245 if (callback == NULL) {
246 return ESP_ERR_INVALID_ARG;
247 }
248
249 btc_profile_cb_set(BTC_PID_AVRC_TG, callback);
250 return ESP_OK;
251 }
252
esp_avrc_tg_init(void)253 esp_err_t esp_avrc_tg_init(void)
254 {
255 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
256 return ESP_ERR_INVALID_STATE;
257 }
258
259 btc_msg_t msg;
260
261 msg.sig = BTC_SIG_API_CALL;
262 msg.pid = BTC_PID_AVRC_TG;
263 msg.act = BTC_AVRC_TG_API_INIT_EVT;
264
265 /* Switch to BTC context */
266 bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL);
267 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
268 }
269
esp_avrc_tg_deinit(void)270 esp_err_t esp_avrc_tg_deinit(void)
271 {
272 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
273 return ESP_ERR_INVALID_STATE;
274 }
275
276 btc_msg_t msg;
277
278 msg.sig = BTC_SIG_API_CALL;
279 msg.pid = BTC_PID_AVRC_TG;
280 msg.act = BTC_AVRC_TG_API_DEINIT_EVT;
281
282 /* Switch to BTC context */
283 bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL);
284 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
285 }
286
esp_avrc_psth_bit_mask_operation(esp_avrc_bit_mask_op_t op,esp_avrc_psth_bit_mask_t * psth,esp_avrc_pt_cmd_t cmd)287 bool esp_avrc_psth_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_psth_bit_mask_t *psth,
288 esp_avrc_pt_cmd_t cmd)
289 {
290 if (!psth ||
291 cmd > ESP_AVRC_PT_CMD_VENDOR) {
292 return false;
293 }
294
295 uint16_t *p = &psth->bits[(uint8_t)cmd >> 4];
296 uint16_t mask = (uint16_t)1 << ((uint8_t)cmd & 0x0F);
297 switch (op) {
298 case ESP_AVRC_BIT_MASK_OP_SET:
299 *p |= mask;
300 break;
301 case ESP_AVRC_BIT_MASK_OP_CLEAR:
302 *p &= ~mask;
303 break;
304 case ESP_AVRC_BIT_MASK_OP_TEST:
305 return (*p & mask);
306 default:
307 return false;
308 }
309
310 return true;
311 }
312
esp_avrc_tg_get_psth_cmd_filter(esp_avrc_psth_filter_t filter,esp_avrc_psth_bit_mask_t * cmd_set)313 esp_err_t esp_avrc_tg_get_psth_cmd_filter(esp_avrc_psth_filter_t filter, esp_avrc_psth_bit_mask_t *cmd_set)
314 {
315 if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
316 (! btc_avrc_tg_init_p())) {
317 return ESP_ERR_INVALID_STATE;
318 }
319 if (filter >= ESP_AVRC_PSTH_FILTER_SUPPORT_MAX ||
320 cmd_set == NULL) {
321 return ESP_ERR_INVALID_ARG;
322 }
323
324 if (filter == ESP_AVRC_PSTH_FILTER_ALLOWED_CMD) {
325 const uint16_t *allowed_cmd_set = btc_avrc_tg_get_allowed_command();
326 memcpy(cmd_set, allowed_cmd_set, sizeof(esp_avrc_psth_bit_mask_t));
327 } else if (filter == ESP_AVRC_PSTH_FILTER_SUPPORTED_CMD) {
328 const uint16_t *supported_cmd_set = btc_avrc_tg_get_supported_command();
329 memcpy(cmd_set, supported_cmd_set, sizeof(esp_avrc_psth_bit_mask_t));
330 } else {
331 }
332
333 return ESP_OK;
334 }
335
esp_avrc_tg_set_psth_cmd_filter(esp_avrc_psth_filter_t filter,const esp_avrc_psth_bit_mask_t * cmd_set)336 esp_err_t esp_avrc_tg_set_psth_cmd_filter(esp_avrc_psth_filter_t filter, const esp_avrc_psth_bit_mask_t *cmd_set)
337 {
338 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
339 return ESP_ERR_INVALID_STATE;
340 }
341 if (filter >= ESP_AVRC_PSTH_FILTER_SUPPORT_MAX ||
342 cmd_set == NULL) {
343 return ESP_ERR_INVALID_ARG;
344 }
345 if (filter == ESP_AVRC_PSTH_FILTER_ALLOWED_CMD) {
346 return ESP_ERR_NOT_SUPPORTED;
347 }
348 if (filter == ESP_AVRC_PSTH_FILTER_SUPPORTED_CMD) {
349 bool allowed = btc_avrc_tg_check_supported_command(cmd_set->bits);
350 if (!allowed) {
351 return ESP_ERR_NOT_SUPPORTED;
352 }
353 btc_msg_t msg;
354 msg.sig = BTC_SIG_API_CALL;
355 msg.pid = BTC_PID_AVRC_TG;
356 msg.act = BTC_AVRC_TG_API_SET_PSTH_SUPPORTED_CMD_EVT;
357
358 btc_avrc_tg_args_t arg;
359 memset(&arg, 0, sizeof(btc_avrc_tg_args_t));
360 arg.set_psth_cmd = (uint16_t *)cmd_set->bits;
361
362 /* Switch to BTC context */
363 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_tg_args_t),
364 btc_avrc_tg_arg_deep_copy, btc_avrc_tg_arg_deep_free);
365 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
366 } else {
367 return ESP_FAIL;
368 }
369 }
370
esp_avrc_tg_get_rn_evt_cap(esp_avrc_rn_evt_cap_t cap,esp_avrc_rn_evt_cap_mask_t * evt_set)371 esp_err_t esp_avrc_tg_get_rn_evt_cap(esp_avrc_rn_evt_cap_t cap, esp_avrc_rn_evt_cap_mask_t *evt_set)
372 {
373 if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
374 (! btc_avrc_tg_init_p())) {
375 return ESP_ERR_INVALID_STATE;
376 }
377 if (cap >= ESP_AVRC_RN_CAP_MAX ||
378 evt_set == NULL) {
379 return ESP_ERR_INVALID_ARG;
380 }
381
382 if (cap == ESP_AVRC_RN_CAP_ALLOWED_EVT) {
383 evt_set->bits = btc_avrc_tg_get_rn_allowed_evt();
384 } else if (cap == ESP_AVRC_RN_CAP_SUPPORTED_EVT) {
385 evt_set->bits = btc_avrc_tg_get_rn_supported_evt();
386 } else {
387 }
388
389 return ESP_OK;
390 }
391
esp_avrc_tg_set_rn_evt_cap(const esp_avrc_rn_evt_cap_mask_t * evt_set)392 esp_err_t esp_avrc_tg_set_rn_evt_cap(const esp_avrc_rn_evt_cap_mask_t *evt_set)
393 {
394 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
395 return ESP_ERR_INVALID_STATE;
396 }
397 if (evt_set == NULL) {
398 return ESP_ERR_INVALID_ARG;
399 }
400
401 bool allowed = btc_avrc_tg_check_rn_supported_evt(evt_set->bits);
402 if (!allowed) {
403 return ESP_ERR_NOT_SUPPORTED;
404 }
405
406 btc_msg_t msg;
407 msg.sig = BTC_SIG_API_CALL;
408 msg.pid = BTC_PID_AVRC_TG;
409 msg.act = BTC_AVRC_TG_API_SET_RN_SUPPORTED_EVT;
410
411 btc_avrc_tg_args_t arg;
412 memset(&arg, 0, sizeof(btc_avrc_tg_args_t));
413
414 arg.set_rn_evt = evt_set->bits;
415
416 /* Switch to BTC context */
417 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_tg_args_t), NULL, NULL);
418 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
419 }
420
esp_avrc_rn_evt_bit_mask_operation(esp_avrc_bit_mask_op_t op,esp_avrc_rn_evt_cap_mask_t * events,esp_avrc_rn_event_ids_t event_id)421 bool esp_avrc_rn_evt_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_rn_evt_cap_mask_t *events,
422 esp_avrc_rn_event_ids_t event_id)
423 {
424 if (!events ||
425 event_id >= ESP_AVRC_RN_MAX_EVT) {
426 return false;
427 }
428
429 uint16_t *p = &events->bits;
430 uint16_t mask = (uint16_t)1 << ((uint8_t)event_id & 0x0F);
431 switch (op) {
432 case ESP_AVRC_BIT_MASK_OP_SET:
433 *p |= mask;
434 break;
435 case ESP_AVRC_BIT_MASK_OP_CLEAR:
436 *p &= ~mask;
437 break;
438 case ESP_AVRC_BIT_MASK_OP_TEST:
439 return (*p & mask);
440 default:
441 return false;
442 }
443
444 return true;
445 }
446
esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id,esp_avrc_rn_rsp_t rsp,esp_avrc_rn_param_t * param)447 esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp,
448 esp_avrc_rn_param_t *param)
449 {
450 if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
451 (! btc_avrc_tg_connected_p())) {
452 return ESP_ERR_INVALID_STATE;
453 }
454
455 if ( ! btc_avrc_tg_rn_evt_supported((uint8_t)event_id)) {
456 return ESP_ERR_NOT_SUPPORTED;
457 }
458
459 btc_msg_t msg;
460 msg.sig = BTC_SIG_API_CALL;
461 msg.pid = BTC_PID_AVRC_TG;
462 msg.act = BTC_AVRC_TG_API_SEND_RN_RSP_EVT;
463
464 btc_avrc_tg_args_t arg;
465 memset(&arg, 0, sizeof(btc_avrc_tg_args_t));
466
467 arg.rn_rsp.event_id = event_id;
468 arg.rn_rsp.rsp = rsp;
469 memcpy(&arg.rn_rsp.param, param, sizeof(esp_avrc_rn_param_t));
470
471 /* Switch to BTC context */
472 bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_tg_args_t), NULL, NULL);
473 return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
474
475 }
476
477 #endif /* #if BTC_AV_INCLUDED */
478