Files
BPI-M2C/source_sync_rls_25c/source/unisoc/power/powerfw/main.c
T
2026-09-22 09:38:26 +08:00

395 lines
12 KiB
C

/*
* Copyright (c) 2022 by UNISOC Technology(Shanghai), Inc. ALL RIGHTS RESERVED.
*
* These coded instructions, statements, and computer programs are the
* copyrighted works and confidential proprietary information of
* UNISOC Technology(Shanghai), Inc. They may not be modified, copied, reproduced,
* distributed, or disclosed to third parties in any manner, medium, or form,
* in whole or in part, without the prior written consent of UNISOC Technology(Shanghai), Inc.
*/
#include "power_manager_api.h"
#include "power_manager.h"
#include "display_manager.h"
#include "inputmanager/input_manager.h"
#include "battery_manager.h"
#include "utils.h"
#include "ledservice/src/ledservice.h"
#include "power_save_controller.h"
#define DBUS_OFONO_VOICECALL_MANAGER_INTERFACE "org.ofono.VoiceCallManager"
#define DBUS_OFONO_MESSAGE_MANAGER_INTERFACE "org.ofono.MessageManager"
#define DBUS_INTERFACE_POWERSAVE "com.unisoc.powersavectl"
#define REQUEST_MODE_AQUIRE 0
#define REQUEST_MODE_RELEASE 1
//dbus listen thread
pthread_t dbus_ptid;
//loop check calling, false while reboot or shutdown
static bool loop = true;
//configuration dictionary
static dictionary* s_cfg_dict;
//time out
static int s_autosuspend_timeout;
static int s_screen_timeout;
static int s_poweroff_timeout;
int pms_loglevel = PMS_LOG_WARN;
//battery config
static int s_bms_cap_low_level;
static int s_bms_cap_urgent_level;
static int s_bms_high_temp_value;
DBusConnection *connection;
//match rules
char* match_rules[] = {"type='signal',interface='org.ofono.MessageManager'", "type='signal',interface='org.ofono.VoiceCallManager'",
"type='signal',interface='com.unisoc.powersavectl'"};
/*
*sig_hander handle shutdown signal and
* set loop flag false.
*@param sig_number: signal number input
*/
static void sig_handler(int sig_number)
{
if((SIGTERM == sig_number) || (SIGKILL == sig_number))
{
loop = false;
YLOGI("%s received signal %d, loop be set false.", __func__, sig_number);
}else{
YLOGD("%s received signal %d.", __func__, sig_number);
}
}
static void get_ini_para(dictionary *config)
{
s_screen_timeout = iniparser_getint(config, KEY_SCREEN_TIMEOUT, DEFAULT_SCREEN_TIMEOUT);
s_autosuspend_timeout = iniparser_getint(config, KEY_AUTOSUSPEND_TIMEOUT, DEFAULT_AUTOSUSPEND_TIMEOUT);
s_poweroff_timeout = iniparser_getint(config, KEY_POWEROFF_TIMEOUT, DEFAULT_POWEROFF_TIMEOUT);
pms_loglevel = iniparser_getint(config, KEY_LOG_LEVEL, DEFAULT_LOG_LEVEL);
s_bms_cap_low_level = iniparser_getint(config, KEY_BMS_CAP_LOW_LEVEL, BMS_CAPACITY_LOW_LEVEL_DEF);
s_bms_cap_urgent_level = iniparser_getint(config, KEY_BMS_CAP_URGENT_LEVEL, BMS_CAPACITY_URGENT_LEVEL_DEF);
s_bms_high_temp_value = iniparser_getint(config, KEY_BMS_HIGH_TEMP_VALUE, BMS_HIGH_TEMP_VALUE_DEF);
YLOGI("screen timeout =%d Sec", s_screen_timeout);
YLOGI("autosuspend timeout =%d Sec", s_autosuspend_timeout);
YLOGI("poweroff timeout =%d Sec", s_poweroff_timeout);
YLOGI("pms loglevel =%d", pms_loglevel);
YLOGI("bms_cap_low_level =%d", s_bms_cap_low_level);
YLOGI("bms_cap_urgent_level =%d", s_bms_cap_urgent_level);
YLOGI("bms_high_temp_value =%d", s_bms_high_temp_value);
}
static int get_dbus_message_basic(DBusMessageIter iter, char **val_char)
{
int ret = dbus_message_iter_get_arg_type(&iter);
if (ret != DBUS_TYPE_INVALID) {
YLOGD("get_dbus_message_basic is %d", ret);
if (ret == DBUS_TYPE_STRING) {
// dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, val_char);
YLOGD("name:%s", *val_char);
} else {
YLOGE("argument not string!");
return -1;
}
} else{
YLOGE("Argument is invalid!");
return -1;
}
return 0;
}
static void reply_method_call(DBusConnection *connection, DBusMessage *message, int ret)
{
DBusMessage *reply = NULL;
DBusMessage *msg = message;
reply = dbus_message_new_method_return(msg);
DBusMessageIter args;
dbus_message_iter_init_append(reply, &args);
dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &ret);
dbus_connection_send(connection, reply, NULL);
dbus_connection_flush(connection);
dbus_message_unref(reply);
YLOGD("reply done");
}
/*
* handle any method call to powermanager
* as a callback function for dbushandler.
*@param msg: message object from dbus, using for get member.
*@param conn: connection object from dbus, using form reply if exist.
*@return: 0-sucess otherwise-fail
*
*/
static int handle_method_call(DBusMessage* msg, DBusConnection* conn)
{
DBusMessageIter iter;
const char *path = NULL;
const char *iface = NULL;
const char *member = NULL;
char* message_name = NULL;
int ret = -1;
//check dbus calling parameters
if ((iface = dbus_message_get_interface (msg))) {
YLOGI("Dbus-interface: %s", iface);
} else {
YLOGE("Dbus-interface is NULL!");
return -1;
}
if ((member = dbus_message_get_member (msg))) {
YLOGD("Dbus-member: %s", member);
} else {
YLOGE("Dbus-member is NULL!");
return -1;
}
if ((path = dbus_message_get_path (msg))) {
YLOGD("Dbus-path: %s", path);
} else {
YLOGE("Dbus-path is NULL!");
return -1;
}
//handle aquire or release wakelock request
if (!strcmp(iface, DBUS_INTERFACE_PM)
&& !strcmp(path, DBUS_PATH_PM)) {
if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_ACQUIRE_LOCK)) {
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
} else {
//get name from iter
dbus_message_iter_get_basic(&iter, &message_name);
YLOGI("acquire wakelock by %s", message_name);
ret = power_manager_acquire_wakelock(message_name);
reply_method_call(conn, msg, ret);
}
} else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_RELEASE_LOCK)) {
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
}else {
//get name from iter
dbus_message_iter_get_basic(&iter, &message_name);
YLOGI("release wakelock by %s", message_name);
ret = power_manager_release_wakelock(message_name);
reply_method_call(conn, msg, ret);
}
} else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_ACQUIRE_BRIGHTLOCK)) {
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
}else {
get_dbus_message_basic(iter, &message_name);
YLOGI("%s acquire brightlock by dbus", message_name);
ret = handle_brightlock_request(message_name, true);
reply_method_call(conn, msg, ret);
}
} else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_RELEASE_BRIGHTLOCK)) {
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
}else {
get_dbus_message_basic(iter, &message_name);
YLOGI("%s release brightlock by dbus", message_name);
ret = handle_brightlock_request(message_name, false);
reply_method_call(conn, msg, ret);
}
} else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_SCREEN_ON)) {
//need receive parameters to be the reason of wakeup
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
return -1;
} else {
get_dbus_message_basic(iter, &message_name);
YLOGI("%s turn screen on by dbus", message_name);
ret = handle_screen_on_request();
reply_method_call(conn, msg, ret);
}
} else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_SCREEN_OFF)) {
//need receive parameters to be the reason of wakeup
if (!dbus_message_iter_init(msg, &iter)) {
YLOGE("no Argument");
return -1;
} else {
get_dbus_message_basic(iter, &message_name);
YLOGI("%s turn screen off by dbus", message_name);
ret = handle_screen_off_request();
reply_method_call(conn, msg, ret);
}
} else {
YLOGE("not method call!");
}
YLOGE("dbus_message is not pm call");
}
return 0;
}
/*
*signal handle function. process the received signal
*
*
*/
static int handle_signal_received(DBusMessage* msg)
{
//DBusMessageIter iter;
const char *path = NULL;
const char *iface = NULL;
const char *member = NULL;
//check dbus calling parameters
if ((iface = dbus_message_get_interface (msg))) {
YLOGI("Dbus-interface: %s", iface);
} else {
YLOGE("Dbus-interface is NULL!");
return -1;
}
if ((member = dbus_message_get_member (msg))) {
YLOGI("Dbus-member: %s", member);
} else {
YLOGE("Dbus-member is NULL!");
return -1;
}
if ((path = dbus_message_get_path (msg))) {
YLOGD("Dbus-path: %s", path);
} else {
YLOGE("Dbus-path is NULL!");
return -1;
}
if (iface != NULL) {
if (!strcmp(iface, DBUS_OFONO_VOICECALL_MANAGER_INTERFACE)) {
YLOGD("OFFNO VOICECALL MESSAGE");
handle_screen_state_for_callsms(member, iface);
} else if (!strcmp(iface, DBUS_OFONO_MESSAGE_MANAGER_INTERFACE)){
YLOGD("OFFNO MESSAGE SIGNAL-");
handle_screen_state_for_callsms(member, iface);
#ifdef CONFIG_POWERSAVE_ENABLE
} else if (!strcmp(iface, DBUS_INTERFACE_POWERSAVE) && strstr(member, "PowerSave")){
handle_power_save_state(member);
#endif
} else {
YLOGE("not matched signal");
}
}
return 0;
}
/*
*dbus_thread_start_routine process incoming method request
* that wakelock and autosuspend related
*@param conn: dbus connection initialized
*
*/
static void* dbus_thread_start_routine(void *arg __attribute__((unused)))
{
dh_monitor_ms(DBUS_BUS_SYSTEM, DBUS_NAME_PM, handle_method_call, match_rules, 3, handle_signal_received, 200);
return NULL;
}
void uevent_listener_init()
{
if (uevent_init()) {
YLOGE("uevent init fail! ");
return;
}
if (uevent_register_listener(input_uevent_listener)) {
YLOGE("uevent register listener fail! ");
return;
}
#if defined (CONFIG_BATTERY_ENABLED)
if (uevent_register_listener(battery_uevent_listener)) {
YLOGE("uevent register listener fail! ");
return;
}
#endif
if (uevent_start_loop()) {
YLOGE("start uevent listen fail! ");
return;
}
}
/*
*main thread, quit while autosuspend thread exit.
*@param: void
*@return: 0-sucess otherwise-fail
*/
int main(int argc, char *argv[]){
if (signal(SIGINT, sig_handler) == SIG_ERR){
YLOGE("can not catch signal");
}
s_cfg_dict = load_config(DEFAULT_CFG_PATH_SYS, DEFAULT_CFG_PATH_USR);
get_ini_para(s_cfg_dict);
input_init(s_poweroff_timeout);
#if defined(CONFIG_LED_ENABLED)
led_init();
#endif
#if defined(CONFIG_BATTERY_ENABLED)
batterymanager_init(s_bms_cap_low_level,s_bms_cap_urgent_level,s_bms_high_temp_value);
#endif
uevent_listener_init();
#if defined(CONFIG_POWERSAVE_ENABLE)
power_save_ctl_init();
#endif
#if defined(CONFIG_DISPLAY_ENABLED)
display_manager_init(s_screen_timeout);
#endif
power_manager_init(s_autosuspend_timeout);
#if (!defined CONFIG_ENABLE_PERIODIC_AUTOSUSPEND) && (!defined CONFIG_SUSPEND_BLOCKER)
pm_enable_auto_suspend();
#endif
//dbus handler
if (pthread_create(&dbus_ptid, NULL, dbus_thread_start_routine, NULL) < 0) {
YLOGE("%s: Failed to create dbus_handler", __FUNCTION__);
return -1;
}
YLOGD("dbus thread create success!");
pthread_join(dbus_ptid, NULL); /* wait "dbus" thread exit. */
YLOGE("dbus thread exit...");
return 0;
}