569 lines
14 KiB
C
569 lines
14 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
|
#pragma bss_seg(".idle.data.bss")
|
|
#pragma data_seg(".idle.data")
|
|
#pragma const_seg(".idle.text.const")
|
|
#pragma code_seg(".idle.text")
|
|
#endif
|
|
#include "idle.h"
|
|
#include "system/includes.h"
|
|
#include "media/includes.h"
|
|
#include "app_config.h"
|
|
#include "app_action.h"
|
|
#include "app_tone.h"
|
|
#include "asm/charge.h"
|
|
#include "app_charge.h"
|
|
#include "app_main.h"
|
|
#include "app_chargestore.h"
|
|
#include "app_testbox.h"
|
|
#include "user_cfg.h"
|
|
#include "ui/ui_api.h"
|
|
#include "ui_manage.h"
|
|
#include "avctp_user.h"
|
|
#include "mic_effect.h"
|
|
#include "linein_dev.h"
|
|
#include "asm/wdt.h"
|
|
#include "audio_config.h"
|
|
#if TCFG_SMART_VOICE_ENABLE
|
|
#include "smart_voice.h"
|
|
#endif
|
|
|
|
#if TCFG_ANC_BOX_ENABLE
|
|
#include "app_ancbox.h"
|
|
#endif
|
|
|
|
#define LOG_TAG "[APP_IDLE]"
|
|
#define LOG_ERROR_ENABLE
|
|
#define LOG_DEBUG_ENABLE
|
|
#define LOG_INFO_ENABLE
|
|
#define LOG_CLI_ENABLE
|
|
#include "debug.h"
|
|
#include "bt_tws.h"
|
|
|
|
static int app_idle_init(int param);
|
|
void app_idle_exit();
|
|
extern uint32_t timer_get_ms(void);
|
|
|
|
#define LOW_POWER_IN_IDLE 0// idle 是否关闭不用的模块,减少功耗
|
|
#define POWER_OFF_TIME 2//最小开机时间
|
|
#define POWER_OFF_CNT 10
|
|
#define POWER_ON_CNT 10
|
|
|
|
static u32 ui_logo_time = 0;
|
|
static u8 goto_poweron_cnt = 0;
|
|
static u8 goto_poweron_flag = 0;
|
|
static u8 goto_poweroff_cnt = 0;
|
|
static u8 goto_poweroff_flag = 0;
|
|
static u8 idle_sub_mode = 0;
|
|
static u8 power_off_tone_play_flag = 0;
|
|
u8 goto_poweroff_first_flag = 0;
|
|
static void power_off_ui_enter()
|
|
{
|
|
UI_SHOW_WINDOW(ID_WINDOW_POWER_OFF);
|
|
ui_logo_time = timer_get_ms();
|
|
|
|
}
|
|
static void power_off_ui_exit()
|
|
{
|
|
while (timer_get_ms() - ui_logo_time <= POWER_OFF_TIME * 1000) { //显示开机logo
|
|
os_time_dly(2);
|
|
}
|
|
UI_HIDE_CURR_WINDOW();
|
|
}
|
|
#if LOW_POWER_IN_IDLE
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 下面处理是为了关闭不需要用的模块,减少系统功耗
|
|
@param
|
|
@return
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
#include "usb/otg.h"
|
|
#include "usb/host/usb_host.h"
|
|
#include "usb/device/usb_stack.h"
|
|
#include "asm/power/p33.h"
|
|
#include "asm/sdmmc.h"
|
|
#include "dev_manager/dev_manager.h"
|
|
|
|
static u8 suspend_flag = 0;
|
|
static u8 is_idle_flag = 0;
|
|
|
|
u32 regs_buf[11] = {0};
|
|
void resume_some_peripheral()
|
|
{
|
|
u32 *regs_ptr = regs_buf;
|
|
|
|
if (!suspend_flag) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
here need to add
|
|
*/
|
|
|
|
suspend_flag = 0;
|
|
}
|
|
|
|
void suspend_some_peripheral()
|
|
{
|
|
u32 *regs_ptr = regs_buf;
|
|
|
|
if (suspend_flag) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
here need to add
|
|
*/
|
|
|
|
suspend_flag = 1;
|
|
}
|
|
|
|
#if 0
|
|
static u8 is_idle_query(void)
|
|
{
|
|
return is_idle_flag;
|
|
}
|
|
REGISTER_LP_TARGET(idle_lp_target) = {
|
|
.name = "not_idle",
|
|
.is_idle = is_idle_query,
|
|
};
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief idle 重新打开需要的模块
|
|
@param 无
|
|
@return
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void idle_app_open_module()
|
|
{
|
|
#if LOW_POWER_IN_IDLE
|
|
is_idle_flag = 0;
|
|
#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0)
|
|
resume_some_peripheral();
|
|
#endif
|
|
|
|
#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE)
|
|
sdx_dev_detect_timer_add();
|
|
#endif
|
|
|
|
#if (TCFG_PC_ENABLE || TCFG_USB_HOST_ENABLE)
|
|
usb_detect_timer_add();
|
|
#endif
|
|
|
|
#if TCFG_APP_LINEIN_EN
|
|
linein_detect_timer_add();
|
|
#endif
|
|
#endif //LOW_POWER_IN_IDLE
|
|
}
|
|
|
|
//*----------------------------------------------------------------------------*/
|
|
/**@brief idle 关闭不需要的模块
|
|
@param 无
|
|
@return
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void idle_app_close_module()
|
|
{
|
|
#if LOW_POWER_IN_IDLE
|
|
is_idle_flag = 1;
|
|
|
|
#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE)
|
|
sdx_dev_detect_timer_del();
|
|
#endif
|
|
|
|
#if (((TCFG_PC_ENABLE) && (!TCFG_USB_PORT_CHARGE)) || ((TCFG_USB_HOST_ENABLE) && (!TCFG_PC_ENABLE)))
|
|
/* extern int usb_mount_offline(usb_dev usb_id); */
|
|
usb_detect_timer_del();
|
|
os_time_dly((TCFG_OTG_DET_INTERVAL + 9) / 10);
|
|
if (usb_otg_online(0) == HOST_MODE) {
|
|
#if TCFG_UDISK_ENABLE
|
|
dev_manager_del("udisk0");
|
|
usb_host_unmount(0);
|
|
usb_h_sie_close(0);
|
|
|
|
/*
|
|
经过测试发现,有相当一部分在DP/DM设成高阻状态下U盘的电流仍维持在
|
|
20 ~ 30mA,需要把DP设成上拉,DM设成下拉,这些U盘的电流才能降到2mA
|
|
以下。即有部分U盘需要主机维持在空闲时J状态才能进入suspend。
|
|
*/
|
|
gpio_set_mode(PORTUSB, PORT_PIN_0, PORT_INPUT_PULLUP_10K);//usb dp
|
|
gpio_set_mode(PORTUSB, PORT_PIN_1, PORT_INPUT_PULLDOWN_10K);//usb dm
|
|
|
|
|
|
/* usb_mount_offline(0); */
|
|
#endif
|
|
} else if (usb_otg_online(0) == SLAVE_MODE) {
|
|
#if TCFG_PC_ENABLE
|
|
usb_pause();
|
|
|
|
gpio_set_mode(PORTUSB, PORT_PIN_0 | PORT_PIN_1, PORT_HIGHZ);//usb dp |dm
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if TCFG_APP_LINEIN_EN
|
|
linein_detect_timer_del();
|
|
#endif
|
|
|
|
#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0)
|
|
suspend_some_peripheral();
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#endif /*LOW_POWER_IN_IDLE*/
|
|
|
|
|
|
//power off前的ui处理
|
|
#if (TCFG_UI_ENABLE)
|
|
void power_off_wait_ui(void)
|
|
{
|
|
printf("[%s] TODO:power off wait ui ", __func__);
|
|
power_off_ui_exit();
|
|
}
|
|
#else
|
|
void power_off_wait_ui()
|
|
{
|
|
}
|
|
#endif
|
|
|
|
|
|
void idle_key_poweron_deal(int msg)
|
|
{
|
|
switch (msg) {
|
|
case APP_MSG_KEY_POWER_ON:
|
|
goto_poweron_cnt = 0;
|
|
goto_poweron_flag = 1;
|
|
break;
|
|
case APP_MSG_KEY_POWER_ON_HOLD:
|
|
printf("poweron flag:%d cnt:%d\n", goto_poweron_flag, goto_poweron_cnt);
|
|
if (goto_poweron_flag) {
|
|
goto_poweron_cnt++;
|
|
if (goto_poweron_cnt >= POWER_ON_CNT) {
|
|
goto_poweron_cnt = 0;
|
|
goto_poweron_flag = 0;
|
|
app_var.goto_poweroff_flag = 0;
|
|
#if LOW_POWER_IN_IDLE
|
|
idle_app_open_module();
|
|
#endif
|
|
app_var.play_poweron_tone = 0;
|
|
app_send_message(APP_MSG_GOTO_MODE, APP_MODE_BT);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if TCFG_USER_TWS_ENABLE
|
|
enum {
|
|
API_POWER_OFF,
|
|
API_TWS_POWER_OFF,
|
|
};
|
|
|
|
static void call_app_api(int api, int err)
|
|
{
|
|
switch (api) {
|
|
case API_POWER_OFF:
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL);
|
|
break;
|
|
case API_TWS_POWER_OFF:
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL_TWS);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
TWS_SYNC_CALL_REGISTER(app_api_sync_call_entry) = {
|
|
.uuid = 0x891E7CD3,
|
|
.func = call_app_api,
|
|
.task_name = "app_core",
|
|
};
|
|
#endif
|
|
void idle_sub_mode_set(u8 mode)
|
|
{
|
|
idle_sub_mode = mode;
|
|
}
|
|
u8 idle_sub_mode_get()
|
|
{
|
|
return idle_sub_mode;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief poweroff 长按等待 关闭蓝牙
|
|
@param 无
|
|
@return 无
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
void power_off_deal(int msg)
|
|
{
|
|
switch (msg) {
|
|
case APP_MSG_KEY_POWER_OFF:
|
|
case APP_MSG_KEY_POWER_OFF_HOLD:
|
|
if (goto_poweroff_first_flag == 0) {
|
|
goto_poweroff_first_flag = 1;
|
|
goto_poweroff_cnt = 0;
|
|
goto_poweroff_flag = 0;
|
|
#if TCFG_APP_BT_EN
|
|
if ((BT_STATUS_CONNECTING == bt_get_connect_status()) ||
|
|
(BT_STATUS_TAKEING_PHONE == bt_get_connect_status()) ||
|
|
(BT_STATUS_PLAYING_MUSIC == bt_get_connect_status())) {
|
|
if ((bt_get_call_status() == BT_CALL_INCOMING) ||
|
|
(bt_get_call_status() == BT_CALL_OUTGOING)) {
|
|
log_info("key call reject\n");
|
|
/* bt_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */
|
|
goto_poweroff_first_flag = 0;
|
|
goto_poweroff_flag = 0;
|
|
break;
|
|
} else if (bt_get_call_status() == BT_CALL_ACTIVE) {
|
|
log_info("key call hangup\n");
|
|
/* bt_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */
|
|
goto_poweroff_first_flag = 0;
|
|
goto_poweroff_flag = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bt_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL);
|
|
#endif
|
|
goto_poweroff_flag = 1;
|
|
break;
|
|
}
|
|
|
|
log_info("poweroff flag:%d cnt:%d\n", goto_poweroff_flag, goto_poweroff_cnt);
|
|
|
|
if (goto_poweroff_flag) {
|
|
goto_poweroff_cnt++;
|
|
|
|
#if CONFIG_TWS_POWEROFF_SAME_TIME
|
|
if (goto_poweroff_cnt == POWER_OFF_CNT) {
|
|
#if TCFG_MIC_EFFECT_ENABLE
|
|
if (mic_effect_player_runing()) {
|
|
mic_effect_player_close();
|
|
}
|
|
#endif
|
|
|
|
#if TCFG_USER_TWS_ENABLE
|
|
if (get_tws_sibling_connect_state()) {
|
|
tws_api_sync_call_by_uuid(0x891E7CD3, API_TWS_POWER_OFF, 100);
|
|
//sys_enter_soft_poweroff(POWEROFF_NORMAL_TWS);
|
|
} else
|
|
#endif
|
|
{
|
|
power_off_tone_play_flag = 1;
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL);
|
|
}
|
|
}
|
|
#else
|
|
if (goto_poweroff_cnt >= POWER_OFF_CNT) {
|
|
goto_poweroff_cnt = 0;
|
|
#if TCFG_MIC_EFFECT_ENABLE
|
|
if (mic_effect_player_runing()) {
|
|
mic_effect_player_close();
|
|
}
|
|
#endif
|
|
#if TCFG_APP_BT_EN
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL);
|
|
#else
|
|
app_var.goto_poweroff_flag = 1;
|
|
app_send_message2(APP_MSG_GOTO_MODE, APP_MODE_IDLE, IDLE_MODE_PLAY_POWEROFF);
|
|
#endif
|
|
}
|
|
#endif /*CONFIG_TWS_POWEROFF_SAME_TIME*/
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief poweroff 立刻关机
|
|
@param 无
|
|
@return 无
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
void power_off_instantly()
|
|
{
|
|
if (goto_poweroff_first_flag == 0) {
|
|
goto_poweroff_first_flag = 1;
|
|
} else {
|
|
puts("power_off_instantly had call\n");
|
|
return;
|
|
}
|
|
#if TCFG_APP_BT_EN
|
|
if ((BT_STATUS_CONNECTING == bt_get_connect_status()) ||
|
|
(BT_STATUS_TAKEING_PHONE == bt_get_connect_status()) ||
|
|
(BT_STATUS_PLAYING_MUSIC == bt_get_connect_status())) {
|
|
if ((bt_get_call_status() == BT_CALL_INCOMING) ||
|
|
(bt_get_call_status() == BT_CALL_OUTGOING)) {
|
|
log_info("key call reject\n");
|
|
/* bt_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */
|
|
return;
|
|
} else if (bt_get_call_status() == BT_CALL_ACTIVE) {
|
|
log_info("key call hangup\n");
|
|
/* bt_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */
|
|
return;
|
|
}
|
|
}
|
|
bt_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL);
|
|
#endif
|
|
|
|
#if TCFG_USER_TWS_ENABLE && CONFIG_TWS_POWEROFF_SAME_TIME
|
|
if (get_tws_sibling_connect_state()) {
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL_TWS);
|
|
} else {
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL);
|
|
}
|
|
#else
|
|
#if TCFG_APP_BT_EN
|
|
sys_enter_soft_poweroff(POWEROFF_NORMAL);
|
|
#else
|
|
app_var.goto_poweroff_flag = 1;
|
|
app_send_message2(APP_MSG_GOTO_MODE, APP_MODE_IDLE, IDLE_MODE_PLAY_POWEROFF);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static void app_idle_enter_softoff(void)
|
|
{
|
|
//power off前的ui处理
|
|
power_off_wait_ui();
|
|
//ui_update_status(STATUS_POWEROFF);
|
|
|
|
#if TCFG_CHARGE_ENABLE
|
|
if (get_lvcmp_det() && (0 == get_charge_full_flag())) {
|
|
log_info("charge inset, system reset!\n");
|
|
cpu_reset();
|
|
}
|
|
#endif
|
|
|
|
#if TCFG_SMART_VOICE_ENABLE && !TCFG_AUDIO_ASR_DEVELOP
|
|
audio_smart_voice_detect_close();
|
|
#endif
|
|
|
|
//关机前先关dac
|
|
dac_power_off();
|
|
|
|
power_set_soft_poweroff();
|
|
}
|
|
|
|
struct app_mode *app_enter_idle_mode(int arg)
|
|
{
|
|
int msg[16];
|
|
struct app_mode *next_mode;
|
|
|
|
app_idle_init(arg);
|
|
|
|
while (1) {
|
|
if (!app_get_message(msg, ARRAY_SIZE(msg), idle_mode_key_table)) {
|
|
continue;
|
|
}
|
|
next_mode = app_mode_switch_handler(msg);
|
|
if (next_mode) {
|
|
break;
|
|
}
|
|
|
|
switch (msg[0]) {
|
|
case MSG_FROM_APP:
|
|
idle_app_msg_handler(msg + 1);
|
|
break;
|
|
case MSG_FROM_DEVICE:
|
|
break;
|
|
}
|
|
|
|
app_default_msg_handler(msg);
|
|
}
|
|
|
|
app_idle_exit();
|
|
|
|
return next_mode;
|
|
}
|
|
|
|
void app_power_off(void *priv)
|
|
{
|
|
app_idle_enter_softoff();
|
|
}
|
|
|
|
static int app_power_off_tone_cb(void *priv, enum stream_event event)
|
|
{
|
|
if (event == STREAM_EVENT_STOP) {
|
|
app_idle_enter_softoff();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int app_idle_init(int param)
|
|
{
|
|
/* printf("idle_mode_enter: %d\n", param); */
|
|
|
|
#if LOW_POWER_IN_IDLE
|
|
idle_app_close_module();
|
|
#endif
|
|
|
|
idle_sub_mode_set(param);
|
|
switch (param) {
|
|
case IDLE_MODE_PLAY_POWEROFF:
|
|
#if TCFG_UI_ENABLE
|
|
power_off_ui_enter();
|
|
#endif
|
|
if (app_var.goto_poweroff_flag) {
|
|
syscfg_write(CFG_MUSIC_VOL, &app_var.music_volume, 2);
|
|
//如果开启了VM配置项暂存RAM功能则在关机前保存数据到vm_flash
|
|
if (get_vm_ram_storage_enable() || get_vm_ram_storage_in_irq_enable()) {
|
|
vm_flush2flash(1);
|
|
}
|
|
os_taskq_flush();
|
|
int ret = play_tone_file_callback(get_tone_files()->power_off, NULL,
|
|
app_power_off_tone_cb);
|
|
printf("power_off tone play ret:%d", ret);
|
|
if (ret) {
|
|
if (app_var.goto_poweroff_flag) {
|
|
log_info("power_off tone play err,enter soft poweroff");
|
|
app_idle_enter_softoff();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IDLE_MODE_WAIT_POWEROFF:
|
|
os_taskq_flush();
|
|
syscfg_write(CFG_MUSIC_VOL, &app_var.music_volume, 2);
|
|
break;
|
|
case IDLE_MODE_CHARGE:
|
|
break;
|
|
}
|
|
|
|
app_send_message(APP_MSG_ENTER_MODE, APP_MODE_IDLE);
|
|
return 0;
|
|
}
|
|
|
|
void app_idle_exit()
|
|
{
|
|
app_send_message(APP_MSG_EXIT_MODE, APP_MODE_IDLE);
|
|
}
|
|
|
|
static int idle_mode_try_enter(int arg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int idle_mode_try_exit()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static const struct app_mode_ops idle_mode_ops = {
|
|
.try_enter = idle_mode_try_enter,
|
|
.try_exit = idle_mode_try_exit,
|
|
};
|
|
|
|
REGISTER_APP_MODE(idle_mode) = {
|
|
.name = APP_MODE_IDLE,
|
|
.index = 0xff,
|
|
.ops = &idle_mode_ops,
|
|
};
|