KT24-1110_65E-HA-651B/apps/soundbox/task_manager/bt/bt_emitter.c
2024-11-10 18:44:17 +08:00

1480 lines
41 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*************************************************************
此文件函数主要是蓝牙发射器接口处理
1、关于AG对讲功能使用说明
发射器需要通过user_emitter_cmd_prepare接口来给接收器发送命令,例如:
(1)发射器主动发起通话
user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_LAST_NO, 0, NULL)
(2)发射器主动关断通话
user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL)
(3)接收器来电接听
user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL)
**************************************************************/
#include "system/app_core.h"
#include "system/includes.h"
#include "app_config.h"
#include "app_task.h"
#include "btstack/btstack_task.h"
#include "btcontroller_modules.h"
#include "btstack/avctp_user.h"
#include "classic/hci_lmp.h"
#include "bt/bt.h"
#include "bt/bt_emitter.h"
#include "user_cfg.h"
#include "vm.h"
#include "app_main.h"
#include "common/app_common.h"
#include "key_event_deal.h"
#include "rcsp_bluetooth.h"
#include "media/includes.h"
#include "audio_config.h"
#include "audio_digital_vol.h"
#include "audio_enc.h"
#include "audio_sbc_codec.h"
#include "media/file_decoder.h"
#include "music/music_player.h"
#include "bt_vartual_fast_connect.h"
#if TCFG_APP_BT_EN
#if TCFG_USER_EMITTER_ENABLE
#define LOG_TAG_CONST BT
#define LOG_TAG "[BT]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define SEARCH_BD_ADDR_LIMITED 0
#define SEARCH_BD_NAME_LIMITED 1
#define SEARCH_CUSTOM_LIMITED 2
#define SEARCH_NULL_LIMITED 3
#define SEARCH_LIMITED_MODE SEARCH_BD_NAME_LIMITED
#define SEARCH_NAME_DEBUG 0
#define HOWLING_ENABLE 0
struct remote_name {
u16 crc;
u8 addr[6];
u8 name[32];
};
struct list_head inquiry_noname_list;
struct inquiry_noname_remote {
struct list_head entry;
u8 match;
s8 rssi;
u8 addr[6];
u32 class;
};
extern int music_player_get_play_status(void);
extern int music_player_pp(void);
extern u16 get_emitter_curr_channel_state();
static u8 read_name_start = 0;
static u8 bt_search_busy = 0;
static u8 search_spp_device = 0;
static u8 emitter_dac_mute_en = 0;
static u8 bt_emitter_start = 0;
void bt_emitter_audio_set_mute(u8 mute)
{
emitter_dac_mute_en = !!mute;
}
/*----------------------------------------------------------------------------*/
/**@brief 音频数据清0
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
int audio_data_set_zero(struct audio_stream_entry *entry, struct audio_data_frame *data_buf)
{
if (emitter_dac_mute_en) {
memset(data_buf->data, 0, data_buf->data_len);
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射发起搜索设备
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void bt_search_device(void)
{
if (!get_bt_init_status()) {
/* log_info("bt on init >>>>>>>>>>>>>>>>>>>>>>>\n"); */
return;
}
if (bt_search_busy) {
/* log_info("bt_search_busy >>>>>>>>>>>>>>>>>>>>>>>\n"); */
//return;
}
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
read_name_start = 0;
bt_search_busy = 1;
u8 inquiry_length = 20; // inquiry_length * 1.28s
user_send_cmd_prepare(USER_CTRL_SEARCH_DEVICE, 1, &inquiry_length);
/* log_info("bt_search_start >>>>>>>>>>>>>>>>>>>>>>>\n"); */
}
void bt_search_spp_device()
{
search_spp_device = 1;
set_start_search_spp_device(1);
bt_search_device();
}
u8 bt_search_status()
{
return bt_search_busy;
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射 提供按键切换发射器或者是音箱功能
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_connect_switch()
{
if (get_emitter_curr_channel_state() != 0) {
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
while (hci_standard_connect_check() != 0) {
//wait disconnect;
os_time_dly(10);
}
} else {
/* log_info("start connect vm addr\n"); */
user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR_MANUALLY, 0, NULL);
}
}
u8 bt_emitter_role_get()
{
return bt_user_priv_var.emitter_or_receiver;
}
void bt_emitter_stop_search_device()
{
user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL);
}
void emitter_bt_connect(u8 *mac)
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
return ;
}
while (hci_standard_connect_check() == 0x80) {
//wait profile connect ok;
if (get_curr_channel_state()) {
break;
}
os_time_dly(10);
}
////断开链接
if (get_curr_channel_state() != 0) {
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
} else {
if (hci_standard_connect_check()) {
user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL);
user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL);
}
}
/* if there are some connected channel ,then disconnect*/
while (hci_standard_connect_check() != 0) {
//wait disconnect;
os_time_dly(10);
}
user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac);
}
void bt_emitter_start_search_device()
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
return ;
}
while (hci_standard_connect_check() == 0x80) {
//wait profile connect ok;
if (get_curr_channel_state()) {
break;
}
os_time_dly(10);
}
////断开链接
if (get_curr_channel_state() != 0) {
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
} else {
if (hci_standard_connect_check()) {
user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL);
user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL);
}
}
/* if there are some connected channel ,then disconnect*/
while (hci_standard_connect_check() != 0) {
//wait disconnect;
os_time_dly(10);
}
////关闭可发现可链接
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
////切换样机状态
bt_search_device();
}
////回链耳机音箱
u8 connect_last_sink_device_from_vm()
{
bd_addr_t mac_addr;
u8 flag = 0;
flag = restore_remote_device_info_profile(&mac_addr, 1, get_remote_dev_info_index(), REMOTE_SINK);
if (flag) {
//connect last conn
printf("last source device addr from vm:");
put_buf(mac_addr, 6);
user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac_addr);
}
//r_printf("connect last vm addr\n");
return flag;
}
////回链手机
u8 connect_last_source_device_from_vm()
{
bd_addr_t mac_addr;
u8 flag = 0;
flag = restore_remote_device_info_profile(&mac_addr, 1, get_remote_dev_info_index(), REMOTE_SOURCE);
if (flag) {
//connect last conn
printf("last source device addr from vm:");
put_buf(mac_addr, 6);
user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac_addr);
}
//r_printf("connect last vm addr\n");
return flag;
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射 提供按键切换发射器或者是音箱功能
@param 1:发射 0接收
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_or_receiver_switch(u8 flag)
{
/* log_info("===emitter_or_receiver_switch %d %x\n", flag, hci_standard_connect_check()); */
/*如果上一次操作记录跟传进来的参数一致,则不操作*/
if (bt_user_priv_var.emitter_or_receiver == flag) {
return ;
}
while (hci_standard_connect_check() == 0x80) {
//wait profile connect ok;
if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { ///蓝牙发射器
r_printf("cur_ch:0x%x", get_emitter_curr_channel_state());
if (get_emitter_curr_channel_state()) {
break;
}
} else {
r_printf("cur_ch:0x%x", get_curr_channel_state());
if (get_curr_channel_state()) {
break;
}
}
os_time_dly(10);
}
////断开链接
if ((get_curr_channel_state() != 0) || (get_emitter_curr_channel_state() != 0)) {
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
} else {
if (hci_standard_connect_check()) {
user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL);
user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL);
}
}
/* if there are some connected channel ,then disconnect*/
while (hci_standard_connect_check() != 0) {
//wait disconnect;
os_time_dly(10);
}
/* g_printf("===wait to switch to mode %d\n", flag); */
bt_user_priv_var.emitter_or_receiver = flag;
if (flag == BT_EMITTER_EN) { ///蓝牙发射器
bredr_bulk_change(0);
////关闭可发现可链接
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
////切换样机状态
__set_emitter_enable_flag(1);
a2dp_source_init(NULL, 0, 1);
#if (USER_SUPPORT_PROFILE_HFP_AG==1)
hfp_ag_buf_init(NULL, 0, 1);
#endif
#if TCFG_VIRTUAL_FAST_CONNECT_FOR_EMITTER
bt_virtual_fast_connect_poweron(BT_EMITTER_EN);
#else
////开启搜索设备
if (connect_last_device_from_vm()) {
log_info("start connect device vm addr\n");
} else {
bt_search_device();
}
#endif
} else if (flag == BT_RECEIVER_EN) { ///蓝牙接收
bredr_bulk_change(1);
////切换样机状态
__set_emitter_enable_flag(0);
emitter_media_source(NULL, 1, 0);
hci_cancel_inquiry();
a2dp_source_init(NULL, 0, 0);
#if (USER_SUPPORT_PROFILE_HFP_AG==1)
hfp_ag_buf_init(NULL, 0, 0);
#endif
////开启可发现可链接
/*if (connect_last_device_from_vm()) {
log_info("start connect vm addr phone \n");
} else {
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL);
}*/
}
}
void bt_emitter_receiver_sw()
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
emitter_or_receiver_switch(BT_EMITTER_EN);
} else {
emitter_or_receiver_switch(BT_RECEIVER_EN);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射变量初始化
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void bt_emitter_init()
{
bt_emitter_start = 1;
INIT_LIST_HEAD(&inquiry_noname_list);
lmp_set_sniff_establish_by_remote(1);
audio_sbc_enc_init();
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射搜索设备没有名字的设备,放进需要获取名字链表
@param status : 获取成功 0获取失败
addr:设备地址
name设备名字
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_search_noname(u8 status, u8 *addr, u8 *name)
{
struct inquiry_noname_remote *remote, *n;
if (!bt_emitter_start) {
return ;
}
u8 res = 0;
local_irq_disable();
if (status) {
list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) {
if (!memcmp(addr, remote->addr, 6)) {
list_del(&remote->entry);
free(remote);
}
}
goto __find_next;
}
list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) {
if (!memcmp(addr, remote->addr, 6)) {
res = emitter_search_result(name, strlen(name), addr, remote->class, remote->rssi);
if (res) {
read_name_start = 0;
remote->match = 1;
user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL);
local_irq_enable();
return;
}
list_del(&remote->entry);
free(remote);
}
}
__find_next:
read_name_start = 0;
remote = NULL;
if (!list_empty(&inquiry_noname_list)) {
remote = list_first_entry(&inquiry_noname_list, struct inquiry_noname_remote, entry);
}
local_irq_enable();
if (remote) {
read_name_start = 1;
user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, remote->addr);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射停止搜索
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_search_stop(u8 result)
{
struct inquiry_noname_remote *remote, *n;
bt_search_busy = 0;
search_spp_device = 0;
set_start_search_spp_device(0);
u8 wait_connect_flag = 1;
if (!list_empty(&inquiry_noname_list)) {
user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL);
}
if (!result) {
list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) {
if (remote->match) {
user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, remote->addr);
wait_connect_flag = 0;
}
list_del(&remote->entry);
free(remote);
}
}
read_name_start = 0;
if (wait_connect_flag) {
/* log_info("wait conenct\n"); */
#if TCFG_SPI_LCD_ENABLE
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
#else
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
if (!result) {
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL);
}
#endif
}
}
#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED)
u8 bd_addr_filt[][6] = {
{0x8E, 0xA7, 0xCA, 0x0A, 0x5E, 0xC8}, /*S10_H*/
{0xA7, 0xDD, 0x05, 0xDD, 0x1F, 0x00}, /*ST-001*/
{0xE9, 0x73, 0x13, 0xC0, 0x1F, 0x00}, /*HBS 730*/
{0x38, 0x7C, 0x78, 0x1C, 0xFC, 0x02}, /*Bluetooth*/
};
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射搜索通过地址过滤
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
u8 search_bd_addr_filt(u8 *addr)
{
u8 i;
log_info("bd_addr:");
log_info_hexdump(addr, 6);
for (i = 0; i < (sizeof(bd_addr_filt) / sizeof(bd_addr_filt[0])); i++) {
if (memcmp(addr, bd_addr_filt[i], 6) == 0) {
/* printf("bd_addr match:%d\n", i); */
return TRUE;
}
}
/*log_info("bd_addr not match\n"); */
return FALSE;
}
#endif
#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
#if (0)
u8 bd_name_filt[][32] = {
"BeMine",
"EDIFIER CSR8635",/*CSR*/
"JL-BT-SDK",/*Realtek*/
"I7-TWS",/*ZKLX*/
"TWS-i7",/*ZKLX*/
"I9",/*ZKLX*/
"小米小钢炮蓝牙音箱",/*XiaoMi*/
"小米蓝牙音箱",/*XiaoMi*/
"XMFHZ02",/*XiaoMi*/
"JBL GO 2",
"i7mini",/*JL tws AC690x*/
"S08U",
"AI8006B_TWS00",
"S046",/*BK*/
"AirPods",
"CSD-TWS-01",
"AC692X_wh",
"JBL GO 2",
"JBL Flip 4",
"BT Speaker",
"CSC608",
"QCY-QY19",
"Newmine",
"HT1+",
"S-35",
"T12-JL",
"Redmi AirDots_R",
"Redmi AirDots_L",
"AC69_Bluetooth",
"FlyPods 3",
"MNS",
"Jam Heavy Metal",
"Bluedio",
"HR-686",
"BT MUSIC",
"BW-USB-DONGLE",
"S530",
"XPDQ7",
"MICGEEK Q9S",
"S10_H",
"S10",/*JL AC690x*/
"S11",/*JL AC460x*/
"HBS-730",
"SPORT-S9",
"Q5",
"IAEB25",
"T5-JL",
"MS-808",
"LG HBS-730",
"NG-BT07"
};
#else
u8 bd_name_filt[20][30] = {
"JBL Flip 4",
"JBL GO",
};
#endif
u8 bd_spp_name_filt[20][30] = {
"AC69_BT_SDK",
};
extern const char *bt_get_emitter_connect_name();
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射搜索通过名字过滤
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
u8 search_bd_name_filt(char *data, u8 len, u32 dev_class, char rssi)
{
char bd_name[64] = {0};
u8 i;
char *targe_name = NULL;
char char_a = 0, char_b = 0;
if ((len > (sizeof(bd_name))) || (len == 0)) {
//printf("bd_name_len error:%d\n", len);
return FALSE;
}
memset(bd_name, 0, sizeof(bd_name));
memcpy(bd_name, data, len);
log_info("name:%s,len:%d,class %x ,rssi %d\n", bd_name, len, dev_class, rssi);
#if SEARCH_NAME_DEBUG
extern char *get_edr_name(void);
printf("tar name:%s,len:%d\n", get_edr_name(), strlen(get_edr_name()));
targe_name = (char *)get_edr_name();
#if 1
//不区分大小写
for (i = 0; i < len; i++) {
char_a = bd_name[i];
char_b = targe_name[i];
if ('A' <= char_a && char_a <= 'Z') {
char_a += 32; //转换成小写
}
if ('A' <= char_b && char_b <= 'Z') {
char_b += 32; //转换成小写
}
//printf("{%d-%d}",char_a,char_b);
if (char_a != char_b) {
return FALSE;
}
}
log_info("\n*****find dev ok******\n");
return TRUE;
#else
//区分大小写
if (memcmp(data, bt_get_emitter_connect_name(), len) == 0) {
log_info("\n*****find dev ok******\n");
return TRUE;
}
return FALSE;
#endif
#else
if (search_spp_device) {
for (i = 0; i < (sizeof(bd_spp_name_filt) / sizeof(bd_spp_name_filt[0])); i++) {
if (memcmp(data, bd_spp_name_filt[i], len) == 0) {
puts("\n*****find dev ok******\n");
return TRUE;
}
}
} else {
for (i = 0; i < (sizeof(bd_name_filt) / sizeof(bd_name_filt[0])); i++) {
if (memcmp(data, bd_name_filt[i], len) == 0) {
puts("\n*****find dev ok******\n");
return TRUE;
}
}
}
return FALSE;
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射搜索结果回调处理
@param name : 设备名字
name_len: 设备名字长度
addr: 设备地址
dev_class: 设备类型
rssi: 设备信号强度
@return 无
@note
蓝牙设备搜索结果,可以做名字/地址过滤,也可以保存搜到的所有设备
在选择一个进行连接,获取其他你想要的操作。
返回TRUE表示搜到指定的想要的设备搜索结束直接连接当前设备
返回FALSE则继续搜索直到搜索完成或者超时
*/
/*----------------------------------------------------------------------------*/
u8 emitter_search_result(char *name, u8 name_len, u8 *addr, u32 dev_class, char rssi)
{
#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
if (name == NULL) {
struct inquiry_noname_remote *remote = malloc(sizeof(struct inquiry_noname_remote));
remote->match = 0;
remote->class = dev_class;
remote->rssi = rssi;
memcpy(remote->addr, addr, 6);
local_irq_disable();
list_add_tail(&remote->entry, &inquiry_noname_list);
local_irq_enable();
if (read_name_start == 0) {
read_name_start = 1;
user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, addr);
}
}
#endif
/* #if (RCSP_BTMATE_EN) */
/* rcsp_msg_post(RCSP_MSG_BT_SCAN, 5, dev_class, addr, rssi, name, name_len); */
/* #endif */
#if (SMART_BOX_EN)
extern void smartbox_command_send_bt_scan_result(char *name, u8 name_len, u8 * addr, u32 dev_class, char rssi);
smartbox_command_send_bt_scan_result(name, name_len, addr, dev_class, rssi);
#endif
#if TCFG_SPI_LCD_ENABLE
/* void bt_menu_list_add(u8 * name, u8 * mac, u8 rssi); */
/* bt_menu_list_add(name, addr, rssi); */
log_info("name:%s,len:%d,class %x ,rssi %d\n", name, name_len, dev_class, rssi);
return false;
#endif
#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
return search_bd_name_filt(name, name_len, dev_class, rssi);
#endif
#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED)
return search_bd_addr_filt(addr);
#endif
#if (SEARCH_LIMITED_MODE == SEARCH_CUSTOM_LIMITED)
/*以下为搜索结果自定义处理*/
char bt_name[63] = {0};
u8 len;
if (name_len == 0) {
log_info("No_eir\n");
} else {
len = (name_len > 63) ? 63 : name_len;
/* display bd_name */
memcpy(bt_name, name, len);
log_info("name:%s,len:%d,class %x ,rssi %d\n", bt_name, name_len, dev_class, rssi);
}
/* display bd_addr */
log_debug_hexdump(addr, 6);
/* You can connect the specified bd_addr by below api */
//user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR,6,addr);
return FALSE;
#endif
#if (SEARCH_LIMITED_MODE == SEARCH_NULL_LIMITED)
/*没有指定限制,则搜到什么就连接什么*/
return TRUE;
#endif
}
typedef enum {
AVCTP_OPID_VOLUME_UP = 0x41,
AVCTP_OPID_VOLUME_DOWN = 0x42,
AVCTP_OPID_MUTE = 0x43,
AVCTP_OPID_PLAY = 0x44,
AVCTP_OPID_STOP = 0x45,
AVCTP_OPID_PAUSE = 0x46,
AVCTP_OPID_NEXT = 0x4B,
AVCTP_OPID_PREV = 0x4C,
} AVCTP_CMD_TYPE;
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射接收到设备按键消息
@param cmd:按键命令
@return 无
@note
发射器收到接收器发过来的控制命令处理
根据实际需求可以在收到控制命令之后做相应的处理
蓝牙库里面定义的是weak函数直接再定义一个同名可获取信息
*/
/*----------------------------------------------------------------------------*/
void emitter_rx_avctp_opid_deal(u8 cmd, u8 id)
{
log_debug("avctp_rx_cmd:%x\n", cmd);
switch (cmd) {
case AVCTP_OPID_NEXT:
log_info("AVCTP_OPID_NEXT\n");
app_task_put_key_msg(KEY_MUSIC_NEXT, 0);
break;
case AVCTP_OPID_PREV:
log_info("AVCTP_OPID_PREV\n");
app_task_put_key_msg(KEY_MUSIC_PREV, 0);
break;
case AVCTP_OPID_PAUSE:
case AVCTP_OPID_STOP:
log_info("AVCTP_OPID_PAUSE\n");
/* bt_emitter_pp(0); */
app_task_put_key_msg(KEY_MUSIC_PP, 0);
break;
case AVCTP_OPID_PLAY:
/* bt_emitter_pp(1); */
app_task_put_key_msg(KEY_MUSIC_PP, 0);
log_info("AVCTP_OPID_PP\n");
break;
case AVCTP_OPID_VOLUME_UP:
log_info("AVCTP_OPID_VOLUME_UP\n");
app_task_put_key_msg(KEY_VOL_UP, 0);
break;
case AVCTP_OPID_VOLUME_DOWN:
log_info("AVCTP_OPID_VOLUME_DOWN\n");
app_task_put_key_msg(KEY_VOL_DOWN, 0);
break;
default:
break;
}
return ;
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射接收设备同步音量
@param vol:接收到设备同步音量
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_rx_vol_change(u8 vol)
{
log_info("vol_change:%d \n", vol);
}
typedef struct _EMITTER_INFO {
volatile u8 role;
u8 media_source;
u8 source_record;/*统计当前有多少设备可用*/
u8 reserve;
} EMITTER_INFO_T;
EMITTER_INFO_T emitter_info = {
.role = 0/*EMITTER_ROLE_SLAVE*/,
};
void emitter_open(u8 source)
{
emitter_info.source_record |= source;
if (emitter_info.media_source == source) {
return;
}
emitter_info.media_source = source;
__emitter_send_media_toggle(NULL, 1);
}
void emitter_close(u8 source)
{
if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) {
music_player_pp();
}
emitter_info.source_record &= ~source;
if (emitter_info.media_source == source) {
emitter_info.media_source = 0/*EMITTER_SOURCE_NULL*/;
__emitter_send_media_toggle(NULL, 0);
//emitter_media_source_next();
}
while (bt_emitter_stu_get()) {
os_time_dly(2);
putchar('K');
}
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射接收设备同步音量
@param source: 高级音频角色 1source 0sink
en:关闭source
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_media_source(u8 *addr, u8 source, u8 en)
{
if (en) {
/*关闭当前的source通道*/
//emitter_media_source_close(emitter_info.media_source);
if ((true != app_check_curr_task(APP_MUSIC_TASK))) {
app_task_switch_to(APP_MUSIC_TASK);
}
if (music_player_get_play_status() != FILE_DEC_STATUS_PLAY) {
music_player_pp();
}
emitter_info.source_record |= source;
if (emitter_info.media_source == source) {
return;
}
emitter_info.media_source = source;
__emitter_send_media_toggle(NULL, 1);
} else {
if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) {
music_player_pp();
}
emitter_info.source_record &= ~source;
if (emitter_info.media_source == source) {
emitter_info.media_source = 0/*EMITTER_SOURCE_NULL*/;
__emitter_send_media_toggle(NULL, 0);
//emitter_media_source_next();
}
if ((true == app_check_curr_task(APP_MUSIC_TASK))) {
app_task_switch_to(APP_BT_TASK);
}
}
log_info("current source: %x-%x\n", source, emitter_info.source_record);
}
#endif
u8 bt_emitter_stu_get(void)
{
return audio_sbc_enc_is_work();//bt_emitter_on;
}
u8 bt_emitter_stu_set(u8 *addr, u8 on)
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
return 0;
}
if (!(get_emitter_curr_channel_state() & A2DP_SRC_CH)) {
emitter_media_source(NULL, 1, 0);
return 0;
}
log_debug("total con dev:%d ", get_total_connect_dev());
if (on && (get_total_connect_dev() == 0)) {
on = 0;
}
/* bt_emitter_on = on; */
emitter_media_source(NULL, 1, on);
return on;
}
u8 bt_emitter_pp(u8 pp)
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
return 0;
}
if (get_total_connect_dev() == 0) {
//如果没有连接就启动一下搜索
/* bt_search_device(); */
return 0;
}
if (!(get_emitter_curr_channel_state() & A2DP_SRC_CH)) {
return 0;
}
return bt_emitter_stu_set(NULL, pp);
}
u8 bt_emitter_stu_sw(void)
{
return bt_emitter_pp(!bt_emitter_stu_get());
}
//////////////////////////////////////////////////////////////////////
// mic
#define ESCO_ADC_BUF_NUM 2
#define ESCO_ADC_IRQ_POINTS 256
#define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS)
#include "audio_dec.h"
#include "clock_cfg.h"
#include "media/pcm_decoder.h"
#define BT_EMITTER_PCM_BUF_LEN (3*1024)
struct bt_emitter_mic_dec_hdl {
struct audio_stream *stream; // 音频流
struct pcm_decoder pcm_dec; // pcm解码句柄
struct audio_res_wait wait; // 资源等待句柄
struct audio_mixer_ch mix_ch; // 叠加句柄
u32 id; // 唯一标识符,随机值
u32 start : 1; // 正在解码
u32 mic_start : 1;
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes
u8 pcm_buf[BT_EMITTER_PCM_BUF_LEN];
cbuffer_t cbuf;
u32 lost;
u32 cbuf_use_max;
u8 skip_cnt; //用来丢掉刚开mic时的前几包异常数据
void *p_howling_hdl; //啸叫抑制句柄
};
static struct bt_emitter_mic_dec_hdl *bt_emitter_mic_dec = NULL;
extern struct audio_adc_hdl adc_hdl;
static void adc_mic_output_handler(void *priv, s16 *data, int len)
{
struct bt_emitter_mic_dec_hdl *dec = bt_emitter_mic_dec;
if (!dec || !dec->start) {
return ;
}
if (dec->skip_cnt) {
dec->skip_cnt--;
memset(data, 0, len);
}
#if HOWLING_ENABLE
if (dec->p_howling_hdl) {
run_howling(dec->p_howling_hdl, data, data, len / 2);
}
#endif
int wlen = cbuf_write(&dec->cbuf, data, len);
if (wlen != len) {
dec->lost++;
}
u32 max = cbuf_get_data_len(&dec->cbuf);
if (dec->cbuf_use_max < max) {
dec->cbuf_use_max = max;
}
audio_decoder_resume(&dec->pcm_dec.decoder);
}
static int bt_emitter_mic_dec_read(void *hdl, void *data, int len)
{
struct bt_emitter_mic_dec_hdl *dec = hdl;
return cbuf_read(&dec->cbuf, data, len);
}
static int bt_emitter_mic_dec_size(void *hdl)
{
struct bt_emitter_mic_dec_hdl *dec = hdl;
return cbuf_get_data_size(&dec->cbuf);
}
static int bt_emitter_mic_dec_total(void *hdl)
{
struct bt_emitter_mic_dec_hdl *dec = hdl;
return dec->cbuf.total_len;
}
static void bt_emitter_mic_dec_relaese()
{
if (bt_emitter_mic_dec) {
audio_decoder_task_del_wait(&decode_task, &bt_emitter_mic_dec->wait);
clock_remove(AUDIO_CODING_PCM);
local_irq_disable();
free(bt_emitter_mic_dec);
bt_emitter_mic_dec = NULL;
local_irq_enable();
}
}
static void bt_emitter_mic_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
if (!bt_emitter_mic_dec) {
log_i("bt_emitter_mic_dec handle err ");
break;
}
if (bt_emitter_mic_dec->id != argv[1]) {
log_w("bt_emitter_mic_dec id err : 0x%x, 0x%x \n", bt_emitter_mic_dec->id, argv[1]);
break;
}
bt_emitter_mic_close();
break;
}
}
static void bt_emitter_mic_dec_out_stream_resume(void *p)
{
struct bt_emitter_mic_dec_hdl *dec = p;
audio_decoder_resume(&dec->pcm_dec.decoder);
}
int bt_emitter_mic_dec_start()
{
int err;
struct bt_emitter_mic_dec_hdl *dec = bt_emitter_mic_dec;
struct audio_mixer *p_mixer = &mixer;
if (!bt_emitter_mic_dec) {
return -EINVAL;
}
err = pcm_decoder_open(&dec->pcm_dec, &decode_task);
if (err) {
goto __err1;
}
bt_emitter_set_vol(app_var.music_volume);
audio_sbc_enc_reset_buf(1);
//
#if HOWLING_ENABLE
dec->p_howling_hdl = open_howling(NULL, dec->pcm_dec.sample_rate, 0, 1);
#endif
// 打开mic驱动
audio_adc_mic_open(&dec->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(&dec->mic_ch, dec->pcm_dec.sample_rate);
audio_adc_mic_set_gain(&dec->mic_ch, app_var.aec_mic_gain);
audio_adc_mic_set_buffs(&dec->mic_ch, dec->adc_buf,
ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM);
dec->adc_output.handler = adc_mic_output_handler;
audio_adc_add_output_handler(&adc_hdl, &dec->adc_output);
cbuf_init(&dec->cbuf, dec->pcm_buf, sizeof(dec->pcm_buf));
audio_adc_mic_start(&dec->mic_ch);
dec->mic_start = 1;
dec->skip_cnt = 30;
pcm_decoder_set_event_handler(&dec->pcm_dec, bt_emitter_mic_dec_event_handler, dec->id);
pcm_decoder_set_read_data(&dec->pcm_dec, bt_emitter_mic_dec_read, dec);
// 设置叠加功能
audio_mixer_ch_open_head(&dec->mix_ch, p_mixer);
struct audio_mixer_ch_sync_info info = {0};
info.priv = dec;
info.get_total = bt_emitter_mic_dec_total;
info.get_size = bt_emitter_mic_dec_size;
audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1);
// 数据流串联
struct audio_stream_entry *entries[8] = {NULL};
u8 entry_cnt = 0;
entries[entry_cnt++] = &dec->pcm_dec.decoder.entry;
entries[entry_cnt++] = &dec->mix_ch.entry;
dec->stream = audio_stream_open(dec, bt_emitter_mic_dec_out_stream_resume);
audio_stream_add_list(dec->stream, entries, entry_cnt);
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
dec->start = 1;
err = audio_decoder_start(&dec->pcm_dec.decoder);
if (err) {
goto __err3;
}
clock_set_cur();
return 0;
__err3:
dec->start = 0;
if (dec->mic_start) {
audio_adc_mic_close(&dec->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &dec->adc_output);
dec->mic_start = 0;
}
audio_mixer_ch_close(&dec->mix_ch);
if (dec->stream) {
audio_stream_close(dec->stream);
dec->stream = NULL;
}
pcm_decoder_close(&dec->pcm_dec);
__err1:
bt_emitter_mic_dec_relaese();
return err;
}
static void __bt_emitter_mic_dec_close(void)
{
if (bt_emitter_mic_dec && bt_emitter_mic_dec->start) {
bt_emitter_mic_dec->start = 0;
pcm_decoder_close(&bt_emitter_mic_dec->pcm_dec);
#if HOWLING_ENABLE
if (bt_emitter_mic_dec->p_howling_hdl) {
close_howling(bt_emitter_mic_dec->p_howling_hdl);
}
#endif
bt_emitter_mic_dec->mic_start = 0;
audio_adc_mic_close(&bt_emitter_mic_dec->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &bt_emitter_mic_dec->adc_output);
audio_mixer_ch_close(&bt_emitter_mic_dec->mix_ch);
if (bt_emitter_mic_dec->stream) {
audio_stream_close(bt_emitter_mic_dec->stream);
bt_emitter_mic_dec->stream = NULL;
}
}
}
static int bt_emitter_mic_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
log_i("bt_emitter_mic_wait_res_handler, event:%d\n", event);
if (event == AUDIO_RES_GET) {
// 启动解码
err = bt_emitter_mic_dec_start();
} else if (event == AUDIO_RES_PUT) {
// 被打断
__bt_emitter_mic_dec_close();
}
return err;
}
void bt_emitter_mic_close(void)
{
if (!bt_emitter_mic_dec) {
return;
}
__bt_emitter_mic_dec_close();
bt_emitter_mic_dec_relaese();
clock_set_cur();
log_i("bt_emitter_mic dec close \n\n ");
}
int bt_emitter_mic_open(void)
{
if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) {
return 0;
}
bt_emitter_mic_close();
int err;
struct bt_emitter_mic_dec_hdl *dec;
dec = zalloc(sizeof(*dec));
if (!dec) {
return -ENOMEM;
}
bt_emitter_mic_dec = dec;
dec->id = rand32();
dec->pcm_dec.ch_num = 1;
dec->pcm_dec.output_ch_num = audio_sbc_enc_get_channel_num();
dec->pcm_dec.sample_rate = audio_sbc_enc_get_rate();
if (dec->pcm_dec.output_ch_num == 2) {
dec->pcm_dec.output_ch_type = AUDIO_CH_LR;
} else {
dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF;
}
dec->wait.priority = 2;
dec->wait.preemption = 1;
dec->wait.handler = bt_emitter_mic_wait_res_handler;
clock_add(AUDIO_CODING_PCM);
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
return err;
}
void audio_sbc_enc_open_exit(void)
{
if (app_check_curr_task(APP_BT_TASK) == true) {
bt_emitter_mic_open();
}
}
void audio_sbc_enc_close_enter(void)
{
bt_emitter_mic_close();
}
//pin code 轮询功能
const char pin_code_list[10][4] = {
{'0', '0', '0', '0'},
{'1', '2', '3', '4'},
{'8', '8', '8', '8'},
{'1', '3', '1', '4'},
{'4', '3', '2', '1'},
{'1', '1', '1', '1'},
{'2', '2', '2', '2'},
{'3', '3', '3', '3'},
{'5', '6', '7', '8'},
{'5', '5', '5', '5'}
};
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射链接pincode 轮询
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
const char *bt_get_emitter_pin_code(u8 flag)
{
static u8 index_flag = 0;
int pincode_num = sizeof(pin_code_list) / sizeof(pin_code_list[0]);
if (flag == 1) {
//reset index
index_flag = 0;
} else if (flag == 2) {
//查询是否要开始继续回连尝试pin code。
if (index_flag >= pincode_num) {
//之前已经遍历完了
return NULL;
} else {
index_flag++; //准备使用下一个
}
} else {
log_debug("get pin code index %d\n", index_flag);
}
return &pin_code_list[index_flag][0];
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射链接保存远端设备名字
@param addr:远端设备地址
name:远端设备名字
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_save_remote_name(u8 *addr, u8 *name)
{
struct remote_name remote_n;
u16 id = CFG_REMOTE_DN_00;
while (1) {
syscfg_read(id, &remote_n, sizeof(struct remote_name));
if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) {
if (!memcmp(addr, remote_n.addr, 6)) {
return;
}
} else {
break;
}
id++;
if (id >= 20) {
break;
}
}
memset(&remote_n, 0, sizeof(struct remote_name));
memcpy(remote_n.addr, addr, 6);
memcpy(remote_n.name, name, strlen(name));
remote_n.crc = CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2);
syscfg_write(id, &remote_n, sizeof(struct remote_name));
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射通过地址来获取设备名字
@param addr:远端设备地址
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
u8 *emitter_get_remote_name(u8 *addr)
{
struct remote_name remote_n;
u16 id = CFG_REMOTE_DN_00;
while (1) {
syscfg_read(id, &remote_n, sizeof(struct remote_name));
if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) {
if (!memcmp(addr, remote_n.addr, 6)) {
return &remote_n.name;
}
} else {
break;
}
id++;
if (id >= 20) {
break;
}
}
return NULL;
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射通过地址来删除vm的设备名字
@param addr:远端设备地址
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_delete_remote_name(u8 *addr)
{
struct remote_name remote_n;
u16 id = CFG_REMOTE_DN_00;
while (1) {
syscfg_read(id, &remote_n, sizeof(struct remote_name));
if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) {
if (!memcmp(addr, remote_n.addr, 6)) {
memset(&remote_n, 0xff, sizeof(struct remote_name));
syscfg_write(id, &remote_n, sizeof(struct remote_name));
return;
}
}
id++;
}
}
#define BD_ADDR_LEN 6
typedef uint8_t bd_addr_t[BD_ADDR_LEN];
static bd_addr_t remote_addr[20];
extern u8 restore_remote_device_info_opt(bd_addr_t *mac_addr, u8 conn_device_num, u8 id);
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙发射获取vm设备记忆
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void emitter_get_vm_device()
{
memset(remote_addr, 0, sizeof(remote_addr));
u8 flag = restore_remote_device_info_opt(&remote_addr, 20, get_remote_dev_info_index());
for (u8 i = 0; i < 20; i++) {
log_debug("----- \n");
log_debug_hexdump(remote_addr[i], 6);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙 开关ag_a2dp
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void bredr_ag_a2dp_open_and_close()
{
if (get_emitter_curr_channel_state() & A2DP_SRC_CH) {
puts("start to disconnect a2dp ");
user_emitter_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL);
} else {
puts("start to connect a2dp ");
user_emitter_cmd_prepare(USER_CTRL_CONN_A2DP, 0, NULL);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 蓝牙 开关ag_hfp
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void bredr_ag_hfp_open_and_close()
{
if (get_emitter_curr_channel_state() & HFP_AG_CH) {
puts("start to disconnect HFP ");
user_emitter_cmd_prepare(USER_CTRL_HFP_DISCONNECT, 0, NULL);
} else {
puts("start to connect HFP ");
user_emitter_cmd_prepare(USER_CTRL_HFP_CMD_BEGIN, 0, NULL);
}
}
#else
void emitter_media_source(u8 *addr, u8 source, u8 en)
{
}
void emitter_or_receiver_switch(u8 flag)
{
}
u8 bt_search_status()
{
return 0;
}
#endif
#endif