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