src/vibrator/vibrator.c
src/core/edbus-handler.c)
+SET(SRCS ${SRCS}
+ display/util.c
+ display/llinterface.c
+ display/conf.c
+ display/setting.c
+ display/poll.c
+ display/core.c
+ display/lsensor.c
+ display/key-filter.c
+ display/battery.c)
+
# libdeviced
SET(DEVICED_SRCS
src/shared/battery.c)
tapi
dlog
syspopup-caller
- notification
device-node
+ sensor
+ notification
libsmack
libsystemd-daemon)
ADD_DEFINITIONS("-DPREDEFINE_SO_DIR=\"${LIB_INSTALL_DIR}/ss_predefine/\"")
ADD_DEFINITIONS("-DLIBPATH=\"${LIB_INSTALL_DIR}/\"")
ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"")
+
+ADD_DEFINITIONS("-DENABLE_KEY_FILTER")
+ADD_DEFINITIONS("-DENABLE_X_LCD_ONOFF")
+ADD_DEFINITIONS("-DENABLE_DLOG_OUT")
+ADD_DEFINITIONS("-DENABLE_PM_LOG")
+
IF( $ENV{ARCH} MATCHES "arm" )
ADD_DEFINITIONS("-DTARGET")
ENDIF()
SET(UDEV_RULES udev-rules/91-system-server.rules)
CONFIGURE_FILE(${UDEV_RULES}.in ${UDEV_RULES} @ONLY)
+CONFIGURE_FILE(device-daemon.in device-daemon @ONLY)
# libdeviced
ADD_LIBRARY(${DEVICED_NAME} SHARED ${DEVICED_SRCS})
INSTALL(FILES ${MOVINAND_FORMAT} DESTINATION bin)
INSTALL(FILES ${UDEV_RULES} DESTINATION ${UDEV_RULES_PATH})
+INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/device-daemon DESTINATION bin)
INSTALL(FILES system-server.conf DESTINATION /etc/dbus-1/system.d)
INSTALL(FILES ${CMAKE_SOURCE_DIR}/packaging/system-server.rule DESTINATION /opt/etc/smack/accesses.d)
INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/mmc-smack-label DESTINATION bin)
ADD_SUBDIRECTORY(restarter)
ADD_SUBDIRECTORY(sys_event)
+ADD_SUBDIRECTORY(pm_event)
ADD_SUBDIRECTORY(sys_pci_noti)
--- /dev/null
+#!/bin/sh
+
+KERNVER=`uname -r`
+
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib
+export PATH=$PATH:/usr/bin
+export ELM_FONT_PATH=@PREFIX@/share/SLP/fonts:@PREFIX@/share/SLP/licensed_fonts:@PREFIX@/share/fonts/truetype/ttf-bitstream-vera
+export PM_EXEC_PRG=@PREFIX@/bin/@IDLE_LOCK@
+
+export PM_TO_NORMAL=600 # normal state timeout seconds
+export PM_TO_LCDDIM=5 # dim state timeout seconds
+export PM_TO_LCDOFF=5 # off state timeout seconds
+#export PM_TO_LCDOFF=0 # prevent suspend mode
+
+export PM_SYS_DIMBRT=0
+
+DEV_INPUT=
+ABS_POSITION_X=0x15
+ABS_POSITION_Y=0x16
+for file in /sys/class/input/event*; do
+ if [ -e $file ]; then
+ dev_keytype=`cat ${file}/device/capabilities/key`
+ if [ "$dev_keytype" != 0 ]; then
+ DEV_INPUT=$DEV_INPUT:/dev/input/${file#/sys/class/input/}
+ continue
+ fi
+ abs_num=`cat ${file}/device/capabilities/abs | wc -w | cut -d ' ' -f 1`
+ if [ $abs_num != 2 ]; then
+ continue
+ fi
+ abs_val=`cat ${file}/device/capabilities/abs | cut -d ' ' -f 1`
+ if [ $(((0x$abs_val >> $ABS_POSITION_X) & 0x1)) != 1 ]; then
+ continue
+ fi
+ if [ $(((0x$abs_val >> $ABS_POSITION_Y) & 0x1)) != 1 ]; then
+ continue
+ fi
+ DEV_INPUT=$DEV_INPUT:/dev/input/${file#/sys/class/input/}
+ fi
+done
+
+export PM_INPUT=$DEV_INPUT
+
+PMD=@PREFIX@/bin/@EXEC@
+
+echo "Input Event: $PM_INPUT"
+OPT_X_DPMS="-x"
+echo "LCD Power: X-DPMS enabled"
+
+/usr/bin/system_server &
+
+exit 0
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#include <Ecore.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "core.h"
+#include "battery.h"
+
+#define CHARGING_STATE(x) ((x) & CHRGR_FLAG)
+#define FULL_CAPACITY_RAW (10000)
+#define FULL_CAPACITY (100)
+#define BATTERY_FULL_THRESHOLD (98)
+#define MAX_COUNT_UNCHARGING (10)
+#define MAX_COUNT_CHARGING (10)
+#define PRINT_ALL_BATT_NODE(x) /*print_all_batt_node(x)*/
+
+int (*get_battery_capacity)();
+
+enum state_b {
+ B_UNCHARGING = 0,
+ B_CHARGING = 1,
+ B_END = 2
+};
+
+typedef struct _batt_node {
+ time_t clock;
+ int capacity;
+ struct _batt_node *preview;
+ struct _batt_node *next;
+} Batt_node;
+
+enum state_a {
+ A_TIMETOEMPTY = 0,
+ A_TIMETOFULL = 1,
+ A_END = 2
+};
+
+static Ecore_Timer *timeout_id = NULL;
+static int noti_fd = 0;
+
+static Batt_node *batt_head[B_END];
+static Batt_node *batt_tail[B_END];
+static int MAX_VALUE_COUNT[B_END] = {MAX_COUNT_UNCHARGING, MAX_COUNT_CHARGING};
+static double avg_factor[B_END] = {-1.0, -1.0};
+static int full_capacity = 0;
+static int old_capacity = 0;
+static int charging_state = 0;
+static int multiply_value[B_END] = {-1, 1};
+extern int system_wakeup_flag;
+
+static void print_all_batt_node(enum state_b b_index)
+{
+ Batt_node *node = NULL;
+ int cnt = 0;
+
+ LOGINFO("print_all_batt_node [%d]", b_index);
+
+ if(b_index < 0 || b_index >= B_END)
+ return;
+
+ if(batt_head[b_index] == NULL)
+ return;
+
+ node = batt_head[b_index];
+ while(node != NULL) {
+ cnt++;
+ LOGINFO("[%d] capacity %5d, time %s", cnt, node->capacity,
+ ctime(&node->clock));
+ node = node->next;
+ }
+}
+
+static int check_value_validity(enum state_b b_index,time_t clock,int capacity)
+{
+ time_t old_clock = 0;
+ int old_capacity = 0;
+ int capadiff = 0;
+
+ if(b_index < 0 || b_index >= B_END)
+ return -1;
+
+ if(batt_head[b_index] == NULL)
+ return 0;
+
+ old_capacity = batt_head[b_index]->capacity;
+
+ if(system_wakeup_flag == true) {
+ LOGERR("check value validity : invalid cuz system suspend!");
+ system_wakeup_flag = false;
+ return -1;
+ }
+ /* capacity */
+ capadiff = capacity - old_capacity;
+ if((capadiff * multiply_value[b_index]) <= 0) {
+ LOGERR("check value validity : capadiff(%d) wrong!", capadiff);
+ return -1;
+ }
+ return 0;
+}
+
+static int add_batt_node(enum state_b b_index, time_t clock, int capacity)
+{
+ Batt_node *node = NULL;
+
+ PRINT_ALL_BATT_NODE(b_index);
+
+ if(b_index < 0 || b_index >= B_END)
+ return -1;
+
+ node = (Batt_node *) malloc(sizeof(Batt_node));
+ if(node == NULL) {
+ LOGERR("Not enough memory, add battery node fail!");
+ return -1;
+ }
+
+ node->clock = clock;
+ node->capacity = capacity;
+
+ if(batt_head[b_index] == NULL && batt_tail[b_index] == NULL) {
+ batt_head[b_index] = batt_tail[b_index] = node;
+ node->preview = NULL;
+ node->next = NULL;
+ } else {
+ node->next = batt_head[b_index];
+ node->preview = NULL;
+ batt_head[b_index]->preview = node;
+ batt_head[b_index] = node;
+ }
+ PRINT_ALL_BATT_NODE(b_index);
+ return 0;
+}
+
+static int reap_batt_node(enum state_b b_index, int max_count)
+{
+ Batt_node *node = NULL;
+ Batt_node *tmp = NULL;
+ int cnt = 0;
+
+ PRINT_ALL_BATT_NODE(b_index);
+
+ if(b_index < 0 || b_index >= B_END)
+ return -1;
+
+ if(max_count <= 0)
+ return -1;
+
+ node = batt_head[b_index];
+
+ while(node != NULL) {
+ if(cnt >= max_count) break;
+ cnt++;
+ node = node->next;
+ }
+
+ if(node != NULL && node != batt_tail[b_index]) {
+ batt_tail[b_index] = node;
+ node = node->next;
+ batt_tail[b_index]->next = NULL;
+ while(node != NULL) {
+ tmp = node;
+ node = node->next;
+ free(tmp);
+ }
+ }
+ PRINT_ALL_BATT_NODE(b_index);
+ return 0;
+}
+
+static int del_all_batt_node(enum state_b b_index)
+{
+ Batt_node *node = NULL;
+
+ PRINT_ALL_BATT_NODE(b_index);
+
+ if(b_index < 0 || b_index >= B_END)
+ return -1;
+ if(batt_head[b_index] == NULL)
+ return 0;
+
+ while(batt_head[b_index] != NULL) {
+ node = batt_head[b_index];
+ batt_head[b_index] = batt_head[b_index]->next;
+ free(node);
+ }
+ batt_tail[b_index] = NULL;
+ PRINT_ALL_BATT_NODE(b_index);
+ return 0;
+}
+
+static float update_factor(enum state_b b_index)
+{
+ Batt_node *node = NULL;
+ double factor = 0.0;
+ double total_factor = 0.0;
+ int cnt = 0;
+ double timediff = 0.0;
+ double capadiff = 0.0;
+
+ if(b_index < 0 || b_index >= B_END)
+ return 0;
+
+ if(batt_head[b_index] == NULL || batt_head[b_index]->next == NULL)
+ return avg_factor[b_index];
+
+ node = batt_head[b_index];
+ while(1) {
+ timediff = difftime(node->clock, node->next->clock);
+ capadiff = node->capacity - node->next->capacity;
+ if(capadiff < 0)
+ capadiff*=(-1);
+ if(capadiff != 0)
+ factor = timediff / capadiff;
+ total_factor += factor;
+
+ node = node->next;
+ cnt++;
+
+ /*LOGINFO("[%d] timediff(%lf) / capadiff(%lf) = factor(%lf)",
+ cnt, timediff, capadiff, factor);*/
+ factor = 0.0;
+
+ if(node == NULL || node->next == NULL)
+ break;
+ if(cnt >= MAX_VALUE_COUNT[b_index]) {
+ reap_batt_node(b_index, MAX_VALUE_COUNT[b_index]);
+ break;
+ }
+ }
+ LOGINFO(" sum = %lf", total_factor);
+ total_factor /= (float)cnt;
+ LOGINFO(" avg_factor = %lf", total_factor);
+
+ return total_factor;
+}
+
+static void update_time(enum state_a a_index, int seconds)
+{
+ int clock;
+
+ if(a_index < 0 || a_index >= A_END)
+ return;
+
+ if(seconds <= 0)
+ return;
+
+ switch(a_index) {
+ case A_TIMETOFULL:
+ vconf_set_int(VCONFKEY_PM_BATTERY_TIMETOFULL,
+ seconds);
+ LOGINFO("update time[%d,%d]", a_index, seconds);
+ break;
+ case A_TIMETOEMPTY:
+ vconf_set_int(VCONFKEY_PM_BATTERY_TIMETOEMPTY,
+ seconds);
+ LOGINFO("update time[%d,%d]", a_index, seconds);
+ break;
+ }
+}
+
+int battinfo_calculation(void)
+{
+ time_t clock;
+ int capacity = 0;
+ int estimated_time = 0;
+ int tmp = 0;
+
+ capacity = get_battery_capacity();
+
+ if(capacity <= 0)
+ return -1;
+ if(capacity == old_capacity)
+ return 0;
+
+ old_capacity = capacity;
+
+ if(get_charging_status(&tmp) == 0)
+ charging_state = (tmp > 0 ? EINA_TRUE : EINA_FALSE);
+
+ clock = time(NULL);
+ if(charging_state == EINA_TRUE) {
+ del_all_batt_node(B_UNCHARGING);
+ if((capacity * 100 / full_capacity)
+ >= BATTERY_FULL_THRESHOLD) {
+ if(battery_ops.get_charge_full()) {
+ del_all_batt_node(B_CHARGING);
+ LOGINFO("battery fully charged!");
+ update_time(A_TIMETOFULL, 0);
+ return 0;
+ }
+ }
+ if(batt_head[B_CHARGING] == NULL) {
+ add_batt_node(B_CHARGING, clock, capacity);
+ } else {
+ add_batt_node(B_CHARGING, clock, capacity);
+ avg_factor[B_CHARGING] = update_factor(B_CHARGING);
+ }
+ estimated_time = (float)(full_capacity - capacity) *
+ avg_factor[B_CHARGING];
+ update_time(A_TIMETOFULL, estimated_time);
+ } else {
+ del_all_batt_node(B_CHARGING);
+ if(system_wakeup_flag == true) {
+ del_all_batt_node(B_UNCHARGING);
+ system_wakeup_flag = false;
+ }
+ if(batt_head[B_UNCHARGING] == NULL) {
+ add_batt_node(B_UNCHARGING, clock, capacity);
+ } else {
+ add_batt_node(B_UNCHARGING, clock, capacity);
+ avg_factor[B_UNCHARGING] = update_factor(B_UNCHARGING);
+ }
+ estimated_time = (float)capacity * avg_factor[B_UNCHARGING];
+ update_time(A_TIMETOEMPTY, estimated_time);
+ }
+ return 0;
+}
+
+static Eina_Bool battinfo_cb(void *data)
+{
+ battinfo_calculation();
+ return ECORE_CALLBACK_RENEW;
+}
+
+static int init_battery_func(void)
+{
+ int ret = -1;
+
+ ret = battery_ops.get_capacity_raw();
+ if(ret >= 0) {
+ get_battery_capacity = battery_ops.get_capacity_raw;
+ full_capacity = FULL_CAPACITY_RAW;
+ LOGINFO("init_battery_func : full capacity(%d)", full_capacity);
+ return 0;
+ }
+
+ ret = battery_ops.get_capacity();
+ if(ret >= 0) {
+ get_battery_capacity = battery_ops.get_capacity;
+ full_capacity = FULL_CAPACITY;
+ LOGINFO("init_battery_func : full capacity(%d)", full_capacity);
+ return 0;
+ }
+
+ LOGERR("init_battery_func : fail to get battery info!");
+ return -1;
+}
+
+int start_battinfo_gathering(int timeout)
+{
+ int ret;
+
+ LOGINFO("Start battery gathering!");
+
+ if(timeout < 0) {
+ LOGERR("invalid timeout value [%d]!", timeout);
+ return -1;
+ }
+ if(init_battery_func() != 0)
+ return -1;
+
+ old_capacity = 0;
+ battinfo_calculation();
+
+ if(timeout > 0) {
+ /* Using g_timer for gathering battery info */
+ timeout_id = ecore_timer_add(timeout,
+ (Ecore_Task_Cb)battinfo_cb, NULL);
+ } else if(timeout == 0) {
+ /* Using heynoti from system-server(udev)
+ for gathering battery info */
+ if((noti_fd = heynoti_init()) < 0) {
+ LOGERR("heynoti init failed!");
+ return -1;
+ }
+ ret = heynoti_subscribe(noti_fd, "device_charge_chgdet",
+ (void *)battinfo_calculation, (void *)NULL);
+ if(ret != 0) {
+ LOGERR("heynoti subscribe fail!");
+ return -1;
+ }
+
+ ret = heynoti_attach_handler(noti_fd);
+ if(ret != 0) {
+ LOGERR("heynoti attach handler fail!");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void end_battinfo_gathering(void)
+{
+ LOGINFO("End battery gathering!");
+
+ if (!timeout_id) {
+ ecore_timer_del(timeout_id);
+ timeout_id = NULL;
+ }
+ if (noti_fd > 0) {
+ heynoti_close(noti_fd);
+ noti_fd = 0;
+ }
+
+ del_all_batt_node(B_UNCHARGING);
+ del_all_batt_node(B_CHARGING);
+}
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef __PM_BATTERY_H_
+#define __PM_BATTERY_H_
+
+#define BATTERY_POLLING_PERIOD 30 /* second */
+
+int start_battinfo_gathering(int timeout);
+void end_battinfo_gathering();
+
+#endif
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "conf.h"
+
+enum {
+ IDX_NAME = 0,
+ IDX_DEFAULT,
+ IDX_END
+};
+
+static const char *def_values[][IDX_END] = {
+ {"PM_INPUT", "/dev/event0:/dev/event1"},
+ {"PM_TO_START", "0"},
+ {"PM_TO_NORMAL", "600"},
+ {"PM_TO_LCDDIM", "5"},
+ {"PM_TO_LCDOFF", "5"},
+ {"PM_TO_SLEEP", "0"},
+ {"PM_SYS_POWER", "/sys/power/state"},
+ {"PM_SYS_BRIGHT", "/sys/class/backlight/mobile-bl/brightness"},
+ {"PM_SYS_BRIGHT", "/sys/class/backlight/mobile-bl/max_brightness"},
+ {"PM_SYS_BLPWR", "/sys/class/backlight/mobile-bl/bl_power"},
+ {"PM_SYS_DIMBRT", "0"},
+ {"PM_SYS_BLON", "0"},
+ {"PM_SYS_BLOFF", "4"},
+ {"PM_SYS_FB_NORMAL", "1"},
+ {"PM_SYS_STATE", "mem"},
+ {"PM_EXEC_PRG", NULL},
+ {"PM_END", ""},
+};
+
+static char *_find_default(char *name)
+{
+ char *ret = NULL;
+ int i = 0;
+
+ while (strcmp("PM_END", def_values[i][IDX_NAME])) {
+ if (!strcmp(name, def_values[i][IDX_NAME])) {
+ ret = def_values[i][IDX_DEFAULT];
+ break;
+ }
+ i++;
+ }
+ return ret;
+}
+
+int get_env(char *name, char *buf, int size)
+{
+ char *ret;
+
+ ret = getenv(name);
+ if ((ret == NULL) || (strlen(ret) > 1024)) {
+ ret = _find_default(name);
+ if (ret)
+ snprintf(buf, size, "%s", ret);
+ else
+ snprintf(buf, size, "");
+ } else {
+ snprintf(buf, size, "%s", ret);
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#ifndef __POWER_MANAGER_CONF_H__
+#define __POWER_MANAGER_CONF_H__
+
+#define EN_SYS_DIMBRT "PM_SYS_DIMBRT"
+
+extern int get_env(char *, char *, int);
+
+#endif
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file core.c
+ * @brief Power manager main loop.
+ *
+ * This file includes Main loop, the FSM, signal processing.
+ */
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <heynoti.h>
+#include <aul.h>
+#include <vconf-keys.h>
+#include <Ecore.h>
+
+#include "core.h"
+#include "battery.h"
+#include "device-node.h"
+#include "core/queue.h"
+#include "core/data.h"
+
+#define USB_CON_PIDFILE "/var/run/.system_server.pid"
+#define PM_STATE_LOG_FILE "/var/log/pm_state.log"
+#define PM_WAKEUP_NOTI_NAME "system_wakeup"
+#define PM_EVENT_NOTI_NAME "pm_event"
+#define PM_EVENT_NOTI_PATH "/opt/share/noti/"PM_EVENT_NOTI_NAME
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+#define LOCKSTATUS_TIMEOUT 3
+#define TELEPHONY_SIGNAL_TIMEOUT 10
+
+#define SET_BRIGHTNESS_IN_BOOTLOADER "/usr/bin/save_blenv SLP_LCD_BRIGHT"
+
+/* default transition, action fuctions */
+static int default_trans(int evt);
+static int default_action(int timeout);
+static int default_check(int next);
+
+unsigned int pm_status_flag;
+
+static void (*power_saving_func) (int onoff);
+static void reset_timeout(int timeout);
+static int get_lcd_timeout_from_settings();
+
+int pm_cur_state;
+int pm_old_state;
+Ecore_Timer *timeout_src_id;
+static time_t last_t;
+static int pre_suspend_flag = false;
+int system_wakeup_flag = false;
+
+struct state states[S_END] = {
+ {S_START, default_trans, default_action, default_check,},
+ {S_NORMAL, default_trans, default_action, default_check,},
+ {S_LCDDIM, default_trans, default_action, default_check,},
+ {S_LCDOFF, default_trans, default_action, default_check,},
+ {S_SLEEP, default_trans, default_action, default_check,}
+};
+
+int (*pm_init_extention) (void *data);
+void (*pm_exit_extention) (void);
+
+static char state_string[5][10] =
+ { "S_START", "S_NORMAL", "S_LCDDIM", "S_LCDOFF", "S_SLEEP" };
+
+static int trans_table[S_END][EVENT_END] = {
+ /* Timeout , Input */
+ {S_START, S_START}, /* S_START */
+ {S_LCDDIM, S_NORMAL}, /* S_NORMAL */
+ {S_LCDOFF, S_NORMAL}, /* S_LCDDIM */
+#ifdef TIZEN_EMUL
+ {S_LCDOFF, S_NORMAL}, /* S_LCDOFF */
+#else
+ {S_SLEEP, S_NORMAL}, /* S_LCDOFF */
+#endif
+ {S_LCDOFF, S_NORMAL}, /* S_SLEEP */
+};
+
+#define SHIFT_UNLOCK 4
+#define MASK_RESET_TIMEOUT 0x8 /* 1000 */
+#define MASK_MARGIN_TIMEOUT (0x1 << 8)
+#define SHIFT_CHANGE_STATE 7
+#define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */
+#define LOCK_SCREEN_TIMEOUT 10
+#define SHIFT_HOLD_KEY_BLOCK 16
+
+#define DEFAULT_NORMAL_TIMEOUT 30
+#define DEFAULT_DIM_TIMEOUT 5
+#define DEFAULT_OFF_TIMEOUT 5
+#define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_HOLD_KEY_BLOCK) & 0x1)
+#define LOCK_SCREEN_WATING_TIME 50000 /* 50 ms */
+#define LOCK_SCREEN_WATING_MAX_COUNT 14 /* 50 * 14 : 700 ms at worst */
+#define MASK32 0xffffffff
+
+static int received_sleep_cmd = 0;
+
+typedef struct _pm_lock_node {
+ pid_t pid;
+ Ecore_Timer *timeout_id;
+ bool holdkey_block;
+ struct _pm_lock_node *next;
+} PmLockNode;
+
+static PmLockNode *cond_head[S_END];
+
+void set_process_active(bool flag, pid_t pid)
+{
+ char str[6];
+
+ sprintf(str, "%d", (int)pid);
+ ss_action_entry_call_internal(
+ (flag ? PREDEF_ACTIVE : PREDEF_INACTIVE), 1, str);
+}
+
+static int refresh_app_cond()
+{
+ trans_condition = 0;
+
+ if (cond_head[S_LCDDIM] != NULL)
+ trans_condition = trans_condition | MASK_DIM;
+ if (cond_head[S_LCDOFF] != NULL)
+ trans_condition = trans_condition | MASK_OFF;
+ if (cond_head[S_SLEEP] != NULL)
+ trans_condition = trans_condition | MASK_SLP;
+
+ return 0;
+}
+
+static PmLockNode *find_node(enum state_t s_index, pid_t pid)
+{
+ PmLockNode *t = cond_head[s_index];
+
+ while (t != NULL) {
+ if (t->pid == pid)
+ break;
+ t = t->next;
+ }
+ return t;
+}
+
+static PmLockNode *add_node(enum state_t s_index, pid_t pid, Ecore_Timer *timeout_id,
+ bool holdkey_block)
+{
+ PmLockNode *n;
+
+ n = (PmLockNode *) malloc(sizeof(PmLockNode));
+ if (n == NULL) {
+ LOGERR("Not enough memory, add cond. fail");
+ return NULL;
+ }
+
+ n->pid = pid;
+ n->timeout_id = timeout_id;
+ n->holdkey_block = holdkey_block;
+ n->next = cond_head[s_index];
+ cond_head[s_index] = n;
+
+ refresh_app_cond();
+ return n;
+}
+
+static int del_node(enum state_t s_index, PmLockNode *n)
+{
+ PmLockNode *t;
+ PmLockNode *prev;
+
+ if (n == NULL)
+ return 0;
+
+ t = cond_head[s_index];
+ prev = NULL;
+ while (t != NULL) {
+ if (t == n) {
+ if (prev != NULL)
+ prev->next = t->next;
+ else
+ cond_head[s_index] = cond_head[s_index]->next;
+ free(t);
+ break;
+ }
+ prev = t;
+ t = t->next;
+ }
+ refresh_app_cond();
+ return 0;
+}
+
+static Eina_Bool del_dim_cond(void *data)
+{
+ PmLockNode *tmp = NULL;
+ LOGINFO("delete prohibit dim condition by timeout\n");
+
+ tmp = find_node(S_LCDDIM, (pid_t) data);
+ del_node(S_LCDDIM, tmp);
+
+ if (timeout_src_id == NULL)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool del_off_cond(void *data)
+{
+ PmLockNode *tmp = NULL;
+ LOGINFO("delete prohibit off condition by timeout\n");
+
+ tmp = find_node(S_LCDOFF, (pid_t) data);
+ del_node(S_LCDOFF, tmp);
+
+ if (timeout_src_id == NULL)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool del_sleep_cond(void *data)
+{
+ PmLockNode *tmp = NULL;
+ LOGINFO("delete prohibit sleep condition by timeout\n");
+
+ tmp = find_node(S_SLEEP, (pid_t) data);
+ del_node(S_SLEEP, tmp);
+
+ if (timeout_src_id == NULL)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ set_process_active(EINA_FALSE, (pid_t)data);
+ return EINA_FALSE;
+}
+
+/* update transition condition for application requrements */
+static int proc_condition(PMMsg *data)
+{
+ PmLockNode *tmp = NULL;
+ unsigned int val = data->cond;
+ pid_t pid = data->pid;
+ Ecore_Timer *cond_timeout_id = NULL;
+ bool holdkey_block = 0;
+ int val_timeout;
+
+ if (val == 0)
+ return 0;
+ /* for debug */
+ char pname[PATH_MAX];
+ char buf[PATH_MAX];
+ int fd_cmdline;
+ snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
+ fd_cmdline = open(buf, O_RDONLY);
+ if (fd_cmdline < 0) {
+ snprintf(pname, PATH_MAX,
+ "does not exist now(may be dead without unlock)");
+ } else {
+ read(fd_cmdline, pname, PATH_MAX);
+ close(fd_cmdline);
+ }
+
+ if (val & MASK_DIM) {
+ if (data->timeout > 0) {
+ cond_timeout_id =
+ ecore_timer_add(data->timeout / 1000,
+ (Ecore_Task_Cb)del_dim_cond, (void*)pid);
+ }
+ holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
+ tmp = find_node(S_LCDDIM, pid);
+ if (tmp == NULL)
+ add_node(S_LCDDIM, pid, cond_timeout_id, holdkey_block);
+ else if (tmp->timeout_id > 0) {
+ ecore_timer_del(tmp->timeout_id);
+ tmp->timeout_id = cond_timeout_id;
+ tmp->holdkey_block = holdkey_block;
+ }
+ /* for debug */
+ LOGINFO("[%s] locked by pid %d - process %s\n", "S_NORMAL", pid,
+ pname);
+ }
+ if (val & MASK_OFF) {
+ if (data->timeout > 0) {
+ cond_timeout_id =
+ ecore_timer_add(data->timeout / 1000,
+ (Ecore_Task_Cb)del_off_cond, (void*)pid);
+ }
+ holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
+ tmp = find_node(S_LCDOFF, pid);
+ if (tmp == NULL)
+ add_node(S_LCDOFF, pid, cond_timeout_id, holdkey_block);
+ else if (tmp->timeout_id > 0) {
+ ecore_timer_del(tmp->timeout_id);
+ tmp->timeout_id = cond_timeout_id;
+ tmp->holdkey_block = holdkey_block;
+ }
+ /* for debug */
+ LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDDIM", pid,
+ pname);
+ }
+ if (val & MASK_SLP) {
+ if (data->timeout > 0) {
+ cond_timeout_id =
+ ecore_timer_add(data->timeout / 1000,
+ (Ecore_Task_Cb)del_sleep_cond, (void*)pid);
+ }
+ tmp = find_node(S_SLEEP, pid);
+ if (tmp == NULL)
+ add_node(S_SLEEP, pid, cond_timeout_id, 0);
+ else if (tmp->timeout_id > 0) {
+ ecore_timer_del(tmp->timeout_id);
+ tmp->timeout_id = cond_timeout_id;
+ tmp->holdkey_block = 0;
+ }
+ set_process_active(EINA_TRUE, (pid_t)data);
+
+ /* for debug */
+ LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDOFF", pid,
+ pname);
+ }
+
+ /* UNLOCK(GRANT) condition processing */
+ val = val >> SHIFT_UNLOCK;
+ if (val & MASK_DIM) {
+ tmp = find_node(S_LCDDIM, pid);
+ del_node(S_LCDDIM, tmp);
+ LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LORMAL",
+ pid, pname);
+ }
+ if (val & MASK_OFF) {
+ tmp = find_node(S_LCDOFF, pid);
+ del_node(S_LCDOFF, tmp);
+ LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDDIM",
+ pid, pname);
+ }
+ if (val & MASK_SLP) {
+ tmp = find_node(S_SLEEP, pid);
+ del_node(S_SLEEP, tmp);
+ set_process_active(EINA_FALSE, (pid_t)data);
+
+ LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDOFF",
+ pid, pname);
+ }
+ val = val >> 8;
+ if (val != 0) {
+ if ((val & 0x1)) {
+ reset_timeout(states[pm_cur_state].timeout);
+ LOGINFO("reset timeout\n", "S_LCDOFF", pid, pname);
+ }
+ } else {
+ /* guard time for suspend */
+ if (pm_cur_state == S_LCDOFF) {
+ reset_timeout(5);
+ LOGINFO("margin timeout (5 seconds)\n");
+ }
+ }
+
+ if (timeout_src_id == 0)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ return 0;
+}
+
+static int proc_change_state(unsigned int cond)
+{
+ int next_state = 0;
+ struct state *st;
+ int i;
+
+ for (i = S_NORMAL; i < S_END; i++) {
+ if ((cond >> (SHIFT_CHANGE_STATE + i)) & 0x1) {
+ next_state = i;
+ break;
+ }
+ }
+ LOGINFO("Change State to %s", state_string[next_state]);
+
+ switch (next_state) {
+ case S_NORMAL:
+ case S_LCDDIM:
+ case S_LCDOFF:
+ /* state transition */
+ pm_old_state = pm_cur_state;
+ pm_cur_state = next_state;
+ st = &states[pm_cur_state];
+
+ /* enter action */
+ if (st->action) {
+ st->action(st->timeout);
+ }
+ break;
+ case S_SLEEP:
+ LOGINFO("Dangerous requests.");
+ /* at first LCD_OFF and then goto sleep */
+ /* state transition */
+ pm_old_state = pm_cur_state;
+ pm_cur_state = S_LCDOFF;
+ st = &states[pm_cur_state];
+ if (st->action) {
+ st->action(0);
+ }
+ pm_old_state = pm_cur_state;
+ pm_cur_state = S_SLEEP;
+ st = &states[pm_cur_state];
+ if (st->action) {
+ st->action(0);
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* If some changed, return 1 */
+int check_processes(enum state_t prohibit_state)
+{
+ PmLockNode *t = cond_head[prohibit_state];
+ PmLockNode *tmp = NULL;
+ int ret = 0;
+
+ while (t != NULL) {
+ if (kill(t->pid, 0) == -1) {
+ LOGERR("%d process does not exist, delete the REQ"
+ " - prohibit state %d ",
+ t->pid, prohibit_state);
+ tmp = t;
+ ret = 1;
+ }
+ t = t->next;
+
+ if (tmp != NULL) {
+ del_node(prohibit_state, tmp);
+ tmp = NULL;
+ }
+ }
+
+ return ret;
+}
+
+int check_holdkey_block(enum state_t state)
+{
+ PmLockNode *t = cond_head[state];
+ int ret = 0;
+
+ LOGINFO("check holdkey block : state of %s", state_string[state]);
+
+ while (t != NULL) {
+ if (t->holdkey_block == true) {
+ ret = 1;
+ LOGINFO("Hold key blocked by pid(%d)!", t->pid);
+ break;
+ }
+ t = t->next;
+ }
+
+ return ret;
+}
+
+int delete_condition(enum state_t state)
+{
+ PmLockNode *t = cond_head[state];
+ int ret = 0;
+ PmLockNode *tmp = NULL;
+
+ LOGINFO("delete condition : state of %s", state_string[state]);
+
+ while (t != NULL) {
+ if (t->timeout_id > 0) {
+ ecore_timer_del(t->timeout_id);
+ }
+ tmp = t;
+ t = t->next;
+ LOGINFO("delete node of pid(%d)", tmp->pid);
+ del_node(state, tmp);
+ }
+
+ return 0;
+}
+
+#ifdef ENABLE_PM_LOG
+
+typedef struct _pm_history {
+ time_t time;
+ enum pm_log_type log_type;
+ int keycode;
+} pm_history;
+
+static int max_history_count = MAX_LOG_COUNT;
+static pm_history pm_history_log[MAX_LOG_COUNT] = {0,};
+static int history_count = 0;
+
+static char history_string[PM_LOG_MAX][15] =
+ {"PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON FAIL",
+ "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF FAIL", "SLEEP"};
+
+void pm_history_init()
+{
+ memset(pm_history_log, 0x0, sizeof(pm_history_log));
+ history_count = 0;
+ max_history_count = MAX_LOG_COUNT;
+}
+
+void pm_history_save(enum pm_log_type log_type, int code)
+{
+ time_t now;
+
+ time(&now);
+ pm_history_log[history_count].time = now;
+ pm_history_log[history_count].log_type = log_type;
+ pm_history_log[history_count].keycode = code;
+ history_count++;
+
+ if (history_count >= max_history_count)
+ history_count = 0;
+}
+
+void pm_history_print(int fd, int count)
+{
+ int start_index, index, i;
+ char buf[255];
+ char time_buf[30];
+
+ if (count <= 0 || count > max_history_count)
+ return 0;
+
+ start_index = (history_count - count + max_history_count)
+ % max_history_count;
+
+ for (i = 0; i < count; i++) {
+ index = (start_index + i) % max_history_count;
+
+ if (pm_history_log[index].time == 0)
+ continue;
+
+ if (pm_history_log[index].log_type < PM_LOG_MIN ||
+ pm_history_log[index].log_type >= PM_LOG_MAX)
+ continue;
+ ctime_r(&pm_history_log[index].time, time_buf);
+ snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s",
+ index,
+ history_string[pm_history_log[index].log_type],
+ pm_history_log[index].keycode,
+ time_buf);
+ write(fd, buf, strlen(buf));
+ }
+}
+#endif
+
+void print_info(int fd)
+{
+ int s_index = 0;
+ char buf[255];
+ int i = 1, ret;
+
+ if (fd < 0)
+ return;
+
+ snprintf(buf, sizeof(buf),
+ "\n==========================================="
+ "===========================\n");
+ write(fd, buf, strlen(buf));
+ snprintf(buf, sizeof(buf),"Timeout Info: Run[%d] Dim[%d] Off[%d]\n",
+ states[S_NORMAL].timeout,
+ states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
+ write(fd, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
+ (trans_condition & MASK_DIM) ? state_string[S_NORMAL] : "-",
+ (trans_condition & MASK_OFF) ? state_string[S_LCDDIM] : "-",
+ (trans_condition & MASK_SLP) ? state_string[S_LCDOFF] : "-");
+ write(fd, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Current State: %s\n",
+ state_string[pm_cur_state]);
+ write(fd, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
+ write(fd, buf, strlen(buf));
+
+ for (s_index = S_NORMAL; s_index < S_END; s_index++) {
+ PmLockNode *t;
+ char pname[PATH_MAX];
+ int fd_cmdline;
+ t = cond_head[s_index];
+
+ while (t != NULL) {
+ snprintf(buf, sizeof(buf), "/proc/%d/cmdline", t->pid);
+ fd_cmdline = open(buf, O_RDONLY);
+ if (fd_cmdline < 0) {
+ snprintf(pname, PATH_MAX,
+ "does not exist now"
+ "(may be dead without unlock)");
+ } else {
+ read(fd_cmdline, pname, PATH_MAX);
+ close(fd_cmdline);
+ }
+ snprintf(buf, sizeof(buf),
+ " %d: [%s] locked by pid %d - process %s\n",
+ i++, state_string[s_index - 1], t->pid, pname);
+ write(fd, buf, strlen(buf));
+ t = t->next;
+ }
+ }
+#ifdef ENABLE_PM_LOG
+ pm_history_print(fd, 250);
+#endif
+}
+
+/* SIGHUP signal handler
+ * For debug... print info to syslog
+ */
+static void sig_hup(int signo)
+{
+ int fd;
+ char buf[255];
+ time_t now_time;
+ char time_buf[30];
+
+ time(&now_time);
+ ctime_r(&now_time, time_buf);
+
+ fd = open(PM_STATE_LOG_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd != -1) {
+ snprintf(buf, sizeof(buf),
+ "\npm_state_log now-time : %d(s) %s\n\n",
+ (int)now_time, time_buf);
+ write(fd, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "pm_status_flag: %x\n", pm_status_flag);
+ write(fd, buf, strlen(buf));
+
+ snprintf(buf, sizeof(buf), "received sleep cmd count : %d\n",
+ received_sleep_cmd);
+ write(fd, buf, strlen(buf));
+
+ print_info(fd);
+ close(fd);
+ }
+
+ fd = open("/dev/console", O_WRONLY);
+ if (fd != -1) {
+ print_info(fd);
+ close(fd);
+ }
+}
+
+/* timeout handler */
+Eina_Bool timeout_handler(void *data)
+{
+ LOGINFO("Time out state %s\n", state_string[pm_cur_state]);
+
+ if (timeout_src_id != NULL) {
+ ecore_timer_del(timeout_src_id);
+ timeout_src_id = NULL;
+ }
+
+ if ((pm_status_flag & VCALL_FLAG)
+ && (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP)) {
+ pm_status_flag &= ~(VCALL_FLAG);
+ reset_timeout(TELEPHONY_SIGNAL_TIMEOUT);
+ return EINA_FALSE;
+ }
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+ return EINA_FALSE;
+}
+
+static void reset_timeout(int timeout)
+{
+ if (timeout_src_id != 0) {
+ ecore_timer_del(timeout_src_id);
+ timeout_src_id = NULL;
+ }
+ if (timeout > 0)
+ timeout_src_id = ecore_timer_add(timeout,
+ (Ecore_Task_Cb)timeout_handler, NULL);
+}
+
+static void sig_usr(int signo)
+{
+ pm_status_flag |= VCALL_FLAG;
+}
+
+/*
+ * default transition function
+ * 1. call check
+ * 2. transition
+ * 3. call enter action function
+ */
+static int default_trans(int evt)
+{
+ struct state *st = &states[pm_cur_state];
+ int next_state;
+
+ if (pm_cur_state == S_NORMAL && st->timeout == 0) {
+ LOGINFO("LCD always on enabled!");
+ return 0;
+ }
+
+ next_state = (enum state_t)trans_table[pm_cur_state][evt];
+
+ /* check conditions */
+ while (st->check && !st->check(next_state)) {
+ /* There is a condition. */
+ LOGINFO("%s -> %s : check fail", state_string[pm_cur_state],
+ state_string[next_state]);
+ if (!check_processes(next_state)) {
+ /* this is valid condition - the application that sent the condition is running now. */
+ return -1;
+ }
+ }
+
+ /* state transition */
+ pm_old_state = pm_cur_state;
+ pm_cur_state = next_state;
+ st = &states[pm_cur_state];
+
+ /* enter action */
+ if (st->action) {
+ if (pm_cur_state == S_LCDDIM && st->timeout == 0) {
+ /* dim timeout 0, enter next state directly */
+ LOGINFO("dim timeout 0, goto LCDOFF state");
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+ }
+ else {
+ st->action(st->timeout);
+ }
+ }
+
+ return 0;
+}
+
+/* default enter action function */
+static int default_action(int timeout)
+{
+ int ret;
+ int wakeup_count = -1;
+ char buf[NAME_MAX];
+ char *pkgname = NULL;
+ int i = 0;
+ int lock_state = -1;
+ struct itimerval val;
+
+ if (pm_cur_state != pm_old_state && pm_cur_state != S_SLEEP) {
+ set_setting_pmstate(pm_cur_state);
+ }
+ switch (pm_cur_state) {
+ case S_NORMAL:
+ /*
+ * normal state : backlight on and restore
+ * the previous brightness
+ */
+ if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP) {
+ if (pre_suspend_flag == true) {
+ power_ops.post_resume();
+ pre_suspend_flag = false;
+ }
+ for (i = 0; i < LOCK_SCREEN_WATING_MAX_COUNT;
+ i++) {
+ vconf_get_int(VCONFKEY_IDLE_LOCK_STATE,
+ &lock_state);
+ LOGERR("Idle lock check: %d, vonf: %d",
+ i, lock_state);
+ if (lock_state)
+ break;
+ usleep(LOCK_SCREEN_WATING_TIME);
+ }
+
+#ifndef X86 /* Different with ARM FB driver, IA gfx driver is sensitive to the order. */
+ backlight_ops.restore();
+ backlight_ops.on();
+#else
+ backlight_ops.on();
+ backlight_ops.restore();
+#endif
+ } else if (pm_old_state == S_LCDDIM)
+ backlight_ops.restore();
+
+ if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON)
+ backlight_ops.on();
+ break;
+
+ case S_LCDDIM:
+ /* lcd dim state : dim the brightness */
+ backlight_ops.dim();
+ if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP) {
+ backlight_ops.on();
+ }
+
+ if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON)
+ backlight_ops.on();
+ break;
+
+ case S_LCDOFF:
+ if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) {
+ /* lcd off state : turn off the backlight */
+ backlight_ops.off();
+
+ if (pre_suspend_flag == false) {
+ pre_suspend_flag = true;
+ power_ops.pre_suspend();
+ }
+ }
+
+ if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF)
+ backlight_ops.off();
+ break;
+
+ case S_SLEEP:
+ /*
+ * We can not always be blocked here because of that
+ * in-progress checking in kernel for wakeup count,
+ * if we cannot get the result within some time, then
+ * just give it up and then retry it in the next time,
+ * this method would not break that original expected
+ * 'aggresive suspend' idea, but at the same time make
+ * the system is 'always' responsible to some keypress
+ * actions like power button press.
+ */
+ val.it_value.tv_sec = TOLERANCE_SLOT;
+ val.it_value.tv_usec = 0;
+ val.it_interval.tv_sec = val.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &val, NULL);
+
+ /* sleep state : set system mode to SUSPEND */
+ if (device_get_property(DEVICE_TYPE_POWER,
+ PROP_POWER_WAKEUP_COUNT, &wakeup_count) < 0)
+ LOGERR("wakeup count read error");
+
+ if (wakeup_count < 0) {
+ LOGINFO("Wakup Event! Can not enter suspend mode.");
+ goto go_lcd_off;
+ }
+
+ if (device_set_property(DEVICE_TYPE_POWER,
+ PROP_POWER_WAKEUP_COUNT, wakeup_count) < 0) {
+ LOGERR("wakeup count write error");
+ goto go_lcd_off;
+ }
+ goto go_suspend;
+ }
+
+ /* set timer with current state timeout */
+ reset_timeout(timeout);
+ LOGINFO("timout set: %s state %d sec",
+ state_string[pm_cur_state], timeout);
+
+ return 0;
+
+go_suspend:
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_SLEEP, pm_cur_state);
+#endif
+ power_ops.suspend();
+ LOGINFO("system wakeup!!");
+ system_wakeup_flag = true;
+ heynoti_publish(PM_WAKEUP_NOTI_NAME);
+ /* Resume !! */
+ if (power_ops.check_wakeup_src() == EVENT_DEVICE)
+ /* system waked up by devices */
+ states[pm_cur_state].trans(EVENT_DEVICE);
+ else
+ /* system waked up by user input */
+ states[pm_cur_state].trans(EVENT_INPUT);
+ return 0;
+
+go_lcd_off:
+ heynoti_publish(PM_WAKEUP_NOTI_NAME);
+ /* Resume !! */
+ states[pm_cur_state].trans(EVENT_DEVICE);
+ return 0;
+}
+
+/*
+ * default check function
+ * return
+ * 0 : can't transit, others : transitable
+ */
+static int default_check(int next)
+{
+ int trans_cond = trans_condition & MASK_BIT;
+ int lock_state = -1;
+
+ LOGINFO("trans_cond : %x", trans_cond);
+
+ vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
+ if (lock_state==VCONFKEY_IDLE_LOCK && next != S_SLEEP) {
+ LOGINFO("default_check:LOCK STATE, it's transitable");
+ return 1;
+ }
+
+ switch (next) {
+ case S_LCDDIM:
+ trans_cond = trans_cond & MASK_DIM;
+ break;
+ case S_LCDOFF:
+ trans_cond = trans_cond & MASK_OFF;
+ break;
+ case S_SLEEP:
+ trans_cond = trans_cond & MASK_SLP;
+ break;
+ default: /* S_NORMAL is exceptional */
+ trans_cond = 0;
+ break;
+ }
+
+ if (trans_cond != 0)
+ return 0;
+
+ return 1; /* transitable */
+}
+
+/* get configurations from setting */
+static int get_lcd_timeout_from_settings(void)
+{
+ int i;
+ int val = 0;
+ int ret = -1;
+ char buf[255];
+
+ for (i = 0; i < S_END; i++) {
+ switch (states[i].state) {
+ case S_NORMAL:
+ ret = get_run_timeout(&val);
+ if (ret != 0) {
+ ret = get_env("PM_TO_NORMAL", buf, 255);
+ val = atoi(buf);
+ }
+ break;
+ case S_LCDDIM:
+ ret = get_dim_timeout(&val);
+ break;
+ case S_LCDOFF:
+ ret = get_off_timeout(&val);
+ break;
+ default:
+ /* This state doesn't need to set time out. */
+ ret = -1;
+ break;
+ }
+ if (ret == 0 || val < 0) {
+ states[i].timeout = val;
+ } else {
+ switch (states[i].state) {
+ case S_NORMAL:
+ states[i].timeout = DEFAULT_NORMAL_TIMEOUT;
+ break;
+ case S_LCDDIM:
+ states[i].timeout = DEFAULT_DIM_TIMEOUT;
+ break;
+ case S_LCDOFF:
+ states[i].timeout = DEFAULT_OFF_TIMEOUT;
+ break;
+ default:
+ states[i].timeout = 0;
+ break;
+ }
+ }
+ LOGINFO("%s state : %d timeout", state_string[i],
+ states[i].timeout);
+ }
+
+ return 0;
+}
+
+static void default_saving_mode(int onoff)
+{
+ if (onoff) {
+ pm_status_flag |= PWRSV_FLAG;
+ } else {
+ pm_status_flag &= ~PWRSV_FLAG;
+ }
+ if (pm_cur_state == S_NORMAL)
+ backlight_ops.restore();
+}
+
+static int poll_callback(int condition, PMMsg *data)
+{
+ time_t now;
+
+ if (condition == INPUT_POLL_EVENT) {
+ if (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP)
+ LOGINFO("Power key input");
+ time(&now);
+ if (last_t != now) {
+ states[pm_cur_state].trans(EVENT_INPUT);
+ last_t = now;
+ }
+ } else if (condition == PM_CONTROL_EVENT) {
+ LOGINFO("process pid(%d) pm_control condition : %x ",
+ data->pid, data->cond);
+
+ if (data->cond & MASK_BIT
+ || (data->cond >> SHIFT_UNLOCK) & MASK_BIT)
+ proc_condition(data);
+
+ if (data->cond & CHANGE_STATE_BIT) {
+ LOGINFO("Change state by pid(%d) request.", data->pid);
+ proc_change_state(data->cond);
+ }
+ }
+
+ return 0;
+}
+
+static int update_setting(int key_idx, int val)
+{
+ char buf[PATH_MAX];
+ int ret = -1;
+ int dim_timeout = -1;
+ int run_timeout = -1;
+ int power_saving_stat = -1;
+ int power_saving_display_stat = -1;
+
+ switch (key_idx) {
+ case SETTING_TO_NORMAL:
+ ret = get_dim_timeout(&dim_timeout);
+ if (ret < 0 || dim_timeout < 0) {
+ LOGERR("Can not get dim timeout.set default 5 seconds");
+ dim_timeout = DEFAULT_DIM_TIMEOUT;
+ }
+ if (val < 0) {
+ LOGERR("LCD timeout is wrong, set default 15 seconds");
+ val = 15;
+ }
+ if (val == 0) {
+ states[S_NORMAL].timeout = 0;
+ } else if (val > dim_timeout) {
+ states[S_NORMAL].timeout = val - dim_timeout;
+ } else {
+ states[S_NORMAL].timeout = 1;
+ }
+ states[pm_cur_state].trans(EVENT_INPUT);
+ break;
+ case SETTING_LOW_BATT:
+ if (val <= VCONFKEY_SYSMAN_BAT_WARNING_LOW &&
+ val >= VCONFKEY_SYSMAN_BAT_POWER_OFF ) {
+ if (!(pm_status_flag & CHRGR_FLAG))
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ } else {
+ if (pm_status_flag & PWRSV_FLAG)
+ power_saving_func(false);
+ pm_status_flag &= ~LOWBT_FLAG;
+ pm_status_flag &= ~BRTCH_FLAG;
+ }
+ break;
+ case SETTING_CHARGING:
+ if (val) {
+ if (pm_status_flag & LOWBT_FLAG) {
+ power_saving_func(false);
+ pm_status_flag &= ~LOWBT_FLAG;
+ }
+ pm_status_flag |= CHRGR_FLAG;
+ } else {
+ int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
+ vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
+ &bat_state);
+ if (bat_state <= VCONFKEY_SYSMAN_BAT_WARNING_LOW &&
+ bat_state >= VCONFKEY_SYSMAN_BAT_POWER_OFF ) {
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ }
+ pm_status_flag &= ~CHRGR_FLAG;
+ }
+ break;
+ case SETTING_BRT_LEVEL:
+ if (pm_status_flag & PWRSV_FLAG) {
+ pm_status_flag |= BRTCH_FLAG;
+ LOGINFO("brightness changed in low battery,"
+ "escape dim state");
+ }
+ backlight_ops.set_default_brt(val);
+ snprintf(buf, sizeof(buf), "%s %d",
+ SET_BRIGHTNESS_IN_BOOTLOADER, val);
+ LOGINFO("Brightness set in bl : %d",val);
+ system(buf);
+ break;
+ case SETTING_LOCK_SCREEN:
+ if (val == VCONFKEY_IDLE_LOCK) {
+ set_lock_screen_state(val);
+ states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
+ states[S_LCDDIM].timeout = 0;
+ LOGERR("LOCKED: NORMAL timeout is set by %d seconds",
+ LOCK_SCREEN_TIMEOUT);
+ } else {
+ set_lock_screen_state(val);
+ get_run_timeout(&run_timeout);
+ if (run_timeout < 0) {
+ LOGERR("Can not get run timeout."
+ "set default 15 seconds");
+ run_timeout = 10;
+ }
+ states[S_NORMAL].timeout = run_timeout;
+ states[S_LCDDIM].timeout = DEFAULT_DIM_TIMEOUT;
+ LOGINFO("UNLOCKED: NORMAL timeout is set by"
+ " %d seconds", run_timeout);
+ }
+ if (pm_cur_state == S_NORMAL) {
+ states[pm_cur_state].trans(EVENT_INPUT);
+ }
+ break;
+ case SETTING_POWER_SAVING:
+ if (val == 1)
+ vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY,
+ &power_saving_display_stat);
+ if (power_saving_display_stat != 1)
+ power_saving_display_stat = 0;
+ set_power_saving_display_stat(power_saving_display_stat);
+ if (device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE,
+ power_saving_display_stat) < 0) {
+ LOGERR("Fail to set display frame rate!");
+ }
+ backlight_ops.restore();
+ break;
+ case SETTING_POWER_SAVING_DISPLAY:
+ vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS,
+ &power_saving_stat);
+ if (power_saving_stat == 1) {
+ if (val == 1)
+ power_saving_display_stat = 1;
+ else
+ power_saving_display_stat = 0;
+ set_power_saving_display_stat(power_saving_display_stat);
+ if (device_set_property(DEVICE_TYPE_DISPLAY,
+ PROP_DISPLAY_FRAME_RATE, power_saving_display_stat) < 0) {
+ LOGERR("Fail to set display frame rate!");
+ }
+ backlight_ops.restore();
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static void check_seed_status(void)
+{
+ int ret = -1;
+ int tmp = 0;
+ int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
+ int max_brt = 0;
+ int brt = 0;
+ int lock_state = -1;
+ int power_saving_stat = -1;
+ int power_saving_display_stat = -1;
+
+ /* Charging check */
+ if ((get_charging_status(&tmp) == 0) && (tmp > 0)) {
+ pm_status_flag |= CHRGR_FLAG;
+ }
+
+ ret = get_setting_brightness(&tmp);
+ if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
+ LOGINFO("fail to read vconf value for brightness");
+ brt = PM_DEFAULT_BRIGHTNESS;
+ if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)
+ vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
+ tmp = brt;
+ }
+ LOGINFO("Set brightness from Setting App. %d", tmp);
+ backlight_ops.set_default_brt(tmp);
+
+ vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
+ if (bat_state <= VCONFKEY_SYSMAN_BAT_WARNING_LOW &&
+ bat_state >= VCONFKEY_SYSMAN_BAT_POWER_OFF) {
+ if (!(pm_status_flag & CHRGR_FLAG)) {
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ }
+ }
+ backlight_ops.restore();
+
+ /* USB connection check
+ * If connected, add sleep prohibit condition */
+ if ((get_usb_status(&tmp) == 0) && (tmp > 0)) {
+ tmp = readpid(USB_CON_PIDFILE);
+ if (tmp != -1) {
+ add_node(S_SLEEP, tmp, -1, 0);
+ }
+ }
+
+ /* lock screen check */
+ ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
+ set_lock_screen_state(lock_state);
+ if (lock_state == VCONFKEY_IDLE_LOCK) {
+ states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
+ states[S_LCDDIM].timeout = 0;
+ LOGERR("LCD NORMAL timeout is set by %d seconds"
+ " for lock screen", LOCK_SCREEN_TIMEOUT);
+ }
+
+ /* power saving display stat */
+ vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS,
+ &power_saving_stat);
+ if (power_saving_stat <= 0) {
+ power_saving_display_stat = 0;
+ } else {
+ vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY,
+ &power_saving_display_stat);
+ }
+ if (power_saving_display_stat < 0) {
+ LOGERR("failed to read power saving display stat!");
+ } else {
+ LOGINFO("power saving display stat : %d",
+ power_saving_display_stat);
+ set_power_saving_display_stat(power_saving_display_stat);
+ }
+
+ return;
+}
+
+enum {
+ INIT_SETTING = 0,
+ INIT_INTERFACE,
+ INIT_POLL,
+ INIT_FIFO,
+ INIT_END
+};
+
+static char *errMSG[INIT_END] = {
+ [INIT_SETTING] = "setting init error",
+ [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
+ [INIT_POLL] = "input devices poll init error",
+ [INIT_FIFO] = "FIFO poll init error",
+};
+
+/* logging indev_list for debug */
+void printlist()
+{
+ int i;
+ unsigned int total = 0;
+ indev *tmp;
+
+ total = eina_list_count(indev_list);
+ LOGINFO("***** total list : %d *****", total);
+ for (i = 0; i < total; i++) {
+ tmp = (indev*)eina_list_nth(indev_list, i);
+ LOGINFO("* %d | path:%s, fd:%d, dev_fd:%d",
+ i, tmp->dev_path, tmp->fd, tmp->dev_fd);
+ }
+ LOGINFO("***************************\n");
+}
+
+static int input_action(char* input_act, char* input_path)
+{
+ int ret = -1;
+ Eina_List *list_node = NULL;
+ Eina_List *l = NULL;
+ Eina_List *l_next = NULL;
+ indev *data = NULL;
+ PmLockNode *tmp = NULL;
+
+ if (!strcmp("add", input_act)) {
+ LOGINFO("add input path : %s", input_path);
+ ret = init_pm_poll_input(poll_callback, input_path);
+ } else if (!strcmp("remove", input_act)) {
+ EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data)
+ if(!strcmp(input_path, data->dev_path)) {
+ LOGINFO("remove %s", input_path);
+ ecore_main_fd_handler_del(data->dev_fd);
+ close(data->fd);
+ free(data->dev_path);
+ indev_list = eina_list_remove_list(indev_list, l);
+ }
+ ret = 0;
+ } else if (!strcmp("change", input_act)) {
+ if (!strcmp("ESD", input_path)) {
+ LOGINFO("ESD on");
+ if (pm_cur_state == S_NORMAL) {
+ backlight_ops.off();
+ backlight_ops.on();
+ } else if (pm_cur_state == S_LCDDIM) {
+ backlight_ops.off();
+ backlight_ops.dim();
+ }
+ ret = 0;
+ }
+ ret = 0;
+ } else if (!strcmp("lock", input_act)) {
+ if (!strcmp("lcdoff", input_path)) {
+ tmp = find_node(S_SLEEP, 1);
+ if (!tmp && add_node(S_SLEEP, 1, -1, 0) != NULL)
+ LOGINFO("lock LCD OFF from pm_event");
+ }
+ ret = 0;
+ } else if (!strcmp("unlock", input_act)) {
+ if (!strcmp("lcdoff", input_path)) {
+ tmp = find_node(S_SLEEP, 1);
+ if (tmp != NULL) {
+ del_node(S_SLEEP, tmp);
+ LOGINFO("unlock LCD OFF from pm_event");
+ }
+ }
+ ret = 0;
+ }
+ return ret;
+}
+
+static void input_cb(void* data)
+{
+ FILE *fp;
+ char input_act[NAME_MAX], input_path[MAX_INPUT];
+ char args[NAME_MAX + MAX_INPUT];
+ int i, ret = -1;
+
+ fp = fopen((char *) data, "r");
+ if (fp == NULL) {
+ LOGERR("input file open fail");
+ return ;
+ }
+
+ while (fgets(args, NAME_MAX + MAX_INPUT, fp) != NULL) {
+ if (args[strlen(args)-1] != '\n') {
+ LOGERR("input file must be terminated with"
+ " new line character\n");
+ break;
+ }
+ args[strlen(args) - 1] = '\0';
+ for (i = 0; i< NAME_MAX + MAX_INPUT; i++) {
+ if (args[i] == ' ') {
+ if (i >= NAME_MAX) {
+ LOGERR("bsfile name is over"
+ " the name_max(255)\n");
+ break;
+ }
+ strncpy(input_act, args,
+ i < NAME_MAX ? i : NAME_MAX);
+ input_act[i]='\0';
+ strncpy(input_path, args + i + 1, MAX_INPUT);
+ input_path[MAX_INPUT - 1] = '\0';
+ ret = input_action(input_act, input_path);
+
+ /* debug */
+ printlist();
+ break;
+ }
+ }
+ if (ret < 0)
+ break;
+ }
+ fclose(fp);
+
+ if (ret != -1) {
+ fp = fopen((char *) data, "w");
+ if (fp == NULL) {
+ return ;
+ }
+ fclose(fp);
+ }
+ return ;
+}
+
+static int set_noti(int *noti_fd)
+{
+ int fd;
+ char buf[PATH_MAX];
+
+ fd = heynoti_init();
+ if (fd < 0) {
+ LOGERR("heynoti_init error");
+ return -1;
+ }
+
+ if (heynoti_subscribe(fd, PM_EVENT_NOTI_NAME,
+ input_cb, PM_EVENT_NOTI_PATH) < 0) {
+ LOGERR("input file change noti add failed(%s). %s",
+ buf, strerror(errno));
+ return -1;
+ } else {
+ LOGERR("input file change noti add ok");
+ }
+
+ if (heynoti_attach_handler(fd) < 0) {
+ LOGERR("heynoti_attach_handler error");
+ return -1;
+ }
+
+ *noti_fd = fd;
+ return 0;
+}
+
+static int unset_noti(int noti_fd)
+{
+ if (noti_fd < 0) {
+ LOGINFO("set noti already failed. nothing to do in unset");
+ return 0;
+ }
+
+ if (heynoti_unsubscribe(noti_fd, PM_EVENT_NOTI_NAME, input_cb) < 0
+ || heynoti_detach_handler(noti_fd) < 0) {
+ LOGERR("heynoti unsubsribe or detach error");
+ return -1;
+ }
+ return 0;
+}
+
+static int noti_fd = -1;
+/**
+ * Power manager Main
+ *
+ */
+void start_pm_main(void)
+{
+ int ret, i;
+ unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
+
+ LOGINFO("Start power manager");
+
+ signal(SIGHUP, sig_hup);
+
+ power_saving_func = default_saving_mode;
+ /* noti init for new input device like bt mouse */
+ indev_list = NULL;
+ set_noti(¬i_fd);
+
+ for (i = INIT_SETTING; i < INIT_END; i++) {
+ switch (i) {
+ case INIT_SETTING:
+ ret = init_setting(update_setting);
+ break;
+ case INIT_INTERFACE:
+ get_lcd_timeout_from_settings();
+ ret = init_sysfs(flags);
+ break;
+ case INIT_POLL:
+ LOGINFO("poll init");
+ ret = init_pm_poll(poll_callback);
+ break;
+ }
+ if (ret != 0) {
+ LOGERR("%s", errMSG[i]);
+ break;
+ }
+ }
+
+ if (i == INIT_END) {
+#ifdef ENABLE_PM_LOG
+ pm_history_init();
+#endif
+ check_seed_status();
+
+ if (pm_init_extention != NULL)
+ pm_init_extention(NULL);
+
+ if (flags & WITHOUT_STARTNOTI) { /* start without noti */
+ LOGINFO("Start Power managing without noti");
+ pm_cur_state = S_NORMAL;
+ set_setting_pmstate(pm_cur_state);
+ reset_timeout(states[S_NORMAL].timeout);
+ }
+ start_battinfo_gathering(30);
+ }
+}
+
+void end_pm_main(void)
+{
+ int i;
+
+ end_battinfo_gathering();
+ for (i = i - 1; i >= INIT_SETTING; i--) {
+ switch (i) {
+ case INIT_SETTING:
+ exit_setting();
+ break;
+ case INIT_INTERFACE:
+ exit_sysfs();
+ break;
+ case INIT_POLL:
+ unset_noti(noti_fd);
+ exit_pm_poll();
+ break;
+ }
+ }
+
+ if (pm_exit_extention != NULL)
+ pm_exit_extention();
+
+ LOGINFO("Stop power manager");
+}
+
+/**
+ * @}
+ */
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file core.h
+ * @brief Power manager main loop header file
+ */
+#ifndef __POWER_MANAGER_H__
+#define __POWER_MANAGER_H__
+
+#include "util.h"
+#include "poll.h"
+#include "llinterface.h"
+#include "setting.h"
+#include "conf.h"
+
+#define WITHOUT_STARTNOTI 0x1
+#define MASK_BIT 0x7 /* 111 */
+#define MASK_DIM 0x1 /* 001 */
+#define MASK_OFF 0x2 /* 010 */
+#define MASK_SLP 0x4 /* 100 */
+
+#define VCALL_FLAG 0x00000001
+#define LOWBT_FLAG 0x00000100
+#define CHRGR_FLAG 0x00000200
+#define PWRSV_FLAG 0x00000400
+#define BRTCH_FLAG 0x00002000
+
+#define TOLERANCE_SLOT 2
+
+#ifdef ENABLE_PM_LOG
+#define MAX_LOG_COUNT 250
+
+enum pm_log_type {
+ PM_LOG_MIN = 0,
+ PM_LOG_KEY_PRESS = PM_LOG_MIN, /* key log */
+ PM_LOG_KEY_LONG_PRESS,
+ PM_LOG_KEY_RELEASE,
+ PM_LOG_LCD_ON, /* lcd log */
+ PM_LOG_LCD_ON_FAIL,
+ PM_LOG_LCD_DIM,
+ PM_LOG_LCD_DIM_FAIL,
+ PM_LOG_LCD_OFF,
+ PM_LOG_LCD_OFF_FAIL,
+ PM_LOG_SLEEP,
+ PM_LOG_MAX
+};
+
+void pm_history_save(enum pm_log_type, int);
+#endif
+
+extern unsigned int pm_status_flag;
+
+/*
+ * State enumeration
+ */
+enum state_t {
+ S_START = 0,
+ S_NORMAL, /*< normal state */
+ S_LCDDIM, /*< LCD dimming */
+ S_LCDOFF, /*< LCD off */
+ S_SLEEP, /*< system suspend */
+ S_END
+};
+
+/*
+ * Global variables
+ * pm_cur_state : current state
+ * states : state definitions
+ * trans_table : state transition table
+ */
+int pm_cur_state;
+int pm_old_state;
+
+/*
+ * @brief State structure
+ */
+struct state {
+ enum state_t state; /**< state number */
+ int (*trans) (int evt); /**< transition function pointer */
+ int (*action) (int timeout); /**< enter action */
+ int (*check) (int next); /**< transition check function */
+ int timeout;
+} states[S_END];
+
+/* If the bit in a condition variable is set,
+ * we cannot transit the state until clear this bit. */
+int trans_condition;
+pid_t idle_pid;
+int (*pm_init_extention) (void *data); /**< extention init function */
+void (*pm_exit_extention) (void); /**< extention exit function */
+int check_processes(enum state_t prohibit_state);
+
+/*
+ * Power manager Main loop
+ *
+ * @internal
+ * @param[in] flags If the first bit of this is set, start managing without Start notification.
+ * If the second bit of ths is set, use unified device manager functions.
+ */
+void start_pm_main();
+
+/**
+ * @}
+ */
+
+#endif
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <vconf.h>
+#include <Ecore.h>
+
+#include "core.h"
+#include "poll.h"
+#include "core/queue.h"
+#include "core/data.h"
+
+#include <linux/input.h>
+#ifndef KEY_SCREENLOCK
+#define KEY_SCREENLOCK 0x98
+#endif
+
+#define PREDEF_LEAVESLEEP "leavesleep"
+
+#define USEC_PER_SEC 1000000
+#define LONG_PRESS_INTERVAL 1 /* 1 second */
+#define COMBINATION_INTERVAL 0.3 /* 0.3 second */
+#define POWER_KEY_PRESS_IGNORE_TIME 0.7 /* 0.7 second */
+
+#define KEY_RELEASED 0
+#define KEY_PRESSED 1
+#define KEY_BEING_PRESSED 2
+
+#define KEY_COMBINATION_STOP 0
+#define KEY_COMBINATION_START 1
+#define KEY_COMBINATION_SCREENCAPTURE 2
+
+static struct timeval pressed_time;
+static Ecore_Timer *longkey_timeout_id = NULL;
+static Ecore_Timer *combination_timeout_id = NULL;
+static int cancel_lcdoff;
+static int key_combination = KEY_COMBINATION_STOP;
+static int powerkey_ignored = false;
+
+static inline int current_state_in_on(void)
+{
+ return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL);
+}
+
+static void longkey_pressed()
+{
+ int val = 0;
+ char *opt;
+ LOGINFO("Power key long pressed!");
+ cancel_lcdoff = 1;
+
+ /* change state - LCD on */
+ recv_data.pid = -1;
+ recv_data.cond = 0x100;
+ (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
+
+ (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
+
+ if (vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val) == 0 && val == 1)
+ opt = PREDEF_POWEROFF;
+ else
+ opt = PREDEF_PWROFF_POPUP;
+
+ ss_action_entry_call_internal(opt, 0);
+}
+
+static Eina_Bool longkey_pressed_cb(void *data)
+{
+ longkey_pressed();
+ longkey_timeout_id = NULL;
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool combination_failed_cb(void *data)
+{
+ key_combination = KEY_COMBINATION_STOP;
+ combination_timeout_id = NULL;
+
+ return EINA_FALSE;
+}
+
+static unsigned long timediff_usec(struct timeval t1, struct timeval t2)
+{
+ unsigned long udiff;
+
+ udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC;
+ udiff += (t2.tv_usec - t1.tv_usec);
+
+ return udiff;
+}
+
+static void stop_key_combination(void)
+{
+ key_combination = KEY_COMBINATION_STOP;
+ if (combination_timeout_id > 0) {
+ g_source_remove(combination_timeout_id);
+ combination_timeout_id = NULL;
+ }
+}
+
+static int process_power_key(struct input_event *pinput)
+{
+ int ignore = true;
+
+ switch (pinput->value) {
+ case KEY_RELEASED:
+ if (current_state_in_on() && !cancel_lcdoff &&
+ !(key_combination == KEY_COMBINATION_SCREENCAPTURE)) {
+ check_processes(S_LCDOFF);
+ check_processes(S_LCDDIM);
+
+ if (!check_holdkey_block(S_LCDOFF) &&
+ !check_holdkey_block(S_LCDDIM)) {
+ delete_condition(S_LCDOFF);
+ delete_condition(S_LCDDIM);
+ /* LCD off forcly */
+ recv_data.pid = -1;
+ recv_data.cond = 0x400;
+ (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
+ }
+ } else {
+ if (!powerkey_ignored)
+ ignore = false;
+ }
+
+ stop_key_combination();
+ cancel_lcdoff = 0;
+ if (longkey_timeout_id > 0) {
+ ecore_timer_del(longkey_timeout_id);
+ longkey_timeout_id = NULL;
+ }
+ break;
+ case KEY_PRESSED:
+ if (timediff_usec(pressed_time, pinput->time) <
+ (POWER_KEY_PRESS_IGNORE_TIME * USEC_PER_SEC)) {
+ LOGINFO("power key double pressed ignored");
+ powerkey_ignored = true;
+ break;
+ } else {
+ powerkey_ignored = false;
+ }
+ LOGINFO("power key pressed");
+ pressed_time.tv_sec = (pinput->time).tv_sec;
+ pressed_time.tv_usec = (pinput->time).tv_usec;
+ if (key_combination == KEY_COMBINATION_STOP) {
+ /* add long key timer */
+ longkey_timeout_id = ecore_timer_add(
+ LONG_PRESS_INTERVAL,
+ (Ecore_Task_Cb)longkey_pressed_cb, NULL);
+ key_combination = KEY_COMBINATION_START;
+ combination_timeout_id = ecore_timer_add(
+ COMBINATION_INTERVAL,
+ (Ecore_Task_Cb)combination_failed_cb, NULL);
+ } else if (key_combination == KEY_COMBINATION_START) {
+ if (combination_timeout_id > 0) {
+ ecore_timer_del(combination_timeout_id);
+ combination_timeout_id = NULL;
+ }
+ LOGINFO("capture mode");
+ key_combination = KEY_COMBINATION_SCREENCAPTURE;
+ ignore = false;
+ }
+ break;
+ case KEY_BEING_PRESSED:
+ if (timediff_usec(pressed_time, pinput->time) >
+ (LONG_PRESS_INTERVAL * USEC_PER_SEC))
+ longkey_pressed();
+ break;
+ }
+
+ return ignore;
+}
+
+static int process_volumedown_key(struct input_event *pinput)
+{
+ int ignore = true;
+
+ if (pinput->value == KEY_PRESSED) {
+ if (key_combination == KEY_COMBINATION_STOP) {
+ key_combination = KEY_COMBINATION_START;
+ combination_timeout_id = ecore_timer_add(
+ COMBINATION_INTERVAL,
+ (Ecore_Task_Cb)combination_failed_cb, NULL);
+ } else if (key_combination == KEY_COMBINATION_START) {
+ if (combination_timeout_id > 0) {
+ ecore_timer_del(combination_timeout_id);
+ combination_timeout_id = NULL;
+ }
+ LOGINFO("capture mode");
+ key_combination = KEY_COMBINATION_SCREENCAPTURE;
+ ignore = false;
+ }
+ } else if (pinput->value == KEY_RELEASED) {
+ if (key_combination != KEY_COMBINATION_SCREENCAPTURE) {
+ stop_key_combination();
+ if (current_state_in_on())
+ ignore = false;
+ }
+ }
+
+ return ignore;
+}
+
+static int check_key(struct input_event *pinput)
+{
+ int ignore = true;
+
+ switch (pinput->code) {
+ case KEY_POWER:
+ ignore = process_power_key(pinput);
+ break;
+ case KEY_VOLUMEDOWN:
+ ignore = process_volumedown_key(pinput);
+ break;
+ case KEY_VOLUMEUP:
+ case KEY_CAMERA:
+ case KEY_EXIT:
+ case KEY_PHONE:
+ case KEY_CONFIG:
+ case KEY_SEARCH:
+ case KEY_MEDIA:
+ stop_key_combination();
+ if (current_state_in_on())
+ ignore = false;
+ break;
+ case KEY_SCREENLOCK:
+ case 0x1DB:
+ case 0x1DC:
+ case 0x1DD:
+ case 0x1DE:
+ stop_key_combination();
+ break;
+ default:
+ stop_key_combination();
+ ignore = false;
+ }
+#ifdef ENABLE_PM_LOG
+ if (pinput->value == KEY_PRESSED)
+ pm_history_save(PM_LOG_KEY_PRESS, pinput->code);
+ else if (pinput->value == KEY_RELEASED)
+ pm_history_save(PM_LOG_KEY_RELEASE, pinput->code);
+#endif
+ return ignore;
+}
+
+int check_key_filter(int length, char buf[])
+{
+ struct input_event *pinput;
+ int ignore = true;
+ int idx = 0;
+
+ do {
+ pinput = (struct input_event *)&buf[idx];
+ switch (pinput->type) {
+ case EV_KEY:
+ ignore = check_key(pinput);
+ break;
+ case EV_REL:
+ ignore = false;
+ break;
+ case EV_ABS:
+ if (current_state_in_on())
+ ignore = false;
+ break;
+ }
+ idx += sizeof(struct input_event);
+ if (ignore == true && length <= idx)
+ return 1;
+ } while (length > idx);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "llinterface.h"
+#include "conf.h"
+#include "vconf.h"
+#include "core.h"
+#include "device-node.h"
+
+#define DISP_INDEX_BIT 4
+#define COMBINE_DISP_CMD(cmd, prop, index) (cmd = (prop | (index << DISP_INDEX_BIT)))
+
+typedef struct _PMSys PMSys;
+struct _PMSys {
+ int def_brt;
+ int dim_brt;
+
+ int (*sys_power_state) (PMSys *, int);
+ int (*sys_get_lcd_power) (PMSys *);
+ int (*bl_onoff) (PMSys *, int);
+ int (*bl_brt) (PMSys *, int);
+ int (*sys_get_battery_capacity) (PMSys *p);
+ int (*sys_get_battery_capacity_raw) (PMSys *p);
+ int (*sys_get_battery_charge_full) (PMSys *p);
+};
+
+static PMSys *pmsys;
+struct _backlight_ops backlight_ops;
+struct _power_ops power_ops;
+struct _battery_ops battery_ops;
+
+#ifdef ENABLE_X_LCD_ONOFF
+#include "x-lcd-on.c"
+static bool x_dpms_enable = false;
+#endif
+
+static int _bl_onoff(PMSys *p, int on)
+{
+ int cmd = 0;
+
+ COMBINE_DISP_CMD(cmd, PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY);
+ return device_set_property(DEVICE_TYPE_DISPLAY, cmd, on);
+}
+
+static int _bl_brt(PMSys *p, int brightness)
+{
+ int cmd;
+ int ret;
+ int old_brt;
+
+ COMBINE_DISP_CMD(cmd, PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
+ ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &old_brt);
+
+ /* Update new brightness to vconf */
+ if (!ret && (brightness != old_brt))
+ vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, brightness);
+
+ /* Update device brightness */
+ ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brightness);
+
+ LOGERR("set brightness %d, %d", brightness, ret);
+
+ return ret;
+}
+
+static int _sys_power_state(PMSys *p, int state)
+{
+ if (state < POWER_STATE_SUSPEND || state > POWER_STATE_POST_RESUME)
+ return 0;
+ return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_STATE, state);
+}
+
+static int _sys_get_lcd_power(PMSys *p)
+{
+ int value = -1;
+ int ret = -1;
+ int cmd = 0;
+
+ COMBINE_DISP_CMD(cmd, PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY);
+ ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &value);
+
+ if (ret < 0 || value < 0)
+ return -1;
+
+ return value;
+}
+
+static int _sys_get_battery_capacity(PMSys *p)
+{
+ int value = 0;
+ int ret = -1;
+
+ ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &value);
+
+ if(ret < 0)
+ return -1;
+
+ if(value < 0)
+ return 0;
+
+ return value;
+}
+
+static int _sys_get_battery_capacity_raw(PMSys *p)
+{
+ int value = 0;
+ int ret = -1;
+
+ ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY_RAW,
+ &value);
+
+ if(ret < 0)
+ return -1;
+
+ if(value < 0)
+ return 0;
+
+ return value;
+}
+
+static int _sys_get_battery_charge_full(PMSys *p)
+{
+ int value = 0;
+ int ret = -1;
+
+ ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL,
+ &value);
+
+ if(ret < 0)
+ return -1;
+
+ if(value < 0)
+ return 0;
+
+ return value;
+}
+
+static void _init_bldev(PMSys *p, unsigned int flags)
+{
+ int ret;
+ //_update_curbrt(p);
+ p->bl_brt = _bl_brt;
+ p->bl_onoff = _bl_onoff;
+#ifdef ENABLE_X_LCD_ONOFF
+ if (flags & FLAG_X_DPMS) {
+ p->bl_onoff = pm_x_set_lcd_backlight;
+ x_dpms_enable = true;
+ }
+#endif
+}
+
+static void _init_pmsys(PMSys *p)
+{
+ char tmp[NAME_MAX];
+
+ get_env(EN_SYS_DIMBRT, tmp, sizeof(tmp));
+
+ p->dim_brt = atoi(tmp);
+ p->sys_power_state = _sys_power_state;
+ p->sys_get_lcd_power = _sys_get_lcd_power;
+ p->sys_get_battery_capacity = _sys_get_battery_capacity;
+ p->sys_get_battery_capacity_raw = _sys_get_battery_capacity_raw;
+ p->sys_get_battery_charge_full = _sys_get_battery_charge_full;
+}
+
+static void *_system_suspend_cb(void *data)
+{
+ LOGINFO("enter system suspend");
+ if (pmsys && pmsys->sys_power_state)
+ return pmsys->sys_power_state(pmsys, POWER_STATE_SUSPEND);
+ return 0;
+}
+
+static int system_suspend(void)
+{
+ pthread_t pth;
+ int ret;
+
+ ret = pthread_create(&pth, 0, _system_suspend_cb, (void*)NULL);
+ if (ret < 0) {
+ LOGERR("pthread creation failed!, suspend directly!");
+ _system_suspend_cb((void*)NULL);
+ } else {
+ pthread_join(pth, NULL);
+ }
+
+ return 0;
+}
+
+static int system_pre_suspend(void)
+{
+ LOGINFO("enter system pre suspend");
+ if (pmsys && pmsys->sys_power_state)
+ return pmsys->sys_power_state(pmsys, POWER_STATE_PRE_SUSPEND);
+
+ return 0;
+}
+
+static int system_post_resume(void)
+{
+ LOGINFO("enter system post resume");
+ if (pmsys && pmsys->sys_power_state)
+ return pmsys->sys_power_state(pmsys, POWER_STATE_POST_RESUME);
+
+ return 0;
+}
+
+static int battery_capacity(void)
+{
+ if (pmsys && pmsys->sys_get_battery_capacity)
+ return pmsys->sys_get_battery_capacity(pmsys);
+
+ return 0;
+}
+
+static int battery_capacity_raw(void)
+{
+ if (pmsys && pmsys->sys_get_battery_capacity_raw)
+ return pmsys->sys_get_battery_capacity_raw(pmsys);
+
+ return 0;
+}
+
+static int battery_charge_full(void)
+{
+ if (pmsys && pmsys->sys_get_battery_charge_full)
+ return pmsys->sys_get_battery_charge_full(pmsys);
+
+ return 0;
+}
+
+static int get_lcd_power(void)
+{
+ if (pmsys && pmsys->sys_get_lcd_power) {
+ return pmsys->sys_get_lcd_power(pmsys);
+ }
+
+ return -1;
+}
+
+static int backlight_on(void)
+{
+ int ret = -1;
+ int i;
+
+ LOGINFO("LCD on");
+
+ if (!pmsys || !pmsys->bl_onoff)
+ return -1;
+
+ for (i = 0; i < PM_LCD_RETRY_CNT; i++) {
+ ret = pmsys->bl_onoff(pmsys, STATUS_ON);
+ if (get_lcd_power() == PM_LCD_POWER_ON) {
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_LCD_ON, pm_cur_state);
+#endif
+ break;
+ } else {
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_LCD_ON_FAIL, pm_cur_state);
+#endif
+#ifdef ENABLE_X_LCD_ONOFF
+ LOGERR("Failed to LCD on, through xset");
+#else
+ LOGERR("Failed to LCD on, through OAL");
+#endif
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+static int backlight_off(void)
+{
+ int ret = -1;
+ int i;
+
+ LOGINFO("LCD off");
+
+ if (!pmsys || !pmsys->bl_onoff)
+ return -1;
+
+ for (i = 0; i < PM_LCD_RETRY_CNT; i++) {
+#ifdef ENABLE_X_LCD_ONOFF
+ if (x_dpms_enable == false)
+#endif
+ usleep(30000);
+ ret = pmsys->bl_onoff(pmsys, STATUS_OFF);
+ if (get_lcd_power() == PM_LCD_POWER_OFF) {
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_LCD_OFF, pm_cur_state);
+#endif
+ break;
+ } else {
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_LCD_OFF_FAIL, pm_cur_state);
+#endif
+#ifdef ENABLE_X_LCD_ONOFF
+ LOGERR("Failed to LCD off, through xset");
+#else
+ LOGERR("Failed to LCD off, through OAL");
+#endif
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+static int backlight_dim(void)
+{
+ int ret = 0;
+ if (pmsys && pmsys->bl_brt) {
+ ret = pmsys->bl_brt(pmsys, pmsys->dim_brt);
+#ifdef ENABLE_PM_LOG
+ if (!ret)
+ pm_history_save(PM_LOG_LCD_DIM, pm_cur_state);
+ else
+ pm_history_save(PM_LOG_LCD_DIM_FAIL, pm_cur_state);
+#endif
+ }
+ return ret;
+}
+
+static int backlight_restore(void)
+{
+ int ret = 0;
+
+ if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) {
+ ret = backlight_dim();
+ } else if (pmsys && pmsys->bl_brt) {
+ ret = pmsys->bl_brt(pmsys, pmsys->def_brt);
+ }
+ return ret;
+}
+
+static int set_default_brt(int level)
+{
+ if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
+ level = PM_DEFAULT_BRIGHTNESS;
+ pmsys->def_brt = level;
+
+ return 0;
+}
+
+static int check_wakeup_src(void)
+{
+ /* TODO if nedded.
+ * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
+ */
+ return EVENT_DEVICE;
+}
+
+void _init_ops(void)
+{
+ backlight_ops.off = backlight_off;
+ backlight_ops.dim = backlight_dim;
+ backlight_ops.on = backlight_on;
+ backlight_ops.restore = backlight_restore;
+ backlight_ops.set_default_brt = set_default_brt;
+ backlight_ops.get_lcd_power = get_lcd_power;
+
+ power_ops.suspend = system_suspend;
+ power_ops.pre_suspend = system_pre_suspend;
+ power_ops.post_resume = system_post_resume;
+ power_ops.check_wakeup_src = check_wakeup_src;
+
+ battery_ops.get_capacity = battery_capacity;
+ battery_ops.get_capacity_raw = battery_capacity_raw;
+ battery_ops.get_charge_full = battery_charge_full;
+}
+
+int init_sysfs(unsigned int flags)
+{
+ int ret;
+
+ pmsys = (PMSys *) malloc(sizeof(PMSys));
+ if (pmsys == NULL) {
+ LOGERR("Not enough memory to alloc PM Sys");
+ return -1;
+ }
+
+ memset(pmsys, 0x0, sizeof(PMSys));
+
+ _init_pmsys(pmsys);
+ _init_bldev(pmsys, flags);
+
+ if (pmsys->bl_onoff == NULL || pmsys->sys_power_state == NULL) {
+ LOGERR
+ ("We have no managable resource to reduce the power consumption");
+ return -1;
+ }
+
+ _init_ops();
+
+ return 0;
+}
+
+int exit_sysfs(void)
+{
+ int fd;
+
+ fd = open("/tmp/sem.pixmap_1", O_RDONLY);
+ if (fd == -1) {
+ LOGERR("X server disable");
+ backlight_on();
+ }
+
+ backlight_restore();
+ free(pmsys);
+ pmsys = NULL;
+ if(fd != -1)
+ close(fd);
+
+ return 0;
+}
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file llinterface.h
+ * @brief Power manager low-level interface module header
+ */
+#ifndef __PM_LLINTERFACE_H__
+#define __PM_LLINTERFACE_H__
+
+#define FLAG_X_DPMS 0x2
+
+#define DEFAULT_DISPLAY 0
+
+#define PM_MAX_BRIGHTNESS 100
+#define PM_MIN_BRIGHTNESS 1
+#ifdef TIZEN_EMUL
+# define PM_DEFAULT_BRIGHTNESS 100
+#else
+# define PM_DEFAULT_BRIGHTNESS 60
+#endif
+
+#define PM_LCD_POWER_ON 0
+#define PM_LCD_POWER_OFF 4
+
+#define PM_LCD_RETRY_CNT 3
+
+/*
+ * Event type enumeration
+ */
+enum {
+ EVENT_TIMEOUT = 0, /*< time out event from timer */
+ EVENT_DEVICE = EVENT_TIMEOUT, /*< wake up by devices except input devices */
+ EVENT_INPUT, /*< input event from noti service */
+ EVENT_END,
+};
+
+extern int init_sysfs(unsigned int);
+extern int exit_sysfs(void);
+
+struct _backlight_ops {
+ int (*off)(void);
+ int (*dim)(void);
+ int (*on)(void);
+ int (*restore)(void);
+ int (*set_default_brt)(int level);
+ int (*get_lcd_power)(void);
+};
+
+struct _power_ops {
+ int (*suspend)(void);
+ int (*pre_suspend)(void);
+ int (*post_resume)(void);
+ int (*check_wakeup_src)(void);
+};
+
+struct _battery_ops {
+ int (*get_capacity)(void);
+ int (*get_capacity_raw)(void);
+ int (*get_charge_full)(void);
+};
+
+extern struct _backlight_ops backlight_ops;
+extern struct _power_ops power_ops;
+extern struct _battery_ops battery_ops;
+
+#endif
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <vconf.h>
+#include <sensor.h>
+#include <Ecore.h>
+
+#include "core.h"
+#include "device-node.h"
+
+#define SAMPLING_INTERVAL 1 /* 1 sec */
+#define MAX_FAULT 5
+
+#define DISP_INDEX_BIT 4
+#define COMBINE_DISP_CMD(cmd, prop, index) (cmd = (prop | (index << DISP_INDEX_BIT)))
+
+static int (*prev_init_extention) (void *data);
+static int (*_default_action) (int);
+static Ecore_Timer *alc_timeout_id = 0;
+static int sf_handle = -1;
+static int fault_count = 0;
+static int power_saving_display_stat = 0;
+
+static bool alc_handler(void* data)
+{
+ int value = 0;
+ static int cur_index = 1;
+ static int old_index = 1;
+
+ sensor_data_t light_data;
+ if (pm_cur_state != S_NORMAL){
+ if (alc_timeout_id > 0)
+ ecore_timer_del(alc_timeout_id);
+ alc_timeout_id = NULL;
+ } else {
+ if (sf_get_data(sf_handle, LIGHT_BASE_DATA_SET, &light_data) < 0) {
+ fault_count++;
+ } else {
+ if (light_data.values[0] < 0.0 || light_data.values[0] > 10.0) {
+ LOGINFO("fail to load light data : %d", (int)light_data.values[0]);
+ fault_count++;
+ } else {
+ int tmp_value;
+ int cmd;
+ int ret;
+ value = PM_MAX_BRIGHTNESS * (int)light_data.values[0] / 10;
+ COMBINE_DISP_CMD(cmd, PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
+ ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &tmp_value);
+ if (!ret && (tmp_value != value)) {
+ backlight_ops.set_default_brt(value);
+ backlight_ops.restore();
+ }
+ LOGINFO("load light data : %d, brightness : %d", (int)light_data.values[0], value);
+ }
+ }
+ }
+
+ if (fault_count > MAX_FAULT) {
+ if (alc_timeout_id > 0)
+ ecore_timer_del(alc_timeout_id);
+ alc_timeout_id = NULL;
+ vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ SETTING_BRIGHTNESS_AUTOMATIC_OFF);
+ LOGERR("Fault counts is over %d, disable automatic brightness",
+ MAX_FAULT);
+ return EINA_FALSE;
+ }
+
+ if (alc_timeout_id != 0)
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+static int alc_action(int timeout)
+{
+ LOGINFO("alc action");
+ /* sampling timer add */
+ if (alc_timeout_id == 0 && !(pm_status_flag & PWRSV_FLAG))
+ alc_timeout_id =
+ ecore_timer_add(SAMPLING_INTERVAL,
+ (Ecore_Task_Cb)alc_handler, NULL);
+
+ if (_default_action != NULL)
+ return _default_action(timeout);
+
+ /* unreachable code */
+ return -1;
+}
+
+static int connect_sfsvc(void)
+{
+ int sf_state = -1;
+ /* connect with sensor fw */
+ LOGINFO("connect with sensor fw");
+ sf_handle = sf_connect(LIGHT_SENSOR);
+ if (sf_handle < 0) {
+ LOGERR("sensor attach fail");
+ return -1;
+ }
+ sf_state = sf_start(sf_handle, 0);
+ if (sf_state < 0) {
+ LOGERR("sensor attach fail");
+ sf_disconnect(sf_handle);
+ sf_handle = -1;
+ return -2;
+ }
+ fault_count = 0;
+ return 0;
+}
+
+static int disconnect_sfsvc(void)
+{
+ LOGINFO("disconnect with sensor fw");
+ if(sf_handle >= 0)
+ {
+ sf_stop(sf_handle);
+ sf_disconnect(sf_handle);
+ sf_handle = -1;
+ }
+
+ if (_default_action != NULL) {
+ states[S_NORMAL].action = _default_action;
+ _default_action = NULL;
+ }
+ if (alc_timeout_id > 0) {
+ ecore_timer_del(alc_timeout_id);
+ alc_timeout_id = NULL;
+ }
+
+ return 0;
+}
+
+static inline void set_brtch_state(void)
+{
+ if (pm_status_flag & PWRSV_FLAG) {
+ pm_status_flag |= BRTCH_FLAG;
+ LOGINFO("brightness changed in low battery,"
+ "escape dim state (light)");
+ }
+}
+
+static int set_alc_function(keynode_t *key_nodes, void *data)
+{
+ int onoff = 0;
+ int ret = -1;
+ int brt = -1;
+ int default_brt = -1;
+ int max_brt = -1;
+
+ if (key_nodes == NULL) {
+ LOGERR("wrong parameter, key_nodes is null");
+ return -1;
+ }
+
+ onoff = vconf_keynode_get_int(key_nodes);
+
+ if (onoff == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
+ if(connect_sfsvc() < 0)
+ return -1;
+ /* escape dim state if it's in low battery.*/
+ set_brtch_state();
+
+ /* change alc action func */
+ if (_default_action == NULL)
+ _default_action = states[S_NORMAL].action;
+ states[S_NORMAL].action = alc_action;
+ alc_timeout_id =
+ ecore_timer_add(SAMPLING_INTERVAL,
+ (Ecore_Task_Cb)alc_handler, NULL);
+ } else if (onoff == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) {
+ LOGINFO("auto brightness paused!");
+ disconnect_sfsvc();
+ } else {
+ disconnect_sfsvc();
+ /* escape dim state if it's in low battery.*/
+ set_brtch_state();
+
+ ret = get_setting_brightness(&default_brt);
+ if (ret != 0 || (default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)) {
+ LOGINFO("fail to read vconf value for brightness");
+ brt = PM_DEFAULT_BRIGHTNESS;
+ if(default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)
+ vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
+ default_brt = brt;
+ }
+
+ backlight_ops.set_default_brt(default_brt);
+ backlight_ops.restore();
+ }
+
+ return 0;
+}
+
+static bool check_sfsvc(void* data)
+{
+ /* this function will return opposite value for re-callback in fail */
+ int vconf_auto;
+ int sf_state = 0;
+
+ LOGINFO("register sfsvc");
+
+ vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &vconf_auto);
+ if (vconf_auto == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
+ if(connect_sfsvc() < 0)
+ return EINA_TRUE;
+
+ /* change alc action func */
+ if (_default_action == NULL)
+ _default_action = states[S_NORMAL].action;
+ states[S_NORMAL].action = alc_action;
+ alc_timeout_id =
+ ecore_timer_add(SAMPLING_INTERVAL,
+ (Ecore_Task_Cb)alc_handler, NULL);
+ if (alc_timeout_id > 0)
+ return EINA_FALSE;
+ disconnect_sfsvc();
+ return EINA_TRUE;
+ }
+ LOGINFO("change vconf value before registering sfsvc");
+ return EINA_FALSE;
+}
+
+static int prepare_lsensor(void *data)
+{
+ int alc_conf;
+ int sf_state = 0;
+
+ vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &alc_conf);
+
+ if (alc_conf == SETTING_BRIGHTNESS_AUTOMATIC_ON)
+ ecore_timer_add(SAMPLING_INTERVAL, (Ecore_Task_Cb)check_sfsvc, NULL);
+
+ /* add auto_brt_setting change handler */
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ (void *)set_alc_function, NULL);
+
+ if (prev_init_extention != NULL)
+ return prev_init_extention(data);
+
+ return 0;
+}
+
+void set_power_saving_display_stat(int stat)
+{
+ LOGINFO("stat = %d", stat);
+ power_saving_display_stat = stat;
+}
+
+static void __attribute__ ((constructor)) pm_lsensor_init(void)
+{
+ _default_action = NULL;
+ if (pm_init_extention != NULL)
+ prev_init_extention = pm_init_extention;
+ pm_init_extention = prepare_lsensor;
+}
+
+static void __attribute__ ((destructor)) pm_lsensor_fini(void)
+{
+
+}
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file poll.c
+ * @brief Power Manager poll implementation (input devices & a domain socket file)
+ *
+ * This file includes the input device poll implementation.
+ * Default input devices are /dev/event0 and /dev/event1
+ * User can use "PM_INPUT" for setting another input device poll in an environment file (/etc/profile).
+ * (ex: PM_INPUT=/dev/event0:/dev/event1:/dev/event5 )
+ */
+
+#include <stdio.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <Ecore.h>
+
+#include "core.h"
+#include "poll.h"
+
+#define DEV_PATH_DLM ":"
+
+PMMsg recv_data;
+int (*g_pm_callback) (int, PMMsg *);
+
+#ifdef ENABLE_KEY_FILTER
+extern int check_key_filter(int length, char buf[]);
+# define CHECK_KEY_FILTER(a, b) do {\
+ if (check_key_filter(a, b) != 0)\
+ return EINA_TRUE;\
+ } while (0);
+
+#else
+# define CHECK_KEY_FILTER(a, b)
+#endif
+
+#define DEFAULT_DEV_PATH "/dev/event1:/dev/event0"
+
+static int sockfd;
+
+static Eina_Bool pm_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ char buf[1024];
+ struct sockaddr_un clientaddr;
+
+ int *fd = (int *)data;
+ int ret;
+ int clilen = sizeof(clientaddr);
+
+ if (g_pm_callback == NULL) {
+ return EINA_FALSE;
+ }
+ if (fd == sockfd) {
+ ret =
+ recvfrom(fd, &recv_data, sizeof(recv_data), 0,
+ (struct sockaddr *)&clientaddr,
+ (socklen_t *)&clilen);
+ (*g_pm_callback) (PM_CONTROL_EVENT, &recv_data);
+ } else {
+ ret = read(fd, buf, sizeof(buf));
+ CHECK_KEY_FILTER(ret, buf);
+ (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
+ }
+
+ return EINA_TRUE;
+}
+
+static int init_sock(char *sock_path)
+{
+ struct sockaddr_un serveraddr;
+ int fd;
+
+ LOGINFO("initialize pm_socket for pm_control library");
+
+ if (sock_path == NULL || strcmp(sock_path, SOCK_PATH)) {
+ LOGERR("invalid sock_path= %s");
+ return -1;
+ }
+
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ LOGERR("socket error");
+ return -1;
+ }
+
+ unlink(sock_path);
+
+ bzero(&serveraddr, sizeof(serveraddr));
+ serveraddr.sun_family = AF_UNIX;
+ strncpy(serveraddr.sun_path, sock_path, sizeof(serveraddr.sun_path) - 1);
+
+ if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
+ LOGERR("bind error");
+ close(fd);
+ return -1;
+ }
+
+ if (chmod(sock_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) /* 0777 */
+ LOGERR("failed to change the socket permission");
+
+ if (!strcmp(sock_path, SOCK_PATH))
+ sockfd = fd;
+
+ LOGINFO("init sock() sueccess!");
+ return fd;
+}
+
+int init_pm_poll(int (*pm_callback) (int, PMMsg *))
+{
+ char *dev_paths, *path_tok, *pm_input_env, *save_ptr;
+ int dev_paths_size;
+
+ Ecore_Fd_Handler *fd_handler;
+ int fd = -1;
+
+ g_pm_callback = pm_callback;
+
+ LOGINFO
+ ("initialize pm poll - input devices and domain socket(libpmapi)");
+
+ pm_input_env = getenv("PM_INPUT");
+ if ((pm_input_env != NULL) && (strlen(pm_input_env) < 1024)) {
+ LOGINFO("Getting input device path from environment: %s",
+ pm_input_env);
+ /* Add 2 bytes for following strncat() */
+ dev_paths_size = strlen(pm_input_env) + strlen(SOCK_PATH) + strlen(DEV_PATH_DLM) + 1;
+ dev_paths = (char *)malloc(dev_paths_size);
+ snprintf(dev_paths, dev_paths_size, "%s", pm_input_env);
+ } else {
+ /* Add 2 bytes for following strncat() */
+ dev_paths_size = strlen(DEFAULT_DEV_PATH) + strlen(SOCK_PATH) + strlen(DEV_PATH_DLM) + 1;
+ dev_paths = (char *)malloc(dev_paths_size);
+ snprintf(dev_paths, dev_paths_size, "%s", DEFAULT_DEV_PATH);
+ }
+
+ /* add the UNIX domain socket file path */
+ strncat(dev_paths, DEV_PATH_DLM, strlen(DEV_PATH_DLM));
+ strncat(dev_paths, SOCK_PATH, strlen(SOCK_PATH));
+ dev_paths[dev_paths_size - 1] = '\0';
+
+ path_tok = strtok_r(dev_paths, DEV_PATH_DLM, &save_ptr);
+ if (path_tok == NULL) {
+ LOGERR("Device Path Tokeninzing Failed");
+ free(dev_paths);
+ return -1;
+ }
+
+ do {
+ if (strcmp(path_tok, SOCK_PATH) == 0) {
+ fd = init_sock(SOCK_PATH);
+ LOGINFO("pm_poll domain socket file: %s, fd: %d",
+ path_tok, fd);
+ } else {
+ fd = open(path_tok, O_RDONLY);
+ LOGINFO("pm_poll input device file: %s, fd: %d",
+ path_tok, fd);
+ }
+
+ if (fd == -1) {
+ LOGERR("Cannot open the file: %s", path_tok);
+ free(dev_paths);
+ return -1;
+ }
+
+ fd_handler = ecore_main_fd_handler_add(fd,
+ ECORE_FD_READ|ECORE_FD_ERROR,
+ pm_handler, fd, NULL, NULL);
+ if (fd_handler == NULL) {
+ LOGERR("Failed ecore_main_handler_add() in init_pm_poll()");
+ free(dev_paths);
+ return -1;
+ }
+
+ } while ((path_tok = strtok_r(NULL, DEV_PATH_DLM, &save_ptr)));
+
+ free(dev_paths);
+ return 0;
+}
+
+int exit_pm_poll(void)
+{
+ close(sockfd);
+ unlink(SOCK_PATH);
+ LOGINFO("pm_poll is finished");
+ return 0;
+}
+
+int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path)
+{
+ indev *new_dev = NULL;
+ indev *data = NULL;
+ Ecore_Fd_Handler *fd_handler = NULL;
+ Eina_List *l = NULL;
+ Eina_List *l_next = NULL;
+ int fd = -1;
+ char *dev_path = NULL;
+
+ if (!pm_callback || !path) {
+ LOGERR("argument is NULL! (%x,%x)", pm_callback, path);
+ return -1;
+ }
+
+ EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data)
+ if(!strcmp(path, data->dev_path)) {
+ LOGERR("%s is already polled!", path);
+ return -1;
+ }
+
+ LOGINFO("initialize pm poll for bt %s", path);
+
+ g_pm_callback = pm_callback;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ LOGERR("Cannot open the file for BT: %s", path);
+ return -1;
+ }
+
+ dev_path = (char*)malloc(strlen(path) + 1);
+ if (!dev_path) {
+ LOGERR("Fail to malloc for dev_path");
+ close(fd);
+ return -1;
+ }
+ strncpy(dev_path, path, strlen(path) +1);
+
+ fd_handler = ecore_main_fd_handler_add(fd,
+ ECORE_FD_READ|ECORE_FD_ERROR,
+ pm_handler, fd, NULL, NULL);
+ if (!fd_handler) {
+ LOGERR("Fail to ecore fd handler add! %s", path);
+ close(fd);
+ free(dev_path);
+ return -1;
+ }
+
+ new_dev = (indev *)malloc(sizeof(indev));
+ if (!new_dev) {
+ LOGERR("Fail to malloc for new_dev %s", path);
+ ecore_main_fd_handler_del(fd_handler);
+ close(fd);
+ free(dev_path);
+ return -1;
+ }
+ new_dev->dev_path = dev_path;
+ new_dev->fd = fd;
+ new_dev->dev_fd = fd_handler;
+
+ LOGINFO("pm_poll for BT input device file(path: %s, fd: %d",
+ new_dev->dev_path, new_dev->fd);
+ indev_list = eina_list_append(indev_list, new_dev);
+
+ return 0;
+}
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file poll.h
+ * @brief Power Manager input device poll implementation
+ *
+ * This file includes the input device poll implementation.
+ * Default input devices are /dev/event0 and /dev/event1
+ * User can use "PM_INPUT_DEV" for setting another input device poll in an environment file (/etc/profile).
+ * (ex: PM_INPUT_DEV=/dev/event0:/dev/event1:/dev/event5 )
+ */
+
+#ifndef __PM_POLL_H__
+#define __PM_POLL_H__
+
+#include <Ecore.h>
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+enum {
+ INPUT_POLL_EVENT = -9,
+ SIDEKEY_POLL_EVENT,
+ PWRKEY_POLL_EVENT,
+ PM_CONTROL_EVENT,
+};
+
+#define SOCK_PATH "/tmp/pm_sock"
+
+typedef struct {
+ pid_t pid;
+ unsigned int cond;
+ unsigned int timeout;
+ unsigned int timeout2;
+} PMMsg;
+
+typedef struct {
+ char *dev_path;
+ int fd;
+ Ecore_Fd_Handler *dev_fd;
+} indev;
+
+Eina_List *indev_list;
+
+PMMsg recv_data;
+int (*g_pm_callback) (int, PMMsg *);
+
+extern int init_pm_poll(int (*pm_callback) (int, PMMsg *));
+extern int exit_pm_poll();
+extern int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path);
+
+/**
+ * @}
+ */
+
+#endif /*__PM_POLL_H__ */
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "display/util.h"
+#include "setting.h"
+#include "conf.h"
+
+static const char *setting_keys[SETTING_GET_END] = {
+ [SETTING_TO_NORMAL] = VCONFKEY_SETAPPL_LCD_TIMEOUT_NORMAL,
+ [SETTING_BRT_LEVEL] = VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+ [SETTING_LOCK_SCREEN] = VCONFKEY_IDLE_LOCK_STATE,
+ [SETTING_POWER_SAVING] = VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS,
+ [SETTING_POWER_SAVING_DISPLAY] = VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY,
+};
+
+static int lock_screen_state = VCONFKEY_IDLE_UNLOCK;
+
+int (*update_pm_setting) (int key_idx, int val);
+
+int get_lock_screen_state(void)
+{
+ return lock_screen_state;
+}
+
+void set_lock_screen_state(int state)
+{
+ switch (state) {
+ case VCONFKEY_IDLE_LOCK:
+ case VCONFKEY_IDLE_UNLOCK:
+ lock_screen_state = state;
+ break;
+ default:
+ lock_screen_state = VCONFKEY_IDLE_UNLOCK;
+ }
+}
+
+int get_charging_status(int *val)
+{
+ return vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, val);
+}
+
+int get_lowbatt_status(int *val)
+{
+ return vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, val);
+}
+
+int get_usb_status(int *val)
+{
+ return vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, val);
+}
+
+int set_setting_pmstate(int val)
+{
+ return vconf_set_int(VCONFKEY_PM_STATE, val);
+}
+
+int get_setting_brightness(int *level)
+{
+ return vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, level);
+}
+
+int get_run_timeout(int *timeout)
+{
+ int dim_timeout = -1, vconf_timeout = -1, ret;
+ get_dim_timeout(&dim_timeout);
+
+ if(dim_timeout < 0) {
+ LOGERR("Can not get dim timeout. set default 5 seconds");
+ dim_timeout = 5;
+ }
+
+ ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout);
+
+ if(vconf_timeout == 0)
+ *timeout = 0; //timeout 0 : Always ON (Do not apply dim_timeout)
+ else
+ *timeout = vconf_timeout - dim_timeout;
+ return ret;
+
+}
+
+int get_dim_timeout(int *timeout)
+{
+ char buf[255];
+ /* TODO if needed */
+ *timeout = 5; /* default timeout */
+ get_env("PM_TO_LCDDIM", buf, sizeof(buf));
+ LOGINFO("Get lcddim timeout [%s]", buf);
+ *timeout = atoi(buf);
+ return 0;
+}
+
+int get_off_timeout(int *timeout)
+{
+ char buf[255];
+ /* TODO if needed */
+ *timeout = 5; /* default timeout */
+ get_env("PM_TO_LCDOFF", buf, sizeof(buf));
+ LOGINFO("Get lcdoff timeout [%s]", buf);
+ *timeout = atoi(buf);
+ return 0;
+}
+
+static int setting_cb(keynode_t *key_nodes, void *data)
+{
+ keynode_t *tmp = key_nodes;
+
+ if ((int)data > SETTING_END) {
+ LOGERR("Unknown setting key: %s, idx=%d",
+ vconf_keynode_get_name(tmp), (int)data);
+ return -1;
+ }
+ if (update_pm_setting != NULL) {
+ switch((int)data) {
+ case SETTING_POWER_SAVING:
+ case SETTING_POWER_SAVING_DISPLAY:
+ update_pm_setting((int)data, vconf_keynode_get_bool(tmp));
+ break;
+ default:
+ update_pm_setting((int)data, vconf_keynode_get_int(tmp));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int init_setting(int (*func) (int key_idx, int val))
+{
+ int i;
+
+ if (func != NULL)
+ update_pm_setting = func;
+
+ for (i = SETTING_BEGIN; i < SETTING_GET_END; i++) {
+ vconf_notify_key_changed(setting_keys[i], (void *)setting_cb,
+ (void *)i);
+ }
+
+ return 0;
+}
+
+int exit_setting(void)
+{
+ int i;
+ for (i = SETTING_BEGIN; i < SETTING_GET_END; i++) {
+ vconf_ignore_key_changed(setting_keys[i], (void *)setting_cb);
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/*
+ * @file setting.h
+ * @brief Power manager setting module header
+ */
+#ifndef __PM_SETTING_H__
+#define __PM_SETTING_H__
+
+#include <vconf.h>
+
+/*
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+enum {
+ SETTING_BEGIN = 0,
+ SETTING_TO_NORMAL = SETTING_BEGIN,
+ SETTING_BRT_LEVEL,
+ SETTING_LOCK_SCREEN,
+ SETTING_POWER_SAVING,
+ SETTING_POWER_SAVING_DISPLAY,
+ SETTING_GET_END,
+ SETTING_PM_STATE = SETTING_GET_END,
+ SETTING_LOW_BATT,
+ SETTING_CHARGING,
+ SETTING_END
+};
+
+extern int (*update_pm_setting) (int key_idx, int val);
+
+extern int get_setting_brightness();
+
+/*
+ * @brief setting initialization function
+ *
+ * get the variables if it exists. otherwise, set the default.
+ * and register some callback functions.
+ *
+ * @internal
+ * @param[in] func configuration change callback function
+ * @return 0 : success, -1 : error
+ */
+extern int init_setting(int (*func) (int key_idx, int val));
+
+extern int exit_setting();
+
+/*
+ * get normal state timeout from SLP-setting SLP_SETTING_LCD_TIMEOUT_NORMAL
+ *
+ * @internal
+ * @param[out] timeout timeout variable pointer
+ * @return 0 : success, -1 : error
+ */
+extern int get_run_timeout(int *timeout);
+
+/*
+ * get LCD dim state timeout from environment variable.
+ *
+ * @internal
+ * @param[out] timeout timeout variable pointer
+ * @return 0 : success, -1 : error
+ */
+extern int get_dim_timeout(int *timeout);
+
+/*
+ * get LCD off state timeout from environment variable.
+ *
+ * @internal
+ * @param[out] timeout timeout variable pointer
+ * @return 0 : success, -1 : error
+ */
+extern int get_off_timeout(int *timeout);
+
+/*
+ * get USB connection status from SLP-setting SLP_SETTING_USB_STATUS
+ *
+ * @internal
+ * @param[out] val usb connection status variable pointer, 0 is disconnected, others is connected.
+ * @return 0 : success, -1 : error
+ */
+extern int get_usb_status(int *val);
+
+/*
+ * set Current power manager state at SLP-setting "memory/pwrmgr/state"
+ *
+ * @internal
+ * @param[in] val current power manager state.
+ * @return 0 : success, -1 : error
+ */
+extern int set_setting_pmstate(int val);
+
+/*
+ * get charging status at SLP-setting "memory/Battery/Charger"
+ *
+ * @internal
+ * @param[in] val charging or not (1 or 0 respectively).
+ * @return 0 : success, -1 : error
+ */
+extern int get_charging_status(int *val);
+
+/*
+ * get current battery low status at SLP-setting "memory/Battery/Status/Low"
+ *
+ * @internal
+ * @param[in] val current low battery status
+ * @return 0 : success, -1 : error
+ */
+extern int get_lowbatt_status(int *val);
+
+/*
+ * @}
+ */
+
+#endif
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @file util.c
+ * @brief Utilities for Power manager
+ *
+ * This file includes logging, daemonize
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include "util.h"
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+/**
+ * @brief logging function
+ *
+ * This is log wrapper
+ *
+ * @param[in] priority log pritority
+ * @param[in] fmt format string
+ */
+void pm_log(int priority, char *fmt, ...)
+{
+ va_list ap;
+ char buf[NAME_MAX]; /* NAME_MAX is 255 */
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ syslog(priority, "%s", buf);
+ printf("\x1b[1;33;44m[PowerManager] %s\x1b[0m\n\n", buf);
+}
+
+/**
+ * @brief write the pid
+ *
+ * get a pid and write it to pidpath
+ *
+ * @param[in] pidpath pid file path
+ * @return 0 (always)
+ */
+int writepid(char *pidpath)
+{
+ FILE *fp;
+
+ fp = fopen(pidpath, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d", getpid());
+ fclose(fp);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief read the pid
+ *
+ * get a pid and write it to pidpath
+ *
+ * @param[in] pidpath pid file path
+ * @return pid : success, -1 : failed
+ */
+int readpid(char *pidpath)
+{
+ FILE *fp;
+ int ret = -1;
+
+ fp = fopen(pidpath, "r");
+ if (fp != NULL) {
+ if (fscanf(fp, "%5d", &ret) == EOF)
+ LOGERR("readpid fscanf failed!");
+ fclose(fp);
+ }
+
+ return ret;
+}
+
+/**
+ * @brief daemonize function
+ *
+ * fork the process, kill the parent process
+ * and replace all the standard fds to /dev/null.
+ *
+ * @return 0 : success, -1 : fork() error
+ */
+int daemonize(void)
+{
+ pid_t pid;
+ int fd;
+
+ pid = fork();
+ if (pid < 0)
+ return -1;
+ else if (pid != 0)
+ exit(0);
+
+ setsid();
+ if (chdir("/") == -1) {
+ LOGERR("Failed to chdir");
+ }
+
+ close(0);
+ close(1);
+ close(2);
+
+ fd = open("/dev/null", O_RDONLY);
+ if (fd == -1) {
+ LOGERR("daemonize open failed [/dev/null RD]");
+ }
+ fd = open("/dev/null", O_RDWR);
+ if (fd == -1) {
+ LOGERR("daemonize open failed [/dev/null RDWR]");
+ }
+ dup(1);
+
+ return 0;
+}
+
+/**
+ * @brief function to run a process
+ *
+ * fork the process, and run the other process if it is child.
+ *
+ * @return new process pid on success, -1 on error
+ */
+
+int exec_process(char *name)
+{
+ int ret, pid;
+ int i;
+
+ if (name[0] == '\0')
+ return 0;
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ LOGERR("Fork error");
+ ret = -1;
+ break;
+ case 0:
+ for (i = 0; i < _NSIG; i++)
+ signal(i, SIG_DFL);
+ execlp(name, name, NULL);
+ LOGERR("execlp() error : %s\n", strerror(errno));
+ exit(-1);
+ break;
+ default:
+ ret = pid;
+ break;
+ }
+ return ret;
+}
+
+char *get_pkgname(char *exepath)
+{
+ char *filename;
+ char pkgname[NAME_MAX];
+
+ filename = strrchr(exepath, '/');
+ if (filename == NULL)
+ filename = exepath;
+ else
+ filename = filename + 1;
+
+ snprintf(pkgname, NAME_MAX, "deb.com.samsung.%s", filename);
+
+ return strdup(pkgname);
+}
+
+/**
+ * @}
+ */
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * @file util.h
+ * @brief Utilities header for Power manager
+ */
+#ifndef __DEF_UTIL_H__
+#define __DEF_UTIL_H__
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+#ifdef ENABLE_DLOG_OUT
+#define LOG_TAG "POWER_MANAGER"
+#endif
+
+#define SEC_TO_MSEC(x) ((x)*1000)
+#define MSEC_TO_SEC(x) (double(x)/1000)
+/*
+ * @brief write the pid
+ *
+ * get a pid and write it to pidpath
+ *
+ * @param[in] pidpath pid file path
+ * @return 0 (always)
+ */
+extern int writepid(char *pidpath);
+
+/*
+ * @brief read the pid
+ *
+ * get a pid and write it to pidpath
+ *
+ * @param[in] pidpath pid file path
+ * @return pid : success, -1 : failed
+ */
+extern int readpid(char *pidpath);
+
+/*
+ * @brief daemonize function
+ *
+ * fork the process, kill the parent process
+ * and replace all the standard fds to /dev/null.
+ *
+ * @return 0 : success, -1 : fork() error
+ */
+extern int daemonize(void);
+
+/**
+ * @brief function to run a process
+ *
+ * fork the process, and run the other process if it is child.
+ *
+ * @return new process pid on success, -1 on error
+ */
+extern int exec_process(char *name);
+
+/**
+ * @brief function to get the pkg name for AUL (Application Util Library)
+ *
+ * remove the path of exepath and make the "com.samsung.<exe_file_name>" string.
+ *
+ * @return new process pid on success, -1 on error
+ */
+extern char *get_pkgname(char *exepath);
+
+/*
+ * @brief logging function
+ *
+ * This is log wrapper
+ *
+ * @param[in] priority log pritority
+ * @param[in] fmt format string
+ */
+extern void pm_log(int priority, char *fmt, ...);
+
+#if defined(ENABLE_DLOG_OUT)
+# include <dlog.h>
+# define LOGINFO LOGI
+# define LOGERR LOGE
+#else
+# include <syslog.h>
+# define LOGINFO(fmt, arg...) pm_log(LOG_INFO, fmt, ## arg)
+# define LOGERR(fmt, arg...) pm_log(LOG_ERR, fmt, ## arg)
+#endif
+
+/**
+ * @}
+ */
+#endif
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#ifndef __PM_X_LCD_ONOFF_C__
+#define __PM_X_LCD_ONOFF_C__
+
+#include <string.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#define CMD_ON "on"
+#define CMD_OFF "off"
+
+static int pm_x_set_lcd_backlight(struct _PMSys *p, int on)
+{
+ pid_t pid;
+ char cmd_line[4];
+ int ret;
+
+ LOGINFO("Backlight on=%d", on);
+ if (on == STATUS_ON)
+ snprintf(cmd_line, sizeof(cmd_line), "%s", CMD_ON);
+ else
+ snprintf(cmd_line, sizeof(cmd_line), "%s", CMD_OFF);
+
+ signal(SIGCHLD, SIG_DFL);
+ pid = vfork();
+
+ if (pid < 0) {
+ LOGERR("[1] Failed to fork child process for LCD On/Off");
+ return -1;
+ }
+
+ if (pid == 0) {
+ LOGERR("[1] Child proccess for LCD %s was created (%s)",
+ ((on == STATUS_ON) ? "ON" : "OFF"), cmd_line);
+ execl("/usr/bin/xset", "/usr/bin/xset", "dpms", "force",
+ cmd_line, NULL);
+ _exit(0);
+ } else if (pid != (ret = waitpid(pid, NULL, 0))) {
+ LOGERR
+ ("[1] Waiting failed for the child process pid: %d, ret: %d, errno: %d",
+ pid, ret, errno);
+ }
+
+ signal(SIGCHLD, SIG_IGN);
+ return 0;
+}
+
+#endif /*__PM_X_LCD_ONOFF_C__ */
Name: system-server
Summary: System server
Version: 0.1.65
-Release: 6
-Group: Framework/system
-License: Apache License, Version 2.0
+Release: 7
+Group: System/Service
+License: Apache-2.0
Source0: system-server-%{version}.tar.gz
Source2: system-server.manifest
Source3: deviced.manifest
BuildRequires: pkgconfig(device-node)
BuildRequires: pkgconfig(libsmack)
BuildRequires: gettext
+BuildRequires: pkgconfig(sensor)
BuildRequires: pkgconfig(libsystemd-daemon)
%{?systemd_requires}
Requires(preun): /usr/bin/systemctl
ln -s ../system-server.service %{buildroot}%{_unitdir}/sockets.target.wants/system-server.socket
%post
-
+#memory type vconf key init
vconftool set -t int memory/sysman/usbhost_status -1 -i
vconftool set -t int memory/sysman/mmc 0 -i
vconftool set -t int memory/sysman/earjack_key 0 -i
#db type vconf key init
vconftool set -t int db/sysman/mmc_dev_changed 0 -i
+vconftool set -t int memory/pm/state 0 -i -g 5000
+vconftool set -t int memory/pm/battery_timetofull -1 -i
+vconftool set -t int memory/pm/battery_timetoempty -1 -i
+vconftool set -t int memory/pm/sip_status 0 -i -g 5000
+vconftool set -t int memory/pm/custom_brightness_status 0 -i -g 5000
+vconftool set -t bool memory/pm/brt_changed_lpm 0 -i
+vconftool set -t int memory/pm/current_brt 60 -i -g 5000
+
+heynotitool set system_wakeup
+heynotitool set pm_event
+
heynotitool set power_off_start
heynotitool set mmcblk_add
if [ $1 == 1 ]; then
systemctl restart system-server.service
fi
+/sbin/ldconfig
%preun
if [ $1 == 0 ]; then
%postun
systemctl daemon-reload
-
+/sbin/ldconfig
%files
%manifest %{name}.manifest
%endif
%{_bindir}/movi_format.sh
%{_bindir}/sys_event
+%{_bindir}/pm_event
%{_bindir}/sys_pci_noti
%{_bindir}/mmc-smack-label
+%{_bindir}/device-daemon
%{_unitdir}/multi-user.target.wants/system-server.service
%{_unitdir}/sockets.target.wants/system-server.socket
%{_unitdir}/system-server.service
%{_unitdir}/system-server.socket
%{_datadir}/system-server/udev-rules/91-system-server.rules
%{_datadir}/system-server/sys_pci_noti/res/locale/*/LC_MESSAGES/*.mo
+%config %{_sysconfdir}/dbus-1/system.d/system-server.conf
%files -n libdeviced
%defattr(-,root,root,-)
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(pm_event C)
+
+SET(SRCS pm_event.c)
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+SET(VERSION 0.1.9)
+INCLUDE(FindPkgConfig)
+FOREACH(flag ${deep_pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${deep_pkgs_LDFLAGS})
+
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"")
+ADD_DEFINITIONS("-DDATAFS=\"$ENV{DATADIR}\"")
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+
--- /dev/null
+/*
+ * power-manager
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#define PM_EVENT_NOTI_PATH "/opt/share/noti/pm_event"
+#define PM_EVENT_CMD_LENGTH 50
+
+int main(int argc, char *argv[])
+{
+ if(argc != 3) {
+ return -1;
+ }
+
+ if(strlen(argv[1]) + strlen(argv[2]) > PATH_MAX) {
+ return -1;
+ }
+
+ int i;
+ char buf[PATH_MAX + PM_EVENT_CMD_LENGTH];
+ snprintf(buf, (PATH_MAX + PM_EVENT_CMD_LENGTH), "echo %s %s >> %s",
+ argv[1], argv[2], PM_EVENT_NOTI_PATH);
+ system(buf);
+
+ return 1;
+}
#include <sysman.h>
#include <fcntl.h>
#include <device-node.h>
-
#include "core/log.h"
#include "core/launch.h"
#include "core/noti.h"
#include "core/queue.h"
#include "core/data.h"
+#include "display/setting.h"
#define BAT_MON_INTERVAL 30
#define BAT_MON_INTERVAL_MIN 2
_E("fail to set charge vconf value");
return -1;
}
+ if (update_pm_setting)
+ update_pm_setting(SETTING_CHARGING, onoff);
return 0;
}
int bat_full = -1;
int i, ret = 0;
int val = 0;
+ int status = -1;
new_bat_capacity = bat_percent;
if (new_bat_capacity < 0)
return -1;
if (val == 1) {
new_bat_state = BATTERY_POWER_OFF;
if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_POWER_OFF);
+ status = VCONFKEY_SYSMAN_BAT_POWER_OFF;
} else {
new_bat_state = BATTERY_REAL_POWER_OFF;
if (vconf_state != VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF);
+ status = VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF;
}
} else if (new_bat_capacity <= BATTERY_POWER_OFF) {
new_bat_state = BATTERY_POWER_OFF;
if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_POWER_OFF);
+ status = VCONFKEY_SYSMAN_BAT_POWER_OFF;
} else if (new_bat_capacity <= BATTERY_CRITICAL_LOW) {
new_bat_state = BATTERY_CRITICAL_LOW;
if (vconf_state != VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_CRITICAL_LOW);
+ status = VCONFKEY_SYSMAN_BAT_CRITICAL_LOW;
} else if (new_bat_capacity <= BATTERY_WARNING_LOW) {
new_bat_state = BATTERY_WARNING_LOW;
if (vconf_state != VCONFKEY_SYSMAN_BAT_WARNING_LOW)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_WARNING_LOW);
+ status = VCONFKEY_SYSMAN_BAT_WARNING_LOW;
} else {
new_bat_state = BATTERY_NORMAL;
if (new_bat_capacity == BATTERY_FULL) {
device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &bat_full);
if (bat_full == 1) {
if (vconf_state != VCONFKEY_SYSMAN_BAT_FULL)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_FULL);
+ status = VCONFKEY_SYSMAN_BAT_FULL;
} else {
if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_NORMAL);
+ status = VCONFKEY_SYSMAN_BAT_NORMAL;
}
} else {
if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL)
- ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_NORMAL);
+ status = VCONFKEY_SYSMAN_BAT_NORMAL;
}
}
- if(ret < 0)
+ if (status != -1) {
+ ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, status);
+ if (update_pm_setting)
+ update_pm_setting(SETTING_LOW_BATT, status);
+ }
+
+ if (ret < 0)
return -1;
ss_lowbat_is_charge_in_now();
{
int val = -1;
int status = -1;
- if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) != 0 ||
+ if ((device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) != 0) ||
vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS,&status) != 0)
return;
if ((val == 1 && status == VCONFKEY_SYSMAN_USB_DISCONNECTED) ||
* limitations under the License.
*/
-#include <systemd/sd-daemon.h>
+
#include <stdio.h>
#include <fcntl.h>
#include <heynoti.h>
}
edbus_init();
system_server_init(&ad);
+ start_pm_main();
signal(SIGTERM, sig_quit);
-
- // Notyfication to systemd
- if (sd_booted())
- sd_notify(0, "READY=1");
-
ecore_main_loop_begin();
+ end_pm_main();
fini(&ad);
edbus_fini();
ecore_shutdown();
return 1;
}
-static int ss_sysnoti_systemd_socket_test(const char *path)
-{
- int type = SOCK_STREAM;
- int listening = 1;
- size_t length = 0;
- int fd = -1;
- int rc;
- int n;
- int i;
-
- // Gets number of created by systemd file descriptors that represent open sockets.
- n = sd_listen_fds(0);
- for (i = 0; i < n; i ++) {
-
- // File descriptor calculation
- fd = SD_LISTEN_FDS_START + i;
-
- // File descriptor veryfication.
- if ((rc = sd_is_socket_unix(fd, type, listening, path, length)) > 0)
- return fd;
-
- // Check error
- if (rc < 0)
- return -1;
- }
-
- // No proper socket
- return -1;
-}
-
static int ss_sysnoti_server_init(void)
{
int fd;
struct sockaddr_un serveraddr;
- // Getting systemd socket
- fd = ss_sysnoti_systemd_socket_test(SYSNOTI_SOCKET_PATH);
- if (fd >= 0)
- return fd;
-
if (access(SYSNOTI_SOCKET_PATH, F_OK) == 0)
unlink(SYSNOTI_SOCKET_PATH);
[Service]
# set DISPLAY for usb_setting launching
-Type=notify
+Type=forking
Environment=DISPLAY=:0
-ExecStart=/usr/bin/system_server
+ExecStart=/usr/bin/device-daemon
TimeoutStopSec=2
NotifyAccess=all
#Smart debug bridge
ACTION=="add", KERNEL=="samsung_sdb", SYMLINK+="tizen_sdb"
+
+#input(like bt)
+ACTION=="add" SUBSYSTEM=="input" DEVPATH=="*/input[0-9]*/event[0-9]*" RUN+="@PREFIX@/bin/pm_event add $DEVNAME"
+ACTION=="remove" SUBSYSTEM=="input" DEVPATH=="*/input[0-9]*/event[0-9]*" RUN+="@PREFIX@/bin/pm_event remove $DEVNAME"
+
+# Since power_manager is running as app user, make sure this user can read the input device nodes
+SUBSYSTEM=="input" DEVPATH=="*/input[0-9]*/event[0-9]*" GROUP="video"