2021-11-24 00:21:13 -05:00
|
|
|
/*
|
2021-12-23 08:05:18 -05:00
|
|
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
2021-11-24 00:21:13 -05:00
|
|
|
*
|
2021-12-06 01:59:55 -05:00
|
|
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
2021-11-24 00:21:13 -05:00
|
|
|
*/
|
2017-04-12 04:42:14 -04:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
|
#include "freertos/task.h"
|
|
|
|
#include "nvs.h"
|
|
|
|
#include "nvs_flash.h"
|
|
|
|
#include "esp_system.h"
|
|
|
|
#include "esp_log.h"
|
|
|
|
|
2017-12-07 08:48:27 -05:00
|
|
|
#include "esp_bt.h"
|
2017-04-12 04:42:14 -04:00
|
|
|
#include "bt_app_core.h"
|
|
|
|
#include "bt_app_av.h"
|
|
|
|
#include "esp_bt_main.h"
|
|
|
|
#include "esp_bt_device.h"
|
|
|
|
#include "esp_gap_bt_api.h"
|
|
|
|
#include "esp_a2dp_api.h"
|
|
|
|
#include "esp_avrc_api.h"
|
2017-10-16 03:19:29 -04:00
|
|
|
#include "driver/i2s.h"
|
2017-04-12 04:42:14 -04:00
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
/* device name */
|
|
|
|
#define LOCAL_DEVICE_NAME "ESP_SPEAKER"
|
|
|
|
|
|
|
|
/* event for stack up */
|
2017-04-12 04:42:14 -04:00
|
|
|
enum {
|
|
|
|
BT_APP_EVT_STACK_UP = 0,
|
|
|
|
};
|
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
/********************************
|
|
|
|
* STATIC FUNCTION DECLARATIONS
|
|
|
|
*******************************/
|
|
|
|
|
|
|
|
/* GAP callback function */
|
|
|
|
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param);
|
2017-04-12 04:42:14 -04:00
|
|
|
/* handler for bluetooth stack enabled events */
|
|
|
|
static void bt_av_hdl_stack_evt(uint16_t event, void *p_param);
|
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
/*******************************
|
|
|
|
* STATIC FUNCTION DEFINITIONS
|
|
|
|
******************************/
|
2017-04-12 04:42:14 -04:00
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
2018-07-09 23:18:52 -04:00
|
|
|
{
|
|
|
|
switch (event) {
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when authentication completed, this event comes */
|
2018-09-04 09:11:03 -04:00
|
|
|
case ESP_BT_GAP_AUTH_CMPL_EVT: {
|
2018-07-09 23:18:52 -04:00
|
|
|
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
|
|
|
|
ESP_LOGI(BT_AV_TAG, "authentication success: %s", param->auth_cmpl.device_name);
|
|
|
|
esp_log_buffer_hex(BT_AV_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN);
|
|
|
|
} else {
|
2021-12-23 08:05:18 -05:00
|
|
|
ESP_LOGE(BT_AV_TAG, "authentication failed, status: %d", param->auth_cmpl.stat);
|
2018-07-09 23:18:52 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-12-07 01:19:47 -05:00
|
|
|
|
|
|
|
#if (CONFIG_BT_SSP_ENABLED == true)
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when Security Simple Pairing user confirmation requested, this event comes */
|
2018-07-09 23:18:52 -04:00
|
|
|
case ESP_BT_GAP_CFM_REQ_EVT:
|
|
|
|
ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
|
|
|
|
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
|
|
|
|
break;
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when Security Simple Pairing passkey notified, this event comes */
|
2018-07-09 23:18:52 -04:00
|
|
|
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
2021-12-23 08:05:18 -05:00
|
|
|
ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey: %d", param->key_notif.passkey);
|
2018-07-09 23:18:52 -04:00
|
|
|
break;
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when Security Simple Pairing passkey requested, this event comes */
|
2018-07-09 23:18:52 -04:00
|
|
|
case ESP_BT_GAP_KEY_REQ_EVT:
|
|
|
|
ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
|
|
|
break;
|
2018-12-07 01:19:47 -05:00
|
|
|
#endif
|
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when GAP mode changed, this event comes */
|
2020-07-21 06:11:11 -04:00
|
|
|
case ESP_BT_GAP_MODE_CHG_EVT:
|
2021-12-23 08:05:18 -05:00
|
|
|
ESP_LOGI(BT_AV_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode: %d", param->mode_chg.mode);
|
2020-07-21 06:11:11 -04:00
|
|
|
break;
|
2021-12-23 08:05:18 -05:00
|
|
|
/* others */
|
2018-07-09 23:18:52 -04:00
|
|
|
default: {
|
|
|
|
ESP_LOGI(BT_AV_TAG, "event: %d", event);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-23 08:05:18 -05:00
|
|
|
|
2017-04-12 04:42:14 -04:00
|
|
|
static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
|
|
|
|
{
|
2021-12-23 08:05:18 -05:00
|
|
|
ESP_LOGD(BT_AV_TAG, "%s event: %d", __func__, event);
|
|
|
|
|
2017-04-12 04:42:14 -04:00
|
|
|
switch (event) {
|
2021-12-23 08:05:18 -05:00
|
|
|
/* when do the stack up, this event comes */
|
2017-04-12 04:42:14 -04:00
|
|
|
case BT_APP_EVT_STACK_UP: {
|
2021-12-23 08:05:18 -05:00
|
|
|
esp_bt_dev_set_device_name(LOCAL_DEVICE_NAME);
|
2018-07-09 23:18:52 -04:00
|
|
|
esp_bt_gap_register_callback(bt_app_gap_cb);
|
2017-04-12 04:42:14 -04:00
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
assert(esp_avrc_ct_init() == ESP_OK);
|
2017-04-12 04:42:14 -04:00
|
|
|
esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
|
2021-12-23 08:05:18 -05:00
|
|
|
assert(esp_avrc_tg_init() == ESP_OK);
|
component/bt: implement AVRCP Target APIs
1. Add more notification events to the enum according to the event list in AVRCP specification.
2. Add API and callback events for basic AVRCP target functionalities to do init, deinit, callback-registration, connection status indication.
3. Implement API to set/get supported PASSTHROUGH command on local AVRCP TG, implement callback events for remote passthrough command indication.
4. Implement API to set/get supported notification eventIDs on local AVRCP TG, implement API to send event notifications to remote CT. \
Currently supported event in TG only includes ESP_AVRC_RN_VOLUME_CHANGE(0xd), which can be extended in later commits.
5. Implement callback events for SetAbsoluteVolume command indication on TG.
6. Add limitation of event_ids supported in RegisterNotification command in CT. The supported event_ids include: \
ESP_AVRC_RN_PLAY_STATUS_CHANGE(0x1), ESP_AVRC_RN_TRACK_CHANGE(0x2), ESP_AVRC_RN_PLAY_POS_CHANGE(0x5), ESP_AVRC_RN_VOLUME_CHANGE(0xd).
7. Add feature bit mask in parameter of callback event ESP_AVRC_CT_REMOTE_FEATURES_EVT for peer feature information got from SDP.
8. Add API and callback event to AVRCP CT to retrieve remote TG's supported notification event capabilities.
9. Modify data type for parameter of callback event ESP_AVRC_CT_CHANGE_NOTIFY_EVT.
10. Change AVRCP version from 1.3 to 1.4 for compatibility cause in using AbsoluteVolume feature.
11. Modify local AVRCP device to be category 1 as CT and category 2 as TG that applies to bluetooth headphones or speakers.
12. Update the use of AVRCP APIs and events in the two examples: a2dp_sink and a2dp_gatts_coex, which include the demo of volume control and notification.
2018-12-21 04:04:21 -05:00
|
|
|
esp_avrc_tg_register_callback(bt_app_rc_tg_cb);
|
|
|
|
|
|
|
|
esp_avrc_rn_evt_cap_mask_t evt_set = {0};
|
|
|
|
esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE);
|
|
|
|
assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK);
|
|
|
|
|
2021-12-23 08:05:18 -05:00
|
|
|
assert(esp_a2d_sink_init() == ESP_OK);
|
component/bt: implement AVRCP Target APIs
1. Add more notification events to the enum according to the event list in AVRCP specification.
2. Add API and callback events for basic AVRCP target functionalities to do init, deinit, callback-registration, connection status indication.
3. Implement API to set/get supported PASSTHROUGH command on local AVRCP TG, implement callback events for remote passthrough command indication.
4. Implement API to set/get supported notification eventIDs on local AVRCP TG, implement API to send event notifications to remote CT. \
Currently supported event in TG only includes ESP_AVRC_RN_VOLUME_CHANGE(0xd), which can be extended in later commits.
5. Implement callback events for SetAbsoluteVolume command indication on TG.
6. Add limitation of event_ids supported in RegisterNotification command in CT. The supported event_ids include: \
ESP_AVRC_RN_PLAY_STATUS_CHANGE(0x1), ESP_AVRC_RN_TRACK_CHANGE(0x2), ESP_AVRC_RN_PLAY_POS_CHANGE(0x5), ESP_AVRC_RN_VOLUME_CHANGE(0xd).
7. Add feature bit mask in parameter of callback event ESP_AVRC_CT_REMOTE_FEATURES_EVT for peer feature information got from SDP.
8. Add API and callback event to AVRCP CT to retrieve remote TG's supported notification event capabilities.
9. Modify data type for parameter of callback event ESP_AVRC_CT_CHANGE_NOTIFY_EVT.
10. Change AVRCP version from 1.3 to 1.4 for compatibility cause in using AbsoluteVolume feature.
11. Modify local AVRCP device to be category 1 as CT and category 2 as TG that applies to bluetooth headphones or speakers.
12. Update the use of AVRCP APIs and events in the two examples: a2dp_sink and a2dp_gatts_coex, which include the demo of volume control and notification.
2018-12-21 04:04:21 -05:00
|
|
|
esp_a2d_register_callback(&bt_app_a2d_cb);
|
|
|
|
esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
|
2017-04-12 04:42:14 -04:00
|
|
|
|
|
|
|
/* set discoverable and connectable mode, wait to be connected */
|
2018-04-09 06:30:48 -04:00
|
|
|
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
2017-04-12 04:42:14 -04:00
|
|
|
break;
|
|
|
|
}
|
2021-12-23 08:05:18 -05:00
|
|
|
/* others */
|
2017-04-12 04:42:14 -04:00
|
|
|
default:
|
2021-12-23 08:05:18 -05:00
|
|
|
ESP_LOGE(BT_AV_TAG, "%s unhandled event: %d", __func__, event);
|
2017-04-12 04:42:14 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-12-23 08:05:18 -05:00
|
|
|
|
|
|
|
/*******************************
|
|
|
|
* MAIN ENTRY POINT
|
|
|
|
******************************/
|
|
|
|
|
|
|
|
void app_main(void)
|
|
|
|
{
|
|
|
|
/* initialize NVS — it is used to store PHY calibration data */
|
|
|
|
esp_err_t err = nvs_flash_init();
|
|
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
|
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
|
|
err = nvs_flash_init();
|
|
|
|
}
|
|
|
|
ESP_ERROR_CHECK(err);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This example only uses the functions of Classical Bluetooth.
|
|
|
|
* So release the controller memory for Bluetooth Low Energy.
|
|
|
|
*/
|
|
|
|
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE));
|
|
|
|
|
|
|
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
|
|
|
if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
|
|
|
ESP_LOGE(BT_AV_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
|
|
|
|
ESP_LOGE(BT_AV_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((err = esp_bluedroid_init()) != ESP_OK) {
|
|
|
|
ESP_LOGE(BT_AV_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((err = esp_bluedroid_enable()) != ESP_OK) {
|
|
|
|
ESP_LOGE(BT_AV_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* I2S configuration parameters */
|
|
|
|
i2s_config_t i2s_config = {
|
|
|
|
#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
|
|
|
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
|
|
|
#else
|
|
|
|
.mode = I2S_MODE_MASTER | I2S_MODE_TX, /* only TX */
|
|
|
|
#endif
|
|
|
|
.sample_rate = 44100,
|
|
|
|
.bits_per_sample = 16,
|
|
|
|
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, /* 2-channels */
|
|
|
|
.communication_format = I2S_COMM_FORMAT_STAND_MSB,
|
|
|
|
.dma_buf_count = 6,
|
|
|
|
.dma_buf_len = 60,
|
|
|
|
.intr_alloc_flags = 0, /* default interrupt priority */
|
|
|
|
.tx_desc_auto_clear = true /* auto clear tx descriptor on underflow */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* enable I2S */
|
|
|
|
i2s_driver_install(0, &i2s_config, 0, NULL);
|
|
|
|
#ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
|
|
|
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
|
|
|
i2s_set_pin(0, NULL);
|
|
|
|
#else
|
|
|
|
i2s_pin_config_t pin_config = {
|
|
|
|
.bck_io_num = CONFIG_EXAMPLE_I2S_BCK_PIN,
|
|
|
|
.ws_io_num = CONFIG_EXAMPLE_I2S_LRCK_PIN,
|
|
|
|
.data_out_num = CONFIG_EXAMPLE_I2S_DATA_PIN,
|
|
|
|
.data_in_num = -1 /* not used */
|
|
|
|
};
|
|
|
|
i2s_set_pin(0, &pin_config);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (CONFIG_BT_SSP_ENABLED == true)
|
|
|
|
/* set default parameters for Secure Simple Pairing */
|
|
|
|
esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
|
|
|
|
esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
|
|
|
|
esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* set default parameters for Legacy Pairing (use fixed pin code 1234) */
|
|
|
|
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_FIXED;
|
|
|
|
esp_bt_pin_code_t pin_code;
|
|
|
|
pin_code[0] = '1';
|
|
|
|
pin_code[1] = '2';
|
|
|
|
pin_code[2] = '3';
|
|
|
|
pin_code[3] = '4';
|
|
|
|
esp_bt_gap_set_pin(pin_type, 4, pin_code);
|
|
|
|
|
|
|
|
bt_app_task_start_up();
|
|
|
|
/* bluetooth device name, connection mode and profile set up */
|
|
|
|
bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL);
|
|
|
|
}
|