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