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