This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
@@ -0,0 +1,471 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_browser.data.bss")
#pragma data_seg(".rcsp_browser.data")
#pragma const_seg(".rcsp_browser.text.const")
#pragma code_seg(".rcsp_browser.text")
#endif
#include "rcsp_browser.h"
#include "app_config.h"
#include "rcsp.h"
#include "dev_manager.h"
#include "file_operate/file_bs_deal.h"
#include "rcsp_event.h"
#include "ble_rcsp_server.h"
#include "JL_rcsp_api.h"
#include "rcsp_functions/rcsp_config.h"
#if RCSP_MODE && RCSP_FILE_OPT
#include "music/music_player.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[browser]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define FILE_BROWSE_BUF_LEN 250//要小于RCSP MTU, 不要随意改大
#define FILE_BROWSE_NAME_MAX_LIMIT 128//限制最大文件夹名称大小
#define FILE_BROWSE_TASK_NAME "rcsp_file_bs"
#if defined(CONFIG_FAT_MAX_DEEPTH) && (CONFIG_FAT_MAX_DEEPTH > 0)
#define MAX_DEEPTH CONFIG_FAT_MAX_DEEPTH
#else
#define MAX_DEEPTH 9/* 0~9 deepth of system */
#endif
typedef enum {
RCSPBrowserObjectTypeFolder = 0,
RCSPBrowserObjectTypeFile,
} RCSPBrowserObjectType;
typedef enum {
RCSPBrowserFileDataFormatUnicode = 0,
RCSPBrowserFileDataFormatANSI,
} RCSPBrowserFileDataFormat;
static const char *dev_logo[] = {
[RCSPDevMapUDISK] = "udisk0",
[RCSPDevMapSD0] = "sd0",
[RCSPDevMapSD1] = "sd1",
#if TCFG_NANDFLASH_UI_FAT_ENABLE
[RCSPDevMapFLASH] = TCFG_NANDFLASH_UI_FAT_LOGO,
#else
[RCSPDevMapFLASH] = "virfat_flash",
#endif
[RCSPDevMapFLASH_2] = "fat_nor",
#ifdef TCFG_NANDFLASH_FAT_ROOT
[RCSPDevMapNANDFLASH] = TCFG_NANDFLASH_FAT_ROOT,
#else
[RCSPDevMapNANDFLASH] = "NULL",
#endif
};
#pragma pack(1)
struct __browser {
u8 path_type;///
u8 read_file_num;
u16 start_num;
u32 dev_handle;
u16 path_len;
u32 path_clust[MAX_DEEPTH];
};
#if (defined TCFG_NANDFLASH_DEV_ENABLE && TCFG_NANDFLASH_DEV_ENABLE)
struct JL_FILE_DATA {
u8 type : 1;
u8 format : 1;
u8 device : 5;
u8 reserve : 1;
u32 clust;
u16 file_num;
u8 name_len;
u8 file_data[0];
};
#else
struct JL_FILE_DATA {
u8 type : 1;
u8 format : 1;
u8 device : 3;
u8 reserve : 3;
u32 clust;
u16 file_num;
u8 name_len;
u8 file_data[0];
};
#endif
#pragma pack()
static const char dec_file_ext[][3] = {
#if (WATCH_FILE_TO_FLASH)
{"ALL"},
{'\0'},
#else // WATCH_FILE_TO_FLASH
#if (TCFG_DEC_MP3_ENABLE)
{"MP1"},
{"MP2"},
{"MP3"},
#endif
#if (TCFG_DEC_WMA_ENABLE)
{"WMA"},
#endif
#if (TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE)
{"WAV"},
#endif
#if (TCFG_DEC_FLAC_ENABLE)
{"FLA"},
#endif
#if (TCFG_DEC_APE_ENABLE)
{"APE"},
#endif
#if (TCFG_DEC_DECRYPT_ENABLE)
{"SMP"},
#endif
#if (TCFG_DEC_AMR_ENABLE)
{"AMR"},
#endif
#if (TCFG_DEC_M4A_ENABLE)
{"M4A"},
{"AAC"},
#endif
#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE)
{"MP4"},
#endif
{"TMP"},
{'\0'},
#endif // WATCH_FILE_TO_FLASH
};
static struct __browser *browser = NULL;
//rcsp获取文件浏览后缀配置
char *rcsp_browser_file_ext(void)
{
return (char *)dec_file_ext;
}
//rcsp获取文件浏览后缀配置数据长度
u16 rcsp_browser_file_ext_size(void)
{
return strlen((const char *)dec_file_ext);
}
//rcsp浏览设备映射
char *rcsp_browser_dev_remap(RCSPDevMap index)
{
if (index >= RCSPDevMapMax) {
return NULL;
}
return (char *)dev_logo[index];
}
//rcsp限制文件名长度(包括文件夹,如:xxx~~~, 省略以"~~~"表示)
u16 rcsp_file_name_cut(u8 *name, u16 len, u16 len_limit)
{
u8 ex_type[8];
u8 three_point_hex[] = {0x2E, 0x00, 0x2E, 0x00, 0x2E, 0x00}; //... 显示unicode码
if (len > len_limit) {
memcpy(name + len_limit - sizeof(three_point_hex), three_point_hex, sizeof(three_point_hex));
return len_limit;
}
return len;
}
static bool browser_get_dir_info(FILE_BS_DEAL *fil_bs, u8 *path_buf, u16 len, RCSPBrowserObjectType type, void *ptr)
{
s16 ret = 0;
u16 i, j = 0;
u32 deep_clust = 0;
FS_DIR_INFO dir_info;
//open root
ret = file_bs_entern_dir(fil_bs, NULL);
if (ret == 0) {
goto end;
}
if (len == 4 && type == RCSPBrowserObjectTypeFolder) {
/* log_info("root deep\n"); */
if (ptr) {
*((u32 *)ptr) = ret;
}
goto end;
} else if (len == 4 && type == RCSPBrowserObjectTypeFile) {
/* log_info("play file path\n"); */
memcpy((u8 *)&deep_clust, path_buf, 4);
deep_clust = app_ntohl(deep_clust);
if (ptr) {
*((u32 *)ptr) = deep_clust;
}
goto end;
}
//deep check
u8 deep = len / 4;
if (deep > MAX_DEEPTH) {
log_error("deep err : %d\n", deep);
return false;
}
/* log_info("get deep%d data\n", deep - 1); */
for (i = 1; i < deep; i++) {
memcpy((u8 *)&deep_clust, path_buf + 4 * i, 4);
deep_clust = app_ntohl(deep_clust);
/* log_info("deep_clust:%x\n", deep_clust); */
for (j = 1; j < ret + 1; j++) {
file_bs_get_dir_info(fil_bs, &dir_info, j, 1);
if (dir_info.sclust == deep_clust) {
break;
}
}
if (i < deep - 1) {
ret = file_bs_entern_dir(fil_bs, &dir_info);
if (ret == 0) {
goto end;
}
}
}
if (type == RCSPBrowserObjectTypeFile) {
if (ptr) {
*((u32 *)ptr) = dir_info.sclust; //file return clust
}
goto end;
} else {
ret = file_bs_entern_dir(fil_bs, &dir_info);
if (ret == 0) {
goto end;
}
if (ptr) {
*((u32 *)ptr) = ret; //file return clust
}
}
end:
return true;
}
static u32 browse_open_dir(FILE_BS_DEAL *fil_bs, u8 *path_buf, u16 len)
{
u32 file_cnt = 0;
browser_get_dir_info(fil_bs, path_buf, len, RCSPBrowserObjectTypeFolder, (void *)&file_cnt);
return file_cnt;
}
static void file_printf_dir(FS_DIR_INFO *dir_inf, u8 cnt)
{
u8 i;
LONG_FILE_NAME *l_name_pt;
for (i = 0; i < cnt; i++) {
/* log_info("file type %d nt:%d clust %x \n", dir_inf[i].dir_type, dir_inf[i].fn_type, dir_inf[i].sclust); */
l_name_pt = &dir_inf[i].lfn_buf;
if (dir_inf[i].fn_type == BS_FNAME_TYPE_SHORT) {
file_comm_display_83name((void *)&l_name_pt->lfn[32], (void *)l_name_pt->lfn);
strcpy(l_name_pt->lfn, &l_name_pt->lfn[32]);
l_name_pt->lfn_cnt = strlen(l_name_pt->lfn);
log_info("%s\n", l_name_pt->lfn);
} else {
if (l_name_pt->lfn_cnt > 510) {
l_name_pt->lfn_cnt = 510;
log_error("***get long name err!!!");
}
l_name_pt->lfn_cnt = file_comm_long_name_fix((void *)l_name_pt->lfn, l_name_pt->lfn_cnt);
l_name_pt->lfn[l_name_pt->lfn_cnt] = 0;
l_name_pt->lfn[l_name_pt->lfn_cnt + 1] = 0;
/* log_info("file name len : %d \n", l_name_pt->lfn_cnt); */
/* log_info_hexdump((u8 *)l_name_pt->lfn, l_name_pt->lfn_cnt); */
}
}
}
static u16 add_one_iterm_to_sendbuf(u8 *dest, u16 max_buf_len, u16 offset, FS_DIR_INFO *p_dir_info, u16 file_cnt, u8 dev_type)
{
struct JL_FILE_DATA file_data;
memset((u8 *)&file_data, 0, sizeof(struct JL_FILE_DATA));
file_data.type = p_dir_info->dir_type;
if (p_dir_info->fn_type == BS_FNAME_TYPE_SHORT) {
file_data.format = RCSPBrowserFileDataFormatANSI;
} else {
file_data.format = RCSPBrowserFileDataFormatUnicode;
}
///限制文件名长度
p_dir_info->lfn_buf.lfn_cnt = rcsp_file_name_cut((u8 *)p_dir_info->lfn_buf.lfn, p_dir_info->lfn_buf.lfn_cnt, FILE_BROWSE_NAME_MAX_LIMIT);
file_data.device = dev_type;
file_data.clust = app_htonl(p_dir_info->sclust);
file_data.file_num = app_htons(file_cnt);
file_data.name_len = p_dir_info->lfn_buf.lfn_cnt;
memcpy(dest + offset, (u8 *)&file_data, sizeof(struct JL_FILE_DATA));
memcpy(dest + offset + sizeof(struct JL_FILE_DATA), (u8 *)p_dir_info->lfn_buf.lfn, p_dir_info->lfn_buf.lfn_cnt);
/* log_info("add send data:"); */
/* log_info_hexdump(dest+offset,p_dir_info->lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA)); */
return (p_dir_info->lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA));
}
static void rcsp_browser_task(void *p)
{
u8 reason = 0;
u32 play_file_clust = 0;
FS_DIR_INFO dir_info;
FILE_BS_DEAL fil_bs;
u8 *path_data = NULL;
memset((u8 *)&dir_info, 0, sizeof(FS_DIR_INFO));
memset((u8 *)&fil_bs, 0, sizeof(FILE_BS_DEAL));
fil_bs.dev = dev_manager_find_spec(rcsp_browser_dev_remap(browser->dev_handle), 0);
if (fil_bs.dev == NULL) {
reason = 1;
log_error("dev nofound!!!\n");
goto _EXIT;
}
file_bs_open_handle(&fil_bs, (u8 *)rcsp_browser_file_ext());
u32 dir_file_cnt = browse_open_dir(&fil_bs, (u8 *)browser->path_clust, browser->path_len);
if (browser->start_num + browser->read_file_num >= dir_file_cnt) {
log_error("file range err\n");
reason = 1;
browser->read_file_num = dir_file_cnt - browser->start_num + 1;
}
/* log_info("start num:%d read file num:%d\n", browser->start_num, browser->read_file_num); */
u16 offset = 0;
u32 ret = 0;
path_data = (u8 *)zalloc(FILE_BROWSE_BUF_LEN);
if (path_data == NULL) {
reason = 1;
log_error("no ram for path_data!! \n");
goto _EXIT;
}
for (int i = browser->start_num ; i < (browser->start_num + browser->read_file_num); i++) {
ret = file_bs_get_dir_info(&fil_bs, &dir_info, i, 1);
if (!ret) {
break;
}
file_printf_dir(&dir_info, 1);
if (offset && ((offset + dir_info.lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA)) > FILE_BROWSE_BUF_LEN)) {
///如果buf不够填充了, 先将数据发送了先,再重新填充
ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_FILE_BROWSE_REQUEST_START, path_data, offset, JL_NOT_NEED_RESPOND, 0, NULL);
if (ret) {
log_error("send data err: %d, %d\n", ret, offset);
goto _EXIT;
}
//reset send buf
offset = 0;
memset(path_data, 0, FILE_BROWSE_BUF_LEN);
offset += add_one_iterm_to_sendbuf(path_data, FILE_BROWSE_BUF_LEN, offset, &dir_info, i, browser->dev_handle);
} else {
offset += add_one_iterm_to_sendbuf(path_data, FILE_BROWSE_BUF_LEN, offset, &dir_info, i, browser->dev_handle);
}
}
//send last package
if (offset) {
ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_FILE_BROWSE_REQUEST_START, path_data, offset, JL_NOT_NEED_RESPOND, 0, NULL);
if (ret) {
log_error("send data err: %d\n", ret);
goto _EXIT;
}
}
_EXIT:
file_bs_close_handle(&fil_bs);
if (path_data) {
free(path_data);
}
rcsp_msg_post(
USER_MSG_RCSP_BS_END,
4,
(int)rcsp_handle_get(),
(int)reason,
(int)rcsp_browser_dev_remap(browser->dev_handle),
(int)play_file_clust);
while (1) {
os_time_dly(10);
}
}
//rcsp文件浏览开始
void rcsp_browser_start(u8 *data, u16 len)
{
///检查数据是否有效
log_info("%s\n", __func__);
if (len > sizeof(struct __browser)) {
return ;
}
///创建数据解析句柄
browser = (struct __browser *)zalloc(sizeof(struct __browser));
if (browser == NULL) {
return ;
}
///解析数据
memcpy((u8 *)browser, data, sizeof(struct __browser));
browser->start_num = app_ntohs(browser->start_num);
browser->dev_handle = app_ntohl(browser->dev_handle);
browser->path_len = app_ntohs(browser->path_len);
///检查设备范围
if (browser->dev_handle >= RCSPDevMapMax) {
log_error("bs dev hdl err !!\n");
free(browser);
browser = NULL;
return ;
}
///检查是否是已经选定好文件播放
if (browser->path_type) {
u8 reason = 2;
u32 play_file_clust = app_ntohl(browser->path_clust[0]);
rcsp_msg_post(
USER_MSG_RCSP_BS_END,
4,
(int)rcsp_handle_get(),
(int)reason,
(int)rcsp_browser_dev_remap(browser->dev_handle),
(int)play_file_clust);
return ;
}
///目录浏览线程创建
if (task_create(rcsp_browser_task, (void *)NULL, FILE_BROWSE_TASK_NAME)) {
free(browser);
browser = NULL;
log_error("rcsp_browser_task creat fail\n");
}
}
//rcsp文件浏览繁忙查询
bool rcsp_browser_busy(void)
{
if (browser) {
return false;
} else {
return true;
}
}
//rcsp文件浏览停止
void rcsp_browser_stop(void)
{
///删除线程,释放资源
task_kill(FILE_BROWSE_TASK_NAME);
if (browser) {
free(browser);
browser = NULL;
}
}
#endif
@@ -0,0 +1,35 @@
#ifndef __RCSP_BROWSER_H__
#define __RCSP_BROWSER_H__
#include "typedef.h"
#include "app_config.h"
///rcsp 对应的设备id枚举
typedef enum {
RCSPDevMapUDISK = 0,
RCSPDevMapSD0,
RCSPDevMapSD1,
RCSPDevMapFLASH,
RCSPDevMapAUX,
RCSPDevMapFLASH_2,
RCSPDevMapNANDFLASH,
RCSPDevMapMax,
} RCSPDevMap;
//rcsp浏览设备映射
char *rcsp_browser_dev_remap(RCSPDevMap index);
//rcsp获取文件浏览后缀配置
char *rcsp_browser_file_ext(void);
//rcsp获取文件浏览后缀配置数据长度
u16 rcsp_browser_file_ext_size(void);
//rcsp限制文件名长度(包括文件夹,如:xxx~~~, 省略以"~~~"表示)
u16 rcsp_file_name_cut(u8 *name, u16 len, u16 len_limit);
//rcsp文件浏览开始
void rcsp_browser_start(u8 *data, u16 len);
//rcsp文件浏览停止
void rcsp_browser_stop(void);
//rcsp文件浏览繁忙查询
bool rcsp_browser_busy(void);
#endif // __RCSP_BROWSER_H__
@@ -0,0 +1,107 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_bt_func.data.bss")
#pragma data_seg(".rcsp_bt_func.data")
#pragma const_seg(".rcsp_bt_func.text.const")
#pragma code_seg(".rcsp_bt_func.text")
#endif
#include "rcsp_bt_func.h"
#include "rcsp_device_info_func_common.h"
#include "rcsp_device_status.h"
#include "rcsp_config.h"
#include "rcsp_event.h"
#include "app_action.h"
#include "ble_rcsp_server.h"
#include "rcsp_music_info_setting.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_attr.h"
#if (RCSP_MODE)
// 后续需要全部从JL_rcsp_protocol.h中拷贝出来
#define BT_INFO_ATTR_MUSIC_TITLE (0)
#define BT_INFO_ATTR_MUSIC_ARTIST (1)
#define BT_INFO_ATTR_MUSIC_ALBUM (2)
#define BT_INFO_ATTR_MUSIC_NUMBER (3)
#define BT_INFO_ATTR_MUSIC_TOTAL (4)
#define BT_INFO_ATTR_MUSIC_GENRE (5)
#define BT_INFO_ATTR_MUSIC_TIME (6)
#define BT_INFO_ATTR_MUSIC_STATE (7)
#define BT_INFO_ATTR_MUSIC_CURR_TIME (8)
#define BT_INFO_ATTR_IRK (0x0A)
typedef uint8_t sm_key_t[16];
extern bool sm_get_local_irk(sm_key_t irk);
extern bool ble_vendor_random_address_generate(u8 *address, u8 type);
//设置固件bt行为
bool rcsp_bt_func_set(void *priv, u8 *data, u16 len)
{
#if RCSP_ADV_MUSIC_INFO_ENABLE
music_info_cmd_handle(data, len);
#endif
return true;
}
//获取固件bt信息
u32 rcsp_bt_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
u16 offset = 0;
#if RCSP_ADV_MUSIC_INFO_ENABLE
u8 player_time[4];
if (mask & BIT(BT_INFO_ATTR_MUSIC_TITLE)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TITLE, (u8 *)get_music_title(), get_music_title_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_ARTIST)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_ARTIST, (u8 *)get_music_artist(), get_music_artist_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_ALBUM)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_ALBUM, (u8 *)get_music_album(), get_music_album_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_NUMBER)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_NUMBER, (u8 *)get_music_number(), get_music_number_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_TOTAL)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TOTAL, (u8 *)get_music_total(), get_music_total_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_GENRE)) {
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_GENRE, (u8 *)get_music_genre(), get_music_genre_len());
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_TIME)) {
u16 music_sec = get_music_total_time();
player_time[0] = music_sec >> 8;
player_time[1] = music_sec;
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TIME, player_time, 2);
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_STATE)) {
//printf("\n music state\n");
u8 music_state = get_music_player_state();
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_STATE, &music_state, 1);
}
if (mask & BIT(BT_INFO_ATTR_MUSIC_CURR_TIME)) {
//printf("\nmusic curr time\n");
u32 curr_music_sec = get_music_curr_time();
player_time[0] = curr_music_sec >> 24;
player_time[1] = curr_music_sec >> 16;
player_time[2] = curr_music_sec >> 8;
player_time[3] = curr_music_sec;
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_CURR_TIME, player_time, 4);
}
#endif
#if CONFIG_USE_RANDOM_ADDRESS_ENABLE
if (mask & BIT(BT_INFO_ATTR_IRK)) {
u8 irk_flag = 0;
sm_key_t irk;
irk_flag = sm_get_local_irk(irk);
u8 irk_reponse[18];
irk_reponse[0] = irk_flag;
irk_reponse[1] = irk_flag ? 16 : 0;
memcpy(irk_reponse + 2, irk, 16);
offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_IRK, irk_reponse, irk_flag ? 18 : 2);
}
#endif
return offset;
}
#endif
@@ -0,0 +1,5 @@
#ifndef __RCSP_BT_FUNC_H__
#define __RCSP_BT_FUNC_H__
#include "typedef.h"
#include "app_config.h"
#endif
@@ -0,0 +1,34 @@
#ifndef __RCSP_DEVICE_INFO_CMD_COMMON_H__
#define __RCSP_DEVICE_INFO_CMD_COMMON_H__
//设置固件fm行为
bool rcsp_fm_func_set(void *priv, u8 *data, u16 len);
//获取固件fm信息
u32 rcsp_fm_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask);
//设置固件rtc行为
bool rcsp_rtc_func_set(void *priv, u8 *data, u16 len);
//获取固件rtc信息
u32 rcsp_rtc_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask);
//rtc消息处理
void rcsp_rtc_msg_deal(int msg);
//获取固件播放器信息
u32 rcsp_music_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask);
//设置固件播放器行为
bool rcsp_music_func_set(void *priv, u8 *data, u16 len);
//停止音乐功能
void rcsp_music_func_stop(void);
//设置固件bt行为
bool rcsp_bt_func_set(void *priv, u8 *data, u16 len);
//获取固件bt信息
u32 rcsp_bt_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask);
//设置固件linein行为
bool rcsp_linein_func_set(void *priv, u8 *data, u16 len);
//获取固件linein信息
u32 rcsp_linein_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask);
//停止linein功能
void rcsp_linein_func_stop(void);
#endif
@@ -0,0 +1,269 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_fm_func.data.bss")
#pragma data_seg(".rcsp_fm_func.data")
#pragma const_seg(".rcsp_fm_func.text.const")
#pragma code_seg(".rcsp_fm_func.text")
#endif
#include "rcsp_fm_func.h"
#include "rcsp_device_info_func_common.h"
#include "rcsp_device_status.h"
#include "rcsp_config.h"
#include "rcsp_event.h"
#include "app_action.h"
#include "key_event_deal.h"
#include "rcsp_functions/rcsp_config.h"
#if (RCSP_MODE && TCFG_APP_FM_EN)
#include "fm_api.h"
#include "fm_rw.h"
#pragma pack(1)
struct _FM_STATUS_INFO {
u8 status;
u8 cur_channel;
u16 cur_fre;
u8 mode;
};
#pragma pack()
#define FM_INFO_ATTR_STATUS (0)
#define FM_INFO_ATTR_FRE (1)
#define SCANE_ALL (0x01)
#define SCANE_DOWN (0x02)
#define SCANE_UP (0x03)
enum {
FM_FUNC_MUSIC_PP = 0x1,
FM_FUNC_PREV_FREQ,
FM_FUNC_NEXT_FREQ,
FM_FUNC_PREV_STATION,
FM_FUNC_NEXT_STATION,
FM_FUNC_SCAN,
FM_FUNC_SET_STATION,
FM_FUNC_DEL_STATION,
FM_FUNC_SET_FRE,
FM_FUNC_DEL_FRE,
};
enum {
FM_FUNC_SCAN_ALL = 0x0,
FM_FUNC_SCAN_ALL_DOWN,
FM_FUNC_SCAN_ALL_UP,
FM_FUNC_SCAN_STOP,
};
enum {
FM_FUNC_STATUS_PLAY = 0x01,
FM_FUNC_STATUS_PAUSE,
FM_FUNC_STATUS_SCANING,
};
static u8 fm_get_status(u8 scan_all_en)
{
extern u8 fm_get_scan_flag(void);
extern u8 fm_get_fm_dev_mute(void);
u8 scan_flag = fm_get_scan_flag();
u8 fm_dev_mute = fm_get_fm_dev_mute();
if (SCANE_DOWN == scan_flag || SCANE_UP == scan_flag) {
return FM_FUNC_STATUS_SCANING;
} else if (SCANE_ALL == scan_flag) {
if (scan_all_en && 0 == fm_dev_mute) {
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
}
return FM_FUNC_STATUS_SCANING;
} else if (0 == fm_dev_mute) {
return FM_FUNC_STATUS_PLAY;
} else {
return FM_FUNC_STATUS_PAUSE;
}
}
static u16 fm_scan_timer = 0;
static void fm_scan_state_func(void *priv)
{
/* printf("fm_scan_state_func\n"); */
if (FM_FUNC_STATUS_SCANING == fm_get_status(1)) {
return;
}
if (fm_scan_timer) {
sys_hi_timer_del(fm_scan_timer);
fm_scan_timer = 0;
}
// 更新
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
}
bool rcsp_fm_func_set(void *priv, u8 *data, u16 len)
{
/* printf("rcsp_fm_func_set\n"); */
/* put_buf(data, len); */
u8 fun_cmd = data[0];
u16 cmd_param = 0;
u16 param_len = len - 1;
switch (fun_cmd) {
case FM_FUNC_MUSIC_PP:
printf("fm pp\n");
fm_volume_pp();
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
break;
case FM_FUNC_PREV_FREQ:
printf("fm prev fre\n");
fm_prev_freq();
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
break;
case FM_FUNC_NEXT_FREQ:
printf("fm next fre\n");
fm_next_freq();
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
break;
case FM_FUNC_PREV_STATION:
printf("fm prev station\n");
fm_prev_station();
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
break;
case FM_FUNC_NEXT_STATION:
printf("fm next station\n");
fm_next_station();
rcsp_device_status_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE));
break;
case FM_FUNC_SCAN:
printf("fm scan\n");
if (1 == param_len) {
cmd_param = data[1];
switch (cmd_param) {
case FM_FUNC_SCAN_ALL:
printf("fm scan all\n");
fm_scan_all();
break;
case FM_FUNC_SCAN_ALL_DOWN:
printf("fm scan prev\n");
fm_scan_up();
break;
case FM_FUNC_SCAN_ALL_UP:
printf("fm scan next\n");
fm_scan_down();
break;
case FM_FUNC_SCAN_STOP:
printf("fm scan stop\n");
if (FM_FUNC_STATUS_SCANING == fm_get_status(0)) {
fm_scan_stop();
}
break;
default:
printf("fm scan default\n");
break;
}
if (0 == fm_scan_timer) {
fm_scan_timer = sys_hi_timer_add(NULL, fm_scan_state_func, 1000);
}
}
break;
case FM_FUNC_SET_STATION:
printf("fm sel station\n");
extern void fm_sel_station(u8 channel);
if (1 == param_len) {
cmd_param = data[1];
fm_sel_station(cmd_param);
}
break;
case FM_FUNC_DEL_STATION:
printf("fm del station\n");
break;
case FM_FUNC_SET_FRE:
printf("fm sel fre\n");
extern u8 fm_set_fre(u16 fre);
printf("param_len : %d\n", param_len);
for (u8 i = 0; i < param_len; i++) {
printf("data[%d] : 0x%x\n", i, data[i + 1]);
}
if (2 == param_len) {
cmd_param = (data[1] << 8 | data[2]) * 10;
printf("fm target = %d\n", cmd_param);
fm_set_fre(cmd_param);
}
break;
case FM_FUNC_DEL_FRE:
printf("fm del ...\n");
break;
default:
break;
}
switch (fun_cmd) {
case FM_FUNC_SET_FRE:
case FM_FUNC_SET_STATION:
// 更新状态
rcsp_msg_post(USER_MSG_RCSP_FM_UPDATE_STATE, 1, (int)priv);
break;
}
return true;
}
//获取固件fm信息
u32 rcsp_fm_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
u16 offset = 0;
if (mask & BIT(FM_INFO_ATTR_STATUS)) {
extern u8 fm_get_cur_channel(void);
extern u16 fm_get_cur_fre(void);
extern u8 fm_get_mode(void);
struct _FM_STATUS_INFO fm_status_info;
u16 fre = fm_get_cur_fre();
fre = app_htons(fre);
fm_status_info.cur_fre = fre;
fm_status_info.cur_channel = fm_get_cur_channel();
fm_status_info.status = fm_get_status(0);
if (FM_FUNC_STATUS_PLAY != fm_status_info.status) {
fm_status_info.status = 0;
}
fm_status_info.mode = fm_get_mode();
/* printf("rcsp_fm_func_get, %d, %d, %d, %d\n", fm_status_info.cur_fre, fm_status_info.cur_channel, fm_status_info.status, fm_status_info.mode); */
offset = add_one_attr(buf, buf_size, offset, FM_INFO_ATTR_STATUS, (u8 *)&fm_status_info, sizeof(fm_status_info));
}
if (mask & BIT(FM_INFO_ATTR_FRE)) {
FM_INFO fm_info = {0};
fm_read_info(&fm_info);
/* printf("get_fm_channel_fre_info:\n"); */
/* put_buf(&fm_info, sizeof(fm_info)); */
u8 fm_info_size = fm_info.total_chanel * 3 + 1;
u8 *fm_fre_info = zalloc(fm_info_size);
if (fm_fre_info) {
u8 *ptr = fm_fre_info;
u16 fm_fre = 0;
u8 total = 1;
u8 i;
u8 k;
*ptr++ = fm_info.total_chanel;
for (i = 0; i < (MEM_FM_LEN); i++) {
for (k = 0; k < 8; k++) {
if (fm_info.dat[i] & BIT(k)) {
fm_fre = i * 8 + k + 874;
fm_fre = app_htons(fm_fre);
*ptr++ = total++;
memcpy(ptr, &fm_fre, sizeof(fm_fre));
ptr += 2;
}
}
}
offset += add_one_attr(buf, buf_size, offset, FM_INFO_ATTR_FRE, fm_fre_info, fm_info_size);
free(fm_fre_info);
}
}
return offset;
}
void rcsp_fm_msg_deal(int msg)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
}
#endif
@@ -0,0 +1,5 @@
#ifndef __RCSP_FM_FUNC_H__
#define __RCSP_FM_FUNC_H__
#include "typedef.h"
#include "app_config.h"
#endif
@@ -0,0 +1,59 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_linein_func.data.bss")
#pragma data_seg(".rcsp_linein_func.data")
#pragma const_seg(".rcsp_linein_func.text.const")
#pragma code_seg(".rcsp_linein_func.text")
#endif
#include "rcsp_linein_func.h"
#include "rcsp_device_info_func_common.h"
#include "rcsp_device_status.h"
#include "rcsp_config.h"
#include "rcsp_event.h"
#include "app_action.h"
#include "app_msg.h"
#include "key_event_deal.h"
#include "tone_player.h"
#if RCSP_MODE && TCFG_APP_LINEIN_EN && !SOUNDCARD_ENABLE
#include "linein.h"
#define LINEIN_INFO_ATTR_STATUS (0)
//设置固件linein行为
bool rcsp_linein_func_set(void *priv, u8 *data, u16 len)
{
if (0 != linein_get_status()) {
return true;
}
return true;
}
//获取固件linein信息
u32 rcsp_linein_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
u16 offset = 0;
if (mask & BIT(LINEIN_INFO_ATTR_STATUS)) {
u8 status = linein_get_status();
offset = add_one_attr(buf, buf_size, offset, LINEIN_INFO_ATTR_STATUS, (u8 *)&status, sizeof(status));
}
return offset;
}
void rcsp_linein_msg_deal(int msg, u8 ret)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
}
//停止linein功能
void rcsp_linein_func_stop(void)
{
#if RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL
if (linein_get_status()) {
app_task_put_key_msg(KEY_MUSIC_PP, 0);
}
#endif
}
#endif
@@ -0,0 +1,5 @@
#ifndef __RCSP_LINEIN_FUNC_H__
#define __RCSP_LINEIN_FUNC_H__
#include "typedef.h"
#include "app_config.h"
#endif
@@ -0,0 +1,181 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_music_func.data.bss")
#pragma data_seg(".rcsp_music_func.data")
#pragma const_seg(".rcsp_music_func.text.const")
#pragma code_seg(".rcsp_music_func.text")
#endif
#include "rcsp_music_func.h"
#include "rcsp_device_info_func_common.h"
#include "rcsp.h"
#include "app_task.h"
#include "rcsp_device_status.h"
#include "rcsp_config.h"
#include "key_event_deal.h"
#include "JL_rcsp_attr.h"
#include "JL_rcsp_api.h"
#include "music/music_player.h"
#if (RCSP_MODE && TCFG_APP_MUSIC_EN)
#define MUSIC_INFO_ATTR_STATUS (0)
#define MUSIC_INFO_ATTR_FILE_NAME (1)
#define MUSIC_INFO_ATTR_FILE_PLAY_MODE (2)
#pragma pack(1)
struct _MUSIC_STATUS_info {
u8 status;
u32 cur_time;
u32 total_time;
u8 cur_dev;
};
#pragma pack()
enum {
MUSIC_FUNC_PP = 0x1,
MUSIC_FUNC_PREV,
MUSIC_FUNC_NEXT,
MUSIC_FUNC_MODE,
MUSIC_FUNC_EQ_MODE,
MUSIC_FUNC_REWIND,
MUSIC_FUNC_FAST_FORWORD,
};
enum {
REPEAT_MODE_ALL = 0x1,
REPEAT_MODE_DEV,
REPEAT_MODE_ONE,
REPEAT_MODE_RANDOM,
REPEAT_MODE_FOLDER,
};
const u8 rcsp_repeat_mode_remap[] = {
[FCYCLE_ALL] = REPEAT_MODE_ALL,
[FCYCLE_ONE] = REPEAT_MODE_ONE,
[FCYCLE_FOLDER] = REPEAT_MODE_FOLDER,
[FCYCLE_RANDOM] = REPEAT_MODE_RANDOM,
};
#define RCSP_MUSIC_FILE_NAME_MAX_LIMIT (128)
// 本文件内用到
static u8 music_func_add_one_attr_ex(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size, u8 att_size)
{
if (offset + size + 2 > max_len) {
printf("add attr err\n");
return 0;
}
buf[offset] = att_size + 1;
buf[offset + 1] = type;
memcpy(&buf[offset + 2], data, size);
return size + 2;
}
// 本文件内用到
static u8 mucis_func_add_one_attr_continue(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size)
{
if ((offset + size) > max_len) {
printf("add attr err 2\n");
return 0;
}
memcpy(&buf[offset], data, size);
return size;
}
//获取固件播放器信息
u32 rcsp_music_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
u16 offset = 0;
#if (TCFG_APP_MUSIC_EN && !RCSP_APP_MUSIC_EN)
u8 app = app_get_curr_task();
if (app != APP_MUSIC_TASK) {
return 0;
}
///获取当前播放状态
struct RcspModel *rcspModel = (struct RcspModel *) priv;
extern struct __music music_hdl;
FILE *file = music_hdl.player_hd->file;
if (mask & BIT(MUSIC_INFO_ATTR_STATUS)) {
/* printf("MUSIC_INFO_ATTR_STATUS\n"); */
struct _MUSIC_STATUS_info music_info;
// RCSP TODO:
printf("RCSP TODO!!!");
music_info.status = 0;
music_info.cur_time = 0;//app_htonl(file_dec_get_cur_time());
music_info.total_time = 60;//app_htonl(file_dec_get_total_time());
char *logo = dev_manager_get_logo(dev_manager_find_active(1));
char *tmp = NULL;
if (logo) {
for (int i = 0; i < RCSPDevMapMax; i++) {
tmp = rcsp_browser_dev_remap(i);
if (tmp && strcmp(tmp, logo) == 0) {
music_info.cur_dev = i;
offset += add_one_attr(buf, buf_size, offset, MUSIC_INFO_ATTR_STATUS, (u8 *)&music_info, sizeof(music_info));
break;
}
}
}
}
if (mask & BIT(MUSIC_INFO_ATTR_FILE_NAME) && file) {
/* printf("MUSIC_INFO_ATTR_FILE_NAME\n"); */
u8 *lfn_buf = zalloc(512);
if (lfn_buf) {
int lfn_len = fget_name(file, lfn_buf, 512);
lfn_len = rcsp_file_name_cut(lfn_buf, lfn_len, RCSP_MUSIC_FILE_NAME_MAX_LIMIT);
struct vfs_attr tmp_attr = {0};
fget_attrs(file, &tmp_attr);
u32 clust = app_htonl(tmp_attr.sclust);
/* u32 clust = tmp_attr.sclust; */
/* printf("clust %x\n", clust); */
u8 code_type = 1;
u8 *tmp_buf = lfn_buf;
if (lfn_buf[0] == '\\' && lfn_buf[1] == 'U') {
code_type = 0;
lfn_len -= 2;
tmp_buf += 2;
}
offset += music_func_add_one_attr_ex(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, (u8 *)&clust, sizeof(u32), lfn_len + sizeof(code_type) + sizeof(clust));
offset += mucis_func_add_one_attr_continue(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, (u8 *)&code_type, 1);
offset += mucis_func_add_one_attr_continue(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, tmp_buf, lfn_len);
free(lfn_buf);
}
}
if (mask & BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE)) {
/* printf("MUSIC_INFO_ATTR_FILE_PLAY_MODE\n"); */
u8 play_mode = music_player_get_repeat_mode();
/* printf("play_mode = %d\n", play_mode); */
play_mode = rcsp_repeat_mode_remap[play_mode];
/* printf("remap = %d\n", play_mode); */
offset += add_one_attr(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_PLAY_MODE, &play_mode, 1);
}
#endif
return offset;
}
//设置固件播放器行为
bool rcsp_music_func_set(void *priv, u8 *data, u16 len)
{
/* printf("%s, %d\n", __func__, data[0]); */
#if (TCFG_APP_MUSIC_EN && !RCSP_APP_MUSIC_EN)
RCSP_UPDATE(MUSIC_FUNCTION_MASK,
BIT(MUSIC_INFO_ATTR_STATUS) | BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE));
#endif
return true;
}
//停止音乐功能
void rcsp_music_func_stop(void)
{
#if (RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) {
app_task_put_key_msg(KEY_MUSIC_PP, 0);
}
#endif
}
#endif
@@ -0,0 +1,5 @@
#ifndef __RCSP_MUSIC_FUNC_H__
#define __RCSP_MUSIC_FUNC_H__
#include "typedef.h"
#include "app_config.h"
#endif
@@ -0,0 +1,911 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_rtc_func.data.bss")
#pragma data_seg(".rcsp_rtc_func.data")
#pragma const_seg(".rcsp_rtc_func.text.const")
#pragma code_seg(".rcsp_rtc_func.text")
#endif
#include "app_config.h"
#include "rcsp_rtc_func.h"
#include "rcsp_device_status.h"
#include "rcsp_config.h"
#include "rcsp_event.h"
#include "app_action.h"
#include "rcsp_music_info_setting.h"
#include "btstack/avctp_user.h"
#include "JL_rcsp_packet.h"
#include "key_event_deal.h"
#include "app_msg.h"
#include "rcsp_manage.h"
#include "tone_player.h"
#include "rcsp_browser.h"
#include "rcsp_functions/rcsp_config.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_attr.h"
#if (RCSP_MODE && TCFG_RTC_ENABLE && RCSP_APP_RTC_EN)
#include "rcsp_device_info_func_common.h"
#if TCFG_APP_LINEIN_EN
#include "linein/linein.h"
#endif
#include "alarm.h"
#include "music/music_player.h"
#include "music/general_player.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[rtc]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define RTC_INFO_ATTR_RTC_TIME (0)
#define RTC_INFO_ATTR_RTC_ALRAM (1)
#define RTC_INFO_ATTR_RTC_ALRAM_ACTIVE (2)
#define RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE (3)
#define RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE (4)
#define RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING (5)
#define RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION (6)
#define RTC_INFO_ATTR_RTC_ALARM_EX (7)
// 0是不停止
#define RCSP_ALARM_RING_MAX 50
#pragma pack(1)
typedef struct __APP_ALARM__ {
u8 index;
u8 sw;
u8 mode;
u8 bHour;
u8 bMin;
u8 name_len;
} T_ALARM_APP, *PT_ALARM_APP;
typedef struct __APP_ALARM_EXTRA_DATA__ {
u8 type;
u8 dev;
u32 clust;
u8 ring_name_len;
u8 ring_name[32];
} T_ALARM_APP_EXTRA_DATA, *PT_ALARM_APP_EXTRA_DATA;
typedef struct __APP_ALARM_RING_AUDITION__ {
u8 prev_app_mode;
u8 ring_op;
u8 ring_type;
u8 ring_dev;
u32 ring_clust;
u32 ring_timeout;
} T_ALARM_APP_RING_AUDITION, *PT_ALARM_APP_RING_AUDITION;
typedef struct __APP_ALARM_DATA_EX {
u8 len;
u8 index;
u8 count;
u8 interval;
u8 alarmTime;
} T_ALARM_APP_DATA_EX, *PT_ALARM_APP_DATA_EX;
#pragma pack()
enum {
E_ALARM_SET = 0x00,
E_ALARM_DELETE,
E_ALARM_UNACTIVE,
};
enum {
ALARM_IDEX_TONE_NUM_0 = 0,
ALARM_IDEX_TONE_NUM_1 = 1,
ALARM_IDEX_TONE_NUM_2 = 2,
ALARM_IDEX_TONE_NUM_3 = 3,
ALARM_IDEX_TONE_NUM_4 = 4,
ALARM_IDEX_TONE_NUM_5 = 5,
ALARM_IDEX_TONE_NUM_6 = 6,
ALARM_IDEX_TONE_NUM_7 = 7,
ALARM_IDEX_TONE_NUM_8 = 8,
ALARM_IDEX_TONE_NUM_9 = 9,
ALARM_IDEX_TONE_MAX_NUM = 10,
};
static const char *default_ringtone_table[] = {
[ALARM_IDEX_TONE_NUM_0] = "tone_zh/0.*",
[ALARM_IDEX_TONE_NUM_1] = "tone_zh/1.*",
[ALARM_IDEX_TONE_NUM_2] = "tone_zh/2.*",
[ALARM_IDEX_TONE_NUM_3] = "tone_zh/3.*",
[ALARM_IDEX_TONE_NUM_4] = "tone_zh/4.*",
[ALARM_IDEX_TONE_NUM_5] = "tone_zh/5.*",
[ALARM_IDEX_TONE_NUM_6] = "tone_zh/6.*",
[ALARM_IDEX_TONE_NUM_7] = "tone_zh/7.*",
[ALARM_IDEX_TONE_NUM_8] = "tone_zh/8.*",
[ALARM_IDEX_TONE_NUM_9] = "tone_zh/9.*",
};
static const char *default_ringtone_name_table[] = {
[ALARM_IDEX_TONE_NUM_0] = "提示音0",
[ALARM_IDEX_TONE_NUM_1] = "1",
[ALARM_IDEX_TONE_NUM_2] = "2",
[ALARM_IDEX_TONE_NUM_3] = "3",
[ALARM_IDEX_TONE_NUM_4] = "4",
[ALARM_IDEX_TONE_NUM_5] = "5",
[ALARM_IDEX_TONE_NUM_6] = "6",
[ALARM_IDEX_TONE_NUM_7] = "7",
[ALARM_IDEX_TONE_NUM_8] = "8",
[ALARM_IDEX_TONE_NUM_9] = "9",
};
static void scan_enter(struct __dev *dev)
{
/* clock_add_set(SCAN_DISK_CLK); */
}
static void scan_exit(struct __dev *dev)
{
/* clock_remove_set(SCAN_DISK_CLK); */
}
static const struct __scan_callback scan_cb = {
.enter = scan_enter,
.exit = scan_exit,
.scan_break = general_player_scandisk_break,
};
static const u8 rtc_func_structure_flag = CUR_RTC_ALARM_MODE;
static u8 rtc_ringing_prev_mode = -1;
static T_ALARM_APP_RING_AUDITION g_ring_audition = {
.prev_app_mode = -1,
};
static u8 count = 0;
static u8 flag = 0;
static u8 count_flag = 0;
static u16 rcsp_rtc_ex_timer = 0;
static u16 rcsp_rtc_ex_timer1 = 0;
u8 index_flag = -1;
extern void file_trans_idle_set(u8 file_trans_idle_flag);
static u8 rcsp_rtc_get_alarm_info(PT_ALARM_APP p, u8 index)
{
extern u8 alarm_get_info(PT_ALARM p, u8 index);
u8 ret = 0;
T_ALARM alarm_param;
ret = alarm_get_info(&alarm_param, index);
p->index = alarm_param.index;
p->sw = alarm_param.sw;
p->mode = alarm_param.mode;
p->bHour = alarm_param.time.hour;
p->bMin = alarm_param.time.min;
p->name_len = alarm_param.name_len;
return ret;
}
static u8 rcsp_rtc_get_alarm_total(void)
{
extern u8 alarm_get_total(void);
u8 total = 0;
total = alarm_get_total();
return total;
}
static u8 m_func_alarm_get_active_index(void)
{
extern u8 alarm_get_active_index(void);
return alarm_get_active_index();
}
static u8 m_func_alarm_name_get(u8 *p, u8 index)
{
extern u8 alarm_name_get(u8 * p, u8 index);
return alarm_name_get(p, index);
}
static void rcsp_rtc_update_time(RTC_TIME *p)
{
extern void rtc_update_time_api(struct sys_time * time);
struct sys_time time = {0};
time.year = p->dYear;
time.month = p->bMonth;
time.day = p->bDay;
time.hour = p->bHour;
time.min = p->bMin;
time.sec = p->bSec;
rtc_update_time_api(&time);
}
static u8 mfunc_alarm_deal_data(PT_ALARM_APP p)
{
extern u8 alarm_add(PT_ALARM p, u8 index);
T_ALARM tmp_alarm = {0};
tmp_alarm.index = p->index;
tmp_alarm.sw = p->sw;
tmp_alarm.mode = p->mode;
tmp_alarm.time.hour = p->bHour;
tmp_alarm.time.min = p->bMin;
tmp_alarm.name_len = p->name_len;
return alarm_add(&tmp_alarm, p->index);
}
static void m_func_alarm_name_set(u8 *p, u8 index, u8 len)
{
extern void alarm_name_set(u8 * p, u8 index, u8 len);
alarm_name_set(p, index, len);
}
static void m_func_alarm_delete(u8 index)
{
extern void alarm_delete(u8 index);
alarm_delete(index);
}
static u8 rcsp_rtc_alarm_extra_data_set(u8 index, u8 *p, u8 len)
{
u8 offset = 0;
T_ALARM_APP_EXTRA_DATA data = {0};
data.type = p[offset++];
data.dev = p[offset++];
data.clust = READ_BIG_U32(p + offset);
offset += sizeof(data.clust);
u8 data_len = p[offset++];
data.ring_name_len = data_len > 32 ? 32 : data_len;
memcpy(data.ring_name, p + offset, data.ring_name_len);
offset += data.ring_name_len;
log_info("ring_type : %d, ring_dev : %d, ring_clust : %d, ring_name_len : %d\n", data.type, data.dev, data.clust, data.ring_name_len);
syscfg_write(VM_ALARM_RING_NAME_0 + index, &data, sizeof(data));
return offset;
}
static u8 rcsp_rtc_alarm_deal(void *priv, u8 *p, u8 len)
{
u8 ret = E_SUCCESS;
u8 op = 0;
u8 nums = 0;
u8 index = 0;
u8 *pTmp = 0;
u8 i = 0;
u8 ring_info_offset = 0;
T_ALARM_APP alarm_tab;
if (len >= 3) {
op = p[2];
log_info("op = %d\n", op);
}
if (len >= 4) {
nums = p[3];
log_info("nums = %d\n", nums);
}
if (nums > M_MAX_ALARM_NUMS) {
log_error("nums is error\n");
return E_FAILURE;
}
switch (op) {
case E_ALARM_SET:
log_info("E_ALARM_SET\n");
for (i = 0; i < nums; i++) {
pTmp = &(p[4 + i * (6 + alarm_tab.name_len) + ring_info_offset]);
alarm_tab.index = pTmp[0];
alarm_tab.sw = pTmp[1];
alarm_tab.mode = pTmp[2];
alarm_tab.bHour = pTmp[3];
alarm_tab.bMin = pTmp[4];
alarm_tab.name_len = pTmp[5];
log_info("index : %d, sw : %d, mode : %d, hour : %d, min : %d, name_len : %d\n", pTmp[0], pTmp[1], pTmp[2], pTmp[3], pTmp[4], pTmp[5]);
ret = mfunc_alarm_deal_data(&alarm_tab);
if (E_SUCCESS == ret) {
m_func_alarm_name_set(&(pTmp[6]), alarm_tab.index, alarm_tab.name_len);
}
if (rtc_func_structure_flag) {
ring_info_offset += rcsp_rtc_alarm_extra_data_set(alarm_tab.index, &pTmp[6 + alarm_tab.name_len], len);
}
}
if (rcsp_rtc_ex_timer) {
sys_timer_del(rcsp_rtc_ex_timer);
rcsp_rtc_ex_timer = 0;
}
if (rcsp_rtc_ex_timer1) {
sys_timer_del(rcsp_rtc_ex_timer1);
rcsp_rtc_ex_timer1 = 0;
}
break;
case E_ALARM_DELETE:
log_info("E_ALARM_DELETE\n");
for (i = 0; i < nums; i++) {
index = p[4 + i];
m_func_alarm_delete(index);
}
if (rcsp_rtc_ex_timer) {
sys_timer_del(rcsp_rtc_ex_timer);
rcsp_rtc_ex_timer = 0;
}
if (rcsp_rtc_ex_timer1) {
sys_timer_del(rcsp_rtc_ex_timer1);
rcsp_rtc_ex_timer1 = 0;
}
break;
case E_ALARM_UNACTIVE:
log_info("E_ALARM_UNACTIVE\n");
index_flag = -1;
alarm_stop(1);
if (rcsp_rtc_ex_timer) {
sys_timer_del(rcsp_rtc_ex_timer);
rcsp_rtc_ex_timer = 0;
}
if (rcsp_rtc_ex_timer1) {
sys_timer_del(rcsp_rtc_ex_timer1);
rcsp_rtc_ex_timer1 = 0;
}
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE));
break;
default:
log_warn("alarm no action!\n");
break;
}
return ret;
}
static u8 rcsp_rtc_play_dev_ring(PT_ALARM_APP_RING_AUDITION ring_param)
{
u8 ret = (u8) - 1;
#if TCFG_APP_MUSIC_EN
log_info("neet to play the dev music, dev %s, clust %x\n", rcsp_browser_dev_remap(ring_param->ring_dev), ring_param->ring_clust);
/* ret = general_play_by_sculst(rcsp_browser_dev_remap(ring_param->ring_dev), ring_param->ring_clust); */
#endif /* #if TCFG_APP_MUSIC_EN */
if (ret) {
ring_param->ring_type = 0;
ring_param->ring_clust = 0;
}
return ret;
}
static u8 rcsp_rtc_ring_audition_deal(PT_ALARM_APP_RING_AUDITION ring_param)
{
u8 ret = 0;
log_info("ring stop");
tone_player_stop();
#if TCFG_APP_MUSIC_EN
/* general_player_stop(0); */
#endif /* #if TCFG_APP_MUSIC_EN */
if (1 == ring_param->ring_op) {
log_info("ringing\n");
if (0 == ring_param->ring_type) {
#if TCFG_APP_MUSIC_EN
/* general_player_stop(0); */
#endif /* #if TCFG_APP_MUSIC_EN */
play_tone_file(default_ringtone_table[ring_param->ring_clust]);
} else if (1 == ring_param->ring_type) {
tone_player_stop();
rcsp_rtc_play_dev_ring(ring_param);
}
}
return ret;
}
static u8 rcsp_rtc_ring_audition_prepare(void *priv, u8 *data, u16 len)
{
u8 ret = 0;
struct RcspModel *rcspModel = (struct RcspModel *)priv;
g_ring_audition.ring_op = data[0];
switch (g_ring_audition.ring_op) {
case 0:
// 回到原来的模式
file_trans_idle_set(1);
if ((u8) - 1 != g_ring_audition.prev_app_mode) {
rcsp_msg_post(USER_MSG_RCSP_MODE_SWITCH, 2, (int)rcspModel, g_ring_audition.prev_app_mode);
g_ring_audition.prev_app_mode = -1;
} else {
rcsp_rtc_ring_audition_deal(&g_ring_audition);
}
break;
case 1:
file_trans_idle_set(0);
g_ring_audition.ring_type = data[1];
g_ring_audition.ring_dev = data[2];
g_ring_audition.ring_clust = READ_BIG_U32(data + 3);
// 进入rtc模式
if (RTC_FUNCTION != rcspModel->cur_app_mode) {
g_ring_audition.prev_app_mode = rcspModel->cur_app_mode;
// 切换rtc模式
rcsp_msg_post(USER_MSG_RCSP_MODE_SWITCH, 2, (int)rcspModel, RTC_FUNCTION_MASK);
} else {
rcsp_rtc_ring_audition_deal(&g_ring_audition);
}
break;
}
return ret;
}
//设置固件rtc行为
bool rcsp_rtc_func_set(void *priv, u8 *data, u16 len)
{
u8 ret = 0;
u8 offset = 0;
RTC_TIME time_info;
while (offset < len) {
u8 len_tmp = data[offset];
u8 type = data[offset + 1];
log_info("rtc info:\n");
log_info_hexdump(&data[offset], len_tmp + 1);
switch (type) {
case RTC_INFO_ATTR_RTC_TIME:
log_info("RTC_INFO_ATTR_RTC_TIME\n");
memcpy((u8 *)&time_info, data + 2, sizeof(time_info));
time_info.dYear = app_htons(time_info.dYear);
rcsp_rtc_update_time(&time_info);
break;
case RTC_INFO_ATTR_RTC_ALRAM:
log_info("RTC_INFO_ATTR_RTC_ALRAM\n");
log_info_hexdump(data, len);
ret = rcsp_rtc_alarm_deal(priv, data, len);
break;
case RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION:
log_info("RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION\n");
ret = rcsp_rtc_ring_audition_prepare(priv, data + offset + 2, len);
break;
}
offset += len_tmp + 1;
}
return (E_SUCCESS == ret);
}
static bool rcsp_rtc_alarm_deal_ex(void *priv, u8 *data, u16 len)
{
u8 *tmp_data = data;
T_ALARM_APP_DATA_EX tmp = {0};
tmp.len = tmp_data[0];
tmp.index = tmp_data[1];
tmp.count = tmp_data[2];
tmp.interval = tmp_data[3];
tmp.alarmTime = tmp_data[4];
log_info_hexdump((u8 *)&tmp, sizeof(tmp));
/* syscfg_write(VM_ALARM_EX0 + tmp.index, &tmp, sizeof(tmp)); */
return 1;
}
bool rcsp_rtc_func_set_ex(void *priv, u8 *data, u16 len)
{
log_info("rtc_ex info:\n");
log_info_hexdump(data, len);
return rcsp_rtc_alarm_deal_ex(priv, data, len);
}
u16 rcsp_rtc_func_get_ex(void *priv, u8 *buf, u16 buf_size, u8 mask)
{
u16 offset = 0;
u8 index = 0;
T_ALARM_APP_DATA_EX data = {0};
data.len = 0x04;
data.count |= 0x81;//可设置
data.interval |= 0x85;
data.alarmTime |= 0x85;
u16 size = sizeof(data);
log_info("mask==%u", mask);
do {
if (mask & 0x01) {
/* if (sizeof(data) != syscfg_read(VM_ALARM_EX0 + index, &data, size)) { */
/* log_info("read VM_ALARM error\n"); */
/* } */
data.index = index;
log_info_hexdump((u8 *)&data, sizeof(data));
memcpy(&buf[offset], (u8 *)&data, size);
offset = offset + size;
}
mask = mask >> 1;
index++;
} while (index < 5);
log_info_hexdump(buf, buf_size);
return offset;
}
static u8 rcsp_rtc_alarm_extra_data_get(u8 *p, u8 index, u8 is_conversion)
{
u8 offset = 0;
T_ALARM_APP_EXTRA_DATA data = {0};
if (sizeof(data) != syscfg_read(VM_ALARM_RING_NAME_0 + index, &data, sizeof(data))) {
// 默认数据
data.type = 0;
data.dev = 0;
data.clust = 0;
memcpy(data.ring_name, default_ringtone_name_table[data.clust], strlen(default_ringtone_name_table[data.clust]) + 1);
data.ring_name_len = strlen((const char *)data.ring_name) + 1;
}
p[offset++] = data.type;
p[offset++] = data.dev;
if (is_conversion) {
WRITE_BIG_U32(p + offset, data.clust);
} else {
memcpy(p + offset, &data.clust, sizeof(data.clust));
}
offset += sizeof(data.clust);
p[offset++] = data.ring_name_len;
memcpy(p + offset, data.ring_name, data.ring_name_len);
offset += data.ring_name_len;
return offset;
}
//获取固件rtc信息
u32 rcsp_rtc_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
u16 offset = 0;
if (mask & BIT(RTC_INFO_ATTR_RTC_TIME)) {
log_info("RTC_INFO_ATTR_RTC_TIME\n");
RTC_TIME time_info = {
.dYear = 2020,
.bMonth = 5,
.bDay = 15,
.bHour = 19,
.bMin = 55,
.bSec = 40,
};
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_TIME, (u8 *)&time_info, sizeof(time_info));
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM)) {
log_info("RTC_INFO_ATTR_RTC_ALRAM\n");
u16 data_len = M_MAX_ALARM_NUMS * (sizeof(T_ALARM_APP) + M_MAX_ALARM_NAME_LEN + sizeof(T_ALARM_APP_EXTRA_DATA));
u8 *alarm_data = zalloc(data_len);
u8 total = 0;
u8 index = 0;
u8 name_len = 0;
u8 *pTmp;
u8 ret = 0;
data_len = 0;
pTmp = alarm_data;
total = rcsp_rtc_get_alarm_total();
log_info("total %d alarm!\n", total);
pTmp[0] = total;
pTmp++;
data_len++;
for (index = 0; index < 5; index++) {
ret = rcsp_rtc_get_alarm_info((PT_ALARM_APP)pTmp, index);
log_info("alarm_tab.sw get==%u&&&", ((PT_ALARM_APP)pTmp)->sw);
if (0 == ret) {
pTmp += sizeof(T_ALARM_APP);
data_len += sizeof(T_ALARM_APP);
name_len = m_func_alarm_name_get(pTmp, index);
pTmp += name_len;
data_len += name_len;
if (rtc_func_structure_flag) {
name_len = rcsp_rtc_alarm_extra_data_get(pTmp, index, 1);
pTmp += name_len;
data_len += name_len;
}
log_info("data_len = %d\n", data_len);
}
}
log_info_hexdump(alarm_data, data_len);
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM, alarm_data, data_len);
if (alarm_data) {
free(alarm_data);
}
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE)) {
log_info("RTC_INFO_ATTR_RTC_ALRAM_ACTIVE\n");
u8 index_mask = 0;
index_mask = m_func_alarm_get_active_index();
log_info("active alarm index : %d\n", index_mask);
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_ACTIVE, (u8 *)&index_mask, sizeof(index_mask));
/* extern void alarm_update_info_after_isr(void); */
/* alarm_update_info_after_isr(); */
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE)) {
log_info("RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE\n");
u8 index_mask = 0;
index_mask = m_func_alarm_get_active_index();
log_info("active alarm index : %d\n", index_mask);
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE, (u8 *)&index_mask, sizeof(index_mask));
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE)) {
log_info("RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE\n");
u8 rtc_structure_flag = rtc_func_structure_flag;
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE, &rtc_structure_flag, sizeof(rtc_structure_flag));
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING)) {
log_info("RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING\n");
u8 i;
// total + index
u8 ring_info_len = 1 + ALARM_IDEX_TONE_MAX_NUM;
for (i = 0; i < ALARM_IDEX_TONE_MAX_NUM; i++) {
// name_len + name_data
ring_info_len += 1 + strlen(default_ringtone_name_table[i]) + 1;
}
u8 default_offset = 0;
u8 ring_name_len = 0;
u8 *default_ring = zalloc(ring_info_len);
default_ring[default_offset++] = ALARM_IDEX_TONE_MAX_NUM;
for (i = 0; i < ALARM_IDEX_TONE_MAX_NUM; i++) {
ring_name_len = strlen(default_ringtone_name_table[i]) + 1;
default_ring[default_offset++] = i;
default_ring[default_offset++] = ring_name_len;
if (ring_name_len) {
memcpy(default_ring + default_offset, default_ringtone_name_table[i], ring_name_len);
}
default_offset += ring_name_len;
}
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING, default_ring, ring_info_len);
if (default_ring) {
free(default_ring);
}
}
if (mask & BIT(RTC_INFO_ATTR_RTC_ALARM_EX)) {
log_info("RTC_INFO_ATTR_RTC_ALARM_EX\n");
u8 tmp[1] = {1};
offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALARM_EX, tmp, 1);
}
return offset;
}
//rtc消息处理
void rcsp_rtc_msg_deal(int msg)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
switch (msg) {
case (int)-1 :
rtc_ringing_prev_mode = rcspModel->cur_app_mode;
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE));
break;
}
}
static void rtc_ring_stop_handle(void)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE) | BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE));
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM));
if ((u8) - 1 != rtc_ringing_prev_mode) {
#if RCSP_MODE == RCSP_MODE_SOUNDBOX
extern void alarm_play_timer_del(void);
alarm_play_timer_del();
rcsp_msg_post(USER_MSG_RCSP_MODE_SWITCH, 2, (int)rcspModel, rtc_ringing_prev_mode);
#endif
rtc_ringing_prev_mode = -1;
}
}
u8 rtc_app_alarm_ring_play(u8 alarm_state);
void rcsp_rtc_ex_deal1(void *priv)
{
rtc_app_alarm_ring_play(1);
}
void rcsp_rtc_ex_deal(void *priv)
{
rtc_ringing_prev_mode = 8;
rcsp_rtc_ex_timer1 = sys_timer_add(NULL, rcsp_rtc_ex_deal1, 500);
}
u8 rtc_get_active_index()
{
u8 index = -1;
u8 cur_active_index = alarm_get_active_index();
for (int i = 0; i < M_MAX_ALARM_NUMS; i++) {
if (cur_active_index & BIT(i)) {
index = i;
break;
}
}
return index;
}
void rtc_sw_set(u8 sw, u8 index)
{
T_ALARM alarm_param;
int ret = alarm_get_info(&alarm_param, index);
if (ret) {
return;
}
if (alarm_param.mode == 0) {
alarm_param.sw = sw;
alarm_add(&alarm_param, index);
}
}
void rtc_ring_sw_deal()
{
if (index_flag != (u8) - 1) {
if (rcsp_rtc_ex_timer1) {
sys_timer_del(rcsp_rtc_ex_timer1);
rcsp_rtc_ex_timer1 = 0;
}
if (rcsp_rtc_ex_timer) {
sys_timer_del(rcsp_rtc_ex_timer);
rcsp_rtc_ex_timer = 0;
}
flag = 0;
count_flag = 0;
rtc_sw_set(0, index_flag);
index_flag = -1;
}
}
static void ring_play_ex()
{
T_ALARM_APP_DATA_EX data = {0};
data.len = 0x04;
data.count |= 0x80;//可设置
data.interval |= 0x80;
data.alarmTime |= 0x80;
u16 size = sizeof(data);
index_flag = rtc_get_active_index();
/* if (sizeof(data) != syscfg_read(VM_ALARM_EX0 + index_flag, &data, size)) { */
/* log_info("read alarm error\n"); */
/* } */
log_info_hexdump((u8 *)&data, sizeof(data));
if (count_flag == 0) {
count = data.count & 0x0f;
count_flag = 1;
}
u8 interval = data.interval & 0x1f;
u8 alarmTime = data.alarmTime & 0x1f;
flag++;
if (flag == alarmTime * 3) { //闹铃结束
flag = 0;
count--;
/* log_info("count==================================================%d", count); */
if (count) {
rcsp_rtc_ex_timer = sys_timeout_add(NULL, rcsp_rtc_ex_deal, interval * 60 * 50);
} else {
count_flag = 0;
rtc_sw_set(0, index_flag);
index_flag = -1;
}
alarm_stop(0);
if (rcsp_rtc_ex_timer1) {
sys_timer_del(rcsp_rtc_ex_timer1);
rcsp_rtc_ex_timer1 = 0;
}
}
}
u8 rtc_app_alarm_ring_play(u8 alarm_state)
{
// 防止g_ring_audition成为临界资源,所以定义多一个局部变量
static T_ALARM_APP_RING_AUDITION ringing_info = {0};
u8 active_flag = m_func_alarm_get_active_index();
u8 index;
if (0 == active_flag && 0 == rtc_func_structure_flag) {
return rtc_func_structure_flag;
}
if (0 == alarm_state) {
file_trans_idle_set(1);
ringing_info.prev_app_mode = 0;
ringing_info.ring_op = 0;
ringing_info.ring_timeout = 0;
rcsp_rtc_ring_audition_deal(&ringing_info);
if (index_flag != (u8) - 1) {
rtc_sw_set(1, index_flag);
}
rtc_ring_stop_handle();
return rtc_func_structure_flag;
} else {
if ((u32) - 1 == (--ringing_info.ring_timeout)) {
ringing_info.ring_timeout = RCSP_ALARM_RING_MAX;
} else if (0 == ringing_info.ring_timeout) {
#if RCSP_MODE == RCSP_MODE_SOUNDBOX
ringing_info.ring_timeout = RCSP_ALARM_RING_MAX;
ring_play_ex();
#else
alarm_stop(1);
#endif
return rtc_func_structure_flag;
}
}
for (index = 0; index < (M_MAX_ALARM_NUMS + M_MAX_SNOOZE_ALARM_NUM); index++) {
if (active_flag & BIT(index)) {
break;
}
}
if (index < (M_MAX_ALARM_NUMS + M_MAX_SNOOZE_ALARM_NUM)) {
if (0 == ringing_info.prev_app_mode) {
// 响铃会进入始终模式,这个时全局变量prev_app_mode应该清除
g_ring_audition.prev_app_mode = -1;
// 暂停正在播放的提示音或设备音乐
g_ring_audition.ring_op = 0;
rcsp_rtc_ring_audition_deal(&g_ring_audition);
T_ALARM_APP_EXTRA_DATA data = {0};
u32 data_len = 0;
rcsp_rtc_alarm_extra_data_get((u8 *)&data, index, 0);
ringing_info.prev_app_mode = -1;
ringing_info.ring_op = 1;
ringing_info.ring_type = data.type;
ringing_info.ring_dev = data.dev;
ringing_info.ring_clust = data.clust;
}
if (get_rcsp_connect_status()) {
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE));
}
#if TCFG_APP_MUSIC_EN
file_trans_idle_set(0);
if (ringing_info.ring_type) {
if (!music_player_get_play_status()) {
// 播放设备音乐
log_info("ringing............................\n");
rcsp_rtc_play_dev_ring(&ringing_info);
}
} else
#endif /* #if TCFG_APP_MUSIC_EN */
{
play_tone_file(default_ringtone_table[ringing_info.ring_clust]);
}
}
return rtc_func_structure_flag;
}
u8 rcsp_rtc_ring_tone(void)
{
#if TCFG_APP_MUSIC_EN
/* general_player_init((struct __scan_callback *)&scan_cb); */
#endif /* #if TCFG_APP_MUSIC_EN */
if ((u8) - 1 != g_ring_audition.prev_app_mode) {
rcsp_rtc_ring_audition_deal(&g_ring_audition);
} else if ((u8) - 1 == rtc_ringing_prev_mode) {
}
return false;
}
void rcsp_rtc_mode_exit(void)
{
#if TCFG_APP_MUSIC_EN
/* general_player_exit(); */
#endif /* #if TCFG_APP_MUSIC_EN */
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
file_trans_idle_set(1);
if ((u8) - 1 != rtc_ringing_prev_mode) {
rtc_ringing_prev_mode = rcspModel->cur_app_mode;
rtc_ring_stop_handle();
}
}
/*添加、删除闹钟后,更新闹钟信息给app*/
void rcsp_update_alarm_info(void)
{
rcsp_device_status_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM));
}
#endif
@@ -0,0 +1,8 @@
#ifndef __RCSP_RTC_FUNC_H__
#define __RCSP_RTC_FUNC_H__
#include "typedef.h"
#include "app_config.h"
void rcsp_update_alarm_info(void);
#endif
@@ -0,0 +1,466 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_device_feature.data.bss")
#pragma data_seg(".rcsp_device_feature.data")
#pragma const_seg(".rcsp_device_feature.text.const")
#pragma code_seg(".rcsp_device_feature.text")
#endif
#include "rcsp_device_feature.h"
#include "app_config.h"
#include "rcsp_config.h"
#include "btstack/avctp_user.h"
#include "rcsp_event.h"
#include "custom_cfg.h"
#include "JL_rcsp_packet.h"
#include "rcsp_extra_flash_opt.h"
#include "rcsp_vol_setting.h"
#include "rcsp_device_status.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_attr.h"
#include "rcsp_functions/rcsp_config.h"
#include "app_task.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[dev feature]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#if (RCSP_MODE)
#pragma pack(1)
struct _SYS_info {
u8 bat_lev;
u8 sys_vol;
u8 max_vol;
u8 vol_is_sync;
};
struct _EDR_info {
u8 addr_buf[6];
u8 profile;
u8 state;
};
#pragma pack()
static u32 target_feature_attr_protocol_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u8 ver = get_rcsp_version();
rlen = add_one_attr(buf, buf_size, offset, attr, &ver, 1);
return rlen;
}
static u32 target_feature_attr_sys_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
struct _SYS_info sys_info = {0};
#if (RCSP_MODE != RCSP_MODE_EARPHONE)
extern u8 get_vbat_percent(void);
sys_info.bat_lev = get_vbat_percent(); //get_battery_level() / 10;
rcsp_get_max_vol_info(&sys_info.max_vol);
rcsp_get_cur_dev_vol_info(&sys_info.sys_vol);
#endif
#if BT_SUPPORT_MUSIC_VOL_SYNC || TCFG_BT_VOL_SYNC_ENABLE
extern u8 avctp_get_remote_vol_sync(bd_addr_t addr);
if ((bt_get_current_remote_addr() && avctp_get_remote_vol_sync(bt_get_current_remote_addr())) || (0 == rcspModel->A_platform)) {
sys_info.vol_is_sync |= BIT(0);
rcspModel->dev_vol_sync = 1;
}
#endif
rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&sys_info, sizeof(sys_info));
return rlen;
}
static u32 target_feature_attr_edr_addr(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
struct _EDR_info edr_info;
extern const u8 *bt_get_mac_addr();
u8 taddr_buf[6];
memcpy(taddr_buf, bt_get_mac_addr(), 6);
edr_info.addr_buf[0] = taddr_buf[5];
edr_info.addr_buf[1] = taddr_buf[4];
edr_info.addr_buf[2] = taddr_buf[3];
edr_info.addr_buf[3] = taddr_buf[2];
edr_info.addr_buf[4] = taddr_buf[1];
edr_info.addr_buf[5] = taddr_buf[0];
edr_info.profile = 0x0E;
if (get_defalut_bt_channel_sel()) {
edr_info.profile |= BIT(7);
} else {
edr_info.profile &= ~BIT(7);
}
if (bt_get_connect_status() == BT_STATUS_WAITINT_CONN) {
edr_info.state = 0;
} else {
edr_info.state = 1;
}
rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&edr_info, sizeof(struct _EDR_info));
return rlen;
}
static u32 target_feature_attr_platform(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
return rlen;
}
static u32 target_feature_function_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 rlen = 0;
u8 tmp_buf[6] = {0};
u32 func_mask = app_htonl(rcspModel->function_mask);
#if RCSP_DEVICE_STATUS_ENABLE
u8 cur_fun = rcsp_get_cur_mode(app_get_curr_task());
#else
u8 cur_fun = BT_FUNCTION;
#endif
memcpy(tmp_buf, (u8 *)&func_mask, 4);
memcpy(tmp_buf + 4, &cur_fun, 1);
memcpy(tmp_buf + 5, &rcspModel->music_icon_mask, 1);
rlen = add_one_attr(buf, buf_size, offset, attr, tmp_buf, sizeof(tmp_buf));
return rlen;
}
static u32 target_feature_dev_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u16 ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG);
ver = READ_BIG_U16(&ver);
rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&ver, sizeof(ver));
return rlen;
}
static u32 target_feature_sdk_type(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 rlen = 0;
u8 sdk_type = rcspModel->sdk_type;
rlen = add_one_attr(buf, buf_size, offset, attr, &sdk_type, 1);
return rlen;
}
static u32 target_feature_uboot_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u8 *uboot_ver_flag = (u8 *)"10";
u8 uboot_version[2] = {uboot_ver_flag[0], uboot_ver_flag[1]};
rlen = add_one_attr(buf, buf_size, offset, attr, uboot_version, sizeof(uboot_version));
return rlen;
}
static u32 target_feature_ota_double_parition(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 rlen = 0;
u8 double_partition_value;
u8 ota_loader_need_download_flag;
u8 update_channel_sel;
u8 update_again_flag = 0;
if (rcspModel->ota_type) {
double_partition_value = 0x1;
ota_loader_need_download_flag = 0x00;
} else {
double_partition_value = 0x0;
ota_loader_need_download_flag = 0x01;
}
update_channel_sel = 0x1; //强制使用BLE升级
#if CONFIG_REUSABLE_RESERVE
extern u32 reusable_area_flash_space(u32 * start_addr, u32 * free_space);
if (reusable_area_flash_space(NULL, NULL)) {
update_again_flag = 1;
}
#elif CONFIG_RESFS_UPDATE_ENABLE
extern u32 resfs_area_flash_space(u32 * start_addr, u32 * free_space);
if (resfs_area_flash_space(NULL, NULL)) {
update_again_flag = 1;
}
#endif
u8 update_param[4] = {
double_partition_value,
ota_loader_need_download_flag,
update_channel_sel,
update_again_flag,
};
rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)update_param, sizeof(update_param));
return rlen;
}
static u32 target_feature_ota_update_status(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u8 update_status_value[3] = {0x0};
#if CONFIG_REUSABLE_RESERVE
extern u32 reusable_area_flash_space(u32 * start_addr, u32 * free_space);
extern u8 reusable_update_app_flag_handle(u8 state, u8 opt);
if (reusable_area_flash_space(NULL, NULL)) {
update_status_value[2] = reusable_update_app_flag_handle(0, 0);
}
#elif CONFIG_RESFS_UPDATE_ENABLE
extern u32 resfs_area_flash_space(u32 * start_addr, u32 * free_space);
extern u8 resfs_update_app_flag_handle(u8 state, u8 opt);
if (resfs_area_flash_space(NULL, NULL)) {
update_status_value[2] = resfs_update_app_flag_handle(0, 0);
}
#endif
#if JL_RCSP_EXTRA_FLASH_OPT
if (0 == update_status_value[2]) {
update_status_value[2] = rcsp_eflash_update_flag_get();
}
#endif
rlen = add_one_attr(buf, buf_size, offset, attr, update_status_value, sizeof(update_status_value));
return rlen;
}
static u32 target_feature_pid_vid(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u16 pvid[2] = {0};
pvid[0] = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
pvid[1] = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
pvid[0] = READ_BIG_U16(&pvid[0]);
pvid[1] = READ_BIG_U16(&pvid[1]);
rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&pvid, sizeof(pvid));
return rlen;
}
static u32 target_feature_authkey(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
#if VER_INFO_EXT_COUNT
u8 authkey_len = 0;
u8 *local_authkey_data = NULL;
get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG);
if (local_authkey_data && authkey_len) {
log_info("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
log_info_hexdump(local_authkey_data, authkey_len);
rlen = add_one_attr(buf, buf_size, offset, attr, local_authkey_data, authkey_len);
}
#endif
return rlen;
}
static u32 target_feature_procode(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
#if VER_INFO_EXT_COUNT
u8 procode_len = 0;
u8 *local_procode_data = NULL;
get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG);
if (local_procode_data && procode_len) {
log_info("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
log_info_hexdump(local_procode_data, procode_len);
rlen = add_one_attr(buf, buf_size, offset, attr, local_procode_data, procode_len);
}
#endif
return rlen;
}
static u32 target_feature_mtu(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u16 rx_max_mtu = JL_packet_get_rx_max_mtu();
u16 tx_max_mtu = JL_packet_get_tx_max_mtu();
u8 t_buf[4];
t_buf[0] = (tx_max_mtu >> 8) & 0xFF;
t_buf[1] = tx_max_mtu & 0xFF;
t_buf[2] = (rx_max_mtu >> 8) & 0xFF;
t_buf[3] = rx_max_mtu & 0xFF;
rlen = add_one_attr(buf, buf_size, offset, attr, t_buf, 4);
return rlen;
}
static u32 target_feature_ble_only(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
u32 rlen = 0;
u8 taddr_buf[7];
taddr_buf[0] = 0;
#if CONFIG_USE_RANDOM_ADDRESS_ENABLE
le_controller_get_random_mac(taddr_buf + 1);
#else
le_controller_get_mac(taddr_buf + 1);
#endif
for (u8 i = 0; i < (6 / 2); i++) {
taddr_buf[i + 1] ^= taddr_buf[7 - i - 1];
taddr_buf[7 - i - 1] ^= taddr_buf[i + 1];
taddr_buf[i + 1] ^= taddr_buf[7 - i - 1];
}
rlen = add_one_attr(buf, buf_size, offset, attr, taddr_buf, sizeof(taddr_buf));
return rlen;
}
static u32 target_feature_bt_emitter_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 rlen = 0;
u8 val = 0;
val |= rcspModel->emitter_en;
val |= rcspModel->emitter_sw;
log_info("val = %d, emitter_en = %d, emitter_sw = %d\n", val, rcspModel->emitter_en, rcspModel->emitter_sw);
rlen = add_one_attr(buf, buf_size, offset, attr, &val, 1);
return rlen;
}
static u32 target_feature_md5_game_support(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 rlen = 0;
u8 ext_function_flag[2] = {0};
u8 md5_support = 0;
#if RCSP_MODE == RCSP_MODE_EARPHONE
md5_support = UPDATE_MD5_ENABLE;
#endif
#if RCSP_MODE != RCSP_MODE_EARPHONE
if (rcspModel->game_mode_en) {
#else
{
#endif
md5_support |= BIT(1);
}
if (rcspModel->find_dev_en) {
md5_support |= BIT(2);
}
if (rcspModel->karaoke_en) {
md5_support |= BIT(3);
}
if (rcspModel->sound_effects_disable) {
md5_support |= BIT(4);
}
if (rcspModel->extra_flash_en) {
md5_support |= BIT(5);
}
#if (RCSP_ADV_ANC_VOICE) || ((defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP)
md5_support |= BIT(6);
#endif
#if ((defined CONFIG_DEBUG_RECORD_ENABLE) && CONFIG_DEBUG_RECORD_ENABLE)
md5_support |= BIT(7);
#endif
ext_function_flag[0] = md5_support;
u8 ext_function_flag_byte1 = 0;
#if (RCSP_ADV_ASSISTED_HEARING)
ext_function_flag_byte1 |= BIT(0);
#endif
#if RCSP_ADV_ADAPTIVE_NOISE_REDUCTION
ext_function_flag_byte1 |= BIT(1);
#endif
#if RCSP_ADV_AI_NO_PICK
ext_function_flag_byte1 |= BIT(3);
#endif
#if RCSP_ADV_SCENE_NOISE_REDUCTION
ext_function_flag_byte1 |= BIT(4);
#endif
#if RCSP_ADV_WIND_NOISE_DETECTION
ext_function_flag_byte1 |= BIT(5);
#endif
#if RCSP_ADV_VOICE_ENHANCEMENT_MODE
ext_function_flag_byte1 |= BIT(6);
#endif
#if TCFG_RCSP_DUAL_CONN_ENABLE
// 是否一拖二
ext_function_flag_byte1 |= BIT(7);
#endif
#if RCSP_ADV_DEVICE_CONFIG_GET
ext_function_flag_byte1 |= BIT(2);
#endif
ext_function_flag[1] = ext_function_flag_byte1;
rlen = add_one_attr(buf, buf_size, offset, attr, ext_function_flag, 2);
return rlen;
}
static u32 target_feature_file_transfer_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return 0;
}
u32 config = 0;
u8 send_buf[4] = {0};
if (rcspModel->file_transfer_mode) {
config |= BIT(0);//文件传输是支持配置分包crc校验使能, 这里默认支持
}
if (rcspModel->file_trans_back_mode) {
config |= BIT(1); // 文件回传支持手机选择外挂flash还是sd卡
}
if (rcspModel->file_simple_trans_mode) {
config |= BIT(2);
}
WRITE_BIG_U32(send_buf, config);
u32 rlen = add_one_attr(buf, buf_size, offset, attr, send_buf, sizeof(config));
return rlen;
}
static const attr_get_func target_feature_mask_get_tab[RCSP_DEVICE_FEATURE_ATTR_TYPE_MAX] = {
[RCSP_DEVICE_FEATURE_ATTR_TYPE_PROTOCOL_VERSION ] = target_feature_attr_protocol_version,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_SYS_INFO ] = target_feature_attr_sys_info,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_EDR_ADDR ] = target_feature_attr_edr_addr,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_PLATFORM ] = target_feature_attr_platform,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_FUNCTION_INFO ] = target_feature_function_info,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_VERSION ] = target_feature_dev_version,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_SDK_TYPE ] = target_feature_sdk_type,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_UBOOT_VERSION ] = target_feature_uboot_version,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DOUBLE_PARITION ] = target_feature_ota_double_parition,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_UPDATE_STATUS ] = target_feature_ota_update_status,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_VID_PID ] = target_feature_pid_vid,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_AUTHKEY ] = target_feature_authkey,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_PROCODE ] = target_feature_procode,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_MAX_MTU ] = target_feature_mtu,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_CONNECT_BLE_ONLY ] = target_feature_ble_only,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_BT_EMITTER_INFO ] = target_feature_bt_emitter_info,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_MD5_GAME_SUPPORT ] = target_feature_md5_game_support,
[RCSP_DEVICE_FEATURE_ATTR_TYPE_FILE_TRANSFER_INFO] = target_feature_file_transfer_info,
};
// 解析设备特征相关的rcsp数据
u32 rcsp_target_feature_parse_packet(void *priv, u8 *buf, u16 buf_size, u32 mask)
{
log_info("rcsp_target_feature_parse_packet, mask = %x\n", mask);
return attr_get(priv, buf, buf_size, target_feature_mask_get_tab, RCSP_DEVICE_FEATURE_ATTR_TYPE_MAX, mask);
}
#if TCFG_CONNECTED_ENABLE || TCFG_BROADCAST_ENABLE
static RCSP_LeAudioMode _leAudioMode = RCSP_LeAudioModeNone;
/**
* @brief 设置leaudio的状态
*
* #param RCSP_LeAudioMode
*/
void rcsp_set_LeAudio_mode(RCSP_LeAudioMode mode)
{
_leAudioMode = mode;
}
/**
* @brief 获取leaudio的状态
*
* @result RCSP_LeAudioMode
*/
RCSP_LeAudioMode rcsp_get_LeAudio_mode()
{
return _leAudioMode;
}
#endif
#endif//RCSP_MODE
@@ -0,0 +1,52 @@
#ifndef __RCSP_DEVICE_FEATURE_H__
#define __RCSP_DEVICE_FEATURE_H__
#include "typedef.h"
#include "app_config.h"
enum {
RCSP_DEVICE_FEATURE_ATTR_TYPE_PROTOCOL_VERSION = 0,
RCSP_DEVICE_FEATURE_ATTR_TYPE_SYS_INFO = 1,
RCSP_DEVICE_FEATURE_ATTR_TYPE_EDR_ADDR = 2,
RCSP_DEVICE_FEATURE_ATTR_TYPE_PLATFORM = 3,
RCSP_DEVICE_FEATURE_ATTR_TYPE_FUNCTION_INFO = 4,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_VERSION = 5,
RCSP_DEVICE_FEATURE_ATTR_TYPE_SDK_TYPE = 6,
RCSP_DEVICE_FEATURE_ATTR_TYPE_UBOOT_VERSION = 7,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DOUBLE_PARITION = 8,
RCSP_DEVICE_FEATURE_ATTR_TYPE_UPDATE_STATUS = 9,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_VID_PID = 10,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_AUTHKEY = 11,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_PROCODE = 12,
RCSP_DEVICE_FEATURE_ATTR_TYPE_DEV_MAX_MTU = 13,
RCSP_DEVICE_FEATURE_ATTR_TYPE_CONNECT_BLE_ONLY = 17,
RCSP_DEVICE_FEATURE_ATTR_TYPE_BT_EMITTER_INFO = 18,
RCSP_DEVICE_FEATURE_ATTR_TYPE_MD5_GAME_SUPPORT = 19,
RCSP_DEVICE_FEATURE_ATTR_TYPE_FILE_TRANSFER_INFO = 21,
RCSP_DEVICE_FEATURE_ATTR_TYPE_MAX,
};
// le aduio mode
typedef enum {
RCSP_LeAudioModeNone = 0x00,
RCSP_LeAudioModeBig = 0x01,
RCSP_LeAudioModeCig = 0x02,
} RCSP_LeAudioMode;
/**
* @brief 设置leaudio的状态
*
* #param RCSP_LeAudioMode
*/
void rcsp_set_LeAudio_mode(RCSP_LeAudioMode mode);
/**
* @brief 获取leaudio的状态
*
* @result RCSP_LeAudioMode
*/
RCSP_LeAudioMode rcsp_get_LeAudio_mode();
// 解析设备特征相关的rcsp数据
u32 rcsp_target_feature_parse_packet(void *priv, u8 *buf, u16 buf_size, u32 mask);
#endif//__RCSP_DEVICE_FEATURE_H__
@@ -0,0 +1,62 @@
#ifndef __RCSP_DEVICE_STATUS_H__
#define __RCSP_DEVICE_STATUS_H__
#include "typedef.h"
#include "app_config.h"
// 0x07、0x08使用以下枚举
enum {
RCSP_DEVICE_STATUS_ATTR_TYPE_BATTERY = 0,
RCSP_DEVICE_STATUS_ATTR_TYPE_VOL = 1,
RCSP_DEVICE_STATUS_ATTR_TYPE_DEV_INFO = 2,
RCSP_DEVICE_STATUS_ATTR_TYPE_ERROR_STATS = 3,
RCSP_DEVICE_STATUS_ATTR_TYPE_EQ_INFO = 4,
RCSP_DEVICE_STATUS_ATTR_TYPE_BS_FILE_TYPE = 5,
RCSP_DEVICE_STATUS_ATTR_TYPE_FUNCTION_MODE = 6,
RCSP_DEVICE_STATUS_ATTR_TYPE_COLOR_LED_SETTING_INFO = 7,
RCSP_DEVICE_STATUS_ATTR_TYPE_FMTX_FREQ = 8,
RCSP_DEVICE_STATUS_ATTR_TYPE_BT_EMITTER_SW = 9,
RCSP_DEVICE_STATUS_ATTR_TYPE_BT_EMITTER_CONNECT_STATES = 10,
RCSP_DEVICE_STATUS_ATTR_TYPE_HIGH_LOW_SET = 11,
RCSP_DEVICE_STATUS_ATTR_TYPE_PRE_FETCH_ALL_EQ_INFO = 12,
RCSP_DEVICE_STATUS_ATTR_TYPE_ANC_VOICE = 13,
RCSP_DEVICE_STATUS_ATTR_TYPE_FETCH_ALL_ANC_VOICE = 14,
RCSP_DEVICE_STATUS_ATTR_TYPE_PHONE_SCO_STATE_INFO = 15,
RCSP_DEVICE_STATUS_ATTR_TYPE_MISC_SETTING_INFO = 16,
RCSP_DEVICE_STATUS_ATTR_TYPE_PRE_FETCH_KARAOKE_EQ_INFO = 17,
RCSP_DEVICE_STATUS_ATTR_TYPE_KARAOKE_EQ_SETTING_INFO = 18,
// 缺一个声卡功能19
RCSP_DEVICE_STATUS_ATTR_TYPE_ASSISTED_HEARING = 20,
RCSP_DEVICE_STATUS_ATTR_TYPE_ADAPTIVE_NOISE_REDUCTION = 21,
RCSP_DEVICE_STATUS_ATTR_TYPE_AI_NO_PICK = 22,
RCSP_DEVICE_STATUS_ATTR_TYPE_SCENE_NOISE_REDUCTION = 23,
RCSP_DEVICE_STATUS_ATTR_TYPE_WIND_NOISE_DETECTION = 24,
RCSP_DEVICE_STATUS_ATTR_TYPE_VOICE_ENHANCEMENT_MODE = 25,
RCSP_DEVICE_STATUS_ATTR_TYPE_AI = 26,
RCSP_DEVICE_STATUS_ATTR_TYPE_1T2 = 27,
RCSP_DEVICE_STATUS_ATTR_TYPE_MAX,
};
// 设备状态更改
bool rcsp_device_status_cmd_set(void *priv, u8 OpCode, u8 OpCode_SN, u8 function, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
// 设备状态更改
bool rcsp_device_status_set(void *priv, u8 OpCode, u8 OpCode_SN, u8 function, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
// 获取设备状态
u32 rcsp_device_status_get(void *priv, u8 function, u8 *data, u16 len, u8 *buf, u16 buf_size);
// 设备状态更改
void rcsp_device_status_update(u8 function, u32 mask);
// rcsp功能设置关闭
void rcsp_device_status_setting_stop(void);
// 获取当前模式
u8 rcsp_get_cur_mode(u8 app_mode);
void function_change_inform(u8 app_mode, u8 ret);
#if (RCSP_MODE)
#define RCSP_UPDATE rcsp_device_status_update
#else
#define RCSP_UPDATE(...)
#endif//RCSP_MODE
#endif//__RCSP_DEVICE_STATUS_H__
@@ -0,0 +1,103 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_extra_flash_cmd.data.bss")
#pragma data_seg(".rcsp_extra_flash_cmd.data")
#pragma const_seg(".rcsp_extra_flash_cmd.text.const")
#pragma code_seg(".rcsp_extra_flash_cmd.text")
#endif
#include "app_config.h"
#include "rcsp_config.h"
#include "rcsp_device_status.h"
#include "rcsp.h"
#include "rcsp_event.h"
#include "rcsp_extra_flash_cmd.h"
#include "rcsp_extra_flash_opt.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_opt.h"
#include "rcsp_manage.h"
#if (RCSP_MODE && JL_RCSP_EXTRA_FLASH_OPT)
/* #define RCSP_DEBUG_EN */
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_printf_buf(x,len) put_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
/**
* @brief 外挂flash命令发送
*
* @param dire 非0:命令发送;0:命令回复
*/
int rcsp_extra_flash_opt_resp(u8 dire, u8 OpCode, u8 OpCode_SN, u8 *resp_data, u16 data_len)
{
if (OpCode) {
if (dire) {
JL_CMD_send(OpCode, resp_data, data_len, JL_NOT_NEED_RESPOND, 0, NULL);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp_data, data_len, 0, NULL);
}
}
return 0;
}
//外挂flash命令处理
int JL_rcsp_extra_flash_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
rcsp_printf("JL_rcsp_extra_flash_cmd_resp, OpCode : %x, OpCode_SN : %x\n", OpCode, OpCode_SN);
int ret = 0;
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return ret;
}
switch (OpCode) {
case JL_OPCODE_EXTRA_FLASH_OPT: // 0x1A - 读写外部Flash命令
ret = rcsp_extra_flash_opt(data, len, OpCode, OpCode_SN);
if (ret < 0) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
} else {
ret = 0;
}
break;
case JL_OPCODE_EXTRA_FLASH_INFO: // 0xD6 - 获取外部Flash信息
ret = rcsp_get_extra_flash_info(priv, data);
if (ret >= 0) {
u16 data_len = (u16) ret;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, data_len, 0, NULL);
ret = rcsp_extra_flash_opt_start();
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
}
break;
default:
ret = -1;
break;
}
return ret;
}
//外挂flash不回复命令处理
int JL_rcsp_extra_flash_cmd_no_resp(void *priv, u8 OpCode, u8 *data, u16 len)
{
rcsp_printf("JL_rcsp_extra_flash_cmd_no_resp, OpCode : %x\n", OpCode);
int ret = 0;
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return ret;
}
switch (OpCode) {
case JL_OPCODE_EXTRA_FLASH_OPT:
ret = rcsp_extra_flash_opt(data, len, 0, 0);
break;
default:
ret = -1;
break;
}
return ret;
}
#endif
@@ -0,0 +1,18 @@
#ifndef _RCSP_EXTRA_FLASH_CMD_H_
#define _RCSP_EXTRA_FLASH_CMD_H_
#include "typedef.h"
#include "system/event.h"
//外挂flash命令处理
int JL_rcsp_extra_flash_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
//外挂flash不回复命令处理
int JL_rcsp_extra_flash_cmd_no_resp(void *priv, u8 OpCode, u8 *data, u16 len);
/**
* @brief 外挂flash命令发送
*
* @param dire 非0:命令发送;0:命令回复
*/
int rcsp_extra_flash_opt_resp(u8 dire, u8 OpCode, u8 OpCode_SN, u8 *resp_data, u16 data_len);
#endif
@@ -0,0 +1,128 @@
#ifndef _RCSP_EXTRA_FLASH_OPT_H_
#define _RCSP_EXTRA_FLASH_OPT_H_
#include "typedef.h"
#include "system/event.h"
//*----------------------------------------------------------------------------*/
/**@brief 外部flash操作函数
@param param:数据, len:数据长度,OpCode:命令号,OpCode_SN:数据包序列号
@return 0-成功,其他-失败
@note
*/
/*----------------------------------------------------------------------------*/
int rcsp_extra_flash_opt(u8 *data, u16 len, u8 OpCode, u8 OpCode_SN);
//*----------------------------------------------------------------------------*/
/**@brief 填充表盘操作第一条命令的数据回复包
@param resp_data:数据回复包
@return 负数-失败,正数-数据长度
@note
*/
/*----------------------------------------------------------------------------*/
int rcsp_get_extra_flash_info(void *priv, u8 *resp_data);
//*----------------------------------------------------------------------------*/
/**@brief 外部flash开始操作
@param
@return 0-成功,其他-失败
@note
*/
/*----------------------------------------------------------------------------*/
int rcsp_extra_flash_opt_start(void);
//*----------------------------------------------------------------------------*/
/**@brief 外部flash结束操作
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_extra_flash_opt_stop(void);
//*----------------------------------------------------------------------------*/
/**@brief 主动通知app当前表盘路径,用于表盘操作
@param file_path:路径名,file_path_size:路名名长度
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_extra_flash_opt_dial_nodify(void);
//*----------------------------------------------------------------------------*/
/**@brief 主动通知app当前表盘背景路径,用于表盘操作
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_extra_flash_opt_dial_backgroud_nodify(void);
//*----------------------------------------------------------------------------*/
/**@brief 设置异常状态标志位
@param eflash_state_type:标志位
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_eflash_flag_set(u8 eflash_state_type);
//*----------------------------------------------------------------------------*/
/**@brief 获取异常状态标志位
@param
@return 1-处于异常,0-正常
@note
*/
/*----------------------------------------------------------------------------*/
u8 rcsp_eflash_flag_get(void);
//*----------------------------------------------------------------------------*/
/**@brief 获取升级异常状态标志位
@param
@return 1-处于异常,0-正常
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_eflash_update_flag_set(u8 eflash_state_type);
//*----------------------------------------------------------------------------*/
/**@brief 获取升级异常状态标志位
@param
@return 1-处于异常,0-正常
@note
*/
/*----------------------------------------------------------------------------*/
u8 rcsp_eflash_update_flag_get(void);
// rcsp外挂flash初始化
void rcsp_extra_flash_init(void);
// rcsp外挂flash事件处理
int rcsp_extra_flash_event_deal(int *msg);
// rcsp外挂flash关闭
void rcsp_extra_flash_close(void);
// rcsp外挂flash无线断开后操作
void rcsp_extra_flash_disconnect_tips(u32 sec);
//*----------------------------------------------------------------------------*/
/**@brief 检查当前是否处于表盘升级状态
@param param:状态标志
@return true-处于升级状态,false-其他状态
@note
*/
/*----------------------------------------------------------------------------*/
bool rcsp_exflash_flash_opt_check(void *param);
//*----------------------------------------------------------------------------*/
/**@brief 大文件传输表盘开始/结束操作
@param 0 大文件续传
1 新文件(不做任何操作)
2 插入结束
3 更新表盘与背景关系
4 删除表盘
-1 重命名前删除重名文件
@return 0 成功
1 写失败
2 数据超出范围
3 crc校验失败
4 内存不足
@note
*/
/*----------------------------------------------------------------------------*/
int rcsp_file_transfer_watch_opt(u8 flag, char *root_path);
#endif
@@ -0,0 +1,90 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".dev_format.data.bss")
#pragma data_seg(".dev_format.data")
#pragma const_seg(".dev_format.text.const")
#pragma code_seg(".dev_format.text")
#endif
#include "dev_format.h"
#include "rcsp.h"
#include "dev_manager.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE)
#include "fs/fs.h"
enum {
DEV_FORMAT_ERR_NONE = 0,
DEV_FORMAT_ERR_OFFLINE,
DEV_FORMAT_ERR_FAIL,
};
void (*end_cbk)(void) = NULL;
//*----------------------------------------------------------------------------*/
/**@brief 设备格式化初始化(手机客户端发指令)
@param
@return 格式化完成回调
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_dev_format_init(void (*end_callback)(void))
{
end_cbk = end_callback;
}
//*----------------------------------------------------------------------------*/
/**@brief 设备格式化退出
@param
@return 格式化完成回调
@note
*/
/*----------------------------------------------------------------------------*/
static void dev_format_close(void)
{
if (end_cbk) {
end_cbk();
}
}
//*----------------------------------------------------------------------------*/
/**@brief 设备格式化处理响应(手机客户端发指令)
@param
@return 格式化完成回调
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_dev_format_start(u8 OpCode_SN, u8 *data, u16 len)
{
u8 reason = DEV_FORMAT_ERR_NONE;
u32 dev_handle = READ_BIG_U32(data);
char *logo = rcsp_browser_dev_remap(dev_handle);
if (logo == NULL) {
reason = DEV_FORMAT_ERR_FAIL ;
JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1, 0, NULL);
dev_format_close();
return ;
}
char *root_path = dev_manager_get_root_path_by_logo(logo);
if (root_path) {
wdt_disable();
int err = f_format(root_path, "fat", 0);
wdt_enable();
if (err) {
reason = DEV_FORMAT_ERR_FAIL ;
JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1, 0, NULL);
} else {
printf("dev format ok\n");
JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_SUCCESS, OpCode_SN, &reason, 1, 0, NULL);
dev_format_close();
return ;
}
} else {
reason = DEV_FORMAT_ERR_OFFLINE ;
JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1, 0, NULL);
}
dev_format_close();
printf("dev format fail\n");
}
#endif
@@ -0,0 +1,26 @@
#ifndef __DEV_FORMAT_H__
#define __DEV_FORMAT_H__
#include "typedef.h"
#include "app_config.h"
//*----------------------------------------------------------------------------*/
/**@brief 设备格式化初始化(手机客户端发指令)
@param
@return 格式化完成回调
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_dev_format_init(void (*end_callback)(void));
//*----------------------------------------------------------------------------*/
/**@brief 设备格式化处理响应(手机客户端发指令)
@param
@return 格式化完成回调
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_dev_format_start(u8 OpCode_SN, u8 *data, u16 len);
#endif//__DEV_FORMAT_H__
@@ -0,0 +1,60 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_bluk_trans_prepare.data.bss")
#pragma data_seg(".file_bluk_trans_prepare.data")
#pragma const_seg(".file_bluk_trans_prepare.text.const")
#pragma code_seg(".file_bluk_trans_prepare.text")
#endif
#include "file_bluk_trans_prepare.h"
#include "rcsp.h"
#include "system/includes.h"
#include "file_operate/file_manager.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE)
enum {
FILE_BLUK_TRANS_BEGIN,
FILE_BLUK_TRANS_END = 0x80,
FILE_BLUK_TRANS_CANCEL = 0x81,
};
static void (*g_end_callback)(void);
//文件流传输准备
void rcsp_file_bluk_trans_prepare(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int ret = 0;
u8 offset = 0;
u8 op = data[offset++];
u8 resp_data[2] = {0};
resp_data[0] = op;
switch (op) {
case FILE_BLUK_TRANS_BEGIN:
app_rcsp_task_prepare(0, RCSP_TASK_ACTION_BLUK_TRANSFER, OpCode_SN);
break;
case FILE_BLUK_TRANS_CANCEL:
case FILE_BLUK_TRANS_END:
rcsp_file_bluk_trans_close(0);
break;
}
JL_CMD_response_send(JL_OPCODE_FILE_BLUK_TRANSFER, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp_data, sizeof(resp_data), 0, NULL);
}
//文件流传输初始化
void rcsp_file_bluk_trans_init(void (*end_callback)(void))
{
g_end_callback = end_callback;
}
//文件流传输关闭
void rcsp_file_bluk_trans_close(u8 dire)
{
if (g_end_callback) {
g_end_callback();
g_end_callback = NULL;
if (dire) {
u8 resp_data[2] = {FILE_BLUK_TRANS_CANCEL, 0};
JL_CMD_send(JL_OPCODE_FILE_BLUK_TRANSFER, resp_data, sizeof(resp_data), 1, 0, NULL);
}
}
}
#endif
@@ -0,0 +1,14 @@
#ifndef __FILE_BLUK_TRANS_PREPARE_H__
#define __FILE_BLUK_TRANS_PREPARE_H__
#include "typedef.h"
#include "app_config.h"
//文件流传输准备
void rcsp_file_bluk_trans_prepare(void *priv, u8 OpCode_SN, u8 *data, u16 len);
//文件流传输初始化
void rcsp_file_bluk_trans_init(void (*end_callback)(void));
//文件流传输关闭
void rcsp_file_bluk_trans_close(u8 dire);
#endif
@@ -0,0 +1,433 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_delete.data.bss")
#pragma data_seg(".file_delete.data")
#pragma const_seg(".file_delete.text.const")
#pragma code_seg(".file_delete.text")
#endif
#include "file_delete.h"
#include "rcsp.h"
#include "includes.h"
#include "fs/fs.h"
#include "dev_manager.h"
#include "key_event_deal.h"
/* #include "app_task.h" */
/* #include "app_task.h" */
#include "app_msg.h"
#include "file_operate/file_manager.h"
#include "rcsp_browser.h"
#include "music/music_player.h"
#include "rcsp_extra_flash_opt.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE)
#include "media/file_decoder.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[file del]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define FILE_DELELET_TIMEOUT (10*1000)
#define FILE_DEL_DEBUG_EN
#ifdef FILE_DEL_DEBUG_EN
#define file_del_printf log_info
#else
#define file_del_printf(...)
#endif
struct __file_del {
struct __dev *dev;//当前设备节点
struct vfscan *fsn;//设备扫描句柄
u8 scandisk_break;
u8 busy;
u16 timerout;
void (*end_callback)(void);
};
struct __file_del *file_d = NULL;
#define __this file_d
///播放参数,文件扫描时用,文件后缀等
static const char scan_parm[] = "-t"
#if (WATCH_FILE_TO_FLASH)
"ALL"
#else // WATCH_FILE_TO_FLASH
#if (TCFG_DEC_MP3_ENABLE)
"MP1MP2MP3"
#endif
#if (TCFG_DEC_WMA_ENABLE)
"WMA"
#endif
#if ( TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE)
"WAVDTS"
#endif
#if (TCFG_DEC_FLAC_ENABLE)
"FLA"
#endif
#if (TCFG_DEC_APE_ENABLE)
"APE"
#endif
#if (TCFG_DEC_M4A_ENABLE)
"M4AAAC"
#endif
#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE)
"MP4"
#endif
#if (TCFG_DEC_AMR_ENABLE)
"AMR"
#endif
#if (TCFG_DEC_DECRYPT_ENABLE)
"SMP"
#endif
#if (TCFG_DEC_MIDI_ENABLE)
"MID"
#endif
"TMP"
#endif // WATCH_FILE_TO_FLASH
" -sn -r"
;
//*----------------------------------------------------------------------------*/
/**@brief 文件删除扫盘匹配文件过程系统消息获取处理接口
@param
@return 1:中断文件扫描处理, 0:继续扫盘
@note 可以在这个函数内相应所需的消息事件
*/
/*----------------------------------------------------------------------------*/
static int file_delete_scandisk_break(void)
{
///注意:
///需要break fsn的事件, 请在这里拦截,
int msg[32] = {0};
struct sys_event *event = NULL;
char *logo = NULL;
char *evt_logo = NULL;
#if (RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
app_task_get_msg(msg, ARRAY_SIZE(msg), 0);
switch (msg[0]) {
case APP_MSG_SYS_EVENT:
event = (struct sys_event *)(&msg[1]);
switch (event->type) {
case SYS_DEVICE_EVENT:
switch ((u32)event->arg) {
case DRIVER_EVENT_FROM_SD0:
case DRIVER_EVENT_FROM_SD1:
case DRIVER_EVENT_FROM_SD2:
evt_logo = (char *)event->u.dev.value;
case DEVICE_EVENT_FROM_OTG:
if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) {
evt_logo = (char *)"udisk0";
}
///设备上下线底层推出的设备逻辑盘符是跟跟音乐设备一致的(音乐/录音设备, 详细看接口注释)
logo = dev_manager_get_phy_logo(__this->dev);
///响应设备插拔打断
if (event->u.dev.event == DEVICE_EVENT_OUT) {
log_i("__func__ = %s logo=%s evt_logo=%s \n", __FUNCTION__, logo, evt_logo);
if (logo && evt_logo && (0 == strcmp(logo, evt_logo))) {
///相同的设备才响应
__this->scandisk_break = 1;
}
} else {
///响应新设备上线
__this->scandisk_break = 1;
}
if (__this->scandisk_break == 0) {
log_i("__func__ = %s DEVICE_EVENT_OUT TODO\n", __FUNCTION__);
#if RCSP_MODE != RCSP_MODE_EARPHONE
dev_status_event_filter(event);
#endif
log_i("__func__ = %s DEVICE_EVENT_OUT OK\n", __FUNCTION__);
}
break;
}
break;
case SYS_BT_EVENT:
if (bt_background_event_handler_filter(event)) {
__this->scandisk_break = 1;
}
break;
case SYS_KEY_EVENT:
switch (event->u.key.event) {
case KEY_CHANGE_MODE:
///响应切换模式事件
__this->scandisk_break = 1;
break;
}
if (__this->scandisk_break) {
app_task_put_key_msg(event->u.key.event, (int)event->u.key.value);
return -1;
}
break;
}
break;
}
#endif
if (__this->scandisk_break) {
///查询到需要打断的事件, 返回1, 并且重新推送一次该事件,跑主循环处理流程
#if (RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
file_del_printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__);
sys_event_notify(event);
file_del_printf("scandisk_break!!!!!!\n");
#endif
return 1;
} else {
return 0;
}
}
static void scan_enter(struct __dev *dev)
{
__this->busy = 1;
#if (RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
clock_add_set(SCAN_DISK_CLK);
#endif
}
static void scan_exit(struct __dev *dev)
{
#if (RCSP_MSG_DISTRIBUTION_VER != RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
clock_remove_set(SCAN_DISK_CLK);
#endif
__this->busy = 0;
}
static const struct __scan_callback scan_cb = {
.enter = scan_enter,
.exit = scan_exit,
.scan_break = file_delete_scandisk_break,
};
//*----------------------------------------------------------------------------*/
/**@brief 文件删除超时处理
@param
@return
@note 这里是等待手机删除命令超时(即没有等到删除命令)
*/
/*----------------------------------------------------------------------------*/
static void file_delete_timeout(void *p)
{
//批量删除超时, 退出删除流程
if (__this && __this->timerout) {
file_del_printf("file_delete_timeout !!\n");
rcsp_file_delete_end();
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件删除结束处理
@param
@return
@note 释放资源
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_delete_end(void)
{
if (__this) {
if (__this->fsn) {
fscan_release(__this->fsn);
}
if (__this->timerout) {
sys_timeout_del(__this->timerout);
__this->timerout = 0;
}
if (__this->end_callback) {
__this->end_callback();
}
free(__this);
__this = NULL;
file_del_printf("rcsp_file_delete_end\n");
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件删除开始处理
@param OpCode_SN:命名包的sn码, 命名回复时用到
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_watch_opt(u32 dev_handle, u8 flag)
{
if (RCSPDevMapFLASH == dev_handle
|| RCSPDevMapFLASH_2 == dev_handle) {
char *root_path = NULL;
if (__this->dev) {
root_path = dev_manager_get_root_path(__this->dev);
}
#if JL_RCSP_EXTRA_FLASH_OPT
rcsp_file_transfer_watch_opt(flag, root_path);
#endif
}
}
static int file_delete_func(FILE *file)
{
int err = 0;
if (NULL == file) {
err = -1;
goto __file_delete_func_end;
}
#if (RCSP_MSG_DISTRIBUTION_VER == RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
// RCSP TODO:
log_info("RCSP TODO!!!");
#else
int music_state = music_player_get_play_status();
if (FILE_DEC_STATUS_PLAY == music_state) {
app_task_put_key_msg(KEY_MUSIC_PP, 0);
}
#endif
err = fdelete(file);
if (err) {
log_error("[%s, %d] fail!!, replay cur file\n", __FUNCTION__, __LINE__);
err = -1;
goto __file_delete_func_end;
} else {
#if (RCSP_MSG_DISTRIBUTION_VER == RCSP_MSG_DISTRIBUTION_VER_VISUAL_CFG_TOOL)
// RCSP TODO:
log_info("RCSP TODO!!!");
#else
log_info("[%s, %d] ok, play next file\n", __FUNCTION__, __LINE__);
if (FILE_DEC_STATUS_PLAY == music_state) {
err = app_task_put_key_msg(KEY_MUSIC_PP, 0);
}
#endif
}
__file_delete_func_end:
return err;
}
//文件删除命令处理
void rcsp_file_delete_start(u8 OpCode_SN, u8 *data, u16 len)
{
FILE *file = NULL;
u8 reason = 0;
u8 last = data[0];
u32 dev_handle = READ_BIG_U32(data + 1);
u8 type = data[5];
u32 sclust = READ_BIG_U32(data + 6);
file_del_printf("last = %d,dev_handle = %d,sclust = %d,type = %d,\n", last, dev_handle, sclust, type);
char *logo = rcsp_browser_dev_remap(dev_handle);
if (logo == NULL) {
goto __err;
}
if (__this == NULL) {
__this = zalloc(sizeof(struct __file_del));
if (__this == NULL) {
goto __err;
}
}
if (__this->timerout) {
sys_timeout_del(__this->timerout);
__this->timerout = 0;
}
if (__this->fsn == NULL) {
__this->dev = dev_manager_find_spec(logo, 0);
if (!__this->dev) {
free(__this);
__this = NULL;
goto __err;
}
if (__this->dev) {
__this->fsn = file_manager_scan_disk(__this->dev, NULL, scan_parm, 0, (struct __scan_callback *)&scan_cb);
if (__this->fsn == NULL) {
free(__this);
__this = NULL;
goto __err;
}
file_del_printf("%s, fscan ok\n", __FUNCTION__);
}
} else {
file_del_printf("%s, fscan aready\n", __FUNCTION__);
if (__this->busy) {
//正在执行删除, 回复APP繁忙
log_error("file delete busy\n");
JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_BUSY, OpCode_SN, NULL, 0, 0, NULL);
return ;
}
}
file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, (struct __scan_callback *)&scan_cb);//根据文件簇号查找断点文件
if (file) {
#if (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP
extern void rcsp_common_info_del_wallpaper(FILE * flie);
rcsp_common_info_del_wallpaper(file);
#endif
file_delete_func(file);
/* fdelete(file); */
file_del_printf("delete file ok!!\n");
JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, 0, NULL);
if (last == 0) {
if (__this->timerout == 0) {
__this->timerout = sys_timeout_add(NULL, file_delete_timeout, FILE_DELELET_TIMEOUT);
} else {
sys_timer_modify(__this->timerout, FILE_DELELET_TIMEOUT);
}
//批量删除, 还没有删除完毕, 等待继续删除
file_del_printf("wait delete file more\n");
return;
}
file_transfer_watch_opt(dev_handle, 4);
} else {
file_del_printf("file delete, no this file\n");
JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_PARAM_ERR, OpCode_SN, NULL, 0, 0, NULL);
}
rcsp_file_delete_end();
return ;
__err:
JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
rcsp_file_delete_end();
}
//*----------------------------------------------------------------------------*/
/**@brief 文件删除初始化
@param end_callback:文件删除结束回调处理
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_delete_init(void (*end_callback)(void))
{
if (__this) {
log_error("rcsp_file_delete_init aready err!!\n");
return ;
}
__this = zalloc(sizeof(struct __file_del));
if (__this == NULL) {
log_error("rcsp_file_delete_init fail\n");
if (end_callback) {
end_callback();
}
return ;
}
__this->end_callback = end_callback;
//启动定时器, 防止APP后续没有发执行删除的命令过来, 可以超时退出
__this->timerout = sys_timeout_add(NULL, file_delete_timeout, 2000);
}
#define PHONE_BOOK_PATH "storage/sd1/C/DOWNLOAD/call.txt"
void rcsp_file_delete_one_file(u8 OpCode_SN, u8 *data, u16 len)
{
FILE *file = fopen(PHONE_BOOK_PATH, "r");
if (file) {
fdelete(file);
}
JL_CMD_response_send(JL_OPCODE_ONE_FILE_DELETE, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, 0, NULL);
}
#endif
@@ -0,0 +1,29 @@
#ifndef __FILE_DELETE_H__
#define __FILE_DELETE_H__
#include "typedef.h"
#include "app_config.h"
//*----------------------------------------------------------------------------*/
/**@brief 文件删除初始化
@param end_callback:文件删除结束回调处理
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_delete_init(void (*end_callback)(void));
//文件删除命令处理
void rcsp_file_delete_start(u8 OpCode_SN, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件删除结束处理
@param
@return
@note 释放资源
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_delete_end(void);
// 删除一个文件
void rcsp_file_delete_one_file(u8 OpCode_SN, u8 *data, u16 len);
#endif//__FILE_DELETE_H__
@@ -0,0 +1,415 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_simple_transfer.data.bss")
#pragma data_seg(".file_simple_transfer.data")
#pragma const_seg(".file_simple_transfer.text.const")
#pragma code_seg(".file_simple_transfer.text")
#endif
#include "rcsp_config.h"
#include "file_simple_transfer.h"
#include "system/includes.h"
#include "fs/fs.h"
#include "dev_manager.h"
#include "JL_rcsp_protocol.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE && JL_RCSP_SIMPLE_TRANSFER)
#define FILE_SIMPLE_TRANSFER_VERSION 0
static rcsp_simple_trans_opt *g_rcsp_simple_trans_opt = NULL;
#define __this g_rcsp_simple_trans_opt
enum {
FILE_SIMPLE_OPT_QUERY,
FILE_SIMPLE_OPT_READ,
FILE_SIMPLE_OPT_INSERT,
FILE_SIMPLE_OPT_UPDATE,
FILE_SIMPLE_OPT_DELETE,
};
static int file_simple_opt_get_id_table(u8 type, u8 *data[], u8 reserved_len)
{
int data_len = 0;
if (NULL == __this) {
printf("err : please specify the simple file opt interface\n");
goto __file_simple_opt_get_id_table_end;
}
if (!__this->get_id_table_len || !__this->get_id_table) {
printf("err : get_id_table_len or get_id_table interface is NULL\n");
goto __file_simple_opt_get_id_table_end;
}
data_len = __this->get_id_table_len(type);
if (!data_len) {
printf("err : id table is empty\n");
goto __file_simple_opt_get_id_table_end;
}
*data = zalloc(data_len + reserved_len);
if (NULL == *data) {
printf("%s is no ram\n", __func__);
data_len = 0;
goto __file_simple_opt_get_id_table_end;
}
if (!__this->get_id_table(type, *data + reserved_len, data_len)) {
printf("err : get id table fail\n");
data_len = 0;
goto __file_simple_opt_get_id_table_end;
}
__file_simple_opt_get_id_table_end:
return data_len;
}
static void file_simple_opt_query(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
u16 index = 0;
u8 file_type = data[0];
u8 *resp_data = NULL;
u16 reserved_len = 2;
int resp_len = file_simple_opt_get_id_table(file_type, &resp_data, reserved_len);
if (!resp_len) {
goto __file_simple_opt_query_end;
}
index = reserved_len;
for (u16 i = reserved_len; i < resp_len + reserved_len; i += 4) {
if (0 == (resp_data[i + 2] | resp_data[i + 3])) {
continue;
}
if (index != i) {
memcpy(resp_data + index, resp_data + i, 4);
}
// id变成大端
resp_data[index] ^= resp_data[index + 1];
resp_data[index + 1] ^= resp_data[index];
resp_data[index] ^= resp_data[index + 1];
// size变成大端
resp_data[index + 2] ^= resp_data[index + 3];
resp_data[index + 3] ^= resp_data[index + 2];
resp_data[index + 2] ^= resp_data[index + 3];
index += 4;
}
__file_simple_opt_query_end:
if (index > reserved_len) {
resp_data[0] = FILE_SIMPLE_OPT_QUERY;
resp_data[1] = FILE_SIMPLE_TRANSFER_VERSION;
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp_data, index, 0, NULL);
} else {
// 防止使用resp_data时是空
data[0] = FILE_SIMPLE_OPT_QUERY;
data[1] = FILE_SIMPLE_TRANSFER_VERSION;
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, 2, 0, NULL);
}
if (resp_data) {
free(resp_data);
}
}
static void file_simple_opt_read(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int index = 0;
u16 offset = 0;
u8 file_type = data[offset + 0];
u16 file_id = data[offset + 1] << 8 | data[offset + 2];
u16 file_offset = data[offset + 3] << 8 | data[offset + 4];
u16 data_len = data[offset + 5] << 8 | data[offset + 6];
u8 package_flag = data[offset + 7];
static u16 data_crc = 0;
// 通过回复把数据返回
u8 *resp_data = NULL;
int resp_len = 0;
if (package_flag) {
data_crc = 0;
}
if (data_len + 1 > (JL_packet_get_tx_max_mtu() - 8)) {
printf("err : data_len is bigger then resp_max_len\n");
goto __file_simple_opt_read_end;
}
resp_len = file_simple_opt_get_id_table(file_type, &resp_data, 0);
if (0 == resp_len) {
goto __file_simple_opt_read_end;
}
for (index = 0; index < resp_len / 4; index++) {
if (0 == memcmp(resp_data + index * 4, &file_id, sizeof(file_id))) {
break;
}
}
if (index == resp_len / 4) {
printf("file id : %x is vaild\n", file_id);
resp_len = 0;
goto __file_simple_opt_read_end;
}
if (0 == (resp_data[index * 4 + 2] | resp_data[index * 4 + 3])) {
resp_len = 0;
printf("file type : %x, file id : %d, file data is empty\n", file_type, file_id);
goto __file_simple_opt_read_end;
}
if (__this->read_file_by_id) {
resp_len = __this->read_file_by_id(file_type, file_id, file_offset, data + 4, data_len);
if (!resp_len) {
printf("err : read data fail %d\n", data_len);
goto __file_simple_opt_read_end;
} else {
// 计算crc
data_len = resp_len;
data_crc = CRC16_with_initval(data + 4, data_len, data_crc);//calc_crc16_with_init_val(data_crc, data + 4, data_len);
data[2] = ((u8 *)&data_crc)[1];
data[3] = ((u8 *)&data_crc)[0];
}
}
__file_simple_opt_read_end:
data[0] = FILE_SIMPLE_OPT_READ;
if (resp_len) {
data[1] = 0;
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, data_len + 4, 0, NULL);
} else {
data[1] = 1;
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, 2, 0, NULL);
}
if (resp_data) {
free(resp_data);
}
}
static void file_simple_opt_insert(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int index = 0;
u16 offset = 0;
u8 file_type = data[offset + 0];
u16 file_offset = data[offset + 1] << 8 | data[offset + 2];
u16 file_size = data[offset + 3] << 8 | data[offset + 4];
u16 verify_crc = data[offset + 5] << 8 | data[offset + 6];
offset = 7;
u16 file_id = 0;
u8 *file_data = data + offset;
u8 *resp_data = NULL;
static u16 data_crc = 0;
if (0 == file_offset) {
data_crc = 0;
}
data_crc = CRC16_with_initval(file_data, len - offset, data_crc);//calc_crc16_with_init_val(data_crc, file_data, len - offset);
if (data_crc != verify_crc) {
printf("err : crc verify is err\n");
data[1] = 3;
goto __file_simple_opt_insert_end;
}
if (__this->insert_file_by_id) {
if (__this->insert_file_by_id(file_type, &file_id, file_offset, file_data, len - offset, file_size)) {
printf("err : insert data fail\n");
data[1] = 1;
goto __file_simple_opt_insert_end;
}
}
data[1] = 0;
int resp_len = 2;
if ((file_offset + len - offset) == file_size) {
// 成功且最后一包
data[2] = ((u8 *)&file_id)[1];
data[3] = ((u8 *)&file_id)[0];
resp_len += 2;
}
__file_simple_opt_insert_end:
data[0] = FILE_SIMPLE_OPT_INSERT;
if (data[1]) {
resp_len = 2;
}
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, resp_len, 0, NULL);
if (resp_data) {
free(resp_data);
}
return;
}
static void file_simple_opt_update(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int index = 0;
u16 offset = 0;
u8 file_type = data[offset + 0];
u16 file_id = data[offset + 1] << 8 | data[offset + 2];
u16 file_offset = data[offset + 3] << 8 | data[offset + 4];
u16 file_size = data[offset + 5] << 8 | data[offset + 6];
u16 verify_crc = data[offset + 7] << 8 | data[offset + 8];
offset = 9;
u8 *file_data = data + offset;
u8 *resp_data = NULL;
int resp_len = 0;
static u16 data_crc = 0;
if (0 == file_offset) {
data_crc = 0;
}
resp_len = file_simple_opt_get_id_table(file_type, &resp_data, 0);
resp_len /= 4;
if (0 == resp_len) {
goto __file_simple_opt_update_end;
}
for (index = 0; index < resp_len; index++) {
if (0 == memcmp(resp_data + index * 4, &file_id, sizeof(file_id))) {
break;
}
}
if (index == resp_len) {
printf("file id : %x is vaild fail\n", file_id);
resp_len = 0;
goto __file_simple_opt_update_end;
}
if (0 == (resp_data[index * 4 + 2] | resp_data[index * 4 + 3])) {
printf("file type : %x, file id : %d, file data is empty\n", file_type, file_id);
resp_len = 0;
goto __file_simple_opt_update_end;
}
data_crc = CRC16_with_initval(file_data, len - offset, data_crc);//calc_crc16_with_init_val(data_crc, file_data, len - offset);
if (data_crc != verify_crc) {
printf("err : crc verify is err\n");
data[1] = 3;
goto __file_simple_opt_update_end;
}
if (__this->update_file_by_id) {
if (__this->update_file_by_id(file_type, file_id, file_offset, file_data, len - offset, file_size)) {
printf("err : update file fail\n");
resp_len = 0;
goto __file_simple_opt_update_end;
}
}
__file_simple_opt_update_end:
data[0] = FILE_SIMPLE_OPT_UPDATE;
if (resp_len) {
data[1] = 0;
} else {
data[1] = 1;
}
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, 2, 0, NULL);
if (resp_data) {
free(resp_data);
}
return;
}
static void file_simple_opt_delete(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int index = 0;
u16 offset = 0;
u8 file_type = data[offset + 0];
u16 file_id = data[offset + 1] << 8 | data[offset + 2];
u8 *resp_data = NULL;
int resp_len = 0;
resp_len = file_simple_opt_get_id_table(file_type, &resp_data, 0);
resp_len /= 4;
if (0 == resp_len) {
goto __file_simple_opt_delete_end;
}
for (index = 0; index < resp_len; index++) {
if (0 == memcmp(resp_data + index * 4, &file_id, sizeof(file_id))) {
break;
}
}
if (index == resp_len) {
printf("file type : %x, file id : %d, file data is null\n", file_type, file_id);
resp_len = 0;
goto __file_simple_opt_delete_end;
}
if (0 == (resp_data[index * 4 + 2] | resp_data[index * 4 + 3])) {
printf("file type : %x, file id : %d, file data is empty\n", file_type, file_id);
resp_len = 0;
goto __file_simple_opt_delete_end;
}
if (__this->delete_file_by_id) {
if (__this->delete_file_by_id(file_type, file_id)) {
printf("err : delete file fail\n");
resp_len = 0;
goto __file_simple_opt_delete_end;
}
}
__file_simple_opt_delete_end:
data[0] = FILE_SIMPLE_OPT_DELETE;
if (resp_len) {
data[1] = 0;
} else {
data[1] = 1;
}
JL_CMD_response_send(JL_OPCODE_SIMPLE_FILE_TRANS, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, 2, 0, NULL);
if (resp_data) {
free(resp_data);
}
return;
}
// rcsp小文件传输命令处理
void rcsp_file_simple_transfer_for_small_file(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
u8 op = data[0];
switch (op) {
case FILE_SIMPLE_OPT_QUERY:
file_simple_opt_query(priv, OpCode_SN, data + 1, len - 1);
break;
case FILE_SIMPLE_OPT_READ:
file_simple_opt_read(priv, OpCode_SN, data + 1, len - 1);
break;
case FILE_SIMPLE_OPT_INSERT:
file_simple_opt_insert(priv, OpCode_SN, data + 1, len - 1);
break;
case FILE_SIMPLE_OPT_UPDATE:
file_simple_opt_update(priv, OpCode_SN, data + 1, len - 1);
break;
case FILE_SIMPLE_OPT_DELETE:
file_simple_opt_delete(priv, OpCode_SN, data + 1, len - 1);
break;
}
}
// rcsp注册小文件传输操作结构体
int rcsp_register_file_simple_transfer_interface(rcsp_simple_trans_opt *file_simple_transfer_interface)
{
g_rcsp_simple_trans_opt = file_simple_transfer_interface;
return 0;
}
#endif
@@ -0,0 +1,27 @@
#ifndef __FILE_SIMPLE_TRANSFER_H__
#define __FILE_SIMPLE_TRANSFER_H__
#include "typedef.h"
#include "app_config.h"
typedef struct file_simple_transfer_opt {
// 返回长度(成功)/0(失败) 根据当前文件类型获取id表长度(传入 文件类型),该接口返回的长度是 [id(2byte) + file_size(没有文件就是0,但都是占2个byte的位置)] * n
int (*get_id_table_len)(u8 file_type);
// 成功返回长度/失败0 根据类型获取文件id列表(传入 文件类型),table_data用于存放返回数据,返回的数据格式:[id(2byte) + file_size(没有文件就是0,但都是占2个byte的位置)] * n
int (*get_id_table)(u8 file_type, u8 *table_data, u16 data_len);
// 成功返回数据长度/失败0 读取文件(文件id,数据偏移,数据,数据长度)
int (*read_file_by_id)(u8 file_type, u16 id, u32 data_offset, u8 *data, u16 data_len);
// 成功返回0/失败非0 新增文件(文件id,数据偏移,数据,数据长度)
int (*insert_file_by_id)(u8 file_type, u16 *id, u32 data_offset, u8 *data, u16 data_len, u16 file_total_size);
// 成功返回0/失败非0 更新文件(文件id,数据偏移,数据,数据长度)
int (*update_file_by_id)(u8 file_type, u16 id, u32 data_offset, u8 *data, u16 data_len, u16 file_total_size);
// 成功返回0/失败非0 删除文件(文件id)
int (*delete_file_by_id)(u8 file_type, u16 id);
} rcsp_simple_trans_opt;
// rcsp小文件传输命令处理
void rcsp_file_simple_transfer_for_small_file(void *priv, u8 OpCode_SN, u8 *data, u16 len);
// rcsp注册小文件传输操作结构体
int rcsp_register_file_simple_transfer_interface(rcsp_simple_trans_opt *file_simple_transfer_interface);
#endif
@@ -0,0 +1,428 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_trans_back.data.bss")
#pragma data_seg(".file_trans_back.data")
#pragma const_seg(".file_trans_back.text.const")
#pragma code_seg(".file_trans_back.text")
#endif
#include "file_trans_back.h"
#include "rcsp.h"
#include "system/includes.h"
#include "file_operate/file_manager.h"
#include "rcsp_browser.h"
#include "fs/fs.h"
#include "rcsp_manage.h"
#include "rcsp_event.h"
#include "rcsp_config.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_packet.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE)
#include "dev_status.h"
#define FTP_DOWNLOAD_FOLDER_NAME "download" //下载目录
#define FILE_TRANS_BACK_TASK_NAME "ftran_back"
enum {
FILE_TRANS_BACK_BY_NAME,
FILE_TRANS_BACK_BY_CLUST,
FILE_TRANS_BACK_BY_NAME_2,
FILE_TRANS_BACK_FINISH = 0x80,
FILE_TRANS_BACK_CANCEL = 0x81,
};
struct __file_trans_back {
FILE *file;
struct __dev *dev;
struct vfscan *fsn;
void (*end_callback)(void);
u8 OpCode_SN;
u8 op;
};
///播放参数,文件扫描时用,文件后缀等
static const char scan_parm[] = "-t"
#if (WATCH_FILE_TO_FLASH)
"ALL"
#else // WATCH_FILE_TO_FLASH
#if (TCFG_DEC_MP3_ENABLE)
"MP1MP2MP3"
#endif
#if (TCFG_DEC_WMA_ENABLE)
"WMA"
#endif
#if ( TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE)
"WAVDTS"
#endif
#if (TCFG_DEC_FLAC_ENABLE)
"FLA"
#endif
#if (TCFG_DEC_APE_ENABLE)
"APE"
#endif
#if (TCFG_DEC_M4A_ENABLE)
"M4AAAC"
#endif
#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE)
"MP4"
#endif
#if (TCFG_DEC_AMR_ENABLE)
"AMR"
#endif
#if (TCFG_DEC_DECRYPT_ENABLE)
"SMP"
#endif
#if (TCFG_DEC_MIDI_ENABLE)
"MID"
#endif
"TMP"
#endif // WATCH_FILE_TO_FLASH
" -sn -r"
;
static struct __file_trans_back *trans_back = NULL;
static u8 g_trans_back_cancel_flag = -1;
static u32 g_dev_handle = RCSPDevMapSD1;
extern u8 check_le_pakcet_sent_finish_flag(void);
extern bool rcsp_send_list_is_empty(void);
extern void file_trans_idle_set(u8 file_trans_idle_flag);
static int get_file_prepare(u32 dev_handle)
{
char *logo = rcsp_browser_dev_remap(dev_handle);
if (NULL == logo) {
printf("trans_back logo is null");
return -1;
}
struct __dev *dev = dev_manager_find_spec(logo, 0);
if (NULL == dev) {
printf("trans_back dev is null");
return -1;
}
if (NULL == trans_back) {
trans_back = zalloc(sizeof(struct __file_trans_back));
if (NULL == trans_back) {
printf("trans_back zalloc err\n");
return -1;
}
trans_back->dev = dev;
}
return 0;
}
static void creat_file_path(char *path, char *root_path, const char *folder, u8 *name, u16 name_len)
{
strcat(path, root_path);
if (folder) {
strcat(path, folder);
strcat(path, "/");
}
//strcat(path, name);
/* memcpy(path + strlen(root_path) + strlen(folder) + 1, name, name_len); */
memcpy(path + strlen(path), name, name_len);
//printf("path = %s\n", path);
}
static u32 creat_path_len(char *root_path, const char *folder, u8 *name, u16 name_len)
{
u32 root_path_len = 0, folder_len = 0;
if (root_path) {
root_path_len = strlen(root_path);
}
if (folder) {
folder_len = strlen(folder);
}
u32 len = (root_path_len + folder_len + name_len + 1);
if (folder) {
len += strlen("/");
}
return len;
}
static u8 file_trans_back_response_send(u8 *data, u16 len, u8 dire, u8 OpCode_SN)
{
u8 ret = 0;
switch (dire) {
case 0:
ret = JL_CMD_response_send(JL_OPCODE_ONE_FILE_TRANS_BACK, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, len, 0, NULL);
break;
case 1:
ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_ONE_FILE_TRANS_BACK, data, len, JL_NOT_NEED_RESPOND, 0, NULL);
break;
case 2:
ret = JL_CMD_send(JL_OPCODE_ONE_FILE_TRANS_BACK, data, len, JL_NEED_RESPOND, 0, NULL);
break;
case 0xFF:
ret = JL_CMD_response_send(JL_OPCODE_ONE_FILE_TRANS_BACK, JL_PRO_STATUS_FAIL, OpCode_SN, data, len, 0, NULL);
break;
}
return ret;
}
static void file_trans_back_task(void *p)
{
struct RcspModel *rcspModel = (struct RcspModel *)p;
// 从文件句柄中获取当前文件的大小
struct vfs_attr attr;
fget_attrs(trans_back->file, &attr);
// 获取文件数据
u32 file_size = attr.fsize;
// 预留 开始头(3byte) + opCode(2byte) + param_len(2byte) + state(1byte) + opCode_SN(1byte) + 结束(1byte)
u16 resp_data_len = JL_packet_get_tx_max_mtu() - 10;
u8 *resp_data = zalloc(resp_data_len);
if (NULL == resp_data) {
// 错误
file_trans_back_response_send(&trans_back->op, sizeof(trans_back->op), (u8) - 1, trans_back->OpCode_SN);
goto __file_trans_back_task_err;
}
// 把大小发送给app
resp_data[0] = trans_back->op;
resp_data[1] = ((u8 *)&file_size)[3];
resp_data[2] = ((u8 *)&file_size)[2];
resp_data[3] = ((u8 *)&file_size)[1];
resp_data[4] = ((u8 *)&file_size)[0];
file_trans_back_response_send(resp_data, sizeof(file_size) + 1, 0, trans_back->OpCode_SN);
// 退出sniff
file_trans_idle_set(0);
u16 crc = 0;
resp_data_len -= 4;
if (FILE_TRANS_BACK_BY_NAME != trans_back->op) {
resp_data_len -= 2;
}
for (u32 offset = 0, data_len = 0, ret = 0; offset < file_size;) {
wdt_clear();
// 假如当前spp或ble断开连接
if (0 == get_rcsp_connect_status()) {
goto __file_trans_back_task_err;
}
if ((u8) - 1 != g_trans_back_cancel_flag) {
break;
}
data_len = (file_size - offset) > resp_data_len ? resp_data_len : file_size - offset;
fseek(trans_back->file, offset, SEEK_SET);
resp_data[0] = ((u8 *)&offset)[3];
resp_data[1] = ((u8 *)&offset)[2];
resp_data[2] = ((u8 *)&offset)[1];
resp_data[3] = ((u8 *)&offset)[0];
if (FILE_TRANS_BACK_BY_NAME == trans_back->op) {
fread(resp_data + 4, data_len, 1, trans_back->file);
} else {
fread(resp_data + 6, data_len, 1, trans_back->file);
// 填充crc
if (JL_ERR_NONE == ret) {
crc = CRC16_with_initval(resp_data + 6, data_len, crc);
}
data_len += 2;
resp_data[4] = crc >> 8;
resp_data[5] = crc & 0xFF;
}
// 发送文件数据
ret = file_trans_back_response_send(resp_data, data_len + 4, 1, trans_back->OpCode_SN);
if (JL_ERR_SEND_DATA_OVER_LIMIT == ret) {
os_time_dly(1);
continue;
}
if (ret) {
printf("file data trans err: %d\n", ret);
break;
}
offset += resp_data_len;
}
while (!(rcsp_send_list_is_empty() && check_le_pakcet_sent_finish_flag())) {
os_time_dly(10);
if (0 == get_rcsp_connect_status()) {
break;
}
}
memset(resp_data, 0, resp_data_len + 1);
if ((u8) - 1 == g_trans_back_cancel_flag) {
// 如果传输完成发送结束命令
resp_data[0] = FILE_TRANS_BACK_FINISH;
file_trans_back_response_send(resp_data, 1 + 4, 2, trans_back->OpCode_SN);
} else {
// 取消
resp_data[0] = FILE_TRANS_BACK_CANCEL;
file_trans_back_response_send(resp_data, 1, 0, trans_back->OpCode_SN);
}
__file_trans_back_task_err:
if (resp_data) {
free(resp_data);
}
file_trans_idle_set(1);
rcsp_msg_post(USER_MSG_RCSP_FILE_TRANS_BACK, 1, (int)p);
while (1) {
os_time_dly(10);
}
}
static int get_file_by_name(void *priv, u8 *data, u16 len)
{
u32 file_offset = data[0] << 24 | data[1] << 16 << data[2] << 8 | data[3];
u8 offset = 4;
u32 param_len = 0;
if (FILE_TRANS_BACK_BY_NAME != trans_back->op) {
param_len = data[offset];
offset++;
}
u8 *file_name = data + offset;
// 拼凑绝对路径
char *root_path = dev_manager_get_root_path(trans_back->dev);
char *folder = NULL;
if (RCSPDevMapFLASH == g_dev_handle ||
RCSPDevMapFLASH_2 == g_dev_handle) {
if ('/' == file_name[0]) {
file_name++;
offset++;
}
} else {
folder = FTP_DOWNLOAD_FOLDER_NAME;
}
char *path = zalloc(creat_path_len(root_path, folder, file_name, len - offset));
creat_file_path(path, root_path, folder, file_name, len - offset);
if (NULL == trans_back->file) {
trans_back->file = fopen(path, "r");
}
if (path) {
free(path);
}
if (NULL == trans_back->file) {
// 文件不存在
goto __get_file_file_by_name_err;
}
if (task_create(file_trans_back_task, priv, FILE_TRANS_BACK_TASK_NAME)) {
goto __get_file_file_by_name_err;
}
return 0;
__get_file_file_by_name_err:
rcsp_file_trans_back_close();
return -1;
}
static int cancel_file_trans_back(u8 OpCode_SN, u8 *data, u16 len)
{
int ret = 0;
if (trans_back) {
trans_back->OpCode_SN = OpCode_SN;
trans_back->op = FILE_TRANS_BACK_CANCEL;
g_trans_back_cancel_flag = data[0];
} else {
ret = -1;
}
return ret;
}
// 关闭向手机发送文件
void rcsp_file_trans_back_close(void)
{
task_kill(FILE_TRANS_BACK_TASK_NAME);
g_trans_back_cancel_flag = -1;
if (trans_back->fsn) {
fscan_release(trans_back->fsn);
trans_back->fsn = NULL;
}
// 关闭文件
if (trans_back->file) {
fclose(trans_back->file);
trans_back->file = NULL;
}
if (trans_back) {
free(trans_back);
trans_back = NULL;
}
}
static int get_file_by_clust(void *priv, u8 *data, u16 len)
{
u32 file_offset = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
u32 cluster = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
// find name by cluster
if (NULL == trans_back->file) {
if (NULL == trans_back->fsn) {
trans_back->fsn = file_manager_scan_disk(trans_back->dev, NULL, scan_parm, 0, NULL);
}
trans_back->file = file_manager_select(trans_back->dev, trans_back->fsn, FSEL_BY_SCLUST, cluster, NULL);
}
if (NULL == trans_back->fsn) {
goto __get_file_by_clust_err;
}
if (NULL == trans_back->file) {
goto __get_file_by_clust_err;
}
if (task_create(file_trans_back_task, priv, FILE_TRANS_BACK_TASK_NAME)) {
goto __get_file_by_clust_err;
}
return 0;
__get_file_by_clust_err:
rcsp_file_trans_back_close();
return -1;
}
// 向手机发送文件
void rcsp_file_trans_back_opt(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
int ret = 0;
u8 offset = 0;
u8 op = data[0];
switch (op) {
case FILE_TRANS_BACK_BY_NAME_2:
g_dev_handle = data[1] << 24 | data[2] << 16 | data[3] << 8 | data[4];
offset = 5;
case FILE_TRANS_BACK_BY_NAME:
ret = get_file_prepare(g_dev_handle);
if (ret) {
break;
}
trans_back->OpCode_SN = OpCode_SN;
trans_back->op = op;
ret = get_file_by_name(priv, data + offset, len - offset);
break;
case FILE_TRANS_BACK_BY_CLUST:
g_dev_handle = data[1] << 24 | data[2] << 16 | data[3] << 8 | data[4];
offset = 5;
ret = get_file_prepare(g_dev_handle);
if (ret) {
break;
}
trans_back->OpCode_SN = OpCode_SN;
trans_back->op = op;
ret = get_file_by_clust(priv, data + offset, len - offset);
break;
case FILE_TRANS_BACK_CANCEL:
ret = cancel_file_trans_back(OpCode_SN, data + 1, len - 1);
break;
}
if (ret) {
file_trans_back_response_send(&op, sizeof(op), (u8) - 1, OpCode_SN);
}
}
#endif
@@ -0,0 +1,12 @@
#ifndef __FILE_TRANS_BACK__
#define __FILE_TRANS_BACK__
#include "typedef.h"
#include "app_config.h"
// 向手机发送文件
void rcsp_file_trans_back_opt(void *priv, u8 OpCode_SN, u8 *data, u16 len);
// 关闭向手机发送文件
void rcsp_file_trans_back_close(void);
#endif
@@ -0,0 +1,964 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_transfer.data.bss")
#pragma data_seg(".file_transfer.data")
#pragma const_seg(".file_transfer.text.const")
#pragma code_seg(".file_transfer.text")
#endif
#include "file_transfer.h"
#include "system/includes.h"
#include "fs/fs.h"
#include "dev_manager.h"
#include "rcsp_browser.h"
#include "rcsp_config.h"
#include "rcsp_extra_flash_opt.h"
#include "JL_rcsp_protocol.h"
#include "ascii.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[file trans]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#if (RCSP_MODE && TCFG_DEV_MANAGER_ENABLE)
#define FTP_FILE_DATA_UNIT (512) //(234)//不能超过RCSP协议的MTU大小
#define FTP_FILE_DATA_RECIEVE_REMAIN_SIZE (128) //接收缓存预留
#define FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE (FTP_FILE_DATA_UNIT + FTP_FILE_DATA_RECIEVE_REMAIN_SIZE)
#define FTP_FILE_DATA_RECIEVE_TIMEOUT (3*1000) //超时拉取数据等待时长, 超时时间到了,自动拉取
#define FTP_DOWNLOAD_FOLDER_NAME "download" //下载目录
#define FTP_FILE_VAILD_MARK "JL_FTP" //断点续传需要用到的文件内容标记
#define FTP_FILE_VAILD_MARK_TIMER_UNIT (10*1000) //单位ms
#define FTP_FILE_CRC_CAC_MAX_COUNTER (100) //文件校验一次校验的数据块个数
#define FTP_FILE_PACKET_CRC_CHECK_EN 1 //文件内容每一包校验使能
#define FTP_FILE_PACKET_CRC_ERR_CONTINUE_EN 0 //出现包crc错之后是否需要继续传输, 如果是测试, 可以设置为0, 会通知APP停止传输
/* #define FTP_DEBUG_ENABLE */
#ifdef FTP_DEBUG_ENABLE
#define ftp_printf log_info
#else
#define ftp_printf(...)
#endif//FTP_DEBUG_ENABLE
enum {
FTP_END_REASON_NONE = 0, //没有错误
FTP_END_REASON_WRITE_ERR, //写失败
FTP_END_REASON_DATA_OVER_LIMIT, //数据超范围
FTP_END_REASON_DATA_CRC_ERR, //文件校验失败
};
struct __file_check {
u16 crc_tmp;
u32 counter;
u32 remain;
};
struct __ftp_download {
u32 file_size;
u32 file_offset;
u8 win[FTP_FILE_DATA_UNIT];
u8 packet_id;
u8 packet_id_max;
u8 last_packet;
u8 packet_crc_err;
u8 packet_crc_check;
u8 progress;
u32 dev_handle;
u16 mark_timer;
u16 get_timeout;
u16 start_timerout;
u16 file_crc;
struct __file_check check;
char *filepath;
FILE *file;
struct __dev *dev;
void (*end_callback)(void);
};
static struct __ftp_download *ftp_d = NULL;
static void file_transfer_download_get_data(void);
static void __file_transfer_download_file_check_caculate(void *priv);
//*----------------------------------------------------------------------------*/
/**@brief 校验分次处理消息发送处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_file_check_continue(void)
{
int msg[4];
msg[0] = (int)__file_transfer_download_file_check_caculate;
msg[1] = 1;
msg[2] = 0;
os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
}
//*----------------------------------------------------------------------------*/
/**@brief 文件数据块crc校验
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void __file_transfer_download_file_check_caculate(void *priv)
{
if (ftp_d == NULL) {
return ;
}
wdt_clear();
JL_ERR err = 0;
u32 cnt;
if (ftp_d->check.counter >= FTP_FILE_CRC_CAC_MAX_COUNTER) {
cnt = FTP_FILE_CRC_CAC_MAX_COUNTER;
} else {
cnt = ftp_d->check.counter;
}
log_info("cnt = %d, check.counter = %d, crc_tmp = %x\n", cnt, ftp_d->check.counter, ftp_d->check.crc_tmp);
for (int i = 0; i < cnt; i++) {
fread(ftp_d->win, sizeof(ftp_d->win), 1, ftp_d->file);
ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, sizeof(ftp_d->win), ftp_d->check.crc_tmp);
}
ftp_d->check.counter -= cnt;
if (ftp_d->check.counter == 0) {
if (ftp_d->check.remain) {
fread(ftp_d->win, ftp_d->check.remain, 1, ftp_d->file);
log_info("remain\n");
log_info_hexdump(ftp_d->win, ftp_d->check.remain);
ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, ftp_d->check.remain, ftp_d->check.crc_tmp);
}
//crc_check end
if (ftp_d->check.crc_tmp == ftp_d->file_crc) {
log_info("crc check ok!!, start rename\n");
fseek(ftp_d->file, ftp_d->file_size, SEEK_SET);
//进入重命名流程
err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
return ;
} else {
log_error("crc check fail, crc_tmp = %x, file_crc = %x!!\n", ftp_d->check.crc_tmp, ftp_d->file_crc);
u8 reason = FTP_END_REASON_DATA_CRC_ERR;
fdelete(ftp_d->file);
ftp_d->file = NULL;
JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
}
} else {
file_transfer_download_file_check_continue();
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件文件校验处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_file_check(void)
{
ftp_d->check.crc_tmp = 0;
ftp_d->check.counter = ftp_d->file_size / sizeof(ftp_d->win);
ftp_d->check.remain = ftp_d->file_size % sizeof(ftp_d->win);
ftp_d->file_offset = ftp_d->file_size;
log_info("crc_tmp = %x, counter = %d, remain = %d\n", ftp_d->check.crc_tmp, ftp_d->check.counter, ftp_d->check.remain);
fseek(ftp_d->file, 0, SEEK_SET);
file_transfer_download_file_check_continue();
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输重命名
@param rename:重命名
@return
@note 此过程接收的数据是实际文件传输的内容
*/
/*----------------------------------------------------------------------------*/
static int file_rename(const char *rename)
{
if (ftp_d && ftp_d->file) {
//rename之前先关闭文件
fclose(ftp_d->file);
ftp_d->file = NULL;
//重新打开文件
ftp_printf("ftp_d->filepath:%s, rename:%s\n", ftp_d->filepath, rename);
ftp_d->file = fopen(ftp_d->filepath, "r");
//free(path);
if (ftp_d->file) {
//文件打开成功, 重命名
int ret = frename(ftp_d->file, rename);
if (ret) {
log_error("rename fail\n");
} else {
log_info("rename ok\n");
}
return ret;
} else {
log_error("rename file open err!!");
}
}
return -1;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件重传文件头信息保存处理
@param file:文件句柄,win:临时缓存,offset:文件偏移
@return
@note 文件传输过程, 定时会触发断点续传信息保存处理
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_vaild_mark_fill(FILE *file, u8 *win, u32 offset, u8 vaild)
{
if (file) {
fseek(file, 0, SEEK_SET);
memset(win, 0, FTP_FILE_DATA_UNIT);
memcpy(win, FTP_FILE_VAILD_MARK, strlen(FTP_FILE_VAILD_MARK));
memcpy(win + strlen(FTP_FILE_VAILD_MARK), &offset, sizeof(offset));
memcpy(win + strlen(FTP_FILE_VAILD_MARK) + sizeof(offset), &vaild, sizeof(vaild));
fwrite(win, FTP_FILE_DATA_UNIT, 1, file);
fseek(file, offset, SEEK_SET);
/* log_info("============================================%s, offset = %d, pos = %d\n", __FUNCTION__, offset, fpos(file)); */
}
}
//*----------------------------------------------------------------------------*/
/**@brief 断点续传信息解析处理
@param file:文件句柄, 文件偏移获取指针
@return
@note 在文件传输开始的时候进行解析, 目的是找到续传文件偏移
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_intermittent_parse(FILE *file, u32 *offset)
{
if (file) {
char mark[10] = {0};
fseek(file, 0, SEEK_SET);
int rlen = fread(mark, strlen(FTP_FILE_VAILD_MARK), 1, file);
if (rlen) {
if (strcmp(mark, FTP_FILE_VAILD_MARK) == 0) {
log_info("find VAILD_MARK !!\n");
rlen = fread(offset, sizeof(u32), 1, file);
if (rlen) {
u8 vaild = 0;
rlen = fread(&vaild, 1, 1, file);
if (rlen && vaild) {
log_info("read offset ok, %d!!\n", *offset);
fseek(file, *offset, SEEK_SET);
return ;
} else {
log_error("read offset ok, but not vaild\n");
}
} else {
log_error("read offset fail!!\n");
}
}
}
}
*offset = 0;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件下载数据拉取超时处理
@param priv:私有参数,
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_get_timeout(void *priv)
{
if (ftp_d) {
ftp_printf("timeout!!!\n");
ftp_d->get_timeout = 0;
//在超时时间内没有收完所需要的数据, 重新拉取数据
file_transfer_download_get_data();
}
}
//*----------------------------------------------------------------------------*/
/**@brief 断点续传定时保存处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_vaild_mark_scan(void *priv)
{
if (ftp_d && ftp_d->file && ftp_d->mark_timer && ftp_d->last_packet == 0) {
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset, 0);
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件下载数据拉取处理
@param 无
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_download_get_data(void)
{
if (ftp_d == NULL || ftp_d->file == NULL) {
ftp_printf("file not ready %d!!\n", __LINE__);
return;
}
u32 file_remain = 0;
u32 file_offset = 0;
u16 recieve_max = rcsp_packet_write_alloc_len();
if (recieve_max < FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE) {
ftp_printf("not enough buf to recieve!!\n");
return;
} else {
///预留些接收缓存给其他通信使用
recieve_max -= FTP_FILE_DATA_RECIEVE_REMAIN_SIZE;
}
ftp_d->packet_id = 0;
ftp_d->packet_id_max = recieve_max / FTP_FILE_DATA_UNIT;
recieve_max = ftp_d->packet_id_max * FTP_FILE_DATA_UNIT;
file_remain = ftp_d->file_size - ftp_d->file_offset;
if ((file_remain) < recieve_max) {
ftp_d->packet_id_max = file_remain / FTP_FILE_DATA_UNIT;
if (file_remain % FTP_FILE_DATA_UNIT) {
ftp_d->packet_id_max ++;
}
}
if (ftp_d->last_packet) {
recieve_max = FTP_FILE_DATA_UNIT;
file_offset = 0;
} else {
file_offset = ftp_d->file_offset;
}
log_info("[get]recieve_max:%d, file_offset %d\n", recieve_max, file_offset);
u8 parm[7] = {0};
parm[0] = 0;
WRITE_BIG_U16(parm + 1, recieve_max);
WRITE_BIG_U32(parm + 3, file_offset);
JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER, parm, sizeof(parm), 0, 0, NULL);
if (err) {
ftp_printf("%s fail!!! %d\n", __FUNCTION__, err);
return;
}
if (ftp_d->get_timeout == 0) {
ftp_d->get_timeout = sys_timeout_add(NULL, file_transfer_download_get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT);
}
return;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件路径长度统计
@param root_path:根目录, folder:文件夹,filename:文件名
@return 文件路径长度
@note
*/
/*----------------------------------------------------------------------------*/
static u32 creat_path_len(char *root_path, const char *folder, u8 *name, u16 name_len)
{
u32 len = (strlen(root_path) + name_len + 1);
if (folder) {
len += strlen(folder);
len += strlen("/");
}
return len;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件路径组装处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void creat_file_path(char *path, char *root_path, const char *folder, u8 *name, u16 name_len)
{
strcat(path, root_path);
if (folder) {
strcat(path, folder);
strcat(path, "/");
}
//strcat(path, name);
memcpy(path + strlen(path), name, name_len);
//log_info("path = %s\n", path);
}
//*----------------------------------------------------------------------------*/
/**@brief 文件下载拓展参数配置
@param OpCode_SN:数据包序列号,data:数据, len:数据长度
@return 文件路径长度
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_parm_extra(u8 OpCode_SN, u8 *data, u16 len)
{
u8 resp[2] = {0};
u8 status = 0;
resp[0] = data[0];//op
if (ftp_d) {
data += 1;
ftp_d->dev_handle = READ_BIG_U32(data);//占用4byte
u8 en = *(data + 4);
if (FTP_FILE_PACKET_CRC_CHECK_EN && en) {
log_info("packet_crc_check enable !!!!!\n");
ftp_d->packet_crc_check = 1;
} else {
log_info("packet_crc_check disable !!!!!\n");
ftp_d->packet_crc_check = 0;
}
resp[1] = ftp_d->packet_crc_check;
status = JL_PRO_STATUS_SUCCESS;
} else {
status = JL_PRO_STATUS_FAIL;
}
JL_CMD_response_send(JL_OPCODE_DEVICE_PARM_EXTRA, status, OpCode_SN, resp, sizeof(resp), 0, NULL);
}
//*----------------------------------------------------------------------------*/
/**@brief 文件下载开始
@param OpCode_SN:数据包序列号,data:数据, len:数据长度
@return 文件路径长度
@note
*/
/*----------------------------------------------------------------------------*/
static int file_transfer_watch_opt(u8 flag, u8 OpCode_SN)
{
int ret = 0;
// 假如当前是大文件传输表盘:
if (RCSPDevMapFLASH == ftp_d->dev_handle
|| RCSPDevMapFLASH_2 == ftp_d->dev_handle) {
// 获取当前root_path
char *root_path = NULL;
if (ftp_d->dev) {
root_path = dev_manager_get_root_path(ftp_d->dev);
}
#if JL_RCSP_EXTRA_FLASH_OPT
ret = rcsp_file_transfer_watch_opt(flag, root_path);
#endif
}
if (ret) {
u16 reason = READ_BIG_U16(&ret);
if (3 != flag) {
rcsp_file_transfer_close();
}
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, (u8 *)&reason, sizeof(reason), 0, NULL);
}
return ret;
}
// rcsp文件下载开始命令处理
void rcsp_file_transfer_download_start(void *priv, u8 OpCode_SN, u8 *data, u16 len)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return ;
}
if (ftp_d) {
//收到了文件传输开始命令, 停止启动超时处理
if (ftp_d->start_timerout) {
/* sys_timeout_del(ftp_d->start_timerout); */
/* sys_timer_re_run(ftp_d->start_timerout); */
sys_timer_modify(ftp_d->start_timerout, FTP_FILE_DATA_RECIEVE_TIMEOUT * 2);
/* ftp_d->start_timerout = 0; */
}
}
JL_ERR err = 0;
///创建文件
u32 file_size = READ_BIG_U32(data);//占用4byte
u16 file_crc = READ_BIG_U16(data + 4);//占用2byte
u8 *file_name = data + 4 + 2;
u16 file_name_len = len - 6;
if (ftp_d == NULL) {
ftp_d = zalloc(sizeof(struct __ftp_download));
if (NULL == ftp_d) {
log_info("%s, no mem\n", __FUNCTION__);
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
return ;
}
ftp_d->dev_handle = (u32) - 1;
}
ftp_printf("file_size = %d, file_crc = %x\n", file_size, file_crc);
struct __dev *dev = NULL;
if (ftp_d->dev_handle == (u32) - 1) {
dev = dev_manager_find_spec("sd1", 0);
} else {
dev = dev_manager_find_spec(rcsp_browser_dev_remap(ftp_d->dev_handle), 0);
}
if (!dev) {
rcsp_file_transfer_close();
ftp_printf("no dev online !!\n");
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
return ;
}
char *root_path = dev_manager_get_root_path(dev);
ASSERT(root_path);
char *folder = NULL;
if (RCSPDevMapSD1 == ftp_d->dev_handle
|| RCSPDevMapSD0 == ftp_d->dev_handle) {
folder = FTP_DOWNLOAD_FOLDER_NAME;
}
char *path = zalloc(creat_path_len(root_path, folder, file_name, file_name_len));
u8 new_file = 0;
ASSERT(path);
creat_file_path(path, root_path, folder, file_name, file_name_len);
ftp_d->dev = dev;
ftp_d->file = fopen(path, "r");
if (ftp_d->file) {
log_info("file exist\n");
new_file = 0;
fclose(ftp_d->file);
ftp_d->file = NULL;
} else {
log_info("file new\n");
new_file = 1;
}
ftp_d->filepath = path;
if (file_transfer_watch_opt(new_file, OpCode_SN)) {
return;
}
ftp_d->file = fopen(path, "w+");
//free(path);
if (ftp_d->file == NULL) {
ftp_printf("file create err\n");
rcsp_file_transfer_close();
///文件打开失败, 回复APP文件传输失败
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
return ;
}
ftp_d->file_offset = 0;
ftp_d->progress = 0;
ftp_d->file_crc = file_crc;
ftp_d->last_packet = 0;
ftp_d->file_size = file_size;
if (ftp_d->file_size > sizeof(ftp_d->win)) {
if (new_file == 0) {
///解析断点续传的文件偏移
file_transfer_download_intermittent_parse(ftp_d->file, &ftp_d->file_offset);
}
if (ftp_d->file_offset == 0 || ftp_d->file_offset > file_size) {
log_error("file offset err !! reset offset \n");
ftp_d->file_offset = sizeof(ftp_d->win);
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset, 0);
} else if (ftp_d->file_offset == file_size) {
//上次文件已经收完, 进入校验流程
log_info("file aready download end \n");
file_transfer_download_file_check();
return ;
}
} else {
ftp_d->last_packet = 1;
}
///回复APP文件传输准备就绪
u16 file_data_unit = 0;
WRITE_BIG_U16(&file_data_unit, FTP_FILE_DATA_UNIT);
err = JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)&file_data_unit, sizeof(u16), 0, NULL);
if (err == 0) {
log_info("%s ok!! file_offset: %d, data unit = %d\n", __FUNCTION__, ftp_d->file_offset, FTP_FILE_DATA_UNIT);
///回复启动成功之后,启动数据拉取操作(这里是第一次)
//fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET);//重定位下文件位置
file_transfer_download_get_data();
ftp_d->mark_timer = sys_timer_add(NULL, file_transfer_download_vaild_mark_scan, FTP_FILE_VAILD_MARK_TIMER_UNIT);
return ;
} else {
ftp_printf("%s resp fail!!\n", __FUNCTION__);
rcsp_file_transfer_close();
ftp_d = NULL;
}
return;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输, 重命名处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_file_rename(u8 status, u8 *data, u16 len)
{
if (ftp_d) {
if (status == JL_PRO_STATUS_SUCCESS) {
log_info("%s !!, %d\n", __FUNCTION__, __LINE__);
log_info_hexdump(data, len);
file_transfer_watch_opt(-1, 0);
//重命名
if (file_rename((const char *)data) == 0) {
u8 reason = FTP_END_REASON_NONE;
int err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
rcsp_file_transfer_close();
}
dev_manager_set_valid(ftp_d->dev, 1);
file_transfer_watch_opt(2, 0);
} else {
//有重名的, 重新获取新名称, 如:“xxx_n.mp3”,n为数字
int err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1, 0, NULL);
if (err) {
rcsp_file_transfer_close();
}
}
} else {
ftp_printf("%s fail!! %d\n", __FUNCTION__, status);
if (ftp_d->file) {
//重命名失败,删除文件
log_error("rename file fail, delete file\n");
fdelete(ftp_d->file);
ftp_d->file = NULL;
}
rcsp_file_transfer_close();
}
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件下载结束(F->A的回复处理)
@param status:命令执行状态,data:数据, len:数据长度
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_end(u8 status, u8 *data, u16 len)
{
if (ftp_d) {
ftp_printf("%s status %d\n", __FUNCTION__, status);
rcsp_file_transfer_close();
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,最后一包数据接收处理
@param data:数据内容 len:数据长度
@return
@note 文件传输流程是最后才写文件第一包数据
*/
/*----------------------------------------------------------------------------*/
static void rcsp_file_transfer_download_doing_last_packet(u8 *data, u16 len)
{
u8 reason = FTP_END_REASON_NONE;
JL_ERR err = 0;
if (len > FTP_FILE_DATA_UNIT) {
log_error("last packet data len err!!\n");
reason = FTP_END_REASON_DATA_OVER_LIMIT;
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
return ;
}
if (ftp_d->get_timeout) {
sys_timeout_del(ftp_d->get_timeout);
ftp_d->get_timeout = 0;
}
log_info("get last packet ok\n");
fseek(ftp_d->file, 0, SEEK_SET);
int wlen = fwrite(data, len, 1, ftp_d->file);
if (wlen != len) {
ftp_printf("%s err !! %d\n", __FUNCTION__, wlen);
reason = FTP_END_REASON_WRITE_ERR;//文件写异常
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
} else {
//文件接收完成,文件校验
file_transfer_download_file_check();
}
//fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET);
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输过程处理(A->F)
@param data:数据, len:数据长度
@return
@note 此过程接收的数据是实际文件传输的内容
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_doing(u8 *data, u16 len)
{
if (ftp_d && ftp_d->file) {
log_info("id = %d, len = %d\n", data[0], len - 1);
if (ftp_d->start_timerout) {
sys_timer_re_run(ftp_d->start_timerout);
}
if (ftp_d->packet_id != data[0]) {
ftp_printf("warning !! packet_id err %d, %d\n", ftp_d->packet_id, data[0]);
return ;
}
ftp_d->packet_id ++;
len -= 1;
data += 1;
if (ftp_d->packet_crc_check) {
u16 packet_crc = READ_BIG_U16(data);//占用2byte
len -= 2;
data += 2;
if (packet_crc != CRC16(data, len)) {
log_error("packet crc err !!!!!!!!!!!!!!!!!!!!!\n");
ftp_d->packet_crc_err = 1;
}
if (ftp_d->packet_crc_err) {
if (ftp_d->packet_id >= ftp_d->packet_id_max) {
ftp_d->packet_crc_err = 0;
#if (FTP_FILE_PACKET_CRC_ERR_CONTINUE_EN)
//重新拉
file_transfer_download_get_data();
#else
//通知APP停止文件传输, 方便排查问题
rcsp_file_transfer_download_active_cancel();
#endif//FTP_FILE_PACKET_CRC_ERR_CONTINUE_EN
}
return ;
}
ftp_printf("packet crc check done\n");
}
u8 reason = FTP_END_REASON_NONE;
int wlen = 0;
JL_ERR err = 0;
if (ftp_d->last_packet) {
rcsp_file_transfer_download_doing_last_packet(data, len);
return ;
}
if (ftp_d->file_offset >= ftp_d->file_size) {
log_error("err, file data is over limit!!\n");
reason = FTP_END_REASON_DATA_OVER_LIMIT;//数据超范围
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
return ;
}
wdt_clear();
wlen = fwrite(data, len, 1, ftp_d->file);
if (wlen != len) {
ftp_printf("%s err !! %d\n", __FUNCTION__, wlen);
reason = FTP_END_REASON_WRITE_ERR;//文件写异常
err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1, 0, NULL);
if (err) {
//命令发送失败, 直接停止
rcsp_file_transfer_close();
}
} else {
if (len != FTP_FILE_DATA_UNIT) {
ftp_printf("data is not a normal unit !!\n");
}
ftp_d->file_offset += len;
ftp_printf("ftp_d->file_offset:%d, ftp_d->file_size:%d, len:%d\n", ftp_d->file_offset, ftp_d->file_size, len);
int cur_progress = ftp_d->file_offset * 100 / ftp_d->file_size;
if (ftp_d->progress != cur_progress) {
ftp_d->progress = cur_progress;
UI_MSG_POST("upgrade:process=%4", cur_progress);
}
if (ftp_d->file_offset >= ftp_d->file_size) {
ftp_printf("file recieve end!! get file first packet\n");
if (ftp_d->mark_timer) {
sys_timer_del(ftp_d->mark_timer);
ftp_d->mark_timer = 0;
}
ftp_d->last_packet = 1;
file_transfer_download_get_data();
return;
}
ftp_d->last_packet = 0;
if (ftp_d->get_timeout) {
//接收数据成功,重置一下超时
ftp_printf("reset timeout!!\n");
sys_timer_modify(ftp_d->get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT);
}
if (ftp_d->packet_id >= ftp_d->packet_id_max) {
//该次数据包已经收完,拉取新的数据
ftp_printf("get more!!\n");
file_transfer_download_get_data();
}
}
}
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief rcsp_file_transfer_download_progress 文件传输进度
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int rcsp_file_transfer_download_progress()
{
if (!ftp_d) {
return 0;
}
int progress = ftp_d->file_offset * 100 / ftp_d->file_size;
log_info("%s :%d", __func__, progress);
return progress;
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,被动取消处理
@param OpCode_SN:数据包sn码, 回复的时候用的
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len)
{
rcsp_file_transfer_close();
log_info("passive_cancel answer\n");
JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_CANCEL, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, 0, NULL);
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,主动取消处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_active_cancel(void)
{
if (ftp_d) {
rcsp_file_transfer_close();
JL_CMD_send(JL_OPCODE_FILE_TRANSFER_CANCEL, NULL, 0, 1, 0, NULL);
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,主动取消处理回复处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len)
{
if (status == JL_PRO_STATUS_SUCCESS) {
log_info("active_cancel_response ok!!");
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输关闭处理
@param
@return
@note 主要是做一些资源释放处理
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_close(void)
{
if (ftp_d) {
if (ftp_d->check.counter) {
log_error("crc caculating !! close err\n");
return ;
}
if (ftp_d->start_timerout) {
sys_timeout_del(ftp_d->start_timerout);
ftp_d->start_timerout = 0;
}
if (ftp_d->get_timeout) {
sys_timeout_del(ftp_d->get_timeout);
ftp_d->get_timeout = 0;
}
if (ftp_d->mark_timer) {
sys_timer_del(ftp_d->mark_timer);
ftp_d->mark_timer = 0;
}
if (ftp_d->file) {
if (ftp_d->last_packet == 0) {
//文件没有传输完, 如果不是直接断电, 有机会执行更新断点续传的文件偏移信息
file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset, 1);
}
fclose(ftp_d->file);
ftp_d->file = NULL;
}
if (ftp_d->filepath) {
free(ftp_d->filepath);
}
file_transfer_watch_opt(3, 0);
if (ftp_d->end_callback) {
ftp_d->end_callback();
}
free(ftp_d);
ftp_d = NULL;
log_info("rcsp_file_transfer_close!!!!!!\n");
}
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输启动超时处理
@param
@return
@note 响应app预处理,之后在设定时间内没有发文件传输开始命令过来触发超时
*/
/*----------------------------------------------------------------------------*/
static void file_transfer_start_timeout(void *priv)
{
log_info("%s\n", __FUNCTION__);
rcsp_file_transfer_close();
}
//*----------------------------------------------------------------------------*/
/**@brief 文件传输初始化处理
@param end_callback:文件传输结束处理回调
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_init(void (*end_callback)(void))
{
if (ftp_d) {
ftp_printf("file downloading err %d!!\n", __LINE__);
return ;
}
ftp_d = zalloc(sizeof(struct __ftp_download));
if (ftp_d == NULL) {
if (end_callback) {
end_callback();
}
return ;
}
//默认不使能每一包文件数据都校验
//如果APP有特意发命令过来, 会根据配置打开
ftp_d->packet_crc_check = 0;
//默认不设置设备, 获取默认最新活动设备
ftp_d->dev_handle = (u32) - 1;
ftp_d->end_callback = end_callback;
//如果在超时时间内都没有发文件传输开始命令, 退出文件传输流程
ftp_d->start_timerout = sys_timeout_add(NULL, file_transfer_start_timeout, 2000);
}
#endif
@@ -0,0 +1,83 @@
#ifndef __FILE_TRANSFER_H__
#define __FILE_TRANSFER_H__
#include "typedef.h"
#include "app_config.h"
//*----------------------------------------------------------------------------*/
/**@brief 文件传输初始化处理
@param end_callback:文件传输结束处理回调
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_init(void (*end_callback)(void));
//*----------------------------------------------------------------------------*/
/**@brief 文件下载拓展参数配置
@param OpCode_SN:数据包序列号,data:数据, len:数据长度
@return 文件路径长度
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_parm_extra(u8 OpCode_SN, u8 *data, u16 len);
// rcsp文件下载开始命令处理
void rcsp_file_transfer_download_start(void *priv, u8 OpCode_SN, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件下载结束(F->A的回复处理)
@param status:命令执行状态,data:数据, len:数据长度
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_end(u8 status, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输过程处理(A->F)
@param data:数据, len:数据长度
@return
@note 此过程接收的数据是实际文件传输的内容
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_doing(u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,被动取消处理
@param OpCode_SN:数据包sn码, 回复的时候用的
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,主动取消处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_active_cancel(void);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输,主动取消处理回复处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输, 重命名处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_file_rename(u8 status, u8 *data, u16 len);
//*----------------------------------------------------------------------------*/
/**@brief 文件传输关闭处理
@param
@return
@note 主要是做一些资源释放处理
*/
/*----------------------------------------------------------------------------*/
void rcsp_file_transfer_close(void);
#endif//__FILE_TRANSFER_H__
@@ -0,0 +1,978 @@
#include "file_transfer.h"
#include "file_delete.h"
#include "file_trans_back.h"
#include "dev_format.h"
#include "btstack/avctp_user.h"
#include "app_action.h"
#include "fs.h"
#include "file_bluk_trans_prepare.h"
#include "sensors_data_opt.h"
#include "file_simple_transfer.h"
#include "custom_cfg.h"
#include "JL_rcsp_api.h"
#include "mass_data.h"
#include "JL_rcsp_packet.h"
#include "JL_rcsp_protocol.h"
#include "timer.h"
#if (RCSP_MODE)
#if TCFG_PSRAM_DEV_ENABLE
#define MASS_MEMORY_USE_PSRAM 1 // 使用psram保存数据
#else
#define MASS_MEMORY_USE_PSRAM 0
#endif
#define MASS_DATA_OP_PARAM 0 // 参数
#define MASS_DATA_OP_DATA 1 // 数据
#define MASS_DATA_WAY_READ 0 // 获取数据
#define MASS_DATA_WAY_WRITE 1 // 发送数据
#define MASS_DATA_ERR_NO 0 // 成功
#define MASS_DATA_ERR_CRC 1 // CRC检验失败
#define MASS_DATA_ERR_SEQ 2 // SEQ不对
#define MASS_DATA_ERR_TYPE 3 // 数据类型不支持
#define MASS_DATA_ERR_WAY 4 // 传输方式不支持
#define MASS_DATA_ERR_TOTAL_LEN 5 // 数据长度超范围
#define MASS_DATA_ERR_WRITE 6 // 写数据失败
#define MASS_DATA_ERR_NO_PARAM 7 // 没有配置参数
#define MASS_DATA_ERR_OTHER 0xff // 其他类型错误
#define MASS_DATA_OP_DATA_SEQ_END BIT(15) // 结束包标识
#define MASS_DATA_VERSION 0 // 版本号
// JL_packet_get_tx_max_mtu() - sizeof(JL_PACKET) - 4 - sizeof(struct _MASSDATA_OP_DATA)
// JL_packet_get_tx_max_mtu() 通过 set_jl_mtu_send() 配置
#define MASS_DATA_DATA_LIMIT 200 // 数据长度限制
#define MASS_DATA_SEND_TIMEOUT_MS 5000 // 发送超时
#if 0
#define DEBUG_PUT_BUF put_buf
#else
#define DEBUG_PUT_BUF(...)
#endif
#pragma pack(1)
// OP-PARAM
struct _MASSDATA_OP_PARAM {
u8 way;
u8 type;
u8 version;
u8 dat[0];
};
struct _MASSDATA_OP_PARAM_READ {
u16 send_data_limit;
u16 recv_data_limit;
};
struct _MASSDATA_OP_PARAM_WRITE {
u32 data_len;
u16 crc;
u16 send_data_limit;
u16 recv_data_limit;
};
// OP-PARAM 回复
struct _MASSDATA_OP_PARAM_RESPOND {
u8 way;
u8 type;
u8 version;
u8 dat[0];
};
struct _MASSDATA_OP_PARAM_RESPOND_READ {
u8 result;
u32 data_len;
u16 crc;
u16 send_data_limit;
u16 recv_data_limit;
};
struct _MASSDATA_OP_PARAM_RESPOND_WRITE {
u8 result;
u16 send_data_limit;
u16 recv_data_limit;
};
// OP-DATA
struct _MASSDATA_OP_DATA {
u8 type;
u16 seq;
u16 crc;
u32 offset;
u16 len;
u8 dat[0];
};
// OP-DATA 回复
struct _MASSDATA_OP_DATA_RESPOND {
u8 type;
u16 seq;
u8 result;
u8 dat[0];
};
#pragma pack()
// recv
struct _MASSDATA_RECV {
u32 total_len;
u16 crc;
u16 seq;
u32 w;
u8 dat[0];
};
// send
struct _MASSDATA_SEND {
u8 result;
volatile u8 tx_flag : 1; // 1-发送中。0-完成
volatile u8 asyn : 1; // 1-异步
u16 send_limit;
u16 seq;
u16 tm;
u16 resend_tm;
void (*evt_cb)(void *priv, int event);
void *evt_cb_priv;
u8 *pkt_buf;
u16 pkt_len;
u16 offset;
u16 dat_len;
u8 dat[0];
};
static struct _MASSDATA_RECV *massdat_rx[MASS_DATA_TYPE_MAX] = {0};
static struct _MASSDATA_RECV_CB rx_cb[MASS_DATA_TYPE_MAX] = {0};
static struct _MASSDATA_SEND *massdat_tx[MASS_DATA_TYPE_MAX] = {0};
static void mass_data_asyn_send_ready_data(u8 type);
static int mass_data_asyn_send_no_wait(u8 type);
static void mass_data_asyn_send_release(u8 type, int event);
extern u8 get_rcsp_connect_status(void);
#if MASS_MEMORY_USE_PSRAM
#include "asm/psram_api.h"
#define MASS_MALLOC malloc_psram
/* #define MASS_ZALLOC zalloc */
#define MASS_FREE free_psram
static inline void *MASS_ZALLOC(size_t size)
{
void *ptr = MASS_MALLOC(size);
if (ptr) {
memset(ptr, 0, size);
}
return ptr;
}
#else
#define MASS_MALLOC malloc
#define MASS_ZALLOC zalloc
#define MASS_FREE free
#endif
void mass_data_recieve(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 *pkt_buf;
u16 res_len;
u8 result = 0;
u8 offset = 0;
u8 op = data[offset++];
struct _MASSDATA_RECV *p_md_rx;
log_i("%s, op:%d \n", __func__, op);
DEBUG_PUT_BUF(data, len);
if (op == MASS_DATA_OP_PARAM) {
struct _MASSDATA_OP_PARAM op_param;
struct _MASSDATA_OP_PARAM_RESPOND *p_respond;
struct _MASSDATA_OP_PARAM_RESPOND_READ *p_respond_read;
struct _MASSDATA_OP_PARAM_RESPOND_WRITE *p_respond_write;
memcpy(&op_param, &data[offset], sizeof(struct _MASSDATA_OP_PARAM));
offset += sizeof(struct _MASSDATA_OP_PARAM);
if (op_param.type >= MASS_DATA_TYPE_MAX) {
// 不支持数据类型
log_e("no support way:%d \n", op_param.type);
result = MASS_DATA_ERR_TYPE;
goto __op_param_end;
}
if (op_param.way != MASS_DATA_WAY_WRITE) {
// 不支持拉取
log_e("no support way:%d \n", op_param.way);
result = MASS_DATA_ERR_WAY;
goto __op_param_end;
}
if (massdat_rx[op_param.type]) {
MASS_FREE(massdat_rx[op_param.type]);
massdat_rx[op_param.type] = NULL;
}
struct _MASSDATA_OP_PARAM_WRITE op_w;
memcpy(&op_w, &data[offset], sizeof(struct _MASSDATA_OP_PARAM_WRITE));
offset += sizeof(struct _MASSDATA_OP_PARAM_WRITE);
op_w.data_len = READ_BIG_U32(&op_w.data_len);
op_w.crc = READ_BIG_U16(&op_w.crc);
op_w.send_data_limit = READ_BIG_U16(&op_w.send_data_limit);
op_w.recv_data_limit = READ_BIG_U16(&op_w.recv_data_limit);
log_i("massdat_rx[%d]:%d, crc:0x%x \n", op_param.type, op_w.data_len, op_w.crc);
if (rx_cb[op_param.type].part_cb) {
massdat_rx[op_param.type] = MASS_ZALLOC(sizeof(struct _MASSDATA_RECV));
} else {
massdat_rx[op_param.type] = MASS_ZALLOC(sizeof(struct _MASSDATA_RECV) + op_w.data_len);
}
ASSERT(massdat_rx[op_param.type]);
massdat_rx[op_param.type]->total_len = op_w.data_len;
massdat_rx[op_param.type]->crc = op_w.crc;
result = 0;
/* goto __op_param_end; */
__op_param_end:
log_e("result:%d \n", result);
if (op_param.way == MASS_DATA_WAY_READ) {
res_len = 1 + sizeof(struct _MASSDATA_OP_PARAM_RESPOND) + sizeof(struct _MASSDATA_OP_PARAM_RESPOND_READ);
pkt_buf = MASS_ZALLOC(res_len);
ASSERT(pkt_buf);
p_respond = (struct _MASSDATA_OP_PARAM_RESPOND *)(pkt_buf + 1);
p_respond_read = (struct _MASSDATA_OP_PARAM_RESPOND_READ *)p_respond->dat;
p_respond_read->result = result;
WRITE_BIG_U16(&p_respond_read->send_data_limit, MASS_DATA_DATA_LIMIT);
WRITE_BIG_U16(&p_respond_read->recv_data_limit, MASS_DATA_DATA_LIMIT);
} else {
res_len = 1 + sizeof(struct _MASSDATA_OP_PARAM_RESPOND) + sizeof(struct _MASSDATA_OP_PARAM_RESPOND_WRITE);
pkt_buf = MASS_ZALLOC(res_len);
ASSERT(pkt_buf);
p_respond = (struct _MASSDATA_OP_PARAM_RESPOND *)(pkt_buf + 1);
p_respond_write = (struct _MASSDATA_OP_PARAM_RESPOND_WRITE *)p_respond->dat;
p_respond_write->result = result;
WRITE_BIG_U16(&p_respond_write->send_data_limit, MASS_DATA_DATA_LIMIT);
WRITE_BIG_U16(&p_respond_write->recv_data_limit, MASS_DATA_DATA_LIMIT);
}
p_respond->way = op_param.way;
p_respond->type = op_param.type;
p_respond->version = op_param.version;
pkt_buf[0] = MASS_DATA_OP_PARAM;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)pkt_buf, res_len, 0, NULL);
MASS_FREE(pkt_buf);
return ;
} else if (op == MASS_DATA_OP_DATA) {
struct _MASSDATA_OP_DATA op_data;
struct _MASSDATA_OP_DATA_RESPOND *p_data_respond;
memcpy(&op_data, &data[offset], sizeof(struct _MASSDATA_OP_DATA));
offset += sizeof(struct _MASSDATA_OP_DATA);
op_data.seq = READ_BIG_U16(&op_data.seq);
op_data.crc = READ_BIG_U16(&op_data.crc);
op_data.offset = READ_BIG_U16(&op_data.offset);
op_data.len = READ_BIG_U16(&op_data.len);
if (op_data.type >= MASS_DATA_TYPE_MAX) {
// 不支持数据类型
log_e("no support way:%d \n", op_data.type);
result = MASS_DATA_ERR_TYPE;
goto __op_data_end;
}
if (massdat_rx[op_data.type] == NULL) {
// 没有配置参数
result = MASS_DATA_ERR_NO_PARAM;
goto __op_data_end;
}
p_md_rx = massdat_rx[op_data.type];
u16 seq = op_data.seq & ~MASS_DATA_OP_DATA_SEQ_END;
if (seq != p_md_rx->seq) {
// 序列号错误
log_e("err seq:%d, %d \n", seq, p_md_rx->seq);
result = MASS_DATA_ERR_SEQ;
goto __op_data_end;
}
if ((p_md_rx->w + op_data.len) > p_md_rx->total_len) {
// 长度错误
log_e("err len0:%d, %d, %d \n", p_md_rx->w, op_data.len, p_md_rx->total_len);
result = MASS_DATA_ERR_TOTAL_LEN;
goto __op_data_end;
}
u16 crc = CRC16(&data[offset], op_data.len);
if (op_data.crc != crc) {
// CRC错误
log_e("err crc0:%x, %x \n", op_data.crc, crc);
result = MASS_DATA_ERR_CRC;
goto __op_data_end;
}
if (rx_cb[op_data.type].part_cb) {
u8 *tmp_buf = (u8 *)MASS_ZALLOC(op_data.len + sizeof(op_data.len));
memcpy(tmp_buf, &op_data.len, sizeof(op_data.len));
memcpy(tmp_buf + sizeof(op_data.len), &data[offset], op_data.len);
if (rx_cb[op_data.type].cb) {
rx_cb[op_data.type].cb(rx_cb[op_data.type].cb_priv, tmp_buf, p_md_rx->total_len);
if (((u8 *)(rx_cb[op_data.type].cb_priv))[0]) {
result = MASS_DATA_ERR_WRITE;
goto __op_data_end;
}
}
MASS_FREE(tmp_buf);
} else {
memcpy(&p_md_rx->dat[p_md_rx->w], &data[offset], op_data.len);
}
p_md_rx->w += op_data.len;
p_md_rx->seq = op_data.seq + 1;
if (op_data.seq & MASS_DATA_OP_DATA_SEQ_END) {
// 结束
if (p_md_rx->w != p_md_rx->total_len) {
// 长度错误
log_e("err len1:%d, %d \n", p_md_rx->w, p_md_rx->total_len);
result = MASS_DATA_ERR_TOTAL_LEN;
goto __op_data_end;
}
if (!rx_cb[op_data.type].part_cb) {
crc = CRC16(p_md_rx->dat, p_md_rx->total_len);
if (p_md_rx->crc != crc) {
// CRC错误
log_e("err crc1:%x, %x \n", op_data.crc, crc);
result = MASS_DATA_ERR_CRC;
goto __op_data_end;
}
}
log_i("datlen[%d]:%d \n", op_data.type, p_md_rx->total_len);
DEBUG_PUT_BUF(p_md_rx->dat, p_md_rx->total_len);
// 回调处理
if ((rx_cb[op_data.type].cb) && (!rx_cb[op_data.type].part_cb)) {
rx_cb[op_data.type].cb(rx_cb[op_data.type].cb_priv, p_md_rx->dat, p_md_rx->total_len);
}
// 清除本次传输
MASS_FREE(massdat_rx[op_data.type]);
massdat_rx[op_data.type] = NULL;
}
result = 0;
/* goto __op_param_end; */
__op_data_end:
log_e("result:%d \n", result);
if ((rx_cb[op_data.type].part_cb) && (rx_cb[op_data.type].evt_cb)) {
// post 失败/成功消息
if (op_data.seq & MASS_DATA_OP_DATA_SEQ_END) {
rx_cb[op_data.type].evt_cb(rx_cb[op_data.type].cb_priv, MASS_DATA_RECV_EVENT_OK, (void *)&result);
} else {
if (result) {
rx_cb[op_data.type].evt_cb(rx_cb[op_data.type].cb_priv, MASS_DATA_RECV_EVENT_ERROR, (void *)&result);
}
}
}
res_len = 1 + sizeof(struct _MASSDATA_OP_DATA_RESPOND) + 4;
pkt_buf = MASS_ZALLOC(res_len);
ASSERT(pkt_buf);
p_data_respond = (struct _MASSDATA_OP_DATA_RESPOND *)(pkt_buf + 1);
p_data_respond->type = op_data.type;
p_data_respond->seq = op_data.seq;
p_data_respond->result = result;
WRITE_BIG_U16(&p_data_respond->seq, op_data.seq);
pkt_buf[0] = MASS_DATA_OP_DATA;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)pkt_buf, res_len, 0, NULL);
MASS_FREE(pkt_buf);
return ;
}
}
void mass_data_respone(void *priv, u8 OpCode, u8 status, u8 *data, u16 len)
{
u8 offset = 0;
u8 op = data[offset++];
log_i("%s, op:%d \n", __func__, op);
DEBUG_PUT_BUF(data, len);
if (op == MASS_DATA_OP_PARAM) {
struct _MASSDATA_OP_PARAM_RESPOND op_param_respond;
memcpy(&op_param_respond, &data[offset], sizeof(struct _MASSDATA_OP_PARAM_RESPOND));
offset += sizeof(struct _MASSDATA_OP_PARAM_RESPOND);
if (op_param_respond.way == MASS_DATA_WAY_WRITE) {
struct _MASSDATA_OP_PARAM_RESPOND_WRITE op_w;
memcpy(&op_w, &data[offset], sizeof(struct _MASSDATA_OP_PARAM_RESPOND_WRITE));
offset += sizeof(struct _MASSDATA_OP_PARAM_RESPOND_WRITE);
u16 send_limit = READ_BIG_U16(&op_w.send_data_limit);
u16 recv_limit = READ_BIG_U16(&op_w.recv_data_limit);
log_i("write[%d] result:%d, limit:%d,%d \n", op_param_respond.type, op_w.result, send_limit, recv_limit);
if (op_param_respond.type >= MASS_DATA_TYPE_MAX) {
log_e("no support type:%d \n", op_param_respond.type);
return ;
}
u8 asyn = 0;
local_irq_disable();
if (massdat_tx[op_param_respond.type]) {
if (send_limit && (massdat_tx[op_param_respond.type]->send_limit > send_limit)) {
massdat_tx[op_param_respond.type]->send_limit = send_limit;
}
massdat_tx[op_param_respond.type]->result = op_w.result;
massdat_tx[op_param_respond.type]->tx_flag = 0;
if (massdat_tx[op_param_respond.type]->asyn) {
asyn = 1;
}
}
local_irq_enable();
if (asyn) {
if (op_w.result) {
mass_data_asyn_send_release(op_param_respond.type, MASS_DATA_SEND_EVENT_RESPOND);
} else {
mass_data_asyn_send_ready_data(op_param_respond.type);
mass_data_asyn_send_no_wait(op_param_respond.type);
}
}
} else {
log_e("err way:%d \n", op_param_respond.way);
}
} else if (op == MASS_DATA_OP_DATA) {
struct _MASSDATA_OP_DATA_RESPOND op_data_respond;
memcpy(&op_data_respond, &data[offset], sizeof(struct _MASSDATA_OP_DATA_RESPOND));
offset += sizeof(struct _MASSDATA_OP_DATA_RESPOND);
u16 seq = READ_BIG_U16(&op_data_respond.seq);
log_i("data[%d] result:%d, seq:%d \n", op_data_respond.type, op_data_respond.result, seq);
if (op_data_respond.type >= MASS_DATA_TYPE_MAX) {
log_e("no support type:%d \n", op_data_respond.type);
return ;
}
u8 asyn = 0;
local_irq_disable();
if (massdat_tx[op_data_respond.type]) {
massdat_tx[op_data_respond.type]->result = op_data_respond.result;
massdat_tx[op_data_respond.type]->tx_flag = 0;
if (massdat_tx[op_data_respond.type]->asyn) {
asyn = 1;
}
}
local_irq_enable();
if (asyn) {
if (op_data_respond.result) {
mass_data_asyn_send_release(op_data_respond.type, MASS_DATA_SEND_EVENT_RESPOND);
} else {
massdat_tx[op_data_respond.type]->seq++;
massdat_tx[op_data_respond.type]->offset += (massdat_tx[op_data_respond.type]->pkt_len - (1 + sizeof(struct _MASSDATA_OP_DATA)));
if (massdat_tx[op_data_respond.type]->offset >= massdat_tx[op_data_respond.type]->dat_len) {
mass_data_asyn_send_release(op_data_respond.type, MASS_DATA_SEND_EVENT_OK);
} else {
mass_data_asyn_send_ready_data(op_data_respond.type);
mass_data_asyn_send_no_wait(op_data_respond.type);
}
}
}
}
}
static int mass_data_send_wait(u8 type, u8 *data, u16 len)
{
int to = 0;
massdat_tx[type]->tx_flag = 1;
log_i("%s, type:%d, len:%d \n", __func__, type, len);
DEBUG_PUT_BUF(data, len);
int result;
__send:
result = JL_CMD_send(JL_OPCODE_MASS_DATA, data, len, JL_NEED_RESPOND, 0, NULL);
if (result) {
if (result == JL_ERR_SEND_BUSY) {
if (to > MASS_DATA_SEND_TIMEOUT_MS) {
log_e("send timeout\n");
return false;
}
log_i("send busy \n");
os_time_dly(1);
to += 10;
goto __send;
}
log_e("send err:%d \n", result);
return false;
}
to = 0;
#if 0
while (!(rcsp_send_list_is_empty() && check_le_pakcet_sent_finish_flag())) {
if (!get_rcsp_connect_status()) {
// rcsp断开
log_e("rcsp disconnect\n");
return false;
}
if (to > MASS_DATA_SEND_TIMEOUT_MS) {
log_e("send timeout\n");
return false;
}
os_time_dly(1);
to += 10;
}
return true;
#else
while (massdat_tx[type]->tx_flag) {
if (!get_rcsp_connect_status()) {
// rcsp断开
log_e("rcsp disconnect\n");
return false;
}
if (to > MASS_DATA_SEND_TIMEOUT_MS) {
log_e("send timeout\n");
return false;
}
os_time_dly(1);
to += 10;
}
return massdat_tx[type]->result ? false : true;
#endif
}
int mass_data_blocking_send(u8 type, u8 *data, u16 len)
{
log_i("%s, task:%s, type:%d,len:%d \n", __func__, os_current_task(), type, len);
DEBUG_PUT_BUF(data, len);
if (type >= MASS_DATA_TYPE_MAX) {
return false;
}
local_irq_disable();
if (massdat_tx[type]) {
local_irq_enable();
log_e("why massdat_tx[%d]:0x%x \n", type, massdat_tx[type]);
return false;
}
struct _MASSDATA_SEND *tx_hdl = MASS_ZALLOC(sizeof(struct _MASSDATA_SEND));
ASSERT(tx_hdl);
massdat_tx[type] = tx_hdl;
local_irq_enable();
int result;
int offset = 0;
u16 pkt_len = 1 + sizeof(struct _MASSDATA_OP_PARAM) + sizeof(struct _MASSDATA_OP_PARAM_WRITE);
u8 *pkt_buf = MASS_ZALLOC(pkt_len);
ASSERT(pkt_buf);
struct _MASSDATA_OP_PARAM *p_op_param = (struct _MASSDATA_OP_PARAM *)(pkt_buf + 1);
struct _MASSDATA_OP_PARAM_WRITE *p_op_w;
p_op_w = (struct _MASSDATA_OP_PARAM_WRITE *)p_op_param->dat;
pkt_buf[0] = MASS_DATA_OP_PARAM;
p_op_param->way = MASS_DATA_WAY_WRITE;
p_op_param->type = type;
p_op_param->version = MASS_DATA_VERSION;
WRITE_BIG_U32(&p_op_w->data_len, len);
WRITE_BIG_U16(&p_op_w->crc, CRC16(data, len));
WRITE_BIG_U16(&p_op_w->send_data_limit, MASS_DATA_DATA_LIMIT);
WRITE_BIG_U16(&p_op_w->recv_data_limit, MASS_DATA_DATA_LIMIT);
massdat_tx[type]->send_limit = MASS_DATA_DATA_LIMIT;
result = mass_data_send_wait(type, pkt_buf, pkt_len);
MASS_FREE(pkt_buf);
if (result == false) {
local_irq_disable();
MASS_FREE(massdat_tx[type]);
massdat_tx[type] = NULL;
local_irq_enable();
return false;
}
u16 limit_len = massdat_tx[type]->send_limit;
pkt_len = 1 + sizeof(struct _MASSDATA_OP_DATA) + limit_len;
pkt_buf = MASS_ZALLOC(pkt_len);
ASSERT(pkt_buf);
struct _MASSDATA_OP_DATA *p_op_data = (struct _MASSDATA_OP_DATA *)(pkt_buf + 1);
u16 seq = 0;
p_op_data->type = type;
pkt_buf[0] = MASS_DATA_OP_DATA;
while (offset < len) {
u16 send_len = len - offset;
if (send_len > limit_len) {
send_len = limit_len;
} else {
seq |= MASS_DATA_OP_DATA_SEQ_END;
}
WRITE_BIG_U16(&p_op_data->seq, seq);
WRITE_BIG_U16(&p_op_data->crc, CRC16(&data[offset], send_len));
WRITE_BIG_U32(&p_op_data->offset, offset);
WRITE_BIG_U16(&p_op_data->len, send_len);
memcpy(p_op_data->dat, &data[offset], send_len);
result = mass_data_send_wait(type, pkt_buf, 1 + sizeof(struct _MASSDATA_OP_DATA) + send_len);
if (result == false) {
break;
}
seq ++;
offset += send_len;
}
MASS_FREE(pkt_buf);
local_irq_disable();
MASS_FREE(massdat_tx[type]);
massdat_tx[type] = NULL;
local_irq_enable();
return result;
}
static void mass_data_asyn_send_release(u8 type, int event)
{
int evt_func = 0;
void *evt_priv;
local_irq_disable();
if (massdat_tx[type]) {
evt_func = (int)massdat_tx[type]->evt_cb;
evt_priv = massdat_tx[type]->evt_cb_priv;
if (massdat_tx[type]->resend_tm) {
sys_timeout_del(massdat_tx[type]->resend_tm);
massdat_tx[type]->resend_tm = 0;
}
if (massdat_tx[type]->tm) {
sys_timeout_del(massdat_tx[type]->tm);
massdat_tx[type]->tm = 0;
}
if (massdat_tx[type]->pkt_buf) {
MASS_FREE(massdat_tx[type]->pkt_buf);
massdat_tx[type]->pkt_buf = NULL;
}
MASS_FREE(massdat_tx[type]);
massdat_tx[type] = NULL;
}
local_irq_enable();
log_i("send[%d] relese evt:%d \n", type, event);
if (evt_func) {
((void (*)(void *, int))evt_func)(evt_priv, event);
}
}
static void mass_data_asyn_send_to(void *priv)
{
u8 *type_ptr = (u8 *)priv;
u8 type = *type_ptr;
if (type >= MASS_DATA_TYPE_MAX) {
return ;
}
log_e("send[%d] timeout\n", type);
mass_data_asyn_send_release(type, MASS_DATA_SEND_EVENT_TO);
}
static void mass_data_asyn_resend_no_wait(void *priv)
{
u8 *type_ptr = (u8 *)priv;
u8 type = *type_ptr;
if (type >= MASS_DATA_TYPE_MAX) {
return ;
}
log_i("resend \n");
if (massdat_tx[type]->resend_tm) {
sys_timeout_del(massdat_tx[type]->resend_tm);
massdat_tx[type]->resend_tm = 0;
}
int result = mass_data_asyn_send_no_wait(type);
if (result == false) {
mass_data_asyn_send_release(type, MASS_DATA_SEND_EVENT_ERR);
}
}
static void mass_data_asyn_send_ready_param(u8 type)
{
if (massdat_tx[type]->pkt_buf) {
MASS_FREE(massdat_tx[type]->pkt_buf);
massdat_tx[type]->pkt_buf = NULL;
}
massdat_tx[type]->pkt_len = 1 + sizeof(struct _MASSDATA_OP_PARAM) + sizeof(struct _MASSDATA_OP_PARAM_WRITE);
massdat_tx[type]->pkt_buf = MASS_ZALLOC(massdat_tx[type]->pkt_len);
ASSERT(massdat_tx[type]->pkt_buf);
struct _MASSDATA_OP_PARAM *p_op_param = (struct _MASSDATA_OP_PARAM *)(massdat_tx[type]->pkt_buf + 1);
struct _MASSDATA_OP_PARAM_WRITE *p_op_w;
p_op_w = (struct _MASSDATA_OP_PARAM_WRITE *)p_op_param->dat;
massdat_tx[type]->pkt_buf[0] = MASS_DATA_OP_PARAM;
p_op_param->way = MASS_DATA_WAY_WRITE;
p_op_param->type = type;
p_op_param->version = MASS_DATA_VERSION;
WRITE_BIG_U32(&p_op_w->data_len, massdat_tx[type]->dat_len);
WRITE_BIG_U16(&p_op_w->crc, CRC16(massdat_tx[type]->dat, massdat_tx[type]->dat_len));
WRITE_BIG_U16(&p_op_w->send_data_limit, MASS_DATA_DATA_LIMIT);
WRITE_BIG_U16(&p_op_w->recv_data_limit, MASS_DATA_DATA_LIMIT);
massdat_tx[type]->send_limit = MASS_DATA_DATA_LIMIT;
massdat_tx[type]->tm = sys_timeout_add((void *)&type, mass_data_asyn_send_to, MASS_DATA_SEND_TIMEOUT_MS);
}
static void mass_data_asyn_send_ready_data(u8 type)
{
if (massdat_tx[type]->pkt_buf) {
MASS_FREE(massdat_tx[type]->pkt_buf);
massdat_tx[type]->pkt_buf = NULL;
}
u16 limit_len = massdat_tx[type]->send_limit;
massdat_tx[type]->pkt_len = 1 + sizeof(struct _MASSDATA_OP_DATA) + limit_len;
massdat_tx[type]->pkt_buf = MASS_ZALLOC(massdat_tx[type]->pkt_len);
ASSERT(massdat_tx[type]->pkt_buf);
struct _MASSDATA_OP_DATA *p_op_data = (struct _MASSDATA_OP_DATA *)(massdat_tx[type]->pkt_buf + 1);
u16 seq = massdat_tx[type]->seq;
p_op_data->type = type;
massdat_tx[type]->pkt_buf[0] = MASS_DATA_OP_DATA;
u16 send_len = massdat_tx[type]->dat_len - massdat_tx[type]->offset;
if (send_len > limit_len) {
send_len = limit_len;
} else {
seq |= MASS_DATA_OP_DATA_SEQ_END;
}
memcpy(p_op_data->dat, &massdat_tx[type]->dat[massdat_tx[type]->offset], send_len);
WRITE_BIG_U16(&p_op_data->seq, seq);
WRITE_BIG_U16(&p_op_data->crc, CRC16(p_op_data->dat, send_len));
WRITE_BIG_U32(&p_op_data->offset, massdat_tx[type]->offset);
WRITE_BIG_U16(&p_op_data->len, send_len);
massdat_tx[type]->pkt_len = 1 + sizeof(struct _MASSDATA_OP_DATA) + send_len;
if (massdat_tx[type]->tm) {
sys_timeout_del(massdat_tx[type]->tm);
massdat_tx[type]->tm = 0;
}
massdat_tx[type]->tm = sys_timeout_add((void *)&type, mass_data_asyn_send_to, MASS_DATA_SEND_TIMEOUT_MS);
}
static int mass_data_asyn_send_no_wait(u8 type)
{
int to = 0;
massdat_tx[type]->tx_flag = 1;
log_i("%s, type:%d, len:%d \n", __func__, type, massdat_tx[type]->pkt_len);
DEBUG_PUT_BUF(massdat_tx[type]->pkt_buf, massdat_tx[type]->pkt_len);
int result = JL_CMD_send(JL_OPCODE_MASS_DATA, massdat_tx[type]->pkt_buf, massdat_tx[type]->pkt_len, JL_NEED_RESPOND, 0, NULL);
if (result) {
if (result == JL_ERR_SEND_BUSY) {
log_i("send busy \n");
massdat_tx[type]->resend_tm = sys_timeout_add((void *)&type, mass_data_asyn_resend_no_wait, 20);
return true;
}
log_e("send err:%d \n", result);
return false;
}
return true;
}
int mass_data_asyn_send_ex(u8 type, u8 *head, u16 head_len, u8 *data, u16 len, void *evt_cb_priv, void (*evt_cb)(void *priv, int event))
{
log_i("%s, task:%s, type:%d,len:%d \n", __func__, os_current_task(), type, len);
DEBUG_PUT_BUF(data, len);
if (type >= MASS_DATA_TYPE_MAX) {
return false;
}
struct _MASSDATA_SEND *tx_hdl = MASS_ZALLOC(sizeof(struct _MASSDATA_SEND) + head_len + len);
local_irq_disable();
if (massdat_tx[type]) {
local_irq_enable();
MASS_FREE(tx_hdl);
log_e("why massdat_tx[%d]:0x%x \n", type, massdat_tx[type]);
return false;
}
ASSERT(tx_hdl);
massdat_tx[type] = tx_hdl;
massdat_tx[type]->asyn = 1;
massdat_tx[type]->dat_len = head_len + len;
massdat_tx[type]->evt_cb = evt_cb;
massdat_tx[type]->evt_cb_priv = evt_cb_priv;
local_irq_enable();
u8 *dat = massdat_tx[type]->dat;
if (head_len) {
memcpy(dat, head, head_len);
dat += head_len;
}
memcpy(dat, data, len);
mass_data_asyn_send_ready_param(type);
int result = mass_data_asyn_send_no_wait(type);
if (result == false) {
return false;
}
return true;
}
int mass_data_asyn_send(u8 type, u8 *data, u16 len, void *evt_cb_priv, void (*evt_cb)(void *priv, int event))
{
return mass_data_asyn_send_ex(type, NULL, 0, data, len, evt_cb_priv, evt_cb);
}
void mass_data_recv_register(u8 type, void *cb_priv, void (*cb)(void *priv, u8 *data, int len))
{
if (type < MASS_DATA_TYPE_MAX) {
rx_cb[type].cb_priv = cb_priv;
rx_cb[type].cb = cb;
}
}
void mass_data_recv_register_ext(u8 type, struct _MASSDATA_RECV_CB *recv_cb)
{
if (type < MASS_DATA_TYPE_MAX) {
memcpy(&rx_cb[type], recv_cb, sizeof(struct _MASSDATA_RECV_CB));
}
}
void aliyun_bt_recv_register(void *cb_priv, void (*cb)(void *priv, u8 *data, int len))
{
mass_data_recv_register(MASS_DATA_TYPE_ALIYUN, cb_priv, cb);
}
int aliyun_bt_data_send(u8 *data, u16 len)
{
/* return mass_data_blocking_send(MASS_DATA_TYPE_ALIYUN, data, len); */
return mass_data_asyn_send(MASS_DATA_TYPE_ALIYUN, data, len, NULL, NULL);
}
int rcsp_overflow_mass_data_send(u8 *data, u16 len)
{
return mass_data_asyn_send(MASS_DATA_TYPE_RCSP_DATA, data, len, NULL, NULL);
}
#if TCFG_CAT1_MODULE_UPDATE_ENABLE
int mass_data_init(void)
{
rx_cb[MASS_DATA_TYPE_CAT1_UPDATE].part_cb = 1;
return 0;
}
platform_initcall(mass_data_init);
#endif
#if 0
#define TEST_ASYN 1
static u16 aliyun_test_len;
static u8 *aliyun_test_buf = NULL;
static void test_tm(void *priv)
{
printf("test_tm \n");
aliyun_test_len = rand32() % 4000 + 50;
if (aliyun_test_buf) {
MASS_FREE(aliyun_test_buf);
}
aliyun_test_buf = MASS_MALLOC(aliyun_test_len);
ASSERT(aliyun_test_buf);
for (int i = 0; i < aliyun_test_len; i++) {
aliyun_test_buf[i] = aliyun_test_len + i;
}
#if TEST_ASYN
mass_data_asyn_send(MASS_DATA_TYPE_ALIYUN, aliyun_test_buf, aliyun_test_len, NULL, NULL);
#else
mass_data_blocking_send(MASS_DATA_TYPE_ALIYUN, aliyun_test_buf, aliyun_test_len);
#endif
}
static int aliyun_test_do(int priv)
{
sys_timeout_add(NULL, test_tm, 5000);
return 0;
}
static void test_cb(void *priv, u8 *data, int len)
{
printf("test_cb:%d \n", len);
/* put_buf(data, len); */
if (len != aliyun_test_len) {
printf("aliyun_test_len:%d \n", aliyun_test_len);
while (1);
}
for (int i = 0; i < aliyun_test_len; i++) {
if ((u8)data[i] != (u8)(aliyun_test_buf[i] + 1)) {
printf("err i:%d, 0x%x, 0x%x, 0x%x \n", i, data[i], aliyun_test_buf[i], aliyun_test_buf[i] + 1);
put_buf(aliyun_test_buf, aliyun_test_len);
while (1);
}
}
#if TEST_ASYN
aliyun_test_do(0);
#else
// 阻塞发送,不能在蓝牙和app_core任务中
if (!strcmp(os_current_task(), "ui")) {
aliyun_test_do(0);
} else {
int msg[3] = {0};
msg[0] = (int)aliyun_test_do;
msg[1] = 1;
do {
int os_err = os_taskq_post_type("ui", Q_CALLBACK, 3, msg);
if (os_err == OS_ERR_NONE) {
break;
}
if (os_err != OS_Q_FULL) {
return ;
}
os_time_dly(1);
} while (1);
}
#endif
}
void aliyun_bt_test(void)
{
aliyun_bt_recv_register(NULL, test_cb);
#if TEST_ASYN
aliyun_test_do(0);
#else
// 阻塞发送,不能在蓝牙和app_core任务中
if (!strcmp(os_current_task(), "ui")) {
aliyun_test_do(0);
} else {
int msg[3] = {0};
msg[0] = (int)aliyun_test_do;
msg[1] = 1;
do {
int os_err = os_taskq_post_type("ui", Q_CALLBACK, 3, msg);
if (os_err == OS_ERR_NONE) {
break;
}
if (os_err != OS_Q_FULL) {
return ;
}
os_time_dly(1);
} while (1);
}
#endif
}
#endif
#endif//SMART_BOX_EN
@@ -0,0 +1,45 @@
#ifndef __MASS_DATA_H__
#define __MASS_DATA_H__
#include "typedef.h"
#include "app_config.h"
#define MASS_DATA_TYPE_ORIGINAL 0 // 原始数据
#define MASS_DATA_TYPE_ALIYUN 1 // 阿里云
#define MASS_DATA_TYPE_RCSP_DATA 2 // RCSP
#define MASS_DATA_TYPE_AI_TEXT 3 // AI
#define MASS_DATA_TYPE_TTS 4 // TTS
#define MASS_DATA_TYPE_VERIFY 5 // 平台接口认证信息
#define MASS_DATA_TYPE_ESIM 6 // esim卡
#define MASS_DATA_TYPE_CAT1_UPDATE 7 // 4G模块升级数据
#define MASS_DATA_TYPE_MAX 8
#define MASS_DATA_SEND_EVENT_OK 0 // OK
#define MASS_DATA_SEND_EVENT_TO 1 // 超时
#define MASS_DATA_SEND_EVENT_ERR 2 // 发送失败
#define MASS_DATA_SEND_EVENT_RESPOND 3 // 回复出错
#define MASS_DATA_RECV_EVENT_OK 0 // 完成
#define MASS_DATA_RECV_EVENT_ERROR 1 // 出错
#define MASS_DATA_RECV_EVENT_TO 2 // 超时
struct _MASSDATA_RECV_CB {
u8 part_cb; // 收到一部分数据后就返回,不等全部收完
void (*cb)(void *priv, u8 *data, int len);
void *cb_priv;
void (*evt_cb)(void *priv, int event, void *evt_param);
};
// 注册收数回调
void mass_data_recv_register(u8 type, void *cb_priv, void (*cb)(void *priv, u8 *data, int len));
void mass_data_recv_register_ext(u8 type, struct _MASSDATA_RECV_CB *recv_cb);
// 非阻塞式发送
int mass_data_asyn_send(u8 type, u8 *data, u16 len, void *evt_cb_priv, void (*evt_cb)(void *priv, int event));
// 非阻塞式发送。数据与头部分开填数
int mass_data_asyn_send_ex(u8 type, u8 *head, u16 head_len, u8 *data, u16 len, void *evt_cb_priv, void (*evt_cb)(void *priv, int event));
// 阻塞式发送 // 不能在app_core和蓝牙相关任务中调用
int mass_data_blocking_send(u8 type, u8 *data, u16 len);
#endif//__MASS_DATA_H__
@@ -0,0 +1,369 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_adv_bluetooth.data.bss")
#pragma data_seg(".rcsp_adv_bluetooth.data")
#pragma const_seg(".rcsp_adv_bluetooth.text.const")
#pragma code_seg(".rcsp_adv_bluetooth.text")
#endif
#include "rcsp_config.h"
#include "ble_rcsp_server.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_setting_opt.h"
#include "rcsp_setting_sync.h"
#include "custom_cfg.h"
#include "btstack/avctp_user.h"
#include "rcsp_manage.h"
#include "rcsp_music_info_setting.h"
#include "rcsp_bt_manage.h"
#include "ble_rcsp_adv.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_attr.h"
#if (RCSP_MODE && RCSP_ADV_EN)
#define RCSP_DEBUG_EN
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_printf_buf(x,len) put_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
#define JL_OPCODE_SET_DEVICE_REBOOT 0xE7
extern int get_bt_tws_connect_status();
static u8 adv_setting_result = 0;
static u8 adv_set_deal_one_attr(u8 *buf, u8 size, u8 offset)
{
u8 rlen = buf[offset];
if ((offset + rlen + 1) > (size - offset)) {
rcsp_printf("\n\ndeal attr end!\n\n");
return rlen;
}
u8 type = buf[offset + 1];
u8 *pbuf = &buf[offset + 2];
u8 dlen = rlen - 1;
adv_setting_result = 0;
RCSP_SETTING_OPT *setting_opt_hdl = get_rcsp_setting_opt_hdl(type);
if (setting_opt_hdl) {
adv_setting_result = set_setting_extra_handle(setting_opt_hdl, pbuf, &dlen);
}
if (!adv_setting_result) {
set_rcsp_opt_setting(setting_opt_hdl, NULL);
}
return rlen + 1;
}
static u32 JL_opcode_set_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
rcsp_printf("JL_opcode_set_adv_info:\n");
rcsp_printf_buf(data, len);
u8 offset = 0;
while (offset < len) {
offset += adv_set_deal_one_attr(data, len, offset);
}
u8 ret = 0;
if (adv_setting_result) {
ret = adv_setting_result;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1, ble_con_handle, spp_remote_addr);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1, ble_con_handle, spp_remote_addr);
}
#if TCFG_RCSP_DUAL_CONN_ENABLE
// 一拖二则需要手机重新拉取C0设置的设备信息
u8 adv_cmd = 0x0;
adv_info_device_request(&adv_cmd, sizeof(adv_cmd));
#endif
return 0;
}
static u8 rcsp_adv_get_and_fill_adv_info(u8 *buf, u16 max_len, u8 offset, u8 type)
{
u8 *adv_data = NULL;
RCSP_SETTING_OPT *setting_opt_hdl = get_rcsp_setting_opt_hdl(type);
u8 size = get_setting_extra_handle(setting_opt_hdl, &adv_data, NULL);
if (size && adv_data) {
size = add_one_attr(buf, max_len, offset, type, (void *)adv_data, size);
}
return size;
}
extern void bt_adv_get_bat(u8 *buf);
static u32 JL_opcode_get_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
u8 buf[256];
u8 offset = 0;
u32 ret = 0;
u32 mask = READ_BIG_U32(data);
rcsp_printf("FEATURE MASK : %x\n", mask);
/* #define ATTR_TYPE_BAT_VALUE (0) */
/* #define ATTR_TYPE_EDR_NAME (1) */
//get version
if (mask & BIT(ATTR_TYPE_BAT_VALUE)) {
rcsp_printf("ATTR_TYPE_BAT_VALUE\n");
u8 bat[3];
bt_adv_get_bat(bat);
offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_BAT_VALUE, bat, 3);
}
#if RCSP_ADV_NAME_SET_ENABLE
if (mask & BIT(ATTR_TYPE_EDR_NAME)) {
rcsp_printf("ATTR_TYPE_EDR_NAME\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_EDR_NAME);
}
#endif // RCSP_ADV_NAME_SET_ENABLE
#if RCSP_ADV_KEY_SET_ENABLE
if (mask & BIT(ATTR_TYPE_KEY_SETTING)) {
rcsp_printf("ATTR_TYPE_KEY_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_KEY_SETTING);
}
if (mask & BIT(ATTR_TYPE_ANC_VOICE_KEY)) {
rcsp_printf("ATTR_TYPE_ANC_VOICE_KEY\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_ANC_VOICE_KEY);
}
#endif // RCSP_ADV_KEY_SET_ENABLE
#if RCSP_ADV_LED_SET_ENABLE
if (mask & BIT(ATTR_TYPE_LED_SETTING)) {
rcsp_printf("ATTR_TYPE_LED_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_LED_SETTING);
}
#endif // RCSP_ADV_LED_SET_ENABLE
#if RCSP_ADV_MIC_SET_ENABLE
if (mask & BIT(ATTR_TYPE_MIC_SETTING)) {
rcsp_printf("ATTR_TYPE_MIC_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_MIC_SETTING);
}
#endif // RCSP_ADV_MIC_SET_ENABLE
#if RCSP_ADV_WORK_SET_ENABLE
if (mask & BIT(ATTR_TYPE_WORK_MODE)) {
rcsp_printf("ATTR_TYPE_WORK_MODE\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_WORK_MODE);
}
#endif // RCSP_ADV_WORK_SET_ENABLE
#if RCSP_ADV_PRODUCT_MSG_ENABLE
if (mask & BIT(ATTR_TYPE_PRODUCT_MESSAGE)) {
rcsp_printf("ATTR_TYPE_PRODUCT_MESSAGE\n");
u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
u8 tversion[6];
tversion[0] = 0x05;
tversion[1] = 0xD6;
tversion[3] = vid & 0xFF;
tversion[2] = vid >> 8;
tversion[5] = pid & 0xFF;
tversion[4] = pid >> 8;
offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_PRODUCT_MESSAGE, (void *)tversion, 6);
}
#endif // RCSP_ADV_PRODUCT_MSG_ENABLE
rcsp_printf_buf(buf, offset);
ret = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, buf, offset, ble_con_handle, spp_remote_addr);
return ret;
}
u8 adv_info_notify(u8 *buf, u16 len)
{
return JL_CMD_send(JL_OPCODE_ADV_DEVICE_NOTIFY, buf, len, JL_NOT_NEED_RESPOND, 0, NULL);
}
u8 adv_info_device_request(u8 *buf, u16 len)
{
printf("JL_OPCODE_ADV_DEVICE_REQUEST\n");
return JL_CMD_send(JL_OPCODE_ADV_DEVICE_REQUEST, buf, len, JL_NEED_RESPOND, 0, NULL);
}
int JL_rcsp_adv_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
rcsp_printf("JL_rcsp_adv_cmd_resp\n");
switch (OpCode) {
case JL_OPCODE_SET_ADV:
rcsp_printf(" JL_OPCODE_SET_ADV\n");
JL_opcode_set_adv_info(priv, OpCode, OpCode_SN, data, len, ble_con_handle, spp_remote_addr);
break;
case JL_OPCODE_GET_ADV:
rcsp_printf(" JL_OPCODE_GET_ADV\n");
JL_opcode_get_adv_info(priv, OpCode, OpCode_SN, data, len, ble_con_handle, spp_remote_addr);
break;
case JL_OPCODE_ADV_NOTIFY_SETTING:
rcsp_printf(" JL_OPCODE_ADV_NOTIFY_SETTING\n");
bt_ble_adv_ioctl(BT_ADV_SET_NOTIFY_EN, *((u8 *)data), 1);
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, ble_con_handle, spp_remote_addr);
break;
case JL_OPCODE_ADV_DEVICE_REQUEST:
rcsp_printf("JL_OPCODE_ADV_DEVICE_REQUEST\n");
break;
default:
return 1;
}
return 0;
}
static void rcsp_wait_reboot_dev(void *priv)
{
if (NULL == priv && !rcsp_send_list_is_empty()) {
return;
}
bt_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
ble_module_enable(0);
cpu_reset();
}
static void rcsp_rcsp_reboot_dev(void)
{
extern void adv_edr_name_change_now(void);
adv_edr_name_change_now();
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
modify_bt_name_and_reset(500);
} else {
if (sys_timer_add(NULL, rcsp_wait_reboot_dev, 500) == 0) {
rcsp_wait_reboot_dev((void *)1);
}
}
#else
if (sys_timer_add(NULL, rcsp_wait_reboot_dev, 500) == 0) {
rcsp_wait_reboot_dev((void *)1);
}
#endif
}
int JL_rcsp_adv_event_handler(struct rcsp_event *rcsp)
{
switch (rcsp->event) {
case MSG_JL_REBOOT_DEV:
rcsp_rcsp_reboot_dev();
break;
case MSG_JL_UPDATE_SEQ:
printf("MSG_JL_UPDATE_SEQ\n");
adv_seq_vaule_sync();
break;
case MSG_JL_UPDAET_ADV_STATE_INFO:
/* if (get_rcsp_connect_status()) { */
/* JL_rcsp_set_auth_flag(rcsp->args[0]); */
/* bt_ble_adv_ioctl(BT_ADV_SET_NOTIFY_EN, rcsp->args[1], 1); */
/* } */
break;
default:
return 1;
}
return 0;
}
// 获取当前已连接spp数目
extern u8 bt_rcsp_spp_conn_num(void);
// 下面是弹窗的其他设置
int app_core_data_for_send(u8 *packet, u16 size)
{
//printf("for app send size %d\n", size);
if (JL_rcsp_get_auth_flag()) {
*packet = 1;
} else {
*packet = 0;
}
if (bt_rcsp_spp_conn_num() > 0) {
if (get_ble_adv_notify()) {
*(packet + 1) = 1;
} else {
*(packet + 1) = 0;
}
#if RCSP_ADV_MUSIC_INFO_ENABLE
if (get_player_time_en()) {
*(packet + 2) = 1;
} else {
*(packet + 2) = 0;
}
#else
*(packet + 2) = 0;
#endif
*(packet + 3) = get_connect_flag();
}
return 4;
}
#if TCFG_USER_TWS_ENABLE
#define TWS_FUNC_ID_RCSP_APP_CORE_DATA \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'P' + 'P') << (2 * 8)) | \
((u8)('C' + 'O' + 'R' + 'E') << (1 * 8)) | \
((u8)('D' + 'A' + 'T' + 'A') << (0 * 8)))
void app_core_data_for_set(u8 *packet, u16 size);
static void rcsp_app_core_data_in_irq(void *_data, u16 len, bool rx)
{
if (rx) {
u8 *data = (u8 *)_data;
app_core_data_for_set(data, len);
}
}
REGISTER_TWS_FUNC_STUB(tws_rcsp_spp_status) = {
.func_id = TWS_FUNC_ID_RCSP_APP_CORE_DATA,
.func = rcsp_app_core_data_in_irq,
};
#endif
void app_core_data_for_set(u8 *packet, u16 size)
{
printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
/* u8 rcsp_auth_flag = *packet; */
u8 ble_adv_notify = *(packet + 1);
u8 player_time_en = *(packet + 2);
u8 connect_flag = *(packet + 3);
#if TCFG_USER_TWS_ENABLE
// 通知从机同步状态
if (get_bt_tws_connect_status() && TWS_ROLE_MASTER == tws_api_get_role()) {
tws_api_send_data_to_sibling((void *)packet, size, TWS_FUNC_ID_RCSP_APP_CORE_DATA);
}
#endif
set_ble_adv_notify(ble_adv_notify);
#if RCSP_ADV_MUSIC_INFO_ENABLE
set_player_time_en(player_time_en);
#endif
set_connect_flag(connect_flag);
}
#elif (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP
u8 adv_info_notify(u8 *buf, u16 len)
{
return JL_CMD_send(JL_OPCODE_ADV_DEVICE_NOTIFY, buf, len, JL_NOT_NEED_RESPOND, 0, NULL);
}
u8 adv_info_device_request(u8 *buf, u16 len)
{
printf("error!!! %s %d", __func__, __LINE__);
return 0;
}
#else // (RCSP_MODE && RCSP_ADV_EN)
u8 adv_info_notify(u8 *buf, u16 len)
{
return 0;
}
u8 adv_info_device_request(u8 *buf, u16 len)
{
return 0;
}
#endif
@@ -0,0 +1,15 @@
#ifndef __RCSP_ADV_BLUETOOTH__
#define __RCSP_ADV_BLUETOOTH__
#include "typedef.h"
#include "system/event.h"
int JL_rcsp_adv_event_handler(struct rcsp_event *rcsp);
int JL_rcsp_adv_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
/**
* @brief 请求手机tws操作C4
*/
u8 adv_info_device_request(u8 *buf, u16 len);
#endif
@@ -0,0 +1,204 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_adv_bluetooth.data.bss")
#pragma data_seg(".rcsp_adv_bluetooth.data")
#pragma const_seg(".rcsp_adv_bluetooth.text.const")
#pragma code_seg(".rcsp_adv_bluetooth.text")
#endif
#include "rcsp_config.h"
#include "ble_rcsp_server.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_setting_opt.h"
#include "rcsp_setting_sync.h"
#include "custom_cfg.h"
#include "btstack/avctp_user.h"
#include "rcsp_manage.h"
#include "rcsp_music_info_setting.h"
#include "rcsp_bt_manage.h"
#include "ble_rcsp_adv.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_attr.h"
#if RCSP_MODE && (!RCSP_ADV_EN)
#if (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP
#define RCSP_DEBUG_EN
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_printf_buf(x,len) put_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
static u8 adv_setting_result = 0;
static u8 adv_set_deal_one_attr(u8 *buf, u8 size, u8 offset)
{
u8 rlen = buf[offset];
if ((offset + rlen + 1) > (size - offset)) {
rcsp_printf("\n\ndeal attr end!\n\n");
return rlen;
}
u8 type = buf[offset + 1];
u8 *pbuf = &buf[offset + 2];
u8 dlen = rlen - 1;
adv_setting_result = 0;
RCSP_SETTING_OPT *setting_opt_hdl = get_rcsp_setting_opt_hdl(type);
if (setting_opt_hdl) {
adv_setting_result = set_setting_extra_handle(setting_opt_hdl, pbuf, &dlen);
}
if (!adv_setting_result) {
set_rcsp_opt_setting(setting_opt_hdl, NULL);
}
return rlen + 1;
}
static u32 JL_opcode_set_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
rcsp_printf("JL_opcode_set_adv_info:\n");
rcsp_printf_buf(data, len);
u8 offset = 0;
while (offset < len) {
offset += adv_set_deal_one_attr(data, len, offset);
}
u8 ret = 0;
if (adv_setting_result) {
ret = adv_setting_result;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1, ble_con_handle, spp_remote_addr);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1, ble_con_handle, spp_remote_addr);
}
#if TCFG_RCSP_DUAL_CONN_ENABLE
// 一拖二则需要手机重新拉取C0设置的设备信息
u8 adv_cmd = 0x0;
adv_info_device_request(&adv_cmd, sizeof(adv_cmd));
#endif
return 0;
}
static u8 rcsp_adv_get_and_fill_adv_info(u8 *buf, u16 max_len, u8 offset, u8 type)
{
u8 *adv_data = NULL;
RCSP_SETTING_OPT *setting_opt_hdl = get_rcsp_setting_opt_hdl(type);
u8 size = get_setting_extra_handle(setting_opt_hdl, &adv_data, NULL);
if (size && adv_data) {
size = add_one_attr(buf, max_len, offset, type, (void *)adv_data, size);
}
return size;
}
static u32 JL_opcode_get_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
u8 buf[256] = {0};
u8 offset = 0;
u32 ret = 0;
u32 mask = READ_BIG_U32(data);
rcsp_printf("FEATURE MASK : %x\n", mask);
/* #define ATTR_TYPE_BAT_VALUE (0) */
/* #define ATTR_TYPE_EDR_NAME (1) */
//get version
if (mask & BIT(ATTR_TYPE_BAT_VALUE)) {
rcsp_printf("ATTR_TYPE_BAT_VALUE\n");
u8 bat[3];
void bt_adv_get_bat(u8 * buf);
bt_adv_get_bat(bat);
offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_BAT_VALUE, bat, 3);
}
#if RCSP_ADV_NAME_SET_ENABLE
if (mask & BIT(ATTR_TYPE_EDR_NAME)) {
rcsp_printf("ATTR_TYPE_EDR_NAME\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_EDR_NAME);
}
#endif // RCSP_ADV_NAME_SET_ENABLE
#if RCSP_ADV_KEY_SET_ENABLE
if (mask & BIT(ATTR_TYPE_KEY_SETTING)) {
rcsp_printf("ATTR_TYPE_KEY_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_KEY_SETTING);
}
if (mask & BIT(ATTR_TYPE_ANC_VOICE_KEY)) {
rcsp_printf("ATTR_TYPE_ANC_VOICE_KEY\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_ANC_VOICE_KEY);
}
#endif // RCSP_ADV_KEY_SET_ENABLE
#if RCSP_ADV_LED_SET_ENABLE
if (mask & BIT(ATTR_TYPE_LED_SETTING)) {
rcsp_printf("ATTR_TYPE_LED_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_LED_SETTING);
}
#endif // RCSP_ADV_LED_SET_ENABLE
#if RCSP_ADV_MIC_SET_ENABLE
if (mask & BIT(ATTR_TYPE_MIC_SETTING)) {
rcsp_printf("ATTR_TYPE_MIC_SETTING\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_MIC_SETTING);
}
#endif // RCSP_ADV_MIC_SET_ENABLE
#if RCSP_ADV_WORK_SET_ENABLE
if (mask & BIT(ATTR_TYPE_WORK_MODE)) {
rcsp_printf("ATTR_TYPE_WORK_MODE\n");
offset += rcsp_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_WORK_MODE);
}
#endif // RCSP_ADV_WORK_SET_ENABLE
#if RCSP_ADV_PRODUCT_MSG_ENABLE
if (mask & BIT(ATTR_TYPE_PRODUCT_MESSAGE)) {
rcsp_printf("ATTR_TYPE_PRODUCT_MESSAGE\n");
u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
u8 tversion[6];
tversion[0] = 0x05;
tversion[1] = 0xD6;
tversion[3] = vid & 0xFF;
tversion[2] = vid >> 8;
tversion[5] = pid & 0xFF;
tversion[4] = pid >> 8;
offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_PRODUCT_MESSAGE, (void *)tversion, 6);
}
#endif // RCSP_ADV_PRODUCT_MSG_ENABLE
rcsp_printf_buf(buf, offset);
ret = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, buf, offset, ble_con_handle, spp_remote_addr);
return ret;
}
int JL_rcsp_adv_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
rcsp_printf("JL_rcsp_adv_cmd_resp\n");
switch (OpCode) {
case JL_OPCODE_SET_ADV:
rcsp_printf(" JL_OPCODE_SET_ADV\n");
JL_opcode_set_adv_info(priv, OpCode, OpCode_SN, data, len, ble_con_handle, spp_remote_addr);
break;
case JL_OPCODE_GET_ADV:
rcsp_printf(" JL_OPCODE_GET_ADV\n");
JL_opcode_get_adv_info(priv, OpCode, OpCode_SN, data, len, ble_con_handle, spp_remote_addr);
break;
default:
return 1;
}
return 0;
}
#endif
#endif
@@ -0,0 +1,259 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_setting_opt.data.bss")
#pragma data_seg(".rcsp_setting_opt.data")
#pragma const_seg(".rcsp_setting_opt.text.const")
#pragma code_seg(".rcsp_setting_opt.text")
#endif
#include "rcsp_config.h"
#include "rcsp_setting_opt.h"
#include "rcsp_setting_sync.h"
#include "rcsp_manage.h"
#include "btstack/avctp_user.h"
#include "bt_tws.h"
#include "rcsp_bt_manage.h"
#if (RCSP_MODE)
static RCSP_SETTING_OPT *g_opt_link_head = NULL;
static u32 g_opt_total_size = 0;
int register_rcsp_setting_opt_setting(void *opt_param)
{
RCSP_SETTING_OPT *opt = g_opt_link_head;
RCSP_SETTING_OPT *item = (RCSP_SETTING_OPT *)opt_param;
while (opt && item) {
if (opt->setting_type == item->setting_type) {
return 0;
}
opt = opt->next;
}
if (item) {
item->next = g_opt_link_head;
g_opt_link_head = item;
return 0;
}
return -1;
}
static u8 deal_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type)
{
u8 offset = 0;
if (src_len) {
des[offset++] = type;
memcpy(des + offset, src, src_len);
offset += src_len;
}
return offset;
}
u8 rcsp_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len)
{
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
int len = 0;
len = syscfg_read(syscfg_id, buf, buf_len);
/* if (buf) { */
/* put_buf(buf, buf_len); */
/* } */
if (len > 0) {
for (int i = 0; i < buf_len; i++) {
if (buf[i] != 0xff) {
return (buf_len == len);
}
}
}
return 0;
}
void rcsp_setting_init(void)
{
RCSP_SETTING_OPT *opt = g_opt_link_head;
u32 opt_total_size = 0;
while (opt) {
u8 *data = NULL;
if (opt->data_len) {
data = zalloc(opt->data_len);
}
if (opt->custom_setting_init) {
opt->custom_setting_init();
} else if (rcsp_read_data_from_vm(opt->syscfg_id, data, opt->data_len)) {
if (opt->set_setting && opt->deal_opt_setting) {
opt->set_setting(data);
opt->deal_opt_setting(NULL, 0, 0);
}
}
if (data) {
free(data);
}
if (opt->data_len) {
opt_total_size += (opt->data_len + 1);
}
opt = opt->next;
}
if (opt_total_size) {
g_opt_total_size = opt_total_size + 2;
}
}
void update_rcsp_setting(u8 type)
{
u16 offset = sizeof(u16);
u8 *setting_to_sync = NULL;
if (g_opt_total_size) {
setting_to_sync = zalloc(g_opt_total_size);
} else {
return;
}
RCSP_SETTING_OPT *opt = g_opt_link_head;
while (opt) {
if (((u8) - 1 == type) || (type == opt->setting_type)) {
u8 *data = NULL;
if (opt->data_len) {
data = zalloc(opt->data_len);
}
if (opt->custom_setting_update) {
opt->custom_setting_update(data);
} else if (opt->get_setting && (opt->data_len > 0)) {
opt->get_setting(data);
}
offset += deal_setting_string_item(setting_to_sync + offset, data, opt->data_len, opt->setting_type);
if (data) {
free(data);
}
}
opt = opt->next;
}
if (offset > sizeof(u16)) {
memcpy(setting_to_sync, &offset, sizeof(offset));
if (((u8) - 1) == type) {
tws_api_send_data_to_sibling(setting_to_sync, offset, TWS_FUNC_ID_ADV_SETTING_SYNC);
tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_APP_RESET_LED_UI, 300);
} else {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_send_data_to_sibling(setting_to_sync, offset, TWS_FUNC_ID_ADV_SETTING_SYNC);
tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_APP_RESET_LED_UI, 300);
}
}
}
if (setting_to_sync) {
free(setting_to_sync);
}
}
void deal_sibling_setting(u8 *buf)
{
u8 type;
u16 len = 0;
memcpy(&len, buf, sizeof(len));
u16 offset = sizeof(len);
u8 *data;
while (offset < len) {
type = buf[offset++];
data = buf + offset;
RCSP_SETTING_OPT *opt = g_opt_link_head;
while (opt) {
if (type == opt->setting_type) {
if (opt->custom_sibling_setting_deal) {
opt->custom_sibling_setting_deal(data);
} else if (opt->set_setting) {
opt->set_setting(data);
}
offset += opt->data_len;
opt->need_opt = true;
break;
}
opt = opt->next;
}
}
// 发送事件
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_UPDATE, NULL, 0);
}
void update_info_from_vm_info(void)
{
RCSP_SETTING_OPT *opt = g_opt_link_head;
while (opt) {
if (opt->need_opt) {
if (opt->custom_vm_info_update) {
opt->custom_vm_info_update();
} else if (opt->deal_opt_setting) {
opt->deal_opt_setting(NULL, 1, 0);
}
opt->need_opt = false;
}
opt = opt->next;
}
}
RCSP_SETTING_OPT *get_rcsp_setting_opt_hdl(u16 setting_type)
{
RCSP_SETTING_OPT *opt = g_opt_link_head;
while (opt) {
if (opt->setting_type == setting_type) {
return opt;
}
opt = opt->next;
}
return NULL;
}
void set_rcsp_opt_setting(RCSP_SETTING_OPT *setting_opt_hdl, u8 *data)
{
if (setting_opt_hdl && setting_opt_hdl->deal_opt_setting) {
setting_opt_hdl->deal_opt_setting(data, 1, 1);
}
}
int get_rcsp_opt_setting(RCSP_SETTING_OPT *setting_opt_hdl, u8 *data)
{
if (setting_opt_hdl && setting_opt_hdl->get_setting) {
return setting_opt_hdl->get_setting(data);
}
return 0;
}
int set_setting_extra_handle(RCSP_SETTING_OPT *setting_opt_hdl, void *data, void *data_len)
{
if (setting_opt_hdl && setting_opt_hdl->set_setting_extra_handle) {
return setting_opt_hdl->set_setting_extra_handle(data, data_len);
}
return -1;
}
int get_setting_extra_handle(RCSP_SETTING_OPT *setting_opt_hdl, void *setting_data, void *setting_data_len)
{
if (setting_opt_hdl && setting_opt_hdl->get_setting_extra_handle) {
return setting_opt_hdl->get_setting_extra_handle(setting_data, setting_data_len);
}
return 0;
}
void rcsp_opt_release(void)
{
RCSP_SETTING_OPT *opt = g_opt_link_head;
while (opt) {
if (opt->custom_setting_release) {
opt->custom_setting_release();
}
opt = opt->next;
}
}
#if RCSP_ADV_EN
void modify_bt_name_and_reset(u32 msec)
{
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_RESET_SYNC, 0, msec);
}
#endif
#endif
@@ -0,0 +1,51 @@
#ifndef __RCSP_SETTING_OPT_H__
#define __RCSP_SETTING_OPT_H__
#include "system/includes.h"
#define REGISTER_APP_SETTING_OPT(rcsp_opt) \
int rcsp_opt##_setting_init(void) {\
return register_rcsp_setting_opt_setting(&rcsp_opt);\
}\
late_initcall(rcsp_opt##_setting_init);
#pragma pack(1)
typedef struct _RCSP_SETTING_OPT {
struct _RCSP_SETTING_OPT *next;
bool need_opt;
u32 data_len;
int setting_type;
int syscfg_id;
int (*get_setting)(u8 *setting_data);
void (*set_setting)(u8 *setting_data);
void (*deal_opt_setting)(u8 *setting_data, u8 write_vm, u8 tws_sync);
// 上面是必填,下面是选填
int (*custom_setting_init)(void);
int (*custom_vm_info_update)(void);
int (*custom_setting_update)(u8 *setting_data);
int (*custom_sibling_setting_deal)(u8 *setting_data);
int (*custom_setting_release)(void);
int (*set_setting_extra_handle)(void *setting_data, void *setting_data_len);
int (*get_setting_extra_handle)(void *setting_data, void *setting_data_len);
} RCSP_SETTING_OPT;
#pragma pack()
void deal_sibling_setting(u8 *buf);
u8 rcsp_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len);
int register_rcsp_setting_opt_setting(void *opt_param);
RCSP_SETTING_OPT *get_rcsp_setting_opt_hdl(u16 setting_type);
void set_rcsp_opt_setting(RCSP_SETTING_OPT *setting_opt, u8 *data);
int get_rcsp_opt_setting(RCSP_SETTING_OPT *setting_opt, u8 *data);
int set_setting_extra_handle(RCSP_SETTING_OPT *setting_opt_hdl, void *setting_data, void *setting_data_len);
int get_setting_extra_handle(RCSP_SETTING_OPT *setting_opt_hdl, void *setting_data, void *setting_data_len);
void rcsp_setting_init(void);
void update_rcsp_setting(u8 type);
void update_info_from_vm_info(void);
void rcsp_opt_release(void);
//属于弹窗
void modify_bt_name_and_reset(u32 msec);
#endif
@@ -0,0 +1,135 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_setting_sync.data.bss")
#pragma data_seg(".rcsp_setting_sync.data")
#pragma const_seg(".rcsp_setting_sync.text.const")
#pragma code_seg(".rcsp_setting_sync.text")
#endif
#include "app_config.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "adv_time_stamp_setting.h"
#include "rcsp_bt_manage.h"
#include "rcsp_manage.h"
#if (RCSP_MODE && TCFG_USER_TWS_ENABLE)
#include "btstack/avctp_user.h"
#include "bt_tws.h"
#include "system/event.h"
#include "app_msg.h"
static u16 g_curr_get_adv_sync_tws_len = 0;
static void rcsp_sync_tws_func_t(void *data, u16 len, bool rx)
{
if (rx) {
g_curr_get_adv_sync_tws_len = len;
deal_sibling_setting((u8 *)data);
}
}
REGISTER_TWS_FUNC_STUB(adv_tws_sync) = {
.func_id = TWS_FUNC_ID_ADV_SETTING_SYNC,
.func = rcsp_sync_tws_func_t,
};
static void tws_app_opt_sync_call_fun(int cmd, int err)
{
struct bt_event bt_e;
bt_e.event = APP_OPT_TWS_EVENT_SYNC_FUN_CMD;
bt_e.args[0] = 0;
bt_e.args[1] = 0;
bt_e.args[2] = cmd;
struct bt_event *bt_e_p = &bt_e;
app_send_message_from(MSG_FROM_RCSP_BT, sizeof(*bt_e_p), (int *)bt_e_p);
}
TWS_SYNC_CALL_REGISTER(tws_tone_sync) = {
.uuid = TWS_FUNC_APP_OPT_UUID,
.func = tws_app_opt_sync_call_fun,
};
#if RCSP_ADV_EN
static void adv_sync_time_stamp_func_t(void *data, u16 len, bool rx)
{
if (rx) {
deal_sibling_time_stamp_setting_switch(data, len);
}
}
REGISTER_TWS_FUNC_STUB(adv_time_stamp_sync) = {
.func_id = TWS_FUNC_ID_TIME_STAMP_SYNC,
.func = adv_sync_time_stamp_func_t,
};
static void adv_sync_reset_sync_func_t(int args, int err)
{
extern void cpu_reset();
cpu_reset();
}
TWS_SYNC_CALL_REGISTER(adv_reset_sync) = {
.uuid = TWS_FUNC_ID_ADV_RESET_SYNC,
.func = adv_sync_reset_sync_func_t,
};
static void adv_find_dev_sync_func_t(int args, int err)
{
/* printf("rcsp_find %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((u8 *)&args, sizeof(int)); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_RESUME, (u8 *)&args, sizeof(args));
}
TWS_SYNC_CALL_REGISTER(adv_find_dev_sync) = {
.uuid = TWS_FUNC_ID_ADV_FIND_DEV_SYNC,
.func = adv_find_dev_sync_func_t,
};
void find_device_sync(u8 *param, u32 msec)
{
/* printf("rcsp_find %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(param, 3); */
int priv = 0;
if (TWS_ROLE_MASTER == tws_api_get_role()) {
memcpy(&priv, param, 3);
/* printf("rcsp_find %s, %s, %d, priv:%d\n", __FILE__, __FUNCTION__, __LINE__, priv); */
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_SYNC, priv, msec);
}
}
static void adv_find_dev_stop_sync_timer_func_t(int args, int err)
{
/* printf("rcsp_find %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((u8 *)&args, sizeof(int)); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_STOP, (u8 *)&args, sizeof(args));
}
TWS_SYNC_CALL_REGISTER(adv_find_dev_stop_sync) = {
.uuid = TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC,
.func = adv_find_dev_stop_sync_timer_func_t,
};
#endif
void find_device_stop_timer(u8 *param, u32 msec)
{
/* printf("rcsp_find %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(param, 3); */
int priv = 0;
if (TWS_ROLE_MASTER == tws_api_get_role()) {
memcpy(&priv, param, 3);
/* printf("rcsp_find %s, %s, %d, priv:%d\n", __FILE__, __FUNCTION__, __LINE__, priv); */
/* put_buf((u8 *)&priv, sizeof(int)); */
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC, priv, msec);
}
}
u16 get_adv_sync_tws_len(void)
{
return (g_curr_get_adv_sync_tws_len > 2) ? (g_curr_get_adv_sync_tws_len - 2) : g_curr_get_adv_sync_tws_len;
}
#endif
@@ -0,0 +1,57 @@
#ifndef __RCSP_SETTING_SYNC_H__
#define __RCSP_SETTING_SYNC_H__
#include "classic/tws_api.h"
#define TWS_FUNC_ID_ADV_SETTING_SYNC \
TWS_FUNC_ID('R', 'C', 'S', 'P')
#define TWS_FUNC_APP_OPT_UUID \
TWS_FUNC_ID('A' + 'P' + 'P', \
'O' + 'P' + 'T', \
'T' + 'W' + 'S', \
'U' + 'U' + 'I' + 'D')
#define SYS_BT_EVENT_FROM_APP_OPT_TWS \
TWS_FUNC_ID('A' + 'P' + 'P', \
'O' + 'P' + 'T', \
'T' + 'S' + 'S', \
'E' + 'V' + 'E' + 'N' + 'T')
// ----属于弹窗----
#define TWS_FUNC_ID_TIME_STAMP_SYNC \
TWS_FUNC_ID('T' + 'W' + 'S', \
'A' + 'D' + 'V', \
'T' + 'I' + 'M' + 'E', \
'S' + 'T' + 'A' + 'M' + 'P')
#define TWS_FUNC_ID_ADV_RESET_SYNC \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'D' + 'V') << (2 * 8)) | \
((u8)('R' + 'E' + 'S' + 'E' + 'T') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
#define TWS_FUNC_ID_ADV_FIND_DEV_SYNC \
(((u8)('A' + 'D' + 'V') << (3 * 8)) | \
((u8)('F' + 'I' + 'N' + 'D') << (2 * 8)) | \
((u8)('D' + 'E' + 'V') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
#define TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC \
(((u8)('F' + 'I' + 'N' + 'D') << (3 * 8)) | \
((u8)('D' + 'E' + 'V') << (2 * 8)) | \
((u8)('S' + 'T' + 'O' + 'P') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
#endif
// ---------------
enum {
APP_OPT_TWS_EVENT_SYNC_FUN_CMD,
};
enum {
APP_OPT_SYNC_CMD_APP_RESET_LED_UI,
APP_OPT_SYNC_CMD_MUSIC_INFO,
APP_OPT_SYNC_CMD_MUSIC_PLAYER_STATE,
APP_OPT_SYNC_CMD_MUSIC_PLAYER_TIEM_EN,
};
@@ -0,0 +1,382 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_1t2_setting.data.bss")
#pragma data_seg(".adv_1t2_setting.data")
#pragma const_seg(".adv_1t2_setting.text.const")
#pragma code_seg(".adv_1t2_setting.text")
#endif
#include "adv_1t2_setting.h"
#include "app_config.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#include "rcsp_define.h"
#include "JL_rcsp_protocol.h"
#include "ble_rcsp_server.h"
#include "app_ble_spp_api.h"
#if RCSP_MODE && TCFG_RCSP_DUAL_CONN_ENABLE
#if RCSP_MODE == RCSP_MODE_EARPHONE
#include "earphone.h"
#endif
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#include "classic/tws_api.h"
#endif
#define DEVICE_NAME_LEN 32 // 缓存设备名长度为32,不可更改该值
#pragma pack(1)
typedef struct _rcsp_device_edr_info {
u8 is_bind;
u8 addr[6];
u8 name_len;
u8 name[DEVICE_NAME_LEN];
u16 ble_con_handle; // 通过协议绑定ble_con_handle
} JL_rcsp_device_edr_info;
#pragma pack()
static JL_rcsp_device_edr_info device_edr_info = {0};
static JL_rcsp_device_edr_info device_edr_info1 = {0};
void rcsp_device_edr_info_dump()
{
return;
printf("%s, %d, a isbind:%d, name_len:%d, ble_con_handle:%d\n", __FUNCTION__, __LINE__, device_edr_info.is_bind, device_edr_info.name_len, device_edr_info.ble_con_handle);
put_buf(device_edr_info.addr, 6);
put_buf(device_edr_info.name, device_edr_info.name_len);
printf("%s, %d, b isbind:%d, name_len:%d, ble_con_handle:%d\n", __FUNCTION__, __LINE__, device_edr_info1.is_bind, device_edr_info1.name_len, device_edr_info1.ble_con_handle);
put_buf(device_edr_info1.addr, 6);
put_buf(device_edr_info1.name, device_edr_info1.name_len);
}
extern u8 bt_rcsp_device_conn_num(void);
// 获取ble hdl对应的地址
extern u8 *rcsp_get_ble_hdl_remote_mac_addr(u16 ble_con_handle);
/**
* @brief 获取rcsp_1t2开关
*
* @result bool
*/
bool rcsp_get_1t2_switch()
{
#if RCSP_MODE == RCSP_MODE_EARPHONE
if (get_bt_dual_config() == DUAL_CONN_SET_TWO) {
return true;
}
#endif
return false;
}
/**
* @brief 设置rcsp_1t2开关
*
* @param mode_switch 开关
*/
void rcsp_set_1t2_switch(bool switch_1t2, u16 ble_con_handle, u8 *spp_remote_addr)
{
printf("%s, switch:%d, ble_con_handle:%d, spp_remote_addr:\n", __FUNCTION__, switch_1t2, ble_con_handle);
put_buf(spp_remote_addr, 6);
rcsp_device_edr_info_dump();
u8 *local_addr = spp_remote_addr;
u8 _addr_temp[6] = {0};
if (ble_con_handle && !memcmp(spp_remote_addr, _addr_temp, 6)) {
// 如果手机没有绑定自己的mac地址,则通过下述api去获取ble的地址,
// 此时ble与edr的地址可能相同则该逻辑正确,如果不相同的话则有无法处理的bug
local_addr = rcsp_get_ble_hdl_remote_mac_addr(ble_con_handle);
}
printf("%s, local_addr:", __FUNCTION__);
put_buf(local_addr, 6);
#if RCSP_MODE == RCSP_MODE_EARPHONE
// 断开edr
set_dual_conn_config(local_addr, switch_1t2 ? 1 : 0);
#else
ASSERT(0, "current sdk type is not support 1t2setting!");
#endif
// 断开ble
rcsp_disconn_other_ble(ble_con_handle);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_1T2_SETTING, NULL, 0);
// 根据设置重新判断是否开启蓝牙广播
#if TCFG_USER_TWS_ENABLE
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
rcsp_ble_adv_enable_with_con_dev();
}
}
#else
rcsp_ble_adv_enable_with_con_dev();
#endif
}
void rcsp_1t2_set_edr_info(u8 *addr, u8 *device_name)
{
if (!addr) {
return;
}
printf("%s, %s, %d, device_name:%s\n", __FILE__, __FUNCTION__, __LINE__, device_name);
put_buf(addr, 6);
if (memcmp(device_edr_info.addr, addr, 6) && memcmp(device_edr_info1.addr, addr, 6)) {
u8 _addr_temp[6] = {0};
if (!memcmp(device_edr_info.addr, _addr_temp, 6)) {
printf("%s, %d\n", __FUNCTION__, __LINE__);
memcpy(device_edr_info.addr, addr, 6);
put_buf(device_edr_info.addr, 6);
device_edr_info.name_len = strlen((const char *)device_name);
if (device_edr_info.name_len) {
memcpy(device_edr_info.name, device_name, device_edr_info.name_len);
}
} else if (!memcmp(device_edr_info1.addr, _addr_temp, 6)) {
printf("%s, %d\n", __FUNCTION__, __LINE__);
memcpy(device_edr_info1.addr, addr, 6);
device_edr_info1.name_len = strlen((const char *)device_name);
if (device_edr_info1.name_len) {
memcpy(device_edr_info1.name, device_name, device_edr_info1.name_len);
}
}
}
if (bt_rcsp_device_conn_num() > 0) {
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status() && TWS_ROLE_MASTER == tws_api_get_role()) {
rcsp_notify_1t2_bt_device_name_list();
}
#else
rcsp_notify_1t2_bt_device_name_list();
#endif
}
rcsp_device_edr_info_dump();
rcsp_1t2_setting_tws_sync();
}
void rcsp_1t2_reset_edr_info_for_ble_disconn(u16 ble_con_handle)
{
if (device_edr_info.ble_con_handle == ble_con_handle) {
device_edr_info.is_bind = 0;
device_edr_info.ble_con_handle = 0;
}
if (device_edr_info1.ble_con_handle == ble_con_handle) {
device_edr_info1.is_bind = 0;
device_edr_info1.ble_con_handle = 0;
}
rcsp_1t2_setting_tws_sync();
rcsp_notify_1t2_bt_device_name_list();
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
rcsp_device_edr_info_dump();
}
void rcsp_1t2_reset_edr_info_for_edr_disconn(u8 *addr)
{
if (!addr) {
return;
}
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(addr, 6); */
u8 _addr_temp[6] = {0};
if (memcmp(device_edr_info.addr, _addr_temp, 6)) {
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(device_edr_info.addr, 6); */
if (!memcmp(device_edr_info.addr, addr, 6)) {
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
rcsp_disconn_designated_ble(device_edr_info.ble_con_handle);
memset(&device_edr_info, 0, sizeof(JL_rcsp_device_edr_info));
}
}
if (memcmp(device_edr_info1.addr, _addr_temp, 6)) {
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(device_edr_info1.addr, 6); */
if (!memcmp(device_edr_info1.addr, addr, 6)) {
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
rcsp_disconn_designated_ble(device_edr_info1.ble_con_handle);
memset(&device_edr_info1, 0, sizeof(JL_rcsp_device_edr_info));
}
}
rcsp_1t2_setting_tws_sync();
rcsp_notify_1t2_bt_device_name_list();
rcsp_device_edr_info_dump();
}
void rcsp_1t2_setting_reset()
{
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
memset(&device_edr_info, 0, sizeof(JL_rcsp_device_edr_info));
memset(&device_edr_info1, 0, sizeof(JL_rcsp_device_edr_info));
}
void rcsp_get_1t2_bt_device_name_list(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
/* put_buf(data, len); */
/* printf("%s, %d, ble_con_handle:%d\n", __FUNCTION__, __LINE__, ble_con_handle); */
/* put_buf(spp_remote_addr, 6); */
rcsp_device_edr_info_dump();
u8 is_bind = 0;
if (len > 0) {
is_bind = data[0];
}
/* printf("%s, %d, is_bind:%d\n", __FUNCTION__, __LINE__, is_bind); */
u8 _addr_temp[6] = {0};
bool need_notify = false;
if (is_bind) {
need_notify = true;
// 已绑定信息,更新本地缓存edr信息
u8 *phone_addr = data + 1;
u8 phone_name_len = data[7];
if (!memcmp(device_edr_info.addr, phone_addr, 6)) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
device_edr_info.is_bind = 1;
if (phone_name_len) {
memset(device_edr_info.name, 0, DEVICE_NAME_LEN);
memcpy(device_edr_info.name, data + 8, phone_name_len);
}
// iOS绑定ble_con_handle
if (ble_con_handle) {
device_edr_info.ble_con_handle = ble_con_handle;
} else {
device_edr_info.ble_con_handle = 0;
}
}
if (!memcmp(device_edr_info1.addr, phone_addr, 6)) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
device_edr_info1.is_bind = 1;
if (phone_name_len) {
memset(device_edr_info1.name, 0, DEVICE_NAME_LEN);
memcpy(device_edr_info1.name, data + 8, phone_name_len);
}
// iOS绑定ble_con_handle
if (ble_con_handle) {
device_edr_info1.ble_con_handle = ble_con_handle;
} else {
device_edr_info1.ble_con_handle = 0;
}
}
} else {
// do nothing
// 未绑定信息,直接发送本地缓存edr信息
}
// 返回已连接手机列表
// device_count + (is_bind + phone_addr + phone_name_len + phone_name) + (...)
u8 total_buf_len = 1;
u8 device_count = 0;
if (memcmp(device_edr_info.addr, _addr_temp, 6)) {
device_count++;
// 详细见rcsp协议文档C031相关命令
total_buf_len += (1 + 6 + 1 + device_edr_info.name_len);
}
if (memcmp(device_edr_info1.addr, _addr_temp, 6)) {
device_count++;
total_buf_len += (1 + 6 + 1 + device_edr_info1.name_len);
}
if (device_count == 0) {
return;
}
u8 *resp = zalloc(total_buf_len);
ASSERT(resp, "func = %s, line = %d, no ram!!\n", __FUNCTION__, __LINE__);
memcpy(resp, (u8 *)&device_count, 1);
u8 buf_index = 1;
if (memcmp(device_edr_info.addr, _addr_temp, 6)) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
memcpy(resp + buf_index, (u8 *)&device_edr_info.is_bind, 1);
buf_index += 1;
memcpy(resp + buf_index, device_edr_info.addr, 6);
buf_index += 6;
memcpy(resp + buf_index, (u8 *)&device_edr_info.name_len, 1);
buf_index += 1;
memcpy(resp + buf_index, device_edr_info.name, device_edr_info.name_len);
buf_index += device_edr_info.name_len;
}
if (memcmp(device_edr_info1.addr, _addr_temp, 6)) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
memcpy(resp + buf_index, (u8 *)&device_edr_info1.is_bind, 1);
buf_index += 1;
memcpy(resp + buf_index, device_edr_info1.addr, 6);
buf_index += 6;
memcpy(resp + buf_index, (u8 *)&device_edr_info1.name_len, 1);
buf_index += 1;
memcpy(resp + buf_index, device_edr_info1.name, device_edr_info1.name_len);
}
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
/* put_buf(resp, total_buf_len); */
if (OpCode == JL_OPCODE_1T2_DEVICE_EDR_INFO_LIST) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
// 回复
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp, total_buf_len, ble_con_handle, spp_remote_addr);
} else {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
// 通知
JL_CMD_send(JL_OPCODE_1T2_DEVICE_EDR_INFO_LIST, resp, total_buf_len, JL_NOT_NEED_RESPOND, 0, NULL);
}
if (need_notify) {
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
JL_CMD_send(JL_OPCODE_1T2_DEVICE_EDR_INFO_LIST, resp, total_buf_len, JL_NOT_NEED_RESPOND, 0, NULL);
}
free(resp);
rcsp_1t2_setting_tws_sync();
}
void rcsp_notify_1t2_bt_device_name_list()
{
rcsp_get_1t2_bt_device_name_list(NULL, 0, 0, NULL, 0, 0, NULL);
}
#if TCFG_USER_TWS_ENABLE
#define TWS_FUNC_ID_RCSP_1T2_SETTING \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('1' + 'T' + '2') << (2 * 8)) | \
((u8)('T' + 'W' + 'S') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
static void rcsp_1t2_setting_tws_sync_in_irq(void *_data, u16 len, bool rx)
{
if (rx) {
u16 info_size = sizeof(JL_rcsp_device_edr_info);
memcpy((void *)&device_edr_info, _data, info_size);
memcpy((void *)&device_edr_info1, _data + info_size, info_size);
/* printf("1t2setting %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((void *)&device_edr_info, info_size); */
/* printf("1t2setting %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((void *)&device_edr_info1, info_size); */
}
}
REGISTER_TWS_FUNC_STUB(tws_rcsp_1t2_setting_sync) = {
.func_id = TWS_FUNC_ID_RCSP_1T2_SETTING,
.func = rcsp_1t2_setting_tws_sync_in_irq,
};
// tws同步1t2缓存信息
void rcsp_1t2_setting_tws_sync(void)
{
if (get_bt_tws_connect_status() && TWS_ROLE_MASTER == tws_api_get_role()) {
u16 info_size = sizeof(JL_rcsp_device_edr_info);
u8 buf[sizeof(JL_rcsp_device_edr_info) * 2] = {0};
memcpy(buf, (void *)&device_edr_info, info_size);
memcpy(buf + info_size, (void *)&device_edr_info1, info_size);
/* printf("1t2setting %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((void *)&device_edr_info, info_size); */
/* printf("1t2setting %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf((void *)&device_edr_info1, info_size); */
/* printf("1t2setting %s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(buf, sizeof(buf)); */
tws_api_send_data_to_sibling(buf, sizeof(buf), TWS_FUNC_ID_RCSP_1T2_SETTING);
}
}
#else
// tws同步1t2缓存信息
void rcsp_1t2_setting_tws_sync(void)
{
}
#endif
#endif // TCFG_RCSP_DUAL_CONN_ENABLE
@@ -0,0 +1,60 @@
#ifndef __ADV_1T2_SETTING_H__
#define __ADV_1T2_SETTING_H__
#include "system/includes.h"
/**
* @brief 获取rcsp_1t2开关
*
* @result bool
*/
bool rcsp_get_1t2_switch();
/**
* @brief 设置rcsp_1t2开关
*
* @param mode_switch 开关
*/
void rcsp_set_1t2_switch(bool mode_switch, u16 ble_con_handle, u8 *spp_remote_addr);
/**
* @brief edr连接的时候记录地址与手机名
*
* @param addr
* @param device_name // 最长32bytes
*/
void rcsp_1t2_set_edr_info(u8 *addr, u8 *device_name);
/**
* @brief edr断开连接的时候记录地址与手机名
*
* @param addr
*/
void rcsp_1t2_reset_edr_info_for_edr_disconn(u8 *addr);
/**
* @brief edr断开连接的时候记录地址与手机名
*
* @param addr
*/
void rcsp_1t2_reset_edr_info_for_ble_disconn(u16 ble_con_handle);
// 初始化内部buf
void rcsp_1t2_setting_reset();
/**
* @brief 获取rcsp_1t2已连接蓝牙设备主机(如手机)名列表
*/
void rcsp_get_1t2_bt_device_name_list(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
/**
* @brief 通知rcsp_1t2已连接蓝牙设备主机(如手机)名列表
*/
void rcsp_notify_1t2_bt_device_name_list();
/**
* @brief 1t2信息同步到从机
*/
void rcsp_1t2_setting_tws_sync(void);
#endif
@@ -0,0 +1,96 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_adaptive_noise_reduction.data.bss")
#pragma data_seg(".adv_adaptive_noise_reduction.data")
#pragma const_seg(".adv_adaptive_noise_reduction.text.const")
#pragma code_seg(".adv_adaptive_noise_reduction.text")
#endif
#include "adv_adaptive_noise_reduction.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "app_config.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_ANC_VOICE && RCSP_ADV_ADAPTIVE_NOISE_REDUCTION)
#include "audio_anc.h"
/**
* @brief 获取自适应降噪信息开关
*
* @result 1:自适应降噪开 0:自适应降噪关
*/
int get_adaptive_noise_reduction_switch()
{
int sw_result = audio_anc_coeff_mode_get();
return sw_result;
}
/**
* @brief 开启自适应降噪
*/
void set_adaptive_noise_reduction_on()
{
audio_anc_coeff_adaptive_set(1, 1, 1);
}
/**
* @brief 关闭自适应降噪
*/
void set_adaptive_noise_reduction_off()
{
audio_anc_coeff_adaptive_set(0, 1, 1);
}
static u8 adaptive_noise_reduction_reseting = 0; // 重新检测状态,1:进行中 0:结束
static u8 adaptive_noise_reduction_reset_result = 0; // 重新检测结果,1:失败 0:成功
/**
* @brief 自适应降噪重新检测
*/
void set_adaptive_noise_reduction_reset()
{
audio_anc_mode_ear_adaptive();
adaptive_noise_reduction_reseting = 1;
}
/**
* @brief 获取自适应降噪重新检测状态
*
* @result 1:进行中 0:结束
*/
u8 get_adaptive_noise_reduction_reset_status()
{
return adaptive_noise_reduction_reseting;
}
/**
* @brief 获取自适应降噪重新检测结果
*
* @result 1:失败 0:成功
*/
u8 get_adaptive_noise_reduction_reset_result()
{
return adaptive_noise_reduction_reset_result;
}
/**
* @brief 自适应降噪重新检测结果回调
*/
void set_adaptive_noise_reduction_reset_callback(u8 result)
{
adaptive_noise_reduction_reseting = 0;
if (result != 0) {
// 成功
adaptive_noise_reduction_reset_result = 0;
} else {
// 失败
adaptive_noise_reduction_reset_result = 1;
}
// 通知手机APP
/* JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ADAPTIVE_NOISE_REDUCTION, NULL, 0);
}
#endif
@@ -0,0 +1,48 @@
#ifndef __ADV_ADAPTIVE_NOISE_REDUCTION_H__
#define __ADV_ADAPTIVE_NOISE_REDUCTION_H__
#include "system/includes.h"
/**
* @brief 获取自适应降噪信息开关
*
* @result 1:自适应降噪开 0:自适应降噪关
*/
int get_adaptive_noise_reduction_switch();
/**
* @brief 开启自适应降噪
*/
void set_adaptive_noise_reduction_on();
/**
* @brief 关闭自适应降噪
*/
void set_adaptive_noise_reduction_off();
/**
* @brief 自适应降噪重新检测
*/
void set_adaptive_noise_reduction_reset();
/**
* @brief 获取自适应降噪重新检测状态
*
* @result 1:进行中 0:结束
*/
u8 get_adaptive_noise_reduction_reset_status();
/**
* @brief 获取自适应降噪重新检测结果
*
* @result 1:失败 0:成功
*/
u8 get_adaptive_noise_reduction_reset_result();
/**
* @brief 自适应降噪重新检测结果回调
*/
void set_adaptive_noise_reduction_reset_callback(u8 result);
#endif
@@ -0,0 +1,85 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_ai_no_pick.data.bss")
#pragma data_seg(".adv_ai_no_pick.data")
#pragma const_seg(".adv_ai_no_pick.text.const")
#pragma code_seg(".adv_ai_no_pick.text")
#endif
#include "adv_ai_no_pick.h"
#include "app_config.h"
#include "rcsp_adv_bluetooth.h"
#if RCSP_ADV_AI_NO_PICK
/**
* @brief 获取智能免摘开关
*
* @result bool
*/
bool get_ai_no_pick_switch()
{
printf("===%s===", __FUNCTION__);
return true;
}
/**
* @brief 开启智能免摘
*/
void set_ai_no_pick_switch(bool p_switch)
{
printf("%s, switch:%d", __FUNCTION__, p_switch);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_AI_NO_PICK, NULL, 0);
}
/**
* @brief 获取智能免摘敏感度
*
* @result RCSP_AI_NO_PICK_SENSITIVITY
*/
RCSP_AI_NO_PICK_SENSITIVITY get_ai_no_pick_sensitivity()
{
printf("===%s===", __FUNCTION__);
return RCSP_AI_NO_PICK_SENSITIVITY_HIGH;
}
/**
* @brief 设置智能免摘敏感度
*/
void set_ai_no_pick_sensitivity(RCSP_AI_NO_PICK_SENSITIVITY sensitivity)
{
switch (sensitivity) {
case RCSP_AI_NO_PICK_SENSITIVITY_HIGH:
case RCSP_AI_NO_PICK_SENSITIVITY_LOW:
default:
printf("%s, sensitivity:%d", __FUNCTION__, sensitivity);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_AI_NO_PICK, NULL, 0);
}
}
/**
* @brief 获取智能免摘自动关闭时间
*
* @result RCSP_AI_NO_PICK_AUTO_CLOSE_TIME
*/
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME get_ai_no_pick_auto_close_time()
{
printf("===%s===", __FUNCTION__);
return RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_NONE;
}
/**
* @brief 设置智能免摘自动关闭时间
*/
void set_ai_no_pick_auto_close_time(RCSP_AI_NO_PICK_AUTO_CLOSE_TIME time_type)
{
switch (time_type) {
case RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_NONE:
case RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_5s:
case RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_15s:
case RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_30s:
default:
printf("%s, type:%d", __FUNCTION__, time_type);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_AI_NO_PICK, NULL, 0);
}
}
#endif
@@ -0,0 +1,54 @@
#ifndef __ADV_AI_NO_PICK_H__
#define __ADV_AI_NO_PICK_H__
#include "system/includes.h"
typedef enum {
RCSP_AI_NO_PICK_SENSITIVITY_HIGH = 0x00,
RCSP_AI_NO_PICK_SENSITIVITY_LOW = 0x01,
} RCSP_AI_NO_PICK_SENSITIVITY;
typedef enum {
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_NONE = 0x00, // 不自动关闭
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_5s = 0x01,
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_15s = 0x02,
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_30s = 0x03,
} RCSP_AI_NO_PICK_AUTO_CLOSE_TIME;
/**
* @brief 获取智能免摘开关
*
* @result bool
*/
bool get_ai_no_pick_switch();
/**
* @brief 开启智能免摘
*/
void set_ai_no_pick_switch(bool p_switch);
/**
* @brief 获取智能免摘敏感度
*
* @result RCSP_AI_NO_PICK_SENSITIVITY
*/
RCSP_AI_NO_PICK_SENSITIVITY get_ai_no_pick_sensitivity();
/**
* @brief 设置智能免摘敏感度
*/
void set_ai_no_pick_sensitivity(RCSP_AI_NO_PICK_SENSITIVITY sensitivity);
/**
* @brief 获取智能免摘自动关闭时间
*
* @result RCSP_AI_NO_PICK_AUTO_CLOSE_TIME
*/
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME get_ai_no_pick_auto_close_time();
/**
* @brief 设置智能免摘自动关闭时间
*/
void set_ai_no_pick_auto_close_time(RCSP_AI_NO_PICK_AUTO_CLOSE_TIME time_type);
#endif // __ADV_AI_NO_PICK_H__
@@ -0,0 +1,668 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_anc_voice.data.bss")
#pragma data_seg(".adv_anc_voice.data")
#pragma const_seg(".adv_anc_voice.text.const")
#pragma code_seg(".adv_anc_voice.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "ble_rcsp_server.h"
#include "smartbox_user_app.h"
#include "adv_anc_voice.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[RCSP-ANC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_CHAR_ENABLE
#include "debug.h"
#if (RCSP_MODE && RCSP_ADV_ANC_VOICE)
#include "audio_anc.h"
// anc信息:mode(1byte/0/1/2) + ( left_max(2byte) + right_max(2byte) + left_cur_val(2byte) + right_cur_val(2byte) ) * 3
static u8 g_anc_info[25] = {0};
extern int get_bt_tws_connect_status();
extern u8 JL_get_cur_bt_channel_sel(void);
static u8 rcsp_adv_anc_event_flag = 0x0;
static void enable_adv_anc_event(void)
{
rcsp_adv_anc_event_flag = 1;
}
static u8 get_adv_anc_event_status(void)
{
return rcsp_adv_anc_event_flag;
}
static void disable_adv_anc_event(void)
{
rcsp_adv_anc_event_flag = 0;
}
static bool check_pos_neg(u8 mode)
{
bool ret = false;
u8 offset = 1 + mode * 8;
#if TCFG_USER_TWS_ENABLE
if ('R' == bt_tws_get_local_channel()) {
offset += 2;
}
#endif
s16 val = g_anc_info[offset] << 8 | g_anc_info[offset + 1];
if (val < 0) {
ret = true;
}
return ret;
}
int get_anc_voice_info(u8 *anc_info)
{
memcpy(anc_info, g_anc_info, sizeof(g_anc_info));
return 0;
}
void set_anc_voice_info(u8 *anc_info)
{
memcpy(g_anc_info, anc_info, sizeof(g_anc_info));
}
static void update_anc_voice_vm_value(u8 *anc_info)
{
u8 anc_vm_info[25] = {-1};
int ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_vm_info, 1);
if (0 != memcmp(anc_vm_info, anc_info, 1)) {
ret = syscfg_write(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_info, 1);
}
ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE, anc_vm_info + 1, sizeof(anc_vm_info) - 1);
if (0 != memcmp(anc_vm_info + 1, anc_info + 1, sizeof(anc_vm_info) - 1)) {
ret = syscfg_write(CFG_RCSP_ADV_ANC_VOICE, anc_info + 1, sizeof(anc_vm_info) - 1);
}
}
static void anc_voice_sync(u8 *anc_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
/* update_adv_setting(BIT(ATTR_TYPE_ANC_VOICE)); */
update_rcsp_setting(ATTR_TYPE_ANC_VOICE);
}
#endif
}
static u8 count_the_num_of_positions(u16 value)
{
u8 cnt;
for (cnt = 0; value; value = value & (value - 1), cnt++);
return cnt;
}
static void anc_voice_effect_set(u8 *anc_setting, u8 mode, s16 value)
{
static s16 value_old = -1;
#if TCFG_AUDIO_ANC_ENABLE
if (value != value_old) {
extern void audio_anc_fade_gain_set(int gain);
audio_anc_fade_gain_set(value);
}
if (anc_setting) {
if (-1 == value_old) {
anc_mode_switch(mode + 1, 0);
} else {
anc_mode_switch(mode + 1, 1);
}
} else {
#if TCFG_USER_TWS_ENABLE
if ((-1 == value_old) || (get_bt_tws_connect_status() && (count_the_num_of_positions(get_adv_anc_event_status()) > 1))) {
#else
if (-1 == value_old) {
#endif
anc_mode_switch(mode + 1, 0);
} else {
anc_mode_switch(mode + 1, 1);
}
}
#endif
value_old = value;
}
static void anc_voice_state_update(u8 *anc_setting)
{
u8 offset = 0;
u8 mode = g_anc_info[offset];
offset++;
offset += mode * 8;
s16 left_max = g_anc_info[offset] << 8 | g_anc_info[offset + 1];
s16 right_max = g_anc_info[offset + 2] << 8 | g_anc_info[offset + 3];
s16 left_val = g_anc_info[offset + 4] << 8 | g_anc_info[offset + 5];
s16 right_val = g_anc_info[offset + 6] << 8 | g_anc_info[offset + 7];
offset += 8;
#if TCFG_USER_TWS_ENABLE
if ('R' == bt_tws_get_local_channel()) {
if (check_pos_neg(mode) && right_val >= right_max) {
anc_voice_effect_set(anc_setting, mode, right_val);
} else if (right_max >= right_val) {
anc_voice_effect_set(anc_setting, mode, right_val);
}
return;
}
#endif
if (check_pos_neg(mode) && left_val >= left_max) {
anc_voice_effect_set(anc_setting, mode, left_val);
} else if (left_max >= left_val) {
anc_voice_effect_set(anc_setting, mode, left_val);
}
}
void deal_anc_voice(u8 *anc_setting, u8 write_vm, u8 tws_sync)
{
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* extern void tws_api_role_switch(); */
/* tws_api_role_switch(); */
/* return; */
u8 anc_info[25] = {0};
if (!anc_setting) {
get_anc_voice_info(anc_info);
} else {
u8 mode = anc_setting[0];
g_anc_info[0] = mode;
memcpy(g_anc_info + 1 + mode * 8, anc_setting + 1, 8);
memcpy(anc_info, g_anc_info, sizeof(anc_info));
}
if (write_vm) {
update_anc_voice_vm_value(anc_info);
}
if (tws_sync) {
anc_voice_sync(anc_info);
}
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
if (TWS_ROLE_MASTER == tws_api_get_role()) {
anc_voice_state_update(anc_info);
} else if (0 == tws_sync) {
anc_voice_state_update(anc_info);
}
} else
#endif
{
anc_voice_state_update(anc_info);
}
// 更新状态
enable_adv_anc_event();
}
#if TCFG_USER_TWS_ENABLE
#define TWS_FUNC_ID_ANC_VOICE_SYNC \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'N' + 'C' + 'S') << (2 * 8)) | \
((u8)('V' + 'O' + 'I' + 'C' + 'E') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
void anc_voice_max_val_swap_sync(u8 *data, u16 len)
{
update_anc_voice_vm_value(g_anc_info);
}
static void anc_voice_state_sync(u8 *data, u16 len)
{
if (NULL == data || 0 == len) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
return;
}
u8 offset = 9;
// 假如当前是右耳,应该填写左值
// 假如当前是左耳,应该填写右值
if ('L' == bt_tws_get_local_channel()) {
offset += 2;
}
// 根据左右耳填充对应的最大值信息
// 降噪(2byte) + 通透(2byte)
memcpy(g_anc_info + offset, data, 2);
memcpy(g_anc_info + offset + 4, data + 4, 2);
offset += 8;
memcpy(g_anc_info + offset, data + 2, 2);
memcpy(g_anc_info + offset + 4, data + 6, 2);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE_MAX_SYNC, NULL, 0);
}
static void adv_anc_voice_tws_func_t(void *data, u16 len, bool rx)
{
if (rx) {
anc_voice_state_sync((u8 *)data, len);
}
}
REGISTER_TWS_FUNC_STUB(adv_tws_sync) = {
.func_id = TWS_FUNC_ID_ANC_VOICE_SYNC,
.func = adv_anc_voice_tws_func_t,
};
#endif
void rcsp_adv_voice_mode_update(u8 mode)
{
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
anc_info[0] = mode;
if (mode) {
memcpy(anc_info + 1, anc_info + 1 + mode * 8, 8);
}
deal_anc_voice(anc_info, 1, 0);
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status() && TWS_ROLE_SLAVE == tws_api_get_role()) {
tws_api_send_data_to_sibling(NULL, 0, TWS_FUNC_ID_ANC_VOICE_SYNC);
return;
}
#endif
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
}
// ==================================================
#define AUDIO_ANC_MODE_OFF 1
#define AUDIO_ANC_MODE_ON 2
#define AUDIO_ANC_MODE_TRANSPARENCY 3
static const u8 g_audio_anc_mode[] = {
AUDIO_ANC_MODE_OFF,
AUDIO_ANC_MODE_ON,
AUDIO_ANC_MODE_TRANSPARENCY
};
// ==================================================
// mode - 模式,0 - 关闭模式,1 - 降噪模式,2 - 通透模式
// type - 类型,0 - 左耳,1 - 右耳
// buf - 获取对应值的buffer
// 返回值:返回数据,0是失败
u16 rcsp_adv_anc_voice_value_get(u8 mode)
{
u8 cur_app_mode;
for (cur_app_mode = 0; cur_app_mode < sizeof(g_audio_anc_mode); cur_app_mode++) {
if (mode == g_audio_anc_mode[cur_app_mode]) {
break;
}
}
u8 anc_vm_info[24] = {0};
if (sizeof(anc_vm_info) != syscfg_read(CFG_RCSP_ADV_ANC_VOICE, anc_vm_info, sizeof(anc_vm_info))) {
return 16384;
}
/* u8 *anc_ptr = anc_vm_info + cur_app_mode * 8 + 4; */
u8 *anc_ptr = anc_vm_info + cur_app_mode * 8;
u8 type = 0;
#if TCFG_USER_TWS_ENABLE
type = ('R' == bt_tws_get_local_channel()) ? 1 : 0;
#endif/*TCFG_USER_TWS_ENABLE*/
switch (type) {
case 1:
// 右耳
anc_ptr += 2;
case 0:
// 左耳
break;
default:
return 16384;
}
return (anc_ptr[0] << 8 | anc_ptr[1]);
}
int anc_voice_setting_sync()
{
int ret = 0;
u8 anc_info[8] = {0};
#if (TCFG_AUDIO_ANC_ENABLE)
#ifdef CONFIG_CPU_BR30
u16 noise_reduction = (u16)audio_anc_fade_gain_get(); // 调用接口获取降噪最大值
u16 transparent = (u16)audio_anc_fade_gain_get(); // 调用接口获取通透最大值
#else
u16 noise_reduction = 16384;
u16 transparent = 16384;
#endif
#else
u16 noise_reduction = 0;
u16 transparent = 0;
#endif
anc_info[0] = ((u8 *)&noise_reduction)[1];
anc_info[1] = ((u8 *)&noise_reduction)[0];
anc_info[2] = ((u8 *)&transparent)[1];
anc_info[3] = ((u8 *)&transparent)[0];
u8 offset = 9;
#if TCFG_USER_TWS_ENABLE
if ('R' == bt_tws_get_local_channel()) {
offset += 2;
}
#endif
// 初始值最大和当前值都是同一个值
// 默认是左值
u8 tmp_value = -1;
int result = 0;
if ((result = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, &tmp_value, sizeof(tmp_value))) != sizeof(tmp_value)) {
tmp_value = offset;
memcpy(g_anc_info + tmp_value, anc_info, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info + 2, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info + 2, 2);
}
#if TCFG_USER_TWS_ENABLE
// 填写当前降噪/通透当前值
memcpy(anc_info + 4, g_anc_info + offset + 4, 2);
memcpy(anc_info + 6, g_anc_info + offset + 8 + 4, 2);
// 把自己的最大值发送给对端
if (get_bt_tws_connect_status()) {
tws_api_send_data_to_sibling(anc_info, sizeof(anc_info), TWS_FUNC_ID_ANC_VOICE_SYNC);
}
#endif
return ret;
}
int anc_voice_setting_init(void)
{
int ret = 1;
u8 anc_mode = -1;
if (syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, &anc_mode, sizeof(anc_mode)) != sizeof(anc_mode)) {
anc_voice_setting_sync();
ret = 0;
} else {
u8 anc_voice_setting[25] = {0};
if (rcsp_read_data_from_vm(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_voice_setting, 1)) {
if (rcsp_read_data_from_vm(CFG_RCSP_ADV_ANC_VOICE, anc_voice_setting + 1, sizeof(anc_voice_setting) - 1)) {
set_anc_voice_info(anc_voice_setting);
deal_anc_voice(NULL, 0, 0);
}
}
ret = 0;
}
return ret;
}
// ====================================================
enum {
anc_VOICE_GET_PREP_MSG,
anc_VOICE_SET_CUR_MODE,
anc_VOICE_NOTICE_MSG,
anc_VOICE_GET_CUR_MODE,
};
static void s16_pos_neg_conversion(u8 *data)
{
s16 tmp_val = data[0] << 8 | data[1];
tmp_val = -tmp_val;
data[1] = ((u8 *)&tmp_val)[0];
data[0] = ((u8 *)&tmp_val)[1];
}
u8 anc_voice_info_get(u8 *data, u16 len)
{
u8 offset = 0;
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
u8 mode = anc_info[0];
data[offset++] = mode;
memcpy(data + offset, anc_info + 1 + mode * 8, 8);
if (check_pos_neg(mode)) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 1 + i);
}
}
offset += 8;
return offset;
}
u8 anc_voice_info_fetch_all_get(u8 *data, u16 len)
{
u8 mode = 0;
u8 offset = 1;
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
for (u8 resp_offset = 1; offset < sizeof(anc_info); offset += 8) {
data[resp_offset++] = mode;
memcpy(data + resp_offset, anc_info + offset, 8);
if (check_pos_neg(mode)) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 2 + mode * 9 + i);
}
}
resp_offset += 8;
mode++;
}
data[0] = mode;
return len;
}
int anc_voice_info_set(u8 *data, u16 len)
{
int ret = 0;
if (check_pos_neg(data[0])) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 1 + i);
}
}
deal_anc_voice(data, 1, 1);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
return ret;
}
static RCSP_SETTING_OPT anc_voice_opt = {
.data_len = 25,
.setting_type = ATTR_TYPE_ANC_VOICE,
.syscfg_id = CFG_RCSP_ADV_ANC_VOICE,
.deal_opt_setting = deal_anc_voice,
.set_setting = set_anc_voice_info,
.get_setting = get_anc_voice_info,
.custom_setting_init = anc_voice_setting_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = NULL,
.get_setting_extra_handle = NULL,
};
REGISTER_APP_SETTING_OPT(anc_voice_opt);
#elif (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP && RCSP_MODE
#include "smartbox_info_manager.h"
/*note: 目前 anc信息 只用到mode */
// anc信息:mode(1byte/0/1/2) + ( left_max(2byte) + right_max(2byte) + left_cur_val(2byte) + right_cur_val(2byte) ) * 3
static u8 g_anc_info[25] = {0};
int get_anc_voice_info(u8 *anc_info)
{
memcpy(anc_info, g_anc_info, sizeof(g_anc_info));
return 0;
}
static void s16_pos_neg_conversion(u8 *data)
{
s16 tmp_val = data[0] << 8 | data[1];
tmp_val = -tmp_val;
data[1] = ((u8 *)&tmp_val)[0];
data[0] = ((u8 *)&tmp_val)[1];
}
static bool check_pos_neg(u8 mode)
{
bool ret = false;
u8 offset = 1 + mode * 8;
#if TCFG_USER_TWS_ENABLE
if ('R' == bt_tws_get_local_channel()) {
offset += 2;
}
#endif
s16 val = g_anc_info[offset] << 8 | g_anc_info[offset + 1];
if (val < 0) {
ret = true;
}
return ret;
}
static void update_anc_voice_vm_value(u8 *anc_info)
{
u8 anc_vm_info[25] = {-1};
int ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_vm_info, 1);
if ((0 != memcmp(anc_vm_info, anc_info, 1)) && (ret == 1)) {
syscfg_write(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_info, 1);
}
ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE, anc_vm_info + 1, sizeof(anc_vm_info) - 1);
if ((0 != memcmp(anc_vm_info + 1, anc_info + 1, sizeof(anc_vm_info) - 1)) && (ret == (sizeof(anc_vm_info) - 1))) {
syscfg_write(CFG_RCSP_ADV_ANC_VOICE, anc_info + 1, sizeof(anc_vm_info) - 1);
}
}
u8 anc_voice_info_get(u8 *data, u16 len)
{
u8 offset = 0;
u8 mode = g_anc_info[0];
if ((!data) || (len < 9)) {
log_error("%s param error", __func__);
}
data[offset++] = mode;
memcpy(data + offset, g_anc_info + 1 + mode * 8, 8);
// if (check_pos_neg(mode)) {
// for (u8 i = 0; i < 8; i += 2) {
// s16_pos_neg_conversion(data + 1 + i);
// }
// }
offset += 8;
return offset;
}
void deal_anc_voice(u8 *anc_setting, u8 write_vm, u8 tws_sync)
{
u8 anc_info[25] = {0};
if (!anc_setting) {
get_anc_voice_info(anc_info);
} else {
u8 mode = anc_setting[0];
g_anc_info[0] = mode;
memcpy(g_anc_info + 1 + mode * 8, anc_setting + 1, 8);
memcpy(anc_info, g_anc_info, sizeof(anc_info));
}
log_info("%s %d %d anc_mode:%d", __func__, write_vm, tws_sync, anc_info[0]);
if (write_vm) {
update_anc_voice_vm_value(anc_info);
}
/*rcsp协议 和 仓与耳机ble协议 模式值定义不一样,这里加1保持一致*/
u8 send_anc_mode = g_anc_info[0] + 1;
sbox_anc_mode_set(send_anc_mode);
if (tws_sync) {
custom_client_send_anc_mode(send_anc_mode);
}
}
u8 anc_voice_info_fetch_all_get(u8 *data, u16 len)
{
u8 mode = 0;
u8 offset = 1;
for (u8 resp_offset = 1; offset < sizeof(g_anc_info); offset += 8) {
data[resp_offset++] = mode;
memcpy(data + resp_offset, g_anc_info + offset, 8);
if (check_pos_neg(mode)) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 2 + mode * 9 + i);
}
}
resp_offset += 8;
mode++;
}
data[0] = mode;
return len;
}
int anc_voice_info_set(u8 *data, u16 len)
{
int ret = 0;
if (check_pos_neg(data[0])) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 1 + i);
}
}
deal_anc_voice(data, 1, 1);
//anc设置完,得再通知app
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
return ret;
}
//anc配置 写入vm和通知app
void anc_ui_set_mode_rcsp_vm(u8 mode)
{
u8 anc_info[25] = {0};
anc_info[0] = (mode - 1);
deal_anc_voice(anc_info, 1, 0);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
}
int anc_voice_setting_init(void)
{
int ret = 0;
u8 anc_mode = -1;
ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, &anc_mode, sizeof(anc_mode));
if (ret != sizeof(anc_mode)) {
anc_mode = 0;
syscfg_write(CFG_RCSP_ADV_ANC_VOICE_MODE, &anc_mode, sizeof(anc_mode));
}
log_info("%s anc_mode:%d", __func__, anc_mode);
g_anc_info[0] = anc_mode;
sbox_anc_mode_set(anc_mode + 1);
return 0;
}
static RCSP_SETTING_OPT anc_voice_opt = {
.data_len = 25,
.setting_type = ATTR_TYPE_ANC_VOICE,
.syscfg_id = CFG_RCSP_ADV_ANC_VOICE,
.deal_opt_setting = NULL,
.set_setting = NULL,
.get_setting = get_anc_voice_info,
.custom_setting_init = anc_voice_setting_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = NULL,
.get_setting_extra_handle = NULL,
};
REGISTER_APP_SETTING_OPT(anc_voice_opt);
#else
void anc_ui_set_mode_rcsp_vm(u8 mode)
{
printf("%s is NULL error!!!", __func__);
}
#endif
@@ -0,0 +1,26 @@
#ifndef __ADV_ANS_VOICE_H__
#define __ADV_ANS_VOICE_H__
#define ANC_VOICE_TYPE_MAX 3
int anc_voice_setting_init(void);
int anc_voice_setting_sync(void);
// void deal_anc_voice(u8 *anc_setting, u8 write_vm, u8 tws_sync);
void set_anc_voice_info(u8 *anc_info);
int get_anc_voice_info(u8 *anc_info);
u8 anc_voice_info_get(u8 *data, u16 len);
u8 anc_voice_info_fetch_all_get(u8 *data, u16 len);
int anc_voice_info_set(u8 *data, u16 len);
int update_anc_voice_key_opt(void);
void rcsp_adv_voice_mode_update(u8 mode);
void anc_ui_set_mode_rcsp_vm(u8 mode);
// mode - 模式,0 - 关闭模式,1 - 降噪模式,2 - 通透模式
// // type - 类型,0 - 左耳,1 - 右耳
// // buf - 获取对应值的buffer
// // 返回值:返回数据,0是失败
u16 rcsp_adv_anc_voice_value_get(u8 mode);
#endif
@@ -0,0 +1,239 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_anc_voice_key.data.bss")
#pragma data_seg(".adv_anc_voice_key.data")
#pragma const_seg(".adv_anc_voice_key.text.const")
#pragma code_seg(".adv_anc_voice_key.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "adv_anc_voice_key.h"
#include "adv_anc_voice.h"
#include "rcsp_setting_opt.h"
#if (RCSP_ADV_EN)
/* #if (RCSP_ADV_KEY_SET_ENABLE && TCFG_AUDIO_ANC_ENABLE) */
#if (RCSP_ADV_KEY_SET_ENABLE)
#include "audio_anc.h"
static u8 g_anc_voice_key_mode[4] = {0, 0, 0, BIT(ANC_VOICE_TYPE_MAX) - 1};
extern int get_bt_tws_connect_status();
static void set_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(g_anc_voice_key_mode, anc_voice_mode, sizeof(g_anc_voice_key_mode));
}
static int get_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(anc_voice_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
return 0;
}
static void update_anc_voice_key_vm_value(u8 *anc_voice_mode)
{
syscfg_write(CFG_RCSP_ADV_ANC_VOICE_KEY, anc_voice_mode, 4);
}
static void anc_voice_key_sync(u8 *key_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_ANC_VOICE_KEY);
}
#endif
}
static void deal_anc_voice_key_setting(u8 *anc_key_setting, u8 write_vm, u8 tws_sync)
{
u8 anc_voice_key_mode[4] = {0};
if (!anc_key_setting) {
get_anc_voice_key_mode(anc_voice_key_mode);
} else {
set_anc_voice_key_mode(anc_key_setting);
memcpy(anc_voice_key_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
}
if (write_vm) {
update_anc_voice_key_vm_value(anc_voice_key_mode);
}
if (tws_sync) {
anc_voice_key_sync(anc_voice_key_mode);
}
}
int update_anc_voice_key_opt(void)
{
int ret = 0;
#if (RCSP_ADV_ANC_VOICE)
u32 mask = g_anc_voice_key_mode[0] << 24 | g_anc_voice_key_mode[1] << 16 | g_anc_voice_key_mode[2] << 8 | g_anc_voice_key_mode[3];
// 获取当前处于什么模式
#if TCFG_AUDIO_ANC_ENABLE
u8 cur_mode = anc_mode_get();
#else
u8 cur_mode = ANC_OFF;
#endif
u8 next_mode = cur_mode % ANC_VOICE_TYPE_MAX;
for (; next_mode < ANC_VOICE_TYPE_MAX; next_mode++) {
if (mask & BIT(next_mode)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
return ret;
}
}
if (mask & BIT(next_mode % ANC_VOICE_TYPE_MAX)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
}
#endif
return ret;
}
static int anc_voice_key_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
//u8 dlen = *((u8 *)setting_data_len);
u8 *key_setting_data = (u8 *)setting_data;
set_anc_voice_key_mode(key_setting_data);
return 0;
}
static int anc_voice_key_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)g_anc_voice_key_mode;
return sizeof(g_anc_voice_key_mode);
}
static RCSP_SETTING_OPT adv_anc_voice_key_opt = {
.data_len = 4,
.setting_type = ATTR_TYPE_ANC_VOICE_KEY,
.syscfg_id = CFG_RCSP_ADV_ANC_VOICE_KEY,
.deal_opt_setting = deal_anc_voice_key_setting,
.set_setting = set_anc_voice_key_mode,
.get_setting = get_anc_voice_key_mode,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = anc_voice_key_set_setting_extra_handle,
.get_setting_extra_handle = anc_voice_key_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_anc_voice_key_opt);
#endif
#elif (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP
#if (RCSP_ADV_KEY_SET_ENABLE)
#include "audio_anc.h"
static u8 g_anc_voice_key_mode[4] = {0, 0, 0, BIT(ANC_VOICE_TYPE_MAX) - 1};
extern int get_bt_tws_connect_status();
static void set_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(g_anc_voice_key_mode, anc_voice_mode, sizeof(g_anc_voice_key_mode));
}
static int get_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(anc_voice_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
return 0;
}
static void update_anc_voice_key_vm_value(u8 *anc_voice_mode)
{
syscfg_write(CFG_RCSP_ADV_ANC_VOICE_KEY, anc_voice_mode, 4);
}
static void anc_voice_key_sync(u8 *key_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_ANC_VOICE_KEY);
}
#endif
}
static void deal_anc_voice_key_setting(u8 *anc_key_setting, u8 write_vm, u8 tws_sync)
{
u8 anc_voice_key_mode[4] = {0};
if (!anc_key_setting) {
get_anc_voice_key_mode(anc_voice_key_mode);
} else {
set_anc_voice_key_mode(anc_key_setting);
memcpy(anc_voice_key_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
}
if (write_vm) {
update_anc_voice_key_vm_value(anc_voice_key_mode);
}
if (tws_sync) {
anc_voice_key_sync(anc_voice_key_mode);
}
}
int update_anc_voice_key_opt(void)
{
int ret = 0;
#if (RCSP_ADV_ANC_VOICE)
u32 mask = g_anc_voice_key_mode[0] << 24 | g_anc_voice_key_mode[1] << 16 | g_anc_voice_key_mode[2] << 8 | g_anc_voice_key_mode[3];
// 获取当前处于什么模式
#if TCFG_AUDIO_ANC_ENABLE
u8 cur_mode = anc_mode_get();
#else
u8 cur_mode = ANC_OFF;
#endif
u8 next_mode = cur_mode % ANC_VOICE_TYPE_MAX;
for (; next_mode < ANC_VOICE_TYPE_MAX; next_mode++) {
if (mask & BIT(next_mode)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
return ret;
}
}
if (mask & BIT(next_mode % ANC_VOICE_TYPE_MAX)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
}
#endif
return ret;
}
static int anc_voice_key_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
//u8 dlen = *((u8 *)setting_data_len);
u8 *key_setting_data = (u8 *)setting_data;
set_anc_voice_key_mode(key_setting_data);
return 0;
}
static int anc_voice_key_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)g_anc_voice_key_mode;
return sizeof(g_anc_voice_key_mode);
}
static RCSP_SETTING_OPT adv_anc_voice_key_opt = {
.data_len = 4,
.setting_type = ATTR_TYPE_ANC_VOICE_KEY,
.syscfg_id = CFG_RCSP_ADV_ANC_VOICE_KEY,
.deal_opt_setting = deal_anc_voice_key_setting,
.set_setting = set_anc_voice_key_mode,
.get_setting = get_anc_voice_key_mode,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = anc_voice_key_set_setting_extra_handle,
.get_setting_extra_handle = anc_voice_key_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_anc_voice_key_opt);
#endif
#endif
@@ -0,0 +1,11 @@
#ifndef __ADV_ANC_VOICE_KEY_H__
#define __ADV_ANC_VOICE_KEY_H__
// void deal_anc_voice_key_setting(u8 *anc_key_setting, u8 write_vm, u8 tws_sync);
// void get_anc_voice_key_mode(u8 *anc_voice_mode);
// void set_anc_voice_key_mode(u8 *anc_voice_mode);
int update_anc_voice_key_opt(void);
#endif
@@ -0,0 +1,119 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_bt_name_setting.data.bss")
#pragma data_seg(".adv_bt_name_setting.data")
#pragma const_seg(".adv_bt_name_setting.text.const")
#pragma code_seg(".adv_bt_name_setting.text")
#endif
#include "app_config.h"
#include "user_cfg.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_opt.h"
#if (RCSP_MODE && RCSP_ADV_EN && RCSP_ADV_NAME_SET_ENABLE)
static u8 g_edr_name[32] = {0};
extern int get_bt_tws_connect_status();
void adv_edr_name_change_now(void)
{
extern BT_CONFIG bt_cfg;
extern const char *bt_get_local_name();
extern void lmp_hci_write_local_name(const char *name);
memcpy(bt_cfg.edr_name, g_edr_name, LOCAL_NAME_LEN);
lmp_hci_write_local_name(bt_get_local_name());
}
static void set_bt_name_setting(u8 *bt_name_setting)
{
memcpy(g_edr_name, bt_name_setting, 32);
}
static int get_bt_name_setting(u8 *bt_name_setting)
{
memcpy(bt_name_setting, g_edr_name, 32);
return 0;
}
// 1、写入VM
static void update_bt_name_vm_value(u8 *bt_name_setting)
{
syscfg_write(CFG_BT_NAME, bt_name_setting, 32);
}
// 2、同步对端
static void bt_name_sync(u8 *bt_name_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_EDR_NAME);
}
#endif
}
static void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync)
{
if (!bt_name_setting) {
get_bt_name_setting(g_edr_name);
} else {
memcpy(g_edr_name, bt_name_setting, 32);
}
if (write_vm) {
update_bt_name_vm_value(g_edr_name);
}
if (tws_sync) {
bt_name_sync(g_edr_name);
}
}
static int bt_name_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int ret = 0;
u8 dlen = *((u8 *)setting_data_len);
u8 *bt_name_setting_data = (u8 *) setting_data;
u8 bt_name[32] = {0};
if (dlen > 20) {
ret = 2;
} else {
memcpy(bt_name, bt_name_setting_data, dlen);
bt_name[dlen] = '\0';
memcpy(g_edr_name, bt_name, sizeof(bt_name));
}
return ret;
}
static int bt_name_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)g_edr_name;
return strlen((const char *)g_edr_name);
}
static RCSP_SETTING_OPT adv_bt_name_opt = {
.data_len = 32,
.setting_type = ATTR_TYPE_EDR_NAME,
.syscfg_id = CFG_BT_NAME,
.deal_opt_setting = deal_bt_name_setting,
.set_setting = set_bt_name_setting,
.get_setting = get_bt_name_setting,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = bt_name_set_setting_extra_handle,
.get_setting_extra_handle = bt_name_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_bt_name_opt);
#else
void adv_edr_name_change_now(void)
{
}
#endif
@@ -0,0 +1,323 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_hearing_aid_setting.data.bss")
#pragma data_seg(".adv_hearing_aid_setting.data")
#pragma const_seg(".adv_hearing_aid_setting.text.const")
#pragma code_seg(".adv_hearing_aid_setting.text")
#endif
#include "adv_hearing_aid_setting.h"
#include "spp_user.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#if (RCSP_ADV_EN && RCSP_ADV_ASSISTED_HEARING)
static u8 g_dha_fitting_data[3 + 2 * 4 * DHA_FITTING_CHANNEL_MAX] = {0};
static u8 g_dha_fitting_info[3 + 2 + 2 * DHA_FITTING_CHANNEL_MAX + 1] = {0};
static bool g_aidIsOperating = false;
static u8 g_aidOpCode = -1;
static u8 g_aidOpCode_SN = -1;
extern int get_bt_tws_connect_status();
extern int tws_api_get_role(void);
extern u8 deal_adv_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type);
extern u16 get_adv_sync_tws_len(void);
extern void set_hearing_aid_operating_flag();
static u16 adv_hearing_aid_convert(u8 *data);
static void hearing_aid_update_handle(u8 *data, u16 data_len)
{
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
hearing_aid_fitting_parse(g_dha_fitting_data, data_len);
#endif /*TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE*/
}
static void hearing_aid_update(void)
{
// 跟进不同命令类型调用设置函数
printf("%s\n", __func__);
/* u16 data_len = get_adv_sync_tws_len(); */
/* if (sizeof(g_dha_fitting_data) == data_len) { */
/* data_len = adv_hearing_aid_convert(g_dha_fitting_data); */
/* put_buf(g_dha_fitting_data, data_len); */
/* } */
#if ASSISTED_HEARING_CUSTOM_TRASNDATA
// 从机才触发
u16 data_len = get_adv_sync_tws_len();
#else
u16 data_len = adv_hearing_aid_convert(g_dha_fitting_data);
#endif
put_buf(g_dha_fitting_data, data_len);
hearing_aid_update_handle(g_dha_fitting_data, data_len);
}
#pragma pack(1)
struct hearing_aid_playload {
u8 cmd;
u16 data_len;
dha_fitting_info_t data_info;
};
#pragma pack()
void get_dha_fitting_info(u8 *dha_fitting_info)
{
printf("%s\n", __func__);
struct hearing_aid_playload playload;
playload.cmd = DHA_FITTING_CMD_INFO;
// 如果当前是主动拿,就把所有信息返回
// 获取0x50对应的数据
/* u8 tmp_data[] = {0, DHA_FITTING_CHANNEL_MAX, 0x12, 0x21, 0x23, 0x32, 0x34, 0x43, 0x45, 0x54, 0x56, 0x65, 0x67, 0x76}; // 例子 */
/* playload.data_len = sizeof(tmp_data); */
/* memcpy(&playload.data_info, tmp_data, sizeof(tmp_data)); */
// 获取0x50对应的数据
dha_fitting_info_t dha_info;
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
playload.data_len = get_hearing_aid_fitting_info(&dha_info);
#endif /*TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE*/
memcpy(&playload.data_info, &dha_info, sizeof(dha_info));
memcpy(g_dha_fitting_info, &playload, sizeof(playload));
// 如果当前是从机通知,就直接memcpy过去,不需要填充前三个头
u16 data_len = adv_hearing_aid_convert(g_dha_fitting_info);
put_buf(g_dha_fitting_info, data_len);
memcpy(dha_fitting_info, g_dha_fitting_info, sizeof(g_dha_fitting_info) - 1);
}
static void hearing_aid_sync(void)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
/* update_adv_setting(BIT(ATTR_TYPE_ASSISTED_HEARING)); */
update_rcsp_setting(ATTR_TYPE_ASSISTED_HEARING);
}
#endif
}
static void big_to_little(u8 *data, u8 data_len)
{
u8 tmp_data = 0;
for (u8 i = 0; i < (data_len / 2); i++) {
tmp_data = data[i];
data[i] = data[data_len - i - 1];
data[data_len - i - 1] = tmp_data;
}
}
static u16 adv_hearing_aid_convert(u8 *data)
{
u16 offset = 0;
u16 data_len = 0;
u8 cmd = data[offset++];
dha_fitting_adjust_t *dha_data; // 0x51
dha_fitting_info_t *dha_info; // 0x50
switch (cmd) {
case DHA_FITTING_CMD_INFO:
big_to_little(data + offset, 2);
data_len = data[offset++] << 8 | data[offset++];
dha_info = (dha_fitting_adjust_t *)(data + offset);
offset += 2;
for (; offset < data_len + 3; offset += 2) {
big_to_little(data + offset, 2);
}
break;
case DHA_FITTING_CMD_ADJUST:
data_len = data[offset] << 8 | data[offset + 1];
big_to_little(data + offset, 2);
offset += 2;
dha_data = (dha_fitting_adjust_t *)(data + offset);
offset += 2;
big_to_little((u8 *)&dha_data->freq, sizeof(dha_data->freq));
offset += 2;
big_to_little((u8 *)&dha_data->gain, sizeof(dha_data->gain));
offset += 4;
break;
case DHA_FITTING_CMD_UPDATE:
data_len = data[offset] << 8 | data[offset + 1];
big_to_little(data + offset, 2);
offset += 3;
for (; offset < data_len + 3; offset += 4) {
big_to_little(g_dha_fitting_data + offset, 4);
}
break;
case DHA_FITTING_CMD_STATE:
big_to_little(data + offset, 2);
data_len = data[offset++] << 8 | data[offset++];
offset += 1;
break;
}
if (data_len + 3 == offset) {
return offset;
}
return 0;
}
void set_hearing_aid_setting(u8 *hear_aid_setting)
{
memcpy(g_dha_fitting_data, hear_aid_setting, sizeof(g_dha_fitting_data));
}
void get_hearing_aid_setting(u8 *hear_aid_setting)
{
memcpy(hear_aid_setting, g_dha_fitting_data, sizeof(g_dha_fitting_data));
}
u32 hearing_aid_rcsp_notify(u8 *data, u16 data_len)
{
u32 ret = 0;
u8 *buf = NULL;
if (0 == adv_hearing_aid_convert(data)) {
return -1;
}
buf = zalloc(data_len + 3);
if (NULL == buf) {
return -1;
}
buf[0] = 0xFF;
data_len = add_one_attr(buf + 1, data_len + 2, 0, RCSP_DEVICE_STATUS_ATTR_TYPE_ASSISTED_HEARING, data, data_len);
ret = JL_CMD_send(JL_OPCODE_SYS_INFO_AUTO_UPDATE, buf, data_len + 1, JL_NOT_NEED_RESPOND, 0, NULL);
if (buf) {
free(buf);
}
return ret;
}
u32 hearing_aid_rcsp_response(u8 *data, u16 data_len)
{
/*不开辅听功能时,不回复app信息*/
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
if (get_hearing_aid_state() == 0)
#endif /*(TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)*/
{
return 0;
}
if ((TWS_ROLE_MASTER == tws_api_get_role()) && (g_aidOpCode >= 0) && (g_aidOpCode_SN >= 0)) {
u32 ret = 0;
ret = JL_CMD_response_send(g_aidOpCode, JL_PRO_STATUS_SUCCESS, g_aidOpCode_SN, data, data_len, 0, NULL);
g_aidIsOperating = false;
g_aidOpCode = -1;
g_aidOpCode_SN = -1;
return ret;
} else {
return -1;
}
}
void deal_hearing_aid_setting(u8 opCode, u8 opCode_SN, u8 *hear_aid_setting, u8 write_en, u8 type_sync)
{
if (TWS_ROLE_MASTER == tws_api_get_role()) {
set_hearing_aid_operating_flag();
}
if (g_aidIsOperating) {
return;
}
if (TWS_ROLE_MASTER == tws_api_get_role()) {
g_aidIsOperating = true;
g_aidOpCode = opCode;
g_aidOpCode_SN = opCode_SN;
}
if (hear_aid_setting) {
u16 len = hear_aid_setting[1] << 8 | hear_aid_setting[2];
memcpy(g_dha_fitting_data, hear_aid_setting, len + 2);
}
if (type_sync) {
hearing_aid_sync();
}
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
if (TWS_ROLE_MASTER == tws_api_get_role()) {
hearing_aid_update();
} else if (0 == type_sync) {
hearing_aid_update();
}
} else
#endif
{
hearing_aid_update();
}
}
#if ASSISTED_HEARING_CUSTOM_TRASNDATA
static struct spp_operation_t *spp_opt = NULL;
static void app_third_party_spp_rx_cbk(void *priv, u8 *buf, u16 len)
{
app_third_party_hearing_aid_handle(buf, len);
}
void adv_hearing_aid_init(void)
{
spp_get_operation_table(&spp_opt);
if (spp_opt && spp_opt->regist_recieve_cbk) {
spp_opt->regist_recieve_cbk(NULL, app_third_party_spp_rx_cbk);
}
}
int app_third_party_hearing_aid_handle(u8 *data, u16 len)
{
#if TCFG_USER_TWS_ENABLE
u8 *tmp_buf = NULL;
u16 offset = 1;
if (len < sizeof(g_dha_fitting_data)) {
return -1;
}
tmp_buf = zalloc(1 + 1 + len);
if (NULL == tmp_buf) {
return -1;
}
offset += deal_adv_setting_string_item(tmp_buf + offset, data, len, ATTR_TYPE_ASSISTED_HEARING);
tmp_buf[0] = offset;
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_send_data_to_sibling(tmp_buf, offset, TWS_FUNC_ID_ADV_SETTING_SYNC);
}
if (tmp_buf) {
free(tmp_buf);
}
#endif
// 处理函数
hearing_aid_update_handle(data, len);
return 0;
}
extern int custom_app_send_user_data(u8 *data, u16 len);
int app_third_party_hearing_aid_resp(u8 *data, u16 len)
{
if (custom_app_send_user_data(data, len)) {
if (spp_opt && spp_opt->send_data) {
return spp_opt->send_data(NULL, data, (u32)len);
}
}
return 0;
}
#else
int app_third_party_hearing_aid_handle(u8 *data, u16 len)
{
return 0;
}
int app_third_party_hearing_aid_resp(u8 *data, u16 len)
{
return 0;
}
void adv_hearing_aid_init(void)
{
}
#endif
#endif
@@ -0,0 +1,31 @@
#ifndef __ADV_HEARING_AID_SETTING_H__
#define __ADV_HEARING_AID_SETTING_H__
#include "app_config.h"
#if RCSP_ADV_ASSISTED_HEARING
#include "audio_hearing_aid.h"
// 是否使用三方的ble/edr数据传输
#define ASSISTED_HEARING_CUSTOM_TRASNDATA 0
void adv_hearing_aid_init(void);
void set_hearing_aid_setting(u8 *hear_aid_setting);
void get_hearing_aid_setting(u8 *hear_aid_setting);
void deal_hearing_aid_setting(u8 opCode, u8 opCode_SN, u8 *hear_aid_setting, u8 write_en, u8 type_sync);
void get_dha_fitting_info(u8 *dha_fitting_info);
// 主动推数给app
u32 hearing_aid_rcsp_notify(u8 *data, u16 data_len);
// app回复函数
u32 hearing_aid_rcsp_response(u8 *data, u16 data_len);
// 第三方调用函数
int app_third_party_hearing_aid_handle(u8 *data, u16 len);
int app_third_party_hearing_aid_resp(u8 *data, u16 len);
#endif // RCSP_ADV_ASSISTED_HEARING
#endif
@@ -0,0 +1,547 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_key_setting.data.bss")
#pragma data_seg(".adv_key_setting.data")
#pragma const_seg(".adv_key_setting.text.const")
#pragma code_seg(".adv_key_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "key_event_deal.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "adv_anc_voice_key.h"
#include "app_msg.h"
#include "key_driver.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[RCSP-KEY-SET]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_CHAR_ENABLE
#include "debug.h"
#if (RCSP_MODE && RCSP_ADV_EN)
#if RCSP_ADV_KEY_SET_ENABLE
extern int get_bt_tws_connect_status();
static u8 rcsp_adv_key_event_flag = 0x0;
#define ADV_POWER_ON_OFF 0
enum RCSP_KEY_TYPE {
RCSP_KEY_TYPE_NULL = 0x00,
#if ADV_POWER_ON_OFF
RCSP_KEY_TYPE_POWER_ON,
RCSP_KEY_TYPE_POWER_OFF,
#endif
RCSP_KEY_TYPE_PREV = 0x03,
RCSP_KEY_TYPE_NEXT,
RCSP_KEY_TYPE_PP,
RCSP_KEY_TYPE_ANSWER_CALL,
RCSP_KEY_TYPE_HANG_UP,
RCSP_KEY_TYPE_CALL_BACK,
RCSP_KEY_TYPE_INC_VOICE,
RCSP_KEY_TYPE_DESC_VOICE,
RCSP_KEY_TYPE_TAKE_PHOTO,
RCSP_KEY_TYPE_ANC_VOICE = 0xFF,
};
enum RCSP_EAR_CHANNEL {
RCSP_EAR_CHANNEL_LEFT = 0x01,
RCSP_EAR_CHANNEL_RIGHT = 0x02,
};
enum RCSP_KEY_ACTION {
RCSP_KEY_ACTION_CLICK = 0x01,
RCSP_KEY_ACTION_DOUBLE_CLICK = 0x02,
};
static u8 g_key_setting[12] = {
RCSP_EAR_CHANNEL_LEFT, RCSP_KEY_ACTION_CLICK, RCSP_KEY_TYPE_PP, \
RCSP_EAR_CHANNEL_RIGHT, RCSP_KEY_ACTION_CLICK, RCSP_KEY_TYPE_PP, \
RCSP_EAR_CHANNEL_LEFT, RCSP_KEY_ACTION_DOUBLE_CLICK, RCSP_KEY_TYPE_ANSWER_CALL, \
RCSP_EAR_CHANNEL_RIGHT, RCSP_KEY_ACTION_DOUBLE_CLICK, RCSP_KEY_TYPE_ANSWER_CALL
};
// 按键缓存
// 第一列 | 第二列 | 第三列
// 01 左耳| 01 单击| 按键功能
// 02 右耳| 02 双击| 按键功能
static void enable_adv_key_event(void)
{
rcsp_adv_key_event_flag = 1;
}
static u8 get_adv_key_event_status(void)
{
return rcsp_adv_key_event_flag;
}
static void disable_adv_key_event(void)
{
rcsp_adv_key_event_flag = 0;
}
static void set_key_setting(u8 *key_setting_info)
{
// 设置左耳短按功能
g_key_setting[3 * 0 + 2] = key_setting_info[0];
// 设置左耳长按功能
g_key_setting[3 * 2 + 2] = key_setting_info[1];
// 设置右耳短按功能
g_key_setting[3 * 1 + 2] = key_setting_info[2];
// 设置右耳长按功能
g_key_setting[3 * 3 + 2] = key_setting_info[3];
}
static int get_key_setting(u8 *key_setting_info)
{
// 获取左耳短按功能
key_setting_info[0] = g_key_setting[3 * 0 + 2];
// 获取左耳长按功能
key_setting_info[1] = g_key_setting[3 * 2 + 2];
// 获取右耳短按功能
key_setting_info[2] = g_key_setting[3 * 1 + 2];
// 获取右耳长按功能
key_setting_info[3] = g_key_setting[3 * 3 + 2];
return 0;
}
static void update_key_setting_vm_value(u8 *key_setting_info)
{
syscfg_write(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, 4);
}
static void key_setting_sync(u8 *key_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_KEY_SETTING);
}
#endif
}
static void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync)
{
u8 key_setting[4];
if (!key_setting_info) {
get_key_setting(key_setting);
} else {
memcpy(key_setting, key_setting_info, 4);
}
// 1、写入VM
if (write_vm) {
update_key_setting_vm_value(key_setting);
}
// 2、同步对端
if (tws_sync) {
key_setting_sync(key_setting);
}
// 3、更新状态
enable_adv_key_event();
}
#if TCFG_USER_TWS_ENABLE
static void rcsp_key_msg_in_task(u8 *_data, u16 len)
{
u8 *data = (u8 *)_data;
u8 key_opt = *data;
switch (key_opt) {
case RCSP_KEY_TYPE_ANC_VOICE:
update_anc_voice_key_opt();
break;
default:
break;
}
free(_data);
}
static void rcsp_key_tws_func_t(void *data, u16 len, bool rx)
{
if (rx) {
int msg[4];
if (!data || (len == 0)) {
ASSERT(0, "this must have key msg buf");
}
u8 *buf = malloc(len);
if (!buf) {
return;
}
memcpy(buf, data, len);
msg[0] = (int)rcsp_key_msg_in_task;
msg[1] = 2;
msg[2] = (int)buf;
msg[3] = (int)len;
os_taskq_post_type("app_core", Q_CALLBACK, sizeof(msg) / sizeof(int), msg);
}
}
#define TWS_FUNC_ID_RCSP_KEY_SYNC \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('K' + 'E' + 'Y') << (2 * 8)) | \
((u8)('M' + 'S' + 'G') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
REGISTER_TWS_FUNC_STUB(adv_key_sync) = {
.func_id = TWS_FUNC_ID_RCSP_KEY_SYNC,
.func = rcsp_key_tws_func_t,
};
#endif
static u8 get_adv_key_opt(u8 key_action, u8 channel)
{
u8 opt;
for (opt = 0; opt < sizeof(g_key_setting); opt += 3) {
if (g_key_setting[opt] == channel &&
g_key_setting[opt + 1] == key_action) {
break;
}
}
if (sizeof(g_key_setting) == opt) {
return -1;
}
switch (g_key_setting[opt + 2]) {
case RCSP_KEY_TYPE_NULL:
opt = RCSP_KEY_TYPE_NULL;
break;
#if ADV_POWER_ON_OFF
case RCSP_KEY_TYPE_POWER_ON:
opt = APP_MSG_POWER_ON;
break;
case RCSP_KEY_TYPE_POWER_OFF:
opt = APP_MSG_POWER_OFF;
break;
#endif
case RCSP_KEY_TYPE_PREV:
opt = APP_MSG_MUSIC_PREV;
break;
case RCSP_KEY_TYPE_NEXT:
opt = APP_MSG_MUSIC_NEXT;
break;
case RCSP_KEY_TYPE_PP:
opt = APP_MSG_MUSIC_PP;
break;
case RCSP_KEY_TYPE_ANSWER_CALL:
opt = APP_MSG_CALL_ANSWER;
break;
case RCSP_KEY_TYPE_HANG_UP:
opt = APP_MSG_CALL_HANGUP;
break;
case RCSP_KEY_TYPE_CALL_BACK:
opt = APP_MSG_CALL_LAST_NO;
break;
case RCSP_KEY_TYPE_INC_VOICE:
opt = APP_MSG_VOL_UP;
break;
case RCSP_KEY_TYPE_DESC_VOICE:
opt = APP_MSG_VOL_DOWN;
break;
case RCSP_KEY_TYPE_TAKE_PHOTO:
opt = APP_MSG_HID_CONTROL;
break;
case RCSP_KEY_TYPE_ANC_VOICE:
#if (RCSP_ADV_EN && RCSP_ADV_ANC_VOICE)
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status() && TWS_ROLE_SLAVE == tws_api_get_role()) {
u8 val = RCSP_KEY_TYPE_ANC_VOICE;
tws_api_send_data_to_sibling((void *)&val, 1, TWS_FUNC_ID_RCSP_KEY_SYNC);
} else {
update_anc_voice_key_opt();
}
#else
update_anc_voice_key_opt();
#endif
#endif
opt = RCSP_KEY_TYPE_NULL;
break;
}
return opt;
}
/**
* rcsp按键配置转换
*
* @param value 按键功能
* @param msg 按键消息
*
* @return 是否拦截消息
*/
int rcsp_key_event_remap(int *msg)
{
int key_action = APP_MSG_KEY_ACTION(msg[0]);
g_printf("key_remap: 0x%x, 0x%x, 0x%x, key_value:%x\n", msg[0], msg[1], APP_KEY_MSG_FROM_TWS);
switch (key_action) {
case KEY_ACTION_CLICK:
// 单击
key_action = RCSP_KEY_ACTION_CLICK;
break;
case KEY_ACTION_DOUBLE_CLICK:
// 双击
key_action = RCSP_KEY_ACTION_DOUBLE_CLICK;
break;
default:
return 0;
}
#if (TCFG_USER_TWS_ENABLE)
u8 channel = tws_api_get_local_channel();
if (get_bt_tws_connect_status()) {
channel = tws_api_get_local_channel();
}
#else
u8 channel = 'U';
#endif
switch (channel) {
case 'U':
case 'L':
channel = (msg[1] == APP_KEY_MSG_FROM_TWS) ? RCSP_EAR_CHANNEL_RIGHT : RCSP_EAR_CHANNEL_LEFT;
break;
case 'R':
channel = (msg[1] == APP_KEY_MSG_FROM_TWS) ? RCSP_EAR_CHANNEL_LEFT : RCSP_EAR_CHANNEL_RIGHT;
break;
default:
return 0;
}
int _msg = get_adv_key_opt(key_action, channel);
if (_msg == RCSP_KEY_TYPE_NULL) {
return 1;
}
if (_msg != -1) {
msg[0] = _msg;
}
return 0;
}
static int key_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *key_setting_data = (u8 *)setting_data;
while (dlen >= 3) {
if (key_setting_data[0] == RCSP_EAR_CHANNEL_LEFT) {
if (key_setting_data[1] == RCSP_KEY_ACTION_CLICK) {
g_key_setting[2] = key_setting_data[2];
} else if (key_setting_data[1] == RCSP_KEY_ACTION_DOUBLE_CLICK) {
g_key_setting[8] = key_setting_data[2];
}
} else if (key_setting_data[0] == RCSP_EAR_CHANNEL_RIGHT) {
if (key_setting_data[1] == RCSP_KEY_ACTION_CLICK) {
g_key_setting[5] = key_setting_data[2];
} else if (key_setting_data[1] == RCSP_KEY_ACTION_DOUBLE_CLICK) {
g_key_setting[11] = key_setting_data[2];
}
}
dlen -= 3;
key_setting_data += 3;
}
return 0;
}
static int key_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)g_key_setting;
return sizeof(g_key_setting);
}
static RCSP_SETTING_OPT adv_key_opt = {
.data_len = 4,
.setting_type = ATTR_TYPE_KEY_SETTING,
.syscfg_id = CFG_RCSP_ADV_KEY_SETTING,
.deal_opt_setting = deal_key_setting,
.set_setting = set_key_setting,
.get_setting = get_key_setting,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = key_set_setting_extra_handle,
.get_setting_extra_handle = key_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_key_opt);
extern int app_default_msg_handler(int *msg);
int rcsp_key_msg_handler(int *msg)
{
if (!APP_MSG_FROM_KEY(msg[0])) {
return 0;
}
if (0 == get_adv_key_event_status()) {
return 0;
}
g_printf("rcsp key msg receive:0x%x\n", msg[0]);
return rcsp_key_event_remap(msg);
}
APP_MSG_PROB_HANDLER(rcsp_key_msg_entry) = {
.owner = 0xff,
.from = MSG_FROM_APP,
.handler = rcsp_key_msg_handler,
};
#endif
#elif (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP
#if RCSP_ADV_KEY_SET_ENABLE
enum RCSP_EAR_CHANNEL {
RCSP_EAR_CHANNEL_LEFT = 0x01,
RCSP_EAR_CHANNEL_RIGHT = 0x02,
};
enum RCSP_KEY_ACTION {
RCSP_KEY_ACTION_CLICK = 0x01,
RCSP_KEY_ACTION_DOUBLE_CLICK = 0x02,
};
enum RCSP_KEY_TYPE {
RCSP_KEY_TYPE_NULL = 0x00,
#if ADV_POWER_ON_OFF
RCSP_KEY_TYPE_POWER_ON,
RCSP_KEY_TYPE_POWER_OFF,
#endif
RCSP_KEY_TYPE_PREV = 0x03,
RCSP_KEY_TYPE_NEXT,
RCSP_KEY_TYPE_PP,
RCSP_KEY_TYPE_ANSWER_CALL,
RCSP_KEY_TYPE_HANG_UP,
RCSP_KEY_TYPE_CALL_BACK,
RCSP_KEY_TYPE_INC_VOICE,
RCSP_KEY_TYPE_DESC_VOICE,
RCSP_KEY_TYPE_TAKE_PHOTO,
RCSP_KEY_TYPE_ANC_VOICE = 0xFF,
};
static u8 g_key_setting[12] = {
RCSP_EAR_CHANNEL_LEFT, RCSP_KEY_ACTION_CLICK, RCSP_KEY_TYPE_PP, \
RCSP_EAR_CHANNEL_RIGHT, RCSP_KEY_ACTION_CLICK, RCSP_KEY_TYPE_PP, \
RCSP_EAR_CHANNEL_LEFT, RCSP_KEY_ACTION_DOUBLE_CLICK, RCSP_KEY_TYPE_ANSWER_CALL, \
RCSP_EAR_CHANNEL_RIGHT, RCSP_KEY_ACTION_DOUBLE_CLICK, RCSP_KEY_TYPE_ANSWER_CALL
};
static int get_key_setting(u8 *key_setting_info)
{
// 获取左耳短按功能
key_setting_info[0] = g_key_setting[3 * 0 + 2];
// 获取左耳长按功能
key_setting_info[1] = g_key_setting[3 * 2 + 2];
// 获取右耳短按功能
key_setting_info[2] = g_key_setting[3 * 1 + 2];
// 获取右耳长按功能
key_setting_info[3] = g_key_setting[3 * 3 + 2];
return 0;
}
static void set_key_setting(u8 *key_setting_info)
{
// 设置左耳短按功能
g_key_setting[3 * 0 + 2] = key_setting_info[0];
// 设置左耳长按功能
g_key_setting[3 * 2 + 2] = key_setting_info[1];
// 设置右耳短按功能
g_key_setting[3 * 1 + 2] = key_setting_info[2];
// 设置右耳长按功能
g_key_setting[3 * 3 + 2] = key_setting_info[3];
}
static void update_key_setting_vm_value(u8 *key_setting_info)
{
syscfg_write(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, 4);
}
static void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync)
{
u8 key_setting[4];
if (!key_setting_info) {
get_key_setting(key_setting);
} else {
memcpy(key_setting, key_setting_info, 4);
}
// 1、写入VM
// if (write_vm) {
update_key_setting_vm_value(key_setting);
// }
// 2、同步对端
// if (tws_sync) {
// key_setting_sync(key_setting);
// }
// 3、更新状态
// enable_adv_key_event();
}
static int key_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *key_setting_data = (u8 *)setting_data;
if (!key_setting_data) {
log_error("%s key_setting_data is NULL", __func__);
return 0;
}
while (dlen >= 3) {
if (key_setting_data[0] == RCSP_EAR_CHANNEL_LEFT) {
if (key_setting_data[1] == RCSP_KEY_ACTION_CLICK) {
g_key_setting[2] = key_setting_data[2];
} else if (key_setting_data[1] == RCSP_KEY_ACTION_DOUBLE_CLICK) {
g_key_setting[8] = key_setting_data[2];
}
} else if (key_setting_data[0] == RCSP_EAR_CHANNEL_RIGHT) {
if (key_setting_data[1] == RCSP_KEY_ACTION_CLICK) {
g_key_setting[5] = key_setting_data[2];
} else if (key_setting_data[1] == RCSP_KEY_ACTION_DOUBLE_CLICK) {
g_key_setting[11] = key_setting_data[2];
}
}
dlen -= 3;
key_setting_data += 3;
}
deal_key_setting(NULL, 1, 0);
return 0;
}
static int key_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)g_key_setting;
return sizeof(g_key_setting);
}
static RCSP_SETTING_OPT adv_key_opt = {
.data_len = 4,
.setting_type = ATTR_TYPE_KEY_SETTING,
.syscfg_id = CFG_RCSP_ADV_KEY_SETTING,
.deal_opt_setting = deal_key_setting,
.set_setting = set_key_setting,
.get_setting = get_key_setting,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = key_set_setting_extra_handle,
.get_setting_extra_handle = key_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_key_opt);
#endif
#endif
@@ -0,0 +1,231 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_led_setting.data.bss")
#pragma data_seg(".adv_led_setting.data")
#pragma const_seg(".adv_led_setting.text.const")
#pragma code_seg(".adv_led_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#if (RCSP_MODE && RCSP_ADV_EN)
#if RCSP_ADV_LED_SET_ENABLE
#include "asm/pwm_led_hw.h"
enum ADV_LED_TYPE {
ADV_LED_TYPE_ALL_OFF = 0x0,
ADV_LED_TYPE_RED_ON,
ADV_LED_TYPE_BLUE_ON,
ADV_LED_TYPE_RAD_BREATHE,
ADV_LED_TYPE_BLUE_BREATHE,
ADV_LED_TYPE_FAST_FLASH,
ADV_LED_TYPE_SLOW_FLASH,
};
static u8 g_led_status[14] = {
0x01, 0x06, \
0x02, 0x05, \
0x03, 0x04, \
0x04, 0x00, \
0x05, 0x00, \
0x06, 0x00, \
0x07, 0x00
};
extern STATUS *get_led_config(void);
extern int get_bt_tws_connect_status();
__attribute__((weak))
u8 adv_get_led_status(void)
{
return 1;
}
static u8 adv_led_value_conversion(u8 adv_led_opt)
{
u8 conversion_value = adv_led_opt;
switch (adv_led_opt) {
case ADV_LED_TYPE_ALL_OFF:
conversion_value = PWM_LED_ALL_OFF;
break;
case ADV_LED_TYPE_RED_ON:
conversion_value = PWM_LED1_ON;
break;
case ADV_LED_TYPE_BLUE_ON:
conversion_value = PWM_LED0_ON;
break;
case ADV_LED_TYPE_RAD_BREATHE:
conversion_value = PWM_LED1_BREATHE;
break;
case ADV_LED_TYPE_BLUE_BREATHE:
conversion_value = PWM_LED0_BREATHE;
break;
case ADV_LED_TYPE_FAST_FLASH:
conversion_value = PWM_LED0_LED1_FAST_FLASH;
break;
case ADV_LED_TYPE_SLOW_FLASH:
conversion_value = PWM_LED0_LED1_SLOW_FLASH;
break;
}
return conversion_value;
}
static void set_led_setting(u8 *led_setting_info)
{
g_led_status[2 * 0 + 1] = led_setting_info[0];
g_led_status[2 * 1 + 1] = led_setting_info[1];
g_led_status[2 * 2 + 1] = led_setting_info[2];
g_led_status[2 * 3 + 1] = led_setting_info[3];
g_led_status[2 * 4 + 1] = led_setting_info[4];
g_led_status[2 * 5 + 1] = led_setting_info[5];
g_led_status[2 * 6 + 1] = led_setting_info[6];
}
static int get_led_setting(u8 *led_setting_info)
{
led_setting_info[0] = g_led_status[2 * 0 + 1];
led_setting_info[1] = g_led_status[2 * 1 + 1];
led_setting_info[2] = g_led_status[2 * 2 + 1];
led_setting_info[3] = g_led_status[2 * 3 + 1];
led_setting_info[4] = g_led_status[2 * 4 + 1];
led_setting_info[5] = g_led_status[2 * 5 + 1];
led_setting_info[6] = g_led_status[2 * 6 + 1];
return 0;
}
// 1、写入VM
static void update_led_setting_vm_value(u8 *led_setting_info)
{
syscfg_write(CFG_RCSP_ADV_LED_SETTING, led_setting_info, 7);
}
// 2、同步对端
static void led_setting_sync(u8 *led_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_LED_SETTING);
}
#endif
}
// 3、更新状态
void update_led_setting_state(void)
{
u8 led_setting_info[7];
get_led_setting(led_setting_info);
// 直接修改led表
LED_REMAP_STATUS *p_led = led_get_remap_t();
// 未配对
p_led->bt_init_ok = adv_led_value_conversion(led_setting_info[0]);
// 未连接
p_led->tws_connect_ok = adv_led_value_conversion(led_setting_info[1]);
// 连接
p_led->bt_connect_ok = adv_led_value_conversion(led_setting_info[2]);
// 断开连接
p_led->bt_disconnect = adv_led_value_conversion(led_setting_info[1]);
// 音乐模式播放音乐
p_led->music_play = adv_led_value_conversion(led_setting_info[3]);
// 音乐模式停止播放
p_led->music_pause = adv_led_value_conversion(led_setting_info[4]);
// Linein模式播放音乐
p_led->linein_play = adv_led_value_conversion(led_setting_info[5]);
// Linein模式静音
p_led->linein_mute = adv_led_value_conversion(led_setting_info[6]);
switch (adv_get_led_status()) {
case STATUS_BT_INIT_OK:
case STATUS_BT_DISCONN:
ui_update_status(STATUS_BT_INIT_OK);
break;
case STATUS_BT_TWS_CONN:
ui_update_status(STATUS_BT_TWS_CONN);
break;
case STATUS_PHONE_ACTIV:
case STATUS_PHONE_OUT:
case STATUS_PHONE_INCOME:
case STATUS_BT_CONN:
ui_update_status(STATUS_BT_CONN);
break;
case STATUS_MUSIC_MODE:
case STATUS_MUSIC_PLAY:
ui_update_status(STATUS_MUSIC_PLAY);
break;
case STATUS_MUSIC_PAUSE:
ui_update_status(STATUS_MUSIC_PAUSE);
break;
case STATUS_LINEIN_MODE:
case STATUS_LINEIN_PLAY:
ui_update_status(STATUS_LINEIN_PLAY);
break;
case STATUS_LINEIN_PAUSE:
ui_update_status(STATUS_LINEIN_PAUSE);
break;
}
}
static void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync)
{
u8 led_setting[7];
if (!led_setting_info) {
get_led_setting(led_setting);
} else {
memcpy(led_setting, led_setting_info, 7);
set_led_setting(led_setting_info);
}
if (write_vm) {
update_led_setting_vm_value(led_setting);
}
if (tws_sync) {
led_setting_sync(led_setting);
}
update_led_setting_state();
}
static int led_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *led_setting_data = (u8 *) setting_data;
while (dlen >= 2) {
if (led_setting_data[0] == 0 || led_setting_data[0] > 7) {
return -1;
} else {
g_led_status[2 * (led_setting_data[0] - 1) + 1] = led_setting_data[1];
}
dlen -= 2;
led_setting_data += 2;
}
return 0;
}
static int led_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = g_led_status;
return sizeof(g_led_status);
}
static RCSP_SETTING_OPT adv_led_opt = {
.data_len = 7,
.setting_type = ATTR_TYPE_LED_SETTING,
.syscfg_id = CFG_RCSP_ADV_LED_SETTING,
.deal_opt_setting = deal_led_setting,
.set_setting = set_led_setting,
.get_setting = get_led_setting,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = led_set_setting_extra_handle,
.get_setting_extra_handle = led_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_led_opt);
#endif
#endif
@@ -0,0 +1,189 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_mic_setting.data.bss")
#pragma data_seg(".adv_mic_setting.data")
#pragma const_seg(".adv_mic_setting.text.const")
#pragma code_seg(".adv_mic_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "adv_mic_setting.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "classic/tws_api.h"
#include "bt_tws.h"
#if (RCSP_MODE && RCSP_ADV_EN)
#if RCSP_ADV_MIC_SET_ENABLE
enum RCSP_MIC_MODE {
RCSP_MIC_MODE_AUTO = 1, // 自动切换
RCSP_MIC_MODE_LEFT = 2, // 始终左耳
RCSP_MIC_MODE_RIGHT = 3, // 始终右耳
};
static u8 g_mic_mode = RCSP_MIC_MODE_LEFT;
static void mic_setting_info_deal(u8 *mic_info_data)
{
#if TCFG_USER_TWS_ENABLE
u8 channel = tws_api_get_local_channel();
printf("%s, channel:%c\n", __FUNCTION__, channel);
if (tws_api_get_role() == TWS_ROLE_MASTER) {
printf("-----master-----\n");
} else {
printf("-----role-----\n");
}
switch (*mic_info_data) {
case RCSP_MIC_MODE_AUTO:
if (get_bt_tws_connect_status()) {
printf("-------auto--------\n");
tws_api_auto_role_switch_enable();
}
break;
case RCSP_MIC_MODE_LEFT:
if (get_bt_tws_connect_status()) {
if (channel != 'L') {
printf("-------!L--------\n");
tws_api_auto_role_switch_disable();
tws_api_role_switch();
}
}
break;
case RCSP_MIC_MODE_RIGHT:
if (get_bt_tws_connect_status()) {
if (channel != 'R') {
printf("-------!R--------\n");
tws_api_auto_role_switch_disable();
tws_api_role_switch();
}
}
break;
default:
break;
}
#endif
}
static void set_mic_setting(u8 *mic_setting_info)
{
g_mic_mode = *mic_setting_info;
}
static int get_mic_setting(u8 *mic_setting_info)
{
*mic_setting_info = g_mic_mode;
return 0;
}
static void update_mic_setting_vm_value(u8 *mic_setting_info)
{
syscfg_write(CFG_RCSP_ADV_MIC_SETTING, mic_setting_info, 1);
}
static void adv_mic_setting_sync(u8 *mic_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_MIC_SETTING);
}
#endif
}
static void deal_mic_setting(u8 *mic_setting_info, u8 write_vm, u8 tws_sync)
{
if (!mic_setting_info) {
} else {
set_mic_setting(mic_setting_info);
}
if (write_vm) {
update_mic_setting_vm_value(&g_mic_mode);
}
if (tws_sync) {
adv_mic_setting_sync(&g_mic_mode);
}
mic_setting_info_deal(&g_mic_mode);
}
#if TCFG_USER_TWS_ENABLE
//通话时,根据esco state,固定mic的位置
void rcsp_user_mic_fixed_deal()
{
u8 channel = tws_api_get_local_channel();
if (!get_bt_tws_connect_status()) {
return;
}
u8 adv_mic_setting = 0;
get_mic_setting(&adv_mic_setting);
if ((tws_api_get_role() == TWS_ROLE_MASTER)
&& (tws_api_get_tws_state() | TWS_STA_ESCO_OPEN)) {
switch (adv_mic_setting) {
case RCSP_MIC_MODE_LEFT:
if (get_bt_tws_connect_status()) {
if (channel != 'L') {
printf("mic_sw_l\n");
tws_api_role_switch();
}
}
break;
case RCSP_MIC_MODE_RIGHT:
if (get_bt_tws_connect_status()) {
if (channel != 'R') {
printf("mic_sw_r\n");
tws_api_role_switch();
}
}
break;
default:
printf("mic_sw_auto\n");
break;
}
}
}
#endif
static int mic_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *mic_setting_data = (u8 *)setting_data;
memcpy(&g_mic_mode, mic_setting_data, dlen);
printf("mic_set_setting_extra_handle mode:%d", g_mic_mode);
return 0;
}
static int mic_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
int **setting_data_ptr = (int **)setting_data;
*setting_data_ptr = (int *)&g_mic_mode;
return sizeof(g_mic_mode);
}
static RCSP_SETTING_OPT adv_mic_opt = {
.data_len = 1,
.setting_type = ATTR_TYPE_MIC_SETTING,
.syscfg_id = CFG_RCSP_ADV_MIC_SETTING,
.deal_opt_setting = deal_mic_setting,
.set_setting = set_mic_setting,
.get_setting = get_mic_setting,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = mic_set_setting_extra_handle,
.get_setting_extra_handle = mic_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_mic_opt);
#endif
#endif
@@ -0,0 +1,6 @@
#ifndef __ADV_MIC_SETTING_H__
#define __ADV_MIC_SETTING_H__
void rcsp_user_mic_fixed_deal();
#endif
@@ -0,0 +1,42 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_scene_noise_reduction.data.bss")
#pragma data_seg(".adv_scene_noise_reduction.data")
#pragma const_seg(".adv_scene_noise_reduction.text.const")
#pragma code_seg(".adv_scene_noise_reduction.text")
#endif
#include "adv_scene_noise_reduction.h"
#include "app_config.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_ANC_VOICE && RCSP_ADV_SCENE_NOISE_REDUCTION)
/**
* @brief 获取场景降噪类型
*
* @result RCSP_SCENE_NOISE_REDUCTION_TYPE
*/
RCSP_SCENE_NOISE_REDUCTION_TYPE get_scene_noise_reduction_type()
{
printf("===%s===", __FUNCTION__);
return RCSP_SCENE_NOISE_REDUCTION_TYPE_INTELLIGENT;
}
/**
* @brief 设置场景降噪类型
*/
void set_scene_noise_reduction_type(RCSP_SCENE_NOISE_REDUCTION_TYPE type)
{
switch (type) {
case RCSP_SCENE_NOISE_REDUCTION_TYPE_INTELLIGENT:
case RCSP_SCENE_NOISE_REDUCTION_TYPE_MILD:
case RCSP_SCENE_NOISE_REDUCTION_TYPE_BALANCE:
case RCSP_SCENE_NOISE_REDUCTION_TYPE_DEEPNESS:
default:
printf("%s, type:%d", __FUNCTION__, type);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_SCENE_NOISE_REDUCTION, NULL, 0);
break;
}
}
#endif
@@ -0,0 +1,27 @@
#ifndef __ADV_SCENE_NOISE_REDUCTION_H__
#define __ADV_SCENE_NOISE_REDUCTION_H__
#include "system/includes.h"
typedef enum {
RCSP_SCENE_NOISE_REDUCTION_TYPE_INTELLIGENT = 0x00,
RCSP_SCENE_NOISE_REDUCTION_TYPE_MILD = 0x01,
RCSP_SCENE_NOISE_REDUCTION_TYPE_BALANCE = 0x02,
RCSP_SCENE_NOISE_REDUCTION_TYPE_DEEPNESS = 0x03,
} RCSP_SCENE_NOISE_REDUCTION_TYPE;
/**
* @brief 获取场景降噪类型
*
* @result RCSP_SCENE_NOISE_REDUCTION_TYPE
*/
RCSP_SCENE_NOISE_REDUCTION_TYPE get_scene_noise_reduction_type();
/**
* @brief 设置场景降噪类型
*/
void set_scene_noise_reduction_type(RCSP_SCENE_NOISE_REDUCTION_TYPE type);
#endif // __ADV_SCENE_NOISE_REDUCTION_H__
@@ -0,0 +1,131 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_time_stamp_setting.data.bss")
#pragma data_seg(".adv_time_stamp_setting.data")
#pragma const_seg(".adv_time_stamp_setting.text.const")
#pragma code_seg(".adv_time_stamp_setting.text")
#endif
#include "rcsp_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "adv_time_stamp_setting.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#if (RCSP_MODE && RCSP_ADV_EN)
extern int get_bt_tws_connect_status();
static u32 adv_time_stamp = 0;
static int get_adv_time_stamp(u8 *time_stamp)
{
memcpy(time_stamp, (u8 *)&adv_time_stamp, sizeof(adv_time_stamp));
return 0;
}
static void set_adv_time_stamp(u8 *time_stamp)
{
memcpy((u8 *)&adv_time_stamp, time_stamp, sizeof(adv_time_stamp));
}
void sync_setting_by_time_stamp(void)
{
tws_api_send_data_to_sibling((u8 *)&adv_time_stamp, sizeof(adv_time_stamp), TWS_FUNC_ID_TIME_STAMP_SYNC);
}
void deal_sibling_time_stamp_setting_switch(void *data, u16 len)
{
u32 time_stamp = *((u32 *)data);
if (adv_time_stamp > time_stamp) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_SYNC, NULL, 0);
}
}
void deal_adv_setting_gain_time_stamp(void)
{
#if TCFG_USER_TWS_ENABLE
extern u8 adv_info_device_request(u8 * buf, u16 len);
static u8 tws_pair = 0;
u8 buf = 2;
u8 ret = 0;
if (get_bt_tws_connect_status()) {
tws_pair = 1;
} else {
if (tws_pair) {
tws_pair = 0;
ret = adv_info_device_request(&buf, sizeof(buf));
}
}
#endif
}
// 1、写入VM
static void update_time_stamp_vm_value(u8 *time_stamp)
{
syscfg_write(CFG_RCSP_ADV_TIME_STAMP, time_stamp, 4);
}
// 2、同步对端
static void adv_time_stamp_sync(u8 *time_stamp)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_TIME_STAMP);
}
#endif
}
static void deal_time_stamp_setting(u8 *time_stamp, u8 write_vm, u8 tws_sync)
{
if (time_stamp) {
set_adv_time_stamp(time_stamp);
}
if (write_vm) {
update_time_stamp_vm_value((u8 *)&adv_time_stamp);
}
if (tws_sync) {
adv_time_stamp_sync((u8 *)&adv_time_stamp);
}
}
static int adv_time_stamp_sibling_settting_deal(u8 *setting_data)
{
u32 time_stamp = (setting_data[0] | (setting_data[1] << 8) | (setting_data[2] << 16) | (setting_data[3] << 24));
set_adv_time_stamp((u8 *)&time_stamp);
return 0;
}
static int time_stamp_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *time_stamp_setting_data = (u8 *) setting_data;
adv_time_stamp = (((time_stamp_setting_data[0] << 8) | time_stamp_setting_data[1]) << 8 | time_stamp_setting_data[2]) << 8 | time_stamp_setting_data[3];
u8 bt_name[32] = {0};
syscfg_read(CFG_BT_NAME, bt_name, sizeof(bt_name));
RCSP_SETTING_OPT *setting_opt_hdl = get_rcsp_setting_opt_hdl(ATTR_TYPE_EDR_NAME);
if (setting_opt_hdl && setting_opt_hdl->set_setting) {
setting_opt_hdl->set_setting(bt_name);
}
return 0;
}
static RCSP_SETTING_OPT adv_time_stamp_opt = {
.data_len = 4,
.setting_type = ATTR_TYPE_TIME_STAMP,
.syscfg_id = CFG_RCSP_ADV_TIME_STAMP,
.deal_opt_setting = deal_time_stamp_setting,
.set_setting = set_adv_time_stamp,
.get_setting = get_adv_time_stamp,
.custom_setting_init = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = adv_time_stamp_sibling_settting_deal,
.custom_setting_release = NULL,
.set_setting_extra_handle = time_stamp_set_setting_extra_handle,
.get_setting_extra_handle = NULL,
};
REGISTER_APP_SETTING_OPT(adv_time_stamp_opt);
#endif
@@ -0,0 +1,10 @@
#ifndef __ADV_TIME_STAMP_SETTING_H__
#define __ADV_TIME_STAMP_SETTING_H__
//void set_adv_time_stamp(u8 *time_stamp);
//void get_adv_time_stamp(u8 *time_stamp);
void deal_sibling_time_stamp_setting_switch(void *data, u16 len);
extern void sync_setting_by_time_stamp(void);
void deal_adv_setting_gain_time_stamp(void);
#endif
@@ -0,0 +1,33 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_voice_enhancement_mode.data.bss")
#pragma data_seg(".adv_voice_enhancement_mode.data")
#pragma const_seg(".adv_voice_enhancement_mode.text.const")
#pragma code_seg(".adv_voice_enhancement_mode.text")
#endif
#include "adv_voice_enhancement_mode.h"
#include "app_config.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_ANC_VOICE && RCSP_ADV_WIND_NOISE_DETECTION)
/**
* @brief 获取人声增强模式开关
*
* @result bool
*/
bool get_voice_enhancement_mode_switch()
{
printf("===%s===", __FUNCTION__);
return true;
}
/**
* @brief 设置人声增强模式开关
*/
void set_voice_enhancement_mode_switch(bool mode_switch)
{
printf("%s, switch:%d\n", __FUNCTION__, mode_switch);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_VOICE_ENHANCEMENT_MODE, NULL, 0);
}
#endif
@@ -0,0 +1,18 @@
#ifndef __ADV_VOICE_ENHANCEMENT_MODE_H__
#define __ADV_VOICE_ENHANCEMENT_MODE_H__
#include "system/includes.h"
/**
* @brief 获取人声增强模式开关
*
* @result bool
*/
bool get_voice_enhancement_mode_switch();
/**
* @brief 设置人声增强模式开关
*/
void set_voice_enhancement_mode_switch(bool mode_switch);
#endif // __ADV_VOICE_ENHANCEMENT_MODE_H__
@@ -0,0 +1,34 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_wind_noise_detection.data.bss")
#pragma data_seg(".adv_wind_noise_detection.data")
#pragma const_seg(".adv_wind_noise_detection.text.const")
#pragma code_seg(".adv_wind_noise_detection.text")
#endif
#include "adv_wind_noise_detection.h"
#include "app_config.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_ANC_VOICE && RCSP_ADV_WIND_NOISE_DETECTION)
/**
* @brief 获取风噪检测开关
*
* @result bool
*/
bool get_wind_noise_detection_switch()
{
printf("===%s===", __FUNCTION__);
return true;
}
/**
* @brief 设置风噪检测开关
*/
void set_wind_noise_detection_switch(bool detection_switch)
{
printf("%s, switch:%d\n", __FUNCTION__, detection_switch);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_WIND_NOISE_DETECTION, NULL, 0);
}
#endif
@@ -0,0 +1,18 @@
#ifndef __ADV_WIND_NOISE_DETECTION_H__
#define __ADV_WIND_NOISE_DETECTION_H__
#include "system/includes.h"
/**
* @brief 获取风噪检测开关
*
* @result bool
*/
bool get_wind_noise_detection_switch();
/**
* @brief 设置风噪检测开关
*/
void set_wind_noise_detection_switch(bool detection_switch);
#endif // __ADV_WIND_NOISE_DETECTION_H__
@@ -0,0 +1,171 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adv_work_setting.data.bss")
#pragma data_seg(".adv_work_setting.data")
#pragma const_seg(".adv_work_setting.text.const")
#pragma code_seg(".adv_work_setting.text")
#endif
#include "app_config.h"
#include "adv_work_setting.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "os/os_api.h"
#include "btstack/avctp_user.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#if (RCSP_MODE && RCSP_ADV_EN)
#if RCSP_ADV_WORK_SET_ENABLE
static u8 g_work_mode = RCSPWorkModeNormal;
extern void bt_set_low_latency_mode(int enable, u8 tone_play_enable, int delay_ms);
static void set_work_setting(u8 *work_setting_info)
{
g_work_mode = *work_setting_info;
/* printf("rcsp_work %s, %s, %d, mode:%d\n", __FILE__, __FUNCTION__, __LINE__, g_work_mode); */
}
static int get_work_setting(u8 *work_setting_info)
{
/* printf("rcsp_work %s, %s, %d, mode:%d\n", __FILE__, __FUNCTION__, __LINE__, g_work_mode); */
*work_setting_info = g_work_mode;
return 0;
}
static void adv_work_setting_vm_value(u8 *work_setting_info)
{
syscfg_write(CFG_RCSP_ADV_WORK_SETTING, work_setting_info, sizeof(u8));
}
static void adv_work_setting_sync(u8 *work_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_WORK_MODE);
}
#endif
}
static void __rcsp_work_set_call(void)
{
/* printf("__rcsp_work_set_call\n"); */
if (RCSPWorkModeNormal == g_work_mode) {
bt_set_low_latency_mode(0, 1, 300);
} else if (RCSPWorkModeGame == g_work_mode) {
bt_set_low_latency_mode(1, 1, 300);
}
}
static void rcsp_work_set_deal(void)
{
int err;
int msg[3];
msg[0] = (int) __rcsp_work_set_call;
msg[1] = 1;
msg[2] = 0;
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
/* printf("%s, err %x\n", __FUNCTION__, err); */
}
static void update_work_setting_state(void)
{
/* printf("%s, set deal\n", __FUNCTION__); */
rcsp_work_set_deal();
}
static void deal_work_setting(u8 *work_setting_info, u8 write_vm, u8 tws_sync)
{
/* printf("rcsp_work %s, %s, %d, work_setting_info:%d\n", __FILE__, __FUNCTION__, __LINE__, *work_setting_info); */
if (work_setting_info) {
set_work_setting(work_setting_info);
}
if (write_vm) {
adv_work_setting_vm_value(work_setting_info);
}
if (tws_sync) {
adv_work_setting_sync(work_setting_info);
}
update_work_setting_state();
}
void rcsp_set_work_mode(RCSPWorkMode work_mode)
{
u8 _work_mode = work_mode;
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
if (TWS_ROLE_MASTER == tws_api_get_role()) {
deal_work_setting(&_work_mode, 1, 1);
}
} else {
deal_work_setting(&_work_mode, 1, 1);
}
#else
deal_work_setting(&_work_mode, 1, 1);
#endif
u8 adv_cmd = 0x0;
adv_info_device_request(&adv_cmd, sizeof(adv_cmd));
}
int ble_vendor_is_slow_state(void)
{
if ((BT_STATUS_PLAYING_MUSIC == bt_get_connect_status()) && (RCSPWorkModeGame == g_work_mode)) {
return 1;
} else {
return 0;
}
}
static int adv_work_opt_init(void)
{
u8 work_setting_info = RCSPWorkModeNormal;
if (rcsp_read_data_from_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info))) {
if (work_setting_info != RCSPWorkModeNormal && work_setting_info != RCSPWorkModeGame) {
work_setting_info = RCSPWorkModeNormal;
}
set_work_setting(&work_setting_info);
__rcsp_work_set_call();
}
return 0;
}
static int work_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 dlen = *((u8 *)setting_data_len);
u8 *work_mode_setting_data = (u8 *)setting_data;
memcpy(&g_work_mode, work_mode_setting_data, dlen);
return 0;
}
static int work_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u8 **setting_data_ptr = (u8 **)setting_data;
*setting_data_ptr = &g_work_mode;
return sizeof(g_work_mode);
}
static RCSP_SETTING_OPT adv_work_opt = {
.data_len = 1,
.setting_type = ATTR_TYPE_WORK_MODE,
.syscfg_id = CFG_RCSP_ADV_WORK_SETTING,
.deal_opt_setting = deal_work_setting,
.set_setting = set_work_setting,
.get_setting = get_work_setting,
.custom_setting_init = adv_work_opt_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = work_set_setting_extra_handle,
.get_setting_extra_handle = work_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(adv_work_opt);
#endif
#endif
@@ -0,0 +1,13 @@
#ifndef __ADV_WORK_SETTING_H__
#define __ADV_WORK_SETTING_H__
typedef enum {
RCSPWorkModeNone = 0,
RCSPWorkModeNormal = 1,
RCSPWorkModeGame = 2,
} RCSPWorkMode;
// 设置工作模式
void rcsp_set_work_mode(RCSPWorkMode work_mode);
#endif
@@ -0,0 +1,226 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_color_led_setting.data.bss")
#pragma data_seg(".rcsp_color_led_setting.data")
#pragma const_seg(".rcsp_color_led_setting.text.const")
#pragma code_seg(".rcsp_color_led_setting.text")
#endif
#include "rcsp_color_led_setting.h"
#if (RCSP_MODE && RCSP_ADV_COLOR_LED_SET_ENABLE)
#include "syscfg_id.h"
#include "user_cfg.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "ui_manage.h"
#include "asm/pwm_led.h"
#include "color_led_app.h"
#define IS_COLOR_LED_LEGAL(color_led) \
((color_led.open_status <= 2) && \
(color_led.mode <= 2) && \
(color_led.fre_mode <= 3))
enum {
OPEN_STATUS_CLOSE = 0,
OPEN_STATUS_OPEN = 1,
OPEN_STATUS_SETTING = 2,
};
enum {
MODE_LIGHT = 0,
MODE_TWINKLE = 1,
MODE_USER = 2,
};
const u32 twinkle_color_table[] = {
COLOR_RED,
COLOR_ORANGE,
COLOR_YELLOW,
COLOR_GREEN,
COLOR_CYAN,
COLOR_BLUE,
COLOR_PURPLE,
};
typedef struct {
u8 open_status : 2;//0:关闭 1:打开 2:设置模式
u8 mode : 3;//0:彩色 2:闪烁 3:情景模式
u8 reseved : 3;
u8 red;
u8 green;
u8 blue;
u8 twinkle_mode;
u8 fre_mode;
u8 user_mode;
u16 hue;
u8 saturation;
u8 lightness;
} __attribute__((packed)) color_led_t;
static color_led_t color_led;
#define COLOR_LED_PROTOCOL_DATA_LEN (sizeof(color_led_t))
u32 rcsp_get_color_led_setting_data_len(void)
{
return COLOR_LED_PROTOCOL_DATA_LEN;
}
static void set_color_led_setting(u8 *color_led_setting_info)
{
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* put_buf(color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN); */
color_led_t color_led_cur;
memcpy((u8 *)&color_led_cur, color_led_setting_info, sizeof(color_led_t));
if ((color_led_cur.open_status == 0) || (color_led_cur.open_status == 1)) {
//switch active,not set other_status
color_led.open_status = color_led_cur.open_status;
return;
}
memcpy((u8 *)&color_led, color_led_setting_info, sizeof(color_led_t));
}
static int get_color_led_setting(u8 *color_led_setting_info)
{
color_led_t color_led_cur;
int len = syscfg_read(VM_COLOR_LED_SETTING, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN);
if (len != COLOR_LED_PROTOCOL_DATA_LEN) {
printf("!!!!!!!!color led data read error !!!!!!!!!!!!!!! \n");
}
return 0;
}
// 1、写入VM
static void update_color_led_setting_vm_value(u8 *color_led_setting_info)
{
color_led_t color_led_cur;
memcpy((u8 *)&color_led_cur, color_led_setting_info, sizeof(color_led_t));
if ((color_led_cur.open_status == 0) || (color_led_cur.open_status == 1)) {
//switch active,not set other_status
u8 open_status = color_led_cur.open_status;
int len = syscfg_read(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN);
color_led_cur.open_status = open_status;
syscfg_write(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN);
return;
}
syscfg_write(VM_COLOR_LED_SETTING, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN);
}
// 2、同步对端
static void color_led_setting_sync(u8 *color_led_setting_info)
{
#if TCFG_USER_TWS_ENABLE
extern int get_bt_tws_connect_status();
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_COLOR_LED_SETTING);
}
#endif
}
static void color_led_flash(void)
{
color_led_t color_led_cur;
get_color_led_setting((u8 *)&color_led_cur);
if (!IS_COLOR_LED_LEGAL(color_led_cur)) {
printf("color led illegal data \n");
return;
}
u8 mode = 0;
u8 fre_mode = 0;
u32 color = 0;
if (color_led_cur.open_status == OPEN_STATUS_CLOSE) {
mode = COLOR_LED_MODE_LIGHT;
color = COLOR_BLACK;
color_led_set_api(mode, fre_mode, color);
return;
}
fre_mode = color_led_cur.fre_mode;
color = color_led_cur.red + ((int)color_led_cur.green << 8) + ((int)color_led_cur.blue << 16);
switch (color_led_cur.mode) {
case MODE_LIGHT:
mode = COLOR_LED_MODE_LIGHT;
break;
case MODE_TWINKLE:
if (color_led_cur.twinkle_mode == 0) {
mode = COLOR_LED_MODE_COLORFUL_TWINKLE;
} else {
mode = COLOR_LED_MODE_TWINKLE;
color = twinkle_color_table[color_led_cur.twinkle_mode - 1];
}
break;
case MODE_USER:
mode = COLOR_LED_MODE_RAINBOW + color_led_cur.user_mode;
break;
default:
break;
}
printf("mode:%d fre_mode:%d color:0x%x \n", mode, fre_mode, color);
color_led_set_api(mode, fre_mode, color);
}
static void deal_color_led_setting(u8 *color_led_setting_info, u8 write_vm, u8 tws_sync)
{
u8 led_setting[COLOR_LED_PROTOCOL_DATA_LEN];
if (!color_led_setting_info) {
get_color_led_setting(led_setting);
} else {
memcpy(led_setting, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN);
set_color_led_setting(color_led_setting_info);
}
if (write_vm) {
update_color_led_setting_vm_value(led_setting);
}
if (tws_sync) {
color_led_setting_sync(led_setting);
}
color_led_flash();
}
static int rcsp_color_led_init(void)
{
color_led_t color_led_cur;
int len = syscfg_read(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN);
if ((!IS_COLOR_LED_LEGAL(color_led)) || (len != COLOR_LED_PROTOCOL_DATA_LEN)) {
printf("first time start device,reset color led data \n");
memset((u8 *)&color_led_cur, 0x00, sizeof(color_led_cur));
color_led_cur.open_status = OPEN_STATUS_SETTING;
color_led_cur.mode = MODE_USER;
color_led_cur.red = 64;
color_led_cur.green = 191;
color_led_cur.blue = 191;
color_led_cur.hue = 180;
color_led_cur.saturation = 50;
color_led_cur.lightness = 50;
color_led_set_api(COLOR_LED_MODE_RAINBOW + color_led_cur.user_mode, 0, 0);
syscfg_write(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN);
color_led = color_led_cur;
}
set_color_led_setting((u8 *)&color_led_cur);
deal_color_led_setting(NULL, 0, 0);
return 0;
}
static RCSP_SETTING_OPT adv_color_led_opt = {
.data_len = COLOR_LED_PROTOCOL_DATA_LEN,
.setting_type = ATTR_TYPE_COLOR_LED_SETTING,
.syscfg_id = VM_COLOR_LED_SETTING,
.deal_opt_setting = deal_color_led_setting,
.set_setting = set_color_led_setting,
.get_setting = get_color_led_setting,
.custom_setting_init = rcsp_color_led_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
};
REGISTER_APP_SETTING_OPT(adv_color_led_opt);
#endif
@@ -0,0 +1,10 @@
#ifndef __RCSP_MUSIC_INFO_SETTING_H__
#define __RCSP_MUSIC_INFO_SETTING_H__
#include "system/includes.h"
#include "app_config.h"
// 获取彩灯配置的数据长度
u32 rcsp_get_color_led_setting_data_len(void);
#endif
@@ -0,0 +1,444 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_eq_setting.data.bss")
#pragma data_seg(".rcsp_eq_setting.data")
#pragma const_seg(".rcsp_eq_setting.text.const")
#pragma code_seg(".rcsp_eq_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "smartbox_user_app.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#define LOG_TAG_CONST APP
#define LOG_TAG "[RCSP-EQ]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_CHAR_ENABLE
#include "debug.h"
#if (defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE && RCSP_MODE && RCSP_ADV_EQ_SET_ENABLE)
#if RCSP_MODE == RCSP_MODE_EARPHONE
#include "media/effects/audio_eq.h"
#include "media/effects/eq_config.h"
#else
#ifndef CONFIG_MEDIA_NEW_ENABLE
#include "media/eq_config.h"
#else
#include "effects/audio_eq.h"
#endif
#endif
#include "clock_manager/clock_manager.h"
extern int get_bt_tws_connect_status();
__attribute__((weak))
u8 eq_get_table_nsection(EQ_MODE mode)
{
return EQ_SECTION_MAX;
}
static u8 g_eq_setting_info[11] = {0};
static void eq_setting_info_deal(u8 *eq_info_data)
{
u8 data;
u8 status;
u8 mode;
if (eq_info_data[0] >> 7) {
status = eq_info_data[2];
} else {
status = *(((u8 *)eq_info_data) + 1);
}
mode = eq_info_data[0] & 0x7F;
if (mode < EQ_MODE_CUSTOM) {
clock_refurbish();
eq_mode_set(mode);
} else {
// 自定义修改EQ参数
if (EQ_MODE_CUSTOM == mode) {
clock_refurbish();
if (status != 0x7F) {
u8 i;
for (i = 0; i < eq_get_table_nsection(0); i++) {
if (eq_info_data[0] >> 7) {
data = eq_info_data[i + 2];
} else {
data = eq_info_data[i + 1];
}
eq_mode_set_custom_param(i, (s8)data);
}
}
eq_mode_set(mode);
}
}
}
static void set_eq_setting(u8 *eq_setting)
{
memcpy(g_eq_setting_info, eq_setting, 11);
}
static int get_eq_setting(u8 *eq_setting)
{
memcpy(eq_setting, g_eq_setting_info, 11);
return 0;
}
// 1、写入VM
static void update_eq_vm_value(u8 *eq_setting)
{
u8 status = *(((u8 *)eq_setting) + 1);
syscfg_write(CFG_RCSP_ADV_EQ_MODE_SETTING, eq_setting, 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
// 多段eq
status = eq_setting[2];
}
if (status != 0x7F) {
syscfg_write(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting[1], 10);
}
}
}
// 2、同步对端
static void eq_sync(u8 *eq_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_EQ_SETTING);
}
#endif
}
static void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync)
{
u8 eq_info[11] = {0};
if (!eq_setting) {
get_eq_setting(eq_info);
} else {
u8 status = *(((u8 *)eq_setting) + 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
status = eq_setting[2];
}
if (status != 0x7F) {
memcpy(eq_info, eq_setting, 11);
set_eq_setting(eq_info);
} else {
g_eq_setting_info[0] = eq_setting[0];
get_eq_setting(eq_info);
}
} else {
memcpy(eq_info, eq_setting, 11);
g_eq_setting_info[0] = eq_setting[0];
}
}
if (write_vm) {
update_eq_vm_value(eq_info);
}
if (tws_sync) {
eq_sync(eq_info);
}
eq_setting_info_deal(eq_info);
}
static u8 app_get_eq_info(u8 *get_eq_info)
{
u16 i;
get_eq_info[0] = eq_mode_get_cur();
u8 data_len = 1;
if (10 == eq_get_table_nsection(0)) {
// 10段eq : mode + gain[10byte]
for (i = 0; i < 10; i++) {
get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i);
data_len++;
}
} else {
// 多段eq : mode + num + value(freq[2byte] + gain[1byte])
get_eq_info[1] = eq_get_table_nsection(0);
data_len++;
for (i = 0; i < eq_get_table_nsection(0); i++) {
get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i);
data_len++;
}
get_eq_info[0] |= (1 << 7);
}
return data_len;
}
static u8 app_get_eq_all_info(u8 *get_eq_info)
{
u16 i;
u8 mode = EQ_MODE_NORMAL;
get_eq_info[0] = eq_get_table_nsection(0);
u8 data_len = 1;
// get freq
for (i = 0; i < eq_get_table_nsection(0); i++) {
u16 eq_freq = (u16)(eq_mode_get_freq(mode, i) & ((u16) - 1));
eq_freq = ((((u8 *)&eq_freq)[0] << 8) + ((u8 *)&eq_freq)[1]);
memcpy(get_eq_info + data_len, &eq_freq, sizeof(eq_freq));
data_len += 2;
}
// get gain
for (; mode < EQ_MODE_CUSTOM; mode++) {
get_eq_info[data_len] = mode;
if (10 != eq_get_table_nsection(0)) {
get_eq_info[data_len] |= (1 << 7);
}
data_len++;
for (i = 0; i < eq_get_table_nsection(0); i++) {
u8 eq_gain = eq_mode_get_gain(mode, i);
get_eq_info[data_len] = eq_gain;
data_len++;
}
}
// get custom
get_eq_info[data_len] = EQ_MODE_CUSTOM;
if (10 != eq_get_table_nsection(0)) {
get_eq_info[data_len] |= (1 << 7);
}
data_len++;
for (i = 0; i < eq_get_table_nsection(0); i++) {
if (10 == eq_get_table_nsection(0)) {
get_eq_info[data_len] = g_eq_setting_info[i + 1];
} else {
get_eq_info[data_len] = g_eq_setting_info[i + 2];
}
data_len++;
}
return data_len;
}
static int eq_opt_init(void)
{
u8 eq_setting_vm_info[11] = {0};
u8 eq_setting_info[10] = {0};
u8 eq_setting_mode = 0;
u8 i;
if (rcsp_read_data_from_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, eq_setting_info, sizeof(eq_setting_info))) {
if (rcsp_read_data_from_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode))) {
eq_setting_vm_info[0] = eq_setting_mode;
memcpy(&eq_setting_vm_info[1], eq_setting_info, 10);
set_eq_setting(eq_setting_vm_info);
deal_eq_setting(NULL, 0, 0);
}
}
return 0;
}
static int eq_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u16 data_len = *((u16 *) setting_data_len);
if (data_len > sizeof(g_eq_setting_info)) {
data_len = app_get_eq_all_info(setting_data);
} else {
data_len = app_get_eq_info(setting_data);
}
return data_len;
}
static RCSP_SETTING_OPT eq_opt = {
.data_len = 11,
.setting_type = ATTR_TYPE_EQ_SETTING,
.syscfg_id = CFG_RCSP_ADV_EQ_DATA_SETTING,
.deal_opt_setting = deal_eq_setting,
.set_setting = set_eq_setting,
.get_setting = get_eq_setting,
.custom_setting_init = eq_opt_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = NULL,
.get_setting_extra_handle = eq_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(eq_opt);
#elif ((!TCFG_EQ_ENABLE) && RCSP_MODE && RCSP_ADV_EQ_SET_ENABLE && (defined TCFG_CSC_BT_APP) && TCFG_CSC_BT_APP)
#if RCSP_MODE == RCSP_MODE_EARPHONE
#include "media/effects/audio_eq.h"
#include "media/effects/eq_config.h"
#else
#ifndef CONFIG_MEDIA_NEW_ENABLE
#include "media/eq_config.h"
#else
#include "effects/audio_eq.h"
#endif
#endif
#include "clock_manager/clock_manager.h"
#include "smartbox_info_manager.h"
static u8 g_eq_setting_info[11];
static void set_eq_setting(u8 *eq_setting)
{
memcpy(g_eq_setting_info, eq_setting, 11);
}
static int get_eq_setting(u8 *eq_setting)
{
memcpy(eq_setting, g_eq_setting_info, 11);
return 0;
}
// 1、写入VM
static void update_eq_vm_value(u8 *eq_setting)
{
u8 status = *(((u8 *)eq_setting) + 1);
syscfg_write(CFG_RCSP_ADV_EQ_MODE_SETTING, eq_setting, 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
// 多段eq
status = eq_setting[2];
}
if (status != 0x7F) {
syscfg_write(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting[1], 10);
}
}
}
//eq配置 写入vm和通知app
void eq_ui_set_rcsp_vm(u8 mode)
{
u8 eq_info[11] = {0};
get_eq_setting(eq_info);
eq_info[0] = mode;
set_eq_setting(eq_info);
update_eq_vm_value(eq_info);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_EQ, NULL, 0);
}
static void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync)
{
u8 eq_info[11] = {0};
if (!eq_setting) {
get_eq_setting(eq_info);
} else {
u8 status = *(((u8 *)eq_setting) + 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
status = eq_setting[2];
}
if (status != 0x7F) {
memcpy(eq_info, eq_setting, 11);
set_eq_setting(eq_info);
} else {
g_eq_setting_info[0] = eq_setting[0];
get_eq_setting(eq_info);
}
} else {
memcpy(eq_info, eq_setting, 11);
g_eq_setting_info[0] = eq_setting[0];
}
}
if (write_vm) {
update_eq_vm_value(eq_info);
}
log_info("%s %d %d eq_mode:%d", __func__, write_vm, tws_sync, eq_info[0]);
sbox_equalizer_mode_set(eq_info[0]);
if (tws_sync) {
custom_client_send_eq_mode(eq_info[0]);
}
}
static int eq_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u16 data_len = *((u16 *) setting_data_len);
// if (data_len > sizeof(g_eq_setting_info)) {
// data_len = app_get_eq_all_info(setting_data);
// } else {
// data_len = app_get_eq_info(setting_data);
// }
if (data_len > sizeof(g_eq_setting_info)) {
data_len = sizeof(g_eq_setting_info);
memcpy(setting_data, g_eq_setting_info, data_len);
} else {
memcpy(setting_data, g_eq_setting_info, data_len);
}
return data_len;
}
static int eq_opt_init(void)
{
u8 eq_setting_vm_info[11] = {0};
u8 eq_setting_info[10] = {0};
u8 eq_setting_mode = 0;
u8 i;
int ret;
log_info("%s", __func__);
ret = rcsp_read_data_from_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, eq_setting_info, sizeof(eq_setting_info));
if (ret == sizeof(eq_setting_info)) {
memcpy(&eq_setting_vm_info[1], eq_setting_info, 10);
}
ret = rcsp_read_data_from_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode));
if (ret == sizeof(eq_setting_mode)) {
eq_setting_vm_info[0] = eq_setting_mode;
}
set_eq_setting(eq_setting_vm_info);
deal_eq_setting(NULL, 0, 0);
return 0;
}
static RCSP_SETTING_OPT eq_opt = {
.data_len = 11,
.setting_type = ATTR_TYPE_EQ_SETTING,
.syscfg_id = CFG_RCSP_ADV_EQ_DATA_SETTING,
.deal_opt_setting = deal_eq_setting,
.set_setting = set_eq_setting,
.get_setting = get_eq_setting,
.custom_setting_init = eq_opt_init,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = NULL,
.get_setting_extra_handle = eq_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(eq_opt);
#else
void eq_ui_set_rcsp_vm(u8 mode)
{
printf("%s is NULL warn!!!", __func__);
}
#endif
@@ -0,0 +1,132 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_high_low_vol_setting.data.bss")
#pragma data_seg(".rcsp_high_low_vol_setting.data")
#pragma const_seg(".rcsp_high_low_vol_setting.text.const")
#pragma code_seg(".rcsp_high_low_vol_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "ble_rcsp_server.h"
#include "JL_rcsp_protocol.h"
#include "effects/audio_bass_treble_eq.h"
#if (RCSP_MODE && RCSP_ADV_HIGH_LOW_SET && TCFG_BASS_TREBLE_NODE_ENABLE)
struct _HIGH_LOW_VOL {
int low_vol;
int high_vol;
};
static struct _HIGH_LOW_VOL high_low_vol = {
.low_vol = 12,
.high_vol = 12,
};
extern int get_bt_tws_connect_status();
extern int audio_out_eq_spec_set_gain(u8 idx, int gain);
static int get_high_low_vol_info(u8 *vol_gain_param)
{
memcpy(vol_gain_param, &high_low_vol, sizeof(struct _HIGH_LOW_VOL));
return 0;
}
static void set_high_low_vol_info(u8 *vol_gain_param)
{
memcpy(&high_low_vol, vol_gain_param, sizeof(struct _HIGH_LOW_VOL));
}
static void update_high_low_vol_vm_value(u8 *vol_gain_param)
{
syscfg_write(CFG_RCSP_ADV_HIGH_LOW_VOL, vol_gain_param, sizeof(struct _HIGH_LOW_VOL));
}
static void high_low_vol_setting_sync(u8 *vol_gain_param)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_HIGH_LOW_VOL);
}
#endif
}
static void high_low_vol_state_update(void)
{
static int low_vol = 0;
static int high_vol = 0;
struct high_bass param = {0};
if (low_vol != high_low_vol.low_vol) {
param.gain = high_low_vol.low_vol - 12;
mix_out_high_bass(AUDIO_EQ_BASS, &param);
low_vol = high_low_vol.low_vol;
}
if (high_vol != high_low_vol.high_vol) {
param.gain = high_low_vol.high_vol - 12;
mix_out_high_bass(AUDIO_EQ_HIGH, &param);
high_vol = high_low_vol.high_vol;
}
}
static void deal_high_low_vol(u8 *vol_gain_data, u8 write_vm, u8 tws_sync)
{
if (vol_gain_data) {
set_high_low_vol_info(vol_gain_data);
printf("low %d, high %d\n", high_low_vol.low_vol, high_low_vol.high_vol);
}
if (write_vm) {
update_high_low_vol_vm_value((u8 *)&high_low_vol);
}
if (tws_sync) {
high_low_vol_setting_sync((u8 *)&high_low_vol);
}
high_low_vol_state_update();
}
static int high_low_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
high_low_vol.low_vol = READ_BIG_U32(setting_data) + 12;
high_low_vol.high_vol = READ_BIG_U32(setting_data + 4) + 12;
high_low_vol.low_vol = high_low_vol.low_vol > 24 ? 24 : high_low_vol.low_vol;
high_low_vol.low_vol = high_low_vol.low_vol < 0 ? 0 : high_low_vol.low_vol;
high_low_vol.high_vol = high_low_vol.high_vol > 24 ? 24 : high_low_vol.high_vol;
high_low_vol.high_vol = high_low_vol.high_vol < 0 ? 0 : high_low_vol.high_vol;
return 0;
}
static int high_low_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
struct _HIGH_LOW_VOL gain_param = {0};
gain_param.low_vol = high_low_vol.low_vol < 0 ? 0 : high_low_vol.low_vol;
gain_param.low_vol = high_low_vol.low_vol > 24 ? 24 : high_low_vol.low_vol;
gain_param.high_vol = high_low_vol.high_vol < 0 ? 0 : high_low_vol.high_vol;
gain_param.high_vol = high_low_vol.high_vol > 24 ? 24 : high_low_vol.high_vol;
gain_param.low_vol -= 12;
gain_param.high_vol -= 12;
gain_param.low_vol = READ_BIG_U32((u8 *)&gain_param.low_vol);
gain_param.high_vol = READ_BIG_U32((u8 *)&gain_param.high_vol);
memcpy(setting_data, &gain_param, sizeof(gain_param));
return sizeof(gain_param);
}
static RCSP_SETTING_OPT high_low_vol_opt = {
.data_len = 8,
.setting_type = ATTR_TYPE_HIGH_LOW_VOL,
.syscfg_id = CFG_RCSP_ADV_HIGH_LOW_VOL,
.deal_opt_setting = deal_high_low_vol,
.set_setting = set_high_low_vol_info,
.get_setting = get_high_low_vol_info,
.custom_setting_init = NULL,
.custom_setting_release = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.set_setting_extra_handle = high_low_set_setting_extra_handle,
.get_setting_extra_handle = high_low_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(high_low_vol_opt);
#endif
@@ -0,0 +1,138 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_karaoke_eq_setting.data.bss")
#pragma data_seg(".rcsp_karaoke_eq_setting.data")
#pragma const_seg(".rcsp_karaoke_eq_setting.text.const")
#pragma code_seg(".rcsp_karaoke_eq_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#if (defined(TCFG_EQ_ENABLE) && MIC_EFFECT_EQ_EN && RCSP_MODE && RCSP_ADV_KARAOKE_EQ_SET_ENABLE && RCSP_ADV_KARAOKE_SET_ENABLE)
#include "effect_cfg.h"
#include "effect_tool.h"
#include "mic_effect.h"
static u8 g_karaoke_setting_info[9] = {EFFECT_EQ_SECTION_MAX, 0};
static void update_eq_setting_info(u8 *eq_info_data)
{
// 更新卡拉ok的EQ值
struct eq_seg_info *eq_info = NULL;
for (u8 i = 0; i < EFFECT_EQ_SECTION_MAX; i++) {
eq_info = mic_eq_get_info(i);
if (eq_info->gain != g_karaoke_setting_info[i + 1]) {
eq_info->gain = g_karaoke_setting_info[i + 1];
mic_eq_set_info(eq_info);
}
}
}
static void set_karaoke_eq_setting(u8 *eq_setting)
{
memcpy(g_karaoke_setting_info, eq_setting, sizeof(g_karaoke_setting_info));
}
static int get_karaoke_eq_setting(u8 *eq_setting)
{
memcpy(eq_setting, g_karaoke_setting_info, sizeof(g_karaoke_setting_info));
return sizeof(g_karaoke_setting_info);
}
// 1、写入VM
static void update_karaoke_eq_vm_value(u8 *eq_setting)
{
syscfg_write(VM_KARAOKE_EQ_SETTING, g_karaoke_setting_info, 9);
}
// 2、同步对端
static void karaoke_eq_sync(u8 *eq_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_KARAOKE_EQ_SETTING);
}
#endif
}
static void deal_karaoke_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync)
{
if (eq_setting) {
set_karaoke_eq_setting(eq_setting);
}
if (write_vm) {
update_karaoke_eq_vm_value(eq_setting);
}
if (tws_sync) {
karaoke_eq_sync(eq_setting);
}
update_eq_setting_info(eq_setting);
}
// 0 - gain
// 1 - freq
static u8 get_karaoke_eq_info(u8 *get_eq_info, u8 type)
{
u8 i;
u8 data_len = 1;
struct eq_seg_info *eq_info = NULL;
get_eq_info[0] = EFFECT_EQ_SECTION_MAX;
for (i = 0; i < EFFECT_EQ_SECTION_MAX; i++) {
eq_info = mic_eq_get_info(i);
if (type) {
u16 eq_freq = eq_info->freq;
eq_freq = ((((u8 *)&eq_freq)[0] << 8) + ((u8 *)&eq_freq)[1]);
memcpy(get_eq_info + data_len, &eq_freq, sizeof(eq_freq));
data_len += sizeof(eq_freq);
} else {
u8 eq_gain = (eq_info->gain >> 20) & 0xFF;
memcpy(get_eq_info + data_len, &eq_gain, sizeof(eq_gain));
data_len += sizeof(eq_gain);
}
}
return data_len;
}
static u8 get_karaoke_eq_all_freq_info(u8 *get_eq_info)
{
return get_karaoke_eq_info(get_eq_info, 1);
}
static u8 get_karoke_eq_all_gain_info(u8 *get_eq_info)
{
return get_karaoke_eq_info(get_eq_info, 0);
}
static int karaoke_eq_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u16 data_len = *((u16 *) setting_data_len);
if (data_len > sizeof(g_karaoke_setting_info)) {
data_len = get_karaoke_eq_all_freq_info(setting_data);
} else {
data_len = get_karaoke_eq_setting(setting_data);
}
return data_len;
}
static RCSP_SETTING_OPT karaoke_eq_opt = {
.data_len = 9,
.setting_type = ATTR_TYPE_KARAOKE_EQ_SETTING,
.syscfg_id = VM_KARAOKE_EQ_SETTING,
.deal_opt_setting = deal_karaoke_eq_setting,
.set_setting = set_karaoke_eq_setting,
.get_setting = get_karaoke_eq_setting,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
.custom_setting_release = NULL,
.set_setting_extra_handle = NULL,
.get_setting_extra_handle = karaoke_eq_get_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(karaoke_eq_opt);
#endif
@@ -0,0 +1,608 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_karaoke_setting.data.bss")
#pragma data_seg(".rcsp_karaoke_setting.data")
#pragma const_seg(".rcsp_karaoke_setting.text.const")
#pragma code_seg(".rcsp_karaoke_setting.text")
#endif
#include "rcsp_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "rcsp_device_status.h"
#if (SOUNDCARD_ENABLE && RCSP_MODE && RCSP_ADV_KARAOKE_SET_ENABLE)
#include "key_event_deal.h"
#include "mic_effect.h"
#include "JL_rcsp_packet.h"
#include "soundcard/soundcard.h"
// mask : 8byte
// 音效 : index(1byte) + value(2byte)
// 气氛 : index(1byte) + value(2byte)
// 参数 : [index(1byte) + value(2byte)] * 7
#define KARAOKE_SETTING_SIZE (8 + ((1 + 2) * 2) + ((1 + 2) * 7))
#define KARAOKE_SETTING_ATMOSPHERE_TYPE_SET 0
enum karaoke_setting_index {
// 音效
KARAOKE_SETTING_SOUND_EFFECT_NORMAL = 0,
KARAOKE_SETTING_SOUND_EFFECT_BOY = 1,
KARAOKE_SETTING_SOUND_EFFECT_GRIL = 2,
KARAOKE_SETTING_SOUND_EFFECT_KIDS = 3,
KARAOKE_SETTING_SOUND_EFFECT_MAGIC = 4,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR = 5,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Ashop_MAJOR = 6,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_B_MAJOR = 7,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_C_MAJOR = 8,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Cshop_MAJOR = 9,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_D_MAJOR = 10,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Dshop_MAJOR = 11,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_E_MAJOR = 12,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_F_MAJOR = 13,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Fshop_MAJOR = 14,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_G_MAJOR = 15,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Gshop_MAJOR = 16,
// 气氛
KARAOKE_SETTING_ATMOSPHERE_CHEERS = 17,
KARAOKE_SETTING_ATMOSPHERE_EMBARRASSED = 18,
KARAOKE_SETTING_ATMOSPHERE_GUNFIRE = 19,
KARAOKE_SETTING_ATMOSPHERE_DESPISE = 20,
KARAOKE_SETTING_ATMOSPHERE_OPEN = 21,
KARAOKE_SETTING_ATMOSPHERE_KISS = 22,
KARAOKE_SETTING_ATMOSPHERE_LAUGHTER = 23,
KARAOKE_SETTING_ATMOSPHERE_APPLAUSE = 24,
KARAOKE_SETTING_ATMOSPHERE_PAY_ATTENTION_TO = 25,
KARAOKE_SETTING_ATMOSPHERE_MUA = 26,
KARAOKE_SETTING_ATMOSPHERE_A_THIEF = 27,
KARAOKE_SETTING_ATMOSPHERE_IF_YOU_ARE_THE_ONE = 28,
// 参数
KARAOKE_SETTING_MIC_PARAM_MIC_VOL = 29,
KARAOKE_SETTING_MIC_PARAM_RECORD_VOL = 30,
KARAOKE_SETTING_MIC_PARAM_REVERBERATION = 31,
KARAOKE_SETTING_MIC_PARAM_HIGH = 32,
KARAOKE_SETTING_MIC_PARAM_BASS = 33,
KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL = 34,
KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL = 35,
// 其他
KARAOKE_SETTING_OTHER_EFFECT_POPPING = 36,
KARAOKE_SETTING_OTHER_EFFECT_SHOUT = 37,
KARAOKE_SETTING_OTHER_EFFECT_DODGE = 38,
KARAOKE_SETTING_INDEX_END,
};
enum {
APP_PITCH_NONE = 0,
APP_PITCH_BOY,
APP_PITCH_GIRL,
APP_PITCH_KIDS,
APP_PITCH_MAGIC,
/* 电音 */
APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_Ashop_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_B_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_C_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_Cshop_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_D_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_Dshop_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_E_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_F_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_Fshop_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_G_MAJOR,
APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR,
APP_SOUNDCARD_MODE_BOOM, // 爆音
APP_SOUNDCARD_MODE_SHOUTING_WHEAT, // 喊麦
APP_SOUNDCARD_MODE_DODGE, // 闪避
};
const static u8 g_mutex_type_table[] = {
KARAOKE_SETTING_SOUND_EFFECT_NORMAL,
KARAOKE_SETTING_SOUND_EFFECT_BOY,
KARAOKE_SETTING_SOUND_EFFECT_GRIL,
KARAOKE_SETTING_SOUND_EFFECT_KIDS,
KARAOKE_SETTING_SOUND_EFFECT_MAGIC,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Ashop_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_B_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_C_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Cshop_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_D_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Dshop_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_E_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_F_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Fshop_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_G_MAJOR,
KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Gshop_MAJOR,
KARAOKE_SETTING_OTHER_EFFECT_POPPING,
KARAOKE_SETTING_OTHER_EFFECT_SHOUT
};
const static u8 g_atmosphere_type_table[] = {
KARAOKE_SETTING_ATMOSPHERE_CHEERS,
KARAOKE_SETTING_ATMOSPHERE_EMBARRASSED,
KARAOKE_SETTING_ATMOSPHERE_GUNFIRE,
KARAOKE_SETTING_ATMOSPHERE_DESPISE,
KARAOKE_SETTING_ATMOSPHERE_OPEN,
KARAOKE_SETTING_ATMOSPHERE_KISS,
KARAOKE_SETTING_ATMOSPHERE_LAUGHTER,
KARAOKE_SETTING_ATMOSPHERE_APPLAUSE,
KARAOKE_SETTING_ATMOSPHERE_PAY_ATTENTION_TO,
KARAOKE_SETTING_ATMOSPHERE_MUA,
KARAOKE_SETTING_ATMOSPHERE_A_THIEF,
KARAOKE_SETTING_ATMOSPHERE_IF_YOU_ARE_THE_ONE
};
const static u8 g_common_type_table[] = {
KARAOKE_SETTING_OTHER_EFFECT_DODGE
};
const static u8 g_value_type_table[] = {
KARAOKE_SETTING_MIC_PARAM_MIC_VOL,
KARAOKE_SETTING_MIC_PARAM_RECORD_VOL,
KARAOKE_SETTING_MIC_PARAM_REVERBERATION,
KARAOKE_SETTING_MIC_PARAM_HIGH,
KARAOKE_SETTING_MIC_PARAM_BASS,
KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL,
KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL
};
#pragma pack(1)
typedef struct {
u8 mask[8];
u8 mic_vol_index;
u16 mic_vol_value;
u8 mic_record_index;
u16 mic_record_value;
u8 mic_reververation_index;
u16 mic_reververation_value;
u8 mic_high_index;
u16 mic_high_value;
u8 mic_low_index;
u16 mic_low_value;
u8 mic_accompaniment_index;
u16 mic_accompaniment_value;
u8 mic_moitor_index;
u16 mic_moitor_value;
} karaoke_setting;
#pragma pack()
static u8 g_update_index_record = -1;
static karaoke_setting g_karaoke_setting = {0};
extern u8 get_curr_soundcard_pitch_by_value(void);
extern u8 get_curr_soundcard_pitch(void);
extern u8 curr_soundcard_mode_is_normal(void);
static void karaoke_setting_mask_set_bit(u8 *mask, u8 index, u8 type)
{
if (type) {
mask[index / 8] |= BIT(index % 8);
} else {
mask[index / 8] &= ~BIT(index % 8);
}
}
static int karaoke_setting_setting_init(void)
{
// 不读VM
// 需要从接口获取初始值并填充
// mic_vol_index
g_karaoke_setting.mic_vol_index = KARAOKE_SETTING_MIC_PARAM_MIC_VOL;
g_karaoke_setting.mic_vol_value = soundcard_get_mic_vol();
// mic_record_index
g_karaoke_setting.mic_record_index = KARAOKE_SETTING_MIC_PARAM_RECORD_VOL;
g_karaoke_setting.mic_record_value = soundcard_get_rec_vol();
// mic_reververation_index
g_karaoke_setting.mic_reververation_index = KARAOKE_SETTING_MIC_PARAM_REVERBERATION;
g_karaoke_setting.mic_reververation_value = soundcard_get_reverb_wet_vol();
// mic_high_index
g_karaoke_setting.mic_high_index = KARAOKE_SETTING_MIC_PARAM_HIGH;
g_karaoke_setting.mic_high_value = soundcard_get_high_sound_vol();
// mic_low_index
g_karaoke_setting.mic_low_index = KARAOKE_SETTING_MIC_PARAM_BASS;
g_karaoke_setting.mic_low_value = soundcard_get_low_sound_vol();
// mic_accompaniment_index
g_karaoke_setting.mic_accompaniment_index = KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL;
g_karaoke_setting.mic_accompaniment_value = soundcard_get_music_vol();
// mic_moitor_index
g_karaoke_setting.mic_moitor_index = KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL;
g_karaoke_setting.mic_moitor_value = soundcard_get_earphone_vol();
// effect_index
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, KARAOKE_SETTING_SOUND_EFFECT_NORMAL, 1);
// atomsphere_index
#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, KARAOKE_SETTING_ATMOSPHERE_CHEERS, 1);
#endif
return 0;
}
static void set_karaoke_setting_setting(u8 *karaoke_setting)
{
memcpy(&g_karaoke_setting, karaoke_setting, sizeof(g_karaoke_setting));
}
static int get_karaoke_setting_setting(u8 *karaoke_setting)
{
memcpy(karaoke_setting, &g_karaoke_setting, sizeof(g_karaoke_setting));
return sizeof(g_karaoke_setting);
}
static int karaoke_setting_set_value(u8 *data, u8 index, u16 value)
{
int offset = 0;
data[offset++] = index;
data[offset++] = ((u8 *)&value)[1];
data[offset++] = ((u8 *)&value)[0];
return offset;
}
static int karaoke_get_setting_extra_handle(void *setting_data, void *setting_data_len)
{
// 全局变量g_karaoke_setting已经把值都存好,只需要进行大小端转化即可
int offset = 0;
u8 *data = (u8 *)setting_data;
for (; offset < sizeof(g_karaoke_setting.mask); offset ++) {
data[sizeof(g_karaoke_setting.mask) - offset - 1] = g_karaoke_setting.mask[offset];
}
if ((u8) - 1 == g_update_index_record) {
// mic_vol_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_vol_index, g_karaoke_setting.mic_vol_value);
// mic_record_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_record_index, g_karaoke_setting.mic_record_value);
// mic_reververation_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_reververation_index, g_karaoke_setting.mic_reververation_value);
// mic_high_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_high_index, g_karaoke_setting.mic_high_value);
// mic_low_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_low_index, g_karaoke_setting.mic_low_value);
// mic_accompaniment_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_accompaniment_index, g_karaoke_setting.mic_accompaniment_value);
// mic_moitor_value
offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_moitor_index, g_karaoke_setting.mic_moitor_value);
} else {
switch (g_update_index_record) {
case KARAOKE_SETTING_MIC_PARAM_MIC_VOL:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_vol_value);
break;
case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_record_value);
break;
case KARAOKE_SETTING_MIC_PARAM_REVERBERATION:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_reververation_value);
break;
case KARAOKE_SETTING_MIC_PARAM_HIGH:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_high_value);
break;
case KARAOKE_SETTING_MIC_PARAM_BASS:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_low_value);
break;
case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_accompaniment_value);
break;
case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL:
offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_moitor_value);
break;
}
g_update_index_record = -1;
}
return offset;
}
static bool karaoke_setting_table_check(u8 index, u8 *table, u8 table_len)
{
for (u8 i = 0; i < table_len; i++) {
if (index == table[i]) {
return true;
}
}
return false;
}
static bool karaoke_setting_mask_set(u8 index, u8 *table, u8 table_len)
{
if (karaoke_setting_table_check(index, table, table_len)) {
for (u8 i = 0; i < table_len; i++) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, table[i], 0);
}
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, index, 1);
return true;
}
return false;
}
static int karaoke_set_setting_extra_handle(void *setting_data, void *setting_data_len)
{
u16 data_len = *((u16 *) setting_data_len) - 1;
u8 *data = (u8 *) setting_data;
u8 i = 0;
while (i < data_len) {
u8 index = data[i++];
u16 value = data[i++] << 8 | data[i++];
karaoke_setting_mask_set(index, g_mutex_type_table, sizeof(g_mutex_type_table));
#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET
karaoke_setting_mask_set(index, g_atmosphere_type_table, sizeof(g_atmosphere_type_table));
#endif
if (karaoke_setting_table_check(index, g_common_type_table, sizeof(g_common_type_table))) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, index, 1);
}
karaoke_setting_mask_set(index, g_value_type_table, sizeof(g_value_type_table));
g_update_index_record = index;
switch (index) {
case KARAOKE_SETTING_MIC_PARAM_MIC_VOL:
g_karaoke_setting.mic_vol_index = index;
g_karaoke_setting.mic_vol_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL:
g_karaoke_setting.mic_record_index = index;
g_karaoke_setting.mic_record_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_REVERBERATION:
g_karaoke_setting.mic_reververation_index = index;
g_karaoke_setting.mic_reververation_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_HIGH:
g_karaoke_setting.mic_high_index = index;
g_karaoke_setting.mic_high_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_BASS:
g_karaoke_setting.mic_low_index = index;
g_karaoke_setting.mic_low_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL:
g_karaoke_setting.mic_accompaniment_index = index;
g_karaoke_setting.mic_accompaniment_value = value;
break;
case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL:
g_karaoke_setting.mic_moitor_index = index;
g_karaoke_setting.mic_moitor_value = value;
break;
}
}
return 0;
}
static void update_karaoke_setting_vm_value(u8 *karaoke_setting)
{
// 不写VM
}
static void karaoke_setting_sync(u8 *color_led_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_KARAOKE_SETTING);
}
#endif
}
static void karaoke_setting_update(void)
{
switch (g_update_index_record) {
case KARAOKE_SETTING_MIC_PARAM_MIC_VOL:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_MIC, g_karaoke_setting.mic_vol_value);
break;
case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_RECORD_VOL, g_karaoke_setting.mic_record_value);
break;
case KARAOKE_SETTING_MIC_PARAM_REVERBERATION:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_WET_GAIN, g_karaoke_setting.mic_reververation_value);
break;
case KARAOKE_SETTING_MIC_PARAM_HIGH:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_HIGH_SOUND, g_karaoke_setting.mic_high_value);
break;
case KARAOKE_SETTING_MIC_PARAM_BASS:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_LOW_SOUND, g_karaoke_setting.mic_low_value);
break;
case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_MUSIC_VOL, g_karaoke_setting.mic_accompaniment_value);
break;
case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL:
app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_EARPHONE_VOL, g_karaoke_setting.mic_moitor_value);
break;
case KARAOKE_SETTING_OTHER_EFFECT_POPPING:
app_task_put_key_msg(KEY_SOUNDCARD_MODE_BOOM, 0);
break;
case KARAOKE_SETTING_SOUND_EFFECT_MAGIC:
app_task_put_key_msg(KEY_SOUNDCARD_MODE_MAGIC, 0);
break;
case KARAOKE_SETTING_OTHER_EFFECT_SHOUT:
app_task_put_key_msg(KEY_SOUNDCARD_MODE_SHOUTING_WHEAT, 0);
break;
case KARAOKE_SETTING_OTHER_EFFECT_DODGE:
app_task_put_key_msg(KEY_SOUNDCARD_MODE_DODGE, 0);
break;
default:
if (karaoke_setting_table_check(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table))) {
app_task_put_key_msg(KEY_SOUNDCARD_MODE_PITCH_BY_VALUE, g_update_index_record);
break;
} else if (karaoke_setting_table_check(g_update_index_record, g_atmosphere_type_table, sizeof(g_atmosphere_type_table))) {
app_task_put_key_msg(KEY_SOUNDCARD_MAKE_NOISE0 + g_update_index_record - KARAOKE_SETTING_ATMOSPHERE_CHEERS, 0);
break;
}
break;
}
/* g_update_index_record = -1; */
}
static void deal_karaoke_setting(u8 *karaoke_setting, u8 write_vm, u8 tws_sync)
{
if (karaoke_setting) {
set_karaoke_setting_setting(karaoke_setting);
}
if (write_vm) {
update_karaoke_setting_vm_value(karaoke_setting);
}
if (tws_sync) {
karaoke_setting_sync(karaoke_setting);
}
karaoke_setting_update();
}
static int karaoke_setting_key_event_update(int event, void *param)
{
int ret = false;
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL || 0 == JL_rcsp_get_auth_flag()) {
return ret;
}
switch (event) {
case KEY_SOUNDCARD_MAKE_NOISE0:
case KEY_SOUNDCARD_MAKE_NOISE1:
case KEY_SOUNDCARD_MAKE_NOISE2:
case KEY_SOUNDCARD_MAKE_NOISE3:
case KEY_SOUNDCARD_MAKE_NOISE4:
case KEY_SOUNDCARD_MAKE_NOISE5:
case KEY_SOUNDCARD_MAKE_NOISE6:
case KEY_SOUNDCARD_MAKE_NOISE7:
case KEY_SOUNDCARD_MAKE_NOISE8:
case KEY_SOUNDCARD_MAKE_NOISE9:
case KEY_SOUNDCARD_MAKE_NOISE10:
case KEY_SOUNDCARD_MAKE_NOISE11:
g_update_index_record = KARAOKE_SETTING_ATMOSPHERE_CHEERS + event - KEY_SOUNDCARD_MAKE_NOISE0;
#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET
karaoke_setting_mask_set(g_update_index_record, g_atmosphere_type_table, sizeof(g_atmosphere_type_table));
#endif
ret = true;
break;
case KEY_SOUNDCARD_MODE_PITCH:
g_update_index_record = get_curr_soundcard_pitch();
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
ret = true;
break;
case KEY_SOUNDCARD_MODE_PITCH_BY_VALUE:
g_update_index_record = get_curr_soundcard_pitch_by_value();
switch (g_update_index_record) {
case APP_SOUNDCARD_MODE_BOOM:
karaoke_setting_mask_set(KARAOKE_SETTING_OTHER_EFFECT_POPPING, g_mutex_type_table, sizeof(g_mutex_type_table));
break;
case APP_SOUNDCARD_MODE_SHOUTING_WHEAT:
karaoke_setting_mask_set(KARAOKE_SETTING_OTHER_EFFECT_SHOUT, g_mutex_type_table, sizeof(g_mutex_type_table));
break;
default:
if (g_update_index_record >= APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR && g_update_index_record <= APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR) {
karaoke_setting_mask_set(g_update_index_record - APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR, g_mutex_type_table, sizeof(g_mutex_type_table));
break;
}
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
break;
}
ret = true;
break;
case KEY_SOUNDCARD_MODE_BOOM:
g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_POPPING;
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
if (curr_soundcard_mode_is_normal()) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0);
}
ret = true;
break;
case KEY_SOUNDCARD_MODE_SHOUTING_WHEAT:
g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_SHOUT;
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
if (curr_soundcard_mode_is_normal()) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0);
}
ret = true;
case KEY_SOUNDCARD_MODE_DODGE:
g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_DODGE;
if (mic_dodge_get_status()) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 1);
} else {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0);
}
ret = true;
break;
case KEY_SOUNDCARD_MODE_ELECTRIC:
g_update_index_record = get_curr_soundcard_pitch_by_value();
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
ret = true;
break;
case KEY_SOUNDCARD_MODE_MAGIC:
g_update_index_record = KARAOKE_SETTING_SOUND_EFFECT_MAGIC;
karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table));
if (curr_soundcard_mode_is_normal()) {
karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0);
}
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_MIC:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_MIC_VOL;
g_karaoke_setting.mic_vol_value = soundcard_get_mic_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_LOW_SOUND:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_BASS;
// 更新对应全局变量
g_karaoke_setting.mic_low_value = soundcard_get_low_sound_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_HIGH_SOUND:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_HIGH;
// 更新对应全局变量
g_karaoke_setting.mic_high_value = soundcard_get_high_sound_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_WET_GAIN:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_REVERBERATION;
g_karaoke_setting.mic_reververation_value = soundcard_get_reverb_wet_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_RECORD_VOL:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_RECORD_VOL;
// 更新对应全局变量
g_karaoke_setting.mic_record_value = soundcard_get_rec_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_MUSIC_VOL:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL;
// 更新对应全局变量
g_karaoke_setting.mic_accompaniment_value = soundcard_get_music_vol();
ret = true;
break;
case KEY_SOUNDCARD_SLIDE_EARPHONE_VOL:
g_update_index_record = KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL;
// 更新对应全局变量
g_karaoke_setting.mic_moitor_value = soundcard_get_earphone_vol();
ret = true;
break;
}
if (ret) {
RCSP_UPDATE(COMMON_FUNCTION, BIT(RCSP_DEVICE_STATUS_ATTR_TYPE_KARAOKE_SETTING_INFO));
}
return ret;
}
static RCSP_SETTING_OPT karaoke_setting_opt = {
.data_len = KARAOKE_SETTING_SIZE,
.setting_type = ATTR_TYPE_KARAOKE_SETTING,
.deal_opt_setting = deal_karaoke_setting,
.set_setting = set_karaoke_setting_setting,
.get_setting = get_karaoke_setting_setting,
.custom_setting_init = karaoke_setting_setting_init,
.set_setting_extra_handle = karaoke_set_setting_extra_handle,
.get_setting_extra_handle = karaoke_get_setting_extra_handle,
.custom_setting_key_event_update = karaoke_setting_key_event_update,
};
REGISTER_APP_SETTING_OPT(karaoke_setting_opt);
#endif
@@ -0,0 +1,70 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_misc_drc_setting.data.bss")
#pragma data_seg(".rcsp_misc_drc_setting.data")
#pragma const_seg(".rcsp_misc_drc_setting.text.const")
#pragma code_seg(".rcsp_misc_drc_setting.text")
#endif
#include "app_config.h"
#include "syscfg_id.h"
#include "rcsp_misc_setting.h"
#include "ble_rcsp_server.h"
#if (RCSP_MODE && RCSP_DRC_VAL_SETTING && TCFG_AUDIO_OUT_EQ_ENABLE && TCFG_DRC_ENABLE && TCFG_AUDIO_OUT_DRC_ENABLE && RCSP_ADV_EQ_SET_ENABLE)
#include "audio_dec.h"
extern int high_bass_drc_set_filter_info(int th);
static s16 drc_val = 0;
static int drc_setting_set(u8 *misc_setting, u8 is_conversion)
{
u32 offset = 0;
if (is_conversion) {
drc_val = misc_setting[offset++] << 8 | misc_setting[offset++];
drc_val = drc_val < 0 ? (drc_val + 61) : drc_val;
} else {
memcpy((u8 *)&drc_val, misc_setting, sizeof(drc_val));
offset += 2;
}
return offset;
}
static int drc_setting_get(u8 *misc_setting, u8 is_conversion)
{
u32 offset = 0;
if (is_conversion) {
drc_val = drc_val > 0 ? (drc_val - 61) : drc_val;
misc_setting[offset++] = (drc_val >> 8) & 0xFF;
misc_setting[offset++] = (drc_val) & 0xFF;
} else {
memcpy(misc_setting, (u8 *)&drc_val, sizeof(drc_val));
offset += 2;
}
return offset;
}
static int drc_state_update(u8 *misc_setting)
{
// 值不相同才设置
static s16 prev_drc_val = -1;
if (-1 == prev_drc_val || prev_drc_val != drc_val) {
high_bass_drc_set_filter_info(drc_val > 0 ? drc_val - 61 : drc_val);
prev_drc_val = drc_val;
}
return 0;
}
static RCSP_MISC_SETTING_OPT drc_setting_opt = {
.misc_data_len = 2,
.misc_setting_type = MISC_SETTING_DRC_VAL,
.misc_syscfg_id = CFG_RCSP_MISC_DRC_SETTING,
.misc_set_setting = drc_setting_set,
.misc_get_setting = drc_setting_get,
.misc_state_update = drc_state_update,
.misc_custom_setting_init = NULL,
.misc_custom_write_vm = NULL,
};
REGISTER_APP_MISC_SETTING_OPT(drc_setting_opt);
#endif
@@ -0,0 +1,158 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_misc_reverbration_setting.data.bss")
#pragma data_seg(".rcsp_misc_reverbration_setting.data")
#pragma const_seg(".rcsp_misc_reverbration_setting.text.const")
#pragma code_seg(".rcsp_misc_reverbration_setting.text")
#endif
#include "rcsp_misc_setting.h"
#include "app_config.h"
#if (RCSP_MODE && RCSP_REVERBERATION_SETTING && TCFG_MIC_EFFECT_ENABLE && RCSP_ADV_EQ_SET_ENABLE)
#include "syscfg_id.h"
#include "rcsp_setting_opt.h"
#include "ble_rcsp_server.h"
#include "mic_effect.h"
#include "key_event_deal.h"
extern void mic_effect_set_echo_delay(u32 delay);
extern u32 mic_effect_get_echo_delay(void);
extern void mic_effect_set_echo_decay(u32 decay);
extern u32 mic_effect_get_echo_decay(void);
extern u8 mic_effect_get_status(void);
#pragma pack(1)
struct t_reverbration {
u8 state;
u16 depth_val;
u16 strength_val;
};
#pragma pack()
static struct t_reverbration reverbration;
static int reverbration_setting_set(u8 *misc_setting, u8 is_conversion)
{
u32 offset = 0;
reverbration.state = misc_setting[offset++];
if (is_conversion) {
reverbration.depth_val = misc_setting[offset++] << 8 | misc_setting[offset++];
reverbration.strength_val = misc_setting[offset++] << 8 | misc_setting[offset++];
} else {
memcpy((u8 *)&reverbration.depth_val, misc_setting + offset, sizeof(reverbration.depth_val));
offset += 2;
memcpy((u8 *)&reverbration.strength_val, misc_setting + offset, sizeof(reverbration.strength_val));
offset += 2;
}
return offset;
}
static int reverbration_setting_get(u8 *misc_setting, u8 is_conversion)
{
u32 offset = 0;
misc_setting[offset++] = reverbration.state;
if (is_conversion) {
misc_setting[offset++] = (reverbration.depth_val >> 8) & 0xFF;
misc_setting[offset++] = (reverbration.depth_val) & 0xFF;
misc_setting[offset++] = (reverbration.strength_val >> 8) & 0xFF;
misc_setting[offset++] = (reverbration.strength_val) & 0xFF;
} else {
memcpy(misc_setting + offset, (u8 *)&reverbration.depth_val, sizeof(reverbration.depth_val));
offset += 2;
memcpy(misc_setting + offset, (u8 *)&reverbration.strength_val, sizeof(reverbration.strength_val));
offset += 2;
}
return offset;
}
static int reverbration_write_vm(u8 *misc_setting)
{
u8 reverbration_state = 0;
syscfg_read(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration_state, sizeof(reverbration_state));
if (reverbration_state != reverbration.state) {
syscfg_write(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration.state, sizeof(reverbration.state));
}
return 0;
}
static int reverbration_state_update(u8 *misc_setting)
{
// 值不相同才设置
static u16 prev_depth_val = -1;
static u16 prev_strength_val = -1;
if (reverbration.state != mic_effect_get_status()) {
app_task_put_key_msg(KEY_REVERB_OPEN, 0);
}
if (mic_effect_get_status() && (-1 == prev_depth_val || reverbration.depth_val != prev_depth_val)) {
mic_effect_set_echo_delay(reverbration.depth_val * 2);
prev_depth_val = reverbration.depth_val;
}
if (mic_effect_get_status() && (-1 == prev_strength_val || reverbration.strength_val != prev_strength_val)) {
mic_effect_set_echo_decay(reverbration.strength_val * 70 / 100);
prev_strength_val = reverbration.strength_val;
}
if (0 == mic_effect_get_status()) {
prev_depth_val = -1;
prev_strength_val = -1;
}
return 0;
}
static int reverbration_custom_setting_init(void)
{
u8 reverbration_state = 0;
if (sizeof(reverbration_state) == syscfg_read(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration_state, sizeof(reverbration_state))) {
reverbration.state = reverbration_state;
} else {
reverbration.state = mic_effect_get_status();
}
reverbration.depth_val = mic_effect_get_echo_delay() / 2;
reverbration.strength_val = mic_effect_get_echo_decay() * 100 / 70;
return 0;
}
static int reverbartion_key_event_callback_deal(u32 event, void *param)
{
int ret = false;
switch (event) {
case KEY_REVERB_OPEN:
reverbration.state = mic_effect_get_status();
reverbration_write_vm(NULL);
reverbration_state_update(NULL);
ret = true;
break;
}
return ret;
}
static RCSP_MISC_SETTING_OPT reverbration_setting_opt = {
.misc_data_len = 5,
.misc_syscfg_id = CFG_RCSP_MISC_REVERB_ON_OFF,
.misc_setting_type = MISC_SETTING_REVERBERATION,
.misc_set_setting = reverbration_setting_set,
.misc_get_setting = reverbration_setting_get,
.misc_state_update = reverbration_state_update,
.misc_custom_setting_init = reverbration_custom_setting_init,
.misc_custom_write_vm = reverbration_write_vm,
.misc_custom_key_event_callback_deal = reverbartion_key_event_callback_deal,
};
REGISTER_APP_MISC_SETTING_OPT(reverbration_setting_opt);
void rcsp_close_reverbrateion_state_and_update(void)
{
if (reverbration.state) {
app_task_put_key_msg(KEY_REVERB_OPEN, 0);
}
}
#else
void rcsp_close_reverbrateion_state_and_update(void)
{
}
#endif
@@ -0,0 +1,264 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_misc_setting.data.bss")
#pragma data_seg(".rcsp_misc_setting.data")
#pragma const_seg(".rcsp_misc_setting.text.const")
#pragma code_seg(".rcsp_misc_setting.text")
#endif
#include "rcsp_misc_setting.h"
#include "app_config.h"
#if (RCSP_MODE && RCSP_REVERBERATION_SETTING && TCFG_MIC_EFFECT_ENABLE && RCSP_ADV_EQ_SET_ENABLE)
#include "syscfg_id.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "ble_rcsp_server.h"
#include "rcsp_config.h"
#include "rcsp_device_status.h"
extern int get_bt_tws_connect_status();
static int misc_setting_init(void);
static int get_misc_setting_info(u8 *misc_setting);
static int set_misc_setting_extra_handle(void *setting_data, void *param);
static void set_misc_setting_info(u8 *misc_setting);
static void deal_misc_setting(u8 *misc_setting, u8 write_vm, u8 tws_sync);
static RCSP_SETTING_OPT misc_setting_opt = {
.data_len = 0,
.setting_type = ATTR_TYPE_MISC_SETTING,
.deal_opt_setting = deal_misc_setting,
.set_setting = set_misc_setting_info,
.get_setting = get_misc_setting_info,
.custom_setting_init = misc_setting_init,
.set_setting_extra_handle = set_misc_setting_extra_handle,
};
REGISTER_APP_SETTING_OPT(misc_setting_opt);
static RCSP_MISC_SETTING_OPT *g_misc_opt_link_head = NULL;
static u32 g_misc_setting_update_type = -1;
int rcsp_register_setting_misc_setting(void *misc_setting)
{
// 需要排序
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
RCSP_MISC_SETTING_OPT *item = (RCSP_MISC_SETTING_OPT *)misc_setting;
RCSP_MISC_SETTING_OPT *existed_item = NULL;
while (misc_opt && item) {
if (misc_opt->misc_setting_type == item->misc_setting_type) {
return 0;
} else if (item->misc_setting_type > misc_opt->misc_setting_type) {
existed_item = misc_opt;
}
misc_opt = misc_opt->next;
}
if (!g_misc_opt_link_head) {
item->next = g_misc_opt_link_head;
g_misc_opt_link_head = item;
return 0;
} else if (item && existed_item) {
item->next = existed_item->next;
existed_item->next = item;
return 0;
}
return -1;
}
static int misc_setting_init(void)
{
u32 total_len = sizeof(u32); // 1个mask的长度
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
while (misc_opt) {
u8 *data = zalloc(misc_opt->misc_data_len);
if (misc_opt->misc_custom_setting_init) {
misc_opt->misc_custom_setting_init();
} else if (rcsp_read_data_from_vm(misc_opt->misc_syscfg_id, data, misc_opt->misc_data_len)) {
if (misc_opt->misc_set_setting) {
misc_opt->misc_set_setting(data, 0);
}
}
if (data) {
free(data);
}
total_len += misc_opt->misc_data_len;
misc_opt = misc_opt->next;
}
if (g_misc_opt_link_head && g_misc_opt_link_head != misc_opt) {
misc_setting_opt.data_len = total_len;
deal_misc_setting(NULL, 0, 0);
}
return 0;
}
static int get_misc_setting_info(u8 *misc_setting)
{
u32 mask = 0;
u32 offset = sizeof(mask);
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
u32 update_mics_setting_type = g_misc_setting_update_type;
g_misc_setting_update_type = -1;
while (misc_opt) {
if (update_mics_setting_type & BIT(misc_opt->misc_setting_type)) {
if (misc_opt->misc_get_setting) {
misc_opt->misc_get_setting(misc_setting + offset, 1);
}
offset += misc_opt->misc_data_len;
mask |= BIT(misc_opt->misc_setting_type);
}
misc_opt = misc_opt->next;
}
misc_setting[0] = (mask >> 24) & 0xFF;
misc_setting[1] = (mask >> 16) & 0xFF;
misc_setting[2] = (mask >> 8) & 0xFF;
misc_setting[3] = (mask) & 0xFF;
return offset;
}
static int set_misc_setting_extra_handle(void *setting_data, void *param)
{
u8 *misc_setting = (u8 *)setting_data;
u32 mask = (misc_setting[0] << 24 | misc_setting[1] << 16 | misc_setting[2] << 8 | misc_setting[3]);
if (0 == mask) {
return -1;
}
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
u32 update_mics_setting_type = 0;
while (misc_opt) {
if (mask & BIT(misc_opt->misc_setting_type) && misc_opt->be_notify_app) {
update_mics_setting_type |= BIT(misc_opt->misc_setting_type);
}
misc_opt = misc_opt->next;
}
if (!param && update_mics_setting_type) {
g_misc_setting_update_type = update_mics_setting_type;
}
return 0;
}
static u32 g_set_mask = -1;
static void set_misc_setting_info(u8 *misc_setting)
{
u32 offset = 4;
g_set_mask = (misc_setting[0] << 24 | misc_setting[1] << 16 | misc_setting[2] << 8 | misc_setting[3]);
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
while (misc_opt) {
if (g_set_mask & BIT(misc_opt->misc_setting_type)) {
if (misc_opt->misc_set_setting) {
misc_opt->misc_set_setting(misc_setting + offset, 1);
}
offset += misc_opt->misc_data_len;
}
misc_opt = misc_opt->next;
}
}
static int write_misc_setting_vm_value(int syscfg_id, u8 *data, u32 data_len)
{
if (!data_len) {
goto end;
}
u8 *vm_data = zalloc(data_len);
syscfg_read(syscfg_id, vm_data, data_len);
if (memcmp(vm_data, data, data_len)) {
syscfg_write(syscfg_id, data, data_len);
}
if (vm_data) {
free(vm_data);
}
end:
return 0;
}
static void update_misc_setting_vm_value(u8 *misc_setting)
{
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
while (misc_opt) {
if (g_set_mask & BIT(misc_opt->misc_setting_type)) {
if (misc_opt->misc_custom_write_vm) {
misc_opt->misc_custom_write_vm(misc_setting);
} else if (misc_opt->misc_syscfg_id && misc_opt->misc_get_setting) {
u8 *data = zalloc(misc_opt->misc_data_len);
misc_opt->misc_get_setting(data, 0);
write_misc_setting_vm_value(misc_opt->misc_syscfg_id, data, misc_opt->misc_data_len);
if (data) {
free(data);
}
}
}
misc_opt = misc_opt->next;
}
}
static void misc_setting_sync(u8 *misc_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_MISC_SETTING);
}
#endif
}
static void misc_setting_state_update(u8 *misc_setting)
{
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
while (misc_opt) {
if (g_set_mask & BIT(misc_opt->misc_setting_type)) {
if (misc_opt->misc_state_update) {
misc_opt->misc_state_update(misc_setting);
}
}
misc_opt = misc_opt->next;
}
}
static void deal_misc_setting(u8 *misc_setting, u8 write_vm, u8 tws_sync)
{
if (misc_setting) {
set_misc_setting_info(misc_setting);
}
if (write_vm) {
update_misc_setting_vm_value(misc_setting);
}
if (tws_sync) {
misc_setting_sync(misc_setting);
}
misc_setting_state_update(misc_setting);
}
u32 rcsp_get_misc_setting_data_len(void)
{
return misc_setting_opt.data_len;
}
int rcsp_misc_event_deal(u32 event, void *param)
{
RCSP_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head;
while (misc_opt) {
if (misc_opt->misc_custom_key_event_callback_deal && misc_opt->misc_custom_key_event_callback_deal(event, param)) {
if (misc_opt->be_notify_app) {
RCSP_UPDATE(COMMON_FUNCTION, BIT(RCSP_DEVICE_STATUS_ATTR_TYPE_MISC_SETTING_INFO));
}
return true;
}
misc_opt = misc_opt->next;
}
g_misc_setting_update_type = -1;
return false;
}
#else
u32 rcsp_get_misc_setting_data_len(void)
{
return 0;
}
int rcsp_misc_event_deal(u32 event, void *param)
{
return false;
}
#endif
@@ -0,0 +1,54 @@
#ifndef __RCSP_MISC_SETTING__
#define __RCSP_MISC_SETTING__
#include "system/includes.h"
#define REGISTER_APP_MISC_SETTING_OPT(rcsp_misc_opt) \
int rcsp_misc_opt##_setting_init(void) {\
return rcsp_register_setting_misc_setting(&rcsp_misc_opt);\
}\
late_initcall(rcsp_misc_opt##_setting_init);
enum {
MISC_SETTING_REVERBERATION = 0,
MISC_SETTING_DRC_VAL = 1,
MISC_SETTING_KARAOKE_SOUND_EFFECT = 2,
MISC_SETTING_KARAOKE_ATMOSPHERE = 3,
MISC_SETTING_KARAOKE_SOUND_PARAM = 4,
MISC_SETTING_MASK_MAX = 32, // 最多只支持32个
};
#pragma pack(1)
typedef struct _RCSP_MISC_SETTING_OPT {
struct _RCSP_MISC_SETTING_OPT *next;
bool be_notify_app; // 接收到数据并更新效果完后是否需要通知app, 如果需要通知app则置1
u32 misc_data_len;
int misc_setting_type;
int misc_syscfg_id;
// misc_set_setting函数参数:
// misc_setting : 传入数据
// is_conversion : 1 - 需要转换,从大端转为小端
// 0 - 不需要转换
int (*misc_set_setting)(u8 *misc_setting, u8 is_conversion);
// misc_get_setting函数参数:
// misc_setting : 传出数据
// is_conversion : 1 - 需要转换,从小端转为大端
// 0 - 不需要转换
int (*misc_get_setting)(u8 *misc_setting, u8 is_conversion);
int (*misc_state_update)(u8 *misc_setting); // 参数用于判断当前更新是设置状态(非空)还是初始化/同步(未空)
// 上面是必填,下面是选填
int (*misc_custom_setting_init)(void);
int (*misc_custom_write_vm)(u8 *misc_setting);
int (*misc_custom_key_event_callback_deal)(u32 event, void *param);
} RCSP_MISC_SETTING_OPT;
#pragma pack()
int rcsp_register_setting_misc_setting(void *misc_setting);
int rcsp_misc_event_deal(u32 event, void *param);
// 获取混响数据的长度
u32 rcsp_get_misc_setting_data_len(void);
#endif
@@ -0,0 +1,573 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_music_info_setting.data.bss")
#pragma data_seg(".rcsp_music_info_setting.data")
#pragma const_seg(".rcsp_music_info_setting.text.const")
#pragma code_seg(".rcsp_music_info_setting.text")
#endif
#include "rcsp_music_info_setting.h"
#include "rcsp_config.h"
#include "syscfg_id.h"
#include "ble_rcsp_server.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "rcsp_bt_manage.h"
#include "btstack/avctp_user.h"
#include "bt_tws.h"
#include "rcsp_functions/rcsp_config.h"
#if (RCSP_MODE && RCSP_ADV_MUSIC_INFO_ENABLE)
struct music_info_t {
u8 title_len;
char title[64];
u8 artist_len;
char artist[64];
u8 album_len;
char album[64];
u8 num_len;
char number;
u8 total_len;
char total[2];
u8 genre_len;
char genre[16];
char time[8];
u8 player_state;
u8 player_time_min;
u8 player_time_sec;
u32 curr_player_time;
u8 player_time_en;
u32 total_time;
volatile int get_music_player_timer;
};
static struct music_info_t music_info;
void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size);
static u8 rcsp_adv_music_info_vaild(void);
u8 get_player_time_en(void)
{
return music_info.player_time_en;
}
void set_player_time_en(u8 en)
{
music_info.player_time_en = en;
}
void reset_player_time_en(void)
{
music_player_time_timer_deal(music_info.player_time_en);
}
void music_player_time_deal(void *priv)
{
#if TCFG_USER_TWS_ENABLE
// 通知从机同步状态
if (get_bt_tws_connect_status() && TWS_ROLE_MASTER != tws_api_get_role()) {
return;
}
#endif
if (BT_STATUS_PLAYING_MUSIC == bt_get_connect_status()) {
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_PLAY_TIME, 0, NULL);
}
}
void get_music_info(void)
{
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_MUSIC_INFO, 0, NULL);
}
void btstack_avrcp_ch_creat_ok(void)
{
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
//printf("\n\n\n\nrcsp ge music info\n");
tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_INFO, 300);
} else {
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) {
//printf("\n\n\nno tws rcsp ge music info\n\n");
get_music_info();
}
}
}
char *get_music_title(void)
{
return music_info.title;
}
u8 get_music_title_len(void)
{
return music_info.title_len;
}
char *get_music_artist(void)
{
return music_info.artist;
}
u8 get_music_artist_len(void)
{
return music_info.artist_len;
}
char *get_music_album(void)
{
return music_info.album;
}
u8 get_music_album_len(void)
{
return music_info.album_len;
}
char *get_music_number(void)
{
return &music_info.number;
}
u8 get_music_number_len(void)
{
return music_info.num_len;
}
char *get_music_total(void)
{
return music_info.total;
}
u8 get_music_total_len(void)
{
return music_info.total_len;
}
char *get_music_genre(void)
{
return music_info.genre;
}
u8 get_music_genre_len(void)
{
return music_info.genre_len;
}
u16 get_music_total_time(void)
{
return (music_info.total_time / 1000);
}
u32 get_music_curr_time(void)
{
return music_info.curr_player_time;
/* return (music_info.player_time_min * 60 + music_info.player_time_sec); */
}
u8 bt_music_total_time(u32 time)
{
music_info.total_time = time;
/* printf("get music time %d\n", music_info.total_time); */
return 0;
}
u8 get_music_player_state(void)
{
return music_info.player_state;
}
void rcsp_update_player_state(void)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (1 == rcspModel->A_platform && rcsp_adv_music_info_vaild()) {
return;
}
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_STATE, NULL, 0);
}
void bt_status_change(u8 state)
{
if (BT_STATUS_PLAYING_MUSIC == state) {
music_info.player_state = 1;
} else {
music_info.player_state = 0;
}
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) {
rcsp_update_player_state();
} else {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_PLAYER_STATE, 300);
} else {
tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_PLAYER_TIEM_EN, 300);
}
}
}
void stop_get_music_timer(u8 en)
{
if (en) {
music_info.player_time_en = 0;
}
if (music_info.get_music_player_timer) {
sys_timeout_del(music_info.get_music_player_timer);
music_info.get_music_player_timer = 0;
}
}
#if TCFG_USER_TWS_ENABLE
#define TWS_FUNC_ID_RCSP_MUSIC_EN \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'P' + 'I') << (2 * 8)) | \
((u8)('M' + 'U') << (1 * 8)) | \
((u8)('E' + 'N') << (0 * 8)))
static void deal_music_en_in_task(void *_data, u16 len)
{
u8 *data = (u8 *)_data;
u8 en = *data;
/* printf("music_en===================:%d\n", en); */
music_player_time_timer_deal(en);
free(data);
}
static void rcsp_music_en_in_irq(void *_data, u16 len, bool rx)
{
if (rx) {
u8 *buf = malloc(len);
ASSERT(buf, "rcsp_music_en_in_irq malloc err!\n");
int msg[] = {(int)deal_music_en_in_task, 2, (int)buf, len};
memcpy(buf, _data, len);
os_taskq_post_type("app_core", Q_CALLBACK, ARRAY_SIZE(msg), msg);
}
}
REGISTER_TWS_FUNC_STUB(tws_rcsp_music_en) = {
.func_id = TWS_FUNC_ID_RCSP_MUSIC_EN,
.func = rcsp_music_en_in_irq,
};
#endif
void music_player_time_timer_deal(u8 en)
{
#if TCFG_USER_TWS_ENABLE
// 通知从机同步状态
if (get_bt_tws_connect_status() && TWS_ROLE_MASTER == tws_api_get_role()) {
tws_api_send_data_to_sibling((void *)&en, 1, TWS_FUNC_ID_RCSP_MUSIC_EN);
}
#endif
if (en) {
if (music_info.get_music_player_timer == 0) {
music_info.get_music_player_timer = sys_timer_add(NULL, music_player_time_deal, 800);
}
} else {
if (music_info.get_music_player_timer) {
sys_timer_del(music_info.get_music_player_timer);
music_info.get_music_player_timer = 0;
}
}
}
void music_info_cmd_handle(u8 *p, u16 len)
{
u8 cmd = *p;
u8 *data = p + 1;
switch (cmd) {
case 0x01:
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL);
break;
case 0x02:
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_PREV, 0, NULL);
break;
case 0x03:
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL);
break;
case 0x04:
music_info.player_time_en = *data;
if (*data) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1);
} else {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1);
}
break;
default:
break;
}
}
u32 char_to_hex(char num, u8 ten_num)
{
u32 char_num;
switch (num) {
case '0':
char_num = 0;
break;
case '1':
char_num = 1;
break;
case '2':
char_num = 2;
break;
case '3':
char_num = 3;
break;
case '4':
char_num = 4;
break;
case '5':
char_num = 5;
break;
case '6':
char_num = 6;
break;
case '7':
char_num = 7;
break;
case '8':
char_num = 8;
break;
case '9':
char_num = 9;
break;
default:
char_num = 0;
}
switch (ten_num) {
case 0:
char_num = char_num;
break;
case 1:
char_num = char_num * 10;
break;
case 2:
char_num = char_num * 100;
break;
case 3:
char_num = char_num * 1000;
break;
case 4:
char_num = char_num * 10000;
break;
case 5:
char_num = char_num * 100000;
break;
case 6:
char_num = char_num * 1000000;
break;
case 7:
char_num = char_num * 10000000;
break;
default:
char_num = char_num;
}
return char_num;
}
u32 num_char_to_hex(char *c, u16 len)
{
u32 total_num = 0;
u8 i;
for (i = 0; i < len; i++) {
total_num += char_to_hex(*(c + i), len - i - 1);
}
return total_num;
}
static void rcsp_adv_update_music_info(void *priv)
{
u8 i;
u32 type = *((u32 *)priv);
if (music_info.player_time_en) {
for (i = 0; i < (sizeof(type) * 8); i++) {
if (type & BIT(i)) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_INFO, &i, 1);
}
}
}
}
static u8 music_info_state = 0;
static void rcsp_adv_music_info_state(void *priv)
{
music_info_state = *((u8 *)priv);
}
static u8 rcsp_adv_music_info_vaild(void)
{
return music_info_state == 0;
}
void rcsp_adv_music_info_set_state(u8 state, u32 time)
{
static u8 cur_state = 0;
cur_state = state;
sys_timeout_add(&cur_state, rcsp_adv_music_info_state, time);
}
void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len)
{
//printf("info len \n");
//put_buf(info,len);
struct RcspModel *rcspModel = rcsp_handle_get();
if (1 == rcspModel->A_platform && rcsp_adv_music_info_vaild()) {
return;
}
#if RCSP_ADV_FIND_DEVICE_ENABLE
extern u8 rcsp_find_device_key_flag_get(void);
if (rcsp_find_device_key_flag_get()) {
return ;
}
#endif
static u32 deal_type = 0;
static u32 final_type = 0;
switch (type) {
case 0:
if (time && time != music_info.total_time) {
/* if(music_info.player_time_en) */
{
music_info.curr_player_time = time;
music_info.player_time_min = time / 1000 / 60;
music_info.player_time_sec = time / 1000 - (music_info.player_time_min * 60);
/* printf("total time %d %d->", music_info.total_time, time); */
/* printf("muisc time %d %d->", music_info.player_time_min, music_info.player_time_sec); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_TIME, NULL, 0);
}
}
return;
case 1:
if ((info)) {
if (len > 64) {
len = 64;
}
if (len) {
music_info.title_len = len;
memcpy(music_info.title, info, len);
} else {
music_info.title[0] = 0;
music_info.title_len = 1;
}
deal_type |= BIT(type);
}
break;
case 2:
if ((info)) {
if (len > 64) {
len = 64;
}
if (len) {
music_info.artist_len = len;
memcpy(music_info.artist, info, len);
} else {
music_info.artist[0] = 0;
music_info.artist_len = 1;
}
deal_type |= BIT(type);
}
break;
case 3:
if ((info)) {
if (len > 64) {
len = 64;
}
if (len) {
music_info.album_len = len;
memcpy(music_info.album, info, len);
} else {
music_info.album[0] = 0;
music_info.album_len = 1;
}
deal_type |= BIT(type);
}
break;
case 4:
if ((info)) {
len = 1;
music_info.num_len = len;
memcpy(&music_info.number, info, len);
deal_type |= BIT(type);
}
break;
case 5:
if ((info)) {
len = 2;
music_info.total_len = len;
memcpy(music_info.total, info, len);
deal_type |= BIT(type);
}
break;
case 6:
if ((info)) {
if (len > 16) {
len = 16;
}
music_info.genre_len = len;
memcpy(music_info.genre, info, len);
deal_type |= BIT(type);
}
break;
case 7:
if ((info)) {
if (len > 8) {
len = 8;
}
memcpy(music_info.time, info, len);
/* printf("get time %s\n", info); */
/* put_buf(music_info.time, len); */
music_info.total_time = num_char_to_hex(music_info.time, len);
deal_type |= BIT(type);
final_type = deal_type;
if (0 == music_info.player_time_en) {
sys_timeout_add(&final_type, rcsp_adv_update_music_info, 500);
}
deal_type = 0;
}
break;
default:
break;
}
if (music_info.player_time_en) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_INFO, &type, 1);
}
/* os_time_dly(2); */
}
void avrcp_element_attr_rsp_ext_process(u8 type, u32 time, u8 *info, u16 len)
{
/* printf("music info len2: \n"); */
/* put_buf(info, len); */
if (0 == len) {
rcsp_adv_music_info_deal(type, time, info, len);
}
}
#else
u8 get_player_time_en(void)
{
return 0;
}
#endif
@@ -0,0 +1,32 @@
#ifndef __RCSP_MUSIC_INFO_SETTING_H__
#define __RCSP_MUSIC_INFO_SETTING_H__
#include "app_config.h"
#include "generic/typedef.h"
#if (RCSP_MODE && RCSP_ADV_MUSIC_INFO_ENABLE)
char *get_music_title(void);
u8 get_music_title_len(void);
char *get_music_artist(void);
u8 get_music_artist_len(void);
char *get_music_album(void);
u8 get_music_album_len(void);
char *get_music_number(void);
u8 get_music_number_len(void);
char *get_music_total(void);
u8 get_music_total_len(void);
char *get_music_genre(void);
u8 get_music_genre_len(void);
u16 get_music_total_time(void);
u32 get_music_curr_time(void);
u8 get_music_player_state(void);
void music_info_cmd_handle(u8 *p, u16 len);
void stop_get_music_timer(u8 en);
extern void music_player_time_timer_deal(u8 en);
u8 get_player_time_en(void);
void set_player_time_en(u8 en);
void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len);
#endif
#endif
@@ -0,0 +1,259 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_vol_setting.data.bss")
#pragma data_seg(".rcsp_vol_setting.data")
#pragma const_seg(".rcsp_vol_setting.text.const")
#pragma code_seg(".rcsp_vol_setting.text")
#endif
#include "rcsp_config.h"
#include "syscfg_id.h"
#include "rcsp_setting_sync.h"
#include "rcsp_setting_opt.h"
#include "ble_rcsp_server.h"
#include "rcsp_device_status.h"
#include "key_event_deal.h"
#include "audio_config.h"
#include "rcsp_functions/rcsp_config.h"
#if (RCSP_MODE && RCSP_ADV_EQ_SET_ENABLE)
#include "vol_sync.h"
static u8 vol_setting[1] = {0};
extern int get_bt_tws_connect_status();
bool rcsp_set_device_volume(int volume)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return false;
}
if (0 == rcspModel->dev_vol_sync) {
return false;
}
if (0 == rcspModel->A_platform) {
set_music_device_volume(volume);
}
return true;
}
bool rcsp_set_volume(s8 volume)
{
static u8 cur_flag = 0;
struct RcspModel *rcspModel = rcsp_handle_get();
if (cur_flag || rcspModel == NULL) {
cur_flag = 0;
return false;
}
if (0 == rcspModel->dev_vol_sync) {
return false;
}
#if TCFG_APP_LINEIN_EN
if (LINEIN_FUNCTION == rcspModel->cur_app_mode) {
cur_flag = 1;
extern int linein_volume_set(u8 vol);
linein_volume_set(volume);
cur_flag = 0;
return true;
}
#endif
return false;
}
bool rcsp_key_volume_down(u8 value)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return false;
}
if (0 == rcspModel->dev_vol_sync) {
return false;
}
#if TCFG_APP_LINEIN_EN
if (LINEIN_FUNCTION == rcspModel->cur_app_mode) {
extern void linein_key_vol_down();
linein_key_vol_down();
return true;
}
#endif
return false;
}
bool rcsp_key_volume_up(u8 value)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return false;
}
if (0 == rcspModel->dev_vol_sync) {
return false;
}
#if TCFG_APP_LINEIN_EN
if (LINEIN_FUNCTION == rcspModel->cur_app_mode) {
extern void linein_key_vol_up();
linein_key_vol_up();
true;
}
#endif
return false;
}
void rcsp_get_max_vol_info(u8 *vol_info)
{
*vol_info = app_audio_volume_max_query(AppVol_BT_MUSIC);
}
void rcsp_get_cur_dev_vol_info(u8 *vol_info)
{
*vol_info = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
}
void rcsp_set_vol_for_find_device(u8 vol_flag)
{
static u8 vol = 0;
static u8 state = 0;
if (state == vol_flag) {
return ;
}
if (vol_flag) {
// 停止媒体
vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
// 最大声
app_audio_set_volume(app_audio_get_state(), app_audio_volume_max_query(AppVol_BT_MUSIC), 1);
} else {
// 恢复
app_audio_set_volume(app_audio_get_state(), vol, 1);
}
rcsp_device_status_update(COMMON_FUNCTION, BIT(RCSP_DEVICE_STATUS_ATTR_TYPE_VOL));
state = vol_flag;
}
static int rcsp_get_vol_info(u8 *vol_info)
{
*vol_info = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
return 0;
}
static void set_vol_info(u8 *vol_info)
{
memcpy(vol_setting, vol_info, sizeof(vol_setting));
}
static void update_vol_vm_value(u8 *vol_info)
{
// 不需要写vm操作,5s后会自动保持音量值
//syscfg_write(CFG_MUSIC_VOL, vol_setting, sizeof(vol_setting));
}
static void vol_setting_sync(u8 *vol_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_rcsp_setting(ATTR_TYPE_VOL_SETTING);
}
#endif
}
static void vol_state_update(void)
{
// 更新操作,包含写vm操作
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL) {
return ;
}
u8 vol = vol_setting[0];
if (LINEIN_FUNCTION == rcspModel->cur_app_mode) {
#if TCFG_APP_LINEIN_EN
extern int linein_volume_set(u8 vol);
linein_volume_set(vol);
#endif
} else {
app_audio_set_volume(app_audio_get_state(), vol, 1);
}
}
static void deal_vol_setting(u8 *vol_info, u8 write_vm, u8 tws_sync)
{
if (vol_info) {
set_vol_info(vol_info);
}
if (write_vm) {
update_vol_vm_value(vol_setting);
}
if (tws_sync) {
vol_setting_sync(vol_setting);
}
vol_state_update();
}
static int vol_setting_init(void)
{
int ret = 0;
u8 cur_vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
set_vol_info(&cur_vol);
return 0;
}
static RCSP_SETTING_OPT vol_setting_opt = {
.data_len = 1,
.setting_type = ATTR_TYPE_VOL_SETTING,
.syscfg_id = CFG_MUSIC_VOL,
.deal_opt_setting = deal_vol_setting,
.set_setting = set_vol_info,
.get_setting = rcsp_get_vol_info,
.custom_setting_init = vol_setting_init, // 初始化不需要vm操作,所以重新实现
.custom_setting_release = NULL,
.custom_vm_info_update = NULL,
.custom_setting_update = NULL,
.custom_sibling_setting_deal = NULL,
};
REGISTER_APP_SETTING_OPT(vol_setting_opt);
#else
void rcsp_set_vol_for_find_device(u8 vol_flag)
{
#if 0
static u8 vol = 0;
static u8 state = 0;
if (state == vol_flag) {
return ;
}
if (vol_flag) {
// 停止媒体
vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
// 最大声
app_audio_set_volume(app_audio_get_state(), app_audio_volume_max_query(AppVol_BT_MUSIC), 1);
} else {
// 恢复
app_audio_set_volume(app_audio_get_state(), vol, 1);
}
rcsp_device_status_update(COMMON_FUNCTION, BIT(RCSP_DEVICE_STATUS_ATTR_TYPE_VOL));
state = vol_flag;
#endif //end of 0
}
bool rcsp_set_device_volume(int volume)
{
return false;
}
void rcsp_get_max_vol_info(u8 *vol_info)
{
}
void rcsp_get_cur_dev_vol_info(u8 *vol_info)
{
}
#endif
@@ -0,0 +1,20 @@
#ifndef __RCSP_VOL_SETTING_H__
#define __RCSP_VOL_SETTING_H__
#include "app_config.h"
/**
* @brief 获取当前设备音量
*
* @param vol_info 当前设备音量大小
*/
void rcsp_get_cur_dev_vol_info(u8 *vol_info);
/**
* @brief 获取当前设备最大音量
*
* @param vol_info 当前设备最大音量
*/
void rcsp_get_max_vol_info(u8 *vol_info);
#endif
@@ -0,0 +1,167 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_switch_device.data.bss")
#pragma data_seg(".rcsp_switch_device.data")
#pragma const_seg(".rcsp_switch_device.text.const")
#pragma code_seg(".rcsp_switch_device.text")
#endif
#include "rcsp_functions/rcsp_config.h"
#include "rcsp_config.h"
#include "rcsp_device_feature.h"
#include "btstack/avctp_user.h"
#include "rcsp_event.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#include "rcsp_update.h"
#include "JL_rcsp_protocol.h"
#include "app_ble_spp_api.h"
#include "app_main.h"
#define LOG_TAG_CONST RCSP
#define LOG_TAG "[switch_device]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#if (RCSP_MODE)
/* #define RCSP_DEBUG_EN */
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) log_char(x)
#define rcsp_printf log_info
#define rcsp_printf_buf(x,len) log_info_hexdump(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
extern void *rcsp_server_ble_hdl;
extern void *rcsp_server_ble_hdl1;
static u8 g_new_reconn_flag = 0;
static u16 g_ble_con_handle = 0; // ble手机发切换通讯方式时不为空
static bool g_is_switching = false;
static u8 g_is_switch_to_spp = 0; // 0:BLE; 1:SPP
#if TCFG_EDR_SCAN_CONN_CTRL
/* 用于区分一键连接时候,ble断连原因 */
static u8 ble_disconnect_by_app_flag = 0; /* 1:一键连接时候,app发命令断连ble */
u8 rcsp_get_ble_disconnect_by_app_flag(void)
{
return ble_disconnect_by_app_flag;
}
void rcsp_set_ble_disconnect_by_app_flag(u8 flag)
{
printf("%s flag:%d", __func__, flag);
ble_disconnect_by_app_flag = flag;
}
#endif
extern void ble_app_disconnect(void);
extern u8 check_le_pakcet_sent_finish_flag(void);
static void wait_response_and_disconn_ble(void *priv)
{
static u16 wait_response_timeout = 0;
static u8 wait_cnt = 0;
// ble切换spp:前一个条件开始不满足,之后满足; 后一个条件开始满足,之后不满足; 超时10次后自动断开ble
if (wait_response_timeout || (g_ble_con_handle && (1 == g_is_switch_to_spp))) {
if ((10 == wait_cnt) || (rcsp_send_list_is_empty() && check_le_pakcet_sent_finish_flag())) {
if (wait_response_timeout) {
sys_timeout_del(wait_response_timeout);
wait_response_timeout = 0;
}
wait_cnt = 0;
#if TCFG_EDR_SCAN_CONN_CTRL
rcsp_set_ble_disconnect_by_app_flag(1);
#endif
ble_app_disconnect();
/* u16 ble_con_handle = app_ble_get_hdl_con_handle(rcsp_server_ble_hdl); */
/* if (g_ble_con_handle == ble_con_handle) { */
/* app_ble_disconnect(rcsp_server_ble_hdl); */
/* } */
/* #if TCFG_RCSP_DUAL_CONN_ENABLE */
/* u16 ble_con_handle1 = app_ble_get_hdl_con_handle(rcsp_server_ble_hdl1); */
/* if (g_ble_con_handle == ble_con_handle1) { */
/* app_ble_disconnect(rcsp_server_ble_hdl1); */
/* } */
/* #endif */
g_is_switching = false;
} else {
wait_cnt++;
wait_response_timeout = sys_timeout_add(NULL, wait_response_and_disconn_ble, 100);
}
} else {
g_is_switching = false;
}
}
#ifdef RCSP_UPDATE_EN
static void wait_disconn_spp_timeout(void *priv)
{
static u8 wait_cnt = 0;
if (wait_cnt++ >= 20) {
log_info("wait spp disconnect timeout\n");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0);
} else {
sys_timeout_add(NULL, wait_disconn_spp_timeout, 100);
}
}
#endif
u8 get_rcsp_support_new_reconn_flag(void)
{
return g_new_reconn_flag;
}
void switch_device(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return ;
}
if (g_is_switching) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_BUSY, OpCode_SN, NULL, 0, ble_con_handle, spp_remote_addr);
return;
}
rcspModel->trans_chl = data[0];//指spp还是ble
log_info("rcspModel->trans_chl:%x\n", rcspModel->trans_chl);
if (len > 1) {
g_new_reconn_flag = data[1];
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &g_new_reconn_flag, 1, ble_con_handle, spp_remote_addr);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, ble_con_handle, spp_remote_addr);
}
g_is_switch_to_spp = data[0];
g_is_switching = true;
g_ble_con_handle = ble_con_handle;
#if RCSP_UPDATE_EN
if (get_jl_update_flag()) {
if (ble_con_handle) {
rcsp_printf("BLE_ CON START DISCON\n");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0);
g_is_switching = false;
} else {
rcsp_printf("WAIT_FOR_SPP_DISCON\n");
wait_disconn_spp_timeout(NULL);
g_is_switching = false;
}
} else {
wait_response_and_disconn_ble(NULL);
}
#else
wait_response_and_disconn_ble(NULL);
#endif
}
#endif//RCSP_MODE
@@ -0,0 +1,11 @@
#ifndef __RCSP_SWITCH_DEVICE_H__
#define __RCSP_SWITCH_DEVICE_H__
#include "typedef.h"
#include "app_config.h"
void switch_device(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
u8 get_rcsp_support_new_reconn_flag(void);
#endif // __RCSP_SWITCH_DEVICE_H__
@@ -0,0 +1,587 @@
#include "jiffies.h"
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_ch_loader_download.data.bss")
#pragma data_seg(".rcsp_ch_loader_download.data")
#pragma const_seg(".rcsp_ch_loader_download.text.const")
#pragma code_seg(".rcsp_ch_loader_download.text")
#endif
//#include "update_lib.h"
#include "app_config.h"
#include "update.h"
#include "uart.h"
#include "update_loader_download.h"
#include "rcsp_update.h"
#include "JL_rcsp_protocol.h"
#include "classic/tws_api.h"
#include "os/os_api.h"
#include "ble_rcsp_server.h"
#include "clock_manager/clock_manager.h"
#include "btstack/avctp_user.h"
#include <string.h>
#include "rcsp_update_tws.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#if (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
#include "fs/fs.h"
#if TCFG_RCSP_DUAL_CONN_ENABLE
#include "adv_1t2_setting.h"
#endif
#define LOG_TAG "[RCSP-UPDATE]"
#define LOG_INFO_ENABLE
#define LOG_ERROR_ENABLE
#include "debug.h"
typedef enum __DEVICE_REFRESH_FW_STATUS {
DEVICE_UPDATE_STA_SUCCESS = 0, //升级成功(default)
DEVICE_UPDATE_STA_VERIFY_ERR, //升级完校验代码出错(default)
DEVICE_UPDATE_STA_FAIL, //升级失败(default)
DEVICE_UPDATE_STA_KEY_ERR, //加密key不匹配
DEVICE_UPDATE_STA_FILE_ERR, //升级文件出错
DEVICE_UPDATE_STA_TYPE_ERR, //升级类型出错,仅code_type;
//DEVICE_UPDATE_STA_MAX_ERR,
DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC = 0x80,
} DEVICE_UPDATE_STA;
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
typedef struct _rcsp_update_param_t {
u32 state;
u32 read_len;
u32 need_rx_len;
u8 *read_buf;
void (*resume_hdl)(void *priv);
int (*sleep_hdl)(void *priv);
u32(*data_send_hdl)(void *priv, u32 offset, u16 len);
u32(*send_update_status_hdl)(void *priv, u8 state);
u32 file_offset;
u8 seek_type;
u16 ble_con_handle;
u8 *spp_remote_addr;
} rcsp_update_param_t;
extern const int support_dual_bank_update_en;
static rcsp_update_param_t rcsp_update_param;
#define __this (&rcsp_update_param)
static u8 *bt_read_buf = NULL;
static u16 g_bt_read_len = 0;
static u32 rcsp_file_offset = 0;
static u8 rcsp_seek_type = 0;
static u8 g_rcsp_ancs_state_flag = 0;
//NOTE:测试盒的定义和本sdk文件系统的seek_type定义不一样;
enum {
BT_SEEK_SET = 0x01,
BT_SEEK_CUR = 0x02,
BT_SEEK_TYPE_UPDATE_LEN = 0x10,
};
// 断开连接时,需要清空正在升级的bthdl
void rcsp_clean_update_hdl_for_end_update(u16 ble_con_handle, u8 *spp_remote_addr)
{
if (ble_con_handle == __this->ble_con_handle) {
__this->ble_con_handle = 0;
__this->spp_remote_addr = NULL;
}
if (__this->spp_remote_addr && spp_remote_addr && !memcmp(spp_remote_addr, __this->spp_remote_addr, 6)) {
__this->ble_con_handle = 0;
__this->spp_remote_addr = NULL;
}
if (!ble_con_handle && !spp_remote_addr) {
__this->ble_con_handle = 0;
__this->spp_remote_addr = NULL;
}
/* if (__this->spp_remote_addr) { */
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
/* put_buf(__this->spp_remote_addr, 6); */
/* } */
}
// 升级前需要设置正在升级的bthdl,防止1t2手机继续升级
void rcsp_set_update_hdl(u16 ble_con_handle, u8 *spp_remote_addr)
{
if (ble_con_handle) {
__this->ble_con_handle = ble_con_handle;
__this->spp_remote_addr = NULL;
} else {
__this->spp_remote_addr = spp_remote_addr;
__this->ble_con_handle = 0;
}
}
// 获取当前升级的上位机信息
void rcsp_get_update_hdl(u16 *ble_con_handle, u8 *spp_remote_addr)
{
/* if (__this->spp_remote_addr) { */
/* printf("%s, %d\n", __FUNCTION__, __LINE__); */
/* put_buf(__this->spp_remote_addr, 6); */
/* } */
*ble_con_handle = __this->ble_con_handle;
if (__this->spp_remote_addr) {
memcpy(spp_remote_addr, __this->spp_remote_addr, 6);
} else {
u8 _addr_temp[6] = {0};
memcpy(spp_remote_addr, _addr_temp, 6);
}
}
void tws_api_auto_role_switch_disable();
void tws_api_auto_role_switch_enable();
int rcsp_f_seek(void *fp, u8 type, u32 offset)
{
if (type == SEEK_SET) {
__this->file_offset = offset;
__this->seek_type = BT_SEEK_SET;
} else if (type == SEEK_CUR) {
__this->file_offset += offset;
__this->seek_type = BT_SEEK_CUR;
}
/* lib_printf("---------UPDATA_seek type %d, offsize %d----------\n", bt_seek_type, bt_file_offset); */
return 0;//FR_OK;
}
static u16 rcsp_f_stop(u8 err);
#define RETRY_TIMES 3
u8 get_rcsp_connect_status();
u16 rcsp_f_read(void *fp, u8 *buff, u16 len)
{
//printf("===rcsp_read:%x %x\n", __this->file_offset, len);
u8 retry_cnt = 0;
__this->need_rx_len = len;
__this->state = UPDATA_REV_DATA;
__this->read_len = 0;
__this->read_buf = buff;
#if((OTA_TWS_SAME_TIME_ENABLE && (RCSP_MODE == RCSP_MODE_SOUNDBOX)))
if ((tws_ota_control(OTA_TYPE_GET) == OTA_TWS) &&
(tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED)) {
//假如TWS一起升级,TWS断开了,返回失败
r_printf("tws disconn, stop update");
rcsp_f_stop(DEVICE_UPDATE_STA_FAIL);
return (u16) - 1;
}
#endif
if (get_rcsp_connect_status()) {
__this->data_send_hdl(fp, __this->file_offset, len);
}
__RETRY:
if (!get_rcsp_connect_status() || g_rcsp_ancs_state_flag) { //如果已经断开连接直接返回-1
return -1;
}
while (!((0 == __this->state) && (__this->read_len == len))) {
if (__this->sleep_hdl && get_rcsp_connect_status()) {
__this->sleep_hdl(NULL);
} else {
len = -1;
break;
}
if (!((0 == __this->state) && (__this->read_len == len))) {
if (retry_cnt++ > RETRY_TIMES) {
len = (u16) - 1;
break;
} else {
goto __RETRY;
}
}
}
if ((u16) - 1 != len) {
__this->file_offset += len;
}
return len;
}
u16 rcsp_f_open(void)
{
log_info(">>>rcsp_f_open\n");
__this->file_offset = 0;
__this->seek_type = BT_SEEK_SET;
return 1;
}
u16 rcsp_send_update_len(u32 update_len)
{
/* while (0 == (bit(updata_start) & bt_updata_get_flag())); */
/* bt_updata_clr_flag(updata_start); //clr flag */
return 1;
}
enum {
BT_UPDATE_OVER = 0,
BT_UPDATE_KEY_ERR,
BT_UPDATE_CONNECT_ERR,
};
static u8 update_result_handle(u8 err)
{
u8 res = 0;
if (0 == support_dual_bank_update_en) {
res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC;
}
#if OTA_TWS_SAME_TIME_ENABLE
tws_api_auto_role_switch_enable();
#endif
if (err & UPDATE_RESULT_FLAG_BITMAP) {
switch (err & 0x7f) {
//升级文件错误
case UPDATE_RESULT_FILE_SIZE_ERR:
case UPDATE_RESULT_LOADER_SIZE_ERR:
case UPDATE_RESULT_REMOTE_FILE_HEAD_ERR:
case UPDATE_RESULT_LOCAL_FILE_HEAD_ERR:
case UPDATE_RESULT_FILE_OPERATION_ERR:
case UPDATE_RESULT_NOT_FIND_TARGET_FILE_ERR:
case UPDATE_RESULT_PRODUCT_INFO_NOT_MATCH:
res = DEVICE_UPDATE_STA_FILE_ERR;
break;
//文件内容校验失败
case UPDATE_RESULT_LOADER_VERIFY_ERR:
case UPDATE_RESULT_FLASH_DATA_VERIFY_ERR:
res = DEVICE_UPDATE_STA_VERIFY_ERR;
break;
case UPDATE_RESULT_EX_DSP_UPDATE_ERR:
res = UPDATE_RESULT_EX_DSP_UPDATE_ERR;
break;
default:
res = err;
break;
}
} else if (UPDATE_RESULT_BT_UPDATE_OVER == err) {
if (support_dual_bank_update_en) {
res = DEVICE_UPDATE_STA_SUCCESS;
} else {
res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC;
}
} else if (UPDATE_RESULT_BT_UPDATE_KEY_ERR == err) {
res = DEVICE_UPDATE_STA_KEY_ERR;
} else {
res = DEVICE_UPDATE_STA_FAIL;
}
#if CONFIG_REUSABLE_RESERVE
extern u8 reusable_update_app_flag_handle(u8 state, u8 opt);
if ((UPDATE_RESULT_ERR_NONE == err) && (3 == reusable_update_app_flag_handle(0, 0))) {
res = DEVICE_UPDATE_STA_SUCCESS;
}
#elif CONFIG_RESFS_UPDATE_ENABLE
extern u8 resfs_update_app_flag_handle(u8 state, u8 opt);
if ((UPDATE_RESULT_ERR_NONE == err) && (3 == resfs_update_app_flag_handle(0, 0))) {
res = DEVICE_UPDATE_STA_SUCCESS;
}
#endif
return res;
}
static u16 rcsp_f_stop(u8 err)
{
/* while (0 == (bit(updata_start) & bt_updata_get_flag())); */
/* bt_updata_clr_flag(updata_start); //clr flag */
err = update_result_handle(err);
log_info(">>>rcsp_stop\n");
__this->state = UPDATA_STOP;
if (!get_rcsp_connect_status() || g_rcsp_ancs_state_flag) {
return 1;
}
if (__this->data_send_hdl) {
__this->data_send_hdl(NULL, 0, 0);
}
while (!(0 == __this->state)) {
if (__this->sleep_hdl && get_rcsp_connect_status()) {
if (__this->sleep_hdl(NULL) == OS_TIMEOUT) {
break;
}
} else {
break;
}
}
if (__this->send_update_status_hdl) {
__this->send_update_status_hdl(NULL, err);
}
return 1;
}
#if((OTA_TWS_SAME_TIME_ENABLE && (RCSP_MODE)))
void db_update_notify_fail_to_phone()
{
if (get_rcsp_connect_status()) {
rcsp_f_stop(DEVICE_UPDATE_STA_FAIL);
}
}
#endif
__attribute__((weak))
void user_change_ble_conn_param(u8 param_index)
{
}
static int rcsp_notify_update_content_size(void *priv, u32 size)
{
int err;
u8 data[4];
if (!get_rcsp_connect_status()) {
return -1;
}
WRITE_BIG_U32(data, size);
user_change_ble_conn_param(0);
log_info("send content_size:%x\n", size);
err = JL_CMD_send(JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE, data, sizeof(data), JL_NEED_RESPOND, __this->ble_con_handle, __this->spp_remote_addr);
return err;
}
void rcsp_update_handle(u8 state, void *buf, int len)
{
/* log_info("R"); */
if (state != __this->state) {
log_error(">>>rcsp state err\n");
return;
}
if (!get_rcsp_connect_status() || g_rcsp_ancs_state_flag) {
return;
}
switch (state) {
case UPDATA_REV_DATA:
if (__this->read_buf) {
memcpy(__this->read_buf, buf, len);
__this->read_len = len;
__this->state = 0;
}
break;
case UPDATA_STOP:
__this->state = 0;
break;
}
if (__this->resume_hdl) {
__this->resume_hdl(NULL);
}
}
void rcsp_resume(void)
{
if (__this->resume_hdl) {
__this->resume_hdl(NULL);
}
}
static void rcsp_update_resume_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
__this->resume_hdl = resume_hdl;
__this->sleep_hdl = sleep_hdl;
}
void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_status_hdl)(void *priv, u8 state))
{
__this->data_send_hdl = data_send_hdl;
__this->send_update_status_hdl = send_update_status_hdl;
}
static int rcsp_update_request_null(void)
{
u8 buff[8];
if (__this->resume_hdl == NULL || __this->sleep_hdl == NULL) {
return -1;
}
rcsp_f_seek(NULL, SEEK_SET, 0);
rcsp_f_read(NULL, buff, sizeof(buff));
return 0;
}
static int rcsp_update_delay_ms(u32 ms)
{
int ret = 0;
u32 t_start;
u32 tick;
u32 keep_time = 0;
tick = ms;
t_start = jiffies_msec();
while (tick--) {
os_time_dly(1);
ret = rcsp_update_request_null();
if (ret) {
log_error("al fail\n");
break;
}
keep_time = jiffies_msec() - t_start;
if (keep_time >= ms) {
break;
}
}
log_info("rcsp update delay %dms\n", keep_time);
return ret;
}
void rcsp_ch_update_init(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
log_info("------------rcsp_ch_update_init\n");
g_rcsp_ancs_state_flag = 0;
rcsp_update_resume_hdl_register(resume_hdl, sleep_hdl);
//register_receive_fw_update_block_handle(rcsp_updata_handle);
/* fix ble disconnect */
rcsp_update_delay_ms(2000);
}
void rcsp_update_ancs_disconn_handler(void)
{
g_rcsp_ancs_state_flag = 1;
rcsp_resume();
}
const update_op_api_t rcsp_update_op = {
.ch_init = rcsp_ch_update_init,
.f_open = rcsp_f_open,
.f_read = rcsp_f_read,
.f_seek = rcsp_f_seek,
.f_stop = rcsp_f_stop,
.notify_update_content_size = rcsp_notify_update_content_size,
};
extern void set_jl_update_flag(u8 flag);
extern u8 *rcsp_get_ble_hdl_remote_mac_addr(u16 ble_con_handle);
static void rcsp_update_state_cbk(int type, u32 state, void *priv)
{
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
if (ret_code) {
log_info("state:%x, update result code:%x\n", ret_code->stu, ret_code->err_code);
}
switch (state) {
case UPDATE_CH_INIT:
#if TCFG_RCSP_DUAL_CONN_ENABLE
/* // 踢掉另一个连接的设备,并关闭广播 */
/* u8 *remote_addr = __this->spp_remote_addr; */
/* if (__this->ble_con_handle) { */
/* remote_addr = rcsp_get_ble_hdl_remote_mac_addr(__this->ble_con_handle); */
/* } */
/* u8 *other_conn_addr = btstack_get_other_dev_addr(remote_addr); */
/* if (other_conn_addr) { */
/* btstack_device_detach(btstack_get_conn_device(other_conn_addr)); */
/* } */
/* rcsp_disconn_other_ble(__this->ble_con_handle); */
rcsp_bt_ble_adv_enable(0);
#endif
// 如果是ble,则设置连接参数,提高传输效率
if (0 == get_curr_device_type()) {
clock_refurbish();
notify_update_connect_parameter(3);
}
break;
case UPDATE_CH_EXIT:
if (UPDATE_DUAL_BANK_IS_SUPPORT()) {
if ((0 == ret_code->stu) && (UPDATE_RESULT_ERR_NONE == ret_code->err_code || UPDATE_RESULT_BT_UPDATE_OVER == ret_code->err_code)) {
set_jl_update_flag(1);
log_info(">>>rcsp update succ\n");
update_result_set(UPDATA_SUCC);
} else {
update_result_set(UPDATA_DEV_ERR);
log_info(">>>rcsp update err\n");
}
} else {
if ((0 == ret_code->stu) && (UPDATE_RESULT_ERR_NONE == ret_code->err_code || UPDATE_RESULT_BT_UPDATE_OVER == ret_code->err_code)) {
set_jl_update_flag(1);
}
}
// 如果是ble,则设置连接参数,还原传输效率
if (0 == get_curr_device_type()) {
notify_update_connect_parameter(-1);
}
#if TCFG_RCSP_DUAL_CONN_ENABLE
rcsp_clean_update_hdl_for_end_update(0, NULL);
#if TCFG_USER_TWS_ENABLE
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
rcsp_ble_adv_enable_with_con_dev();
}
} else {
rcsp_ble_adv_enable_with_con_dev();
}
#else
rcsp_ble_adv_enable_with_con_dev();
#endif
#endif
break;
}
}
void rcsp_update_loader_download_init(int update_type, void (*result_cbk)(void *priv, u8 type, u8 cmd))
{
update_mode_info_t info = {
.type = update_type,
.state_cbk = rcsp_update_state_cbk,
.p_op_api = &rcsp_update_op,
.task_en = 1,
};
app_active_update_task_init(&info);
}
#else // (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
// 断开连接时,需要清空正在升级的bthdl
void rcsp_clean_update_hdl_for_end_update(u16 ble_con_handle, u8 *spp_remote_addr)
{
}
void db_update_notify_fail_to_phone()
{
}
void rcsp_resume(void)
{
}
#endif // (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
@@ -0,0 +1,938 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_update.data.bss")
#pragma data_seg(".rcsp_update.data")
#pragma const_seg(".rcsp_update.text.const")
#pragma code_seg(".rcsp_update.text")
#endif
#include "app_config.h"
#include "rcsp_update.h"
#if (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
#include "uart.h"
#include "system/timer.h"
#include "update.h"
#include "custom_cfg.h"
#include "btstack/avctp_user.h"
#include "ble_rcsp_server.h"
#include "rcsp_manage.h"
#include "rcsp_bt_manage.h"
#include "update_loader_download.h"
#include "ble_rcsp_server.h"
#include "classic/tws_api.h"
#include "rcsp_task.h"
#include "rcsp_config.h"
#include "syscfg_id.h"
#include "rcsp_device_status.h"
#include "JL_rcsp_protocol.h"
#include "rcsp_config.h"
#include "rcsp_functions/rcsp_config.h"
#if RCSP_ADV_EN
#include "rcsp_setting_opt.h"
#endif
#if (RCSP_MODE == RCSP_MODE_EARPHONE)
#include "bt_tws.h"
#endif
#if (RCSP_MODE == RCSP_MODE_WATCH)
#include "rcsp_extra_flash_opt.h"
#endif
#if (RCSP_MODE == RCSP_MODE_SOUNDBOX)
#include "rcsp_misc_setting.h"
#endif
#define RCSP_DEBUG_EN
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_put_buf(x,len) put_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_put_buf(...)
#endif
#define DEV_UPDATE_FILE_INFO_OFFEST 0x00//0x40
#define DEV_UPDATE_FILE_INFO_LEN 0x00//(0x10 + VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1))
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
static update_file_ext_id_t update_file_id_info = {
.update_file_id_info.ver[0] = 0xff,
.update_file_id_info.ver[1] = 0xff,
};
extern u8 get_charge_online_flag(void);
extern u8 get_self_battery_level(void);
extern const int support_dual_bank_update_en;
extern void ble_app_disconnect(void);
extern void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len);
extern u8 check_le_pakcet_sent_finish_flag(void);
// 获取rcsp已连接设备
extern u8 bt_rcsp_device_conn_num(void);
// 获取当前ble连接设备的mac地址
u8 *rcsp_get_ble_hdl_remote_mac_addr(u16 ble_con_handle);
static u8 update_flag = 0;
static u8 tws_need_update = 0; //标志耳机是否需要强制升级
#if RCSP_MODE == RCSP_MODE_EARPHONE
static u8 tws_need_role_switch = 0; //用于tws连接之后版本号不匹配进行role_switch,低版本号的作为主机进行强制升级
#endif
enum {
UPDATE_FLAG_OK,
UPDATE_FLAG_LOW_POWER,
UPDATE_FLAG_FW_INFO_ERR,
UPDATE_FLAG_FW_INFO_CONSISTENT,
UPDATE_FLAG_TWS_DISCONNECT,
UPDATE_FLAG_TWS_NOT_IN_CHARGESTORE,
UPDATE_FLAG_ALREADY, //已有升级任务
UPDATE_FLAG_MULTI_CONN_DEVICE, //多个蓝牙连接设备不允许升级
};
static void rcsp_update_change_mtu(u16 new_mtu);
static void rcsp_update_prepare()
{
///升级前可以选择关闭需要关闭的模块
#if RCSP_DEVICE_STATUS_ENABLE
rcsp_device_status_setting_stop();
#endif
#if (RCSP_MODE != RCSP_MODE_SOUNDBOX)
// 关闭混响
extern void rcsp_close_reverbrateion_state_and_update(void);
rcsp_close_reverbrateion_state_and_update();
#endif
#if (SOUNDCARD_ENABLE)
extern void soundcard_close(void);
soundcard_close();
return ;
#endif
#if (TCFG_MIC_EFFECT_ENABLE && (0 == RCSP_REVERBERATION_SETTING))
mic_effect_stop();
#endif
}
static void rcsp_update_fail_and_resume(void)
{
#if (TCFG_MIC_EFFECT_ENABLE)
mic_effect_start();
#endif
#if (SOUNDCARD_ENABLE)
extern void soundcard_start(void);
soundcard_start();
#endif
}
u8 get_jl_update_flag(void)
{
printf("get_update_flag:%x\n", update_flag);
return update_flag;
}
void set_jl_update_flag(u8 flag)
{
update_flag = flag;
printf("update_flag:%x\n", update_flag);
}
/**
* @abstract 获取当前连接设备类型
*
* @return 0:ble,1:spp
*/
static u8 device_type = 0;
static void set_curr_update_type(u8 type)
{
device_type = type;
}
/**
* @abstract 获取当前连接设备类型
*
* @return 0:ble,1:spp
*/
u8 get_curr_device_type(void)
{
return device_type;
}
#if (RCSP_MODE == RCSP_MODE_WATCH)
void set_update_ex_flash_flag(u8 update_flag)
{
// 读取vm,如果相同不设置,如果不同设置vm
u8 tmp_flag = 0;
syscfg_read(VM_RESET_EX_FLASH_FLAG, &tmp_flag, sizeof(tmp_flag));
if (tmp_flag != update_flag) {
syscfg_write(VM_RESET_EX_FLASH_FLAG, &update_flag, sizeof(update_flag));
}
}
u8 get_update_ex_flash_flag(void)
{
// 从vm中获取标志位
u8 update_flag = 0;
u8 tmp_flag = -1;
if (sizeof(tmp_flag) ==
syscfg_read(VM_RESET_EX_FLASH_FLAG, &tmp_flag, sizeof(tmp_flag))) {
update_flag = tmp_flag;
}
return update_flag;
}
#endif // (RCSP_MODE == RCSP_MODE_WATCH)
typedef struct _update_mode_t {
u8 opcode;
u8 opcode_sn;
u16 ble_con_handle;
u8 spp_remote_addr[6];
} update_mode_t;
static update_mode_t update_record_info;
#if (RCSP_MODE == RCSP_MODE_SOUNDBOX)
#define RCSP_UPDATE_WAIT_SPP_DISCONN_TIME (1000)
static bool check_edr_is_disconnct(void);
static void rcsp_update_private_param_fill(UPDATA_PARM *p);
static void rcsp_update_before_jump_handle(int type);
static void wait_response_and_disconn_spp(void *priv)
{
static u32 wait_time = 0;
if (check_edr_is_disconnct()) {
rcsp_printf("b");
if (wait_time > RCSP_UPDATE_WAIT_SPP_DISCONN_TIME) {
wait_time = 0;
bt_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
} else {
wait_time += 100;
}
sys_timeout_add(NULL, wait_response_and_disconn_spp, 100);
return;
}
wait_time = 0;
rcsp_printf("BLE_APP_UPDATE\n");
update_mode_api_v2(BLE_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
}
#endif // (RCSP_MODE == RCSP_MODE_SOUNDBOX)
static void JL_controller_save_curr_cmd_para(u8 OpCode, u8 OpCode_SN)
{
update_record_info.opcode = OpCode;
update_record_info.opcode_sn = OpCode_SN;
}
static void JL_controller_get_curr_cmd_para(u8 *OpCode, u8 *OpCode_SN)
{
*OpCode = update_record_info.opcode;
*OpCode_SN = update_record_info.opcode_sn;
}
static void (*fw_update_block_handle)(u8 state, void *buf, int len) = NULL;
static void register_receive_fw_update_block_handle(void (*handle)(u8 state, void *buf, int len))
{
fw_update_block_handle = handle;
}
static u16 ble_discon_timeout;
static void ble_discon_timeout_handle(void *priv)
{
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0);
}
static u16 wait_response_timeout;
static void wait_response_and_disconn_ble(void *priv)
{
rcsp_printf("W");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0);
}
static void rcsp_update_before_jump_handle(int type)
{
#if CONFIG_UPDATE_JUMP_TO_MASK
void latch_reset();
latch_reset();
#else
cpu_reset();
#endif
}
static void rcsp_wait_reboot_dev(void *priv)
{
if (NULL == priv && !rcsp_send_list_is_empty()) {
return;
}
bt_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
extern void ble_module_enable(u8 en);
ble_module_enable(0);
#if CONFIG_UPDATE_JUMP_TO_MASK
void latch_reset();
latch_reset();
#else
cpu_reset();
#endif
}
static void rcsp_rcsp_reboot_dev(void)
{
extern void adv_edr_name_change_now(void);
adv_edr_name_change_now();
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
#if RCSP_ADV_EN
modify_bt_name_and_reset(500);
#endif
} else {
if (sys_timer_add(NULL, rcsp_wait_reboot_dev, 500) == 0) {
rcsp_wait_reboot_dev((void *)1);
}
}
#else
if (sys_timer_add(NULL, rcsp_wait_reboot_dev, 500) == 0) {
rcsp_wait_reboot_dev((void *)1);
}
#endif
}
extern void rcsp_set_update_hdl(u16 ble_con_handle, u8 *spp_remote_addr);
extern void rcsp_get_update_hdl(u16 *ble_con_handle, u8 *spp_remote_addr);
void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd);
u32 rcsp_update_status_response(void *priv, u8 status);
u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len);
extern void rcsp_update_handle(u8 state, void *buf, int len);
extern void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_handl)(void *priv, u8 state));
extern void bt_set_low_latency_mode(int enable);
extern void bt_ble_rcsp_adv_disable(void);
void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta, u16 ble_con_handle, u8 *spp_remote_addr);
void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN, u16 ble_con_handle, u8 *spp_remote_addr);
int JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
if ((OpCode >= JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET) && \
(OpCode <= JL_OPCODE_SET_DEVICE_REBOOT)) {
#if TCFG_USER_TWS_ENABLE
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
if (!(support_dual_bank_update_en && (OTA_TWS_SAME_TIME_ENABLE == 0))) { //如果双备份且没有打开TWS_SAME_TIME_ENABLE还是需要监听,应该是需要打开TWS_SAME_TIME_ENABEL,不然BLE传输只能升级一边
putchar('&');
return 0;
}
}
#endif
}
int ret = 0;
u8 msg[5];
rcsp_printf("%s\n", __FUNCTION__);
switch (OpCode) {
case JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET:
if (0 == len) {
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET\n");
JL_rcsp_resp_dev_update_file_info_offest(OpCode, OpCode_SN, ble_con_handle, spp_remote_addr);
} else {
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET ERR\n");
}
break;
case JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:
rcsp_printf("JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:%x %x\n", len, data[0]);
if (len) {
u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR;
set_curr_update_type(data[0]);
#if (TCFG_USER_TWS_ENABLE && OTA_TWS_SAME_TIME_ENABLE)
int get_bt_tws_connect_status();
if (get_bt_tws_connect_status() || (!support_dual_bank_update_en)) {
can_update_flag = UPDATE_FLAG_OK;
} else {
can_update_flag = UPDATE_FLAG_TWS_DISCONNECT;
}
#else
can_update_flag = UPDATE_FLAG_OK;
#endif // (TCFG_USER_TWS_ENABLE && OTA_TWS_SAME_TIME_ENABLE)
// 1t2判断是否已有升级任务
u8 cur_con_dev = bt_rcsp_device_conn_num();
if (cur_con_dev > 1) {
can_update_flag = UPDATE_FLAG_MULTI_CONN_DEVICE;
}
if (UPDATE_FLAG_OK == can_update_flag) {
u8 max_con_dev = rcsp_max_support_con_dev_num();
if (max_con_dev > 1) {
u16 current_update_ble_con_hdl = 0;
u8 current_update_spp_addr[6] = {0};
u8 _addr_temp[6] = {0};
rcsp_get_update_hdl(&current_update_ble_con_hdl, current_update_spp_addr);
if (current_update_ble_con_hdl || memcmp(current_update_spp_addr, _addr_temp, 6)) {
can_update_flag = UPDATE_FLAG_ALREADY;
}
}
}
//低电逻辑处理
struct RcspModel *rcsp_hd = rcsp_handle_get();
if ((0 == get_charge_online_flag()) && rcsp_hd->low_battery_level && (get_self_battery_level() <= (rcsp_hd->low_battery_level % 10))) { // 防止设置low_battery_level大于10
can_update_flag = UPDATE_FLAG_LOW_POWER;
}
//todo;judge voltage
JL_resp_inquire_device_if_can_update(OpCode, OpCode_SN, can_update_flag, ble_con_handle, spp_remote_addr);
if (UPDATE_FLAG_OK != can_update_flag) {
break;
}
rcsp_set_update_hdl(ble_con_handle, spp_remote_addr);
rcsp_update_prepare();
if (0 == support_dual_bank_update_en) {
#if RCSP_MODE == RCSP_MODE_EARPHONE
if (tws_api_get_role() == TWS_ROLE_MASTER) {
g_printf("tws master start update...\n");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_LOADER_DOWNLOAD_START, NULL, 0);
//需要通知从机进入了升级
u8 data = TWS_UPDATE_INFO;
tws_api_send_data_to_sibling(&data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC);
} else {
bt_ble_rcsp_adv_disable();
ble_module_enable(0); //关闭广播防止从机被手机误回连
r_printf("slave close adv...\n");
sys_timeout_add(NULL, update_slave_adv_reopen, 1000 * 60); //延迟一分钟再开广播
}
if (RCSP_USE_SPP == get_curr_device_type()) {
#if TCFG_USER_TWS_ENABLE
tws_api_detach(TWS_DETACH_BY_LOCAL, 5000); //单备份升级断开tws
tws_cancle_all_noconn();
#endif
}
#else
#if (TCFG_USER_TWS_ENABLE == 1)
if (!tws_api_get_role()) {
#else
if (1) {
#endif
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_LOADER_DOWNLOAD_START, NULL, 0);
} else {
tws_need_update = 1; //置上该标志位APP重新连接的时候强制进入升级
}
#endif
}
}
break;
case JL_OPCODE_EXIT_UPDATE_MODE:
rcsp_printf("JL_OPCODE_EXIT_UPDATE_MODE\n");
break;
case JL_OPCODE_ENTER_UPDATE_MODE:
rcsp_printf("JL_OPCODE_ENTER_UPDATE_MODE\n");
bt_set_low_latency_mode(0);
#if TCFG_USER_TWS_ENABLE
if (support_dual_bank_update_en && !tws_api_get_role()) {
#else
if (support_dual_bank_update_en) {
#endif
u8 status = 0;
#if JL_RCSP_EXTRA_FLASH_OPT
if (!get_update_ex_flash_flag()) {
register_user_chip_update_handle(NULL);
if (rcsp_eflash_update_flag_get()) {
extern void app_rcsp_task_disable_opt(void);
app_rcsp_task_disable_opt();
app_rcsp_task_prepare(0, RCSP_TASK_ACTION_WATCH_TRANSFER, 0);
}
} else if (0 == get_curr_platform()) {
#if UPDATE_EX_FALSH_USE_4K_BUF
/* u32 update_once_req_size = rcsp_packet_write_alloc_len() / 256 * 256; */
u32 update_once_req_size = 4096;
extern void ex_flash_update_once_req_size_set(u32 pack_size);
ex_flash_update_once_req_size_set(update_once_req_size);
set_jl_mtu_resv(rcsp_packet_write_alloc_len());
rcsp_update_change_mtu(rcsp_packet_write_alloc_len());
#endif
}
#endif
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &status, 1, ble_con_handle, spp_remote_addr);
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
printf("rcsp_update_loader_download_init %d\n", __LINE__);
rcsp_update_loader_download_init(DUAL_BANK_UPDATA, rcsp_loader_download_result_handle);
}
break;
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
rcsp_printf("JL_OPCODE_SEND_FW_UPDATE_BLOCK\n");
break;
case JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS:
rcsp_printf("JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS\n");
JL_controller_save_curr_cmd_para(OpCode, OpCode_SN);
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_STOP, NULL, 0);
}
break;
case JL_OPCODE_SET_DEVICE_REBOOT:
rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n");
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, ble_con_handle, spp_remote_addr);
rcsp_rcsp_reboot_dev();
break;
#if 0//TCFG_RCSP_DUAL_CONN_ENABLE
case JL_OPCODE_CHECK_DEVICE_CONN_NUM:
rcsp_printf("JL_OPCODE_CHECK_DEVICE_CONN_NUM\n");
u8 cur_con_dev = bt_rcsp_device_conn_num();
if (cur_con_dev > 1) {
// 踢掉另一个连接的设备
u8 first_flag = data[0];
if (first_flag) {
u8 *remote_addr = spp_remote_addr;
if (ble_con_handle) {
remote_addr = rcsp_get_ble_hdl_remote_mac_addr(ble_con_handle);
}
u8 *other_conn_addr = btstack_get_other_dev_addr(remote_addr);
if (other_conn_addr) {
btstack_device_detach(btstack_get_conn_device(other_conn_addr));
}
rcsp_disconn_other_ble(ble_con_handle);
}
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &cur_con_dev, 1, ble_con_handle, spp_remote_addr);
} else {
// 通知手机可以进入升级了
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &cur_con_dev, 1, ble_con_handle, spp_remote_addr);
}
break;
#endif
default:
ret = 1;
break;
}
return ret;
}
static void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN, u16 ble_con_handle, u8 *spp_remote_addr)
{
u8 data[4 + 2];
u16 update_file_info_offset = DEV_UPDATE_FILE_INFO_OFFEST;
u16 update_file_info_len = DEV_UPDATE_FILE_INFO_LEN;
WRITE_BIG_U32(data + 0, update_file_info_offset);
WRITE_BIG_U16(data + 4, update_file_info_len);
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data), ble_con_handle, spp_remote_addr);
}
static void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta, u16 ble_con_handle, u8 *spp_remote_addr)
{
u8 data[1];
data[0] = update_sta;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data), ble_con_handle, spp_remote_addr);
}
static u8 judge_remote_version_can_update(void)
{
//extern u16 ex_cfg_get_local_version_info(void);
u16 remote_file_ver = READ_BIG_U16(update_file_id_info.update_file_id_info.ver);
//u16 local_ver = ex_cfg_get_local_version_info();
u16 local_ver = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
#if (0 == VER_INFO_EXT_COUNT)
//extern u16 ex_cfg_get_local_pid_info(void);
//extern u16 ex_cfg_get_local_vid_info(void);
//u16 local_pid = ex_cfg_get_local_pid_info();
//u16 local_vid = ex_cfg_get_local_vid_info();
u16 local_pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
u16 local_vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
u16 remote_file_pid = READ_BIG_U16(update_file_id_info.update_file_id_info.pid);
u16 remote_file_vid = READ_BIG_U16(update_file_id_info.update_file_id_info.vid);
if (remote_file_ver > local_ver || remote_file_pid != local_pid || remote_file_vid != local_vid) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#else
//extern u32 ex_cfg_get_local_authkey_info(u8 * authkey_data[], u8 * authkey_len);
//extern u32 ex_cfg_get_local_procode_info(u8 * procode_data[], u8 * procode_len);
u8 authkey_len = 0;
u8 *local_authkey_data = NULL;
get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG);
u8 procode_len = 0;
u8 *local_procode_data = NULL;
get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG);
//ex_cfg_get_local_authkey_info(&local_authkey_data, &authkey_len);
//ex_cfg_get_local_procode_info(&local_procode_data, &procode_len);
u8 *remote_authkey_data = update_file_id_info.ext;
u8 *remote_procode_data = update_file_id_info.ext + authkey_len + 1;
if (remote_file_ver < local_ver
|| 0 != memcmp(remote_authkey_data, local_authkey_data, authkey_len)
|| 0 != memcmp(remote_procode_data, local_procode_data, procode_len)) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#endif
if (remote_file_ver == local_ver) {
rcsp_printf("remote_file_ver is %x, local_ver is %x, remote_file_ver is similar to local_ver\n", remote_file_ver, local_ver);
return UPDATE_FLAG_FW_INFO_CONSISTENT;
}
return UPDATE_FLAG_OK;
}
static bool check_edr_is_disconnct(void)
{
if (bt_get_curr_channel_state()) {
return TRUE;
} else {
return FALSE;
}
}
static bool check_ble_all_packet_sent(void)
{
if (check_le_pakcet_sent_finish_flag()) {
return TRUE;
} else {
return FALSE;
}
}
static u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len)
{
u32 err;
u8 data[4 + 2];
WRITE_BIG_U32(data, offset_addr);
WRITE_BIG_U16(data + 4, len);
u16 current_update_ble_con_hdl = 0;
u8 current_update_spp_addr[6] = {0};
rcsp_get_update_hdl(&current_update_ble_con_hdl, current_update_spp_addr);
/* printf("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__); */
/* u8 _addr_temp[6] = {0}; */
/* if (memcmp(current_update_spp_addr, _addr_temp, 6)) { */
/* put_buf(current_update_spp_addr, 6); */
/* } */
err = JL_CMD_send(JL_OPCODE_SEND_FW_UPDATE_BLOCK, data, sizeof(data), JL_NEED_RESPOND, current_update_ble_con_hdl, current_update_spp_addr);
return err;
}
static JL_ERR JL_controller_resp_get_dev_refresh_fw_status(u8 OpCode, u8 OpCode_SN, u8 result)
{
JL_ERR send_err = JL_ERR_NONE;
u8 data[1];
data[0] = result; //0:sucess 1:fail;
u16 current_update_ble_con_hdl = 0;
u8 current_update_spp_addr[6] = {0};
rcsp_get_update_hdl(&current_update_ble_con_hdl, current_update_spp_addr);
send_err = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data), current_update_ble_con_hdl, current_update_spp_addr);
return send_err;
}
static u32 rcsp_update_status_response(void *priv, u8 status)
{
u8 OpCode;
u8 OpCode_SN;
JL_ERR send_err = JL_ERR_NONE;
JL_controller_get_curr_cmd_para(&OpCode, &OpCode_SN);
//log_info("get cmd para:%x %x\n", OpCode, OpCode_SN);
if (JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS == OpCode) {
send_err = JL_controller_resp_get_dev_refresh_fw_status(OpCode, OpCode_SN, status);
}
return send_err;
}
int JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len)
{
int ret = 0;
switch (OpCode) {
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_REV_DATA, data, len);
}
break;
default:
ret = 1;
break;
}
return ret;
}
static void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd)
{
if (UPDATE_LOADER_OK == cmd) {
//JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,MSG_JL_UPDATE_START,NULL,0);
set_jl_update_flag(1);
if (support_dual_bank_update_en) {
rcsp_printf(">>>rcsp update succ\n");
update_result_set(UPDATA_SUCC);
}
} else {
rcsp_printf(">>>update loader err\n");
#if 1//(RCSP_MODE == RCSP_MODE_SOUNDBOX)
rcsp_update_fail_and_resume();
#endif
/* #if OTA_TWS_SAME_TIME_ENABLE */
/* if((tws_ota_control(OTA_TYPE_GET) == OTA_TWS)) { */
/* tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR); */
/* } */
/* #endif */
//rcsp_db_update_fail_deal();
}
}
extern u32 ex_cfg_fill_content_api(void);
static void rcsp_update_private_param_fill(UPDATA_PARM *p)
{
u32 exif_addr = ex_cfg_fill_content_api();
memcpy(p->parm_priv, (u8 *)&exif_addr, sizeof(exif_addr));
}
static void rcsp_update_change_mtu(u16 new_mtu)
{
u8 buf[2] = {0};
buf[0] = ((u8 *)&new_mtu)[1];
buf[1] = ((u8 *)&new_mtu)[0];
u16 current_update_ble_con_hdl = 0;
u8 current_update_spp_addr[6] = {0};
rcsp_get_update_hdl(&current_update_ble_con_hdl, current_update_spp_addr);
JL_CMD_send(JL_OPCODE_NOTIFY_MTU, (u8 *)buf, sizeof(buf), JL_NOT_NEED_RESPOND, current_update_ble_con_hdl, current_update_spp_addr);
}
extern void register_user_chip_update_handle(const user_chip_update_t *user_update_ins);
extern void bt_adv_seq_change(void);
extern int bt_tws_poweroff();
extern void bt_wait_phone_connect_control(u8 enable);
extern int tws_api_get_role(void);
extern void tws_cancle_all_noconn();
extern void bt_ble_rcsp_adv_enable(void);
extern u32 ex_cfg_fill_content_api(void);
extern void update_param_priv_fill(UPDATA_PARM *p, void *priv, u16 priv_len);
#if RCSP_MODE == RCSP_MODE_EARPHONE
u8 rcsp_get_update_flag(void)
{
return tws_need_update;
}
void rcsp_set_update_flag(u8 flag)
{
tws_need_update = flag;
}
u8 rcsp_update_get_role_switch(void)
{
return tws_need_role_switch;
}
void rcsp_update_set_role_switch(u8 sw)
{
tws_need_role_switch = sw;
}
void update_slave_adv_reopen(void *priv)
{
r_printf("slave reopen adv...\n");
ble_module_enable(1);
bt_ble_rcsp_adv_enable();
}
#endif
int JL_rcsp_update_msg_deal(void *hdl, u8 event, u8 *msg)
{
int ret = 0;
u16 remote_file_version;
u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR;
static int wait_edr_count = 0;
printf("---%s --- %d %d\n", __func__, __LINE__, event);
switch (event) {
case MSG_JL_DEV_DISCONNECT:
if (rcsp_send_list_is_empty() && check_ble_all_packet_sent()) {
rcsp_printf("MSG_JL_DEV_DISCONNECT\n");
ble_app_disconnect();
if (check_edr_is_disconnct()) {
puts("-need discon edr\n");
bt_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
}
if (RCSP_USE_BLE == get_curr_device_type()) {
ble_discon_timeout = sys_timeout_add(NULL, ble_discon_timeout_handle, 1000);
}
} else {
wait_response_timeout = sys_timeout_add(NULL, wait_response_and_disconn_ble, 100);
}
break;
case MSG_JL_LOADER_DOWNLOAD_START:
printf("---%s --- %d\n", __func__, __LINE__);
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
#if (RCSP_MODE == RCSP_MODE_WATCH)
u32 update_once_req_size = 4096;
extern void ex_flash_update_once_req_size_set(u32 pack_size);
ex_flash_update_once_req_size_set(update_once_req_size);
set_jl_mtu_resv(rcsp_packet_write_alloc_len());
rcsp_update_change_mtu(rcsp_packet_write_alloc_len());
#endif
if (RCSP_USE_BLE == get_curr_device_type()) {
printf("rcsp_update_loader_download_init %d\n", __LINE__);
rcsp_update_loader_download_init(BLE_APP_UPDATA, rcsp_loader_download_result_handle);
} else if (RCSP_USE_SPP == get_curr_device_type()) {
printf("rcsp_update_loader_download_init %d\n", __LINE__);
rcsp_update_loader_download_init(SPP_APP_UPDATA, rcsp_loader_download_result_handle);
}
break;
case MSG_JL_UPDATE_START:
// loader加载完成,开始进入loader升级
if (check_edr_is_disconnct() && wait_edr_count < 20) {
rcsp_printf("b");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0);
wait_edr_count++;
break;
}
wait_edr_count = 0;
// 单备份的loader都是使用ble
rcsp_printf("BLE_APP_UPDATE\n");
update_mode_api_v2(BLE_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
/* sys_timeout_add(NULL, wait_response_and_disconn_spp, 100); */
break;
default:
ret = 1;
break;
}
return ret;
}
static u8 rcsp_update_flag = 0;
void set_rcsp_db_update_status(u8 value)
{
rcsp_update_flag = value;
}
u8 get_rcsp_db_update_status()
{
return rcsp_update_flag;
}
void rcsp_before_enter_db_update_mode() //进入双备份升级前
{
r_printf("%s", __func__);
rcsp_update_flag = 1;
void sys_auto_shut_down_disable(void);
if (bt_get_total_connect_dev() == 0) {
sys_auto_shut_down_disable();
}
#if TCFG_USER_TWS_ENABLE
int tws_api_get_role(void);
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
return;
}
#endif
#if !TCFG_USER_TWS_ENABLE
bt_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
bt_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
#endif
}
extern void sys_auto_shut_down_enable(void);
void rcsp_db_update_fail_deal() //双备份升级失败处理
{
r_printf("%s", __func__);
if (rcsp_update_flag) {
rcsp_update_flag = 0;
if (bt_get_total_connect_dev() == 0) {
sys_auto_shut_down_enable();
}
}
/* cpu_reset(); //升级失败直接复位 */
}
#else // (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
//以下函数是为了编译通过
int JL_rcsp_update_msg_deal(void *hdl, u8 event, u8 *msg)
{
printf("%s:NULL", __func__);
return 0;
}
void set_jl_update_flag(u8 flag)
{
printf("%s:NULL", __func__);
}
void update_slave_adv_reopen(void *priv)
{
printf("%s:NULL", __func__);
}
void rcsp_set_update_flag(u8 flag)
{
printf("%s:NULL", __func__);
}
void rcsp_update_set_role_switch(u8 sw)
{
printf("%s:NULL", __func__);
}
u8 get_jl_update_flag(void)
{
printf("%s:NULL", __func__);
return 0;
}
u8 rcsp_get_update_flag(void)
{
printf("%s:NULL", __func__);
return 0;
}
u8 get_update_ex_flash_flag(void)
{
return 0;
}
void set_update_ex_flash_flag(u8 update_flag)
{
}
int JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len)
{
return -1;
}
int JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr)
{
return -1;
}
#endif // (RCSP_MODE && RCSP_UPDATE_EN && !RCSP_BLE_MASTER && TCFG_APP_UPDATE_EN)
@@ -0,0 +1,19 @@
#ifndef _RCSP_UPDATE_H_
#define _RCSP_UPDATE_H_
//#include "rcsp_protocol.h"
//#include "rcsp_packet.h"
#include "typedef.h"
int JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len, u16 ble_con_handle, u8 *spp_remote_addr);
int JL_rcsp_update_msg_deal(void *hdl, u8 event, u8 *msg);
int JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len);
u8 get_jl_update_flag(void);
void set_jl_update_flag(u8 flag);
u8 get_curr_device_type(void);
void update_slave_adv_reopen(void *priv);
u8 rcsp_update_get_role_switch(void);
#endif
@@ -0,0 +1,759 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rcsp_update_tws.data.bss")
#pragma data_seg(".rcsp_update_tws.data")
#pragma const_seg(".rcsp_update_tws.text.const")
#pragma code_seg(".rcsp_update_tws.text")
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "generic/circular_buf.h"
#include "os/os_api.h"
#include "update_loader_download.h"
#include "system/task.h"
#include "system/timer.h"
#include "init.h"
#include "rcsp_update_tws.h"
#include "dual_bank_updata_api.h"
#include "bt_tws.h"
#include "app_config.h"
#include "btstack/avctp_user.h"
#include "update.h"
#include "app_main.h"
#if ((RCSP_MODE == RCSP_MODE_SOUNDBOX) && OTA_TWS_SAME_TIME_ENABLE)
//#define LOG_TAG_CONST EARPHONE
#define LOG_TAG "[UPDATE_TWS]"
#define log_errorOR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define THIS_TASK_NAME "tws_ota"
#define SLAVE_REV_BUF_LEN 1024*2
enum {
TWS_UPDATE_START,
TWS_UPDATE_RESULT_EXCHANGE,
TWS_UPDATE_RESULT_EXCHANGE_RES,
TWS_UPDATE_OVER,
TWS_UPDATE_OVER_CONFIRM,
TWS_UPDATE_OVER_CONFIRM_REQ,
TWS_UPDATE_OVER_CONFIRM_RES,
TWS_UPDATE_VERIFY,
};
extern void sys_enter_soft_poweroff(void *priv);
void db_update_notify_fail_to_phone();
struct __tws_ota_var {
OS_SEM master_sem;
OS_SEM slave_sem;
OS_SEM confirm_sem;
struct __tws_ota_para para;
u8 ota_type;
u8 ota_status;
u8 ota_remote_status;
u8 ota_result;
volatile u32 ota_data_len;
u16 ota_timer_id;
u8 ota_verify_cnt;
volatile u32 ota_confirm;
cbuffer_t cbuffer;
u8 *slave_r_buf;
};
struct __tws_ota_var tws_ota_var;
#define __this (&tws_ota_var)
void tws_ota_event_post(u32 type, u8 event)
{
struct sys_event e;
e.type = SYS_BT_EVENT;
e.arg = (void *)type;
e.u.bt.event = event;
sys_event_notify(&e);
}
u8 tws_ota_control(int type, ...)
{
int ret = 0;
int role = 0;
int value = 0;
va_list argptr;
va_start(argptr, type);
switch (type) {
case OTA_TYPE_SET:
value = va_arg(argptr, int);
__this->ota_type = value;
break;
case OTA_TYPE_GET:
ret = __this->ota_type;
break;
case OTA_STATUS_SET:
value = va_arg(argptr, int);
__this->ota_status = value;
break;
case OTA_STATUS_GET:
ret = __this->ota_status;
break;
case OTA_REMOTE_STATUS_SET:
value = va_arg(argptr, int);
__this->ota_remote_status = value;
break;
case OTA_REMOTE_STATUS_GET:
ret = __this->ota_remote_status;
break;
case OTA_RESULT_SET:
value = va_arg(argptr, int);
role = va_arg(argptr, int);
if (value == 1) {
__this->ota_result |= BIT(role);
} else {
__this->ota_result &= ~BIT(role);
}
break;
case OTA_RESULT_GET:
ret = __this->ota_result;
break;
}
va_end(argptr);
return ret;
}
int tws_ota_init(void)
{
memset((u8 *)__this, 0, sizeof(struct __tws_ota_var));
__this->ota_status = OTA_INIT;
__this->ota_type = OTA_TWS;
if (a2dp_get_status() == BT_MUSIC_STATUS_STARTING) {
/* log_info("try pause a2dp music"); */
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PAUSE, 0, NULL);
}
return 0;
}
#define TWS_FUNC_ID_OTA_SYNC TWS_FUNC_ID('O', 'T', 'A', 'S')
static void tws_ota_data_read_s_from_m(void *_data, u16 len, bool rx)
{
if (rx && __this->ota_status == OTA_START && __this->slave_r_buf) {
/* r_log_info("Offset:%x r_len:%d\n",__this->ota_data_len,len); */
/* put_buf(_data, len); */
__this->ota_data_len += len;
if (cbuf_is_write_able(&(__this->cbuffer), len)) {
cbuf_write(&(__this->cbuffer), _data, len);
} else {
log_info("ota cbuf write err\n");
}
os_sem_post(&__this->slave_sem);
}
}
REGISTER_TWS_FUNC_STUB(app_ota_sync_stub) = {
.func_id = TWS_FUNC_ID_OTA_SYNC,
.func = tws_ota_data_read_s_from_m,
};
int tws_ota_data_send_m_to_s(u8 *buf, u16 len)
{
if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) {
return 0;
}
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
return 0;
}
int ret = tws_api_send_data_to_slave(buf, len, TWS_FUNC_ID_OTA_SYNC);
return ret;
}
int tws_ota_err_callback(u8 reason)
{
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR);
return 0;
}
static void tws_ota_update_loop(void *priv)
{
u32 total_len = 0;
u32 len = 0;
u8 *tmp_buf = NULL;
int ret = 0;
u8 sniff_wait_exit_timeout = 30;//3s
log_info("tws_ota_update_loop\n");
while (1) {
os_sem_pend(&__this->slave_sem, 0);
if (sniff_wait_exit_timeout) {
//wait slave exit sniff
extern u8 btstcak_get_bt_mode(void);
while (btstcak_get_bt_mode() && sniff_wait_exit_timeout--) {
log_info("wait sniff exit \n");
os_time_dly(10);
}
log_info(">>>>>>>sniff timeout:%d \n", sniff_wait_exit_timeout);
if (!sniff_wait_exit_timeout) {
log_info(">>>>>>wait sniff exit timeout !!!! \n");
}
sniff_wait_exit_timeout = 0;
dual_bank_passive_update_init(__this->para.fm_crc16, __this->para.fm_size, __this->para.max_pkt_len, NULL);
ret = dual_bank_update_allow_check(__this->para.fm_size);
if (ret) {
log_info("fm_size:%x can't update\n", __this->para.fm_size);
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR);
continue;
}
tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_UPDATE, 400);
continue;
}
total_len = cbuf_get_data_size(&(__this->cbuffer));
/* log_info("total_len : %d\n",total_len); */
while (total_len) {
if (total_len > get_dual_bank_passive_update_max_buf()) {
len = get_dual_bank_passive_update_max_buf();
} else {
len = total_len;
}
if (!len) {
continue;
}
tmp_buf = malloc(len);
if (tmp_buf) {
if (cbuf_read(&(__this->cbuffer), tmp_buf, len) == len) {
putchar('D');
dual_bank_update_write(tmp_buf, len, NULL);
} else {
log_error("read err\n");
}
free(tmp_buf);
} else {
log_error("malloc err\n");
}
total_len -= len;
}
}
}
static void ota_finish_confirm(void *priv)
{
log_info("ota_finish_confirm:%d\n", __this->ota_confirm);
if (!__this->ota_confirm) {
//ota tws confirm err,earse boot info
flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK);
/* ASSERT(0, "ota tws confirm err\n"); */
}
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_SUCC);
}
u16 tws_ota_enter_verify(void *priv)
{
if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) {
log_info("tws_disconn in verify\n");
db_update_notify_fail_to_phone();
return -1;
}
tws_ota_send_data_to_sibling(TWS_UPDATE_VERIFY, NULL, 0);
os_sem_pend(&__this->master_sem, 1000);
//这里pend完,要做超时的准备
if (__this->ota_status == OTA_VERIFY_ING) {
return 0;
} else {
db_update_notify_fail_to_phone();
return -1;
}
}
u16 tws_ota_exit_verify(u8 *res, u8 *up_flg)
{
//not updata boot info in lib
*up_flg = 1;
u8 tws_ota_result[2];
u8 master_result = *res;
u8 result = 0;
tws_ota_control(OTA_STATUS_SET, OTA_VERIFY_END);
tws_ota_control(OTA_RESULT_SET, !master_result, TWS_ROLE_MASTER);
__RESTART:
if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) {
db_update_notify_fail_to_phone();
return 0;
}
result = tws_ota_control(OTA_RESULT_GET);
tws_ota_result[0] = result;
tws_ota_result[1] = tws_ota_control(OTA_STATUS_GET);
tws_ota_send_data_to_sibling(TWS_UPDATE_RESULT_EXCHANGE, (u8 *)&tws_ota_result, 2);
if ((result & BIT(TWS_ROLE_SLAVE)) && (result & BIT(TWS_ROLE_SLAVE))) {
log_info("tws already ota succ1\n");
os_sem_set(&__this->master_sem, 0);
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_OVER);
return 1;
} else if (__this->ota_remote_status == OTA_VERIFY_END || __this->ota_remote_status == OTA_OVER) {
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR);
return 0;
} else {
os_sem_pend(&__this->master_sem, 200);
goto __RESTART;
}
return 1;
}
u16 tws_ota_updata_boot_info_over(void *priv)
{
log_info("master update_burn_boot_info succ\n");
if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) {
log_info("tws_disconn, ota open fail");
db_update_notify_fail_to_phone();
return -1;
}
//等待从机更新完成
log_info("1------pend in");
os_sem_pend(&__this->confirm_sem, 300);
log_info("1------pend out");
log_info("-------mz01");
if (__this->ota_confirm) {
log_info("-------mz02");
os_sem_set(&__this->confirm_sem, 0);
tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM_REQ, NULL, 0);
log_info("2------pend in");
if (OS_TIMEOUT == os_sem_pend(&__this->confirm_sem, 300)) {
__this->ota_confirm = 0;
}
log_info("2------pend out");
}
if (!__this->ota_confirm) {
log_info("-------mz03");
//ota tws confirm err,earse boot info
flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK);
/* ASSERT(0, "ota tws confirm err\n"); */
return -1;
}
/* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_UPDATE_SUCC); //主机等手机发重启命令*/
return 0;
}
int tws_ota_open(struct __tws_ota_para *para)
{
int ret = 0;
log_info("tws_ota_open\n");
if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) {
log_info("tws_disconn, ota open fail");
db_update_notify_fail_to_phone();
return -1;
}
os_sem_create(&__this->master_sem, 0);
os_sem_create(&__this->slave_sem, 0);
os_sem_create(&__this->confirm_sem, 0);
if (tws_api_get_role() == TWS_ROLE_MASTER) {
extern void bt_check_exit_sniff();
bt_check_exit_sniff();
//master 发命令给slave启动升级
log_info("master updata info: crc16:%x size:%x max_pkt_len:%d\n", para->fm_crc16, para->fm_size, para->max_pkt_len);
if (__this->ota_type == OTA_TWS) {
tws_ota_send_data_to_sibling(TWS_UPDATE_START, (u8 *)para, sizeof(struct __tws_ota_para));
log_info("sem pend in ...");
os_sem_pend(&__this->master_sem, 600);
log_info("sem pend out ...");
//判断对耳状态
if (__this->ota_status == OTA_START) {
log_info("slave has ready");
ret = 0;
} else {
log_info("slave answer timeout");
db_update_notify_fail_to_phone();
ret = -1;
}
}
} else {
log_info("slave updata info: crc16:%x size:%x max_pkt_len:%d\n", para->fm_crc16, para->fm_size, para->max_pkt_len);
/* tws_api_sync_call_by_uuid('T', SYNC_CMD_START_UPDATE, 100); */
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_UPDATE_READY);
}
return ret;
}
int tws_ota_close(void)
{
int ret = 0;
log_info("%s", __func__);
if (__this->slave_r_buf) {
free(__this->slave_r_buf);
__this->slave_r_buf = 0;
task_kill(THIS_TASK_NAME);
}
return ret;
}
static void ota_verify_timeout(void *priv)
{
log_info("ota_verify_timeout:%x %x\n", __this->para.fm_size, __this->ota_data_len);
if (__this->ota_data_len == __this->para.fm_size) {
/* tws_api_sync_call_by_uuid('T', SYNC_CMD_START_VERIFY, 100); */
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_VERIFY);
return;
}
if (__this->ota_verify_cnt > 4) {
log_info("code len err\n");
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR);
sys_timeout_del(__this->ota_timer_id);
__this->ota_timer_id = 0;
return;
}
__this->ota_verify_cnt ++;
__this->ota_timer_id = 0;
__this->ota_timer_id = sys_timeout_add(NULL, ota_verify_timeout, 500);
}
int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len)
{
u8 tws_ota_result[2];
switch (opcode) {
//master->slave
case TWS_UPDATE_START:
log_info("TWS_AI_START_UPDATE:%d\n", opcode);
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
if (__this->slave_r_buf) {
tws_ota_close();
}
tws_ota_init();
memcpy((u8 *) & (__this->para), data, len);
tws_ota_open(&(__this->para));
}
break;
//master->slave
case TWS_UPDATE_RESULT_EXCHANGE:
log_info("TWS_UPDATE_RESULT_EXCHANGE:%d %d\n", data[0], data[1]);
__this->ota_remote_status = data[1];
tws_ota_control(OTA_RESULT_SET, (data[0] & BIT(TWS_ROLE_MASTER) ? 1 : 0), TWS_ROLE_MASTER);
tws_ota_result[0] = __this->ota_result;
tws_ota_result[1] = __this->ota_status;
tws_ota_send_data_to_sibling(TWS_UPDATE_RESULT_EXCHANGE_RES, (u8 *)tws_ota_result, 2);
log_info("master ota result:%x %d\n", tws_ota_control(OTA_RESULT_GET), __this->ota_status);
break;
//slave->master
case TWS_UPDATE_RESULT_EXCHANGE_RES:
log_info("TWS_UPDATE_RESULT_EXCHANGE_RES:%d %d\n", data[0], data[1]);
__this->ota_remote_status = data[1];
tws_ota_control(OTA_RESULT_SET, (data[0] & BIT(TWS_ROLE_SLAVE) ? 1 : 0), TWS_ROLE_SLAVE);
log_info("slave ota result:%x %d\n", tws_ota_control(OTA_RESULT_GET), __this->ota_status);
if (tws_ota_control(OTA_RESULT_GET) & BIT(TWS_ROLE_SLAVE)) {
os_sem_post(&__this->master_sem);
}
break;
//master->slave
case TWS_UPDATE_VERIFY:
log_info("TWS_UPDATE_VERIFY\n");
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_VERIFY);
break;
case TWS_UPDATE_OVER:
log_info("TWS_AI_UPDATE_OVER:%d\n", opcode);
__this->ota_status = OTA_OVER;
break;
//slave to master
case TWS_UPDATE_OVER_CONFIRM:
log_info("TWS_UPDATE_OVER_CONFIRM\n");
__this->ota_confirm = 1;
if (tws_api_get_role() == TWS_ROLE_MASTER) {
log_info("1------post");
os_sem_post(&__this->confirm_sem);
}
break;
//master->slave
case TWS_UPDATE_OVER_CONFIRM_REQ:
log_info("TWS_UPDATE_OVER_CONFIRM_REQ\n");
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
__this->ota_confirm = 1;
tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM_RES, NULL, 0);
log_info("2------post");
os_sem_post(&__this->confirm_sem);
}
break;
//slave->master
case TWS_UPDATE_OVER_CONFIRM_RES:
log_info("TWS_UPDATE_OVER_CONFIRM_RES\n");
if (tws_api_get_role() == TWS_ROLE_MASTER) {
log_info("3------post");
os_sem_post(&__this->confirm_sem);
}
break;
}
return 0;
}
void tws_ota_send_data_to_sibling(u8 opcode, u8 *data, u8 len)
{
extern void tws_data_to_sibling_send(u8 opcode, u8 * data, u8 len);
tws_data_to_sibling_send(opcode, data, len);
}
u8 dual_bank_update_burn_boot_info_callback(u8 ret)
{
if (ret) {
log_info("update_burn_boot_info err\n");
} else {
log_info("slave update_burn_boot_info succ\n");
tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM, NULL, 0);
//not recive master confirm
log_info("3------pend in");
os_sem_pend(&__this->confirm_sem, 300);
log_info("3------pend out");
if (!__this->ota_confirm) {
//ota tws confirm err,earse boot info
flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK);
/* ASSERT(0, "ota tws confirm err\n"); */
return 0;
}
//确保从机的回复命令送达到主机
os_time_dly(50);
tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_SUCC);
return 0;
}
return 1;
}
//slave ota result
static sint32_t gma_ota_slave_result(int crc_res)
{
u8 ret = crc_res;
tws_ota_control(OTA_STATUS_SET, OTA_VERIFY_END);
tws_ota_control(OTA_RESULT_SET, crc_res, TWS_ROLE_SLAVE);
log_info("gma_ota_slave_result:%d %d\n", crc_res, tws_ota_control(OTA_STATUS_GET));
return 0;
}
int tws_ota_sync_cmd(int reason)
{
int ret = 1;
switch (reason) {
//slave request
case SYNC_CMD_START_UPDATE:
log_info("SYNC_CMD_START_UPDATE\n");
if (__this->ota_status != OTA_INIT) {
log_info("tws ota no init");
break;
}
__this->ota_status = OTA_START;
__this->ota_data_len = 0;
__this->ota_remote_status = OTA_START;
if (tws_api_get_role() == TWS_ROLE_MASTER) {
os_sem_post(&__this->master_sem);
} else {
}
break;
//slave request
case SYNC_CMD_START_VERIFY:
log_info("SYNC_CMD_START_VERIFY\n");
__this->ota_status = OTA_VERIFY_ING;
__this->ota_remote_status = OTA_VERIFY_ING;
if (tws_api_get_role() == TWS_ROLE_MASTER) {
os_sem_post(&__this->master_sem);
} else {
dual_bank_update_verify(NULL, NULL, gma_ota_slave_result);
}
break;
//master request
case SYNC_CMD_UPDATE_OVER:
log_info("SYNC_CMD_UPDATE_OVER\n");
__this->ota_status = OTA_OVER;
__this->ota_remote_status = OTA_OVER;
if ((__this->ota_result & BIT(TWS_ROLE_MASTER)) && (__this->ota_result & BIT(TWS_ROLE_SLAVE))) {
log_info("OTA SUCCESS\n");
//update boot info
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
dual_bank_update_burn_boot_info(dual_bank_update_burn_boot_info_callback);
}
} else {
log_info("OTA ERR\n");
/* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_UPDATE_SUCC); */
}
break;
//slave request
case SYNC_CMD_UPDATE_ERR:
log_info("SYNC_CMD_UPDATE_ERR\n");
if (tws_api_get_role() == TWS_ROLE_MASTER) {
} else {
tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR);
}
break;
default:
ret = 0;
break;
}
return ret;
}
void tws_ota_app_event_deal(u8 event)
{
if (__this->ota_status == OTA_OVER) {
return;
}
switch (event) {
case TWS_EVENT_CONNECTION_DETACH:
/* case TWS_EVENT_PHONE_LINK_DETACH: */
case TWS_EVENT_REMOVE_PAIRS:
log_info("stop ota : %d --1\n", event);
tws_ota_stop(OTA_STOP_LINK_DISCONNECT);
break;
default:
break;
}
}
void tws_ota_stop(u8 reason)
{
log_info("%s", __func__);
if (__this->ota_status != OTA_OVER) {
//reconnect hfp when start err
if (reason == OTA_STOP_APP_DISCONNECT || reason == OTA_STOP_UPDATE_OVER_ERR) {
//在更新信息的时候,手机app断开
/* if(tws_api_get_role() == TWS_ROLE_MASTER) { */
/* extern void user_post_key_msg(u8 user_msg); */
/* user_post_key_msg(USER_TWS_OTA_RESUME); */
/* } */
}
__this->ota_status = OTA_OVER;
if (__this->ota_timer_id) {
sys_timeout_del(__this->ota_timer_id);
__this->ota_timer_id = 0;
}
tws_ota_close();
dual_bank_passive_update_exit(NULL);
extern void rcsp_db_update_fail_deal(); //双备份升级失败处理
rcsp_db_update_fail_deal();
}
}
int bt_ota_event_handler(struct bt_event *bt)
{
int ret = 0;
switch (bt->event) {
case OTA_START_UPDATE:
log_info("OTA_START_UPDATE\n");
tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_UPDATE, 400);
break;
case OTA_START_UPDATE_READY:
log_info("OTA_START_UPDATE_READY:%x %x %d\n", __this->para.fm_crc16, __this->para.fm_size, __this->para.max_pkt_len);
extern void rcsp_before_enter_db_update_mode();
rcsp_before_enter_db_update_mode();
if (__this->slave_r_buf) {
ASSERT(0, "tws_ota_update_loop already exit\n");
}
task_create(tws_ota_update_loop, NULL, THIS_TASK_NAME);
__this->slave_r_buf = malloc(SLAVE_REV_BUF_LEN);
ASSERT(__this->slave_r_buf, "slave_r_buf malloc err\n");
cbuf_init(&(__this->cbuffer), __this->slave_r_buf, SLAVE_REV_BUF_LEN);
os_sem_post(&__this->slave_sem);
/* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_START_UPDATE); */
break;
case OTA_START_VERIFY:
log_info("OTA_START_VERIFY\n");
if (__this->ota_data_len == __this->para.fm_size) {
tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_VERIFY, 1000);
} else {
if (__this->ota_timer_id) {
sys_timeout_del(__this->ota_timer_id);
__this->ota_timer_id = 0;
}
__this->ota_timer_id = sys_timeout_add(NULL, ota_verify_timeout, 500);
}
break;
case OTA_UPDATE_OVER:
log_info("OTA_UPDATE_OVER\n");
tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_UPDATE_OVER, 400);
break;
case OTA_UPDATE_ERR:
log_info("OTA_UPDATE_ERR\n");
tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_UPDATE_ERR, 400);
break;
case OTA_UPDATE_SUCC:
log_info("OTA_UPDATE_SUCC\n");
update_result_set(UPDATA_SUCC);
dual_bank_passive_update_exit(NULL);
/* update_result_set(UPDATA_SUCC); */
/* extern void cpu_reset(); */
/* cpu_reset(); */
//user_ctl.shutdown_need_adv = 0;
sys_enter_soft_poweroff((void *)1);
break;
default:
break;
}
return 0;
}
static void rcsp_tws_ota_sync_handler(int reason, int err)
{
tws_ota_sync_cmd(reason);
}
TWS_SYNC_CALL_REGISTER(rcsp_tws_ota_sync) = {
.uuid = 0xA2E22223,
.task_name = "app_core",
.func = rcsp_tws_ota_sync_handler,
};
#endif
@@ -0,0 +1,92 @@
#ifndef RCSP_UPDATE_TWS_H
#define RCSP_UPDATE_TWS_H
#include "app_config.h"
#if ((RCSP_MODE == RCSP_MODE_SOUNDBOX) && OTA_TWS_SAME_TIME_ENABLE)
#define SYS_BT_OTA_EVENT_TYPE_STATUS (('O' << 24) | ('T' << 16) | ('A' << 8) | '\0')
#include "system/event.h"
#include "update_loader_download.h"
typedef int sint32_t;
enum {
OTA_OVER = 0,
OTA_INIT,
OTA_START,
OTA_VERIFY_ING,
OTA_VERIFY_END,
OTA_SUCC,
};
enum {
OTA_SINGLE_EARPHONE,
OTA_TWS,
};
enum {
OTA_START_UPDATE = 0,
OTA_START_UPDATE_READY,
OTA_START_VERIFY,
OTA_UPDATE_OVER,
OTA_UPDATE_ERR,
OTA_UPDATE_SUCC,
};
enum {
OTA_TYPE_SET = 0,
OTA_TYPE_GET,
OTA_STATUS_SET,
OTA_STATUS_GET,
OTA_REMOTE_STATUS_SET,
OTA_REMOTE_STATUS_GET,
OTA_RESULT_SET,
OTA_RESULT_GET,
};
enum {
OTA_STOP_APP_DISCONNECT,
OTA_STOP_LINK_DISCONNECT,
OTA_STOP_UPDATE_OVER_SUCC,
OTA_STOP_UPDATE_OVER_ERR,
OTA_STOP_PHONE,
};
enum {
SYNC_CMD_START_UPDATE,
SYNC_CMD_START_VERIFY,
SYNC_CMD_UPDATE_OVER,
SYNC_CMD_UPDATE_ERR,
};
int tws_ota_init(void);
int tws_ota_close(void);
int tws_ota_open(struct __tws_ota_para *para);
void tws_ota_stop(u8 reason);
u16 tws_ota_enter_verify(void *priv);
u16 tws_ota_exit_verify(u8 *res, u8 *up_flg);
u16 tws_ota_updata_boot_info_over(void *priv);
int tws_ota_err_callback(u8 reason);
int tws_ota_data_send_m_to_s(u8 *buf, u16 len);
int tws_ota_sync_cmd(int reason);
void tws_ota_app_event_deal(u8 event);
u8 dual_bank_update_burn_boot_info_callback(u8 ret);
int bt_ota_event_handler(struct bt_event *bt);
void tws_ota_event_post(u32 type, u8 event);
u8 tws_ota_control(int type, ...);
void tws_ota_send_data_to_sibling(u8 opcode, u8 *data, u8 len);
int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len);
#endif // ((RCSP_MODE == RCSP_MODE_SOUNDBOX) && OTA_TWS_SAME_TIME_ENABLE)
#endif // RCSP_UPDATE_TWS_H
@@ -0,0 +1,871 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".nfc_data_opt.data.bss")
#pragma data_seg(".nfc_data_opt.data")
#pragma const_seg(".nfc_data_opt.text.const")
#pragma code_seg(".nfc_data_opt.text")
#endif
#include "rcsp_config.h"
#include "nfc_data_opt.h"
#include "rcsp_browser.h"
#include "rcsp_event.h"
#if (RCSP_MODE && JL_RCSP_SENSORS_DATA_OPT && JL_RCSP_NFC_DATA_OPT)
#define FTP_DOWNLOAD_FOLDER_NAME "download" //下载目录
#define WATCH_NFC_MSG_TRANS_BACK "w_nfc_back"
#define WATCH_NFC_ID_MAX 10
#pragma pack(1)
typedef struct nfc_msg_head_t {
u16 nfc_file_id;
u16 reserver;
u32 dev_hanlder;
u32 update_time;
u8 nfc_file_name[6];
u8 nfc_nick_name[24];
u16 data_len; // crc + nfc_unique_id
u16 crc;
} nfc_msg_head;
#pragma pack()
enum {
NFC_DATA_INFO_SYNC_BEGIN,
NFC_DATA_INFO_SYNC_END,
NFC_DATA_INFO_MODIFY,
NFC_DATA_INFO_DELETE,
NFC_DATA_INFO_UPDATE,
NFC_DATA_INFO_DEFAULT_ID,
NFC_DATA_INFO_INSERT,
NFC_DATA_INFO_INSERT_FINISH,
};
enum {
NFC_DATA_INFO_MODIFY_TIME,
NFC_DATA_INFO_MODIFY_NICE_NAME,
};
enum {
NFC_DATA_INFO_DEFAULT_ID_GET,
NFC_DATA_INFO_DEFAULT_ID_SET,
NFC_DATA_INFO_DEFAULT_ID_NOTIFY,
};
struct __nfc_file_msg {
struct __dev *dev;
u32 handler;
u8 OpCode_SN;
u8 op;
};
static struct __nfc_file_msg *g_nfc_file_msg = NULL;
static u32 g_nfc_file_index_record = 0;
static int get_nfc_file_prepare(u32 dev_handle)
{
char *logo = rcsp_browser_dev_remap(dev_handle);
if (NULL == logo) {
printf("g_nfc_file_msg logo is null");
return -1;
}
struct __dev *dev = dev_manager_find_spec(logo, 0);
if (NULL == dev) {
printf("g_nfc_file_msg dev is null");
return -1;
}
if (NULL == g_nfc_file_msg) {
g_nfc_file_msg = zalloc(sizeof(struct __nfc_file_msg));
if (NULL == g_nfc_file_msg) {
printf("g_nfc_file_msg zalloc err\n");
return -1;
}
g_nfc_file_msg->dev = dev;
}
return 0;
}
static int nfc_id_default_get_from_vm(u8 *data, u16 data_len)
{
if (data_len != syscfg_read(VM_WATCH_DEFAULT_NFC_ID, data, data_len)) {
printf("%s, read vm fail\n", __func__);
return -1;
}
return 0;
}
static int nfc_id_default_set_to_vm(u8 *data, u16 data_len)
{
u8 *tmp_data = zalloc(data_len);
if (NULL == tmp_data) {
printf("%s, no enough memory!!\n", __func__);
goto __nfc_id_default_set_to_vm_end;
}
if (nfc_id_default_get_from_vm(tmp_data, data_len)) {
memset(tmp_data, 0xff, data_len);
}
if (0 == memcmp(data, tmp_data, data_len)) {
goto __nfc_id_default_set_to_vm_end;
}
syscfg_write(VM_WATCH_DEFAULT_NFC_ID, data, data_len);
__nfc_id_default_set_to_vm_end:
if (tmp_data) {
free(tmp_data);
}
return 0;
}
static void creat_file_path(char *path, char *root_path, const char *folder, u8 *name, u16 name_len)
{
strcat(path, root_path);
if (folder) {
strcat(path, folder);
strcat(path, "/");
}
if (name) {
memcpy(path + strlen(path), name, name_len);
}
}
static u32 creat_path_len(char *root_path, const char *folder, u8 *name, u16 name_len)
{
u32 len = (strlen(root_path) + strlen(folder) + name_len + 1);
if (folder) {
len += strlen("/");
}
return len;
}
static int get_nfc_file_path(u8 *path[], u8 file_index, u8 *file_name)
{
if (NULL == g_nfc_file_msg) {
printf("%s, g_nfc_file_msg is null\n", __func__);
goto __get_nfc_file_path_err;
}
char *root_path = dev_manager_get_root_path(g_nfc_file_msg->dev);
char *folder = NULL;
if (RCSPDevMapSD1 == g_nfc_file_msg->handler) {
folder = FTP_DOWNLOAD_FOLDER_NAME;
}
char tmp_name[] = "00.nfc";
if (*path) {
free(*path);
*path = NULL;
}
if (NULL == *path) {
if (file_name) {
*path = zalloc(creat_path_len(root_path, folder, file_name, strlen(file_name) + 1));
} else {
*path = zalloc(creat_path_len(root_path, folder, tmp_name, strlen(tmp_name) + 1));
}
}
if (NULL == *path) {
printf("%s, no enough memory!!\n", __func__);
goto __get_nfc_file_path_err;
}
if (file_index) {
tmp_name[0] = (file_index / 10) + '0';
tmp_name[1] = (file_index % 10) + '0';
}
if (file_name) {
creat_file_path(*path, root_path, folder, file_name, strlen(file_name));
} else {
creat_file_path(*path, root_path, folder, tmp_name, strlen(tmp_name));
}
return 0;
__get_nfc_file_path_err:
if (*path) {
free(*path);
*path = NULL;
}
return -1;
}
static u8 file_trans_back_response_send(u8 *data, u16 len, u8 dire, u8 OpCode_SN)
{
u8 ret = 0;
switch (dire) {
case 0:
ret = JL_CMD_response_send(JL_OPCODE_SENSOR_NFC_FUNCTION_OPT, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, len, 0, NULL);
break;
case 1:
ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_SENSOR_NFC_FUNCTION_OPT, data, len, JL_NOT_NEED_RESPOND, 0, NULL);
break;
case 2:
ret = JL_CMD_send(JL_OPCODE_SENSOR_NFC_FUNCTION_OPT, data, len, JL_NOT_NEED_RESPOND, 0, NULL);
break;
case 0xFF:
ret = JL_CMD_response_send(JL_OPCODE_SENSOR_NFC_FUNCTION_OPT, JL_PRO_STATUS_FAIL, OpCode_SN, data, len, 0, NULL);
break;
}
return ret;
}
static int nfc_file_read(char *path, u8 *buffer, u16 buffer_size, u8 offset, u8 *reason, u8 *file_index_record)
{
u8 ret = 0;
FILE *file = fopen(path, "r");
if (NULL == file) {
printf("%s, file open fail\n", __func__);
goto __nfc_file_read_end;
}
u32 nfc_data_len = sizeof(nfc_msg_head) - 2;
if (nfc_data_len > buffer_size - offset) {
ret = file_trans_back_response_send(buffer, offset, 1, g_nfc_file_msg->op);
offset = 0;
if (ret) {
// 错误
printf("%s, send data err : %d, %d", __func__, ret, offset);
*reason = ret;
goto __nfc_file_read_end;
}
}
nfc_msg_head *nfc_msg = (nfc_msg_head *)(buffer + offset);
offset += fread(file, buffer + offset, nfc_data_len);
u8 crc_uuid_len = ((u8 *)&nfc_msg->data_len)[0] << 8 | ((u8 *)&nfc_msg->data_len)[1];
if (crc_uuid_len > buffer_size - offset) {
ret = file_trans_back_response_send(buffer, offset, 1, g_nfc_file_msg->op);
offset = 0;
if (ret) {
// 错误
printf("%s, send data err : %d, %d", __func__, ret, offset);
*reason = ret;
goto __nfc_file_read_end;
}
}
fseek(file, nfc_data_len, SEEK_SET);
offset += fread(file, buffer + offset, crc_uuid_len);
*file_index_record = 1;
__nfc_file_read_end:
if (file) {
fclose(file);
file = NULL;
}
return offset;
}
static void nfc_rcsp_file_trans_back_close(void)
{
task_kill(WATCH_NFC_MSG_TRANS_BACK);
if (g_nfc_file_msg) {
free(g_nfc_file_msg);
g_nfc_file_msg = NULL;
}
}
// 返回大于0是有默认值,等于0是没有默认值,-1是错误
static u16 nfc_file_exist_check(u8 *file_index_record, u16 record_len)
{
// 读出nfc_id,如果读取失败则返回
u16 tmp_nfc_id = 0;
if (nfc_id_default_get_from_vm(&tmp_nfc_id, sizeof(tmp_nfc_id))) {
return -1;
}
// 这种情况不可能也不应该出现
if (tmp_nfc_id >= record_len) {
printf("err : %s vaild !!\n");
return -1;
}
// 判断file_index_record对用nfc_id的位置有没有值,有则返回
if (file_index_record[tmp_nfc_id]) {
return tmp_nfc_id + 1;
}
// 如果没有值,取最接近的上一个
for (u16 i = tmp_nfc_id; i > 0; i--) {
u16 tmp_index = i - 1;
if (file_index_record[tmp_index]) {
nfc_id_default_set_to_vm(&tmp_index, sizeof(tmp_index));
return tmp_index + 1;
}
}
// 如果还是没有,取最接近的下一个
for (u16 i = tmp_nfc_id + 1; i < record_len; i++) {
if (file_index_record[i]) {
nfc_id_default_set_to_vm(&i, sizeof(i));
return i + 1;
}
}
// 如果file_index_record里的值是全0,则把nfc_id对应的vm值设置为0
tmp_nfc_id = 0;
nfc_id_default_set_to_vm(&tmp_nfc_id, sizeof(tmp_nfc_id));
return 0;
}
static void nfc_file_trans_back_task(void *p)
{
u8 ret = 0;
u8 reason = 0;
u8 offset = 0;
u8 *path = NULL;
// 回复当前命令
u16 resp_data_len = JL_packet_get_tx_max_mtu() - 6;
u8 *resp_data = zalloc(resp_data_len);
u8 *file_index_record = zalloc(WATCH_NFC_ID_MAX);
if (NULL == resp_data || NULL == file_index_record) {
reason = -1;
file_trans_back_response_send(NULL, 0, (u8) - 1, g_nfc_file_msg->OpCode_SN);
goto __nfc_file_trans_back_task_err;
}
file_trans_back_response_send(&ret, sizeof(ret), 0, g_nfc_file_msg->OpCode_SN);
g_nfc_file_index_record = 0;
for (u8 i = 0; i < WATCH_NFC_ID_MAX; i++) {
// 读取文件:01~09.nfc
if (get_nfc_file_path(&path, i, NULL)) {
reason = -1;
break;
}
offset = nfc_file_read(path, resp_data, resp_data_len, offset, &reason, file_index_record + i);
if (reason) {
break;
}
if (file_index_record[i]) {
g_nfc_file_index_record |= BIT(i);
}
}
if (offset) {
// 发送
if (file_trans_back_response_send(resp_data, offset, 1, g_nfc_file_msg->op)) {
printf("%s, send data err : %d, %d", __func__, ret, offset);
reason = -1;
}
}
nfc_file_exist_check(file_index_record, WATCH_NFC_ID_MAX);
__nfc_file_trans_back_task_err:
if (path) {
free(path);
}
if (resp_data) {
free(resp_data);
}
if (file_index_record) {
free(file_index_record);
}
// 发送事件结束
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)p,
(int)g_nfc_file_msg->handler,
NFC_DATA_INFO_SYNC_BEGIN,
(int)reason, 0);
while (1) {
os_time_dly(10);
}
}
static int nfc_data_msg_modify(void *priv, u8 *data, u16 len)
{
u8 ret = 0;
u8 offset = 0;
u8 *path = NULL;
FILE *file = NULL;
u8 file_index = data[offset++] * 10 + data[offset++];
if (get_nfc_file_path(&path, file_index, NULL)) {
ret = -1;
goto __nfc_data_msg_modify_end;
}
file = fopen(path, "r");
if (file) {
fclose(file);
file = NULL;
} else {
ret = -1;
printf("%s, file open err\n", __func__);
goto __nfc_data_msg_modify_end;
}
file = fopen(path, "w+");
if (NULL == file) {
ret = -1;
printf("%s, file open err\n", __func__);
goto __nfc_data_msg_modify_end;
}
nfc_msg_head nfc_msg = {0};
fread(file, &nfc_msg, sizeof(nfc_msg));
u32 mask = data[offset++] << 24 | data[offset++] << 16 | data[offset++] << 8 | data[offset++];
// 假如是时间戳
if (mask & BIT(NFC_DATA_INFO_MODIFY_TIME)) {
memcpy(&nfc_msg.update_time, data + offset, sizeof(nfc_msg.update_time));
offset += sizeof(nfc_msg.update_time);
}
// 假如是别名
if (mask & BIT(NFC_DATA_INFO_MODIFY_NICE_NAME)) {
if (len - offset > sizeof(nfc_msg.nfc_nick_name)) {
printf("err : remote nick name len is vaild\n");
ret = -1;
goto __nfc_data_msg_modify_end;
}
memset(nfc_msg.nfc_nick_name, 0, sizeof(nfc_msg.nfc_nick_name));
memcpy(nfc_msg.nfc_nick_name, data + offset, len - offset);
}
int nfc_total_len = flen(file);
fseek(file, 0, SEEK_SET);
fwrite(file, &nfc_msg, sizeof(nfc_msg));
fseek(file, nfc_total_len, SEEK_SET);
__nfc_data_msg_modify_end:
if (path) {
free(path);
path = NULL;
}
if (file) {
fclose(file);
file = NULL;
}
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)priv,
(int)g_nfc_file_msg->handler,
NFC_DATA_INFO_MODIFY,
(int)ret,
(int)file_index);
return 0;
}
static int nfc_data_msg_default_id_get(u16 *default_nfc_id)
{
int ret = 0;
u8 *file_index_record = zalloc(WATCH_NFC_ID_MAX);
if (NULL == file_index_record) {
printf("%s, no enough memory!!\n", __func__);
ret = -1;
goto __nfc_data_msg_default_id_get_end;
}
for (u8 i = 0; i < WATCH_NFC_ID_MAX && i < sizeof(g_nfc_file_index_record); i++) {
file_index_record[i] = !!(g_nfc_file_index_record & BIT(i));
}
u16 tmp_nfc_id = nfc_file_exist_check(file_index_record, WATCH_NFC_ID_MAX);
if (0 == tmp_nfc_id || (u16) - 1 == tmp_nfc_id) {
ret = -1;
goto __nfc_data_msg_default_id_get_end;
}
*default_nfc_id = tmp_nfc_id - 1;
__nfc_data_msg_default_id_get_end:
if (file_index_record) {
free(file_index_record);
}
return ret;
}
static int nfc_data_msg_delete(void *priv, u8 *data, u16 len)
{
u8 ret = 0;
u8 offset = 0;
u8 file_index = data[offset++] * 10 + data[offset++];
u8 *path = NULL;
FILE *file = NULL;
if (get_nfc_file_path(&path, file_index, NULL)) {
ret = -1;
goto __nfc_data_msg_delete_end;
}
if ((file = fopen(path, "r"))) {
if (fdelete(file)) {
//错误
printf("%s, delete fail\n", __func__);
ret = -1;
goto __nfc_data_msg_delete_end;
}
file = NULL;
g_nfc_file_index_record &= ~BIT(file_index);
}
__nfc_data_msg_delete_end:
if (path) {
free(path);
path = NULL;
}
if (file) {
fclose(file);
file = NULL;
}
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)priv,
(int)g_nfc_file_msg->handler,
NFC_DATA_INFO_DELETE,
(int)ret,
(int)file_index);
return 0;
}
static int nfc_data_msg_insert(void *priv, u8 *data, u16 len)
{
int ret = 0;
u8 offset = 0;
u8 *path = NULL;
FILE *file = NULL;
u8 file_index = 0;
// 可以用于判断FLASH/SD卡容量是否足够
u32 file_size = data[offset++] << 24 | data[offset++] << 16 | data[offset++] << 8 | data[offset++];
u8 *nfc_file_name = zalloc(len - offset + 1);
if (NULL == nfc_file_name) {
printf("%s, no enough memory!!\n", __func__);
ret = -1;
goto __nfc_data_msg_insert_end;
}
memcpy(nfc_file_name, data + offset, len - offset);
file_index = (nfc_file_name[0] - '0') * 10 + nfc_file_name[1] - '0';
ret = get_nfc_file_path(&path, 0, nfc_file_name);
if (ret) {
goto __nfc_data_msg_insert_end;
}
if ((file = fopen(path, "r"))) {
if (fdelete(file)) {
printf("%s, delete fail\n", __func__);
ret = -1;
goto __nfc_data_msg_insert_end;
}
file = NULL;
}
__nfc_data_msg_insert_end:
if (file) {
fclose(file);
}
if (path) {
free(path);
}
if (nfc_file_name) {
free(nfc_file_name);
}
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)priv,
(int)g_nfc_file_msg->handler,
NFC_DATA_INFO_INSERT,
(int)ret,
(int)file_index);
return 0;
}
static int nfc_data_msg_insert_finish(void *priv, u8 *data, u16 len)
{
int ret = 0;
u8 *path = NULL;
FILE *file = NULL;
u16 nfc_id = 0;
u8 *nfc_file_name = zalloc(len + 1);
if (NULL == nfc_file_name) {
printf("%s, no enough memory!!\n", __func__);
ret = -1;
goto __nfc_data_msg_insert_finish_end;
}
memcpy(nfc_file_name, data, len);
ret = get_nfc_file_path(&path, 0, nfc_file_name);
if (ret) {
goto __nfc_data_msg_insert_finish_end;
}
nfc_id = (nfc_file_name[0] - '0') * 10 + (nfc_file_name[1] - '0');
if ((file = fopen(path, "r"))) {
// 读出数据
// 把数据写给nfc外设
g_nfc_file_index_record |= BIT(nfc_id);
}
__nfc_data_msg_insert_finish_end:
if (file) {
fclose(file);
}
if (path) {
free(path);
}
if (nfc_file_name) {
free(nfc_file_name);
}
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)priv,
(int)g_nfc_file_msg->handler,
NFC_DATA_INFO_INSERT_FINISH,
(int)ret,
(int)nfc_id);
return ret;
}
static int nfc_id_default_opt(void *priv, u8 *data, u16 len, u8 OpCode_SN)
{
u8 offset = 0;
u8 flag = data[offset++];
u8 resp_data[3] = {0};
u8 resp_data_len = 0;
u8 file_index = 0;
u8 op = NFC_DATA_INFO_DEFAULT_ID;
memcpy(resp_data + 1, data + offset, 2);
switch (flag) {
case NFC_DATA_INFO_DEFAULT_ID_GET:
printf("NFC_DATA_INFO_DEFAULT_ID_GET\n");
// 把id写入vm
u16 default_nfc_id = 0;
if (nfc_id_default_get_from_vm(&default_nfc_id, sizeof(default_nfc_id))) {
resp_data[0] = -1;
break;
}
resp_data[1] = ((u8 *)&default_nfc_id)[1];
resp_data[2] = ((u8 *)&default_nfc_id)[0];
resp_data_len = 3;
op = -1;
file_trans_back_response_send(resp_data, resp_data_len, 0, OpCode_SN);
break;
case NFC_DATA_INFO_DEFAULT_ID_SET:
printf("NFC_DATA_INFO_DEFAULT_ID_SET\n");
u16 nfc_id = data[offset++] << 8 | data[offset++];
if (nfc_id > WATCH_NFC_ID_MAX - 1) {
printf("%s, nfc id is vaild\n", __func__);
resp_data[0] = -1;
}
nfc_id_default_set_to_vm(&nfc_id, sizeof(nfc_id));
resp_data_len = 1;
file_index = nfc_id;
break;
}
rcsp_msg_post(
USER_MSG_RCSP_NFC_FILE_TRANS_BACK,
5,
(int)priv,
(int)g_nfc_file_msg->handler,
op,
(int)resp_data[0],
(int)file_index);
return 0;
}
static int nfc_data_opt_check(u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 offset = 0;
u32 handle = data[offset++] << 24 | data[offset++] << 16 | data[offset++] << 8 | data[offset++];
int ret = get_nfc_file_prepare(handle);
if (0 == ret) {
g_nfc_file_msg->op = OpCode;
g_nfc_file_msg->OpCode_SN = OpCode_SN;
g_nfc_file_msg->handler = handle;
}
return ret;
}
static int nfc_data_opt(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 op = 0;
u8 offset = 0;
int ret = nfc_data_opt_check(OpCode, OpCode_SN, data + offset, len - offset);
if (ret) {
goto __nfc_data_opt_end;
}
offset += 4;
op = data[offset++];
switch (op) {
case NFC_DATA_INFO_SYNC_BEGIN:
if (task_create(nfc_file_trans_back_task, priv, WATCH_NFC_MSG_TRANS_BACK)) {
ret = -1;
nfc_rcsp_file_trans_back_close();
goto __nfc_data_opt_end;
}
break;
case NFC_DATA_INFO_MODIFY:
nfc_data_msg_modify(priv, data + offset, len - offset);
break;
case NFC_DATA_INFO_DELETE:
nfc_data_msg_delete(priv, data + offset, len - offset);
break;
case NFC_DATA_INFO_DEFAULT_ID:
nfc_id_default_opt(priv, data + offset, len - offset, OpCode_SN);
break;
case NFC_DATA_INFO_INSERT:
nfc_data_msg_insert(priv, data + offset, len - offset);
break;
case NFC_DATA_INFO_INSERT_FINISH:
nfc_data_msg_insert_finish(priv, data + offset, len - offset);
break;
}
__nfc_data_opt_end:
if (ret) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)&ret, 1, 0, NULL);
file_trans_back_response_send(&ret, 1, 0, OpCode_SN);
}
return ret;
}
int nfc_id_default_notify(u32 devHeadler, u16 nfc_id)
{
int ret = 0;
u8 resp_data[] = {((u8 *)&devHeadler)[3], ((u8 *)&devHeadler)[2], ((u8 *)&devHeadler)[1], ((u8 *)&devHeadler)[0], NFC_DATA_INFO_DEFAULT_ID, NFC_DATA_INFO_DEFAULT_ID_NOTIFY, ((u8 *)&nfc_id)[1], ((u8 *)&nfc_id)[0]};
if (nfc_id > WATCH_NFC_ID_MAX - 1) {
ret = -1;
goto __nfc_id_default_notify_end;
}
// 从vm中读取nfc_id
u16 default_nfc_id = -1;
ret = file_trans_back_response_send(resp_data, sizeof(resp_data), 2, 0);
nfc_id_default_set_to_vm(&nfc_id, sizeof(nfc_id));
__nfc_id_default_notify_end:
return ret;
}
static void nfc_peripherals_deal(u32 handler, u8 file_index)
{
u8 *path = NULL;
u8 *nfc_data = NULL;
FILE *file = NULL;
if (get_nfc_file_path(&path, file_index, NULL)) {
goto __nfc_peripherals_deal_end;
}
file = fopen(path, "r");
if (NULL == file) {
printf("%s, file open fail\n", __func__);
goto __nfc_peripherals_deal_end;
}
// 获取当前文件对应的数据
nfc_msg_head nfc_msg = {0};
fread(file, (u8 *)&nfc_msg, sizeof(nfc_msg));
int nfc_id_crc_len = ((u8 *)&nfc_msg.data_len)[0] << 8 | ((u8 *)&nfc_msg.data_len)[1];
int nfc_data_len = flen(file);
nfc_data_len = nfc_data_len - (sizeof(nfc_msg) - 2) - nfc_id_crc_len;
if (nfc_data_len <= 0) {
goto __nfc_peripherals_deal_end;
}
nfc_data = zalloc(nfc_data_len);
if (NULL == nfc_data) {
printf("%s, file open fail\n", __func__);
goto __nfc_peripherals_deal_end;
}
fseek(file, (sizeof(nfc_msg) - 2) + nfc_id_crc_len, SEEK_SET);
fread(file, nfc_data, nfc_data_len);
// 把数据写到nfc外设中
__nfc_peripherals_deal_end:
if (path) {
free(path);
}
if (nfc_data) {
free(nfc_data);
}
if (file) {
fclose(file);
}
}
void nfc_file_trans_back_end(void *priv, u32 handler, u8 op, int result, int param)
{
u8 ret = (u8)result;
u8 file_index = (u8) param;
if (NFC_DATA_INFO_SYNC_BEGIN != op && (u8) - 1 != op) {
file_trans_back_response_send(&ret, sizeof(ret), 0, g_nfc_file_msg->OpCode_SN);
}
switch (op) {
case NFC_DATA_INFO_SYNC_BEGIN:
printf("NFC_DATA_INFO_SYNC_BEGIN end\n");
u8 resp_data[2] = {NFC_DATA_INFO_SYNC_END, ret};
file_trans_back_response_send(resp_data, sizeof(resp_data), 2, 0);
break;
case NFC_DATA_INFO_MODIFY:
printf("NFC_DATA_INFO_MODIFY end\n");
break;
case NFC_DATA_INFO_DELETE:
printf("NFC_DATA_INFO_DELETE end\n");
// 获取默认id
u16 default_nfc_id = 0;
if (0 == ret && 0 == nfc_data_msg_default_id_get(&default_nfc_id)) {
nfc_id_default_notify(handler, default_nfc_id);
}
break;
case NFC_DATA_INFO_DEFAULT_ID:
printf("NFC_DATA_INFO_DEFAULT_ID end\n");
if (0 == ret) {
// 写入外设
nfc_peripherals_deal(handler, file_index);
}
break;
case NFC_DATA_INFO_INSERT:
printf("NFC_DATA_INFO_INSERT end\n");
// 插入开始,可以做对应得初始化动作
break;
case NFC_DATA_INFO_INSERT_FINISH:
printf("NFC_DATA_INFO_INSERT_FINISH end\n");
// 插入结束,这个时候已经存在文件,可以读出来写入外设
if (0 == ret) {
// 写入外设
}
break;
}
nfc_rcsp_file_trans_back_close();
}
int JL_rcsp_nfc_data_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
int ret = -1;
switch (OpCode) {
case JL_OPCODE_SENSOR_NFC_FUNCTION_OPT:
ret = 0;
nfc_data_opt(priv, OpCode, OpCode_SN, data, len);
break;
}
return ret;
}
#else
int JL_rcsp_nfc_data_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
return -1;
}
void nfc_file_trans_back_end(void *priv, u32 handler, u8 op, int result, int param)
{
}
int nfc_id_default_notify(u32 devHeadler, u16 nfc_id)
{
return 0;
}
#endif
@@ -0,0 +1,11 @@
#ifndef __RCSP_NFC_DATA_FUNC_H__
#define __RCSP_NFC_DATA_FUNC_H__
#include "typedef.h"
#include "app_config.h"
int JL_rcsp_nfc_data_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
int nfc_id_default_notify(u32 devHeadler, u16 nfc_id);
void nfc_file_trans_back_end(void *priv, u32 handler, u8 op, int result, int param);
#endif
@@ -0,0 +1,123 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".sensor_log_notify.data.bss")
#pragma data_seg(".sensor_log_notify.data")
#pragma const_seg(".sensor_log_notify.text.const")
#pragma code_seg(".sensor_log_notify.text")
#endif
#include "rcsp_functions/rcsp_config.h"
#include "sensor_log_notify.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_protocol.h"
#if (RCSP_MODE && JL_RCSP_SENSORS_DATA_OPT)
#define FUNCTION_UPDATE_MAX_LEN (256)
static int pedometer_data_get(u8 *data, u16 max_len)
{
int rlen = 0;
#if TCFG_GSENSOR_ENABLE
extern int gSensor_read_data(u8 * buf[]);
u8 *tmp_data = NULL;
rlen = gSensor_read_data(&tmp_data);
if (rlen > max_len) {
rlen = 0;
} else {
memcpy(data, tmp_data, rlen);
}
#endif
return rlen;
}
static void sensors_log_nofity_trigger(void *priv, u8 OpCode, u8 *data, u16 len)
{
u8 ret = 0;
u32 mask = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
u8 *resp_data = zalloc(FUNCTION_UPDATE_MAX_LEN);
if (NULL == resp_data) {
ret = -1;
printf("%s, no ram err !!!\n", __func__);
goto __sensors_log_nofity_trigger_end;
}
if (mask & BIT(SENSOR_LOG_ACCELERATION)) {
// 触发加速度
u16 data_len = 0;
resp_data[data_len++] = 0xa5;
watch_sensor_log_notify(SENSOR_LOG_ACCELERATION, resp_data, data_len);
}
if (mask & BIT(SENSOR_LOG_HEART_RATE_BLOOD_OXYGEN)) {
// 触发血氧
u16 data_len = 0;
resp_data[data_len++] = 0x5a;
watch_sensor_log_notify(SENSOR_LOG_HEART_RATE_BLOOD_OXYGEN, resp_data, data_len);
}
if (mask & BIT(SENSOR_LOG_PEDOMETER)) {
u16 data_len = 0;
data_len = pedometer_data_get(resp_data, len);
watch_sensor_log_notify(SENSOR_LOG_PEDOMETER, resp_data, data_len);
}
__sensors_log_nofity_trigger_end:
if (resp_data) {
free(resp_data);
}
}
int JL_rcsp_sensors_log_notify(void *priv, u8 OpCode, u8 *data, u16 len)
{
int ret = -1;
switch (OpCode) {
case JL_OPCODE_SENSOR_LOG_DATA_AUTO_UPDATE:
ret = 0;
sensors_log_nofity_trigger(priv, OpCode, data, len);
break;
}
return ret;
}
void watch_sensor_log_notify(u8 type, u8 *data, u16 data_len)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL || 0 == JL_rcsp_get_auth_flag()) {
return ;
}
u8 *resp_data = zalloc(FUNCTION_UPDATE_MAX_LEN);
if (NULL == resp_data) {
printf("%s, no ram err !!!\n", __func__);
return;
}
for (u16 offset = 0, rlen = 0; offset < data_len; offset += FUNCTION_UPDATE_MAX_LEN - 1) {
rlen = (data_len - offset) > (FUNCTION_UPDATE_MAX_LEN - 1) ? (FUNCTION_UPDATE_MAX_LEN - 1) : (data_len - offset);
u32 mask = BIT(type);
resp_data[0] = ((u8 *)&mask)[3];
resp_data[1] = ((u8 *)&mask)[2];
resp_data[2] = ((u8 *)&mask)[1];
resp_data[3] = ((u8 *)&mask)[0];
memcpy(resp_data + 4, data + offset, rlen);
if (JL_CMD_send(JL_OPCODE_SENSOR_LOG_DATA_AUTO_UPDATE, resp_data, rlen + 4, JL_NOT_NEED_RESPOND, 0, NULL)) {
break;
}
}
if (resp_data) {
free(resp_data);
}
}
#else
int JL_rcsp_sensors_log_notify(void *priv, u8 OpCode, u8 *data, u16 len)
{
return 0;
}
void watch_sensor_log_notify(u8 type, u8 *data, u16 data_len)
{
}
#endif
@@ -0,0 +1,16 @@
#ifndef __RCSP_SENSOR_LOG_NOTIFY_H__
#define __RCSP_SENSOR_LOG_NOTIFY_H__
#include "typedef.h"
#include "app_config.h"
enum {
SENSOR_LOG_ACCELERATION,
SENSOR_LOG_HEART_RATE_BLOOD_OXYGEN,
SENSOR_LOG_PEDOMETER,
};
void watch_sensor_log_notify(u8 type, u8 *data, u16 data_len);
int JL_rcsp_sensors_log_notify(void *priv, u8 OpCode, u8 *data, u16 len);
#endif
@@ -0,0 +1,30 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".sensors_data_opt.data.bss")
#pragma data_seg(".sensors_data_opt.data")
#pragma const_seg(".sensors_data_opt.text.const")
#pragma code_seg(".sensors_data_opt.text")
#endif
#include "sensors_data_opt.h"
#include "sport_data_func.h"
#include "sport_info_sync.h"
#include "nfc_data_opt.h"
#include "sport_info_opt.h"
#if (RCSP_MODE && JL_RCSP_SENSORS_DATA_OPT)
int JL_rcsp_sensors_data_opt(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
if (0 == JL_rcsp_sports_data_funciton(priv, OpCode, OpCode_SN, data, len)) {
return 0;
}
if (0 == JL_rcsp_nfc_data_funciton(priv, OpCode, OpCode_SN, data, len)) {
return 0;
}
if (0 == JL_rcsp_sports_info_funciton(priv, OpCode, OpCode_SN, data, len)) {
return 0;
}
if (0 == JL_rcsp_sports_info_sync_funciton(priv, OpCode, OpCode_SN, data, len)) {
return 0;
}
return -1;
}
#endif
@@ -0,0 +1,9 @@
#ifndef __RCSP_SENSORS_DATA_OPT_H__
#define __RCSP_SENSORS_DATA_OPT_H__
#include "typedef.h"
#include "app_config.h"
int JL_rcsp_sensors_data_opt(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
#endif
@@ -0,0 +1,431 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".sport_data_func.data.bss")
#pragma data_seg(".sport_data_func.data")
#pragma const_seg(".sport_data_func.text.const")
#pragma code_seg(".sport_data_func.text")
#endif
#include "rcsp_config.h"
#include "sport_data_func.h"
#include "rcsp_event.h"
#include "rcsp_manage.h"
#include "rcsp_extra_flash_opt.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_api.h"
#if (RCSP_MODE && JL_RCSP_SENSORS_DATA_OPT)
#define SPROT_DATA_PROTOCOL_VERSION 0
#define FUNCTION_UPDATE_MAX_LEN (256 - 32) // 预留32个byte放别的突发的命令
//#define SPORT_DATA_TIMED_NOFIFYCATION_TIME (5 * 60 * 1000) // 5min
#define SPORT_DATA_TIMED_NOFIFYCATION_TIME 0 // 默认关闭连上app后定时发送运动数据
#define ASSET_CMD_DATA_LEN(len, limit) \
do{ \
if(len >= limit){ \
}else{ \
return ; \
}\
}while(0);
static rcsp_sport_data_opt_t *g_rcsp_sport_data_opt = NULL;
#define __this g_rcsp_sport_data_opt
static OS_SEM g_sport_data_get_sem;
static int sport_data_func_multi_pack_update(void *priv, u8 *resp_pack, u16 resp_pack_len, sport_resp_data *sport_data, u16 sport_data_len);
extern u8 get_ota_status();
extern u8 rcsp_eflash_update_flag_get(void);
static u32 rcsp_sport_data_function_get(void *priv, u32 mask, u8 *sub_mask, u8 *buf, u16 buf_size)
{
printf("rcsp_sport_data_function_get, mask = %x\n", mask);
struct RcspModel *rcspModel = (struct RcspModel *)priv;
u32 offset = 0;
u32 record_len = 0;
sport_attr_get_func func = NULL;
sport_resp_data *resp_data = (sport_resp_data *)zalloc(SPORTS_DATA_FUNC_ATTR_TYPE_GET_MAX * sizeof(sport_resp_data));
for (u8 i = 0, j = 0; i < SPORTS_DATA_FUNC_ATTR_TYPE_GET_MAX; i++) {
if (mask & BIT(i)) {
rcspModel->priv = (void *)(resp_data + i);
if (i >= __this->sport_data_get_tab_num) {
continue;
}
func = __this->sport_data_get_tab[i];
if (func) {
offset += func(priv, i, sub_mask[j++], buf, buf_size, offset);
}
if (resp_data[i].resp_data_len) {
record_len += resp_data[i].resp_data_len + 2;
}
}
}
if (rcspModel->err_code) {
sport_data_func_multi_pack_update(priv, buf, buf_size, resp_data, record_len);
offset = 0;
}
for (u8 i = 0; i < SPORTS_DATA_FUNC_ATTR_TYPE_GET_MAX; i++) {
if (resp_data[i].call_back) {
resp_data[i].call_back(resp_data[i].priv);
}
}
if (resp_data) {
free(resp_data);
}
return offset;
}
static bool rcsp_data_function_set(void *priv, u8 function, u8 *data, u16 len)
{
printf("rcsp_data_function_set\n");
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return false;
}
put_buf(data, len);
if (function >= __this->sport_data_set_tab_num) {
return false;
}
attr_set_func func = __this->sport_data_set_tab[function];
if (func) {
func(priv, function, data, len, 0, NULL);
}
if (rcspModel->err_code) {
rcspModel->err_code = 0;
return false;
}
return true;
}
static void get_sport_data_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return;
}
// 加锁
/* sport_data_func_get_prepare_deal(); */
rcspModel->OpCode_record = OpCode;
rcspModel->OpCode_SN_record = OpCode_SN;
u8 offset = 0;
u32 mask = data[offset + 0] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
offset += 4;
u8 version = data[offset++];
u8 *sub_mask = data + offset;
u8 *resp = zalloc(TARGET_FEATURE_RESP_BUF_SIZE);
u32 rlen = rcsp_sport_data_function_get(priv, mask, sub_mask, resp + 2, TARGET_FEATURE_RESP_BUF_SIZE - 2);
resp[0] = (rlen == 0);
resp[1] = 1; // 附带response data
if (rcspModel->err_code) {
rcspModel->err_code = 0;
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp, (u16)rlen + 2, 0, NULL);
}
if (resp) {
free(resp);
}
/* sport_data_func_get_finish_deal(); */
}
static void set_sport_data_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 offset = 0;
u8 function = data[offset++];
u8 version = data[offset++];
bool ret = rcsp_data_function_set(priv, function, data + offset, len - offset);
u8 resp_data[2] = {function, ret};
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp_data, sizeof(resp_data), 0, NULL);
}
void sport_data_func_update(u32 mask, u8 *sub_mask)
{
struct RcspModel *rcspModel = rcsp_handle_get();
//ota不响应运动数据
if (rcspModel == NULL || 0 == JL_rcsp_get_auth_flag() || rcsp_eflash_update_flag_get() || get_ota_status()) {
return ;
}
// 加锁
/* sport_data_func_get_prepare_deal(); */
u32 rlen = 0;
u8 *buf = zalloc(FUNCTION_UPDATE_MAX_LEN);
if (NULL == buf) {
printf("%s, no ram err!!\n", __func__);
return;
}
buf[0] = SPROT_DATA_PROTOCOL_VERSION; // version
buf[1] = 1; // package count
buf[2] = 0; // package id
rcspModel->OpCode_record = JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE;
rlen = rcsp_sport_data_function_get((void *)rcspModel, mask, sub_mask, buf + 3, FUNCTION_UPDATE_MAX_LEN - 3);
if (rlen) {
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE, buf, rlen + 3, JL_NOT_NEED_RESPOND, 0, NULL);
}
if (buf) {
free(buf);
}
/* sport_data_func_get_finish_deal(); */
}
int JL_rcsp_sports_data_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
int ret = -1;
if (!__this) {
return ret;
}
switch (OpCode) {
case JL_OPCODE_SPORTS_DATA_INFO_GET:
ret = 0;
//ota不响应运动数据
if (get_ota_status()) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
break;
}
get_sport_data_info(priv, OpCode, OpCode_SN, data, len);
break;
case JL_OPCODE_SPORTS_DATA_INFO_SET:
ret = 0;
//ota不响应运动数据
if (get_ota_status()) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
break;
}
set_sport_data_info(priv, OpCode, OpCode_SN, data, len);
break;
}
return ret;
}
// 处理多包的情况
static u16 sport_data_func_multi_pack_detailed_update(u8 *resp_pack, u16 resp_pack_len, sport_resp_data *sport_data, u16 offset)
{
u8 *resp_data = resp_pack + 3;
u8 resp_data_len = resp_pack_len - 3;
if (!sport_data->resp_data_len) {
return offset;
}
u16 data_len = sport_data->resp_data_len + 2;
if (offset + 2 > resp_data_len) {
resp_data[offset++] = ((u8 *)&data_len)[1];
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE, resp_pack, resp_pack_len, JL_NOT_NEED_RESPOND, 0, NULL);
resp_pack[2]++;
offset = 0;
resp_data[offset++] = ((u8 *)&data_len)[0];
} else if (offset + 3 > resp_data_len) {
resp_data[offset++] = ((u8 *)&data_len)[1];
resp_data[offset++] = ((u8 *)&data_len)[0];
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE, resp_pack, resp_pack_len, JL_NOT_NEED_RESPOND, 0, NULL);
resp_pack[2]++;
offset = 0;
} else {
resp_data[offset++] = ((u8 *)&data_len)[1];
resp_data[offset++] = ((u8 *)&data_len)[0];
}
resp_data[offset++] = sport_data->resp_mask;
resp_data[offset++] = sport_data->resp_sub_mask;
for (data_len = 0; data_len < sport_data->resp_data_len;) {
u16 len = 0;
if (resp_data_len - offset > sport_data->resp_data_len - data_len) {
len = sport_data->resp_data_len - data_len;
memcpy(resp_data + offset, sport_data->resp_data + data_len, len);
offset += len;
} else {
len = resp_data_len - offset;
memcpy(resp_data + offset, sport_data->resp_data + data_len, len);
offset = 0;
}
if (offset) {
break;
} else {
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE, resp_pack, resp_pack_len, JL_NOT_NEED_RESPOND, 0, NULL);
resp_pack[2]++;
}
data_len += len;
}
return offset;
}
static int sport_data_func_multi_pack_update(void *priv, u8 *resp_pack, u16 resp_pack_len, sport_resp_data *sport_data, u16 sport_data_len)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return false;
}
// 假如rcspModel->err_code为0,则是普通推送
if (JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE != rcspModel->OpCode_record) {
// 假如不是主动推送,先回复命令
resp_pack[0] = 0;
resp_pack[1] = 0; // 不带response data
JL_CMD_response_send(rcspModel->OpCode_record, JL_PRO_STATUS_SUCCESS, rcspModel->OpCode_SN_record, resp_pack, 2, 0, NULL);
}
// 组装数据并发送
resp_pack[0] = SPROT_DATA_PROTOCOL_VERSION;
resp_pack[1] = sport_data_len / resp_pack_len + !!(sport_data_len % resp_pack_len);
resp_pack[2] = 0;
u16 offset = 0;
for (u8 i = 0; i < SPORTS_DATA_FUNC_ATTR_TYPE_GET_MAX; i++) {
offset = sport_data_func_multi_pack_detailed_update(resp_pack, resp_pack_len, sport_data + i, offset);
}
if (offset) {
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_AUTO_UPDATE, resp_pack, offset + 3, JL_NOT_NEED_RESPOND, 0, NULL);
}
return 0;
}
static int sport_data_global_var_callback(void *priv)
{
if (NULL == priv) {
return 0;
}
u8 **data = (u8 **)priv;
if (*data) {
free(*data);
*data = NULL;
}
return 0;
}
u16 add_one_attr_with_submask_huge(u8 *buf, u16 max_len, u8 offset, u8 type, u8 sub_mask, u8 *data, u16 size)
{
if (offset + size + 4 > max_len) {
/* printf("\n\nadd attr err!\n\n"); */
return 0;
}
u16 data_len = size + 2;
buf[offset] = ((u8 *)&data_len)[1];
buf[offset + 1] = ((u8 *)&data_len)[0];
buf[offset + 2] = type;
buf[offset + 3] = sub_mask;
memcpy(&buf[offset + 4], data, size);
return size + 4;
}
void sport_data_global_var_deal(void *priv, u8 type, u8 sub_mask, u8 *data, u16 data_len, u8 result_len, void *callback_param)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
sport_resp_data *resp_data = (sport_resp_data *)rcspModel->priv;
resp_data->resp_mask = type;
resp_data->resp_sub_mask = sub_mask;
resp_data->resp_data_len = data_len;
resp_data->resp_data = data;
resp_data->call_back = sport_data_global_var_callback;
resp_data->priv = callback_param;
if (!result_len) {
rcspModel->err_code = 1;
}
}
static void sport_data_regular_update(void *priv)
{
// 隔一段时间向app推送运动数据,这里以获取心率统计值为例子
#if JL_RCSP_EXTRA_FLASH_OPT
if (!rcsp_eflash_update_flag_get()) {
u32 mask = BIT(SPORTS_DATA_FUNC_ATTR_TYPE_HEART_RATE) | BIT(SPORTS_DATA_FUNC_ATTR_TYPE_BLOOD_OXYGEN) | BIT(SPORTS_DATA_FUNC_ATTR_TYPE_ALTITUDE) | BIT(SPORTS_DATA_FUNC_ATTR_TYPE_AIR_PRESSURE) | BIT(SPORTS_DATA_FUNC_ATTR_TYPE_ALTITUDE) | BIT(SPORTS_DATA_FUNC_ATTR_TYPE_EXERCISE_STEPS);
u8 sub_mask[5] = {0};
sub_mask[0] = 0x01;
sub_mask[1] = 0x01;
sub_mask[2] = 0x01;
sub_mask[3] = 0x01;
sub_mask[4] = 0x01;
sport_data_func_update(mask, sub_mask);
}
#endif
}
void sport_data_func_event(void *priv, u8 flag)
{
struct RcspModel *rcspModel = (struct RcspModel *)priv;
static u16 sport_data_update_timer = 0;
if (flag) {
// 连上
if (SPORT_DATA_TIMED_NOFIFYCATION_TIME && 0 == sport_data_update_timer) {
sport_data_update_timer = sys_timer_add(NULL, sport_data_regular_update, SPORT_DATA_TIMED_NOFIFYCATION_TIME);
}
} else {
// 断开
if (sport_data_update_timer) {
sys_timer_del(sport_data_update_timer);
sport_data_update_timer = 0;
}
}
}
void sport_data_func_init(void)
{
struct RcspModel *rcspModel = rcsp_handle_get();
rcsp_msg_post(USER_MSG_RCSP_SPORT_DATA_EVENT, 2, (int)rcspModel, 1);
if (!os_sem_valid(&g_sport_data_get_sem)) {
os_sem_create(&g_sport_data_get_sem, 1);
}
}
void sport_data_func_release(void)
{
struct RcspModel *rcspModel = rcsp_handle_get();
/* if (os_sem_valid(&g_sport_data_get_sem)) { */
/* os_sem_del(&g_sport_data_get_sem, 0); */
/* } */
rcsp_msg_post(USER_MSG_RCSP_SPORT_DATA_EVENT, 2, (int)rcspModel, 0);
}
void sport_data_func_get_prepare_deal(void)
{
if (get_rcsp_connect_status()) {
os_sem_pend(&g_sport_data_get_sem, 0);
}
}
void sport_data_func_get_finish_deal(void)
{
if (get_rcsp_connect_status()) {
os_sem_post(&g_sport_data_get_sem);
}
}
int rcsp_register_sport_data_opt_interface(rcsp_sport_data_opt_t *rcsp_sport_data_opt_interface)
{
g_rcsp_sport_data_opt = rcsp_sport_data_opt_interface;
return 0;
}
#else
void sport_data_func_update(u32 mask, u8 *sub_mask)
{
}
void sport_data_func_init(void)
{
}
void sport_data_func_release(void)
{
}
void sport_data_func_event(void *priv, u8 flag)
{
}
void sport_data_func_get_prepare_deal(void)
{
}
void sport_data_func_get_finish_deal(void)
{
}
#endif
@@ -0,0 +1,61 @@
#ifndef __RCSP_SPORT_DATA_FUNC_H__
#define __RCSP_SPORT_DATA_FUNC_H__
#include "typedef.h"
#include "JL_rcsp_attr.h"
enum {
SPORTS_DATA_FUNC_ATTR_TYPE_HEART_RATE,
SPORTS_DATA_FUNC_ATTR_TYPE_AIR_PRESSURE,
SPORTS_DATA_FUNC_ATTR_TYPE_ALTITUDE,
SPORTS_DATA_FUNC_ATTR_TYPE_EXERCISE_STEPS,
SPORTS_DATA_FUNC_ATTR_TYPE_PRESSURE_DETECTION,
SPORTS_DATA_FUNC_ATTR_TYPE_BLOOD_OXYGEN,
SPORTS_DATA_FUNC_ATTR_TYPE_TRAINING_LOAD,
SPORTS_DATA_FUNC_ATTR_TYPE_MAX_OXYGEN_UPTAKE,
SPORTS_DATA_FUNC_ATTR_TYPE_EXERCISE_RECOVERY_TIME,
SPORTS_DATA_FUNC_ATTR_TYPE_SPORTS_INFORMATION,
SPORTS_DATA_FUNC_ATTR_TYPE_GET_MAX,
};
enum {
DATA_FUNC_ATTR_TYPE_LOCATION,
DATA_FUNC_ATTR_TYPE_WEATHER,
DATA_FUNC_ATTR_TYPE_NOTICE,
DATA_FUNC_ATTR_TYPE_NOTICE_REMOVE,
DATA_FUNC_ATTR_TYPE_SET_MAX,
};
typedef struct sport_resp_data_t {
u16 resp_data_len;
u8 resp_mask;
u8 resp_sub_mask;
u8 *resp_data;
int (*call_back)(void *priv);
void *priv;
} sport_resp_data;
typedef u32(*sport_attr_get_func)(void *priv, u8 attr, u8 type, u8 *buf, u16 buf_size, u32 offset);
typedef struct rcsp_sport_data_opt {
const sport_attr_get_func *sport_data_get_tab;
int sport_data_get_tab_num;
const attr_set_func *sport_data_set_tab;
int sport_data_set_tab_num;
} rcsp_sport_data_opt_t;
int JL_rcsp_sports_data_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
void sport_data_func_update(u32 mask, u8 *sub_mask);
void sport_data_global_var_deal(void *priv, u8 type, u8 sub_mask, u8 *data, u16 data_len, u8 result_len, void *callback_param);
u16 add_one_attr_with_submask_huge(u8 *buf, u16 max_len, u8 offset, u8 type, u8 sub_mask, u8 *data, u16 size);
void sport_data_func_get_prepare_deal(void);
void sport_data_func_get_finish_deal(void);
int rcsp_register_sport_data_opt_interface(rcsp_sport_data_opt_t *rcsp_sport_data_opt_interface);
// #if (RCSP_MODE)
// #define RCSP_UPDATE sport_data_func_update
// #else
// #define RCSP_UPDATE(...)
// #endif
#endif
@@ -0,0 +1,139 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".sport_info_opt.data.bss")
#pragma data_seg(".sport_info_opt.data")
#pragma const_seg(".sport_info_opt.text.const")
#pragma code_seg(".sport_info_opt.text")
#endif
#include "rcsp_config.h"
#include "JL_rcsp_attr.h"
#include "sport_info_opt.h"
#include "rcsp_event.h"
#include "rcsp_manage.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_api.h"
#if (RCSP_MODE && JL_RCSP_SENSORS_DATA_OPT)
#define FUNCTION_UPDATE_MAX_LEN (256)
#define ASSET_CMD_DATA_LEN(len, limit) \
do{ \
if(len >= limit){ \
}else{ \
return ; \
}\
}while(0);
enum {
SPORTS_INFO_OPT_GET,
SPORTS_INFO_OPT_SET,
SPORTS_INFO_OPT_NOTIFY,
};
static rcsp_sport_info_opt_t *g_rcsp_sport_info_opt = NULL;
#define __this g_rcsp_sport_info_opt
static void get_sport_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
printf("get_sport_info\n");
u32 rlen = 0;
u32 mask = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
u8 *resp = zalloc(TARGET_FEATURE_RESP_BUF_SIZE);
if (NULL == resp) {
printf("%s, %d, no ram!!\n", __func__, __LINE__);
goto __get_sport_info_end;
}
rlen = attr_get(priv, resp, TARGET_FEATURE_RESP_BUF_SIZE, __this->sport_info_get_tab, __this->sport_info_get_tab_num, mask);
__get_sport_info_end:
if (0 == rlen) {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp, (u16)rlen, 0, NULL);
}
if (resp) {
free(resp);
}
}
static void set_sport_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
printf("set_sport_info\n");
struct RcspModel *rcspModel = (struct RcspModel *)priv;
if (rcspModel == NULL) {
return;
}
put_buf(data, len);
attr_set(priv, data, len, __this->sport_info_set_tab, __this->sport_info_set_tab_num, 0, NULL);
if (rcspModel->err_code) {
rcspModel->err_code = 0;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0, 0, NULL);
} else {
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0, 0, NULL);
}
}
void sport_info_opt_update(u32 mask)
{
struct RcspModel *rcspModel = rcsp_handle_get();
if (rcspModel == NULL || 0 == JL_rcsp_get_auth_flag()) {
return ;
}
u32 rlen = 0;
u8 *buf = zalloc(FUNCTION_UPDATE_MAX_LEN);
if (buf == NULL) {
printf("no ram err\n");
return;
}
buf[0] = SPORTS_INFO_OPT_NOTIFY;
rlen = attr_get((void *)rcspModel, buf + 1, FUNCTION_UPDATE_MAX_LEN - 1, __this->sport_info_get_tab, __this->sport_info_get_tab_num, mask);
if (rlen) {
JL_CMD_send(JL_OPCODE_SPORTS_DATA_INFO_OPT, buf, (u16)rlen + 1, JL_NOT_NEED_RESPOND, 0, NULL);
}
if (buf) {
free(buf);
}
}
int JL_rcsp_sports_info_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
int ret = -1;
if (!__this) {
return ret;
}
if (JL_OPCODE_SPORTS_DATA_INFO_OPT == OpCode) {
u8 op = data[0];
switch (op) {
case SPORTS_INFO_OPT_GET:
get_sport_info(priv, OpCode, OpCode_SN, data + 1, len - 1);
break;
case SPORTS_INFO_OPT_SET:
set_sport_info(priv, OpCode, OpCode_SN, data + 1, len - 1);
break;
case SPORTS_INFO_OPT_NOTIFY:
break;
}
ret = 0;
}
return ret;
}
int rcsp_register_sport_info_opt_interface(rcsp_sport_info_opt_t *rcsp_sport_info_opt_interface)
{
g_rcsp_sport_info_opt = rcsp_sport_info_opt_interface;
return 0;
}
#else
void sport_info_opt_update(u32 mask)
{
}
#endif
@@ -0,0 +1,97 @@
#ifndef __RCSP_SPORT_INFO_OPT_H__
#define __RCSP_SPORT_INFO_OPT_H__
#include "typedef.h"
#include "JL_rcsp_attr.h"
enum {
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_RESERVE,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_SENSOR_OPT,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_SEDENTARY,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_CONTINUOUS_HEART_RATE,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_EXERCISE_HEART_RATE,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_PRESSURE_DETECTION,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_SLEEP_DETECTION,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_FALL_DETECTION,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_RAISE_WRIST,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_PERSONAL_INFO,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_BT_DISCONN,
SPORTS_INFO_OPT_FUNC_ATTR_TYPE_MAX,
};
// 开关
enum {
SPORT_INFO_SWTICH_TYPE_SENSOR,
// 传感器功能
SPORT_INFO_SWTICH_TYPE_SENSOR_PEDOMETER,
SPORT_INFO_SWTICH_TYPE_SENSOR_PEDOMETER_RECORD,
SPORT_INFO_SWTICH_TYPE_SENSOR_HEART_RATE,
SPORT_INFO_SWTICH_TYPE_SENSOR_HEART_RATE_RECORD,
SPORT_INFO_SWTICH_TYPE_SENSOR_BLOOD_OXYGEN,
SPORT_INFO_SWTICH_TYPE_SENSOR_BLOOD_OXYGEN_RECORD,
SPORT_INFO_SWTICH_TYPE_SENSOR_ALTITUDE,
SPORT_INFO_SWTICH_TYPE_SENSOR_ALTITUDE_RECORD,//8
// 久坐提醒
SPORT_INFO_SWTICH_TYPE_SEDENTARY,
// 连续测量心率
SPORT_INFO_SWTICH_TYPE_CONTINUOUS_HEART_RATE,
// 运动心率
SPORT_INFO_SWTICH_TYPE_EXERCISE_HEART_RATE,
// 压力自动检测
SPORT_INFO_SWTICH_TYPE_PRESSURE_DETECTION,
// 睡眠检测
SPORT_INFO_SWTICH_TYPE_SLEEP_DETECTION,
// 跌倒检测
SPORT_INFO_SWTICH_TYPE_FALL_DETECTION,
// 抬腕检测
SPORT_INFO_SWTICH_TYPE_RAISE_WRIST,
// 蓝牙断开提示
SPORT_INFO_SWTICH_TYPE_BT_DISCONN,
// 当前最大值
SPORT_INFO_SWITCH_TYPE_END,
};
// 开关类型扩展
enum SPORT_INFO_SWITCH_EXPAND_TYPE {
// 睡眠检测 - 自定义时间段
SPORT_INFO_SWTICH_TYPE_SLEEP_DETECTION_CUSTOMIZE = SPORT_INFO_SWITCH_TYPE_END,
// 抬腕检测 - 自定义时间段
SPORT_INFO_SWTICH_TYPE_RAISE_WRIST_CUSTOMIZE,
// 最大值,不超过31
SPORT_INFO_SWTICH_TYPE_MAX,
};
// 模式
enum {
// 久坐提醒
SPORT_INFO_MODE_TYPE_SEDENTARY,
// 连续心率
SPORT_INFO_MODE_TYPE_CONTINUOUS_HEART_RATE,
// 压力检测
SPORT_INFO_MODE_TYPE_PRESSURE_DETECTION,
// 跌倒检测
SPORT_INFO_MODE_TYPE_FALL_DETECTION,
// 抬碗检测
SPORT_INFO_MODE_TYPE_RAISE_WRIST,
// 蓝牙断开提示
SPORT_INFO_MODE_TYPE_BT_DISCONN,
// 最大值
SPORT_INFO_MODE_TYPE_MAX,
};
typedef struct rcsp_sport_info_opt {
const attr_get_func *sport_info_get_tab;
int sport_info_get_tab_num;
const attr_set_func *sport_info_set_tab;
int sport_info_set_tab_num;
} rcsp_sport_info_opt_t;
int JL_rcsp_sports_info_funciton(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
void sport_info_opt_update(u32 mask);
int rcsp_register_sport_info_opt_interface(rcsp_sport_info_opt_t *rcsp_sport_info_opt_interface);
#endif

Some files were not shown because too many files have changed in this diff Show More