Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:51:50 +0000 (01:51 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:51:50 +0000 (01:51 +0900)
40 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE.APLv2 [new file with mode: 0644]
NOTICE [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/power-manager-bin.install.in [new file with mode: 0644]
debian/power-manager-bin.postinst.in [new file with mode: 0644]
debian/rules [new file with mode: 0755]
main.c [new file with mode: 0644]
packaging/power-manager.manifest [new file with mode: 0644]
packaging/power-manager.service [new file with mode: 0644]
packaging/power-manager.spec [new file with mode: 0644]
pm_battery.c [new file with mode: 0644]
pm_battery.h [new file with mode: 0644]
pm_conf.c [new file with mode: 0644]
pm_conf.h [new file with mode: 0644]
pm_core.c [new file with mode: 0644]
pm_core.h [new file with mode: 0644]
pm_device_plugin.c [new file with mode: 0644]
pm_device_plugin.h [new file with mode: 0644]
pm_event/CMakeLists.txt [new file with mode: 0644]
pm_event/pm_event.c [new file with mode: 0644]
pm_key_filter.c [new file with mode: 0644]
pm_llinterface.c [new file with mode: 0644]
pm_llinterface.h [new file with mode: 0644]
pm_lsensor.c [new file with mode: 0644]
pm_poll.c [new file with mode: 0644]
pm_poll.h [new file with mode: 0644]
pm_setting.c [new file with mode: 0644]
pm_setting.h [new file with mode: 0644]
pm_x_lcd_onoff.c [new file with mode: 0644]
pmctrl.in [new file with mode: 0644]
udev-rules/91-power-manager.rules.in [new file with mode: 0644]
util.c [new file with mode: 0644]
util.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..cc6ce5d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Seunghun Pi <sh.pi at samsung dot com>\r
+Suchang Woo <suchang.woo at samsung dot com>\r
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c75267d
--- /dev/null
@@ -0,0 +1,59 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(power_manager C)
+
+SET(SRCS
+       util.c
+       main.c
+       pm_llinterface.c
+       pm_conf.c
+       pm_setting.c
+       pm_poll.c
+       pm_core.c
+       pm_lsensor.c
+       pm_device_plugin.c
+       pm_key_filter.c
+       pm_battery.c )
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED vconf glib-2.0 sysman aul dlog heynoti devman_plugin sensor)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+ADD_DEFINITIONS("-DENABLE_KEY_FILTER")
+ADD_DEFINITIONS("-DENABLE_X_LCD_ONOFF")
+ADD_DEFINITIONS("-DENABLE_DLOG_OUT")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC ${PROJECT_NAME})
+CONFIGURE_FILE(pmctrl.in pmctrl @ONLY)
+
+SET(UDEV_RULES_PATH share/power-manager/udev-rules)
+SET(UDEV_RULES udev-rules/91-power-manager.rules)
+
+CONFIGURE_FILE(${UDEV_RULES}.in ${UDEV_RULES} @ONLY)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/pmctrl DESTINATION bin)
+INSTALL(FILES ${UDEV_RULES} DESTINATION ${UDEV_RULES_PATH})
+INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/pmctrl DESTINATION /etc/rc.d/init.d)
+
+ADD_SUBDIRECTORY(pm_event)
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..08a1d59
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, This software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..f2640b9
--- /dev/null
@@ -0,0 +1,16 @@
+power-manager (1.3.21-96) unstable; urgency=low
+
+  *  Update for tizen 2.0
+  * Git: magnolia/framework/system/power-manager
+  * Tag: power-manager_1.3.21-96
+
+ -- Seunghun Pi <sh.pi@samsung.com>  Thu, 23 Aug 2012 10:43:03 +0900
+
+power-manager (1.3.21-87) unstable; urgency=low
+
+  * update for new oal layer
+  * Git: slp/pkgs/p/power-manager
+  * Tag: power-manager_1.3.21-87
+
+ -- Jinkun Jang <jinkun.jang@samsung.com>  Mon, 09 Apr 2012 14:47:03 +0900
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..d74f208
--- /dev/null
@@ -0,0 +1,20 @@
+Source: power-manager
+Section: system
+Priority: extra
+Maintainer: Jonghoon Han <jonghoon.han@samsung.com> Jinkun Jang <jinkun.jang@samsung.com> DongGi Jang <dg0402.jang@samsung.com> TAESOO JUN <steve.jun@samsung.com>
+Uploaders: Jinkun Jang <jinkun.jang@samsung.com>
+Build-Depends: debhelper (>= 5), libglib2.0-dev, libslp-setting-dev, libslp-sysman-dev, libaul-1-dev, dlog-dev, libheynoti-dev, libslp-sensor-dev, libdevman-plugin-dev
+Standards-Version: 3.7.2
+
+Package: power-manager-bin
+Architecture: any 
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Power manager
+ Power manager
+Package: power-manager-bin-dbg
+Section: debug
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, power-manager-bin (= ${Source-Version})
+Description: Power manager
+ Power manager (unstripped)
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..ca882bb
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..a0f0008
--- /dev/null
@@ -0,0 +1 @@
+CMakeLists.txt
diff --git a/debian/power-manager-bin.install.in b/debian/power-manager-bin.install.in
new file mode 100644 (file)
index 0000000..f564239
--- /dev/null
@@ -0,0 +1,3 @@
+@PREFIX@/bin/*
+@PREFIX@/share/power-manager/*
+etc/*
diff --git a/debian/power-manager-bin.postinst.in b/debian/power-manager-bin.postinst.in
new file mode 100644 (file)
index 0000000..7805f53
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+vconftool set -t int memory/pm/state 0 -i
+
+heynotitool set system_wakeup
+
+mkdir -p /etc/udev/rules.d
+if ! [ -L /etc/udev/rules.d/91-power-manager.rules ]; then
+       ln -s @PREFIX@/share/power-manager/udev-rules/91-power-manager.rules /etc/udev/rules.d/91-power-manager.rules
+fi
+
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..10c3e3d
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+CFLAGS ?= -Wall -g
+CXXFLAGS ?=  -Wall -g
+LDFLAGS ?= 
+PREFIX ?= /usr
+DATADIR ?= /opt
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+       CXXFLAGS += -O0
+else
+       CFLAGS += -O2
+       CXXFLAGS += -O2
+endif
+
+LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed
+
+configure: configure-stamp
+configure-stamp: 
+       dh_testdir
+       # Add here commands to configure the package.
+       CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake . -DCMAKE_INSTALL_PREFIX=$(PREFIX)
+
+       touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+       #docbook-to-man debian/wavplayer.sgml > wavplayer.1
+
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               cat $$f > $${f%.in}; \
+               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
+               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
+       done
+
+
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -$(MAKE) clean
+       rm -rf CMakeCache.txt
+       rm -rf CMakeFiles
+       rm -rf cmake_install.cmake
+       rm -rf Makefile
+       rm -rf install_manifest.txt
+       rm -rf *.so
+       rm -rf ./pm_event/CMakeCache.txt
+       rm -rf ./pm_event/CMakeFiles
+       rm -rf ./pm_event/cmake_install.cmake
+       rm -rf ./pm_event/Makefile
+       rm -rf ./pm_event/install_manifest.txt
+       rm -rf ./pm_event/pm_event
+       
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               rm -f $${f%.in}; \
+       done
+
+       for f in `find $(CURDIR)/ -name "*.in"`; do \
+               rm -f $${f%.in}; \
+       done
+
+
+       dh_clean 
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       # Add here commands to install the package into debian/wavplayer.
+       $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+       mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/
+       mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/
+
+       ln -s ../init.d/power_manager.sh $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/S35power-manager
+       ln -s ../init.d/power_manager.sh $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/S00power-manager
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs 
+       dh_installdocs
+       dh_installexamples
+       dh_install --sourcedir=debian/tmp
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_python
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+       dh_installman
+       dh_link
+#      dh_strip
+       dh_strip --dbg-package=power-manager-bin-dbg
+       dh_compress
+       dh_fixperms
+#      dh_perl
+       dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure patch unpatch
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..75608a2
--- /dev/null
+++ b/main.c
@@ -0,0 +1,133 @@
+/*
+ * 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       main.c
+ * @version    0.1
+ * @brief      Power Manager main file
+ *
+ * Process the user options, Daemonize the process, Start Main loop
+ */
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ *
+ * @section execution How to execute 
+ *   # powermanager {options...} <br>
+ *
+ * Options: <br><br>
+ *  &nbsp; -f --foreground<br>
+ *  &nbsp; &nbsp; Run as foreground process<br> <br>
+ *  &nbsp; -d --direct<br>
+ *  &nbsp; &nbsp; Start without notification<br> <br>
+ *
+ * @}
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "pm_core.h"
+
+/**
+ * Print the usage
+ *
+ * @internal
+ */
+void usage()
+{
+       printf("Options: \n");
+       printf("  -f, --foreground         Run as foreground process\n");
+       printf("  -d, --direct             Start without notification\n");
+       printf
+           ("  -x, --xdpms              With LCD-onoff control by x-dpms \n");
+       printf("\n");
+
+       exit(0);
+}
+
+/**
+ * Pid file path
+ */
+#define        DEFAULT_PID_PATH "/var/run/power-manager.pid"
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int runflags = 0;       /* run as daemon */
+       unsigned int flags = 0x0;       /* 0 : start with noti */
+
+       while (1) {
+               int option_index = 0;
+               static struct option long_options[] = {
+                       {"foreground", no_argument, NULL, 'f'},
+                       {"direct", no_argument, NULL, 'd'},
+                       {"xdpms", no_argument, NULL, 'x'},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long(argc, argv, "fdx", long_options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'f':
+                       runflags = 1;
+                       break;
+
+               case 'd':
+                       flags = flags | WITHOUT_STARTNOTI;      /* 0x1 : start without noti */
+                       break;
+
+               case 'x':
+                       flags = flags | FLAG_X_DPMS;    /* 0x2 : X control LCD onoff */
+                       break;
+
+               default:
+                       usage();
+                       break;
+               }
+       }
+
+       if (optind < argc)
+               usage();
+
+       if (access(DEFAULT_PID_PATH, F_OK) == 0) {      /* pid file exist */
+               printf
+                   ("Check the PM is running. If it isn't, delete \"%s\" and retry.\n",
+                    DEFAULT_PID_PATH);
+               return -1;
+       }
+
+       if (!runflags)
+               daemonize();
+
+       writepid(DEFAULT_PID_PATH);
+
+       /* this function is main loop, defined in pm_core.c */
+       start_main(flags);
+
+       unlink(DEFAULT_PID_PATH);
+       return 0;
+}
diff --git a/packaging/power-manager.manifest b/packaging/power-manager.manifest
new file mode 100644 (file)
index 0000000..e4d4971
--- /dev/null
@@ -0,0 +1,13 @@
+<manifest>
+    <define>
+        <domain name="power_manager"/>
+    </define>
+    <request>
+        <domain name="power_manager"/>
+    </request>
+    <assign>
+        <filesystem path="/etc/rc.d/init.d/pmctrl" label="_" exec_label="none" />
+        <filesystem path="/etc/rc.d/rc3.d/S35power-manager" label="_" exec_label="none" />
+    </assign>
+</manifest>
+
diff --git a/packaging/power-manager.service b/packaging/power-manager.service
new file mode 100644 (file)
index 0000000..13609c8
--- /dev/null
@@ -0,0 +1,10 @@
+[Unit]
+Description=Start the power manager service
+
+[Service]
+Type=forking
+ExecStart=/usr/bin/pmctrl start
+Environment=DISPLAY=:0
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packaging/power-manager.spec b/packaging/power-manager.spec
new file mode 100644 (file)
index 0000000..0004a9c
--- /dev/null
@@ -0,0 +1,83 @@
+Name:       power-manager
+Summary:    Power manager
+Version:    1.3.23
+Release:    8
+Group:      framework/system
+License:    APLv2
+Source0:    %{name}-%{version}.tar.gz
+Source1001: packaging/power-manager.manifest 
+Requires(post): /usr/bin/vconftool
+Source1:        power-manager.service
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(sysman)
+BuildRequires:  pkgconfig(aul)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(devman)
+BuildRequires:  pkgconfig(devman_plugin)
+BuildRequires:  pkgconfig(heynoti)
+
+%description
+Description: Power manager
+
+
+%prep
+%setup -q 
+
+%build
+cp %{SOURCE1001} .
+%ifnarch %arm
+%if 0%{?simulator}
+#for emulator
+CFLAGS+=" -DTIZEN_EMUL"
+%else
+#for real device
+CFLAGS+=" -DX86"
+%endif
+export CFLAGS
+%endif
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants
+install -m 0644 %{SOURCE1} %{buildroot}%{_libdir}/systemd/system/power-manager.service
+ln -s ../power-manager.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/power-manager.service
+
+mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc3.d/
+mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc5.d/
+ln -s %{_sysconfdir}/init.d/pmctrl %{buildroot}%{_sysconfdir}/rc.d/rc3.d/S35power-manager
+ln -s %{_sysconfdir}/init.d/pmctrl %{buildroot}%{_sysconfdir}/rc.d/rc5.d/S00power-manager
+
+%post
+vconftool set -t int memory/pm/state 0 -i
+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/custom_brightness_status 0 -i -g 5000
+vconftool set -t bool memory/pm/brt_changed_lpm 0 -i
+
+heynotitool set system_wakeup
+heynotitool set pm_event
+
+mkdir -p /etc/udev/rules.d
+if ! [ -L /etc/udev/rules.d/91-power-manager.rules ]; then
+        ln -s %{_datadir}/power-manager/udev-rules/91-power-manager.rules /etc/udev/rules.d/91-power-manager.rules
+fi
+
+%files
+%manifest power-manager.manifest
+%{_sysconfdir}/rc.d/init.d/pmctrl
+%{_sysconfdir}/rc.d/rc3.d/S35power-manager
+%{_sysconfdir}/rc.d/rc5.d/S00power-manager
+%{_bindir}/pm_event
+%{_bindir}/pmctrl
+%{_bindir}/power_manager
+%{_libdir}/systemd/system/power-manager.service
+%{_libdir}/systemd/system/multi-user.target.wants/power-manager.service
+%{_datadir}/power-manager/udev-rules/91-power-manager.rules
diff --git a/pm_battery.c b/pm_battery.c
new file mode 100644 (file)
index 0000000..a413774
--- /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 <glib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pm_core.h"
+#include "pm_device_plugin.h"
+#include "pm_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   (5)
+#define MAX_COUNT_CHARGING     (5)
+#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 int timeout_id = 0;
+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};
+
+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;
+       }
+}
+
+void battinfo_calculation()
+{
+       time_t clock;
+       int capacity = 0;
+       int estimated_time = 0;
+       int tmp = 0;
+
+       capacity = get_battery_capacity();
+
+       if(capacity <= 0)
+               return;
+       if(capacity == old_capacity)
+               return;
+
+       old_capacity = capacity;
+
+       if(get_charging_status(&tmp) == 0)
+               charging_state = (tmp > 0 ? TRUE : FALSE);
+
+       clock = time(NULL);
+       if(charging_state == TRUE) {
+               del_all_batt_node(B_UNCHARGING);
+               if((capacity * 100 / full_capacity)
+                               >= BATTERY_FULL_THRESHOLD) {
+                       if(battery_charge_full()) {
+                               del_all_batt_node(B_CHARGING);
+                               LOGINFO("battery fully charged!");
+                               update_time(A_TIMETOFULL, 0);
+                               return;
+                       }
+               }
+               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);
+       }
+}
+
+static gboolean battinfo_cb(gpointer data)
+{
+       battinfo_calculation();
+       return TRUE;
+}
+
+static int init_battery_func()
+{
+       int ret = -1;
+       int value = -1;
+
+       ret = battery_capacity_raw(&value);
+       if(ret >= 0) {
+               get_battery_capacity = battery_capacity_raw;
+               full_capacity = FULL_CAPACITY_RAW;
+               LOGINFO("init_battery_func : full capacity(%d)", full_capacity);
+               return 0;
+       }
+
+       ret = battery_capacity(&value);
+       if(ret >= 0) {
+               get_battery_capacity = battery_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 = g_timeout_add_full(G_PRIORITY_DEFAULT, timeout,
+                                       (GSourceFunc)battinfo_cb, NULL, 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()
+{
+       LOGINFO("End battery gathering!");
+
+       if(timeout_id > 0) {
+               g_source_remove(timeout_id);
+               timeout_id = 0;
+       }
+       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/pm_battery.h b/pm_battery.h
new file mode 100644 (file)
index 0000000..1d5b0e7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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 30000 /* ms */
+
+/*
+* If system is suspend state for a long time,
+* it's hard to expect power consumption.
+* Therefore, Previous capacity value is ignored
+* when system changes from suspend state to resume state.
+* This flag indicates phone wakes up from suspend state.
+* In this case, all nodes saved are ignored.
+*/
+extern int system_wakeup_flag;
+
+int start_battinfo_gathering(int timeout);
+void end_battinfo_gathering();
+
+#endif
diff --git a/pm_conf.c b/pm_conf.c
new file mode 100644 (file)
index 0000000..9ee6e54
--- /dev/null
+++ b/pm_conf.c
@@ -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 "pm_conf.h"
+
+enum {
+       IDX_NAME = 0,
+       IDX_DEFAULT,
+       IDX_END
+};
+
+static 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/pm_conf.h b/pm_conf.h
new file mode 100644 (file)
index 0000000..8a3894d
--- /dev/null
+++ b/pm_conf.h
@@ -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/pm_core.c b/pm_core.c
new file mode 100644 (file)
index 0000000..d53aa27
--- /dev/null
+++ b/pm_core.c
@@ -0,0 +1,1356 @@
+/*
+ * 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       pm_core.c
+ * @version    0.2
+ * @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 <glib.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 <sysman.h>
+#include <aul.h>
+#include <vconf-keys.h>
+
+#include "pm_device_plugin.h"
+#include "pm_core.h"
+#include "pm_battery.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 status_flag;
+
+static void (*power_saving_func) (int onoff);
+static void reset_timeout(int timeout);
+
+int cur_state;
+int old_state;
+static GMainLoop *mainloop;
+guint 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, When wake up by devices, go lcd_off state  */
+};
+
+#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    5
+#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)
+
+static int received_sleep_cmd = 0;
+
+typedef struct _node {
+       pid_t pid;
+       int timeout_id;
+       gboolean holdkey_block;
+       struct _node *next;
+} Node;
+
+static Node *cond_head[S_END];
+
+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 Node *find_node(enum state_t s_index, pid_t pid)
+{
+       Node *t = cond_head[s_index];
+
+       while (t != NULL) {
+               if (t->pid == pid)
+                       break;
+               t = t->next;
+       }
+       return t;
+}
+
+static Node *add_node(enum state_t s_index, pid_t pid, int timeout_id,
+               gboolean holdkey_block)
+{
+       Node *n;
+
+       n = (Node *) malloc(sizeof(Node));
+       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, Node *n)
+{
+       Node *t;
+       Node *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 gboolean del_dim_cond(gpointer data)
+{
+       Node *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 == 0)
+               states[cur_state].trans(EVENT_TIMEOUT);
+
+       return FALSE;
+}
+
+static gboolean del_off_cond(gpointer data)
+{
+       Node *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 == 0)
+               states[cur_state].trans(EVENT_TIMEOUT);
+
+       return FALSE;
+}
+
+static gboolean del_sleep_cond(gpointer data)
+{
+       Node *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 == 0)
+               states[cur_state].trans(EVENT_TIMEOUT);
+
+       sysman_inform_inactive((pid_t) data);
+       return FALSE;
+}
+
+/* update transition condition for application requrements */
+static int proc_condition(PMMsg *data)
+{
+       Node *tmp = NULL;
+       unsigned int val = data->cond;
+       pid_t pid = data->pid;
+       int cond_timeout_id = -1;
+       gboolean holdkey_block = 0;
+
+       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 =
+                               g_timeout_add_full(G_PRIORITY_DEFAULT,
+                                               data->timeout,
+                                               (GSourceFunc) del_dim_cond,
+                                               (gpointer) pid, NULL);
+               }
+               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) {
+                       g_source_remove(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 =
+                               g_timeout_add_full(G_PRIORITY_DEFAULT,
+                                               data->timeout,
+                                               (GSourceFunc) del_off_cond,
+                                               (gpointer) pid, NULL);
+               }
+               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) {
+                       g_source_remove(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 =
+                               g_timeout_add_full(G_PRIORITY_DEFAULT,
+                                               data->timeout,
+                                               (GSourceFunc) del_sleep_cond,
+                                               (gpointer) pid, NULL);
+               }
+               tmp = find_node(S_SLEEP, pid);
+               if (tmp == NULL)
+                       add_node(S_SLEEP, pid, cond_timeout_id, 0);
+               else if (tmp->timeout_id > 0) {
+                       g_source_remove(tmp->timeout_id);
+                       tmp->timeout_id = cond_timeout_id;
+                       tmp->holdkey_block = 0;
+               }
+               sysman_inform_active(pid);
+               /* 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);
+               sysman_inform_inactive(pid);
+               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[cur_state].timeout);
+                       LOGINFO("reset timeout\n", "S_LCDOFF", pid, pname);
+               }
+       } else {
+               /* guard time for suspend */
+               if (cur_state == S_LCDOFF) {
+                       reset_timeout(5);
+                       LOGINFO("margin timeout (5 seconds)\n");
+               }
+       }
+
+       if (timeout_src_id == 0)
+               states[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 */
+                       old_state = cur_state;
+                       cur_state = next_state;
+                       st = &states[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 */
+                       old_state = cur_state;
+                       cur_state = S_LCDOFF;
+                       st = &states[cur_state];
+                       if (st->action) {
+                               st->action(0);
+                       }
+                       old_state = cur_state;
+                       cur_state = S_SLEEP;
+                       st = &states[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)
+{
+       Node *t = cond_head[prohibit_state];
+       Node *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)
+{
+       Node *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)
+{
+       Node *t = cond_head[state];
+       int ret = 0;
+       Node *tmp = NULL;
+
+       LOGINFO("delete condition : state of %s", state_string[state]);
+
+       while(t != NULL) {
+               if(t->timeout_id > 0) {
+                       g_source_remove(t->timeout_id);
+               }
+               tmp = t;
+               t = t->next;
+               LOGINFO("delete node of pid(%d)", tmp->pid);
+               del_node(state, tmp);
+       }
+
+       return 0;
+}
+
+/* SIGINT, SIGTERM, SIGQUIT signal handler */
+static void sig_quit(int signo)
+{
+       LOGINFO("received %d signal : stops a main loop", signo);
+       if (mainloop)
+               g_main_loop_quit(mainloop);
+}
+
+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[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++) {
+               Node *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;
+               }
+       }
+}
+
+/* SIGHUP signal handler 
+ * For debug... print info to syslog
+ */
+static void sig_hup(int signo)
+{
+       int fd;
+       char buf[255];
+       time_t now_time;
+
+       time(&now_time);
+
+       fd = open(PM_STATE_LOG_FILE, O_CREAT | O_WRONLY, 0644);
+       if (fd != -1) {
+               snprintf(buf, sizeof(buf), "\npm_state_log now-time : %d (s)\n\n",
+                               (int)now_time);
+               write(fd, buf, strlen(buf));
+
+               snprintf(buf, sizeof(buf), "status_flag: %x\n", 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  */
+gboolean timeout_handler(gpointer data)
+{
+       LOGINFO("Time out state %s\n", state_string[cur_state]);
+
+       if (timeout_src_id != 0) {
+               g_source_remove(timeout_src_id);
+               timeout_src_id = 0;
+       }
+
+       if ((status_flag & VCALL_FLAG)
+                       && (cur_state == S_LCDOFF || cur_state == S_SLEEP)) {
+               status_flag &= ~(VCALL_FLAG);
+               reset_timeout(TELEPHONY_SIGNAL_TIMEOUT);
+               return FALSE;
+       }
+       states[cur_state].trans(EVENT_TIMEOUT);
+       return FALSE;
+}
+
+static void reset_timeout(int timeout)
+{
+       if (timeout_src_id != 0) {
+               g_source_remove(timeout_src_id);
+               timeout_src_id = 0;
+       }
+       if (timeout > 0) {
+               timeout_src_id = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
+                               timeout,
+                               (GSourceFunc)
+                               timeout_handler,
+                               NULL, NULL);
+       }
+}
+
+static void sig_usr(int signo)
+{
+       status_flag |= VCALL_FLAG;
+}
+
+static void sig_break_block(int signo)
+{
+       LOGINFO("We got signal to break that pending checking in kernel\n");
+}
+
+/* 
+ * default transition function
+ *   1. call check 
+ *   2. transition 
+ *   3. call enter action function
+ */
+static int default_trans(int evt)
+{
+       struct state *st = &states[cur_state];
+       int next_state;
+
+       if(cur_state == S_NORMAL && st->timeout == 0) {
+               LOGINFO("LCD always on enabled!");
+               return 0;
+       }
+
+       next_state = (enum state_t)trans_table[cur_state][evt];
+
+       /* check conditions */
+       while (st->check && !st->check(next_state)) {
+               /* There is a condition. */
+               LOGINFO("%s -> %s : check fail", state_string[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 */
+       old_state = cur_state;
+       cur_state = next_state;
+       st = &states[cur_state];
+
+       /* enter action */
+       if (st->action) {
+               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 (cur_state != old_state && cur_state != S_SLEEP)
+               set_setting_pmstate(cur_state);
+
+       switch (cur_state) {
+               case S_NORMAL:
+                       /* normal state : backlight on and restore the previous brightness */
+                       if (old_state == S_LCDOFF || old_state == S_SLEEP) {
+                               if (pre_suspend_flag == true) {
+                                       system_post_resume();
+                                       pre_suspend_flag = false;
+                               }
+                               for (i = 0; i < 14; 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(50000);
+                               }
+#ifndef X86 /* Different with ARM FB driver, IA gfx driver is sensitive to the order. */
+                               backlight_restore();
+                               backlight_on();
+#else
+                               backlight_on();
+                               backlight_restore();
+#endif
+                       } else if (old_state == S_LCDDIM)
+                               backlight_restore();
+                       break;
+
+               case S_LCDDIM:
+                       if (old_state == S_LCDOFF || old_state == S_SLEEP) {
+                               backlight_on();
+                       }
+                       /* lcd dim state : dim the brightness */
+                       backlight_dim();
+                       break;
+
+               case S_LCDOFF:
+                       if (old_state != S_SLEEP && old_state != S_LCDOFF) {
+                               /* lcd off state : turn off the backlight */
+                               backlight_off();
+                               if (pre_suspend_flag == false) {
+                                       pre_suspend_flag = true;
+                                       system_pre_suspend();
+                               }
+                       }
+                       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 (0 > plugin_intf->OEM_sys_get_power_wakeup_count(&wakeup_count)) 
+                               LOGERR("wakeup count read error");
+
+                       if (wakeup_count < 0) {
+                               LOGINFO("Wakup Event! Can not enter suspend mode.");
+                               goto go_lcd_off;
+                       }
+
+                       if (0 > plugin_intf->OEM_sys_set_power_wakeup_count(wakeup_count)) {
+                               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[cur_state], timeout);
+
+       return 0;
+
+go_suspend:
+       system_suspend();
+       LOGINFO("system wakeup!!");
+       system_wakeup_flag = true;
+       heynoti_publish(PM_WAKEUP_NOTI_NAME);
+       /* Resume !! */
+       if (check_wakeup_src() == EVENT_DEVICE)
+               /* system waked up by devices */
+               states[cur_state].trans(EVENT_DEVICE);
+       else
+               /* system waked up by user input */
+               states[cur_state].trans(EVENT_INPUT);
+       return 0;
+
+go_lcd_off:
+       heynoti_publish(PM_WAKEUP_NOTI_NAME);
+       /* Resume !! */
+       states[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_settings()
+{
+       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) {
+               status_flag |= PWRSV_FLAG;
+       } else {
+               status_flag &= ~PWRSV_FLAG;
+       }
+       if (cur_state == S_NORMAL)
+               backlight_restore();
+}
+
+static int poll_callback(int condition, PMMsg *data)
+{
+       time_t now;
+
+       if (condition == INPUT_POLL_EVENT) {
+               if (cur_state == S_LCDOFF || cur_state == S_SLEEP)
+                       LOGINFO("Power key input");
+               time(&now);
+               if (last_t != now) {
+                       states[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 = 5;
+               }
+               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[cur_state].trans(EVENT_INPUT);
+               break;
+       case SETTING_LOW_BATT:
+               if (val < VCONFKEY_SYSMAN_BAT_WARNING_LOW) {
+                       if (!(status_flag & CHRGR_FLAG))
+                               power_saving_func(true);
+                       status_flag |= LOWBT_FLAG;
+               } else {
+                       if (status_flag & PWRSV_FLAG)
+                               power_saving_func(false);
+                       status_flag &= ~LOWBT_FLAG;
+                       status_flag &= ~BRTCH_FLAG;
+                       vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
+                           false);
+               }
+               break;
+       case SETTING_CHARGING:
+               if (val) {
+                       if (status_flag & LOWBT_FLAG) {
+                               power_saving_func(false);
+                               status_flag &= ~LOWBT_FLAG;
+                       }
+                       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_NORMAL) {
+                               power_saving_func(true);
+                               status_flag |= LOWBT_FLAG;
+                       }
+                       status_flag &= ~CHRGR_FLAG;
+               }
+               break;
+       case SETTING_BRT_LEVEL:
+               if (status_flag & PWRSV_FLAG) {
+                       status_flag |= BRTCH_FLAG;
+                       vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
+                           true);
+                       LOGINFO("brightness changed in low battery, escape dim state");
+               }
+               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) {
+                       states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
+                       LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
+               } else {
+                       get_run_timeout(&run_timeout);
+                       if(run_timeout < 0) {
+                               LOGERR("Can not get run timeout. set default 15 seconds(includes dim 5 seconds)");
+                               run_timeout = 10;
+                       }
+                       states[S_NORMAL].timeout = run_timeout;
+                       LOGINFO("LCD NORMAL timeout is set by %d seconds because phone is unlocked", run_timeout);
+               }
+               if (cur_state == S_NORMAL) {
+                       states[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;
+               plugin_intf->OEM_sys_set_display_frame_rate(power_saving_display_stat);
+               backlight_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;
+                       plugin_intf->OEM_sys_set_display_frame_rate(power_saving_display_stat);
+                       backlight_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;
+
+       /* Charging check */
+       if ((get_charging_status(&tmp) == 0) && (tmp > 0)) {
+               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);
+       set_default_brt(tmp);
+
+       vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
+       if (bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
+               if (!(status_flag & CHRGR_FLAG)) {
+                       power_saving_func(true);
+                       status_flag |= LOWBT_FLAG;
+               }
+       }
+       backlight_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);
+       if(lock_state == VCONFKEY_IDLE_LOCK) {
+               states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
+               LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
+       }
+
+       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 printglist()
+{
+        int i;
+        guint total=0;
+        indev *tmp;
+
+        total=g_list_length(indev_list);
+        LOGINFO("***** total list : %d *****",total);
+        for(i=0;i<total;i++) {
+                tmp=(indev*)(g_list_nth(indev_list, i)->data);
+                LOGINFO("* %d | path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
+                if(i==total-1 && g_list_nth(indev_list, i)->next==NULL)
+                        LOGINFO("okokok");
+        }
+        LOGINFO("***************************\n");
+}
+
+static GList *find_glist(GList *glist, char *path)
+{
+       int i;
+       guint total=0;
+       indev *tmp;
+
+       total=g_list_length(indev_list);
+       for(i=0;i<total;i++) {
+               tmp=(indev*)(g_list_nth(indev_list, i)->data);
+               if(!strcmp(tmp->dev_path, path)){
+                       LOGINFO("nth : %d, path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
+                       return g_list_nth(indev_list, i);
+               }
+       }
+       return NULL;
+}
+
+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;
+       GList *glist = NULL;
+
+       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';
+
+                               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) ){
+                                       glist=find_glist(indev_list, input_path);
+                                       if(glist != NULL){
+                                               LOGINFO("remove input dev");
+                                               g_source_remove_poll(((indev*)(glist->data))->dev_src, ((indev*)(glist->data))->dev_fd);
+                                               g_source_destroy(((indev*)(glist->data))->dev_src);
+                                               close(((indev*)(glist->data))->dev_fd->fd);
+                                               g_free(((indev*)(glist->data))->dev_fd);
+                                               free(((indev*)(glist->data))->dev_path);
+                                               indev_list=g_list_remove(indev_list, glist->data);
+                                       }
+                                       ret=0;
+                               }
+                               /* debug */
+                               printglist();
+
+                               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];
+
+       noti_fd = heynoti_init();
+       if (noti_fd < 0) {
+               LOGERR("heynoti_init error");
+               return -1;
+       }
+
+       if (heynoti_subscribe(noti_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(noti_fd) < 0) {
+               LOGERR("heynoti_attach_handler error");
+               return -1;
+       }
+
+       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;
+}
+
+/**
+ * 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_main(unsigned int flags)
+{
+       int ret, i;
+
+       if (0 > _pm_devman_plugin_init()) {
+               LOGERR("Device Manager Plugin initialize failed");
+               exit (-1);
+       }
+
+       LOGINFO("Start power manager daemon");
+
+       signal(SIGHUP, sig_hup);
+       signal(SIGCHLD, SIG_IGN);
+       signal(SIGUSR1, sig_usr);
+       signal(SIGUSR2, sig_quit);
+       signal(SIGALRM, sig_break_block);
+
+       mainloop = g_main_loop_new(NULL, FALSE);
+       power_saving_func = default_saving_mode;
+
+       /* noti init for new input device like bt mouse */
+       int noti_fd;
+       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_settings();
+                               ret = init_sysfs(flags);
+                               break;
+                       case INIT_POLL:
+                               LOGINFO("poll init");
+                               ret = init_pm_poll(poll_callback);
+                               break;
+               }
+               if (ret != 0) {
+                       LOGERR(errMSG[i]);
+                       break;
+               }
+       }
+
+       if (i == INIT_END) {
+               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");
+                       cur_state = S_NORMAL;
+                       set_setting_pmstate(cur_state);
+                       reset_timeout(states[S_NORMAL].timeout);
+               }
+               if (start_battinfo_gathering(BATTERY_POLLING_PERIOD) < 0)
+                       LOGERR("Start Battery time info failed!");
+
+               g_main_loop_run(mainloop);
+               g_main_loop_unref(mainloop);
+       }
+
+       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("Terminate power manager daemon");
+}
+
+/**
+ * @}
+ */
diff --git a/pm_core.h b/pm_core.h
new file mode 100644 (file)
index 0000000..8df792a
--- /dev/null
+++ b/pm_core.h
@@ -0,0 +1,104 @@
+/*
+ * 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       pm_core.h
+ * @author     Suchang Woo (suchang.woo@samsung.com)
+ * @modified by Wonil Choi (wonil22.choi@samsung.com)
+ * @version    0.2
+ * @brief       Power manager main loop header file
+ */
+#ifndef __POWER_MANAGER_H__
+#define __POWER_MANAGER_H__
+
+#include "util.h"
+#include "pm_poll.h"
+#include "pm_llinterface.h"
+#include "pm_setting.h"
+#include "pm_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
+
+unsigned int 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
+ *   cur_state   : current state
+ *   states      : state definitions
+ *   trans_table : state transition table
+ */
+int cur_state;
+int 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_main(unsigned int flags);
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/pm_device_plugin.c b/pm_device_plugin.c
new file mode 100644 (file)
index 0000000..00663d6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 <dlfcn.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "pm_device_plugin.h"
+
+static void *dlopen_handle;
+
+int _pm_devman_plugin_init()
+{
+       char *error;
+
+       dlopen_handle = dlopen(DEVMAN_PLUGIN_PATH, RTLD_NOW);
+       if (!dlopen_handle) {
+               LOGERR("dlopen() failed");
+               return -1;
+       }
+
+       const OEM_sys_devman_plugin_interface *(*get_devman_plugin_interface) ();
+       get_devman_plugin_interface = dlsym(dlopen_handle, "OEM_sys_get_devman_plugin_interface");
+       if ((error = dlerror()) != NULL) {
+               LOGERR("dlsym() failed: %s", error);
+               dlclose(dlopen_handle);
+               return -1;
+       }
+
+       plugin_intf = get_devman_plugin_interface();
+       if (!plugin_intf) {
+               LOGERR("get_devman_plugin_interface() failed");
+               dlclose(dlopen_handle);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+int _pm_devman_plugin_fini()
+{
+       if (dlopen_handle) {
+               dlclose(dlopen_handle);
+       }
+
+       return 0;
+}
+
+
diff --git a/pm_device_plugin.h b/pm_device_plugin.h
new file mode 100644 (file)
index 0000000..1cf1b8e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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_DEVICE_PLUGIN_H__
+#define __PM_DEVICE_PLUGIN_H__
+
+#include "devman_plugin_intf.h"
+
+#define DEVMAN_PLUGIN_PATH      "/usr/lib/libslp_devman_plugin.so"
+
+int _pm_devman_plugin_init(void);
+int _pm_devman_plugin_fini(void);
+
+const OEM_sys_devman_plugin_interface *plugin_intf;
+
+#endif  /* __PM_DEVICE_PLUGIN_H__ */
diff --git a/pm_event/CMakeLists.txt b/pm_event/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2b69259
--- /dev/null
@@ -0,0 +1,30 @@
+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..14167af
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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"
+
+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 + 25];
+       snprintf(buf, PATH_MAX + 25, "echo %s %s >> %s", argv[1], argv[2], PM_EVENT_NOTI_PATH);
+       system(buf);
+
+       return 1;
+}
diff --git a/pm_key_filter.c b/pm_key_filter.c
new file mode 100644 (file)
index 0000000..2e282a9
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * 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 <glib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <vconf.h>
+#include <sysman.h>
+
+#include "util.h"
+#include "pm_core.h"
+#include "pm_poll.h"
+
+#include <linux/input.h>
+#ifndef KEY_SCREENLOCK
+#define KEY_SCREENLOCK         0x98
+#endif
+
+#define PREDEF_PWROFF_POPUP    "pwroff-popup"
+#define PREDEF_LEAVESLEEP      "leavesleep"
+#define PREDEF_POWEROFF                "poweroff"
+
+#define USEC_PER_SEC                   1000000
+#define LONG_PRESS_INTERVAL            1000000 /* 1000 ms */
+#define COMBINATION_INTERVAL           300000  /* 300 ms */
+#define POWER_KEY_PRESS_IGNORE_TIME    700000  /* 700 ms */
+
+#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 guint longkey_timeout_id = 0;
+static guint combination_timeout_id = 0;
+static int cancel_lcdoff;
+static int key_combination = KEY_COMBINATION_STOP;
+static int powerkey_ignored = false;
+
+void unlock()
+{
+       vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
+}
+
+static inline int current_state_in_on()
+{
+       return (cur_state == S_LCDDIM || cur_state == S_NORMAL);
+}
+
+static void longkey_pressed()
+{
+       int rc = -1, val = 0;
+       LOGINFO("Power key long pressed!");
+       cancel_lcdoff = 1;
+
+       rc = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val);
+
+       if (rc < 0 || val != 1) {
+               if (sysman_call_predef_action(PREDEF_PWROFF_POPUP, 0) <
+                               0)
+                       LOGERR("poweroff popup exec failed");
+       } else {
+               if (sysman_call_predef_action(PREDEF_POWEROFF, 0) < 0) {
+                       LOGERR("poweroff exec failed");
+                       system("poweroff");
+               }
+
+       }
+       (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
+}
+
+static gboolean longkey_pressed_cb(gpointer data)
+{
+       longkey_pressed();
+       longkey_timeout_id = 0;
+
+       return FALSE;
+}
+
+static gboolean combination_failed_cb(gpointer data)
+{
+       key_combination = KEY_COMBINATION_STOP;
+       combination_timeout_id = 0;
+
+       return 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()
+{
+       key_combination = KEY_COMBINATION_STOP;
+       if (combination_timeout_id > 0) {
+               g_source_remove(combination_timeout_id);
+               combination_timeout_id = 0;
+       }
+}
+
+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) {
+                       g_source_remove(longkey_timeout_id);
+                       longkey_timeout_id = 0;
+               }
+               break;
+       case KEY_PRESSED:
+               if (timediff_usec(pressed_time, pinput->time) <
+                   POWER_KEY_PRESS_IGNORE_TIME) {
+                       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 = g_timeout_add_full(
+                                       G_PRIORITY_DEFAULT,
+                                       LONG_PRESS_INTERVAL / 1000,
+                                       (GSourceFunc)longkey_pressed_cb,
+                                       NULL, NULL);
+                       key_combination = KEY_COMBINATION_START;
+                       combination_timeout_id = g_timeout_add_full(
+                                       G_PRIORITY_DEFAULT,
+                                       COMBINATION_INTERVAL / 1000,
+                                       (GSourceFunc)combination_failed_cb,
+                                       NULL, NULL);
+               } else if (key_combination == KEY_COMBINATION_START) {
+                       if (combination_timeout_id > 0) {
+                               g_source_remove(combination_timeout_id);
+                               combination_timeout_id = 0;
+                       }
+                       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)
+                       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 = g_timeout_add_full(
+                               G_PRIORITY_DEFAULT,
+                               COMBINATION_INTERVAL / 1000,
+                               (GSourceFunc)combination_failed_cb,
+                               NULL, NULL);
+               } else if (key_combination == KEY_COMBINATION_START) {
+                       if (combination_timeout_id > 0) {
+                               g_source_remove(combination_timeout_id);
+                               combination_timeout_id = 0;
+                       }
+                       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:
+               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;
+       }
+
+       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/pm_llinterface.c b/pm_llinterface.c
new file mode 100644 (file)
index 0000000..df4ffdc
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * 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 "pm_llinterface.h"
+#include "pm_device_plugin.h"
+#include "util.h"
+#include "pm_conf.h"
+#include "vconf.h"
+#include "pm_core.h"
+
+typedef struct _PMSys PMSys;
+struct _PMSys {
+       int def_brt;
+       int dim_brt;
+
+       int (*sys_power_state) (PMSys *, int);
+       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;
+
+#ifdef ENABLE_X_LCD_ONOFF
+#include "pm_x_lcd_onoff.c"
+static bool x_dpms_enable = false;
+#endif
+
+/*
+static void _update_curbrt(PMSys *p)
+{
+       int power_saving_stat = -1;
+       int power_saving_display_stat = -1;
+       vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
+       if (power_saving_stat == 1)
+               vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, &power_saving_display_stat);
+       if (power_saving_display_stat != 1)
+               power_saving_display_stat = 0;
+       plugin_intf->OEM_sys_get_backlight_brightness(DEFAULT_DISPLAY, &(p->def_brt), power_saving_display_stat);
+}
+*/
+
+static int _bl_onoff(PMSys *p, int onoff)
+{
+       return plugin_intf->OEM_sys_set_lcd_power(DEFAULT_DISPLAY, onoff);
+}
+
+static int _bl_brt(PMSys *p, int brightness)
+{
+       int power_saving_stat = -1;
+       int power_saving_display_stat = -1;
+       vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
+       if (power_saving_stat == 1)
+               vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, &power_saving_display_stat);
+       if (power_saving_display_stat != 1)
+               power_saving_display_stat = 0;
+       int ret = plugin_intf->OEM_sys_set_backlight_brightness(DEFAULT_DISPLAY, brightness, power_saving_display_stat);
+LOGERR("set brightness %d,%d(saving %d) %d", DEFAULT_DISPLAY, brightness, power_saving_display_stat, 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 plugin_intf->OEM_sys_set_power_state(state);
+}
+
+static int _sys_get_battery_capacity(PMSys *p)
+{
+       int value = 0;
+       int ret = -1;
+
+       ret = plugin_intf->OEM_sys_get_battery_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 = plugin_intf->OEM_sys_get_battery_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 = plugin_intf->OEM_sys_get_battery_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_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;
+}
+
+int system_suspend()
+{
+       LOGINFO("enter system suspend");
+       if (pmsys && pmsys->sys_power_state)
+               return pmsys->sys_power_state(pmsys, POWER_STATE_SUSPEND);
+
+       return 0;
+}
+
+int system_pre_suspend()
+{
+       LOGINFO("enter system pre suspend");
+       if (pmsys && pmsys->sys_power_state)
+               return pmsys->sys_power_state(pmsys, POWER_STATE_PRE_SUSPEND);
+
+       return 0;
+}
+
+int system_post_resume()
+{
+       LOGINFO("enter system post resume");
+       if (pmsys && pmsys->sys_power_state)
+               return pmsys->sys_power_state(pmsys, POWER_STATE_POST_RESUME);
+
+       return 0;
+}
+
+int battery_capacity()
+{
+       if (pmsys && pmsys->sys_get_battery_capacity)
+               return pmsys->sys_get_battery_capacity(pmsys);
+
+       return 0;
+}
+
+int battery_capacity_raw()
+{
+       if (pmsys && pmsys->sys_get_battery_capacity_raw)
+               return pmsys->sys_get_battery_capacity_raw(pmsys);
+
+       return 0;
+}
+
+int battery_charge_full()
+{
+       if (pmsys && pmsys->sys_get_battery_charge_full)
+               return pmsys->sys_get_battery_charge_full(pmsys);
+
+       return 0;
+}
+
+int backlight_on()
+{
+       LOGINFO("LCD on");
+
+       if (pmsys && pmsys->bl_onoff) {
+               return pmsys->bl_onoff(pmsys, STATUS_ON);
+       }
+
+       return 0;
+}
+
+int backlight_off()
+{
+       LOGINFO("LCD off");
+
+       if (pmsys && pmsys->bl_onoff) {
+#ifdef ENABLE_X_LCD_ONOFF
+               if (x_dpms_enable == false)
+#endif
+                       usleep(30000);
+               return pmsys->bl_onoff(pmsys, STATUS_OFF);
+       }
+
+       return 0;
+}
+
+int backlight_dim()
+{
+       int ret = 0;
+       if (pmsys && pmsys->bl_brt) {
+               ret = pmsys->bl_brt(pmsys, pmsys->dim_brt);
+       }
+       return ret;
+}
+
+int backlight_restore()
+{
+       int ret = 0;
+       int val = -1;
+
+       ret = vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &val);
+       if (ret == 0 && val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) {
+               LOGINFO("custom brightness mode! brt no restored");
+               return 0;
+       }
+       if ((status_flag & PWRSV_FLAG) && !(status_flag & BRTCH_FLAG))
+               ret = backlight_dim();
+       else if (pmsys && pmsys->bl_brt)
+               ret = pmsys->bl_brt(pmsys, pmsys->def_brt);
+
+       return ret;
+}
+
+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;
+}
+
+inline int check_wakeup_src(void)
+{
+       /*  TODO if nedded.
+        * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
+        */
+       return EVENT_DEVICE;
+}
+
+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;
+       }
+
+       return 0;
+}
+
+int exit_sysfs()
+{
+       int fd = -1;
+
+       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/pm_llinterface.h b/pm_llinterface.h
new file mode 100644 (file)
index 0000000..83b00d6
--- /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.
+*/
+
+
+/**
+ * @file       pm_llinterface.h
+ * @author     Suchang Woo (suchang.woo@samsung.com)
+ * @version    0.1
+ * @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
+
+/*
+ * 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);
+
+extern int system_suspend(void);
+
+extern int backlight_on(void);
+extern int backlight_off(void);
+
+extern int backlight_dim(void);
+extern int backlight_restore(void);
+
+extern int set_default_brt(int level);
+
+extern int check_wakeup_src(void);
+
+#endif
diff --git a/pm_lsensor.c b/pm_lsensor.c
new file mode 100644 (file)
index 0000000..71d6ddb
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * 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 <glib.h>
+#include <vconf.h>
+#include <sensor.h>
+
+#include "pm_core.h"
+#include "pm_device_plugin.h"
+
+#define SAMPLING_INTERVAL      1       /* 1 sec */
+#define MAX_FAULT                      5
+
+static int (*prev_init_extention) (void *data);
+static int (*_default_action) (int);
+static int alc_timeout_id = 0;
+static int sf_handle = -1;
+static int fault_count = 0;
+
+static gboolean alc_handler(gpointer data)
+{
+       int value = 0;
+       static int cur_index = 1;
+       static int old_index = 1;
+
+       sensor_data_t light_data;
+       if (cur_state != S_NORMAL){
+               if (alc_timeout_id != 0)
+                       g_source_remove(alc_timeout_id);
+               alc_timeout_id = 0;
+       } 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 power_saving_stat = -1;
+                               int power_saving_display_stat = -1;
+                               vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
+                               if (power_saving_stat == 1)
+                                       vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, &power_saving_display_stat);
+                               if (power_saving_display_stat != 1)
+                                       power_saving_display_stat = 0;
+                               value = PM_MAX_BRIGHTNESS * (int)light_data.values[0] / 10;
+                               plugin_intf->OEM_sys_get_backlight_brightness(DEFAULT_DISPLAY, &tmp_value, power_saving_display_stat);
+                               if (tmp_value != value) {
+                                       set_default_brt(value);
+                                       backlight_restore();
+                               }
+                               LOGINFO("load light data : %d, brightness : %d", (int)light_data.values[0], value);
+                       }
+               }
+       }
+
+       if (fault_count > MAX_FAULT) {
+               if (alc_timeout_id != 0)
+                       g_source_remove(alc_timeout_id);
+               alc_timeout_id = 0;
+               vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, SETTING_BRIGHTNESS_AUTOMATIC_OFF);
+               LOGERR("Fault counts is over 5, disable automatic brightness");
+               return FALSE;
+       }
+
+       if (alc_timeout_id != 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static int alc_action(int timeout)
+{
+       LOGINFO("alc action");
+       /* sampling timer add */
+       if (alc_timeout_id == 0 && !(status_flag & PWRSV_FLAG))
+               alc_timeout_id =
+                   g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+                                              SAMPLING_INTERVAL,
+                                              (GSourceFunc) alc_handler, NULL,
+                                              NULL);
+
+       if (_default_action != NULL)
+               return _default_action(timeout);
+
+       /* unreachable code */
+       return -1;
+}
+
+static int connect_sfsvc()
+{
+       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()
+{
+       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) {
+               g_source_remove(alc_timeout_id);
+               alc_timeout_id = 0;
+       }
+
+       return 0;
+}
+
+static inline void set_brtch_state()
+{
+       if (status_flag & PWRSV_FLAG) {
+               status_flag |= BRTCH_FLAG;
+               vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
+               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 =
+                   g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+                                              SAMPLING_INTERVAL,
+                                              (GSourceFunc) alc_handler, NULL,
+                                              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;
+               }
+
+               set_default_brt(default_brt);
+               backlight_restore();
+       }
+
+       return 0;
+}
+
+static gboolean check_sfsvc(gpointer 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 TRUE;
+
+               /* change alc action func */
+               if (_default_action == NULL)
+                       _default_action = states[S_NORMAL].action;
+               states[S_NORMAL].action = alc_action;
+               alc_timeout_id =
+                       g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+                                       SAMPLING_INTERVAL,
+                                       (GSourceFunc) alc_handler, NULL,
+                                       NULL);
+               if (alc_timeout_id != 0)
+                       return FALSE;
+               disconnect_sfsvc();
+               return TRUE;
+       }
+       LOGINFO("change vconf value before registering sfsvc");
+       return 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) {
+               g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+                               SAMPLING_INTERVAL,
+                               (GSourceFunc) check_sfsvc, NULL,
+                               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;
+}
+
+static void __attribute__ ((constructor)) pm_lsensor_init()
+{
+       _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()
+{
+
+}
diff --git a/pm_poll.c b/pm_poll.c
new file mode 100644 (file)
index 0000000..c91ca4d
--- /dev/null
+++ b/pm_poll.c
@@ -0,0 +1,301 @@
+/*
+ * 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       pm_poll.c
+ * @version    0.2
+ * @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 <glib.h>
+#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 "util.h"
+#include "pm_core.h"
+#include "pm_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 TRUE;\
+                                                       } while (0);
+
+#else
+#  define CHECK_KEY_FILTER(a, b)
+#endif
+
+#define DEFAULT_DEV_PATH "/dev/event1:/dev/event0"
+
+static GSource *src;
+static GSourceFuncs *funcs;
+static int sockfd;
+
+static gboolean pm_check(GSource *src)
+{
+       GSList *fd_list;
+       GPollFD *tmp;
+
+       fd_list = src->poll_fds;
+       do {
+               tmp = (GPollFD *) fd_list->data;
+               if ((tmp->revents & (POLLIN | POLLPRI)))
+                       return TRUE;
+               fd_list = fd_list->next;
+       } while (fd_list);
+
+       return FALSE;
+}
+
+static gboolean pm_dispatch(GSource *src, GSourceFunc callback, gpointer data)
+{
+       callback(data);
+       return TRUE;
+}
+
+static gboolean pm_prepare(GSource *src, gint *timeout)
+{
+       return FALSE;
+}
+
+gboolean pm_handler(gpointer data)
+{
+       char buf[1024];
+       struct sockaddr_un clientaddr;
+
+       GPollFD *gpollfd = (GPollFD *) data;
+       int ret;
+       int clilen = sizeof(clientaddr);
+
+       if (g_pm_callback == NULL) {
+               return FALSE;
+       }
+       if (gpollfd->fd == sockfd) {
+               ret =
+                   recvfrom(gpollfd->fd, &recv_data, sizeof(recv_data), 0,
+                            (struct sockaddr *)&clientaddr,
+                            (socklen_t *)&clilen);
+               (*g_pm_callback) (PM_CONTROL_EVENT, &recv_data);
+       } else {
+               ret = read(gpollfd->fd, buf, sizeof(buf));
+               CHECK_KEY_FILTER(ret, buf);
+               (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
+       }
+
+       return 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 *))
+{
+
+       guint ret;
+       char *dev_paths, *path_tok, *pm_input_env, *save_ptr;
+       int dev_paths_size;
+
+       GPollFD *gpollfd;
+
+       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;
+       }
+
+       funcs = (GSourceFuncs *) g_malloc(sizeof(GSourceFuncs));
+       funcs->prepare = pm_prepare;
+       funcs->check = pm_check;
+       funcs->dispatch = pm_dispatch;
+       funcs->finalize = NULL;
+
+       do {
+               src = g_source_new(funcs, sizeof(GSource));
+
+               gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
+               gpollfd->events = POLLIN;
+
+               if (strcmp(path_tok, SOCK_PATH) == 0) {
+                       gpollfd->fd = init_sock(SOCK_PATH);
+                       LOGINFO("pm_poll domain socket file: %s, fd: %d",
+                              path_tok, gpollfd->fd);
+               } else {
+                       gpollfd->fd = open(path_tok, O_RDONLY);
+                       LOGINFO("pm_poll input device file: %s, fd: %d",
+                              path_tok, gpollfd->fd);
+               }
+
+               if (gpollfd->fd == -1) {
+                       LOGERR("Cannot open the file: %s", path_tok);
+                       free(dev_paths);
+                       return -1;
+               }
+               g_source_add_poll(src, gpollfd);
+               g_source_set_callback(src, (GSourceFunc) pm_handler,
+                                     (gpointer) gpollfd, NULL);
+
+               g_source_set_priority(src, G_PRIORITY_LOW);
+               ret = g_source_attach(src, NULL);
+               if (ret == 0) {
+                       LOGERR("Failed g_source_attach() in init_pm_poll()");
+                       free(dev_paths);
+                       return -1;
+               }
+               g_source_unref(src);
+
+       } while ((path_tok = strtok_r(NULL, DEV_PATH_DLM, &save_ptr)));
+
+       free(dev_paths);
+       return 0;
+}
+
+int exit_pm_poll()
+{
+       g_free(funcs);
+       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)
+{
+       guint ret;
+       indev *adddev = NULL;
+
+       g_pm_callback = pm_callback;
+
+       GPollFD *gpollfd;
+       const char *devpath;
+       GSource *devsrc;
+
+       LOGINFO("initialize pm poll for bt %s",path);
+       adddev=(indev *)malloc(sizeof(indev));
+       adddev->dev_fd = (GPollFD *)g_malloc(sizeof(GPollFD));
+       (adddev->dev_fd)->events = POLLIN;
+       (adddev->dev_fd)->fd = open(path, O_RDONLY);
+       if((adddev->dev_fd)->fd == -1) {
+               LOGERR("Cannot open the file for BT: %s",path);
+               g_free(adddev->dev_fd);
+               free(adddev);
+               return -1;
+       }
+       adddev->dev_path = (char *)malloc(strlen(path) + 1);
+       strncpy(adddev->dev_path, path, strlen(path) + 1);
+       adddev->dev_src = g_source_new(funcs, sizeof(GSource));
+       LOGINFO("pm_poll for BT input device file(path: %s, gsource: %d, gpollfd: %d", adddev->dev_path, adddev->dev_src, adddev->dev_fd);
+       indev_list=g_list_append(indev_list, adddev);
+       
+       g_source_add_poll(adddev->dev_src, adddev->dev_fd);
+       
+       g_source_set_callback(adddev->dev_src, (GSourceFunc) pm_handler, (gpointer)adddev->dev_fd, NULL);
+       
+
+       g_source_set_priority(adddev->dev_src, G_PRIORITY_LOW );
+       
+       ret = g_source_attach(adddev->dev_src, NULL);
+       if(ret == 0)
+       {
+               LOGERR("Failed g_source_attach() in init_pm_poll()");
+               return -1;
+       }
+       g_source_unref(adddev->dev_src);
+       return 0;
+}
diff --git a/pm_poll.h b/pm_poll.h
new file mode 100644 (file)
index 0000000..d1fb454
--- /dev/null
+++ b/pm_poll.h
@@ -0,0 +1,74 @@
+/*
+ * 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       pm_poll.h
+ * @version    0.2
+ * @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<glib.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;
+} PMMsg;
+
+typedef struct {
+       char *dev_path;
+       GSource *dev_src;
+       GPollFD *dev_fd;
+} indev;
+
+GList *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/pm_setting.c b/pm_setting.c
new file mode 100644 (file)
index 0000000..c552edb
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 "pm_setting.h"
+#include "pm_conf.h"
+#include "util.h"
+
+static const char *setting_keys[SETTING_GET_END] = {
+       [SETTING_TO_NORMAL] = VCONFKEY_SETAPPL_LCD_TIMEOUT_NORMAL,
+       [SETTING_LOW_BATT] = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
+       [SETTING_CHARGING] = VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+       [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 (*update_setting) (int key_idx, int val);
+
+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, (int)data);
+               return -1;
+       }
+       if (update_setting != NULL) {
+               if ((int)data >= SETTING_POWER_SAVING)
+                       update_setting((int)data, vconf_keynode_get_bool(tmp));
+               else
+                       update_setting((int)data, vconf_keynode_get_int(tmp));
+       }
+
+       return 0;
+}
+
+int init_setting(int (*func) (int key_idx, int val))
+{
+       int i;
+
+       if (func != NULL)
+               update_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()
+{
+       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/pm_setting.h b/pm_setting.h
new file mode 100644 (file)
index 0000000..bf2b8e2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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       pm_setting.h
+ * @version    0.1
+ * @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_LOW_BATT,
+       SETTING_CHARGING,
+       SETTING_BRT_LEVEL,
+       SETTING_LOCK_SCREEN,
+       SETTING_POWER_SAVING,
+       SETTING_POWER_SAVING_DISPLAY,
+       SETTING_GET_END,
+       SETTING_PM_STATE = SETTING_GET_END,
+       SETTING_END
+};
+
+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/pm_x_lcd_onoff.c b/pm_x_lcd_onoff.c
new file mode 100644 (file)
index 0000000..01200ae
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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>
+
+#include "pm_device_plugin.h"
+
+#define CMD_ON         "on"
+#define CMD_OFF                "off"
+
+static int pm_x_set_lcd_backlight(struct _PMSys *p, int onoff)
+{
+       pid_t pid;
+       char cmd_line[32];
+       int ret;
+
+       LOGINFO("Backlight onoff=%d", onoff);
+       if (onoff == 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) {
+               LOGINFO("[1] Child proccess for LCD %s was created (%s)",
+                       ((onoff == 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__ */
diff --git a/pmctrl.in b/pmctrl.in
new file mode 100644 (file)
index 0000000..e6d8b5d
--- /dev/null
+++ b/pmctrl.in
@@ -0,0 +1,86 @@
+#!/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"
+
+case "$1" in
+       start)
+               if [ ! -e /opt/etc/.hib_capturing ]; then
+                       $PMD -d $OPT_X_DPMS
+               fi
+               ;;
+       stop)
+               if [ -e /var/run/power-manager.pid ] ; then
+                       kill -USR2 `cat /var/run/power-manager.pid`
+               fi
+               ;;
+       restart)
+               if [ -e /var/run/power-manager.pid ] ; then
+                       kill -USR2 `cat /var/run/power-manager.pid`
+                       # sleep 1 second to wait PID file get removed
+                       sleep 1
+               fi
+               if [ ! -e /opt/etc/.hib_capturing ]; then
+                       $PMD -d $OPT_X_DPMS
+               fi
+               ;;
+       log)
+               if [ -e /var/run/power-manager.pid ] ; then
+                       kill -HUP `cat /var/run/power-manager.pid`
+               fi
+               ;;
+       status)
+               echo "power manager is $([ ! -e /var/run/power-manager.pid ] &&
+                       echo "not ")running"
+               ;;
+       *)
+               echo "Usage: pmctrl {start | stop | restart | log | status}"
+               exit 1
+esac
+
+exit 0
+
diff --git a/udev-rules/91-power-manager.rules.in b/udev-rules/91-power-manager.rules.in
new file mode 100644 (file)
index 0000000..45ffb59
--- /dev/null
@@ -0,0 +1,7 @@
+#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"
+
diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..9368295
--- /dev/null
+++ b/util.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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
+ * @version    0.1
+ * @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>
+
+#ifdef ENABLE_DLOG_OUT
+#define LOG_TAG                "POWER_MANAGER"
+#endif
+
+#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);
+#ifdef ENABLE_DLOG_OUT
+       switch (priority) {
+       case DLOG_DEBUG:
+               SLOGD("%s", buf);
+               break;
+       case DLOG_ERROR:
+               SLOGE("%s", buf);
+               break;
+       case DLOG_INFO:
+               SLOGI("%s", buf);
+               break;
+       default:
+               SLOGV("%s", buf);
+               break;
+       }
+#else
+       syslog(priority, "%s", buf);
+#endif
+       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) {
+               fscanf(fp, "%5d", &ret);
+               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;
+
+       pid = fork();
+       if (pid < 0)
+               return -1;
+       else if (pid != 0)
+               exit(0);
+
+       setsid();
+       chdir("/");
+
+       close(0);
+       close(1);
+       close(2);
+
+       open("/dev/null", O_RDONLY);
+       open("/dev/null", O_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/util.h b/util.h
new file mode 100644 (file)
index 0000000..de05fcf
--- /dev/null
+++ b/util.h
@@ -0,0 +1,110 @@
+/*
+ * 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
+ * @version    0.1
+ * @brief      Utilities header for Power manager
+ */
+#ifndef __DEF_UTIL_H__
+#define __DEF_UTIL_H__
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+/*
+ * @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>
+/*
+ * @brief LOG_INFO wrapper
+ */
+#  define LOGINFO(fmt, arg...) pm_log(DLOG_INFO, fmt, ## arg)
+
+/*
+ * @brief LOG_ERR wrapper
+ */
+#  define LOGERR(fmt, arg...) pm_log(DLOG_ERROR, fmt, ## arg)
+#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