power-manager logic is running in system-server. 38/14138/4
authorjy910.yun <jy910.yun@samsung.com>
Wed, 19 Jun 2013 13:08:23 +0000 (22:08 +0900)
committerLukasz Stelmach <l.stelmach@samsung.com>
Mon, 30 Dec 2013 07:52:10 +0000 (23:52 -0800)
Refactor system fw (pm is merged to system-server). Currently there are
two daemons: power-manager and system-server.  The plan is to provide
only one daemon to control all devices on a target.  This patch merges
power-manager into system-server.

Change-Id: Ifa9bb4f7a21dc33600cce94b99a68b530d3e813b
Signed-off-by: Krzysztof Sasiak <k.sasiak@samsung.com>
Signed-off-by: Ɓukasz Stelmach <l.stelmach@samsung.com>
28 files changed:
CMakeLists.txt
device-daemon.in [new file with mode: 0644]
display/battery.c [new file with mode: 0644]
display/battery.h [new file with mode: 0644]
display/conf.c [new file with mode: 0644]
display/conf.h [new file with mode: 0644]
display/core.c [new file with mode: 0644]
display/core.h [new file with mode: 0644]
display/key-filter.c [new file with mode: 0644]
display/llinterface.c [new file with mode: 0644]
display/llinterface.h [new file with mode: 0644]
display/lsensor.c [new file with mode: 0644]
display/poll.c [new file with mode: 0644]
display/poll.h [new file with mode: 0644]
display/setting.c [new file with mode: 0644]
display/setting.h [new file with mode: 0644]
display/util.c [new file with mode: 0644]
display/util.h [new file with mode: 0644]
display/x-lcd-on.c [new file with mode: 0644]
packaging/system-server.spec
pm_event/CMakeLists.txt [new file with mode: 0755]
pm_event/pm_event.c [new file with mode: 0644]
src/battery/lowbat-handler.c
src/core/device-change-handler.c
src/core/main.c
src/core/sysnoti.c
systemd/system-server.service
udev-rules/91-system-server.rules.in

index 61ca672..dd1f311 100755 (executable)
@@ -30,6 +30,17 @@ SET(SRCS
        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)
@@ -55,8 +66,9 @@ pkg_check_modules(pkgs REQUIRED
        tapi
        dlog
        syspopup-caller
-       notification
        device-node
+       sensor
+       notification
        libsmack
        libsystemd-daemon)
 
@@ -75,6 +87,12 @@ ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
 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()
@@ -84,6 +102,7 @@ SET(UDEV_RULES_PATH share/system-server/udev-rules)
 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})
@@ -104,6 +123,7 @@ INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
 
 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)
@@ -114,4 +134,5 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/system-server.socket  DESTINAT
 
 ADD_SUBDIRECTORY(restarter)
 ADD_SUBDIRECTORY(sys_event)
+ADD_SUBDIRECTORY(pm_event)
 ADD_SUBDIRECTORY(sys_pci_noti)
diff --git a/device-daemon.in b/device-daemon.in
new file mode 100644 (file)
index 0000000..8fb6f1e
--- /dev/null
@@ -0,0 +1,53 @@
+#!/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
+
diff --git a/display/battery.c b/display/battery.c
new file mode 100644 (file)
index 0000000..3d93c23
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * 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);
+}
+
diff --git a/display/battery.h b/display/battery.h
new file mode 100644 (file)
index 0000000..f9db24b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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
diff --git a/display/conf.c b/display/conf.c
new file mode 100644 (file)
index 0000000..dc1ebee
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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;
+}
diff --git a/display/conf.h b/display/conf.h
new file mode 100644 (file)
index 0000000..8a3894d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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
diff --git a/display/core.c b/display/core.c
new file mode 100644 (file)
index 0000000..b247a84
--- /dev/null
@@ -0,0 +1,1511 @@
+/*
+ * 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(&noti_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");
+}
+
+/**
+ * @}
+ */
diff --git a/display/core.h b/display/core.h
new file mode 100644 (file)
index 0000000..dc8f6ff
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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
diff --git a/display/key-filter.c b/display/key-filter.c
new file mode 100644 (file)
index 0000000..b164238
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * 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;
+}
+
diff --git a/display/llinterface.c b/display/llinterface.c
new file mode 100644 (file)
index 0000000..221108a
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * 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;
+}
diff --git a/display/llinterface.h b/display/llinterface.h
new file mode 100644 (file)
index 0000000..7a4250f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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
+
diff --git a/display/lsensor.c b/display/lsensor.c
new file mode 100644 (file)
index 0000000..e1a957f
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * 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)
+{
+
+}
diff --git a/display/poll.c b/display/poll.c
new file mode 100644 (file)
index 0000000..88afec5
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * 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;
+}
diff --git a/display/poll.h b/display/poll.h
new file mode 100644 (file)
index 0000000..593d024
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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__ */
diff --git a/display/setting.c b/display/setting.c
new file mode 100644 (file)
index 0000000..df505fb
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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;
+}
+
diff --git a/display/setting.h b/display/setting.h
new file mode 100644 (file)
index 0000000..c78ddd7
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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
diff --git a/display/util.c b/display/util.c
new file mode 100644 (file)
index 0000000..81858a8
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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);
+}
+
+/**
+ * @}
+ */
diff --git a/display/util.h b/display/util.h
new file mode 100644 (file)
index 0000000..5b00f05
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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
diff --git a/display/x-lcd-on.c b/display/x-lcd-on.c
new file mode 100644 (file)
index 0000000..4ef2dcd
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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__ */
index c1df839..067e081 100755 (executable)
@@ -2,9 +2,9 @@
 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
@@ -26,6 +26,7 @@ BuildRequires:  pkgconfig(udev)
 BuildRequires:  pkgconfig(device-node)
 BuildRequires:  pkgconfig(libsmack)
 BuildRequires:  gettext
+BuildRequires:  pkgconfig(sensor)
 BuildRequires:  pkgconfig(libsystemd-daemon)
 %{?systemd_requires}
 Requires(preun): /usr/bin/systemctl
@@ -70,7 +71,7 @@ ln -s ../system-server.service %{buildroot}%{_unitdir}/multi-user.target.wants/s
 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
@@ -101,6 +102,17 @@ vconftool set -t int memory/sysman/stime_changed 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
@@ -129,6 +141,7 @@ systemctl daemon-reload
 if [ $1 == 1 ]; then
     systemctl restart system-server.service
 fi
+/sbin/ldconfig
 
 %preun
 if [ $1 == 0 ]; then
@@ -137,7 +150,7 @@ fi
 
 %postun
 systemctl daemon-reload
-
+/sbin/ldconfig
 
 %files
 %manifest %{name}.manifest
@@ -153,14 +166,17 @@ systemctl daemon-reload
 %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,-)
diff --git a/pm_event/CMakeLists.txt b/pm_event/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..e3af587
--- /dev/null
@@ -0,0 +1,31 @@
+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)
+
diff --git a/pm_event/pm_event.c b/pm_event/pm_event.c
new file mode 100644 (file)
index 0000000..9fe086b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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;
+}
index c063ae7..464a4e7 100755 (executable)
 #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
@@ -128,6 +128,8 @@ int ss_lowbat_set_charge_on(int onoff)
                _E("fail to set charge vconf value");
                return -1;
        }
+       if (update_pm_setting)
+               update_pm_setting(SETTING_CHARGING, onoff);
        return 0;
 }
 
@@ -157,6 +159,7 @@ static int lowbat_process(int bat_percent, void *ad)
        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;
@@ -180,42 +183,48 @@ static int lowbat_process(int bat_percent, void *ad)
                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();
index 648a923..bac3ff3 100755 (executable)
@@ -172,7 +172,7 @@ static void __sync_usb_status(void)
 {
        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) ||
index cd8abe4..22682bf 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <systemd/sd-daemon.h>
+
 #include <stdio.h>
 #include <fcntl.h>
 #include <heynoti.h>
@@ -102,14 +102,11 @@ static int system_main(int argc, char **argv)
        }
        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();
index 778e314..1838ecd 100755 (executable)
@@ -268,46 +268,11 @@ static int sysnoti_cb(void *data, Ecore_Fd_Handler * fd_handler)
        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);
 
index 01cf784..22540c9 100644 (file)
@@ -4,9 +4,9 @@ After=vconf-setup.service
 
 [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
 
index 1c1d528..63d0531 100644 (file)
@@ -37,3 +37,10 @@ ACTION=="remove"     SUBSYSTEM=="input"      DEVPATH=="*/virtio[1-9]*/input/input[1-9]*/e
 
 #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"