mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-08 04:27:12 +03:00
BT source improvment, GPIO expander intr fix, SPI display improvments
This commit is contained in:
@@ -43,7 +43,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
|||||||
if (CSPin >= 0) {
|
if (CSPin >= 0) {
|
||||||
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false );
|
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false );
|
||||||
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false );
|
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false );
|
||||||
}
|
}
|
||||||
|
|
||||||
memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) );
|
memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) );
|
||||||
|
|
||||||
@@ -74,16 +74,23 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
|
static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
|
||||||
spi_transaction_t SPITransaction = { 0 };
|
spi_transaction_t SPITransaction = { };
|
||||||
|
|
||||||
NullCheck( SPIHandle, return false );
|
NullCheck( SPIHandle, return false );
|
||||||
NullCheck( Data, return false );
|
NullCheck( Data, return false );
|
||||||
|
|
||||||
if ( DataLength > 0 ) {
|
if ( DataLength > 0 ) {
|
||||||
gpio_set_level( DCPin, WriteMode );
|
gpio_set_level( DCPin, WriteMode );
|
||||||
|
|
||||||
SPITransaction.length = DataLength * 8;
|
SPITransaction.length = DataLength * 8;
|
||||||
SPITransaction.tx_buffer = Data;
|
|
||||||
|
if (DataLength <= 4) {
|
||||||
|
SPITransaction.flags = SPI_TRANS_USE_TXDATA;
|
||||||
|
SPITransaction.tx_data[0] = *Data++; SPITransaction.tx_data[1] = *Data++;
|
||||||
|
SPITransaction.tx_data[2] = *Data++; SPITransaction.tx_data[3] = *Data;
|
||||||
|
} else {
|
||||||
|
SPITransaction.tx_buffer = Data;
|
||||||
|
}
|
||||||
|
|
||||||
// only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
|
// only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
|
||||||
ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );
|
ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false );
|
||||||
|
|||||||
@@ -6,27 +6,27 @@
|
|||||||
CONDITIONS OF ANY KIND, either express or implied.
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bt_app_core.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "esp_system.h"
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/xtensa_api.h"
|
|
||||||
#include "freertos/FreeRTOSConfig.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "esp_bt.h"
|
||||||
|
#include "esp_bt_main.h"
|
||||||
|
#include "esp_gap_bt_api.h"
|
||||||
|
#include "bt_app_core.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
static const char * TAG = "btappcore";
|
static const char *TAG = "btappcore";
|
||||||
|
|
||||||
static void bt_app_task_handler(void *arg);
|
static void bt_app_task_handler(void *arg);
|
||||||
static bool bt_app_send_msg(bt_app_msg_t *msg);
|
static bool bt_app_send_msg(bt_app_msg_t *msg);
|
||||||
static void bt_app_work_dispatched(bt_app_msg_t *msg);
|
static void bt_app_work_dispatched(bt_app_msg_t *msg);
|
||||||
|
|
||||||
static xQueueHandle s_bt_app_task_queue = NULL;
|
static xQueueHandle s_bt_app_task_queue;
|
||||||
static xTaskHandle s_bt_app_task_handle = NULL;
|
static bool running;
|
||||||
|
|
||||||
bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback)
|
bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback)
|
||||||
{
|
{
|
||||||
@@ -77,9 +77,49 @@ static void bt_app_work_dispatched(bt_app_msg_t *msg)
|
|||||||
static void bt_app_task_handler(void *arg)
|
static void bt_app_task_handler(void *arg)
|
||||||
{
|
{
|
||||||
bt_app_msg_t msg;
|
bt_app_msg_t msg;
|
||||||
for (;;) {
|
esp_err_t err;
|
||||||
|
|
||||||
|
s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t));
|
||||||
|
|
||||||
|
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(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(err));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = esp_bluedroid_init()) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = esp_bluedroid_enable()) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(err));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bluetooth device name, connection mode and profile set up */
|
||||||
|
bt_app_work_dispatch((bt_av_hdl_stack_evt_t*) arg, BT_APP_EVT_STACK_UP, NULL, 0, NULL);
|
||||||
|
|
||||||
|
#if (CONFIG_BT_SSP_ENABLED)
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) {
|
if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) {
|
||||||
ESP_LOGV(TAG,"%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event);
|
ESP_LOGV(TAG,"%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event);
|
||||||
|
|
||||||
switch (msg.sig) {
|
switch (msg.sig) {
|
||||||
case BT_APP_SIG_WORK_DISPATCH:
|
case BT_APP_SIG_WORK_DISPATCH:
|
||||||
bt_app_work_dispatched(&msg);
|
bt_app_work_dispatched(&msg);
|
||||||
@@ -87,36 +127,46 @@ static void bt_app_task_handler(void *arg)
|
|||||||
default:
|
default:
|
||||||
ESP_LOGW(TAG,"%s, unhandled sig: %d", __func__, msg.sig);
|
ESP_LOGW(TAG,"%s, unhandled sig: %d", __func__, msg.sig);
|
||||||
break;
|
break;
|
||||||
} // switch (msg.sig)
|
}
|
||||||
|
|
||||||
if (msg.param) {
|
if (msg.param) {
|
||||||
free(msg.param);
|
free(msg.param);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGW(TAG,"No messaged received from queue.");
|
ESP_LOGW(TAG,"No messaged received from queue.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "bt_app_task shutting down");
|
||||||
|
|
||||||
|
if (esp_bluedroid_disable() != ESP_OK) goto exit;
|
||||||
|
// this disable has a sleep timer BTA_DISABLE_DELAY in bt_target.h and
|
||||||
|
// if we don't wait for it then disable crashes... don't know why
|
||||||
|
vTaskDelay(2*200 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "esp_bluedroid_disable called successfully");
|
||||||
|
if (esp_bluedroid_deinit() != ESP_OK) goto exit;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully");
|
||||||
|
if (esp_bt_controller_disable() != ESP_OK) goto exit;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "esp_bt_controller_disable called successfully");
|
||||||
|
if (esp_bt_controller_deinit() != ESP_OK) goto exit;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "bt stopped successfully");
|
||||||
|
|
||||||
|
exit:
|
||||||
|
vQueueDelete(s_bt_app_task_queue);
|
||||||
|
running = false;
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_app_task_start_up(void)
|
void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler)
|
||||||
{
|
{
|
||||||
|
xTaskCreate(bt_app_task_handler, "BtAppT", 4096, handler, configMAX_PRIORITIES - 3, NULL);
|
||||||
s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t));
|
|
||||||
assert(s_bt_app_task_queue!=NULL);
|
|
||||||
assert(xTaskCreate(bt_app_task_handler, "BtAppT", 4096, NULL, configMAX_PRIORITIES - 3, &s_bt_app_task_handle)==pdPASS);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_app_task_shut_down(void)
|
void bt_app_task_shut_down(void)
|
||||||
{
|
{
|
||||||
if (s_bt_app_task_handle) {
|
running = false;
|
||||||
vTaskDelete(s_bt_app_task_handle);
|
|
||||||
s_bt_app_task_handle = NULL;
|
|
||||||
}
|
|
||||||
if (s_bt_app_task_queue) {
|
|
||||||
vQueueDelete(s_bt_app_task_queue);
|
|
||||||
s_bt_app_task_queue = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
#define BT_APP_CORE_TAG "BT_APP_CORE"
|
#define BT_APP_CORE_TAG "BT_APP_CORE"
|
||||||
#define BT_APP_SIG_WORK_DISPATCH (0x01)
|
#define BT_APP_SIG_WORK_DISPATCH (0x01)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BT_APP_EVT_STACK_UP = 0,
|
||||||
|
};
|
||||||
|
|
||||||
/* A2DP global state */
|
/* A2DP global state */
|
||||||
enum {
|
enum {
|
||||||
APP_AV_STATE_IDLE,
|
APP_AV_STATE_IDLE,
|
||||||
@@ -56,12 +60,17 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src);
|
typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief callback for startup event
|
||||||
|
*/
|
||||||
|
typedef void bt_av_hdl_stack_evt_t(uint16_t event, void *p_param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief work dispatcher for the application task
|
* @brief work dispatcher for the application task
|
||||||
*/
|
*/
|
||||||
bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback);
|
bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback);
|
||||||
|
|
||||||
void bt_app_task_start_up(void);
|
void bt_app_task_start_up(bt_av_hdl_stack_evt_t* handler);
|
||||||
|
|
||||||
void bt_app_task_shut_down(void);
|
void bt_app_task_shut_down(void);
|
||||||
|
|
||||||
|
|||||||
@@ -37,19 +37,15 @@
|
|||||||
#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3)
|
#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3)
|
||||||
#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4)
|
#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4)
|
||||||
|
|
||||||
#define BT_AV_TAG "bt_app"
|
static const char BT_AV_TAG[] = "BT_AV";
|
||||||
#define BT_RC_TG_TAG "bt_rctg"
|
static const char BT_RC_TG_TAG[] = "RCTG";
|
||||||
#define BT_RC_CT_TAG "bt_rcct"
|
static const char BT_RC_CT_TAG[] = "RCCT";
|
||||||
|
|
||||||
#ifndef CONFIG_BT_NAME
|
#ifndef CONFIG_BT_NAME
|
||||||
#define CONFIG_BT_NAME "ESP32-BT"
|
#define CONFIG_BT_NAME "ESP32-BT"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* event for handler "bt_av_hdl_stack_up */
|
static char * bt_name = NULL;
|
||||||
enum {
|
|
||||||
BT_APP_EVT_STACK_UP = 0,
|
|
||||||
};
|
|
||||||
char * bt_name = NULL;
|
|
||||||
|
|
||||||
static bool (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...);
|
static bool (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...);
|
||||||
static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len);
|
static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len);
|
||||||
@@ -570,48 +566,13 @@ static void bt_av_hdl_avrc_tg_evt(uint16_t event, void *p_param)
|
|||||||
|
|
||||||
void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb)
|
void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
|
||||||
|
|
||||||
bt_app_a2d_cmd_cb = cmd_handler;
|
bt_app_a2d_cmd_cb = cmd_handler;
|
||||||
cmd_handler_chain = cmd_cb;
|
cmd_handler_chain = cmd_cb;
|
||||||
bt_app_a2d_data_cb = data_cb;
|
bt_app_a2d_data_cb = data_cb;
|
||||||
|
|
||||||
esp_bt_controller_mem_release(ESP_BT_MODE_BLE);
|
// create task and run event loop
|
||||||
|
bt_app_task_start_up(bt_av_hdl_stack_evt);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create application task */
|
|
||||||
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);
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
char *item = config_alloc_get_default(NVS_TYPE_STR, "bt_sink_volume", "127", 0);
|
char *item = config_alloc_get_default(NVS_TYPE_STR, "bt_sink_volume", "127", 0);
|
||||||
sink_volume = atol(item);
|
sink_volume = atol(item);
|
||||||
free(item);
|
free(item);
|
||||||
@@ -640,33 +601,17 @@ void bt_sink_init(bt_cmd_vcb_t cmd_cb, bt_data_cb_t data_cb)
|
|||||||
bError=true;
|
bError=true;
|
||||||
}
|
}
|
||||||
esp_pin_code[i]= pin_code[i];
|
esp_pin_code[i]= pin_code[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
if(bError){
|
|
||||||
esp_pin_code[0]='1';
|
if (bError) memcpy(esp_pin_code, "1234", 4);
|
||||||
esp_pin_code[1]='2';
|
esp_bt_gap_set_pin(pin_type, strlen(pin_code), esp_pin_code);
|
||||||
esp_pin_code[2]='3';
|
|
||||||
esp_pin_code[3]='4';
|
|
||||||
}
|
|
||||||
esp_bt_gap_set_pin(pin_type, strlen(pin_code), esp_pin_code);
|
|
||||||
free(pin_code);
|
free(pin_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_sink_deinit(void)
|
void bt_sink_deinit(void)
|
||||||
{
|
{
|
||||||
bt_app_task_shut_down();
|
bt_app_task_shut_down();
|
||||||
ESP_LOGD(BT_AV_TAG, "bt_app_task shutdown successfully");
|
|
||||||
if (esp_bluedroid_disable() != ESP_OK) return;
|
|
||||||
// this disable has a sleep timer BTA_DISABLE_DELAY in bt_target.h and
|
|
||||||
// if we don't wait for it then disable crashes... don't know why
|
|
||||||
vTaskDelay(2*200 / portTICK_PERIOD_MS);
|
|
||||||
ESP_LOGD(BT_AV_TAG, "esp_bluedroid_disable called successfully");
|
|
||||||
if (esp_bluedroid_deinit() != ESP_OK) return;
|
|
||||||
ESP_LOGD(BT_AV_TAG, "esp_bluedroid_deinit called successfully");
|
|
||||||
if (esp_bt_controller_disable() != ESP_OK) return;
|
|
||||||
ESP_LOGD(BT_AV_TAG, "esp_bt_controller_disable called successfully");
|
|
||||||
if (esp_bt_controller_deinit() != ESP_OK) return;
|
|
||||||
ESP_LOGD(BT_AV_TAG, "bt stopped successfully");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||||
|
|||||||
@@ -32,11 +32,6 @@ extern bool is_recovery_running;
|
|||||||
static void bt_app_av_state_connecting(uint16_t event, void *param);
|
static void bt_app_av_state_connecting(uint16_t event, void *param);
|
||||||
static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
|
static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
|
||||||
|
|
||||||
/* event for handler "bt_av_hdl_stack_up */
|
|
||||||
enum {
|
|
||||||
BT_APP_EVT_STACK_UP = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
char * APP_AV_STATE_DESC[] = {
|
char * APP_AV_STATE_DESC[] = {
|
||||||
"APP_AV_STATE_IDLE",
|
"APP_AV_STATE_IDLE",
|
||||||
"APP_AV_STATE_DISCOVERING",
|
"APP_AV_STATE_DISCOVERING",
|
||||||
@@ -105,8 +100,6 @@ static int s_connecting_intv = 0;
|
|||||||
cJSON * peers_list=NULL;
|
cJSON * peers_list=NULL;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
// int control_delay;
|
|
||||||
// int connect_timeout_delay;
|
|
||||||
char * sink_name;
|
char * sink_name;
|
||||||
} squeezelite_conf;
|
} squeezelite_conf;
|
||||||
|
|
||||||
@@ -122,6 +115,7 @@ static cJSON * peers_list_get_entry(const char * s_peer_bdname){
|
|||||||
ESP_LOGV(TAG,"Entry name %s NOT found in current scan list", s_peer_bdname);
|
ESP_LOGV(TAG,"Entry name %s NOT found in current scan list", s_peer_bdname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void peers_list_reset(){
|
static void peers_list_reset(){
|
||||||
cJSON * element=NULL;
|
cJSON * element=NULL;
|
||||||
cJSON_ArrayForEach(element,peers_list){
|
cJSON_ArrayForEach(element,peers_list){
|
||||||
@@ -132,6 +126,7 @@ static void peers_list_reset(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void peers_list_purge(){
|
static void peers_list_purge(){
|
||||||
cJSON * element=NULL;
|
cJSON * element=NULL;
|
||||||
cJSON_ArrayForEach(element,peers_list){
|
cJSON_ArrayForEach(element,peers_list){
|
||||||
@@ -144,12 +139,14 @@ static void peers_list_purge(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cJSON * peers_list_create_entry(const char * s_peer_bdname, int32_t rssi){
|
static cJSON * peers_list_create_entry(const char * s_peer_bdname, int32_t rssi){
|
||||||
cJSON * entry = cJSON_CreateObject();
|
cJSON * entry = cJSON_CreateObject();
|
||||||
cJSON_AddStringToObject(entry,"name",s_peer_bdname);
|
cJSON_AddStringToObject(entry,"name",s_peer_bdname);
|
||||||
cJSON_AddNumberToObject(entry,"rssi",rssi);
|
cJSON_AddNumberToObject(entry,"rssi",rssi);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void peers_list_update_add(const char * s_peer_bdname, int32_t rssi){
|
static void peers_list_update_add(const char * s_peer_bdname, int32_t rssi){
|
||||||
cJSON * element= peers_list_get_entry(s_peer_bdname);
|
cJSON * element= peers_list_get_entry(s_peer_bdname);
|
||||||
if(element){
|
if(element){
|
||||||
@@ -166,6 +163,7 @@ static void peers_list_update_add(const char * s_peer_bdname, int32_t rssi){
|
|||||||
cJSON_AddItemToArray(peers_list,element);
|
cJSON_AddItemToArray(peers_list,element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void peers_list_maintain(const char * s_peer_bdname, int32_t rssi){
|
static void peers_list_maintain(const char * s_peer_bdname, int32_t rssi){
|
||||||
if(!peers_list){
|
if(!peers_list){
|
||||||
ESP_LOGV(TAG,"Initializing BT peers list");
|
ESP_LOGV(TAG,"Initializing BT peers list");
|
||||||
@@ -198,35 +196,35 @@ int bt_app_source_get_a2d_state(){
|
|||||||
}
|
}
|
||||||
return bt_app_source_a2d_state;
|
return bt_app_source_a2d_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bt_app_source_get_media_state(){
|
int bt_app_source_get_media_state(){
|
||||||
ESP_LOGD(TAG,"media state : %u ", bt_app_source_media_state);
|
ESP_LOGD(TAG,"media state : %u ", bt_app_source_media_state);
|
||||||
return bt_app_source_media_state;
|
return bt_app_source_media_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_app_source_state(int new_state){
|
void set_app_source_state(int new_state){
|
||||||
if(bt_app_source_a2d_state!=new_state){
|
if(bt_app_source_a2d_state!=new_state){
|
||||||
ESP_LOGD(TAG, "Updating state from %s to %s", APP_AV_STATE_DESC[bt_app_source_a2d_state], APP_AV_STATE_DESC[new_state]);
|
ESP_LOGD(TAG, "Updating state from %s to %s", APP_AV_STATE_DESC[bt_app_source_a2d_state], APP_AV_STATE_DESC[new_state]);
|
||||||
bt_app_source_a2d_state=new_state;
|
bt_app_source_a2d_state=new_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_a2dp_media_state(int new_state){
|
void set_a2dp_media_state(int new_state){
|
||||||
if(bt_app_source_media_state!=new_state){
|
if(bt_app_source_media_state!=new_state){
|
||||||
bt_app_source_media_state=new_state;
|
bt_app_source_media_state=new_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hal_bluetooth_init(const char * options)
|
void hal_bluetooth_init(const char * options)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct arg_str *sink_name;
|
struct arg_str *sink_name;
|
||||||
// struct arg_int *control_delay;
|
|
||||||
// struct arg_int *connect_timeout_delay;
|
|
||||||
struct arg_end *end;
|
struct arg_end *end;
|
||||||
} squeezelite_args;
|
} squeezelite_args;
|
||||||
|
|
||||||
ESP_LOGD(TAG,"Initializing Bluetooth HAL");
|
ESP_LOGD(TAG,"Initializing Bluetooth HAL");
|
||||||
|
|
||||||
squeezelite_args.sink_name = arg_str0("n", "name", "<sink name>", "the name of the bluetooth to connect to");
|
squeezelite_args.sink_name = arg_str0("n", "name", "<sink name>", "the name of the bluetooth to connect to");
|
||||||
// squeezelite_args.control_delay = arg_int0("d", "delay", "<control delay>", "the delay between each pass at the A2DP control loop");
|
|
||||||
// squeezelite_args.connect_timeout_delay = arg_int0("t","timeout", "<timeout>", "the timeout duration for connecting to the A2DP sink");
|
|
||||||
squeezelite_args.end = arg_end(2);
|
squeezelite_args.end = arg_end(2);
|
||||||
|
|
||||||
ESP_LOGD(TAG,"Copying parameters");
|
ESP_LOGD(TAG,"Copying parameters");
|
||||||
@@ -269,83 +267,17 @@ void hal_bluetooth_init(const char * options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if(squeezelite_args.connect_timeout_delay->count == 0)
|
|
||||||
// {
|
|
||||||
// ESP_LOGD(TAG,"Using default connect timeout");
|
|
||||||
// char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_ctmt", NULL, 0);
|
|
||||||
// if(p){
|
|
||||||
// squeezelite_conf.connect_timeout_delay=atoi(p);
|
|
||||||
// free(p);
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// squeezelite_conf.connect_timeout_delay=CONFIG_A2DP_CONNECT_TIMEOUT_MS;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// squeezelite_conf.connect_timeout_delay=squeezelite_args.connect_timeout_delay->ival[0];
|
|
||||||
// }
|
|
||||||
// if(squeezelite_args.control_delay->count == 0)
|
|
||||||
// {
|
|
||||||
// ESP_LOGD(TAG,"Using default control delay");
|
|
||||||
// char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_ctrld", NULL, 0);
|
|
||||||
// if(p){
|
|
||||||
// squeezelite_conf.control_delay=atoi(p);
|
|
||||||
// free(p);
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// squeezelite_conf.control_delay=CONFIG_A2DP_CONNECT_TIMEOUT_MS;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// squeezelite_conf.control_delay=squeezelite_args.control_delay->ival[0];
|
|
||||||
// }
|
|
||||||
ESP_LOGD(TAG,"Freeing options");
|
ESP_LOGD(TAG,"Freeing options");
|
||||||
free(argv);
|
free(argv);
|
||||||
free(opts);
|
free(opts);
|
||||||
|
|
||||||
/*
|
// create task and run event loop
|
||||||
* Bluetooth audio source init Start
|
bt_app_task_start_up(bt_av_hdl_stack_evt);
|
||||||
*/
|
|
||||||
//running_test = false;
|
|
||||||
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 (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG,"%s initialize controller failed\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG,"%s enable controller failed\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_bluedroid_init() != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG,"%s initialize bluedroid failed\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_bluedroid_enable() != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG,"%s enable bluedroid failed\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* create application task */
|
|
||||||
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);
|
|
||||||
|
|
||||||
#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
|
* Set default parameters for Legacy Pairing
|
||||||
* Use variable pin, input pin code when pairing
|
* Use variable pin, input pin code when pairing
|
||||||
*/
|
*/
|
||||||
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE;
|
esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE;
|
||||||
esp_bt_pin_code_t pin_code;
|
esp_bt_pin_code_t pin_code;
|
||||||
esp_bt_gap_set_pin(pin_type, 0, pin_code);
|
esp_bt_gap_set_pin(pin_type, 0, pin_code);
|
||||||
@@ -353,23 +285,14 @@ void hal_bluetooth_init(const char * options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void hal_bluetooth_stop(void) {
|
void hal_bluetooth_stop(void) {
|
||||||
/* this still does not work, can't figure out how to stop properly this BT stack */
|
|
||||||
bt_app_task_shut_down();
|
bt_app_task_shut_down();
|
||||||
ESP_LOGI(TAG, "bt_app_task shutdown successfully");
|
|
||||||
if (esp_bluedroid_disable() != ESP_OK) return;
|
|
||||||
ESP_LOGI(TAG, "esp_bluedroid_disable called successfully");
|
|
||||||
if (esp_bluedroid_deinit() != ESP_OK) return;
|
|
||||||
ESP_LOGI(TAG, "esp_bluedroid_deinit called successfully");
|
|
||||||
if (esp_bt_controller_disable() != ESP_OK) return;
|
|
||||||
ESP_LOGI(TAG, "esp_bt_controller_disable called successfully");
|
|
||||||
if (esp_bt_controller_deinit() != ESP_OK) return;
|
|
||||||
ESP_LOGI(TAG, "bt stopped successfully");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||||
{
|
{
|
||||||
bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL);
|
bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param){
|
static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param){
|
||||||
char * pin_str = config_alloc_get_default(NVS_TYPE_STR, "a2dp_spin", "0000", 0);
|
char * pin_str = config_alloc_get_default(NVS_TYPE_STR, "a2dp_spin", "0000", 0);
|
||||||
int pinlen=pin_str?strlen(pin_str):0;
|
int pinlen=pin_str?strlen(pin_str):0;
|
||||||
@@ -405,6 +328,7 @@ static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_par
|
|||||||
}
|
}
|
||||||
FREE_AND_NULL(pin_str);
|
FREE_AND_NULL(pin_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -414,28 +338,21 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
|
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
|
||||||
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED)
|
|
||||||
{
|
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
|
||||||
peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_PURGE);
|
peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_PURGE);
|
||||||
if (bt_app_source_a2d_state == APP_AV_STATE_DISCOVERED)
|
if (bt_app_source_a2d_state == APP_AV_STATE_DISCOVERED) {
|
||||||
{
|
set_app_source_state(APP_AV_STATE_CONNECTING);
|
||||||
ESP_LOGI(TAG,"Discovery completed. Ready to start connecting to %s. ",s_peer_bdname);
|
ESP_LOGI(TAG,"Discovery completed. Ready to start connecting to %s. ", s_peer_bdname);
|
||||||
set_app_source_state(APP_AV_STATE_UNCONNECTED);
|
esp_a2d_source_connect(s_peer_bda);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// not discovered, continue to discover
|
// not discovered, continue to discover
|
||||||
ESP_LOGI(TAG,"Device discovery failed, continue to discover...");
|
ESP_LOGI(TAG, "Device discovery failed, continue to discover...");
|
||||||
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||||
}
|
}
|
||||||
}
|
} else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
|
||||||
else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
|
ESP_LOGI(TAG, "Discovery started.");
|
||||||
ESP_LOGI(TAG,"Discovery started.");
|
peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_RESET);
|
||||||
peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_RESET);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG,"This shouldn't happen. Discovery has only 2 states (for now).");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -523,10 +440,12 @@ static const char * conn_state_str(esp_a2d_connection_state_t state){
|
|||||||
}
|
}
|
||||||
return statestr;
|
return statestr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unexpected_connection_state(int from, esp_a2d_connection_state_t to)
|
static void unexpected_connection_state(int from, esp_a2d_connection_state_t to)
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", APP_AV_STATE_DESC[from], from,conn_state_str(to), to);
|
ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", APP_AV_STATE_DESC[from], from,conn_state_str(to), to);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param){
|
static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param){
|
||||||
ESP_LOGV(TAG, "A2DP Event while unconnected ");
|
ESP_LOGV(TAG, "A2DP Event while unconnected ");
|
||||||
switch (param->conn_stat.state)
|
switch (param->conn_stat.state)
|
||||||
@@ -553,17 +472,10 @@ static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param){
|
static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param){
|
||||||
ESP_LOGV(TAG, "A2DP connection state event : %s ",conn_state_str(param->conn_stat.state));
|
ESP_LOGV(TAG, "A2DP connection state event : %s ",conn_state_str(param->conn_stat.state));
|
||||||
// a2d = (esp_a2d_cb_param_t *)(param);
|
|
||||||
// if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
|
|
||||||
// ESP_LOGI(BT_AV_TAG, "a2dp connected");
|
|
||||||
// s_a2d_state = APP_AV_STATE_CONNECTED;
|
|
||||||
// s_media_state = APP_AV_MEDIA_STATE_IDLE;
|
|
||||||
// esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
|
|
||||||
// } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
|
|
||||||
// s_a2d_state = APP_AV_STATE_UNCONNECTED;
|
|
||||||
// }
|
|
||||||
switch (param->conn_stat.state)
|
switch (param->conn_stat.state)
|
||||||
{
|
{
|
||||||
case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
|
case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
|
||||||
@@ -575,9 +487,8 @@ static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *
|
|||||||
}
|
}
|
||||||
set_app_source_state(APP_AV_STATE_UNCONNECTED);
|
set_app_source_state(APP_AV_STATE_UNCONNECTED);
|
||||||
break;
|
break;
|
||||||
case ESP_A2D_CONNECTION_STATE_CONNECTING: {
|
case ESP_A2D_CONNECTION_STATE_CONNECTING:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case ESP_A2D_CONNECTION_STATE_CONNECTED:
|
case ESP_A2D_CONNECTION_STATE_CONNECTED:
|
||||||
set_app_source_state(APP_AV_STATE_CONNECTED);
|
set_app_source_state(APP_AV_STATE_CONNECTED);
|
||||||
set_a2dp_media_state(APP_AV_MEDIA_STATE_IDLE);
|
set_a2dp_media_state(APP_AV_MEDIA_STATE_IDLE);
|
||||||
@@ -768,8 +679,6 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* search for device named "ESP_SPEAKER" in its extended inqury response */
|
|
||||||
if (eir) {
|
if (eir) {
|
||||||
ESP_LOGV(TAG,"--Getting details from eir.\n");
|
ESP_LOGV(TAG,"--Getting details from eir.\n");
|
||||||
get_name_from_eir(eir, s_peer_bdname, NULL);
|
get_name_from_eir(eir, s_peer_bdname, NULL);
|
||||||
@@ -781,27 +690,16 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
|
|||||||
|
|
||||||
if (squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) >0 && strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) {
|
if (squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) >0 && strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) {
|
||||||
ESP_LOGI(TAG,"Found our target device. address %s, name %s", bda_str, s_peer_bdname);
|
ESP_LOGI(TAG,"Found our target device. address %s, name %s", bda_str, s_peer_bdname);
|
||||||
ESP_LOGV(TAG,"=======================\n");
|
memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
||||||
if(esp_bt_gap_cancel_discovery()!=ESP_ERR_INVALID_STATE)
|
set_app_source_state(APP_AV_STATE_DISCOVERED);
|
||||||
{
|
esp_bt_gap_cancel_discovery();
|
||||||
ESP_LOGD(TAG,"Cancel device discovery ...");
|
} else {
|
||||||
memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
|
||||||
set_app_source_state(APP_AV_STATE_DISCOVERED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG,"Cancel device discovery failed...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGV(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name?squeezelite_conf.sink_name:"N/A");
|
ESP_LOGV(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name?squeezelite_conf.sink_name:"N/A");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
|
static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case BT_APP_EVT_STACK_UP: {
|
case BT_APP_EVT_STACK_UP: {
|
||||||
ESP_LOGI(TAG,"BT Stack going up.");
|
ESP_LOGI(TAG,"BT Stack going up.");
|
||||||
@@ -960,7 +858,6 @@ static void bt_app_av_state_unconnected(uint16_t event, void *param)
|
|||||||
break;
|
break;
|
||||||
case ESP_A2D_AUDIO_STATE_EVT:
|
case ESP_A2D_AUDIO_STATE_EVT:
|
||||||
ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
|
ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ESP_A2D_AUDIO_CFG_EVT:
|
case ESP_A2D_AUDIO_CFG_EVT:
|
||||||
ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
|
ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
|
||||||
|
|||||||
@@ -99,23 +99,23 @@ static const struct gpio_exp_model_s {
|
|||||||
void (*set_pull_mode)(gpio_exp_t* self);
|
void (*set_pull_mode)(gpio_exp_t* self);
|
||||||
} registered[] = {
|
} registered[] = {
|
||||||
{ .model = "pca9535",
|
{ .model = "pca9535",
|
||||||
.trigger = GPIO_INTR_NEGEDGE,
|
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||||
.set_direction = pca9535_set_direction,
|
.set_direction = pca9535_set_direction,
|
||||||
.read = pca9535_read,
|
.read = pca9535_read,
|
||||||
.write = pca9535_write, },
|
.write = pca9535_write, },
|
||||||
{ .model = "pca85xx",
|
{ .model = "pca85xx",
|
||||||
.trigger = GPIO_INTR_NEGEDGE,
|
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||||
.read = pca85xx_read,
|
.read = pca85xx_read,
|
||||||
.write = pca85xx_write, },
|
.write = pca85xx_write, },
|
||||||
{ .model = "mcp23017",
|
{ .model = "mcp23017",
|
||||||
.trigger = GPIO_INTR_NEGEDGE,
|
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||||
.init = mcp23017_init,
|
.init = mcp23017_init,
|
||||||
.set_direction = mcp23017_set_direction,
|
.set_direction = mcp23017_set_direction,
|
||||||
.set_pull_mode = mcp23017_set_pull_mode,
|
.set_pull_mode = mcp23017_set_pull_mode,
|
||||||
.read = mcp23017_read,
|
.read = mcp23017_read,
|
||||||
.write = mcp23017_write, },
|
.write = mcp23017_write, },
|
||||||
{ .model = "mcp23s17",
|
{ .model = "mcp23s17",
|
||||||
.trigger = GPIO_INTR_NEGEDGE,
|
.trigger = GPIO_INTR_LOW_LEVEL,
|
||||||
.init = mcp23s17_init,
|
.init = mcp23s17_init,
|
||||||
.set_direction = mcp23s17_set_direction,
|
.set_direction = mcp23s17_set_direction,
|
||||||
.set_pull_mode = mcp23s17_set_pull_mode,
|
.set_pull_mode = mcp23s17_set_pull_mode,
|
||||||
@@ -406,6 +406,9 @@ static void IRAM_ATTR intr_isr_handler(void* arg) {
|
|||||||
gpio_exp_t *self = (gpio_exp_t*) arg;
|
gpio_exp_t *self = (gpio_exp_t*) arg;
|
||||||
BaseType_t woken = pdFALSE;
|
BaseType_t woken = pdFALSE;
|
||||||
|
|
||||||
|
// edge interrupts do not work because of read/clear = potential short pulse
|
||||||
|
gpio_intr_disable(self->intr);
|
||||||
|
|
||||||
// activate all, including ourselves
|
// activate all, including ourselves
|
||||||
for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true;
|
for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true;
|
||||||
|
|
||||||
@@ -439,26 +442,22 @@ void service_handler(void *arg) {
|
|||||||
for (int i = 0; i < n_expanders; i++) {
|
for (int i = 0; i < n_expanders; i++) {
|
||||||
gpio_exp_t *expander = expanders + i;
|
gpio_exp_t *expander = expanders + i;
|
||||||
|
|
||||||
// no interrupt for that gpio
|
// no interrupt for that gpio or not pending (safe as interrupt is disabled)
|
||||||
if (expander->intr < 0) continue;
|
if (expander->intr < 0 || !expander->intr_pending) continue;
|
||||||
|
|
||||||
// only check expander with pending interrupts
|
|
||||||
gpio_intr_disable(expander->intr);
|
|
||||||
if (!expander->intr_pending) {
|
|
||||||
gpio_intr_enable(expander->intr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
expander->intr_pending = false;
|
|
||||||
gpio_intr_enable(expander->intr);
|
|
||||||
|
|
||||||
xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50));
|
xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50));
|
||||||
|
|
||||||
// read GPIOs and clear all pending status
|
// read GPIOs and clear all pending status
|
||||||
uint32_t value = expander->model->read(expander);
|
uint32_t value = expander->model->read(expander);
|
||||||
|
expander->age = xTaskGetTickCount();
|
||||||
|
|
||||||
|
// re-enable interrupt now that it has been cleared
|
||||||
|
expander->intr_pending = false;
|
||||||
|
gpio_intr_enable(expander->intr);
|
||||||
|
|
||||||
uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask);
|
uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask);
|
||||||
expander->shadow = value;
|
expander->shadow = value;
|
||||||
expander->pending = 0;
|
expander->pending = 0;
|
||||||
expander->age = xTaskGetTickCount();
|
|
||||||
|
|
||||||
xSemaphoreGive(expander->mutex);
|
xSemaphoreGive(expander->mutex);
|
||||||
ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending);
|
ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending);
|
||||||
@@ -468,7 +467,7 @@ void service_handler(void *arg) {
|
|||||||
gpio -= clz;
|
gpio -= clz;
|
||||||
if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0
|
if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0
|
||||||
else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg);
|
else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -408,35 +408,27 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args)
|
|||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* We provide the generic codec register option
|
* We provide the generic codec register option
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(ESP_PLATFORM) && defined(CONFIG_BT_SINK)
|
|
||||||
void bt_delay_start(TimerHandle_t xTimer) {
|
|
||||||
xTimerDelete(xTimer, portMAX_DELAY);
|
|
||||||
bt_sink_init(bt_sink_cmd_handler, sink_data_handler);
|
|
||||||
LOG_INFO("Initializing BT sink");
|
|
||||||
}
|
|
||||||
|
|
||||||
void bt_delay_stop(TimerHandle_t xTimer) {
|
|
||||||
xTimerDelete(xTimer, portMAX_DELAY);
|
|
||||||
bt_sink_deinit();
|
|
||||||
LOG_INFO("Stopping BT sink");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void register_external(void) {
|
void register_external(void) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
#if CONFIG_BT_SINK
|
#if CONFIG_BT_SINK
|
||||||
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_bt_sink")) != NULL) {
|
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_bt_sink")) != NULL) {
|
||||||
enable_bt_sink = strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0;
|
enable_bt_sink = !strcmp(p,"1") || !strcasecmp(p,"y");
|
||||||
free(p);
|
free(p);
|
||||||
|
if (!strcasestr(output.device, "BT") && enable_bt_sink) {
|
||||||
|
bt_sink_init(bt_sink_cmd_handler, sink_data_handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_AIRPLAY_SINK
|
#if CONFIG_AIRPLAY_SINK
|
||||||
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_airplay")) != NULL) {
|
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_airplay")) != NULL) {
|
||||||
enable_airplay = strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0;
|
enable_airplay = !strcmp(p,"1") || !strcasecmp(p,"y");
|
||||||
free(p);
|
free(p);
|
||||||
|
if (enable_airplay){
|
||||||
|
raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler);
|
||||||
|
LOG_INFO("Initializing AirPlay sink");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -447,29 +439,6 @@ void register_external(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_BT_SINK
|
|
||||||
if (!strcasestr(output.device, "BT ") ) {
|
|
||||||
if(enable_bt_sink){
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
// we need to delay the start because current task is in spiram
|
|
||||||
TimerHandle_t timer = xTimerCreate("delay", 1, pdFALSE, NULL, bt_delay_start);
|
|
||||||
xTimerStart(timer, portMAX_DELAY);
|
|
||||||
#else
|
|
||||||
bt_sink_init(bt_sink_cmd_handler, sink_data_handler);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG_WARN("Cannot be a BT sink and source");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_AIRPLAY_SINK
|
|
||||||
if (enable_airplay){
|
|
||||||
raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler);
|
|
||||||
LOG_INFO("Initializing AirPlay sink");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_CSPOT_SINK
|
#if CONFIG_CSPOT_SINK
|
||||||
if (enable_cspot){
|
if (enable_cspot){
|
||||||
cspot_sink_init(cspot_cmd_handler, sink_data_handler);
|
cspot_sink_init(cspot_cmd_handler, sink_data_handler);
|
||||||
@@ -480,14 +449,8 @@ void register_external(void) {
|
|||||||
|
|
||||||
void deregister_external(void) {
|
void deregister_external(void) {
|
||||||
#if CONFIG_BT_SINK
|
#if CONFIG_BT_SINK
|
||||||
if (!strcasestr(output.device, "BT ") && enable_bt_sink) {
|
if (!strcasestr(output.device, "BT") && enable_bt_sink) {
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
// we need to delay the stop because current task is in spiram
|
|
||||||
TimerHandle_t timer = xTimerCreate("delay", 1, pdFALSE, NULL, bt_delay_stop);
|
|
||||||
xTimerStart(timer, portMAX_DELAY);
|
|
||||||
#else
|
|
||||||
bt_sink_deinit();
|
bt_sink_deinit();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -503,7 +466,7 @@ void deregister_external(void) {
|
|||||||
LOG_INFO("Stopping CSpot sink");
|
LOG_INFO("Stopping CSpot sink");
|
||||||
cspot_sink_deinit();
|
cspot_sink_deinit();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_restore(int external) {
|
void decode_restore(int external) {
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ static void server(in_addr_t ip, u16_t hport, u16_t cport) {
|
|||||||
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
||||||
|
|
||||||
sprintf(msg, "%s:%hu", inet_ntoa(ip), hport);
|
sprintf(msg, "%s:%hu", inet_ntoa(ip), hport);
|
||||||
if (display && displayer.owned) GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg);
|
if (display && displayer.owned) GDS_TextPos(display, GDS_FONT_LINE_1, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg);
|
||||||
displayer.dirty = true;
|
displayer.dirty = true;
|
||||||
|
|
||||||
xSemaphoreGive(displayer.mutex);
|
xSemaphoreGive(displayer.mutex);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ void output_init_embedded(log_level level, char *device, unsigned output_buf_siz
|
|||||||
output.rate_delay = rate_delay;
|
output.rate_delay = rate_delay;
|
||||||
|
|
||||||
#if CONFIG_BT_SINK
|
#if CONFIG_BT_SINK
|
||||||
if (strcasestr(device, "BT ") || !strcasecmp(device, "BT")) {
|
if (strcasestr(device, "BT")) {
|
||||||
LOG_INFO("init Bluetooth");
|
LOG_INFO("init Bluetooth");
|
||||||
close_cb = &output_close_bt;
|
close_cb = &output_close_bt;
|
||||||
output_init_bt(level, device, output_buf_size, params, rates, rate_delay, idle);
|
output_init_bt(level, device, output_buf_size, params, rates, rate_delay, idle);
|
||||||
|
|||||||
Reference in New Issue
Block a user