ADD_SUBDIRECTORY(plugins/mobile/display)
ADD_SUBDIRECTORY(plugins/wearable/display)
ADD_SUBDIRECTORY(plugins/tv/display)
+ADD_SUBDIRECTORY(plugins/iot/display)
%description plugin-profile-tv
Plugin libraries for TV devices
+%package plugin-profile-iot
+Summary: Plugin libraries for IoT devices
+Group: System/Management
+Requires: %{name} = %{version}-%{release}
+
+%description plugin-profile-iot
+Plugin libraries for IoT devices
+
%prep
%setup -q
mkdir -p %{_libdir}/deviced
mv %{_libdir}/tv-display.so %{_libdir}/deviced/display.so
+%post plugin-profile-iot
+mkdir -p %{_libdir}/deviced
+mv %{_libdir}/iot-display.so %{_libdir}/deviced/display.so
+
%files
%manifest %{name}.manifest
%license LICENSE.Apache-2.0
%license LICENSE.Apache-2.0
%defattr(-,root,root,-)
%{_libdir}/tv-display.so
+
+%files plugin-profile-iot
+%manifest deviced.manifest
+%license LICENSE.Apache-2.0
+%defattr(-,root,root,-)
+%{_libdir}/iot-display.so
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(iot-display C)
+
+FILE(GLOB ALL_SRCS "*.c")
+SET(SRCS ${ALL_SRCS})
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/core ${CMAKE_SOURCE_DIR}/src/display)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(libpkgs REQUIRED
+ dlog
+ glib-2.0
+ gio-2.0
+ gio-unix-2.0
+ libinput
+ capi-system-sensor)
+
+FOREACH(flag ${libpkgs_CFLAGS})
+ SET(EXTRA_LIB_CFLAGS "${EXTRA_LIB_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_LIB_CFLAGS}")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${libpkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME iot-display)
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2017 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 <fcntl.h>
+#include <libgdbus/dbus-system.h>
+
+#include "util.h"
+#include "core.h"
+#include "display-ops.h"
+#include "core/device-notifier.h"
+#include "core/devices.h"
+
+#define ON "on"
+#define OFF "off"
+
+#define SIGNAL_AMBIENT_MODE "AmbientMode"
+#define CLOCK_START "clockstart"
+#define CLOCK_END "clockend"
+#define TIMEOUT_NONE (-1)
+#define AMBIENT_CLOCK_WAITING_TIME 5000 /* ms */
+
+extern struct display_plugin disp_plgn;
+static int ambient_state;
+static pid_t ambient_pid; /* Ambient Clock pid */
+static int ambient_condition;
+static unsigned int update_count;
+
+void broadcast_ambient_state(int state)
+{
+ dbus_handle_broadcast_dbus_signal_var(DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ SIGNAL_AMBIENT_MODE,
+ g_variant_new("(i)", (state == 0 ? 0 : 1)));
+}
+
+int ambient_get_condition(void)
+{
+ return ambient_condition;
+}
+
+int ambient_get_state(void)
+{
+ return ambient_state;
+}
+
+static void ambient_set_condition(keynode_t *key_nodes, void *data)
+{
+ int state;
+
+ if (key_nodes == NULL) {
+ _E("wrong parameter, key_nodes is null");
+ return;
+ }
+
+ ambient_condition = vconf_keynode_get_bool(key_nodes);
+ _I("ambient mode condition is %d", ambient_condition);
+
+ state = (ambient_condition == 0 ? 0 : 1);
+ device_notify(DEVICE_NOTIFIER_DISPLAY_AMBIENT_CONDITION, (void *)&state);
+
+ set_dim_state(state);
+}
+
+int ambient_set_state(int on)
+{
+ if (!ambient_condition)
+ return 0;
+
+ broadcast_ambient_state(on);
+
+ update_count = 0;
+
+ if (!on)
+ ambient_pid = 0;
+
+ _D("AMBIENT is %s", (on ? ON : OFF));
+
+ ambient_state = on;
+
+ device_notify(DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE, (void *)&ambient_state);
+
+ return 0;
+}
+
+void ambient_check_invalid_state(pid_t pid)
+{
+ if (pid != INTERNAL_LOCK_AMBIENT)
+ return;
+
+ if (backlight_ops.get_lcd_power() == DPMS_OFF)
+ return;
+
+ if (is_emulator()) {
+ /* In emulator, deviced does not turn off the display. */
+ if (backlight_ops.get_lcd_power() == DPMS_ON)
+ return;
+ }
+
+ if (ambient_get_state() == false)
+ return;
+
+ _E("Invalid state! Ambient state is change to off!");
+
+ /* If lcd_power is on and ambient state is true
+ * when pm state is changed to sleep,
+ * deviced doesn't get the clock signal.
+ * deviced just turns off lcd in this case. */
+
+ ambient_set_state(false);
+ backlight_ops.off(NORMAL_MODE);
+}
+
+static void start_clock(void)
+{
+ if (pm_cur_state == S_NORMAL ||
+ pm_cur_state == S_LCDDIM ||
+ ambient_state == false)
+ return;
+
+ if (disp_plgn.pm_lock_internal)
+ disp_plgn.pm_lock_internal(INTERNAL_LOCK_AMBIENT, LCD_OFF, STAY_CUR_STATE,
+ AMBIENT_CLOCK_WAITING_TIME);
+}
+
+static void end_clock(pid_t pid)
+{
+ if (pm_cur_state == S_NORMAL ||
+ pm_cur_state == S_LCDDIM ||
+ ambient_state == false)
+ return;
+
+ if (update_count == 0)
+ broadcast_lcd_off_late(LCD_OFF_LATE_MODE);
+
+ if (disp_plgn.pm_unlock_internal)
+ disp_plgn.pm_unlock_internal(INTERNAL_LOCK_AMBIENT, LCD_OFF, PM_SLEEP_MARGIN);
+
+ update_count++;
+ if (update_count == UINT_MAX)
+ update_count = 1;
+ ambient_pid = pid;
+
+ _I("enter real ambient state by %d",
+ ambient_pid);
+}
+
+int ambient_set_screen(char *screen, pid_t pid)
+{
+ if (!screen)
+ return -EINVAL;
+
+ if (!strncmp(screen, CLOCK_START, strlen(CLOCK_START)))
+ start_clock();
+ else if (!strncmp(screen, CLOCK_END, strlen(CLOCK_END)))
+ end_clock(pid);
+
+ return 0;
+}
+
+static void ambient_init(void *data)
+{
+ int ret;
+
+ ret = vconf_get_bool(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ &ambient_condition);
+ if (ret < 0) {
+ _E("Failed to get ambient mode condition ! (%d)", ret);
+ ambient_condition = false;
+ }
+ _I("ambient mode condition is %d", ambient_condition);
+
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ ambient_set_condition, NULL);
+}
+
+static void ambient_exit(void *data)
+{
+ ambient_set_state(false);
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ ambient_set_condition);
+}
+
+static const struct display_ops ambient_ops = {
+ .name = "ambient",
+ .init = ambient_init,
+ .exit = ambient_exit,
+};
+
+DISPLAY_OPS_REGISTER(&ambient_ops)
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 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 <math.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <vconf.h>
+#include <sensor.h>
+
+
+#include "util.h"
+#include "core.h"
+#include "display-ops.h"
+#include "device-node.h"
+#include "setting.h"
+#include "core/device-notifier.h"
+#include "core/config-parser.h"
+
+#define METHOD_CHECK_SUPPORTED "CheckSupported"
+
+#define DISP_FORCE_SHIFT 12
+#define DISP_FORCE_CMD(prop, force) (((force) << DISP_FORCE_SHIFT) | prop)
+
+#define SAMPLING_INTERVAL 1 /* 1 sec */
+#define MAX_SAMPLING_COUNT 3
+#define MAX_FAULT 5
+#define DEFAULT_AUTOMATIC_BRT 5
+#define AUTOMATIC_DEVIDE_VAL 10
+#define AUTOMATIC_DELAY_TIME 0.5 /* 0.5 sec */
+
+#define RADIAN_VALUE (57.2957)
+#define ROTATION_90 90
+#define WORKING_ANGLE_MIN 0
+#define WORKING_ANGLE_MAX 20
+
+#define BOARD_CONF_FILE "/etc/deviced/display.conf"
+
+#define ON_LUX -1
+#define OFF_LUX -1
+#define ON_COUNT 1
+#define OFF_COUNT 1
+
+static int (*_default_action) (int);
+static guint alc_timeout_id = 0;
+static guint update_timeout;
+static sensor_listener_h light_listener;
+static sensor_listener_h accel_listener;
+static int fault_count;
+static int automatic_brt = DEFAULT_AUTOMATIC_BRT;
+static int min_brightness = PM_MIN_BRIGHTNESS;
+static char *min_brightness_name = 0;
+
+/* light sensor */
+static float lmax, lmin;
+
+static bool update_working_position(void)
+{
+ sensor_event_s data;
+ int ret;
+ float x, y, z, pitch, realg;
+
+ if (!display_conf.accel_sensor_on)
+ return false;
+
+ ret = sensor_listener_read_data(accel_listener, &data);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Fail to get accelerometer data! %d", ret);
+ return true;
+ }
+
+ x = data.values[0];
+ y = data.values[1];
+ z = data.values[2];
+
+ realg = (float)sqrt((x * x) + (y * y) + (z * z));
+ pitch = ROTATION_90 - abs((int) (asin(z / realg) * RADIAN_VALUE));
+
+ _D("accel data [%f, %f, %f] - %f", x, y, z, pitch);
+
+ if (pitch >= WORKING_ANGLE_MIN && pitch <= WORKING_ANGLE_MAX)
+ return true;
+ return false;
+}
+
+static void alc_set_brightness(int setting, int value, float light)
+{
+ static float old;
+ int position, tmp_value = 0, ret;
+
+ ret = backlight_ops.get_brightness(&tmp_value);
+ if (ret < 0) {
+ _E("Fail to get display brightness!");
+ return;
+ }
+
+ if (value < min_brightness)
+ value = min_brightness;
+
+ if (tmp_value != value) {
+ if (!setting && min_brightness == PM_MIN_BRIGHTNESS &&
+ display_conf.accel_sensor_on == true) {
+ position = update_working_position();
+ if (!position && (old > light)) {
+ _D("It's not working position, "
+ "LCD isn't getting dark!");
+ return;
+ }
+ }
+ int diff, step;
+
+ diff = value - tmp_value;
+ if (abs(diff) < display_conf.brightness_change_step)
+ step = (diff > 0 ? 1 : -1);
+ else
+ step = (int)ceil(diff /
+ (float)display_conf.brightness_change_step);
+
+ _D("%d", step);
+ while (tmp_value != value) {
+ if (step == 0) break;
+
+ tmp_value += step;
+ if ((step > 0 && tmp_value > value) ||
+ (step < 0 && tmp_value < value))
+ tmp_value = value;
+
+ backlight_ops.set_default_brt(tmp_value);
+ backlight_ops.update();
+ }
+ _I("load light data:%f ,auto brt %d,min brightness %d,"
+ "brightness %d", light, automatic_brt, min_brightness, value);
+ old = light;
+ }
+}
+
+static bool check_brightness_changed(int value)
+{
+ int i;
+ static int values[MAX_SAMPLING_COUNT], count = 0;
+
+ if (count >= MAX_SAMPLING_COUNT || count < 0)
+ count = 0;
+
+ values[count++] = value;
+
+ for (i = 0; i < MAX_SAMPLING_COUNT - 1; i++)
+ if (values[i] != values[i+1])
+ return false;
+ return true;
+}
+
+static bool alc_update_brt(bool setting)
+{
+ int value = 0;
+ int ret = -1;
+ sensor_event_s light_data;
+ int index;
+ float light;
+
+ ret = sensor_listener_read_data(light_listener, &light_data);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to read light sensor data(%d)", ret);
+ goto out;
+ }
+
+ index = light_data.value_count - 1;
+ if (index < 0 || light_data.values[index] < 0) {
+ _E("Invalid light sensor data");
+ goto out;
+ }
+
+ light = light_data.values[index];
+ ret = backlight_ops.get_brightness_by_light_sensor(
+ lmax, lmin, light, &value);
+ if (ret == -ENOTSUP) {
+ _E("Not supported to handle the light data");
+ goto out;
+ }
+
+ if (ret < 0 || value < PM_MIN_BRIGHTNESS || value > PM_MAX_BRIGHTNESS) {
+ _E("fail to load light data : light(%f), value(%d), ret(%d)", light, value, ret);
+ goto out;
+ }
+
+ fault_count = 0;
+
+ if (display_conf.continuous_sampling &&
+ !check_brightness_changed(value) &&
+ !setting)
+ return true;
+
+ alc_set_brightness(setting, value, light);
+
+ return true;
+
+out:
+ fault_count++;
+
+ if ((fault_count > MAX_FAULT) && !(pm_status_flag & PWROFF_FLAG)) {
+ if (alc_timeout_id) {
+ g_source_remove(alc_timeout_id);
+ alc_timeout_id = 0;
+ }
+ vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ SETTING_BRIGHTNESS_AUTOMATIC_OFF);
+ _E("Fault counts is over %d, disable automatic brightness", MAX_FAULT);
+ return false;
+ }
+ return true;
+}
+
+static gboolean alc_handler(void *data)
+{
+ if (pm_cur_state != S_NORMAL) {
+ if (alc_timeout_id > 0)
+ g_source_remove(alc_timeout_id);
+ alc_timeout_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ if (!alc_update_brt(false))
+ return G_SOURCE_REMOVE;
+
+ if (alc_timeout_id != 0)
+ return G_SOURCE_CONTINUE;
+
+ return G_SOURCE_REMOVE;
+}
+
+static int alc_action(int timeout)
+{
+ /* sampling timer add */
+ if (alc_timeout_id == 0 && !(pm_status_flag & PWRSV_FLAG)) {
+ display_info.update_auto_brightness(true);
+
+ alc_timeout_id =
+ g_timeout_add_seconds(display_conf.lightsensor_interval,
+ alc_handler, NULL);
+ }
+
+ if (_default_action != NULL)
+ return _default_action(timeout);
+
+ /* unreachable code */
+ return -1;
+}
+
+static int connect_sensor(void)
+{
+ int ret;
+ sensor_h sensor;
+ sensor_h *list = NULL;
+ int cnt = 0;
+
+ _I("connect with sensor fw");
+ /* light sensor */
+ ret = sensor_get_sensor_list(SENSOR_LIGHT, &list, &cnt);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to get light sensor list(%d)", ret);
+ goto error;
+ }
+
+ /* TODO
+ * Sensor apis will be fixed
+ * to provide which sensor is effective among sensors */
+ if (cnt == 3) /* three light sensors exist */
+ sensor = list[2];
+ else
+ sensor = list[0];
+
+ free(list);
+
+ ret = sensor_get_min_range(sensor, &lmin);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to get light sensor min range (%d)", ret);
+ goto error;
+ }
+ ret = sensor_get_max_range(sensor, &lmax);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to get light sensor max range (%d)", ret);
+ goto error;
+ }
+ _I("Light sensor min(%f), max(%f)", lmin, lmax);
+
+ ret = sensor_create_listener(sensor, &light_listener);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to create listener(light)!");
+ goto error;
+ }
+ sensor_listener_set_option(light_listener, SENSOR_OPTION_ALWAYS_ON);
+ ret = sensor_listener_start(light_listener);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to start light sensor!");
+ sensor_destroy_listener(light_listener);
+ light_listener = 0;
+ goto error;
+ }
+
+ if (!display_conf.accel_sensor_on)
+ goto success;
+
+ /* accelerometer sensor */
+ ret = sensor_get_default_sensor(SENSOR_ACCELEROMETER, &sensor);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to get default accel sensor!");
+ goto error;
+ }
+ ret = sensor_create_listener(&sensor, &accel_listener);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to create listener(accel)!");
+ goto error;
+ }
+ sensor_listener_set_option(accel_listener, SENSOR_OPTION_ALWAYS_ON);
+ ret = sensor_listener_start(accel_listener);
+ if (ret != SENSOR_ERROR_NONE) {
+ _E("Failed to start accel sensor!");
+ sensor_destroy_listener(accel_listener);
+ accel_listener = 0;
+ goto error;
+ }
+
+success:
+ fault_count = 0;
+ return 0;
+
+error:
+ if (light_listener > 0) {
+ sensor_listener_stop(light_listener);
+ sensor_destroy_listener(light_listener);
+ light_listener = 0;
+ }
+ if (display_conf.accel_sensor_on && accel_listener > 0) {
+ sensor_listener_stop(accel_listener);
+ sensor_destroy_listener(accel_listener);
+ accel_listener = 0;
+ }
+ return -EIO;
+}
+
+static int disconnect_sensor(void)
+{
+ _I("disconnect with sensor fw");
+ /* light sensor*/
+ if (light_listener > 0) {
+ sensor_listener_stop(light_listener);
+ sensor_destroy_listener(light_listener);
+ light_listener = 0;
+ }
+
+ /* accelerometer sensor*/
+ if (display_conf.accel_sensor_on && accel_listener > 0) {
+ sensor_listener_stop(accel_listener);
+ sensor_destroy_listener(accel_listener);
+ accel_listener = 0;
+ }
+
+ 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;
+}
+
+void set_brightness_changed_state(void)
+{
+ if (pm_status_flag & PWRSV_FLAG) {
+ pm_status_flag |= BRTCH_FLAG;
+ _D("brightness changed in low battery,"
+ "escape dim state (light)");
+ }
+}
+
+static int set_autobrightness_state(int status)
+{
+ int ret = -1;
+ int brt = -1;
+ int default_brt = -1;
+
+ if (status == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
+ if (connect_sensor() < 0)
+ return -1;
+
+ /* escape dim state if it's in low battery.*/
+ set_brightness_changed_state();
+
+ /* change alc action func */
+ if (_default_action == NULL)
+ _default_action = states[S_NORMAL].action;
+ states[S_NORMAL].action = alc_action;
+
+ display_info.update_auto_brightness(true);
+
+ alc_timeout_id =
+ g_timeout_add_seconds(display_conf.lightsensor_interval,
+ alc_handler, NULL);
+ } else if (status == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) {
+ _I("auto brightness paused!");
+ disconnect_sensor();
+ } else {
+ disconnect_sensor();
+ /* escape dim state if it's in low battery.*/
+ set_brightness_changed_state();
+
+ ret = get_setting_brightness(&default_brt);
+ if (ret != 0 || (default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)) {
+ _I("fail to read vconf value for brightness");
+ brt = PM_DEFAULT_BRIGHTNESS;
+ if (default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)
+ vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
+ default_brt = brt;
+ }
+
+ backlight_ops.set_default_brt(default_brt);
+ backlight_ops.update();
+ }
+
+ return 0;
+}
+
+static void set_alc_function(keynode_t *key_nodes, void *data)
+{
+ int status, ret;
+
+ if (key_nodes == NULL) {
+ _E("wrong parameter, key_nodes is null");
+ return;
+ }
+
+ status = vconf_keynode_get_int(key_nodes);
+
+ switch (status) {
+ case SETTING_BRIGHTNESS_AUTOMATIC_OFF:
+ case SETTING_BRIGHTNESS_AUTOMATIC_ON:
+ case SETTING_BRIGHTNESS_AUTOMATIC_PAUSE:
+ ret = set_autobrightness_state(status);
+ _D("set auto brightness : %d", ret);
+ break;
+ default:
+ _E("invalid value! %d", status);
+ }
+}
+
+static void set_alc_automatic_brt(keynode_t *key_nodes, void *data)
+{
+ if (key_nodes == NULL) {
+ _E("wrong parameter, key_nodes is null");
+ return;
+ }
+ automatic_brt = vconf_keynode_get_int(key_nodes) / AUTOMATIC_DEVIDE_VAL;
+ _D("automatic brt : %d", automatic_brt);
+
+ alc_update_brt(true);
+}
+
+static gboolean update_handler(void *data)
+{
+ int ret, on;
+
+ update_timeout = 0;
+
+ if (pm_cur_state != S_NORMAL)
+ return G_SOURCE_REMOVE;
+
+ ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &on);
+ if (ret < 0 || on != SETTING_BRIGHTNESS_AUTOMATIC_ON)
+ return G_SOURCE_REMOVE;
+
+ _D("auto brightness is working!");
+ alc_update_brt(true);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void update_auto_brightness(bool update)
+{
+ if (update_timeout) {
+ g_source_remove(update_timeout);
+ update_timeout = 0;
+ }
+
+ if (update) {
+ update_timeout = g_timeout_add_seconds(AUTOMATIC_DELAY_TIME,
+ update_handler, NULL);
+ }
+}
+
+static int prepare_lsensor(void *data)
+{
+ int status, ret;
+ int brt = -1;
+
+ ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
+
+ if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON)
+ set_autobrightness_state(status);
+
+ /* add auto_brt_setting change handler */
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ set_alc_function, NULL);
+
+ vconf_get_int(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS, &brt);
+ if (brt < PM_MIN_BRIGHTNESS || brt > PM_MAX_BRIGHTNESS) {
+ _E("Failed to get automatic brightness!");
+ } else {
+ automatic_brt = brt / AUTOMATIC_DEVIDE_VAL;
+ _I("automatic brt init success %d", automatic_brt);
+ }
+
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS,
+ set_alc_automatic_brt, NULL);
+
+ return 0;
+}
+
+static void update_brightness_direct(void)
+{
+ int ret, status;
+
+ ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
+ if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON)
+ alc_update_brt(true);
+}
+
+static int set_autobrightness_min(int val, char *name)
+{
+ if (!name)
+ return -EINVAL;
+
+ if (val < PM_MIN_BRIGHTNESS || val > PM_MAX_BRIGHTNESS)
+ return -EINVAL;
+
+ min_brightness = val;
+
+ if (min_brightness_name) {
+ free(min_brightness_name);
+ min_brightness_name = 0;
+ }
+ min_brightness_name = strndup(name, strlen(name));
+
+ update_brightness_direct();
+
+ _I("auto brightness min value changed! (%d, %s)",
+ min_brightness, min_brightness_name);
+
+ return 0;
+}
+
+static void reset_autobrightness_min(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *unique_name,
+ gpointer data)
+{
+ if (!sender)
+ return;
+
+ if (!min_brightness_name)
+ return;
+
+ if (strcmp(sender, min_brightness_name))
+ return;
+
+ _I("change to default %d -> %d, %s", min_brightness,
+ PM_MIN_BRIGHTNESS, min_brightness_name);
+ min_brightness = PM_MIN_BRIGHTNESS;
+ if (min_brightness_name) {
+ free(min_brightness_name);
+ min_brightness_name = 0;
+ }
+
+ update_brightness_direct();
+}
+
+static int lcd_changed_cb(void *data)
+{
+ int lcd_state;
+
+ if (!data)
+ return 0;
+ lcd_state = *(int *)data;
+ if (lcd_state == S_LCDOFF && alc_timeout_id > 0) {
+ g_source_remove(alc_timeout_id);
+ alc_timeout_id = 0;
+ }
+
+ return 0;
+}
+
+static int booting_done_cb(void *data)
+{
+ int state;
+
+ if (!data)
+ return 0;
+
+ state = *(int *)data;
+ if (state != true)
+ return 0;
+
+ /* get light data from sensor fw */
+ prepare_lsensor(NULL);
+
+ return 0;
+}
+
+static void exit_lsensor(void)
+{
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ set_alc_function);
+
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS,
+ set_alc_automatic_brt);
+
+ set_autobrightness_state(SETTING_BRIGHTNESS_AUTOMATIC_OFF);
+}
+
+static void auto_brightness_init(void *data)
+{
+ display_info.update_auto_brightness = update_auto_brightness;
+ display_info.set_autobrightness_min = set_autobrightness_min;
+ display_info.reset_autobrightness_min = reset_autobrightness_min;
+
+ register_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb);
+ register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done_cb);
+}
+
+static void auto_brightness_exit(void *data)
+{
+ exit_lsensor();
+
+ unregister_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb);
+ unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done_cb);
+}
+
+static const struct display_ops display_autobrightness_ops = {
+ .name = "auto-brightness",
+ .init = auto_brightness_init,
+ .exit = auto_brightness_exit,
+};
+
+DISPLAY_OPS_REGISTER(&display_autobrightness_ops)
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @file core.c
+ * @brief Power manager main loop.
+ *
+ * This file includes Main loop, the FSM, signal processing.
+ */
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <vconf-keys.h>
+#include <sys/time.h>
+#include <tzplatform_config.h>
+#include <libgdbus/dbus-system.h>
+
+#include "ambient-mode.h"
+#include "util.h"
+#include "core.h"
+#include "device-node.h"
+#include "lock-detector.h"
+#include "display-ops.h"
+#include "core/devices.h"
+#include "core/device-notifier.h"
+#include "core/udev.h"
+#include "core/list.h"
+#include "core/common.h"
+#include "battery/battery.h"
+#include "shared/plugin.h"
+#include "core/config-parser.h"
+#include "core/launch.h"
+#include "extcon/extcon.h"
+#include "power/power-handler.h"
+#include "dd-display.h"
+
+#define PM_STATE_LOG_FILE tzplatform_mkpath(TZ_SYS_ALLLOGS, "pm_state.log")
+#define DISPLAY_CONF_FILE "/etc/deviced/display.conf"
+
+/**
+ * @addtogroup POWER_MANAGER
+ * @{
+ */
+
+#define SET_BRIGHTNESS_IN_BOOTLOADER "/usr/bin/save_blenv SLP_LCD_BRIGHT"
+#define LOCK_SCREEN_INPUT_TIMEOUT 10000
+#define LOCK_SCREEN_CONTROL_TIMEOUT 5000
+#define DD_LCDOFF_INPUT_TIMEOUT 3000
+#define ALWAYS_ON_TIMEOUT 3600000 //3600000 = 1 hour
+
+#define GESTURE_STR "gesture"
+#define POWER_KEY_STR "powerkey"
+#define TOUCH_STR "touch"
+#define EVENT_STR "event"
+#define TIMEOUT_STR "timeout"
+#define UNKNOWN_STR "unknown"
+
+extern void init_pm_internal();
+extern struct display_plugin disp_plgn;
+unsigned int pm_status_flag;
+static int trans_condition;
+
+static void (*power_saving_func) (int onoff);
+static enum device_ops_status status = DEVICE_OPS_STATUS_UNINIT;
+
+int pm_cur_state;
+int pm_old_state;
+guint timeout_src_id;
+static unsigned int custom_normal_timeout = 0;
+static unsigned int custom_dim_timeout = 0;
+static int custom_holdkey_block = false;
+static int custom_change_pid = -1;
+static char *custom_change_name;
+static bool hallic_open = true;
+static guint lock_timeout_id;
+static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT;
+static struct timeval lcdon_tv;
+static int lcd_paneloff_mode = false;
+static int stay_touchscreen_off = false;
+static dd_list *lcdon_ops;
+static bool lcdon_broadcast = true;
+static bool touch_blocked = false;
+
+/* default transition, action fuctions */
+static int default_trans(int evt);
+static int default_action(int timeout);
+static int default_check(int curr, int next);
+
+static gboolean del_normal_cond(void *data);
+static gboolean del_dim_cond(void *data);
+static gboolean del_off_cond(void *data);
+
+static int default_proc_change_state(unsigned int cond, pid_t pid);
+static int (*proc_change_state)(unsigned int cond, pid_t pid) = default_proc_change_state;
+
+struct state states[S_END] = {
+ { S_START, "S_START", NULL, NULL, NULL, NULL },
+ { S_NORMAL, "S_NORMAL", default_trans, default_action, default_check, del_normal_cond },
+ { S_LCDDIM, "S_LCDDIM", default_trans, default_action, default_check, del_dim_cond },
+ { S_LCDOFF, "S_LCDOFF", default_trans, default_action, default_check, del_off_cond },
+ { S_STANDBY, "S_STANDBY", NULL, NULL, NULL, NULL },
+ { S_SLEEP, "S_SLEEP", default_trans, default_action, default_check, NULL },
+ { S_POWEROFF, "S_POWEROFF", NULL, NULL, NULL, NULL },
+};
+
+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 */
+ { S_SLEEP, S_NORMAL }, /* S_LCDOFF */
+ { S_SLEEP, S_STANDBY }, /* S_STANDBY */
+ { S_LCDOFF, S_NORMAL }, /* S_SLEEP */
+ { S_POWEROFF, S_POWEROFF }, /* S_POWEROFF */
+};
+
+enum signal_type {
+ SIGNAL_INVALID = 0,
+ SIGNAL_PRE,
+ SIGNAL_POST,
+ SIGNAL_MAX,
+};
+
+static const char *lcdon_sig_lookup[SIGNAL_MAX] = {
+ [SIGNAL_PRE] = "LCDOn",
+ [SIGNAL_POST] = "LCDOnCompleted",
+};
+static const char *lcdoff_sig_lookup[SIGNAL_MAX] = {
+ [SIGNAL_PRE] = "LCDOff",
+ [SIGNAL_POST] = "LCDOffCompleted",
+};
+
+#define SHIFT_UNLOCK 4
+#define SHIFT_CHANGE_STATE 7
+#define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */
+#define SHIFT_LOCK_FLAG 16
+#define SHIFT_CHANGE_TIMEOUT 20
+#define CUSTOM_TIMEOUT_BIT 0x1
+#define CUSTOM_HOLDKEY_BIT 0x2
+#define HOLD_KEY_BLOCK_BIT 0x1
+#define TIMEOUT_NONE (-1)
+
+#define S_COVER_TIMEOUT 8000
+#define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_LOCK_FLAG) & HOLD_KEY_BLOCK_BIT)
+#define BOOTING_DONE_WATING_TIME 60000 /* 1 minute */
+#define LOCK_TIME_WARNING 60 /* 60 seconds */
+
+#define ACTIVE_ACT "active"
+#define INACTIVE_ACT "inactive"
+
+#define LOCK_SCREEN_WATING_TIME 0.3 /* 0.3 second */
+#define LONG_PRESS_INTERVAL 2 /* 2 seconds */
+#define SAMPLING_INTERVAL 1 /* 1 sec */
+#define BRIGHTNESS_CHANGE_STEP 10
+#define LCD_ALWAYS_ON 1
+#define ACCEL_SENSOR_ON 1
+#define CONTINUOUS_SAMPLING 1
+#define LCDOFF_TIMEOUT 500 /* milli second */
+
+#define DIFF_TIMEVAL_MS(a, b) \
+ (((a.tv_sec * 1000000 + a.tv_usec) - \
+ (b.tv_sec * 1000000 + b.tv_usec)) \
+ / 1000)
+
+struct display_config display_conf = {
+ .lock_wait_time = LOCK_SCREEN_WATING_TIME,
+ .longpress_interval = LONG_PRESS_INTERVAL,
+ .lightsensor_interval = SAMPLING_INTERVAL,
+ .lcdoff_timeout = LCDOFF_TIMEOUT,
+ .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
+ .lcd_always_on = LCD_ALWAYS_ON,
+ .framerate_app = {1, 0, 0, 0},
+ .control_display = 1,
+ .powerkey_doublepress = 0,
+ .accel_sensor_on = ACCEL_SENSOR_ON,
+ .continuous_sampling = CONTINUOUS_SAMPLING,
+ .timeout_enable = false,
+ .input_support = true,
+};
+
+struct display_function_info display_info = {
+ .update_auto_brightness = NULL,
+ .set_autobrightness_min = NULL,
+ .reset_autobrightness_min = NULL,
+ .face_detection = NULL,
+};
+
+typedef struct _pm_lock_node {
+ pid_t pid;
+ guint timeout_id;
+ time_t time;
+ bool holdkey_block;
+ bool background;
+} PmLockNode;
+
+static dd_list *cond_head[S_END];
+
+static void set_process_active(bool flag, pid_t pid)
+{
+ int ret;
+
+ if (pid >= INTERNAL_LOCK_BASE)
+ return;
+
+ /* Send dbug to resourced */
+ ret = dbus_handle_broadcast_dbus_signal_var(RESOURCED_PATH_PROCESS,
+ RESOURCED_INTERFACE_PROCESS,
+ RESOURCED_METHOD_ACTIVE,
+ g_variant_new("(si)", (flag ? ACTIVE_ACT : INACTIVE_ACT), pid));
+ if (ret < 0)
+ _E("Fail to send dbus signal to resourced!!");
+}
+
+bool check_lock_state(int state)
+{
+ dd_list *elem;
+ PmLockNode *t;
+
+ DD_LIST_FOREACH(cond_head[state], elem, t) {
+ if (t->background == false)
+ return true;
+ }
+
+ return false;
+}
+
+void change_state_action(enum state_t state, int (*func)(int timeout))
+{
+ _I("[%s] action is changed", states[state].name);
+ states[state].action = func;
+}
+
+void change_state_trans(enum state_t state, int (*func)(int evt))
+{
+ _I("[%s] trans is changed", states[state].name);
+ states[state].trans = func;
+}
+
+void change_state_check(enum state_t state, int (*func)(int curr, int next))
+{
+ _I("[%s] check is changed", states[state].name);
+ states[state].check = func;
+}
+
+void change_state_name(enum state_t state, char *name)
+{
+ _I("[%s] name is changed", states[state].name);
+ states[state].name = name;
+}
+
+void change_trans_table(enum state_t state, enum state_t next)
+{
+ _I("[%s] timeout trans table is changed", states[state].name);
+ trans_table[state][EVENT_TIMEOUT] = next;
+}
+
+void change_proc_change_state(int (*func)(unsigned int cond, pid_t pid))
+{
+ _I("proc change state is changed");
+ proc_change_state = func;
+}
+
+static void broadcast_lcd_on(enum signal_type type, enum device_flags flags)
+{
+ const char *str;
+ const char *signal;
+
+ if (type <= SIGNAL_INVALID || type >= SIGNAL_MAX) {
+ _E("invalid signal type %d", type);
+ return;
+ }
+
+ if (flags & LCD_ON_BY_GESTURE)
+ str = GESTURE_STR;
+ else if (flags & LCD_ON_BY_POWER_KEY)
+ str = POWER_KEY_STR;
+ else if (flags & LCD_ON_BY_EVENT)
+ str = EVENT_STR;
+ else if (flags & LCD_ON_BY_TOUCH)
+ str = TOUCH_STR;
+ else
+ str = UNKNOWN_STR;
+
+ signal = lcdon_sig_lookup[type];
+ _I("lcdstep : broadcast %s %s", signal, str);
+ dbus_handle_broadcast_dbus_signal_var(DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ signal,
+ g_variant_new("(s)", str));
+}
+
+static void broadcast_lcd_off(enum signal_type type, enum device_flags flags)
+{
+ const char *str;
+ const char *signal;
+
+ if (type <= SIGNAL_INVALID || type >= SIGNAL_MAX) {
+ _E("invalid signal type %d", type);
+ return;
+ }
+
+ signal = lcdoff_sig_lookup[type];
+
+ if (flags & LCD_OFF_BY_POWER_KEY)
+ str = POWER_KEY_STR;
+ else if (flags & LCD_OFF_BY_TIMEOUT)
+ str = TIMEOUT_STR;
+ else if (flags & LCD_OFF_BY_EVENT)
+ str = EVENT_STR;
+ else
+ str = UNKNOWN_STR;
+
+ _I("lcdstep : broadcast %s", signal);
+ dbus_handle_broadcast_dbus_signal_var(DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ signal,
+ g_variant_new("(s)", str));
+}
+
+void broadcast_lcd_off_late(enum device_flags flags)
+{
+ static enum device_flags late_flags;
+
+ if (flags & LCD_OFF_LATE_MODE)
+ broadcast_lcd_off(SIGNAL_POST, late_flags);
+ else
+ late_flags = flags;
+}
+
+static unsigned long get_lcd_on_flags(void)
+{
+ unsigned long flags = NORMAL_MODE;
+
+ if (lcd_paneloff_mode)
+ flags |= LCD_PANEL_OFF_MODE;
+
+ if (stay_touchscreen_off)
+ flags |= TOUCH_SCREEN_OFF_MODE;
+
+ if (ambient_get_condition() == true) {
+ flags |= AMBIENT_MODE;
+ flags |= LCD_PHASED_TRANSIT_MODE;
+ }
+
+ return flags;
+}
+
+bool touch_event_blocked(void)
+{
+ return touch_blocked;
+}
+
+void lcd_on_procedure(int state, enum device_flags flag)
+{
+ dd_list *l = NULL;
+ const struct device_ops *ops = NULL;
+ unsigned long flags = get_lcd_on_flags();
+ flags |= flag;
+
+ /* send LCDOn dbus signal */
+ if (!lcdon_broadcast) {
+ broadcast_lcd_on(SIGNAL_PRE, flags);
+ lcdon_broadcast = true;
+ }
+
+ if (flags & AMBIENT_MODE) {
+ if (ambient_get_state() == false &&
+ backlight_ops.get_lcd_power() == DPMS_ON)
+ return;
+ ambient_set_state(false);
+ }
+
+ if (!(flags & LCD_PHASED_TRANSIT_MODE)) {
+ /* Update brightness level */
+ if (state == LCD_DIM)
+ backlight_ops.dim();
+ else if (state == LCD_NORMAL)
+ backlight_ops.update();
+ }
+
+ if (state == LCD_NORMAL)
+ set_setting_pmstate(S_NORMAL);
+ else if (state == LCD_DIM)
+ set_setting_pmstate(S_LCDDIM);
+
+ DD_LIST_FOREACH(lcdon_ops, l, ops)
+ ops->start(flags);
+
+ broadcast_lcd_on(SIGNAL_POST, flags);
+
+ if (CHECK_OPS(keyfilter_ops, backlight_enable))
+ keyfilter_ops->backlight_enable(true);
+
+ touch_blocked = false;
+}
+
+static inline unsigned long get_lcd_off_flags(void)
+{
+ unsigned long flags = NORMAL_MODE;
+
+ if (ambient_get_condition() == true) {
+ flags |= AMBIENT_MODE;
+ flags |= LCD_PHASED_TRANSIT_MODE;
+ }
+
+ return flags;
+}
+
+
+inline void lcd_off_procedure(enum device_flags flag)
+{
+ dd_list *l = NULL;
+ const struct device_ops *ops = NULL;
+ unsigned long flags = get_lcd_off_flags();
+ flags |= flag;
+
+ touch_blocked = true;
+
+ if (flags & AMBIENT_MODE) {
+ if (ambient_get_state() == true)
+ return;
+ ambient_set_state(true);
+ }
+
+ if (lcdon_broadcast) {
+ broadcast_lcd_off(SIGNAL_PRE, flags);
+ lcdon_broadcast = false;
+ }
+ if (CHECK_OPS(keyfilter_ops, backlight_enable))
+ keyfilter_ops->backlight_enable(false);
+
+ set_setting_pmstate(S_LCDOFF);
+
+ DD_LIST_FOREACH(lcdon_ops, l, ops)
+ ops->stop(flags);
+
+ if (flags & AMBIENT_MODE)
+ /* Do not broadcast the post signal here.
+ * The signal will be broadcasted
+ * after showing Ambient clock */
+ broadcast_lcd_off_late(flags);
+ else
+ broadcast_lcd_off(SIGNAL_POST, flags);
+}
+
+void set_stay_touchscreen_off(int val)
+{
+ _D("stay touch screen off : %d", val);
+ stay_touchscreen_off = val;
+
+ lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
+ set_setting_pmstate(LCD_NORMAL);
+}
+
+void set_lcd_paneloff_mode(int val)
+{
+ _D("lcd paneloff mode : %d", val);
+ lcd_paneloff_mode = val;
+
+ lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
+ set_setting_pmstate(LCD_NORMAL);
+}
+
+int low_battery_state(int val)
+{
+ switch (val) {
+ case VCONFKEY_SYSMAN_BAT_POWER_OFF:
+ case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
+ case VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF:
+ return true;
+ }
+ return false;
+}
+
+int get_hallic_open(void)
+{
+ return hallic_open;
+}
+
+static int refresh_app_cond()
+{
+ trans_condition = 0;
+
+ if (check_lock_state(S_NORMAL))
+ trans_condition = trans_condition | MASK_NORMAL;
+ if (check_lock_state(S_LCDDIM))
+ trans_condition = trans_condition | MASK_DIM;
+ if (check_lock_state(S_LCDOFF))
+ trans_condition = trans_condition | MASK_OFF;
+
+ return 0;
+}
+
+static void makeup_trans_condition(void)
+{
+ check_processes(S_NORMAL);
+ check_processes(S_LCDDIM);
+ check_processes(S_LCDOFF);
+ refresh_app_cond();
+}
+
+static PmLockNode *find_node(enum state_t s_index, pid_t pid)
+{
+ dd_list *elem;
+ PmLockNode *t;
+
+ DD_LIST_FOREACH(cond_head[s_index], elem, t) {
+ if (t->pid == pid)
+ return t;
+ }
+
+ return NULL;
+}
+
+static PmLockNode *add_node(enum state_t s_index, pid_t pid, guint timeout_id,
+ bool holdkey_block)
+{
+ PmLockNode *n;
+ time_t now;
+
+ n = (PmLockNode *) malloc(sizeof(PmLockNode));
+ if (n == NULL) {
+ _E("Not enough memory, add cond. fail");
+ return NULL;
+ }
+
+ time(&now);
+ n->pid = pid;
+ n->timeout_id = timeout_id;
+ n->time = now;
+ n->holdkey_block = holdkey_block;
+ n->background = false;
+ DD_LIST_APPEND(cond_head[s_index], n);
+
+ refresh_app_cond();
+ return n;
+}
+
+static int del_node(enum state_t s_index, PmLockNode *n)
+{
+ if (n == NULL)
+ return 0;
+
+ DD_LIST_REMOVE(cond_head[s_index], n);
+
+ /* delete timer */
+ if (n->timeout_id) {
+ g_source_remove(n->timeout_id);
+ n->timeout_id = 0;
+ }
+ free(n);
+ refresh_app_cond();
+ return 0;
+}
+
+static void print_node(int next)
+{
+ dd_list *elem;
+ PmLockNode *n;
+ char buf[30];
+ time_t now;
+ double diff;
+
+ if (next <= S_START || next >= S_END)
+ return;
+
+ time(&now);
+ DD_LIST_FOREACH(cond_head[next], elem, n) {
+ diff = difftime(now, n->time);
+ ctime_r(&n->time, buf);
+
+ if (diff > LOCK_TIME_WARNING)
+ _W("over %.0f s, pid: %5d, lock time: %s", diff, n->pid, buf);
+ else
+ _I("pid: %5d, lock time: %s", n->pid, buf);
+ }
+}
+
+void get_pname(pid_t pid, char *pname)
+{
+ char buf[PATH_MAX];
+ int cmdline, r;
+
+ if (pid >= INTERNAL_LOCK_BASE)
+ snprintf(buf, PATH_MAX, "/proc/%d/cmdline", getpid());
+ else
+ snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
+
+ cmdline = open(buf, O_RDONLY);
+ if (cmdline < 0) {
+ pname[0] = '\0';
+ _E("%d does not exist now(may be dead without unlock)", pid);
+ return;
+ }
+
+ r = read(cmdline, pname, PATH_MAX);
+ if ((r >= 0) && (r < PATH_MAX))
+ pname[r] = '\0';
+ else
+ pname[0] = '\0';
+
+ close(cmdline);
+}
+
+static void del_state_cond(void *data, enum state_t state)
+{
+ PmLockNode *tmp = NULL;
+ char pname[PATH_MAX];
+ pid_t pid;
+
+ if (!data)
+ return;
+
+ /* A passed data is a pid_t type data, not a 64bit data. */
+ pid = (pid_t)((intptr_t)data);
+ _I("delete prohibit dim condition by timeout (%d)", pid);
+
+ tmp = find_node(state, pid);
+ del_node(state, tmp);
+ get_pname(pid, pname);
+ set_unlock_time(pname, state);
+
+ if (!timeout_src_id)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ if (state == S_LCDOFF)
+ set_process_active(FALSE, pid);
+}
+
+static gboolean del_normal_cond(void *data)
+{
+ del_state_cond(data, S_NORMAL);
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean del_dim_cond(void *data)
+{
+ del_state_cond(data, S_LCDDIM);
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean del_off_cond(void *data)
+{
+ del_state_cond(data, S_LCDOFF);
+ return G_SOURCE_REMOVE;
+}
+
+/* timeout handler */
+gboolean timeout_handler(void *data)
+{
+ int run_timeout;
+
+ _I("Time out state %s\n", states[pm_cur_state].name);
+ /* default setting */
+ get_run_timeout(&run_timeout);
+
+ /* for sdk
+ * if the run_timeout is zero, it regards AlwaysOn state
+ */
+ if (pm_cur_state == S_NORMAL && (run_timeout == 0 || display_conf.lcd_always_on)) {
+ _D("run_timeout is always on");
+ return G_SOURCE_CONTINUE;
+ }
+
+ if (timeout_src_id) {
+ g_source_remove(timeout_src_id);
+ timeout_src_id = 0;
+ }
+
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+ return G_SOURCE_REMOVE;
+}
+
+void reset_timeout(int timeout)
+{
+ if (!display_conf.timeout_enable)
+ return;
+
+ _I("Reset Timeout (%d)ms", timeout);
+ if (timeout_src_id != 0) {
+ g_source_remove(timeout_src_id);
+ timeout_src_id = 0;
+ }
+
+ if (trans_table[pm_cur_state][EVENT_TIMEOUT] == pm_cur_state)
+ return;
+
+ if (timeout > 0)
+ timeout_src_id = g_timeout_add_seconds(MSEC_TO_SEC((double)timeout),
+ timeout_handler, NULL);
+ else if (timeout == 0)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+}
+
+/* get configurations from setting */
+static int get_lcd_timeout_from_settings(void)
+{
+ int i;
+ int val = 0;
+
+ for (i = 0; i < S_END; i++) {
+ switch (states[i].state) {
+ case S_NORMAL:
+ get_run_timeout(&val);
+ break;
+ case S_LCDDIM:
+ get_dim_timeout(&val);
+ break;
+ case S_LCDOFF:
+ val = display_conf.lcdoff_timeout;
+ break;
+ default:
+ /* This state doesn't need to set time out. */
+ val = 0;
+ break;
+ }
+ if (val > 0)
+ states[i].timeout = val;
+
+ _I("%s state : %d ms timeout", states[i].name,
+ states[i].timeout);
+ }
+
+ return 0;
+}
+
+static void update_display_time(void)
+{
+ int run_timeout, val;
+
+ /* first priority : s cover */
+ if (!hallic_open) {
+ states[S_NORMAL].timeout = S_COVER_TIMEOUT;
+ _I("S cover closed : timeout is set by normal(%d ms)",
+ S_COVER_TIMEOUT);
+ return;
+ }
+
+ /* second priority : custom timeout */
+ if (custom_normal_timeout > 0) {
+ states[S_NORMAL].timeout = custom_normal_timeout;
+ states[S_LCDDIM].timeout = custom_dim_timeout;
+ _I("CUSTOM : timeout is set by normal(%d ms), dim(%d ms)",
+ custom_normal_timeout, custom_dim_timeout);
+ return;
+ }
+
+ /* third priority : lock state */
+ if ((__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) &&
+ !get_lock_screen_bg_state()) {
+ /* timeout is different according to key or event. */
+ states[S_NORMAL].timeout = lock_screen_timeout;
+ _I("LOCK : timeout is set by normal(%d ms)",
+ lock_screen_timeout);
+ return;
+ }
+
+ /* default setting */
+ get_run_timeout(&run_timeout);
+
+ /* for sdk
+ * if the run_timeout is zero, it regards AlwaysOn state
+ */
+ if (run_timeout == 0 || display_conf.lcd_always_on) {
+ run_timeout = ALWAYS_ON_TIMEOUT;
+ _I("LCD Always On");
+ }
+
+ states[S_NORMAL].timeout = run_timeout;
+
+ get_dim_timeout(&val);
+ states[S_LCDDIM].timeout = val;
+
+ _I("Normal: NORMAL timeout is set by %d ms", states[S_NORMAL].timeout);
+ _I("Normal: DIM timeout is set by %d ms", states[S_LCDDIM].timeout);
+}
+
+static void update_display_locktime(int time)
+{
+ lock_screen_timeout = time;
+ update_display_time();
+}
+
+
+void set_dim_state(bool on)
+{
+ _I("dim state is %d", on);
+ update_display_time();
+ states[pm_cur_state].trans(EVENT_INPUT);
+}
+
+
+void lcd_on_direct(enum device_flags flags)
+{
+ int ret, call_state;
+
+ if (power_ops.get_power_lock_support()
+ && pm_cur_state == S_SLEEP)
+ power_ops.power_lock();
+
+#ifdef MICRO_DD
+ _D("lcd is on directly");
+ gettimeofday(&lcdon_tv, NULL);
+ lcd_on_procedure(LCD_NORMAL, flags);
+ reset_timeout(DD_LCDOFF_INPUT_TIMEOUT);
+#else
+ ret = vconf_get_int(VCONFKEY_CALL_STATE, &call_state);
+ if ((ret >= 0 && call_state != VCONFKEY_CALL_OFF) ||
+ (__get_lock_screen_state() == VCONFKEY_IDLE_LOCK)) {
+ _D("LOCK state, lcd is on directly");
+ lcd_on_procedure(LCD_NORMAL, flags);
+ }
+ reset_timeout(display_conf.lcdoff_timeout);
+#endif
+ update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT);
+}
+
+static inline bool check_lcd_is_on(void)
+{
+ if (backlight_ops.get_lcd_power() != DPMS_ON)
+ return false;
+
+ return true;
+}
+
+int custom_lcdon(int timeout)
+{
+ struct state *st;
+
+ if (timeout <= 0)
+ return -EINVAL;
+
+ if (check_lcd_is_on() == false)
+ lcd_on_direct(LCD_ON_BY_GESTURE);
+
+ _I("custom lcd on %d ms", timeout);
+ if (set_custom_lcdon_timeout(timeout) == true)
+ update_display_time();
+
+ /* state transition */
+ pm_old_state = pm_cur_state;
+ pm_cur_state = S_NORMAL;
+ st = &states[pm_cur_state];
+
+ /* enter action */
+ if (st->action)
+ st->action(st->timeout);
+
+ return 0;
+}
+
+static void default_proc_change_state_action(enum state_t next, int timeout)
+{
+ struct state *st;
+
+ pm_old_state = pm_cur_state;
+ pm_cur_state = next;
+
+ st = &states[pm_cur_state];
+
+ if (st && st->action) {
+ if (timeout < 0)
+ st->action(st->timeout);
+ else
+ st->action(timeout);
+ }
+}
+
+static int default_proc_change_state(unsigned int cond, pid_t pid)
+{
+ enum state_t next;
+
+ next = GET_COND_STATE(cond);
+ _I("Change State to %s (%d)", states[next].name, pid);
+
+ switch (next) {
+ case S_NORMAL:
+ if (check_lcd_is_on() == false)
+ lcd_on_direct(LCD_ON_BY_EVENT);
+ update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT);
+ default_proc_change_state_action(next, -1);
+ break;
+ case S_LCDDIM:
+ default_proc_change_state_action(next, -1);
+ break;
+ case S_LCDOFF:
+ if (backlight_ops.get_lcd_power() != DPMS_OFF)
+ lcd_off_procedure(LCD_OFF_BY_EVENT);
+ if (set_custom_lcdon_timeout(0))
+ update_display_time();
+ default_proc_change_state_action(next, -1);
+ break;
+ case S_SLEEP:
+ _I("Dangerous requests.");
+ /* at first LCD_OFF and then goto sleep */
+ /* state transition */
+ default_proc_change_state_action(S_LCDOFF, TIMEOUT_NONE);
+ delete_condition(S_LCDOFF);
+ default_proc_change_state_action(S_SLEEP, TIMEOUT_NONE);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* update transition condition for application requrements */
+static void update_lock_timer(PMMsg *data,
+ PmLockNode *node, guint timeout_id)
+{
+ time_t now;
+
+ if (data->timeout > 0) {
+ time(&now);
+ node->time = now;
+ }
+
+ if (node->timeout_id)
+ g_source_remove(node->timeout_id);
+ node->timeout_id = timeout_id;
+}
+
+static void proc_condition_lock(PMMsg *data)
+{
+ PmLockNode *tmp;
+ guint cond_timeout_id = 0;
+ char pname[PATH_MAX];
+ pid_t pid = data->pid;
+ enum state_t state;
+ int holdkey_block;
+
+ state = GET_COND_STATE(data->cond);
+ if (!state)
+ return;
+
+ get_pname(pid, pname);
+
+ if (state == S_LCDOFF &&
+ pm_cur_state == S_SLEEP)
+ proc_change_state(data->cond, INTERNAL_LOCK_PM);
+
+ if (data->timeout > 0) {
+ /* To pass a pid_t data through the timer infrastructure
+ * without memory allocation, a pid_t data becomes typecast
+ * to intptr_t and void *(64bit) type. */
+ cond_timeout_id = g_timeout_add_seconds(
+ MSEC_TO_SEC((double)data->timeout),
+ states[state].timeout_cb,
+ (void*)((intptr_t)pid));
+ if (!cond_timeout_id)
+ _E("Failed to register display timer");
+ }
+
+ holdkey_block = GET_COND_FLAG(data->cond) & PM_FLAG_BLOCK_HOLDKEY;
+
+ tmp = find_node(state, pid);
+ if (!tmp)
+ add_node(state, pid, cond_timeout_id, holdkey_block);
+ else {
+ update_lock_timer(data, tmp, cond_timeout_id);
+ tmp->holdkey_block = holdkey_block;
+ }
+
+ if (state == S_LCDOFF)
+ set_process_active(TRUE, pid);
+
+ /* for debug */
+ _SD("[%s] locked by pid %d - process %s holdkeyblock %d\n",
+ states[state].name, pid, pname, holdkey_block);
+ set_lock_time(pname, state);
+
+ device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)true);
+}
+
+static void proc_condition_unlock(PMMsg *data)
+{
+ pid_t pid = data->pid;
+ enum state_t state;
+ PmLockNode *tmp;
+ char pname[PATH_MAX];
+
+ state = GET_COND_STATE(data->cond);
+ if (!state)
+ return;
+
+ get_pname(pid, pname);
+
+ tmp = find_node(state, pid);
+ del_node(state, tmp);
+
+ if (state == S_LCDOFF)
+ set_process_active(FALSE, pid);
+
+ if (ambient_get_state())
+ ambient_check_invalid_state(pid);
+
+ _SD("[%s] unlocked by pid %d - process %s\n",
+ states[state].name, pid, pname);
+ set_unlock_time(pname, state);
+
+ device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)false);
+}
+
+static int proc_condition(PMMsg *data)
+{
+ unsigned int flags;
+
+ if (IS_COND_REQUEST_LOCK(data->cond))
+ proc_condition_lock(data);
+
+ if (IS_COND_REQUEST_UNLOCK(data->cond))
+ proc_condition_unlock(data);
+
+ if (!display_conf.timeout_enable)
+ return 0;
+
+ flags = GET_COND_FLAG(data->cond);
+ if (flags == 0) {
+ /* guard time for suspend */
+ if (pm_cur_state == S_LCDOFF) {
+ reset_timeout(states[S_LCDOFF].timeout);
+ _I("Margin timeout (%d ms)", states[S_LCDOFF].timeout);
+ }
+ } else {
+ if (flags & PM_FLAG_RESET_TIMER) {
+ reset_timeout(states[pm_cur_state].timeout);
+ _I("Reset timeout (%d ms)", states[pm_cur_state].timeout);
+ }
+ }
+
+ if (!timeout_src_id)
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+
+ return 0;
+}
+
+/* If some changed, return 1 */
+int check_processes(enum state_t prohibit_state)
+{
+ dd_list *elem, *next;
+ PmLockNode *t;
+ int ret = 0;
+
+ DD_LIST_FOREACH_SAFE(cond_head[prohibit_state], elem, next, t) {
+ if (t->pid < INTERNAL_LOCK_BASE && kill(t->pid, 0) == -1) {
+ _E("%d process does not exist, delete the REQ"
+ " - prohibit state %d ",
+ t->pid, prohibit_state);
+ if (t->pid == custom_change_pid) {
+ get_lcd_timeout_from_settings();
+ custom_normal_timeout = custom_dim_timeout = 0;
+ custom_change_pid = -1;
+ }
+ ret = 1;
+ del_node(prohibit_state, t);
+ }
+ }
+
+ return ret;
+}
+
+int check_holdkey_block(enum state_t state)
+{
+ dd_list *elem;
+ PmLockNode *t;
+ int ret = 0;
+
+ _I("check holdkey block : state of %s", states[state].name);
+
+ if (custom_holdkey_block == true) {
+ _I("custom hold key blocked by pid(%d)",
+ custom_change_pid);
+ return 1;
+ }
+
+ DD_LIST_FOREACH(cond_head[state], elem, t) {
+ if (t->holdkey_block == true) {
+ ret = 1;
+ _I("Hold key blocked by pid(%d)!", t->pid);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int delete_condition(enum state_t state)
+{
+ dd_list *elem, *next;
+ PmLockNode *t;
+ pid_t pid;
+ char pname[PATH_MAX];
+
+ _I("delete condition : state of %s", states[state].name);
+
+ if (!cond_head[state])
+ return 0;
+
+ DD_LIST_FOREACH_SAFE(cond_head[state], elem, next, t) {
+ if (t->timeout_id > 0) {
+ g_source_remove(t->timeout_id);
+ t->timeout_id = 0;
+ }
+ pid = t->pid;
+ if (state == S_LCDOFF)
+ set_process_active(FALSE, pid);
+ _I("delete node of pid(%d)", pid);
+ del_node(state, t);
+ get_pname(pid, pname);
+ set_unlock_time(pname, state-1);
+ }
+
+ DD_LIST_FREE_LIST(cond_head[state]);
+ cond_head[state] = NULL;
+
+ return 0;
+}
+
+void update_lcdoff_source(int source)
+{
+ switch (source) {
+ case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
+ _I("LCD OFF by timeout");
+ break;
+ case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
+ _I("LCD OFF by powerkey");
+ break;
+ default:
+ _E("Invalid value(%d)", source);
+ return;
+ }
+ vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
+}
+
+#ifdef ENABLE_PM_LOG
+
+typedef struct _pm_history {
+ time_t time;
+ enum pm_log_type log_type;
+ int keycode;
+} pm_history;
+
+static int max_history_count = MAX_LOG_COUNT;
+static pm_history pm_history_log[MAX_LOG_COUNT] = {{0, }, };
+static int history_count = 0;
+
+static const char history_string[PM_LOG_MAX][15] = {
+ "PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON FAIL",
+ "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF FAIL", "SLEEP"};
+
+void pm_history_init()
+{
+ memset(pm_history_log, 0x0, sizeof(pm_history_log));
+ history_count = 0;
+ max_history_count = MAX_LOG_COUNT;
+}
+
+void pm_history_save(enum pm_log_type log_type, int code)
+{
+ time_t now;
+
+ time(&now);
+ pm_history_log[history_count].time = now;
+ pm_history_log[history_count].log_type = log_type;
+ pm_history_log[history_count].keycode = code;
+ history_count++;
+
+ if (history_count >= max_history_count)
+ history_count = 0;
+}
+
+void pm_history_print(int fd, int count)
+{
+ int start_index, index, i;
+ int ret;
+ char buf[255];
+ char time_buf[30];
+
+ if (count <= 0 || count > max_history_count)
+ return;
+
+ start_index = (history_count - count + max_history_count)
+ % max_history_count;
+
+ for (i = 0; i < count; i++) {
+ index = (start_index + i) % max_history_count;
+
+ if (pm_history_log[index].time == 0)
+ continue;
+
+ if (pm_history_log[index].log_type < PM_LOG_MIN ||
+ pm_history_log[index].log_type >= PM_LOG_MAX)
+ continue;
+ ctime_r(&pm_history_log[index].time, time_buf);
+ snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s",
+ index,
+ history_string[pm_history_log[index].log_type],
+ pm_history_log[index].keycode,
+ time_buf);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+ }
+}
+#endif
+
+void print_info(int fd)
+{
+ int s_index = 0;
+ char buf[255];
+ int i = 1;
+ int ret;
+ char pname[PATH_MAX];
+ PmLockNode *t;
+ dd_list *elem;
+ char time_buf[30];
+
+ if (fd < 0)
+ return;
+
+ snprintf(buf, sizeof(buf),
+ "\n==========================================="
+ "===========================\n");
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+ snprintf(buf, sizeof(buf), "Timeout Info: Run[%dms] Dim[%dms] Off[%dms]\n",
+ states[S_NORMAL].timeout,
+ states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
+ (trans_condition & MASK_NORMAL) ? states[S_NORMAL].name : "-",
+ (trans_condition & MASK_DIM) ? states[S_LCDDIM].name : "-",
+ (trans_condition & MASK_OFF) ? states[S_LCDOFF].name : "-");
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf), "Current State: %s\n",
+ states[pm_cur_state].name);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ for (s_index = S_NORMAL; s_index < S_END; s_index++) {
+ DD_LIST_FOREACH(cond_head[s_index], elem, t) {
+ get_pname((pid_t)t->pid, pname);
+ ctime_r(&t->time, time_buf);
+ snprintf(buf, sizeof(buf),
+ " %d: [%s] locked by pid %d %s %s",
+ i++, states[s_index].name, t->pid, pname, time_buf);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+ }
+ }
+
+ print_lock_info_list(fd);
+
+#ifdef ENABLE_PM_LOG
+ pm_history_print(fd, 250);
+#endif
+}
+
+void save_display_log(void)
+{
+ int fd, ret;
+ char buf[255];
+ time_t now_time;
+ char time_buf[30];
+
+ _D("internal state is saved!");
+
+ time(&now_time);
+ ctime_r(&now_time, time_buf);
+
+ fd = open(PM_STATE_LOG_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd != -1) {
+ snprintf(buf, sizeof(buf),
+ "\npm_state_log now-time : %d(s) %s\n\n",
+ (int)now_time, time_buf);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf), "pm_status_flag: %x\n", pm_status_flag);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf), "screen lock status : %d\n",
+ __get_lock_screen_state());
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+ print_info(fd);
+ close(fd);
+ }
+
+ fd = open("/dev/console", O_WRONLY);
+ if (fd != -1) {
+ print_info(fd);
+ close(fd);
+ }
+}
+
+/* SIGHUP signal handler
+ * For debug... print info to syslog
+ */
+static void sig_hup(int signo)
+{
+ save_display_log();
+}
+
+int check_lcdoff_direct(void)
+{
+ int ret, lock, cradle;
+ int hdmi_state;
+
+ if (pm_old_state != S_NORMAL)
+ return false;
+
+ if (pm_cur_state != S_LCDDIM)
+ return false;
+
+ lock = __get_lock_screen_state();
+ if (lock != VCONFKEY_IDLE_LOCK && hallic_open)
+ return false;
+
+ hdmi_state = extcon_get_status(EXTCON_CABLE_HDMI);
+ if (hdmi_state)
+ return false;
+
+ ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
+ if (ret >= 0 && cradle == DOCK_SOUND)
+ return false;
+
+ _D("Goto LCDOFF direct(%d,%d,%d)", lock, hdmi_state, cradle);
+
+ return true;
+}
+
+static int __check_lcdoff_lock_state(void)
+{
+ if (cond_head[S_LCDOFF] != NULL)
+ return true;
+
+ return false;
+}
+
+/*
+ * default transition function
+ * 1. call check
+ * 2. transition
+ * 3. call enter action function
+ */
+static int default_trans(int evt)
+{
+ struct state *st = &states[pm_cur_state];
+ int next_state;
+
+ next_state = (enum state_t)trans_table[pm_cur_state][evt];
+
+ /* check conditions */
+ while (st->check && !st->check(pm_cur_state, next_state)) {
+ /* There is a condition. */
+ _I("(%s) locked. Trans to (%s) failed", states[pm_cur_state].name,
+ states[next_state].name);
+ if (!check_processes(pm_cur_state)) {
+ /* This is valid condition
+ * The application that sent the condition is running now. */
+ return -1;
+ }
+ }
+
+ /* state transition */
+ pm_old_state = pm_cur_state;
+ pm_cur_state = next_state;
+ st = &states[pm_cur_state];
+
+ /* enter action */
+ if (st->action) {
+ if (pm_cur_state == S_LCDOFF)
+ update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT);
+
+ if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDOFF)
+ if (set_custom_lcdon_timeout(0) == true)
+ update_display_time();
+
+ if (check_lcdoff_direct() == true) {
+ /* enter next state directly */
+ states[pm_cur_state].trans(EVENT_TIMEOUT);
+ } else {
+ st->action(st->timeout);
+ }
+ }
+
+ return 0;
+}
+
+static gboolean lcd_on_expired(void *data)
+{
+ int lock_state, ret;
+
+ if (lock_timeout_id)
+ lock_timeout_id = 0;
+
+ /* check state of lock */
+ ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
+
+ if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK)
+ return G_SOURCE_REMOVE;
+
+ /* lock screen is not launched yet, but lcd is on */
+ if (check_lcd_is_on() == false)
+ lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
+
+ return G_SOURCE_REMOVE;
+}
+
+static inline void stop_lock_timer(void)
+{
+ if (lock_timeout_id) {
+ g_source_remove(lock_timeout_id);
+ lock_timeout_id = 0;
+ }
+}
+
+static void check_lock_screen(void)
+{
+ int lock_setting, lock_state, app_state, ret;
+
+ stop_lock_timer();
+
+ ret = vconf_get_int(VCONFKEY_CALL_STATE, &app_state);
+ if (ret >= 0 && app_state != VCONFKEY_CALL_OFF)
+ goto lcd_on;
+
+ /* check setting of lock screen is enabled. */
+ ret = vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT,
+ &lock_setting);
+
+ /* check state of lock */
+ ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
+
+ if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK)
+ goto lcd_on;
+
+ /* Use time to check lock is done. */
+ lock_timeout_id = g_timeout_add_seconds(display_conf.lock_wait_time,
+ lcd_on_expired, NULL);
+
+ return;
+
+lcd_on:
+ if (check_lcd_is_on() == false)
+ lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
+}
+
+/* default enter action function */
+static int default_action(int timeout)
+{
+ int wakeup_count = -1;
+ time_t now;
+ double diff;
+ static time_t last_update_time = 0;
+ static int last_timeout = 0;
+ struct timeval now_tv;
+
+ if (status != DEVICE_OPS_STATUS_START) {
+ _E("display is not started!");
+ return -EINVAL;
+ }
+
+ if (pm_cur_state != S_SLEEP) {
+ if (pm_cur_state == S_NORMAL &&
+ lcdon_tv.tv_sec != 0) {
+ gettimeofday(&now_tv, NULL);
+ timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv);
+ lcdon_tv.tv_sec = 0;
+ }
+ /* set timer with current state timeout */
+ reset_timeout(timeout);
+
+ if (pm_cur_state == S_NORMAL) {
+ time(&last_update_time);
+ last_timeout = timeout;
+ } else {
+ _I("timout set: %s state %d ms",
+ states[pm_cur_state].name, timeout);
+ }
+ }
+
+ if (pm_cur_state != pm_old_state && pm_cur_state != S_SLEEP) {
+ if (power_ops.get_power_lock_support())
+ power_ops.power_lock();
+ set_setting_pmstate(pm_cur_state);
+ device_notify(DEVICE_NOTIFIER_LCD, &pm_cur_state);
+ }
+
+ if (pm_old_state == S_NORMAL && pm_cur_state != S_NORMAL) {
+ time(&now);
+ diff = difftime(now, last_update_time);
+ _I("S_NORMAL is changed to %s [%d ms, %.0f s]",
+ states[pm_cur_state].name, last_timeout, diff);
+ }
+
+ switch (pm_cur_state) {
+ case S_NORMAL:
+ /*
+ * normal state : backlight on and restore
+ * the previous brightness
+ */
+ if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP)
+ check_lock_screen();
+ else if (pm_old_state == S_LCDDIM)
+ backlight_ops.update();
+
+ if (check_lcd_is_on() == false)
+ lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
+ break;
+
+ case S_LCDDIM:
+ if (pm_old_state == S_NORMAL &&
+ backlight_ops.get_custom_status())
+ backlight_ops.save_custom_brightness();
+ /* lcd dim state : dim the brightness */
+ backlight_ops.dim();
+
+ if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP)
+ lcd_on_procedure(LCD_DIM, NORMAL_MODE);
+ break;
+
+ case S_LCDOFF:
+ if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) {
+ stop_lock_timer();
+ /* lcd off state : turn off the backlight */
+ if (backlight_ops.get_lcd_power() != DPMS_OFF)
+ lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
+ }
+
+ if (backlight_ops.get_lcd_power() != DPMS_OFF
+ || lcd_paneloff_mode)
+ lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
+ break;
+
+ case S_SLEEP:
+ if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF)
+ stop_lock_timer();
+
+ if (backlight_ops.get_lcd_power() != DPMS_OFF)
+ lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
+
+ if (!power_ops.get_power_lock_support()) {
+ /* sleep state : set system mode to SUSPEND */
+ if (power_ops.get_wakeup_count(&wakeup_count) < 0)
+ _E("wakeup count read error");
+
+ if (wakeup_count < 0) {
+ _I("Wakup Event! Can not enter suspend mode.");
+ goto go_lcd_off;
+ }
+
+ if (power_ops.set_wakeup_count(wakeup_count) < 0) {
+ _E("wakeup count write error");
+ goto go_lcd_off;
+ }
+ }
+ goto go_suspend;
+ }
+
+ return 0;
+
+go_suspend:
+#ifdef ENABLE_PM_LOG
+ pm_history_save(PM_LOG_SLEEP, pm_cur_state);
+#endif
+ if (power_ops.get_power_lock_support()) {
+ if (power_ops.enable_autosleep)
+ power_ops.enable_autosleep();
+
+ if (power_ops.power_unlock() < 0)
+ _E("power unlock state error!");
+ } else {
+ dd_list *elem, *elem_n;
+ const struct device_ops *dev;
+ /* Devices Suspend */
+ DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
+ if (dev->suspend)
+ dev->suspend();
+ }
+
+ power_ops.suspend();
+
+ /* Devices Resume */
+ DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
+ if (dev->resume)
+ dev->resume();
+ }
+
+ _I("system wakeup!!");
+ disp_plgn.system_wakeup_flag = true;
+ /* Resume !! */
+ if (power_ops.check_wakeup_src() == EVENT_DEVICE)
+ /* system waked up by devices */
+ states[pm_cur_state].trans(EVENT_DEVICE);
+ else
+ /* system waked up by user input */
+ states[pm_cur_state].trans(EVENT_INPUT);
+ }
+ return 0;
+
+go_lcd_off:
+ if (!power_ops.get_power_lock_support()) {
+ /* Resume !! */
+ states[pm_cur_state].trans(EVENT_DEVICE);
+ }
+ return 0;
+}
+
+/*
+ * default check function
+ * return
+ * 0 : can't transit, others : transitable
+ */
+static int default_check(int curr, int next)
+{
+ int trans_cond;
+
+ makeup_trans_condition();
+
+ trans_cond = trans_condition & MASK_BIT;
+
+ if (next == S_NORMAL) /* S_NORMAL is exceptional */
+ return 1;
+
+ switch (curr) {
+ case S_NORMAL:
+ trans_cond = trans_cond & MASK_NORMAL;
+ break;
+ case S_LCDDIM:
+ trans_cond = trans_cond & MASK_DIM;
+ break;
+ case S_LCDOFF:
+ trans_cond = trans_cond & MASK_OFF;
+ break;
+ default:
+ trans_cond = 0;
+ break;
+ }
+
+ if (trans_cond != 0) {
+ print_node(curr);
+ return 0;
+ }
+
+ return 1; /* transitable */
+}
+
+static void default_saving_mode(int onoff)
+{
+ if (onoff)
+ pm_status_flag |= PWRSV_FLAG;
+ else
+ pm_status_flag &= ~PWRSV_FLAG;
+
+ if (pm_cur_state == S_NORMAL)
+ backlight_ops.update();
+}
+
+static int poll_callback(int condition, PMMsg *data)
+{
+ static time_t last_t;
+ time_t now;
+
+ if (status != DEVICE_OPS_STATUS_START) {
+ _E("display logic is not started!");
+ return -ECANCELED;
+ }
+
+ if (condition == INPUT_POLL_EVENT) {
+ if (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP)
+ _I("Power key input");
+ time(&now);
+ if (last_t != now ||
+ pm_cur_state == S_LCDOFF ||
+ pm_cur_state == S_SLEEP) {
+ states[pm_cur_state].trans(EVENT_INPUT);
+ last_t = now;
+ }
+ }
+
+ if (condition == PM_CONTROL_EVENT) {
+ proc_condition(data);
+
+ if (IS_COND_REQUEST_CHANGE(data->cond))
+ proc_change_state(data->cond, data->pid);
+ }
+
+ return 0;
+}
+
+static int update_setting(int key_idx, int val)
+{
+ char buf[PATH_MAX];
+
+ switch (key_idx) {
+ case SETTING_TO_NORMAL:
+ update_display_time();
+ states[pm_cur_state].trans(EVENT_INPUT);
+ break;
+ case SETTING_HALLIC_OPEN:
+ hallic_open = val;
+ update_display_time();
+ if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDDIM)
+ states[pm_cur_state].trans(EVENT_INPUT);
+ else if (pm_cur_state == S_SLEEP && hallic_open)
+ proc_change_state(S_LCDOFF, INTERNAL_LOCK_HALLIC);
+ break;
+ case SETTING_LOW_BATT:
+ if (low_battery_state(val)) {
+ if (!(pm_status_flag & CHRGR_FLAG))
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ } else {
+ if (pm_status_flag & PWRSV_FLAG)
+ power_saving_func(false);
+ pm_status_flag &= ~LOWBT_FLAG;
+ pm_status_flag &= ~BRTCH_FLAG;
+ vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
+ false);
+ }
+ break;
+ case SETTING_CHARGING:
+ if (val) {
+ if (pm_status_flag & LOWBT_FLAG) {
+ power_saving_func(false);
+ pm_status_flag &= ~LOWBT_FLAG;
+ }
+ pm_status_flag |= CHRGR_FLAG;
+ } else {
+ int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
+ vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
+ &bat_state);
+ if (low_battery_state(bat_state)) {
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ }
+ pm_status_flag &= ~CHRGR_FLAG;
+ }
+ break;
+ case SETTING_BRT_LEVEL:
+ if (pm_status_flag & PWRSV_FLAG) {
+ pm_status_flag |= BRTCH_FLAG;
+ vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
+ true);
+ _I("brightness changed in low battery,"
+ "escape dim state");
+ }
+ backlight_ops.set_default_brt(val);
+ snprintf(buf, sizeof(buf), "%d", val);
+ _D("Brightness set in bl : %d", val);
+ launch_evenif_exist(SET_BRIGHTNESS_IN_BOOTLOADER, buf);
+ break;
+ case SETTING_LOCK_SCREEN:
+ set_lock_screen_state(val);
+ if (val == VCONFKEY_IDLE_UNLOCK) {
+ if (CHECK_OPS(keyfilter_ops, backlight_enable))
+ keyfilter_ops->backlight_enable(false);
+ }
+
+ /* LCD on if lock screen show before waiting time */
+ if (pm_cur_state == S_NORMAL &&
+ val == VCONFKEY_IDLE_LOCK &&
+ backlight_ops.get_lcd_power() != DPMS_ON)
+ lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
+ stop_lock_timer();
+ update_display_time();
+ if (pm_cur_state == S_NORMAL)
+ states[pm_cur_state].trans(EVENT_INPUT);
+ break;
+ case SETTING_LOCK_SCREEN_BG:
+ set_lock_screen_bg_state(val);
+ update_display_time();
+ if (pm_cur_state == S_NORMAL)
+ states[pm_cur_state].trans(EVENT_INPUT);
+ break;
+ case SETTING_POWEROFF:
+ switch (val) {
+ case POWER_OFF_NONE:
+ case POWER_OFF_POPUP:
+ pm_status_flag &= ~PWROFF_FLAG;
+ break;
+ case POWER_OFF_DIRECT:
+ case POWER_OFF_RESTART:
+ pm_status_flag |= PWROFF_FLAG;
+ break;
+ }
+ break;
+ case SETTING_POWER_CUSTOM_BRIGHTNESS:
+ if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
+ backlight_ops.set_custom_status(true);
+ else
+ backlight_ops.set_custom_status(false);
+ break;
+
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+extern int get_charging_status(int *val);
+//static int get_charging_status(int *val)
+//{
+ //return vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, val);
+//}
+
+static void check_seed_status(void)
+{
+ int ret = -1;
+ int tmp = 0;
+ int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
+ int brt = 0;
+ int lock_state = -1;
+
+ /* Charging check */
+ if ((get_charging_status(&tmp) == 0) && (tmp > 0))
+ pm_status_flag |= CHRGR_FLAG;
+
+ ret = get_setting_brightness(&tmp);
+ if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
+ _I("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;
+ }
+ _I("Set brightness from Setting App. %d", tmp);
+ backlight_ops.set_default_brt(tmp);
+
+ vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
+ if (low_battery_state(bat_state)) {
+ if (!(pm_status_flag & CHRGR_FLAG)) {
+ power_saving_func(true);
+ pm_status_flag |= LOWBT_FLAG;
+ }
+ }
+
+ /* lock screen check */
+ ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
+ set_lock_screen_state(lock_state);
+ if (lock_state == VCONFKEY_IDLE_LOCK) {
+ states[S_NORMAL].timeout = lock_screen_timeout;
+ _I("LCD NORMAL timeout is set by %d ms"
+ " for lock screen", lock_screen_timeout);
+ }
+
+ return;
+}
+
+static void init_lcd_operation(void)
+{
+ const struct device_ops *ops = NULL;
+
+ ops = find_device("display");
+ if (!check_default(ops))
+ DD_LIST_APPEND(lcdon_ops, ops);
+
+ ops = find_device("touchkey");
+ if (!check_default(ops))
+ DD_LIST_APPEND(lcdon_ops, ops);
+
+ ops = find_device("touchscreen");
+ if (!check_default(ops))
+ DD_LIST_APPEND(lcdon_ops, ops);
+}
+
+static void exit_lcd_operation(void)
+{
+ dd_list *l = NULL;
+ dd_list *l_next = NULL;
+ const struct device_ops *ops = NULL;
+
+ DD_LIST_FOREACH_SAFE(lcdon_ops, l, l_next, ops)
+ DD_LIST_REMOVE_LIST(lcdon_ops, l);
+}
+
+enum {
+ INIT_SETTING = 0,
+ INIT_INTERFACE,
+ INIT_POLL,
+ INIT_FIFO,
+ INIT_DBUS,
+ INIT_END
+};
+
+static const 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",
+ [INIT_DBUS] = "d-bus init error",
+};
+
+int set_lcd_timeout(int on, int dim, int holdkey_block, const char *name)
+{
+ if (on == 0 && dim == 0) {
+ _I("LCD timeout changed : default setting");
+ custom_normal_timeout = custom_dim_timeout = 0;
+ } else if (on < 0 || dim < 0) {
+ _E("fail to set value (%d,%d)", on, dim);
+ return -EINVAL;
+ } else {
+ _I("LCD timeout changed : on(%ds), dim(%ds)", on, dim);
+ custom_normal_timeout = SEC_TO_MSEC(on);
+ custom_dim_timeout = SEC_TO_MSEC(dim);
+ }
+ /* Apply new backlight time */
+ update_display_time();
+ if (pm_cur_state == S_NORMAL)
+ states[pm_cur_state].trans(EVENT_INPUT);
+
+ if (holdkey_block) {
+ custom_holdkey_block = true;
+ _I("hold key disabled !");
+ } else {
+ custom_holdkey_block = false;
+ _I("hold key enabled !");
+ }
+
+ if (custom_change_name) {
+ free(custom_change_name);
+ custom_change_name = 0;
+ }
+
+ if (custom_normal_timeout == 0 &&
+ custom_dim_timeout == 0 &&
+ !holdkey_block)
+ return 0;
+
+ custom_change_name = strndup(name, strlen(name));
+ if (!custom_change_name) {
+ _E("Malloc falied!");
+ custom_normal_timeout = custom_dim_timeout = 0;
+ custom_holdkey_block = false;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void reset_lcd_timeout(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *unique_name,
+ gpointer data)
+{
+ if (!sender)
+ return;
+
+ if (!custom_change_name)
+ return;
+
+ if (strcmp(sender, custom_change_name))
+ return;
+
+ _I("reset lcd timeout %s: set default timeout", sender);
+
+ free(custom_change_name);
+ custom_change_name = 0;
+ custom_normal_timeout = custom_dim_timeout = 0;
+ custom_holdkey_block = false;
+
+ update_display_time();
+ if (pm_cur_state == S_NORMAL)
+ states[pm_cur_state].trans(EVENT_INPUT);
+}
+
+static int booting_done(void *data)
+{
+ static int done;
+
+ if (!data)
+ return done;
+
+ done = *(int*)data;
+ if (!done)
+ return done;
+
+ _I("booting done. Release display and power lock");
+ if (disp_plgn.pm_unlock_internal) {
+ disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
+ disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
+ }
+
+ return done;
+}
+
+int device_poweroff(void *data)
+{
+ static int off;
+
+ if (!data)
+ return off;
+
+ off = *(int *)data;
+ if (off)
+ _I("Poweroff");
+
+ return off;
+}
+
+static int process_background(void *data)
+{
+ pid_t pid;
+ PmLockNode *node;
+
+ pid = *(pid_t *)data;
+
+ node = find_node(S_NORMAL, pid);
+ if (node) {
+ node->background = true;
+ _I("%d pid is background, then PM will be unlocked LCD_NORMAL", pid);
+ }
+
+ return 0;
+}
+
+static int process_foreground(void *data)
+{
+ pid_t pid;
+ PmLockNode *node;
+
+ pid = *(pid_t *)data;
+
+ node = find_node(S_NORMAL, pid);
+ if (node) {
+ node->background = false;
+ _I("%d pid is foreground, then PM will be maintained locked LCD_NORMAL", pid);
+ }
+
+ return 0;
+}
+
+static int display_load_config(struct parse_result *result, void *user_data)
+{
+ struct display_config *c = user_data;
+
+ _D("%s,%s,%s", result->section, result->name, result->value);
+
+ if (!c)
+ return -EINVAL;
+
+ if (!MATCH(result->section, "Display"))
+ return 0;
+
+ if (MATCH(result->name, "LockScreenWaitingTime")) {
+ SET_CONF(c->lock_wait_time, atof(result->value));
+ _D("lock wait time is %.3f", c->lock_wait_time);
+ } else if (MATCH(result->name, "LongPressInterval")) {
+ SET_CONF(c->longpress_interval, atof(result->value));
+ _D("long press interval is %.3f", c->longpress_interval);
+ } else if (MATCH(result->name, "LightSensorSamplingInterval")) {
+ SET_CONF(c->lightsensor_interval, atof(result->value));
+ _D("lightsensor interval is %.3f", c->lightsensor_interval);
+ } else if (MATCH(result->name, "LCDOffTimeout")) {
+ SET_CONF(c->lcdoff_timeout, atoi(result->value));
+ _D("lcdoff timeout is %d ms", c->lcdoff_timeout);
+ } else if (MATCH(result->name, "BrightnessChangeStep")) {
+ SET_CONF(c->brightness_change_step, atoi(result->value));
+ _D("brightness change step is %d", c->brightness_change_step);
+ } else if (MATCH(result->name, "LCDAlwaysOn")) {
+ c->lcd_always_on = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("LCD always on is %d", c->lcd_always_on);
+ } else if (MATCH(result->name, "ChangedFrameRateAllowed")) {
+ if (strstr(result->value, "setting")) {
+ c->framerate_app[REFRESH_SETTING] = 1;
+ _D("framerate app is Setting");
+ }
+ if (strstr(result->value, "all")) {
+ memset(c->framerate_app, 1, sizeof(c->framerate_app));
+ _D("framerate app is All");
+ }
+ } else if (MATCH(result->name, "ControlDisplay")) {
+ c->control_display = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("ControlDisplay is %d", c->control_display);
+ } else if (MATCH(result->name, "PowerKeyDoublePressSupport")) {
+ c->powerkey_doublepress = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("PowerKeyDoublePressSupport is %d", c->powerkey_doublepress);
+ } else if (MATCH(result->name, "AccelSensorOn")) {
+ c->accel_sensor_on = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("AccelSensorOn is %d", c->accel_sensor_on);
+ } else if (MATCH(result->name, "ContinuousSampling")) {
+ c->continuous_sampling = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("ContinuousSampling is %d", c->continuous_sampling);
+ } else if (MATCH(result->name, "TimeoutEnable")) {
+ c->timeout_enable = (MATCH(result->value, "yes") ? true : false);
+ _D("Timeout is %s", c->timeout_enable ? "enalbed" : "disabled");
+ } else if (MATCH(result->name, "InputSupport")) {
+ c->input_support = (MATCH(result->value, "yes") ? true : false);
+ _D("Input is %s", c->input_support ? "supported" : "NOT supported");
+ }
+
+ return 0;
+}
+
+static bool check_wm_ready(void)
+{
+ if (access("/run/.wm_ready", F_OK) == 0) {
+ _I("Window manager is ready");
+ return true;
+ }
+
+ _I("Window manager is not ready");
+ return false;
+}
+
+static gboolean lcd_on_wm_ready(gpointer data)
+{
+ int timeout;
+
+ if (!check_wm_ready())
+ return G_SOURCE_CONTINUE;
+
+ switch (pm_cur_state) {
+ case S_NORMAL:
+ case S_LCDDIM:
+ lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
+ if (display_conf.timeout_enable) {
+ timeout = states[S_NORMAL].timeout;
+ /* check minimun lcd on time */
+ if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
+ timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
+ reset_timeout(timeout);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void add_timer_for_wm_ready(void)
+{
+ guint id = g_timeout_add(500/* milliseconds */, lcd_on_wm_ready, NULL);
+ if (id == 0)
+ _E("Failed to add wm_ready timeout");
+}
+
+/**
+ * Power manager Main
+ *
+ */
+static int display_probe(void *data)
+{
+ int ret;
+
+ /**
+ * load display service
+ * if there is no display shared library,
+ * deviced does not provide any method and function of display.
+ */
+ ret = display_service_load();
+ if (ret)
+ return ret;
+
+ /* display_plugin instance initialization */
+ init_pm_internal();
+ disp_plgn.check_lcdoff_lock_state = __check_lcdoff_lock_state;
+
+ return 0;
+}
+
+static void display_init(void *data)
+{
+ int ret, i;
+ int timeout = 0;
+ bool wm_ready;
+
+ _I("Start power manager");
+
+ signal(SIGHUP, sig_hup);
+
+ power_saving_func = default_saving_mode;
+
+ /* load configutation */
+ ret = config_parse(DISPLAY_CONF_FILE, display_load_config, &display_conf);
+ if (ret < 0)
+ _W("Failed to load %s, %d Use default value!",
+ DISPLAY_CONF_FILE, ret);
+
+ register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+ register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background);
+ register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground);
+ register_notifier(DEVICE_NOTIFIER_POWEROFF, device_poweroff);
+
+ for (i = INIT_SETTING; i < INIT_END; i++) {
+ switch (i) {
+ case INIT_SETTING:
+ ret = init_setting(update_setting);
+ break;
+ case INIT_INTERFACE:
+ if (display_conf.timeout_enable)
+ get_lcd_timeout_from_settings();
+ ret = init_sysfs();
+ break;
+ case INIT_POLL:
+ _I("input init");
+ pm_callback = poll_callback;
+ if (display_conf.input_support)
+ ret = init_input();
+ else
+ ret = 0;
+ break;
+ case INIT_DBUS:
+ _I("dbus init");
+ ret = init_pm_dbus();
+ break;
+ }
+ if (ret != 0) {
+ _E("%s", errMSG[i]);
+ break;
+ }
+ }
+
+ if (i == INIT_END) {
+ display_ops_init(NULL);
+#ifdef ENABLE_PM_LOG
+ pm_history_init();
+#endif
+ init_lcd_operation();
+ check_seed_status();
+
+ /* wm_ready needs to be checked
+ * since display manager can be launched later than deviced.
+ * In the case, display cannot be turned on at the first booting */
+ wm_ready = check_wm_ready();
+ if (wm_ready)
+ lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
+ else
+ add_timer_for_wm_ready();
+
+ if (display_conf.lcd_always_on) {
+ _I("LCD always on!");
+ trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL;
+ }
+
+ _I("Start Power managing without noti");
+ if (power_ops.get_power_lock_support())
+ power_ops.power_lock();
+
+ pm_cur_state = S_NORMAL;
+ set_setting_pmstate(pm_cur_state);
+
+ if (display_conf.timeout_enable) {
+ timeout = states[S_NORMAL].timeout;
+ /* check minimun lcd on time */
+ if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
+ timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
+
+ reset_timeout(timeout);
+ }
+
+ status = DEVICE_OPS_STATUS_START;
+ /*
+ * Lock lcd off until booting is done.
+ * deviced guarantees all booting script is executing.
+ * Last script of booting unlocks this suspend blocking state.
+ */
+ if (disp_plgn.pm_lock_internal) {
+ disp_plgn.pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
+ STAY_CUR_STATE, BOOTING_DONE_WATING_TIME);
+ disp_plgn.pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL,
+ STAY_CUR_STATE, BOOTING_DONE_WATING_TIME);
+ }
+
+ if (display_conf.input_support)
+ if (CHECK_OPS(keyfilter_ops, init))
+ keyfilter_ops->init();
+ }
+}
+
+static void display_exit(void *data)
+{
+ int i = INIT_END;
+
+ status = DEVICE_OPS_STATUS_STOP;
+
+ /* Set current state to S_NORMAL */
+ pm_cur_state = S_NORMAL;
+ set_setting_pmstate(pm_cur_state);
+ /* timeout is not needed */
+ reset_timeout(TIMEOUT_NONE);
+
+ if (CHECK_OPS(keyfilter_ops, exit))
+ keyfilter_ops->exit();
+
+ display_ops_exit(NULL);
+
+ 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:
+ unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+ unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background);
+ unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground);
+ unregister_notifier(DEVICE_NOTIFIER_POWEROFF, device_poweroff);
+
+ exit_input();
+ break;
+ }
+ }
+
+ exit_lcd_operation();
+ free_lock_info_list();
+
+ /* free display service */
+ display_service_free();
+
+ _I("Stop power manager");
+}
+
+static int display_start(enum device_flags flags)
+{
+ /* NORMAL MODE */
+ if (flags & NORMAL_MODE) {
+ if (flags & LCD_PANEL_OFF_MODE)
+ /* standby on */
+ backlight_ops.standby(true);
+ else
+ /* normal lcd on */
+ backlight_ops.on(flags);
+ return 0;
+ }
+
+ /* CORE LOGIC MODE */
+ if (!(flags & CORE_LOGIC_MODE))
+ return 0;
+
+ if (status == DEVICE_OPS_STATUS_START)
+ return -EALREADY;
+
+ if (display_probe(NULL) < 0)
+ return -EPERM;
+
+ display_init(NULL);
+
+ return 0;
+}
+
+static int display_stop(enum device_flags flags)
+{
+ /* NORMAL MODE */
+ if (flags & NORMAL_MODE) {
+ backlight_ops.off(flags);
+ return 0;
+ }
+
+ /* CORE LOGIC MODE */
+ if (!(flags & CORE_LOGIC_MODE))
+ return 0;
+
+ if (status == DEVICE_OPS_STATUS_STOP)
+ return -EALREADY;
+
+ display_exit(NULL);
+
+ return 0;
+}
+
+static int display_status(void)
+{
+ return status;
+}
+
+static const struct device_ops display_device_ops = {
+ .priority = DEVICE_PRIORITY_HIGH,
+ .name = "display",
+ .probe = display_probe,
+ .init = display_init,
+ .exit = display_exit,
+ .start = display_start,
+ .stop = display_stop,
+ .status = display_status,
+};
+
+DEVICE_OPS_REGISTER(&display_device_ops)
+
+/**
+ * @}
+ */
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2015 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 <math.h>
+#include <assert.h>
+#include <errno.h>
+#include <hw/display.h>
+
+#include "ambient-mode.h"
+#include "core/log.h"
+#include "core/devices.h"
+#include "core/list.h"
+#include "core/common.h"
+#include "util.h"
+#include "device-interface.h"
+#include "vconf.h"
+#include "core.h"
+#include "device-node.h"
+
+#define TOUCH_ON 1
+#define TOUCH_OFF 0
+
+#define LCD_PHASED_MIN_BRIGHTNESS 1
+#define LCD_PHASED_MAX_BRIGHTNESS 100
+#define LCD_PHASED_CHANGE_STEP 5
+#define LCD_PHASED_DELAY 35000 /* microsecond */
+
+#define POWER_AUTOSLEEP_PATH "/sys/power/autosleep"
+#define POWER_LOCK_PATH "/sys/power/wake_lock"
+#define POWER_UNLOCK_PATH "/sys/power/wake_unlock"
+#define POWER_WAKEUP_PATH "/sys/power/wakeup_count"
+#define POWER_STATE_PATH "/sys/power/state"
+
+enum {
+ POWER_UNLOCK = 0,
+ POWER_LOCK,
+};
+
+struct _backlight_ops backlight_ops;
+struct _power_ops power_ops;
+
+static bool custom_status;
+static int custom_brightness;
+static int force_brightness;
+static int default_brightness;
+
+static struct display_device *display_dev;
+
+static int bl_onoff(int on)
+{
+ enum display_state val;
+
+ if (!display_dev || !display_dev->set_state)
+ return dpms_set_power(on);
+
+ switch (on) {
+ case DPMS_ON:
+ val = DISPLAY_ON;
+ break;
+ case DPMS_STANDBY:
+ val = DISPLAY_STANDBY;
+ break;
+ case DPMS_SUSPEND:
+ val = DISPLAY_SUSPEND;
+ break;
+ case DPMS_OFF:
+ val = DISPLAY_OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return display_dev->set_state(val);
+}
+
+static int bl_brt(int brightness, int delay)
+{
+ int ret = -1;
+
+ if (delay > 0)
+ usleep(delay);
+
+ if (force_brightness > 0) {
+ _I("brightness(%d), force brightness(%d)",
+ brightness, force_brightness);
+ brightness = force_brightness;
+ }
+
+ /* Update device brightness */
+ ret = backlight_ops.set_brightness(brightness);
+
+ _I("set brightness %d, %d", brightness, ret);
+
+ return ret;
+}
+
+static int system_suspend(void)
+{
+ int ret;
+
+ _I("system suspend");
+ ret = sys_set_str(POWER_STATE_PATH, "mem");
+ _I("system resume (result : %d)", ret);
+ return 0;
+}
+
+static int system_enable_autosleep(void)
+{
+ _I("system autosleep enabled");
+ return sys_set_str(POWER_AUTOSLEEP_PATH, "mem");
+}
+
+static int system_power_lock(void)
+{
+ dd_list *elem, *elem_n;
+ const struct device_ops *dev;
+ int ret;
+
+ _I("system power lock");
+ ret = sys_set_str(POWER_LOCK_PATH, "mainlock");
+
+ /* Devices Resume */
+ DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
+ if (dev->resume)
+ dev->resume();
+ }
+
+ return ret;
+}
+
+static int system_power_unlock(void)
+{
+ dd_list *elem, *elem_n;
+ const struct device_ops *dev;
+
+ /* Devices Suspend */
+ DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
+ if (dev->suspend)
+ dev->suspend();
+ }
+
+ _I("system power unlock");
+ return sys_set_str(POWER_UNLOCK_PATH, "mainlock");
+}
+
+static int system_get_power_lock_support(void)
+{
+ static int power_lock_support = -1;
+ int ret;
+
+ if (power_lock_support >= 0)
+ goto out;
+
+ ret = sys_check_node(POWER_LOCK_PATH);
+ if (ret < 0)
+ power_lock_support = false;
+ else
+ power_lock_support = true;
+
+ _I("system power lock : %s",
+ (power_lock_support ? "support" : "not support"));
+
+out:
+ return power_lock_support;
+}
+
+static int get_lcd_power(void)
+{
+ enum dpms_state state;
+ enum display_state val;
+ int ret;
+
+ if (ambient_get_state())
+ return DPMS_OFF;
+
+ if (!display_dev || !display_dev->get_state) {
+ ret = dpms_get_power(&state);
+ if (ret < 0)
+ return ret;
+ return state;
+ }
+
+ ret = display_dev->get_state(&val);
+ if (ret < 0)
+ return ret;
+
+ switch (val) {
+ case DISPLAY_ON:
+ return DPMS_ON;
+ case DISPLAY_STANDBY:
+ return DPMS_STANDBY;
+ case DISPLAY_SUSPEND:
+ return DPMS_SUSPEND;
+ case DISPLAY_OFF:
+ return DPMS_OFF;
+ default:
+ return -EINVAL;
+ }
+}
+
+void change_brightness(int start, int end, int step)
+{
+ int diff, val;
+ int ret = -1;
+ int prev;
+
+ if ((pm_status_flag & PWRSV_FLAG) &&
+ !(pm_status_flag & BRTCH_FLAG))
+ return;
+
+ ret = backlight_ops.get_brightness(&prev);
+ if (ret < 0) {
+ _E("fail to get brightness : %d", ret);
+ return;
+ }
+
+ if (prev == end)
+ return;
+
+ _D("start %d end %d step %d", start, end, step);
+
+ diff = end - start;
+
+ if (abs(diff) < step)
+ val = (diff > 0 ? 1 : -1);
+ else
+ val = (int)ceil((double)diff / step);
+
+ while (start != end) {
+ if (val == 0) break;
+
+ start += val;
+ if ((val > 0 && start > end) ||
+ (val < 0 && start < end))
+ start = end;
+
+ bl_brt(start, LCD_PHASED_DELAY);
+ }
+}
+
+static int backlight_on(enum device_flags flags)
+{
+ int ret = -1;
+
+ _D("LCD on %x", flags);
+
+ ret = bl_onoff(DPMS_ON);
+ if (ret < 0)
+ _E("Failed to turn on backlight");
+
+ if (flags & LCD_PHASED_TRANSIT_MODE)
+ change_brightness(LCD_PHASED_MIN_BRIGHTNESS,
+ default_brightness, LCD_PHASED_CHANGE_STEP);
+
+ return ret;
+}
+
+static int backlight_off(enum device_flags flags)
+{
+ int ret = -1;
+
+ _D("LCD off %x", flags);
+
+ if (flags & LCD_PHASED_TRANSIT_MODE)
+ change_brightness(default_brightness,
+ LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
+
+ if (flags & AMBIENT_MODE)
+ return 0;
+
+ ret = bl_onoff(DPMS_OFF);
+ if (ret < 0)
+ _E("Failed to turn off backlight");
+
+ return ret;
+}
+
+static int backlight_dim(void)
+{
+ int ret;
+ int brightness;
+
+ if (vconf_get_int(VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS, &brightness) != 0) {
+ _E("Failed to get VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS value");
+ return -EPERM;
+ }
+
+ ret = bl_brt(brightness, 0);
+#ifdef ENABLE_PM_LOG
+ if (!ret)
+ pm_history_save(PM_LOG_LCD_DIM, pm_cur_state);
+ else
+ pm_history_save(PM_LOG_LCD_DIM_FAIL, pm_cur_state);
+#endif
+ return ret;
+}
+
+static int set_custom_status(bool on)
+{
+ custom_status = on;
+ return 0;
+}
+
+static bool get_custom_status(void)
+{
+ return custom_status;
+}
+
+static int save_custom_brightness(void)
+{
+ int ret, brightness;
+
+ ret = backlight_ops.get_brightness(&brightness);
+
+ custom_brightness = brightness;
+
+ return ret;
+}
+
+static int custom_backlight_update(void)
+{
+ int ret = 0;
+
+ if (custom_brightness < PM_MIN_BRIGHTNESS ||
+ custom_brightness > PM_MAX_BRIGHTNESS)
+ return -EINVAL;
+
+ if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) {
+ ret = backlight_dim();
+ } else {
+ _I("custom brightness restored! %d", custom_brightness);
+ ret = bl_brt(custom_brightness, 0);
+ }
+
+ return ret;
+}
+
+static int set_force_brightness(int level)
+{
+ if (level < 0 || level > PM_MAX_BRIGHTNESS)
+ return -EINVAL;
+
+ force_brightness = level;
+
+ return 0;
+}
+
+static int backlight_update(void)
+{
+ int ret = 0;
+
+ if (get_custom_status()) {
+ _I("custom brightness mode! brt no updated");
+ return 0;
+ }
+ if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG))
+ ret = backlight_dim();
+ else
+ ret = bl_brt(default_brightness, 0);
+
+ return ret;
+}
+
+static int backlight_standby(int force)
+{
+ int ret = -1;
+
+ if ((get_lcd_power() == DPMS_ON) || force) {
+ _I("LCD standby");
+ ret = bl_onoff(DPMS_STANDBY);
+ }
+
+ return ret;
+}
+
+static int set_default_brt(int level)
+{
+ if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
+ level = PM_DEFAULT_BRIGHTNESS;
+
+ default_brightness = level;
+
+ return 0;
+}
+
+static int check_wakeup_src(void)
+{
+ /* TODO if nedded.
+ * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
+ */
+ return EVENT_DEVICE;
+}
+
+static int get_wakeup_count(int *cnt)
+{
+ int ret;
+ int wakeup_count;
+
+ if (!cnt)
+ return -EINVAL;
+
+ ret = sys_get_int(POWER_WAKEUP_PATH, &wakeup_count);
+ if (ret < 0)
+ return ret;
+
+ *cnt = wakeup_count;
+ return 0;
+}
+
+static int set_wakeup_count(int cnt)
+{
+ int ret;
+
+ ret = sys_set_int(POWER_WAKEUP_PATH, cnt);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int get_max_brightness(void)
+{
+ static int max = -1;
+ int ret;
+
+ if (max > 0)
+ return max;
+
+ if (!display_dev) {
+ _E("there is no display device");
+ return -ENOENT;
+ }
+
+ if (!display_dev->get_max_brightness) {
+ max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
+ return max;
+ }
+
+ ret = display_dev->get_max_brightness(&max);
+ if (ret < 0) {
+ _E("Failed to get max brightness (%d)", ret);
+ return ret;
+ }
+
+ return max;
+}
+
+static int set_brightness(int val)
+{
+ int max;
+
+ if (!display_dev || !display_dev->set_brightness) {
+ _E("there is no display device");
+ return -ENOENT;
+ }
+
+ max = get_max_brightness();
+ if (max < 0) {
+ _E("Failed to get max brightness");
+ return max;
+ }
+
+ /* Maximum Brightness to users is 100.
+ * Thus real brightness need to be calculated */
+ val = val * max / 100;
+
+ return display_dev->set_brightness(val);
+}
+
+static int get_brt_normalized(int brt_raw)
+{
+ int quotient, remainder;
+ int max;
+
+ max = get_max_brightness();
+ if (max < 0) {
+ _E("Failed to get max brightness");
+ return max;
+ }
+
+ /* Maximum Brightness to users is 100.
+ * Thus the brightness value need to be calculated using real brightness.
+ * ex) Let's suppose that the maximum brightness of driver is 255.
+ * case 1) When the user sets the brightness to 41,
+ * real brightness is
+ * 41 * 255 / 100 = 104.55 = 104 (rounded off)
+ * case 2) When the user gets the brightness,
+ * the driver returns the brightness 104.
+ * Thus the brightness to users is
+ * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
+ */
+ quotient = brt_raw * 100 / max;
+ remainder = brt_raw * 100 % max;
+ if (remainder > 0)
+ quotient++;
+
+ return quotient;
+}
+
+static int get_brightness(int *val)
+{
+ int brt, ret;
+
+ if (!display_dev || !display_dev->get_brightness) {
+ _E("there is no display device");
+ return -ENOENT;
+ }
+
+ ret = display_dev->get_brightness(&brt);
+ if (ret < 0) {
+ _E("failed to get brightness (%d)", ret);
+ return ret;
+ }
+
+ *val = get_brt_normalized(brt);
+ return 0;
+}
+
+static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
+{
+ int brt_raw;
+ int ret;
+
+ if (!display_dev || !display_dev->get_auto_brightness)
+ return -ENOTSUP;
+
+ ret = display_dev->get_auto_brightness(lmax, lmin, light, &brt_raw);
+ if (ret < 0) {
+ _E("failed to get brightness by light sensor(%d)", ret);
+ return ret;
+ }
+
+ *brt = get_brt_normalized(brt_raw);
+ return 0;
+}
+
+static int get_frame_rate(int *rate)
+{
+ if (!rate)
+ return -EINVAL;
+
+ if (!display_dev || !display_dev->get_frame_rate)
+ return -ENOTSUP;
+
+ return display_dev->get_frame_rate(rate);
+}
+
+static int set_frame_rate(int rate)
+{
+ int ret;
+ static int fmin = -1, fmax = -1;
+
+ if (!display_dev ||
+ !display_dev->set_frame_rate)
+ return -ENOTSUP;
+
+ if (display_dev->get_min_frame_rate) {
+ if (fmin < 0) {
+ ret = display_dev->get_min_frame_rate(&fmin);
+ if (ret < 0) {
+ _E("Failed to get min frate rate (%d)", ret);
+ return ret;
+ }
+ }
+ if (rate < fmin) {
+ _E("Invalid rate(%d)! (Valid rate: %d <= rate)", rate, fmin);
+ return -EINVAL;
+ }
+ }
+
+ if (display_dev->get_max_frame_rate) {
+ if (fmax < 0) {
+ ret = display_dev->get_max_frame_rate(&fmax);
+ if (ret < 0) {
+ _E("Failed to get max frate rate (%d)", ret);
+ return ret;
+ }
+ }
+ if (rate > fmax) {
+ _E("Invalid rate(%d)! (Valid rate: rate <= %d)", rate, fmax);
+ return -EINVAL;
+ }
+ }
+
+ return display_dev->set_frame_rate(rate);
+}
+
+static void _init_ops(void)
+{
+ backlight_ops.off = backlight_off;
+ backlight_ops.dim = backlight_dim;
+ backlight_ops.on = backlight_on;
+ backlight_ops.update = backlight_update;
+ backlight_ops.standby = backlight_standby;
+ backlight_ops.set_default_brt = set_default_brt;
+ backlight_ops.get_lcd_power = get_lcd_power;
+ backlight_ops.set_custom_status = set_custom_status;
+ backlight_ops.get_custom_status = get_custom_status;
+ backlight_ops.save_custom_brightness = save_custom_brightness;
+ backlight_ops.custom_update = custom_backlight_update;
+ backlight_ops.set_force_brightness = set_force_brightness;
+ backlight_ops.set_brightness = set_brightness;
+ backlight_ops.get_brightness = get_brightness;
+ backlight_ops.get_brightness_by_light_sensor = get_brightness_by_light_sensor;
+ backlight_ops.get_frame_rate = get_frame_rate;
+ backlight_ops.set_frame_rate = set_frame_rate;
+
+ power_ops.suspend = system_suspend;
+ power_ops.enable_autosleep = system_enable_autosleep;
+ power_ops.power_lock = system_power_lock;
+ power_ops.power_unlock = system_power_unlock;
+ power_ops.get_power_lock_support = system_get_power_lock_support;
+ power_ops.check_wakeup_src = check_wakeup_src;
+ power_ops.get_wakeup_count = get_wakeup_count;
+ power_ops.set_wakeup_count = set_wakeup_count;
+}
+
+int display_service_load(void)
+{
+ struct hw_info *info;
+ int r;
+
+ if (display_dev)
+ return 0;
+
+ r = hw_get_info(DISPLAY_HARDWARE_DEVICE_ID,
+ (const struct hw_info **)&info);
+ if (r < 0) {
+ _I("display shared library is not supported: %d", r);
+ return -ENODEV;
+ }
+
+ if (!info->open) {
+ _E("fail to open display device : open(NULL)");
+ return -EPERM;
+ }
+
+ r = info->open(info, NULL, (struct hw_common **)&display_dev);
+ if (r < 0) {
+ _E("fail to get display device structure : %d", r);
+ return -EPERM;
+ }
+
+ _D("display device structure load success");
+ return 0;
+}
+
+int display_service_free(void)
+{
+ struct hw_info *info;
+
+ if (!display_dev)
+ return -ENOENT;
+
+ info = display_dev->common.info;
+
+ assert(info);
+
+ info->close((struct hw_common *)display_dev);
+ display_dev = NULL;
+
+ return 0;
+}
+
+int init_sysfs()
+{
+ _init_ops();
+ return 0;
+}
+
+int exit_sysfs(void)
+{
+ const struct device_ops *ops = NULL;
+
+ backlight_update();
+
+ ops = find_device("touchscreen");
+ if (!check_default(ops))
+ ops->start(NORMAL_MODE);
+
+ ops = find_device("touchkey");
+ if (!check_default(ops))
+ ops->start(NORMAL_MODE);
+
+ return 0;
+}
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2014 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 "util.h"
+#include "display-actor.h"
+#include "core/list.h"
+#include "core/common.h"
+
+static dd_list *actor_head;
+
+void display_add_actor(struct display_actor_ops *actor)
+{
+ DD_LIST_APPEND(actor_head, actor);
+}
+
+static struct display_actor_ops *display_find_actor(enum display_actor_id id)
+{
+ dd_list *elem;
+ struct display_actor_ops *actor;
+
+ DD_LIST_FOREACH(actor_head, elem, actor) {
+ if (actor->id == id)
+ return actor;
+ }
+ return NULL;
+}
+
+int display_set_caps(enum display_actor_id id, unsigned int caps)
+{
+ struct display_actor_ops *actor;
+
+ if (id <= 0 || !caps)
+ return -EINVAL;
+
+ actor = display_find_actor(id);
+ if (!actor)
+ return -EINVAL;
+
+ actor->caps |= caps;
+
+ return 0;
+}
+
+int display_reset_caps(enum display_actor_id id, unsigned int caps)
+{
+ struct display_actor_ops *actor;
+
+ if (id <= 0 || !caps)
+ return -EINVAL;
+
+ actor = display_find_actor(id);
+ if (!actor)
+ return -EINVAL;
+
+ actor->caps &= ~caps;
+
+ return 0;
+}
+
+unsigned int display_get_caps(enum display_actor_id id)
+{
+ struct display_actor_ops *actor;
+
+ if (id <= 0)
+ return 0;
+
+ actor = display_find_actor(id);
+ if (!actor)
+ return 0;
+
+ return actor->caps;
+}
+
+int display_has_caps(unsigned int total_caps, unsigned int caps)
+{
+ if (!total_caps || !caps)
+ return false;
+
+ if ((total_caps & caps) == caps)
+ return true;
+
+ return false;
+}
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 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 display-dbus.c
+ * @brief dbus interface
+ *
+ */
+
+#include <error.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <device-node.h>
+#include <libgdbus/dbus-system.h>
+
+#include "ambient-mode.h"
+#include "core/log.h"
+#include "util.h"
+#include "core.h"
+#include "core/common.h"
+#include "core/devices.h"
+#include "core/device-idler.h"
+#include "apps/apps.h"
+#include "dd-display.h"
+#include "display-actor.h"
+#include "display-ops.h"
+#include <device/display.h>
+
+#define SIGNAL_HOMESCREEN "HomeScreen"
+
+#define DUMP_MODE_WATING_TIME 600000
+
+#define EXPIRED_POPUP_TYPE_POWER "power_lock_expired"
+#define EXPIRED_POPUP_PID "_APP_PID_"
+#define EXPIRED_POPUP_COMM "_APP_COMM_"
+#define EXPIRED_POPUP_ID "_REQUEST_ID_"
+
+#define CHECK_POWEROFF() \
+ do { \
+ if (device_poweroff(NULL)) { \
+ _E("Ignore requests for display during power off"); \
+ return g_variant_new("(i)", -EBUSY); \
+ } \
+ } while (0)
+
+extern struct display_plugin disp_plgn;
+
+GVariant *dbus_start(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ static const struct device_ops *display_device_ops = NULL;
+
+ if (device_poweroff(NULL))
+ goto out;
+
+ if (!display_device_ops)
+ display_device_ops = find_device("display");
+ if (NOT_SUPPORT_OPS(display_device_ops))
+ goto out;
+
+ display_device_ops->start(CORE_LOGIC_MODE);
+out:
+ return dbus_handle_new_g_variant_tuple();
+}
+
+GVariant *dbus_stop(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ static const struct device_ops *display_device_ops = NULL;
+
+ if (device_poweroff(NULL))
+ goto out;
+
+ if (!display_device_ops)
+ display_device_ops = find_device("display");
+ if (NOT_SUPPORT_OPS(display_device_ops))
+ goto out;
+
+ display_device_ops->stop(CORE_LOGIC_MODE);
+out:
+ return dbus_handle_new_g_variant_tuple();
+}
+
+GVariant *dbus_lockstate(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ char *state_str;
+ char *option1_str;
+ char *option2_str;
+ int timeout;
+ pid_t pid;
+ int state;
+ int flag;
+ int ret = 0;
+ unsigned int caps;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(sssi)", &state_str, &option1_str, &option2_str, &timeout);
+
+ if (!state_str || timeout < 0) {
+ _E("message is invalid!");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(state_str, "privilege check"))
+ goto out;
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ if (kill(pid, 0) == -1) {
+ _E("%d process does not exist, dbus ignored!", pid);
+ ret = -ESRCH;
+ goto out;
+ }
+
+ if (!strcmp(state_str, PM_LCDON_STR))
+ state = LCD_NORMAL;
+ else if (!strcmp(state_str, PM_LCDDIM_STR))
+ state = LCD_DIM;
+ else if (!strcmp(state_str, PM_LCDOFF_STR))
+ state = LCD_OFF;
+ else {
+ _E("%s state is invalid, dbus ignored!", state_str);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(option1_str, STAYCURSTATE_STR))
+ flag = STAY_CUR_STATE;
+ else if (!strcmp(option1_str, GOTOSTATENOW_STR))
+ flag = GOTO_STATE_NOW;
+ else {
+ _E("%s option is invalid. set default option!", option1_str);
+ flag = STAY_CUR_STATE;
+ }
+
+ if (!strcmp(option2_str, HOLDKEYBLOCK_STR))
+ flag |= HOLD_KEY_BLOCK;
+
+ if (flag & GOTO_STATE_NOW) {
+ caps = display_get_caps(DISPLAY_ACTOR_API);
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDON) &&
+ state == LCD_NORMAL) {
+ _D("No lcdon capability!");
+ ret = -EPERM;
+ goto out;
+ }
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDOFF) &&
+ state == LCD_OFF) {
+ _D("No lcdoff capability!");
+ ret = -EPERM;
+ goto out;
+ }
+ }
+
+ if (check_dimstay(state, flag) == true) {
+ _E("LCD state can not be changed to OFF state now!");
+ flag &= ~GOTO_STATE_NOW;
+ flag |= STAY_CUR_STATE;
+ }
+
+ if (disp_plgn.pm_lock_internal)
+ ret = disp_plgn.pm_lock_internal(pid, state, flag, timeout);
+out:
+ g_free(state_str);
+ g_free(option1_str);
+ g_free(option2_str);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_unlockstate(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ char *state_str;
+ char *option_str;
+ pid_t pid;
+ int state;
+ int flag;
+ int ret = 0;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(ss)", &state_str, &option_str);
+
+ if (!state_str) {
+ _E("message is invalid!");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(state_str, "privilege check"))
+ goto out;
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ if (kill(pid, 0) == -1) {
+ _E("%d process does not exist, dbus ignored!", pid);
+ ret = -ESRCH;
+ goto out;
+ }
+
+ if (!strcmp(state_str, PM_LCDON_STR))
+ state = LCD_NORMAL;
+ else if (!strcmp(state_str, PM_LCDDIM_STR))
+ state = LCD_DIM;
+ else if (!strcmp(state_str, PM_LCDOFF_STR))
+ state = LCD_OFF;
+ else {
+ _E("%s state is invalid, dbus ignored!", state_str);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(option_str, SLEEP_MARGIN_STR))
+ flag = PM_SLEEP_MARGIN;
+ else if (!strcmp(option_str, RESET_TIMER_STR))
+ flag = PM_RESET_TIMER;
+ else if (!strcmp(option_str, KEEP_TIMER_STR))
+ flag = PM_KEEP_TIMER;
+ else {
+ _E("%s option is invalid. set default option!", option_str);
+ flag = PM_RESET_TIMER;
+ }
+
+ if (disp_plgn.pm_unlock_internal)
+ ret = disp_plgn.pm_unlock_internal(pid, state, flag);
+out:
+ g_free(state_str);
+ g_free(option_str);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_changestate(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ char *state_str;
+ pid_t pid;
+ int state;
+ int ret = 0;
+ unsigned int caps;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(s)", &state_str);
+
+ if (!state_str) {
+ _E("message is invalid!");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!strcmp(state_str, "privilege check"))
+ goto out;
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ if (kill(pid, 0) == -1) {
+ _E("%d process does not exist, dbus ignored!", pid);
+ ret = -ESRCH;
+ goto out;
+ }
+
+ if (!strcmp(state_str, PM_LCDON_STR))
+ state = LCD_NORMAL;
+ else if (!strcmp(state_str, PM_LCDDIM_STR))
+ state = LCD_DIM;
+ else if (!strcmp(state_str, PM_LCDOFF_STR))
+ state = LCD_OFF;
+ else if (!strcmp(state_str, PM_STANDBY_STR))
+ state = STANDBY;
+ else if (!strcmp(state_str, PM_SUSPEND_STR))
+ state = SUSPEND;
+ else {
+ _E("%s state is invalid, dbus ignored!", state_str);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ caps = display_get_caps(DISPLAY_ACTOR_API);
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDON) &&
+ state == LCD_NORMAL) {
+ _D("No lcdon capability!");
+ ret = -EPERM;
+ goto out;
+ }
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDOFF) &&
+ state == LCD_OFF) {
+ _D("No lcdoff capability!");
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (check_dimstay(state, GOTO_STATE_NOW) == true) {
+ _E("LCD state can not be changed to OFF state!");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (disp_plgn.pm_change_internal)
+ ret = disp_plgn.pm_change_internal(pid, state);
+
+ if (!ret && state == LCD_OFF)
+ update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT);
+out:
+ g_free(state_str);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_getdisplaycount(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret;
+
+ CHECK_POWEROFF();
+
+ ret = DEFAULT_DISPLAY_COUNT;
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_getmaxbrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret, state;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &state);
+ if (state == DISPLAY_STATE_NORMAL)
+ ret = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
+ else if (state == DISPLAY_STATE_SCREEN_DIM)
+ ret = DEFAULT_DISPLAY_MAX_DIM_BRIGHTNESS;
+ else
+ ret = -EINVAL;
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_setmaxbrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret;
+
+ CHECK_POWEROFF();
+
+ ret = -ENOTSUP;
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_getbrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int brt = -1, state, ret;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &state);
+
+ if (state == DISPLAY_STATE_NORMAL) {
+ ret = backlight_ops.get_brightness(&brt);
+ } else if (state == DISPLAY_STATE_SCREEN_DIM) {
+ ret = vconf_get_int(VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS, &brt);
+ } else
+ ret = -EINVAL;
+
+ if (ret >= 0)
+ ret = brt;
+
+ _I("get brightness %d, %d", brt, ret);
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_setbrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int state, brt, autobrt, ret = 0, caps;
+
+ CHECK_POWEROFF();
+
+ caps = display_get_caps(DISPLAY_ACTOR_API);
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_BRIGHTNESS)) {
+ _D("No brightness changing capability!");
+ ret = -EPERM;
+ goto error;
+ }
+
+ g_variant_get(param, "(ii)", &state, &brt);
+
+ if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) {
+ _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value");
+ autobrt = SETTING_BRIGHTNESS_AUTOMATIC_OFF;
+ }
+
+ if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
+ _E("auto_brightness state is ON, can not change the brightness value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (state == DISPLAY_STATE_NORMAL) {
+ ret = backlight_ops.set_brightness(brt);
+ if (ret < 0)
+ goto error;
+
+ if (vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt) != 0)
+ _E("Failed to set VCONFKEY_SETAPPL_LCD_BRIGHTNESS value");
+ } else if (state == DISPLAY_STATE_SCREEN_DIM) {
+ if (pm_cur_state == S_LCDDIM) {
+ ret = backlight_ops.set_brightness(brt);
+ if (ret < 0)
+ goto error;
+ }
+
+ if (vconf_set_int(VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS, brt) != 0)
+ _E("Failed to set VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS value");
+ } else
+ ret = -EINVAL;
+
+ _I("set brightness %d, %d", brt, ret);
+
+error:
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_holdbrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int brt, autobrt, ret, caps;
+
+ CHECK_POWEROFF();
+
+ caps = display_get_caps(DISPLAY_ACTOR_API);
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_BRIGHTNESS)) {
+ _D("No brightness changing capability!");
+ ret = -EPERM;
+ goto error;
+ }
+
+ g_variant_get(param, "(i)", &brt);
+
+ if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) {
+ _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value");
+ autobrt = SETTING_BRIGHTNESS_AUTOMATIC_OFF;
+ }
+
+ vconf_set_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON);
+
+ ret = backlight_ops.set_brightness(brt);
+ if (ret < 0)
+ goto error;
+
+ if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_ON) {
+ _D("Auto brightness will be paused");
+ vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, SETTING_BRIGHTNESS_AUTOMATIC_PAUSE);
+ }
+
+ _I("hold brightness %d, %d", brt, ret);
+
+error:
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_releasebrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int bat, charger, changed, setting, brt, autobrt, ret = 0;
+
+ CHECK_POWEROFF();
+
+ if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat) != 0) {
+ _E("Failed to get VCONFKEY_SYSMAN_BATTERY_STATUS_LOW value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &charger) != 0) {
+ _E("Failed to get VCONFKEY_SYSMAN_CHARGER_STATUS value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (vconf_get_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, &changed) != 0) {
+ _E("Failed to get VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &setting) != 0) {
+ _E("Failed to get VCONFKEY_SETAPPL_LCD_BRIGHTNESS value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) {
+ _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value");
+ ret = -EPERM;
+ goto error;
+ }
+
+ vconf_set_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, VCONFKEY_PM_CUSTOM_BRIGHTNESS_OFF);
+
+ ret = backlight_ops.get_brightness(&brt);
+ if (ret < 0)
+ brt = ret;
+
+ // check dim state
+ if (low_battery_state(bat) &&
+ charger == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED && !changed) {
+ _D("batt warning low : brightness is not changed!");
+ if (brt != 0)
+ backlight_ops.set_brightness(0);
+ goto error;
+ }
+
+ if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_OFF) {
+ if (brt != setting)
+ backlight_ops.set_brightness(setting);
+ } else if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) {
+ _D("Auto brightness will be enable");
+ vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, SETTING_BRIGHTNESS_AUTOMATIC_ON);
+ }
+
+error:
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_setrefreshrate(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int app, val, ret, control;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(ii)", &app, &val);
+
+ if (app < 0 || app >= ARRAY_SIZE(display_conf.framerate_app) || val < 0) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (!display_conf.framerate_app[app]) {
+ _I("This case(%d) is not support in this target", app);
+ ret = -EPERM;
+ goto error;
+ }
+
+ control = display_conf.control_display;
+
+ if (control)
+ backlight_ops.off(NORMAL_MODE);
+
+ _D("app : %d, value : %d", app, val);
+ ret = backlight_ops.set_frame_rate(val);
+ if (ret < 0)
+ _E("Failed to set frame rate (%d)", ret);
+
+ if (control)
+ backlight_ops.on(NORMAL_MODE);
+
+error:
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_setautobrightnessmin(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int val, ret;
+ pid_t pid;
+ int id = 0;
+
+ CHECK_POWEROFF();
+
+ if (!display_info.set_autobrightness_min) {
+ ret = -EIO;
+ goto error;
+ }
+ g_variant_get(param, "(i)", &val);
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ ret = display_info.set_autobrightness_min(val, (char *)sender);
+ if (ret) {
+ _W("fail to set autobrightness min %d, %d by %d", val, ret, pid);
+ goto error;
+ }
+ if (display_info.reset_autobrightness_min) {
+ id = dbus_handle_watch_name(sender, display_info.reset_autobrightness_min, NULL, NULL, NULL);
+ if (id <= 0) {
+ _E("failed to watch name %s, id %d", sender, id);
+ //todo: set return value
+ }
+ _I("set autobrightness min %d by %d", val, pid);
+ }
+error:
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_setlcdtimeout(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int on, dim, holdkey_block, ret;
+ pid_t pid;
+ int id = 0;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(iii)", &on, &dim, &holdkey_block);
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ ret = set_lcd_timeout(on, dim, holdkey_block, sender);
+ if (ret) {
+ _W("fail to set lcd timeout %d by %d", ret, pid);
+ } else {
+ id = dbus_handle_watch_name(sender, reset_lcd_timeout, NULL, NULL, NULL);
+ if (id <= 0) {
+ _E("failed to watch name %s, id %d", sender, id);
+ //todo: set return value
+ }
+ _I("set lcd timeout on %d, dim %d, holdblock %d by %d",
+ on, dim, holdkey_block, pid);
+ }
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_lockscreenbgon(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ char *on = NULL;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(s)", &on);
+
+ if (!strcmp(on, "true")) {
+ if (disp_plgn.update_pm_setting)
+ disp_plgn.update_pm_setting(SETTING_LOCK_SCREEN_BG, true);
+ } else if (!strcmp(on, "false")) {
+ if (disp_plgn.update_pm_setting)
+ disp_plgn.update_pm_setting(SETTING_LOCK_SCREEN_BG, false);
+ } else {
+ ret = -EINVAL;
+ }
+
+ g_free(on);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_dumpmode(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ char *on;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(s)", &on);
+
+ if (!strcmp(on, "on")) {
+ if (disp_plgn.pm_lock_internal)
+ disp_plgn.pm_lock_internal(INTERNAL_LOCK_DUMPMODE, LCD_OFF,
+ STAY_CUR_STATE, DUMP_MODE_WATING_TIME);
+ } else if (!strcmp(on, "off")) {
+ if (disp_plgn.pm_unlock_internal)
+ disp_plgn.pm_unlock_internal(INTERNAL_LOCK_DUMPMODE, LCD_OFF, PM_SLEEP_MARGIN);
+ } else {
+ ret = -EINVAL;
+ }
+
+ g_free(on);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_savelog(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ if (!device_poweroff(NULL))
+ save_display_log();
+ return dbus_handle_new_g_variant_tuple();
+}
+
+GVariant *dbus_powerkeyignore(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ int on;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &on);
+
+ if (CHECK_OPS(keyfilter_ops, set_powerkey_ignore))
+ keyfilter_ops->set_powerkey_ignore(on == 1 ? true : false);
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_powerkeylcdoff(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret;
+
+ CHECK_POWEROFF();
+
+ if (CHECK_OPS(keyfilter_ops, powerkey_lcdoff))
+ ret = keyfilter_ops->powerkey_lcdoff();
+ else
+ ret = -ENOSYS;
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_customlcdon(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ int timeout;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &timeout);
+
+ ret = custom_lcdon(timeout);
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_staytouchscreenoff(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ int val;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &val);
+
+ set_stay_touchscreen_off(val);
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_lcdpaneloffmode(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ int val;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(i)", &val);
+
+ set_lcd_paneloff_mode(val);
+
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_actorcontrol(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0, val, actor;
+ char *op;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(sii)", &op, &actor, &val);
+
+ if (!strcmp(op, "set"))
+ ret = display_set_caps(actor, val);
+ else if (!strcmp(op, "reset"))
+ ret = display_reset_caps(actor, val);
+ else
+ ret = -EINVAL;
+
+ g_free(op);
+ return g_variant_new("(i)", ret);
+}
+
+GVariant *dbus_getcustombrightness(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int status = 0;
+
+ CHECK_POWEROFF();
+
+ status = backlight_ops.get_custom_status();
+
+ return g_variant_new("(i)", status);
+}
+
+struct pmlock_expired_s {
+ char req_id[32];
+ GDBusMethodInvocation *invocation;
+ int value;
+ pid_t pid;
+};
+
+static dd_list *expired_req_list;
+
+static int get_command(pid_t pid, char *comm, size_t len)
+{
+ FILE *fp;
+ char path[PATH_MAX];
+ char name[NAME_MAX];
+ char *tmp;
+ int ret;
+
+ snprintf(path, sizeof(path), "/proc/%d/comm", pid);
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ _E("Failed to open file %s, errno:%d", path, errno);
+ return -errno;
+ }
+
+ ret = fread(name, 1, sizeof(name) - 1, fp);
+ name[ret] = '\0';
+ fclose(fp);
+
+ tmp = name;
+ while (*tmp != '\0') {
+ if (*tmp == '\n' ||
+ *tmp == '\r') {
+ *tmp = '\0';
+ break;
+ }
+ tmp++;
+ }
+
+ snprintf(comm, len, "%s", name);
+
+ return 0;
+}
+
+GVariant *dbus_locktimeout_expired(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret;
+ char *req_id;
+ pid_t pid;
+ char pid_str[16];
+ char comm[NAME_MAX];
+ struct pmlock_expired_s *ex = NULL;
+ GVariant *gvar = NULL;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(s)", &req_id);
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ if (kill(pid, 0) == -1) {
+ _E("%d process does not exist, dbus ignored!", pid);
+ ret = -ESRCH;
+ goto out;
+ }
+
+ ret = get_command(pid, comm, sizeof(comm));
+ if (ret < 0) {
+ _E("Failed to get command (%d)", ret);
+ goto out;
+ }
+
+ ex = calloc(1, sizeof(struct pmlock_expired_s));
+ if (!ex) {
+ _E("calloc() failed");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ snprintf(pid_str, sizeof(pid_str), "%d", pid);
+ ret = launch_system_app(APP_DEFAULT, 8,
+ APP_KEY_TYPE,
+ EXPIRED_POPUP_TYPE_POWER,
+ EXPIRED_POPUP_PID,
+ pid_str,
+ EXPIRED_POPUP_COMM,
+ comm,
+ EXPIRED_POPUP_ID,
+ req_id);
+ if (ret < 0) {
+ _E("Failed to launch pmlock expired popup(%d)", ret);
+ goto out;
+ }
+
+ ex->pid = pid;
+ snprintf(ex->req_id, sizeof(ex->req_id), "%s", req_id);
+
+ ex->invocation = invocation;
+
+ DD_LIST_APPEND(expired_req_list, ex);
+
+ g_free(req_id);
+ return NULL;
+
+out:
+ gvar = g_variant_new("(si)", req_id, ret);
+ g_free(req_id);
+ if (ex)
+ free(ex);
+ return gvar;
+}
+
+static gboolean app_term(gpointer data)
+{
+ struct pmlock_expired_s *ex = data;
+
+ if (ex) {
+ if (kill(ex->pid, 0) != -1)
+ kill(ex->pid, SIGKILL);
+ free(ex);
+ }
+ return G_SOURCE_REMOVE;
+}
+
+static void expired_deliver_result(void *data)
+{
+ struct pmlock_expired_s *ex = data;
+ struct pmlock_expired_s *item = NULL;
+ dd_list *l;
+ size_t len;
+ int value;
+ char *id;
+
+ if (!ex)
+ return;
+
+ len = strlen(ex->req_id) + 1;
+ DD_LIST_FOREACH(expired_req_list, l, item) {
+ if (!strncmp(item->req_id, ex->req_id, len)) {
+ DD_LIST_REMOVE(expired_req_list, item);
+ break;
+ }
+ }
+ if (!item)
+ goto out;
+
+ id = ex->req_id;
+ value = ex->value;
+
+ _I("User input of req_id(%s) is (%s)", id, value == 0 ? "ALLOW power lock" :
+ (value == 2) ? "KILL app" : "Release power lock");
+
+ if (!item->invocation) {
+ _E("item->invocation is null");
+ goto out;
+ }
+ g_dbus_method_invocation_return_value(item->invocation, g_variant_new("(si)", id, value));
+
+ if (value == 2) {
+ kill(item->pid, SIGTERM);
+ g_timeout_add(3000, app_term, (gpointer)item);
+ item = NULL;
+ }
+
+out:
+ free(ex);
+ free(item);
+}
+
+GVariant *dbus_locktimeout_input(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret;
+ char *req_id;
+ struct pmlock_expired_s *ex;
+ int value;
+
+ CHECK_POWEROFF();
+
+ g_variant_get(param, "(si)", &req_id, &value);
+
+ ex = calloc(1, sizeof(struct pmlock_expired_s));
+ if (!ex) {
+ _E("calloc() failed");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ snprintf(ex->req_id, sizeof(ex->req_id), "%s", req_id);
+ ex->value = value;
+
+ _I("req_id(%s), value(%d)", ex->req_id, ex->value);
+
+ add_idle_request(expired_deliver_result, ex);
+
+ ret = 0;
+
+out:
+ g_free(req_id);
+ return g_variant_new("(i)", ret);
+}
+
+static const dbus_method_s dbus_methods[] = {
+ { "start", NULL, NULL, dbus_start },
+ { "stop", NULL, NULL, dbus_stop },
+ { "lockstate", "sssi", "i", dbus_lockstate },
+ { "unlockstate", "ss", "i", dbus_unlockstate },
+ { "changestate", "s", "i", dbus_changestate },
+ { "ChangeState", "s", "i", dbus_changestate },
+ { "getbrightness", "i", "i", dbus_getbrightness }, /* deprecated */
+ { "setbrightness", "ii", "i", dbus_setbrightness }, /* deprecated */
+ { "setframerate", "ii", "i", dbus_setrefreshrate }, /* deprecated */
+ { "setautobrightnessmin", "i", "i", dbus_setautobrightnessmin },
+ { "setlcdtimeout", "iii", "i", dbus_setlcdtimeout },
+ { "LockScreenBgOn", "s", "i", dbus_lockscreenbgon },
+ { "GetDisplayCount", NULL, "i", dbus_getdisplaycount },
+ { "GetMaxBrightness", "i", "i", dbus_getmaxbrightness },
+ { "SetMaxBrightness", "i", "i", dbus_setmaxbrightness },
+ { "GetBrightness", "i", "i", dbus_getbrightness },
+ { "SetBrightness", "ii", "i", dbus_setbrightness },
+ { "HoldBrightness", "i", "i", dbus_holdbrightness },
+ { "ReleaseBrightness", NULL, "i", dbus_releasebrightness },
+ { "SetRefreshRate", "ii", "i", dbus_setrefreshrate },
+ { "Dumpmode", "s", "i", dbus_dumpmode },
+ { "SaveLog", NULL, NULL, dbus_savelog },
+ { "PowerKeyIgnore", "i", "i", dbus_powerkeyignore },
+ { "PowerKeyLCDOff", NULL, "i", dbus_powerkeylcdoff },
+ { "CustomLCDOn", "i", "i", dbus_customlcdon },
+ { "StayTouchScreenOff", "i", "i", dbus_staytouchscreenoff },
+ { "LCDPanelOffMode", "i", "i", dbus_lcdpaneloffmode },
+ { "ActorControl", "sii", "i", dbus_actorcontrol },
+ { "CustomBrightness", NULL, "i", dbus_getcustombrightness },
+ { "CurrentBrightness", NULL, "i", dbus_getbrightness }, /* deprecated. It is remained for tizen 2.4 */
+ { "LockTimeoutExpired", "s", "i", dbus_locktimeout_expired },
+ { "LockTimeoutInput", "si", "i", dbus_locktimeout_input },
+ /* Add methods here */
+};
+
+static const dbus_interface_u dbus_interface = {
+ .oh = NULL,
+ .name = DEVICED_INTERFACE_DISPLAY,
+ .methods = dbus_methods,
+ .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+
+static void homescreen_signal_handler(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *path,
+ const gchar *iface,
+ const gchar *name,
+ GVariant *param,
+ gpointer data)
+{
+ char *screen;
+ pid_t pid;
+
+ g_variant_get(param, "(s)", &screen);
+
+ _D("screen : %s", screen);
+
+ pid = dbus_connection_get_sender_pid(conn, sender);
+ ambient_set_screen(screen, pid);
+ g_free(screen);
+}
+
+/*
+ * Default capability
+ * api := LCDON | LCDOFF | BRIGHTNESS
+ * gesture := LCDON
+ */
+static struct display_actor_ops display_api_actor = {
+ .id = DISPLAY_ACTOR_API,
+ .caps = DISPLAY_CAPA_LCDON |
+ DISPLAY_CAPA_LCDOFF |
+ DISPLAY_CAPA_BRIGHTNESS,
+};
+
+static struct display_actor_ops display_gesture_actor = {
+ .id = DISPLAY_ACTOR_GESTURE,
+ .caps = DISPLAY_CAPA_LCDON,
+};
+
+int init_pm_dbus(void)
+{
+ int ret;
+
+ display_add_actor(&display_api_actor);
+ display_add_actor(&display_gesture_actor);
+
+ ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+ if (ret < 0)
+ _E("fail to init dbus method(%d)", ret);
+
+ ret = subscribe_dbus_signal(NULL,
+ DEVICED_OBJECT_PATH,
+ DEVICED_INTERFACE_NAME,
+ SIGNAL_HOMESCREEN,
+ homescreen_signal_handler,
+ NULL, NULL);
+ if (ret <= 0) {
+ _E("Failed to register signal handler! %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 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 "util.h"
+#include "display-ops.h"
+#include "core/list.h"
+#include "core/common.h"
+
+static dd_list *disp_head;
+
+void add_display(const struct display_ops *disp)
+{
+ DD_LIST_APPEND(disp_head, disp);
+}
+
+void remove_display(const struct display_ops *disp)
+{
+ DD_LIST_REMOVE(disp_head, disp);
+}
+
+const struct display_ops *find_display_feature(const char *name)
+{
+ dd_list *elem;
+ const struct display_ops *disp;
+
+ DD_LIST_FOREACH(disp_head, elem, disp) {
+ if (!strcmp(disp->name, name))
+ return disp;
+ }
+ return NULL;
+}
+
+void display_ops_init(void *data)
+{
+ dd_list *elem;
+ const struct display_ops *disp;
+
+ DD_LIST_FOREACH(disp_head, elem, disp) {
+ _D("[%s] initialize", disp->name);
+ if (disp->init)
+ disp->init(data);
+ }
+}
+
+void display_ops_exit(void *data)
+{
+ dd_list *elem;
+ const struct display_ops *disp;
+
+ DD_LIST_FOREACH(disp_head, elem, disp) {
+ _D("[%s] deinitialize", disp->name);
+ if (disp->exit)
+ disp->exit(data);
+ }
+}
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2015 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 <libgdbus/dbus-system.h>
+
+#include "device-interface.h"
+#include "util.h"
+#include "core.h"
+
+#define ENLIGHTENMENT_BUS_NAME "org.enlightenment.wm"
+#define ENLIGHTENMENT_OBJECT_PATH "/org/enlightenment/wm"
+#define ENLIGHTENMENT_INTERFACE_NAME ENLIGHTENMENT_BUS_NAME".dpms"
+
+static void dpms_set_cb(GVariant *var, void *user_data, GError *err)
+{
+ int state;
+
+ if (!var) {
+ _E("no message [%s], Cannot get pmlock check",
+ err->message);
+ return;
+ }
+
+ if (!dh_get_param_from_var(var, "(i)", &state)) {
+ _E("no message [%s]", g_variant_get_type_string(var));
+ goto out;
+ }
+
+ _D("DPMS was set %d", state);
+
+#ifdef ENABLE_PM_LOG
+ switch (state) {
+ case DPMS_ON:
+ pm_history_save(PM_LOG_LCD_ON, pm_cur_state);
+ break;
+ case DPMS_OFF:
+ pm_history_save(PM_LOG_LCD_OFF, pm_cur_state);
+ break;
+ default:
+ break;
+ }
+#endif
+
+out:
+ g_variant_unref(var);
+}
+
+int dpms_set_power(enum dpms_state state)
+{
+ int ret;
+
+ ret = dbus_handle_method_async_with_reply_var(ENLIGHTENMENT_BUS_NAME,
+ ENLIGHTENMENT_OBJECT_PATH,
+ ENLIGHTENMENT_INTERFACE_NAME,
+ "set",
+ g_variant_new("(u)", state),
+ dpms_set_cb,
+ -1,
+ NULL);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int dpms_get_power(enum dpms_state *state)
+{
+ int ret;
+
+ if (!state)
+ return -EINVAL;
+
+ ret = dbus_handle_method_sync(ENLIGHTENMENT_BUS_NAME,
+ ENLIGHTENMENT_OBJECT_PATH,
+ ENLIGHTENMENT_INTERFACE_NAME,
+ "get",
+ NULL, NULL);
+ if (ret < 0)
+ return ret;
+
+ *state = ret;
+ return 0;
+}
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2015 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 <fcntl.h>
+#include <sys/stat.h>
+#include <linux/input.h>
+#include <libinput.h>
+
+#include "util.h"
+#include "core.h"
+#include "poll.h"
+
+#define SEAT_NAME "seat0"
+
+static struct udev *udev;
+static struct libinput *li;
+static guint efd;
+
+int (*pm_callback) (int, PMMsg *);
+
+static inline void process_event(struct libinput_event *ev)
+{
+ static const struct device_ops *display_device_ops;
+ struct input_event input;
+ struct libinput *li;
+ struct libinput_event_keyboard *k;
+ unsigned int time;
+ int fd;
+
+ if (!pm_callback)
+ return;
+
+ if (!display_device_ops) {
+ display_device_ops = find_device("display");
+ if (!display_device_ops)
+ return;
+ }
+
+ /* do not operate when display stops */
+ if (device_get_status(display_device_ops)
+ != DEVICE_OPS_STATUS_START) {
+ _E("display status is stop");
+ return;
+ }
+
+ switch (libinput_event_get_type(ev)) {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ return;
+ case LIBINPUT_EVENT_KEYBOARD_KEY:
+ k = libinput_event_get_keyboard_event(ev);
+ time = libinput_event_keyboard_get_time(k);
+ li = libinput_event_get_context(ev);
+
+ input.time.tv_sec = MSEC_TO_SEC(time);
+ input.time.tv_usec = MSEC_TO_USEC(time % 1000);
+ input.type = EV_KEY;
+ input.code = libinput_event_keyboard_get_key(k);
+ input.value = libinput_event_keyboard_get_key_state(k);
+
+ fd = libinput_get_fd(li);
+ _D("time %d.%d type %d code %d value %d fd %d",
+ input.time.tv_sec, input.time.tv_usec, input.type,
+ input.code, input.value, fd);
+
+ if (CHECK_OPS(keyfilter_ops, check) &&
+ keyfilter_ops->check(&input, fd) != 0)
+ return;
+ break;
+ case LIBINPUT_EVENT_POINTER_MOTION:
+ case LIBINPUT_EVENT_POINTER_BUTTON:
+ case LIBINPUT_EVENT_POINTER_AXIS:
+ li = libinput_event_get_context(ev);
+ input.type = EV_REL;
+
+ fd = libinput_get_fd(li);
+ _D("type %d fd %d", input.type, fd);
+
+ if (CHECK_OPS(keyfilter_ops, check) &&
+ keyfilter_ops->check(&input, fd) != 0)
+ return;
+ break;
+ case LIBINPUT_EVENT_TOUCH_DOWN:
+ case LIBINPUT_EVENT_TOUCH_UP:
+ case LIBINPUT_EVENT_TOUCH_MOTION:
+ case LIBINPUT_EVENT_TOUCH_FRAME:
+ if (touch_event_blocked())
+ return ;
+ break;
+ default:
+ break;
+ }
+
+ /* lcd on or update lcd timeout */
+ (*pm_callback) (INPUT_POLL_EVENT, NULL);
+}
+
+static gboolean input_handler(gint fd, GIOCondition cond, void *data)
+{
+ struct libinput_event *ev;
+ struct libinput *input = (struct libinput *)data;
+
+ /* Ignore input during poweroff */
+ if (device_poweroff(NULL))
+ return G_SOURCE_CONTINUE;
+
+ if (!input)
+ return G_SOURCE_CONTINUE;
+
+ libinput_dispatch(input);
+
+ while ((ev = libinput_get_event(input))) {
+ process_event(ev);
+
+ libinput_event_destroy(ev);
+ libinput_dispatch(input);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static int open_restricted(const char *path, int flags, void *user_data)
+{
+ int fd;
+ unsigned int clockid = CLOCK_MONOTONIC;
+
+ if (!path)
+ return -EINVAL;
+
+ fd = open(path, flags);
+ if (fd >= 0) {
+ /* TODO Why does fd change the clock? */
+ if (ioctl(fd, EVIOCSCLOCKID, &clockid) < 0)
+ _E("fail to change clock %s", path);
+ }
+
+ return fd < 0 ? -errno : fd;
+}
+
+static void close_restricted(int fd, void *user_data)
+{
+ close(fd);
+}
+
+static const struct libinput_interface interface = {
+ .open_restricted = open_restricted,
+ .close_restricted = close_restricted,
+};
+
+int init_input(void)
+{
+ int ret;
+ int fd;
+
+ udev = udev_new();
+ if (!udev) {
+ _E("fail to create udev library context");
+ return -EPERM;
+ }
+
+ li = libinput_udev_create_context(&interface, NULL, udev);
+ if (!li) {
+ _E("fail to create a new libinput context from udev");
+ return -EPERM;
+ }
+
+ ret = libinput_udev_assign_seat(li, SEAT_NAME);
+ if (ret < 0) {
+ _E("fail to assign a seat");
+ return -EPERM;
+ }
+
+ fd = libinput_get_fd(li);
+ if (fd < 0) {
+ _E("fail to get file descriptor from libinput context");
+ return -EPERM;
+ }
+
+ /* add to poll handler */
+ efd = g_unix_fd_add(fd, G_IO_IN,
+ input_handler,
+ (void *)((intptr_t)li));
+ if (!efd) {
+ _E("fail to g_unix_fd_add");
+ /* TODO Does it really need close()? */
+ close(fd);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+int exit_input(void)
+{
+ if (efd) {
+ g_source_remove(efd);
+ efd = -1;
+ }
+ /* todo: close fd */
+
+ if (li)
+ libinput_unref(li);
+
+ if (udev)
+ udev_unref(udev);
+
+ return 0;
+}
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <vconf.h>
+#include <sys/types.h>
+#include <libgdbus/dbus-system.h>
+
+#include "ambient-mode.h"
+#include "util.h"
+#include "core.h"
+#include "poll.h"
+#include "device-node.h"
+#include "display-actor.h"
+#include "display-ops.h"
+#include "core/common.h"
+#include "core/devices.h"
+#include "core/device-notifier.h"
+#include "power/power-handler.h"
+#include "led/touch-key.h"
+
+#include <linux/input.h>
+#ifndef KEY_SCREENLOCK
+#define KEY_SCREENLOCK 0x98
+#endif
+#ifndef SW_GLOVE
+#define SW_GLOVE 0x16
+#endif
+
+#define PREDEF_LEAVESLEEP "leavesleep"
+#define POWEROFF_ACT "poweroff"
+#define PWROFF_POPUP_ACT "pwroff-popup"
+#define USEC_PER_SEC 1000000
+
+#define CAPTURE_COMBINATION_INTERVAL 0.5 /* 0.5 second */
+
+#define KEY_MAX_DELAY_TIME 700 /* ms */
+
+#define KEY_RELEASED 0
+#define KEY_PRESSED 1
+#define KEY_BEING_PRESSED 2
+
+#define SIGNAL_CHANGE_HARDKEY "ChangeHardkey"
+#define SIGNAL_LCDON_BY_POWERKEY "LCDOnByPowerkey"
+#define SIGNAL_LCDOFF_BY_POWERKEY "LCDOffByPowerkey"
+
+#define TOUCH_RELEASE (-1)
+
+#define GLOVE_MODE 1
+
+extern struct display_plugin disp_plgn;
+
+enum key_combination_flags {
+ KEY_COMBINATION_STOP = 0,
+ KEY_COMBINATION_POWERKEY = BIT(0),
+ KEY_COMBINATION_MENUKEY = BIT(1),
+};
+
+enum combination_process {
+ COMBINATION_STOP = KEY_COMBINATION_STOP,
+ COMBINATION_SCREENCAPTURE = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_MENUKEY,
+};
+
+int __WEAK__ get_glove_state(void);
+void __WEAK__ switch_glove_key(int val);
+
+static struct timeval pressed_time;
+static guint longkey_timeout_id = 0;
+static int cancel_lcdoff;
+static int key_combination = KEY_COMBINATION_STOP;
+static double combination_pressed_time;
+static bool touch_pressed = false;
+static int skip_lcd_off = false;
+static int skip_combination = false;
+static const struct device_ops *touchled;
+
+static int booting_done(void *data)
+{
+ static int done = 0;
+
+ if (!data)
+ return done;
+
+ done = *(int *)data;
+
+ _I("Booting done(%d)", done);
+
+ return done;
+}
+
+static inline int current_state_in_on(void)
+{
+ return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL);
+}
+
+static inline void restore_custom_brightness(void)
+{
+ if (pm_cur_state == S_LCDDIM &&
+ backlight_ops.get_custom_status())
+ backlight_ops.custom_update();
+}
+
+static int power_execute(void *data)
+{
+ static const struct device_ops *ops = NULL;
+
+ FIND_DEVICE_INT(ops, POWER_OPS_NAME);
+
+ return ops->execute(data);
+}
+
+static void longkey_pressed()
+{
+ char *opt;
+ unsigned int caps;
+
+ _I("Power key long pressed!");
+ cancel_lcdoff = 1;
+
+ caps = display_get_caps(DISPLAY_ACTOR_POWER_KEY);
+
+ if (display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
+ /* change state - LCD on */
+ if (disp_plgn.pm_change_internal)
+ disp_plgn.pm_change_internal(INTERNAL_LOCK_POWERKEY, LCD_NORMAL);
+ (*pm_callback)(INPUT_POLL_EVENT, NULL);
+ }
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDOFF)) {
+ _D("No poweroff capability!");
+ return;
+ }
+
+
+ if (display_conf.lcd_always_on)
+ opt = POWEROFF_ACT;
+ else
+ opt = PWROFF_POPUP_ACT;
+ power_execute(opt);
+}
+
+static gboolean longkey_pressed_cb(void *data)
+{
+ longkey_pressed();
+ longkey_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+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 inline void check_key_pair(int code, int new, int *old)
+{
+ if (new == *old)
+ _E("key pair is not matched! (%d, %d)", code, new);
+ else
+ *old = new;
+}
+
+static inline void broadcast_lcdon_by_powerkey(void)
+{
+ dbus_handle_broadcast_dbus_signal(DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ SIGNAL_LCDON_BY_POWERKEY,
+ NULL, NULL);
+}
+
+static inline void broadcast_lcdoff_by_powerkey(void)
+{
+ dbus_handle_broadcast_dbus_signal(DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ SIGNAL_LCDOFF_BY_POWERKEY,
+ NULL, NULL);
+}
+
+static inline bool switch_on_lcd(void)
+{
+ if (current_state_in_on())
+ return false;
+
+ if (backlight_ops.get_lcd_power() == DPMS_ON) {
+ if (ambient_get_state() == false)
+ return false;
+ }
+
+ broadcast_lcdon_by_powerkey();
+
+ lcd_on_direct(LCD_ON_BY_POWER_KEY);
+
+ return true;
+}
+
+static inline void switch_off_lcd(void)
+{
+ if (!current_state_in_on())
+ return;
+
+ if (backlight_ops.get_lcd_power() == DPMS_OFF)
+ return;
+
+ broadcast_lcdoff_by_powerkey();
+
+ lcd_off_procedure(LCD_OFF_BY_POWER_KEY);
+}
+
+static void check_key_combination(struct input_event *pinput)
+{
+ double press_time, diff_time;
+ press_time = (pinput->time).tv_sec + USEC_TO_SEC((pinput->time).tv_usec);
+
+ switch (key_combination) {
+ case COMBINATION_SCREENCAPTURE:
+ diff_time = press_time - combination_pressed_time;
+ if (diff_time <= CAPTURE_COMBINATION_INTERVAL) {
+ _I("Combination key : SCREENCAPTURE mode");
+ skip_combination = true;
+ }
+ break;
+ default:
+ combination_pressed_time = press_time;
+ return;
+ }
+
+}
+
+static void start_key_combination(struct input_event *pinput)
+{
+ switch (pinput->code) {
+ case KEY_POWER:
+ key_combination |= KEY_COMBINATION_POWERKEY;
+ break;
+ case KEY_MENU:
+ key_combination |= KEY_COMBINATION_MENUKEY;
+ break;
+ default:
+ return;
+ }
+
+ check_key_combination(pinput);
+}
+
+static void stop_key_combination(struct input_event *pinput)
+{
+ if (pinput == NULL) {
+ key_combination = KEY_COMBINATION_STOP;
+ return;
+ }
+
+ switch (pinput->code) {
+ case KEY_POWER:
+ key_combination &= ~KEY_COMBINATION_POWERKEY;
+ break;
+ case KEY_MENU:
+ key_combination &= ~KEY_COMBINATION_MENUKEY;
+ break;
+ default:
+ _E("Thid code(%d) is not combination type", pinput->code);
+ break;
+ }
+}
+
+static void process_combination_key(struct input_event *pinput)
+{
+ if (pinput->value == KEY_PRESSED)
+ start_key_combination(pinput);
+ else if (pinput->value == KEY_RELEASED)
+ stop_key_combination(pinput);
+}
+
+static int process_menu_key(struct input_event *pinput)
+{
+ int caps;
+
+ caps = display_get_caps(DISPLAY_ACTOR_MENU_KEY);
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
+ if (current_state_in_on())
+ return false;
+ _D("No lcd-on capability!");
+ return true;
+ } else if (pinput->value == KEY_PRESSED) {
+ switch_on_lcd();
+ }
+
+ return false;
+}
+
+static int decide_lcdoff(void)
+{
+ /* It's not needed if it's already LCD off state */
+ if (!current_state_in_on() &&
+ backlight_ops.get_lcd_power() != DPMS_ON)
+ return false;
+
+ /*
+ * This flag is set at the moment
+ * that LCD is turned on by power key
+ * LCD has not to turned off in the situation.
+ */
+ if (skip_lcd_off)
+ return false;
+
+ /* LCD is not turned off when powerkey is pressed,not released */
+ if (key_combination == KEY_COMBINATION_POWERKEY)
+ return false;
+
+ /* LCD-off is blocked at the moment poweroff popup shows */
+ if (cancel_lcdoff)
+ return false;
+
+ /* LCD-off is blocked when powerkey and volmedown key are pressed */
+ if (skip_combination)
+ return false;
+
+ /* At booting time, display must do not turn off */
+ if (!booting_done(NULL))
+ return false;
+
+ return true;
+}
+
+static int lcdoff_powerkey(void)
+{
+ int ignore = true;
+
+ if (decide_lcdoff() == true) {
+ check_processes(S_NORMAL);
+ check_processes(S_LCDDIM);
+
+ if (!check_holdkey_block(S_NORMAL) &&
+ !check_holdkey_block(S_LCDDIM)) {
+ if (display_info.update_auto_brightness)
+ display_info.update_auto_brightness(false);
+ switch_off_lcd();
+ delete_condition(S_NORMAL);
+ delete_condition(S_LCDDIM);
+ update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
+ if (disp_plgn.pm_change_internal)
+ disp_plgn.pm_change_internal(INTERNAL_LOCK_POWERKEY, LCD_OFF);
+ }
+ } else {
+ ignore = false;
+ skip_combination = false;
+ }
+ cancel_lcdoff = 0;
+
+ return ignore;
+}
+
+static bool release_short_powerkey(void)
+{
+// mobile d - no, a - no
+// wearable d - yes, a - no
+// tv d - no, a - yes
+ if (!display_conf.powerkey_doublepress && !display_conf.lcd_always_on) {
+ lcdoff_powerkey();
+ return true;
+ } else if (display_conf.powerkey_doublepress && !display_conf.lcd_always_on) {
+ if (skip_lcd_off)
+ return false;
+ else
+ return true;
+ } else if (!display_conf.powerkey_doublepress && display_conf.lcd_always_on) {
+ longkey_pressed();
+ return false;
+ }
+
+ return true;
+}
+
+static int process_power_key(struct input_event *pinput)
+{
+ int ignore = true;
+ static int value = KEY_RELEASED;
+ unsigned int caps;
+
+ caps = display_get_caps(DISPLAY_ACTOR_POWER_KEY);
+
+ switch (pinput->value) {
+ case KEY_RELEASED:
+ check_key_pair(pinput->code, pinput->value, &value);
+
+ ignore = release_short_powerkey();
+
+ if (!display_has_caps(caps, DISPLAY_CAPA_LCDON))
+ ignore = true;
+
+ if (longkey_timeout_id > 0) {
+ g_source_remove(longkey_timeout_id);
+ longkey_timeout_id = 0;
+ }
+
+ break;
+ case KEY_PRESSED:
+ if (display_has_caps(caps, DISPLAY_CAPA_LCDON)) {
+ skip_lcd_off = switch_on_lcd();
+ } else {
+ _D("No lcdon capability!");
+ skip_lcd_off = false;
+ }
+ check_key_pair(pinput->code, pinput->value, &value);
+ _I("power key pressed");
+ pressed_time.tv_sec = (pinput->time).tv_sec;
+ pressed_time.tv_usec = (pinput->time).tv_usec;
+ if (key_combination == KEY_COMBINATION_POWERKEY) {
+ /* add long key timer */
+ longkey_timeout_id = g_timeout_add_seconds(
+ display_conf.longpress_interval,
+ longkey_pressed_cb, NULL);
+ }
+ if (skip_lcd_off)
+ ignore = false;
+ cancel_lcdoff = 0;
+
+ break;
+ case KEY_BEING_PRESSED:
+ if (timediff_usec(pressed_time, pinput->time) >
+ (display_conf.longpress_interval * USEC_PER_SEC))
+ longkey_pressed();
+ break;
+ }
+ return ignore;
+}
+
+static int process_screenlock_key(struct input_event *pinput)
+{
+ if (pinput->value != KEY_RELEASED) {
+ stop_key_combination(NULL);
+ return true;
+ }
+
+ if (!current_state_in_on())
+ return false;
+
+ check_processes(S_NORMAL);
+ check_processes(S_LCDDIM);
+
+ if (!check_holdkey_block(S_NORMAL) && !check_holdkey_block(S_LCDDIM)) {
+ delete_condition(S_NORMAL);
+ delete_condition(S_LCDDIM);
+ update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
+
+ /* LCD off forcly */
+ if (disp_plgn.pm_change_internal)
+ disp_plgn.pm_change_internal(-1, LCD_OFF);
+ }
+
+ return true;
+}
+
+static void sound_vibrate_hardkey(void)
+{
+ /* device notify(vibrator) */
+ /* sound(dbus) */
+ /* Need to notify to deviced-vibrator. deviced-vibrator receives ChangedHardKey signal */
+ dbus_handle_broadcast_dbus_signal(DEVICED_PATH_KEY,
+ DEVICED_INTERFACE_KEY,
+ SIGNAL_CHANGE_HARDKEY,
+ NULL, NULL);
+}
+
+static void process_hardkey_backlight(struct input_event *pinput)
+{
+ int opt;
+
+ _E("pinput->value : %d", pinput->value);
+ if (pinput->value == KEY_PRESSED) {
+ if (touch_pressed) {
+ _I("Touch is pressed, then hard key is not working!");
+ return;
+ }
+ /* Sound & Vibrate only in unlock state */
+ if (__get_lock_screen_state() == VCONFKEY_IDLE_UNLOCK
+ || get_lock_screen_bg_state())
+ sound_vibrate_hardkey();
+
+ if (touchled && touchled->execute) {
+ opt = TOUCHLED_PRESS;
+ touchled->execute(&opt);
+ }
+ } else if (pinput->value == KEY_RELEASED) {
+ /* if lockscreen is idle lock */
+ if (__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) {
+ _D("Lock state, key backlight is off when phone is unlocked!");
+ return;
+ }
+
+ if (touchled && touchled->execute) {
+ opt = TOUCHLED_RELEASE;
+ touchled->execute(&opt);
+ }
+ }
+}
+
+static int check_key(struct input_event *pinput, int fd)
+{
+ int ignore = true;
+
+ process_combination_key(pinput);
+ switch (pinput->code) {
+ case KEY_MENU:
+ ignore = process_menu_key(pinput);
+ break;
+ case KEY_POWER:
+ ignore = process_power_key(pinput);
+ if (current_state_in_on())
+ ignore = false;
+ break;
+ case KEY_SCREENLOCK:
+ ignore = process_screenlock_key(pinput);
+ break;
+ case KEY_BACK:
+ case KEY_PHONE:
+ stop_key_combination(NULL);
+ if (current_state_in_on()) {
+ process_hardkey_backlight(pinput);
+ ignore = false;
+ }
+ break;
+ case KEY_VOLUMEUP:
+ case KEY_VOLUMEDOWN:
+ case KEY_CAMERA:
+ case KEY_EXIT:
+ case KEY_CONFIG:
+ case KEY_MEDIA:
+ case KEY_MUTE:
+ case KEY_PLAYPAUSE:
+ case KEY_PLAYCD:
+ case KEY_PAUSECD:
+ case KEY_STOPCD:
+ case KEY_NEXTSONG:
+ case KEY_PREVIOUSSONG:
+ case KEY_REWIND:
+ case KEY_FASTFORWARD:
+ stop_key_combination(NULL);
+ if (current_state_in_on())
+ ignore = false;
+ break;
+ case 0x1DB:
+ case 0x1DC:
+ case 0x1DD:
+ case 0x1DE:
+ stop_key_combination(NULL);
+ break;
+ default:
+ stop_key_combination(NULL);
+ ignore = false;
+ }
+#ifdef ENABLE_PM_LOG
+ if (pinput->value == KEY_PRESSED)
+ pm_history_save(PM_LOG_KEY_PRESS, pinput->code);
+ else if (pinput->value == KEY_RELEASED)
+ pm_history_save(PM_LOG_KEY_RELEASE, pinput->code);
+#endif
+ return ignore;
+}
+
+static int check_key_filter(void *data, int fd)
+{
+ struct input_event *pinput = data;
+ int ignore = true;
+ static int old_fd, code, value;
+
+ assert(pinput);
+
+ switch (pinput->type) {
+ case EV_KEY:
+ if (pinput->code == BTN_TOUCH &&
+ pinput->value == KEY_RELEASED)
+ touch_pressed = false;
+ /*
+ * Normally, touch press/release events don't occur
+ * in lcd off state. But touch release events can occur
+ * in the state abnormally. Then touch events are ignored
+ * when lcd is off state.
+ */
+ if (pinput->code == BTN_TOUCH && !current_state_in_on())
+ break;
+ if (pinput->code == code && pinput->value == value) {
+ _E("Same key(%d, %d) is polled [%d,%d]",
+ code, value, old_fd, fd);
+ }
+ old_fd = fd;
+ code = pinput->code;
+ value = pinput->value;
+
+ ignore = check_key(pinput, fd);
+ restore_custom_brightness();
+
+ break;
+ case EV_REL:
+ ignore = false;
+ break;
+ case EV_ABS:
+ if (current_state_in_on())
+ ignore = false;
+
+ if (ambient_get_condition() == true) {
+ switch_on_lcd();
+ ignore = false;
+ }
+
+ restore_custom_brightness();
+
+ touch_pressed =
+ (pinput->value == TOUCH_RELEASE ? false : true);
+ break;
+ case EV_SW:
+ if (!get_glove_state || !switch_glove_key)
+ break;
+ if (pinput->code == SW_GLOVE &&
+ get_glove_state() == GLOVE_MODE) {
+ switch_glove_key(pinput->value);
+ }
+ break;
+ }
+
+ if (ignore)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Default capability
+ * powerkey := LCDON | LCDOFF | POWEROFF
+ * homekey := LCDON
+ */
+static struct display_actor_ops display_powerkey_actor = {
+ .id = DISPLAY_ACTOR_POWER_KEY,
+ .caps = DISPLAY_CAPA_LCDON |
+ DISPLAY_CAPA_LCDOFF |
+ DISPLAY_CAPA_POWEROFF,
+};
+
+static struct display_actor_ops display_menukey_actor = {
+ .id = DISPLAY_ACTOR_MENU_KEY,
+ .caps = DISPLAY_CAPA_LCDON,
+};
+
+static void keyfilter_init(void)
+{
+ display_add_actor(&display_powerkey_actor);
+ display_add_actor(&display_menukey_actor);
+
+ touchled = find_device(TOUCHLED_NAME);
+
+ register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+}
+
+static void keyfilter_exit(void)
+{
+ unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+}
+
+static void key_backlight_enable(bool enable)
+{
+ int opt;
+
+ if (!touchled || !touchled->execute)
+ return;
+
+ if (enable)
+ opt = TOUCHLED_DIRECT_ON;
+ else
+ opt = TOUCHLED_DIRECT_OFF;
+
+ touchled->execute(&opt);
+}
+
+static const struct display_keyfilter_ops normal_keyfilter_ops = {
+ .init = keyfilter_init,
+ .exit = keyfilter_exit,
+ .check = check_key_filter,
+ .set_powerkey_ignore = NULL,
+ .powerkey_lcdoff = NULL,
+ .backlight_enable = key_backlight_enable,
+};
+
+const struct display_keyfilter_ops *keyfilter_ops = &normal_keyfilter_ops;
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 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 lock-detector.c
+ * @brief
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "util.h"
+#include "core.h"
+#include "core/list.h"
+
+struct lock_info {
+ unsigned long hash;
+ char *name;
+ int state;
+ int count;
+ long locktime;
+ long unlocktime;
+ long time;
+};
+
+#define LIMIT_COUNT 128
+
+static dd_list *lock_info_list;
+
+static long get_time(void)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return (long)(now.tv_sec * 1000 + now.tv_usec / 1000);
+}
+
+static void shrink_lock_info_list(void)
+{
+ dd_list *l, *l_prev;
+ struct lock_info *info;
+ unsigned int count;
+
+ count = DD_LIST_LENGTH(lock_info_list);
+ if (count <= LIMIT_COUNT)
+ return;
+ _D("list is shrink : count %d", count);
+
+ DD_LIST_REVERSE_FOREACH_SAFE(lock_info_list, l, l_prev, info) {
+ if (info->locktime == 0) {
+ DD_LIST_REMOVE_LIST(lock_info_list, l);
+ if (info->name)
+ free(info->name);
+ free(info);
+ count--;
+ }
+ if (count <= (LIMIT_COUNT / 2))
+ break;
+ }
+}
+
+int set_lock_time(const char *pname, int state)
+{
+ struct lock_info *info;
+ dd_list *l;
+ unsigned long val;
+
+ if (!pname)
+ return -EINVAL;
+
+ if (state < S_NORMAL || state > S_SLEEP)
+ return -EINVAL;
+
+ val = g_str_hash(pname);
+
+ DD_LIST_FOREACH(lock_info_list, l, info)
+ if (info->hash == val &&
+ !strncmp(info->name, pname, strlen(pname)+1) &&
+ info->state == state) {
+ info->count += 1;
+ if (info->locktime == 0)
+ info->locktime = get_time();
+ info->unlocktime = 0;
+ DD_LIST_REMOVE(lock_info_list, info);
+ DD_LIST_PREPEND(lock_info_list, info);
+ return 0;
+ }
+
+ info = malloc(sizeof(struct lock_info));
+ if (!info) {
+ _E("Malloc is failed for lock_info!");
+ return -ENOMEM;
+ }
+
+ info->hash = val;
+ info->name = strndup(pname, strlen(pname));
+ info->state = state;
+ info->count = 1;
+ info->locktime = get_time();
+ info->unlocktime = 0;
+ info->time = 0;
+
+ DD_LIST_APPEND(lock_info_list, info);
+
+ return 0;
+}
+
+int set_unlock_time(const char *pname, int state)
+{
+ bool find = false;
+ long diff;
+ struct lock_info *info;
+ dd_list *l;
+ unsigned long val;
+
+ if (!pname)
+ return -EINVAL;
+
+ if (state < S_NORMAL || state > S_SLEEP)
+ return -EINVAL;
+
+ val = g_str_hash(pname);
+
+ DD_LIST_FOREACH(lock_info_list, l, info)
+ if (info->hash == val &&
+ !strncmp(info->name, pname, strlen(pname)+1) &&
+ info->state == state) {
+ DD_LIST_REMOVE(lock_info_list, info);
+ DD_LIST_PREPEND(lock_info_list, info);
+ find = true;
+ break;
+ }
+
+ if (!find)
+ return -EINVAL;
+
+ if (info->locktime == 0)
+ return -EINVAL;
+
+ /* update time */
+ info->unlocktime = get_time();
+ diff = info->unlocktime - info->locktime;
+ if (diff > 0)
+ info->time += diff;
+ info->locktime = 0;
+
+ if (DD_LIST_LENGTH(lock_info_list) > LIMIT_COUNT)
+ shrink_lock_info_list();
+
+ return 0;
+}
+
+void free_lock_info_list(void)
+{
+ dd_list *l, *l_next;
+ struct lock_info *info;
+
+ if (!lock_info_list)
+ return;
+
+ DD_LIST_FOREACH_SAFE(lock_info_list, l, l_next, info) {
+ DD_LIST_REMOVE(lock_info_list, info);
+ if (info->name)
+ free(info->name);
+ free(info);
+ }
+ lock_info_list = NULL;
+}
+
+void print_lock_info_list(int fd)
+{
+ struct lock_info *info;
+ dd_list *l;
+ char buf[255];
+ int ret;
+
+ if (!lock_info_list)
+ return;
+
+ snprintf(buf, sizeof(buf),
+ "current time : %ld ms\n", get_time());
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ snprintf(buf, sizeof(buf),
+ "[%10s %6s] %6s %10s %10s %10s %s\n", "hash", "state",
+ "count", "locktime", "unlocktime", "time", "process name");
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+
+ DD_LIST_FOREACH(lock_info_list, l, info) {
+ long time = 0;
+ if (info->locktime != 0 && info->unlocktime == 0)
+ time = get_time() - info->locktime;
+ snprintf(buf, sizeof(buf),
+ "[%10lu %6d] %6d %10ld %10ld %10ld %s\n",
+ info->hash,
+ info->state,
+ info->count,
+ info->locktime,
+ info->unlocktime,
+ info->time + time,
+ info->name);
+ ret = write(fd, buf, strlen(buf));
+ if (ret < 0)
+ _E("write() failed (%d)", errno);
+ }
+}
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @file poll.c
+ * @brief Power Manager poll implementation
+ *
+ */
+
+#include <stdio.h>
+#include "util.h"
+#include "core.h"
+#include "poll.h"
+#include "display/display-ops.h"
+
+#define SHIFT_UNLOCK 4
+#define SHIFT_UNLOCK_PARAMETER 12
+#define SHIFT_CHANGE_STATE 8
+#define SHIFT_CHANGE_TIMEOUT 20
+#define LOCK_FLAG_SHIFT 16
+#define __HOLDKEY_BLOCK_BIT 0x1
+#define HOLDKEY_BLOCK_BIT (__HOLDKEY_BLOCK_BIT << LOCK_FLAG_SHIFT)
+
+static PMMsg recv_data;
+extern struct display_plugin disp_plgn;
+
+int check_dimstay(int next_state, int flag)
+{
+ if (next_state != LCD_OFF)
+ return false;
+
+ if (!(flag & GOTO_STATE_NOW))
+ return false;
+
+ if (!(pm_status_flag & DIMSTAY_FLAG))
+ return false;
+
+ return true;
+}
+
+static enum state_t get_state(int s_bits)
+{
+ switch (s_bits) {
+ case LCD_NORMAL:
+ return S_NORMAL;
+ case LCD_DIM:
+ return S_LCDDIM;
+ case LCD_OFF:
+ return S_LCDOFF;
+ case STANDBY:
+ return S_STANDBY;
+ case SUSPEND:
+ return S_SLEEP;
+ default:
+ return -EINVAL;
+ }
+}
+
+static bool state_supported(enum state_t st)
+{
+ if (states[st].trans)
+ return true;
+ return false;
+}
+
+static int __pm_lock_internal(pid_t pid, int s_bits, int flag, int timeout)
+{
+ int cond;
+
+ if (!pm_callback)
+ return -1;
+
+ cond = get_state(s_bits);
+ if (cond < 0)
+ return cond;
+
+ if (!state_supported(cond))
+ return -ENOTSUP;
+
+ cond = SET_COND_REQUEST(cond, PM_REQUEST_LOCK);
+
+ if (flag & GOTO_STATE_NOW)
+ /* if the flag is true, go to the locking state directly */
+ cond = SET_COND_FLAG(cond, PM_REQUEST_CHANGE);
+
+ if (flag & HOLD_KEY_BLOCK)
+ cond = SET_COND_FLAG(cond, PM_FLAG_BLOCK_HOLDKEY);
+
+ recv_data.pid = pid;
+ recv_data.cond = cond;
+ recv_data.timeout = timeout;
+
+ (*pm_callback)(PM_CONTROL_EVENT, &recv_data);
+
+ return 0;
+}
+
+static int __pm_unlock_internal(pid_t pid, int s_bits, int flag)
+{
+ int cond;
+
+ if (!pm_callback)
+ return -1;
+
+ cond = get_state(s_bits);
+ if (cond < 0)
+ return cond;
+
+ if (!state_supported(cond))
+ return -ENOTSUP;
+
+ cond = SET_COND_REQUEST(cond, PM_REQUEST_UNLOCK);
+
+ if (flag & PM_KEEP_TIMER)
+ cond = SET_COND_FLAG(cond, PM_FLAG_KEEP_TIMER);
+
+ if (flag & PM_RESET_TIMER)
+ cond = SET_COND_FLAG(cond, PM_FLAG_RESET_TIMER);
+
+ recv_data.pid = pid;
+ recv_data.cond = cond;
+ recv_data.timeout = 0;
+
+ (*pm_callback)(PM_CONTROL_EVENT, &recv_data);
+
+ return 0;
+}
+
+static int __pm_change_internal(pid_t pid, int s_bits)
+{
+ int cond;
+
+ if (!pm_callback)
+ return -1;
+
+ cond = get_state(s_bits);
+ if (cond < 0)
+ return cond;
+
+ if (!state_supported(cond))
+ return -ENOTSUP;
+
+ cond = SET_COND_REQUEST(cond, PM_REQUEST_CHANGE);
+
+ recv_data.pid = pid;
+ recv_data.cond = cond;
+ recv_data.timeout = 0;
+
+ (*pm_callback)(PM_CONTROL_EVENT, &recv_data);
+
+ return 0;
+}
+
+void init_pm_internal()
+{
+ disp_plgn.pm_lock_internal = __pm_lock_internal;
+ disp_plgn.pm_unlock_internal = __pm_unlock_internal;
+ disp_plgn.pm_change_internal = __pm_change_internal;
+}
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 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 <errno.h>
+#include <stdbool.h>
+#include <bundle.h>
+#include <eventsystem.h>
+
+#include "ambient-mode.h"
+#include "core.h"
+#include "util.h"
+#include "setting.h"
+#include "display-ops.h"
+
+#define LCD_DIM_RATIO 0.3
+#define LCD_MAX_DIM_TIMEOUT 7000
+#define LCD_MIN_DIM_TIMEOUT 500
+
+extern struct display_plugin disp_plgn;
+static const char *setting_keys[SETTING_GET_END] = {
+ [SETTING_TO_NORMAL] = VCONFKEY_SETAPPL_LCD_TIMEOUT_NORMAL,
+ [SETTING_BRT_LEVEL] = VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+ [SETTING_LOCK_SCREEN] = VCONFKEY_IDLE_LOCK_STATE,
+ [SETTING_POWER_CUSTOM_BRIGHTNESS] = VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS,
+};
+
+static int lock_screen_state = VCONFKEY_IDLE_UNLOCK;
+static bool lock_screen_bg_state = false;
+static int force_lcdtimeout = 0;
+static int custom_on_timeout = 0;
+static int custom_normal_timeout = 0;
+static int custom_dim_timeout = 0;
+
+static void display_state_send_system_event(int state)
+{
+ bundle *b;
+ const char *str;
+
+ if (state == S_NORMAL)
+ str = EVT_VAL_DISPLAY_NORMAL;
+ else if (state == S_LCDDIM)
+ str = EVT_VAL_DISPLAY_DIM;
+ else if (state == S_LCDOFF)
+ str = EVT_VAL_DISPLAY_OFF;
+ else
+ return;
+
+ _I("eventsystem (%s)", str);
+
+ b = bundle_create();
+ bundle_add_str(b, EVT_KEY_DISPLAY_STATE, str);
+ eventsystem_send_system_event(SYS_EVENT_DISPLAY_STATE, b);
+ bundle_free(b);
+}
+
+int set_force_lcdtimeout(int timeout)
+{
+ if (timeout < 0)
+ return -EINVAL;
+
+ force_lcdtimeout = timeout;
+
+ return 0;
+}
+
+int __get_lock_screen_state(void)
+{
+ return lock_screen_state;
+}
+
+void set_lock_screen_state(int state)
+{
+ switch (state) {
+ case VCONFKEY_IDLE_LOCK:
+ case VCONFKEY_IDLE_UNLOCK:
+ lock_screen_state = state;
+ break;
+ default:
+ lock_screen_state = VCONFKEY_IDLE_UNLOCK;
+ }
+}
+
+int get_lock_screen_bg_state(void)
+{
+ return lock_screen_bg_state;
+}
+
+void set_lock_screen_bg_state(bool state)
+{
+ _I("state is %d", state);
+ lock_screen_bg_state = state;
+}
+
+int set_setting_pmstate(int val)
+{
+ static int old = -1;
+
+ if (old == val)
+ return 0;
+ old = val;
+
+ display_state_send_system_event(val);
+ return vconf_set_int(VCONFKEY_PM_STATE, val);
+}
+
+int get_setting_brightness(int *level)
+{
+ return vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, level);
+}
+
+void get_dim_timeout(int *dim_timeout)
+{
+ int vconf_timeout, on_timeout, val, ret;
+
+ if (custom_dim_timeout > 0) {
+ *dim_timeout = custom_dim_timeout;
+ return;
+ }
+
+ if (ambient_get_condition() == true) {
+ *dim_timeout = LCD_MIN_DIM_TIMEOUT;
+ return;
+ }
+
+ ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout);
+ if (ret != 0) {
+ _E("Failed ro get setting timeout!");
+ vconf_timeout = DEFAULT_NORMAL_TIMEOUT;
+ }
+
+ if (force_lcdtimeout > 0)
+ on_timeout = SEC_TO_MSEC(force_lcdtimeout);
+ else
+ on_timeout = SEC_TO_MSEC(vconf_timeout);
+
+ val = (double)on_timeout * LCD_DIM_RATIO;
+ if (val > LCD_MAX_DIM_TIMEOUT)
+ val = LCD_MAX_DIM_TIMEOUT;
+
+ *dim_timeout = val;
+}
+
+void get_run_timeout(int *timeout)
+{
+ int dim_timeout = -1;
+ int vconf_timeout = -1;
+ int on_timeout;
+ int ret;
+
+ if (custom_normal_timeout > 0) {
+ *timeout = custom_normal_timeout;
+ return;
+ }
+
+ ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout);
+ if (ret != 0) {
+ _E("Failed ro get setting timeout!");
+ vconf_timeout = DEFAULT_NORMAL_TIMEOUT;
+ }
+
+ if (force_lcdtimeout > 0)
+ on_timeout = SEC_TO_MSEC(force_lcdtimeout);
+ else
+ on_timeout = SEC_TO_MSEC(vconf_timeout);
+
+ if (on_timeout == 0) {
+ *timeout = on_timeout;
+ return;
+ }
+
+ get_dim_timeout(&dim_timeout);
+ *timeout = on_timeout - dim_timeout;
+}
+
+int set_custom_lcdon_timeout(int timeout)
+{
+ int changed = (custom_on_timeout == timeout ? false : true);
+
+ custom_on_timeout = timeout;
+
+ if (timeout <= 0) {
+ custom_normal_timeout = 0;
+ custom_dim_timeout = 0;
+ return changed;
+ }
+
+ custom_dim_timeout = (double)timeout * LCD_DIM_RATIO;
+ custom_normal_timeout = timeout - custom_dim_timeout;
+
+ _I("custom normal(%d), dim(%d)", custom_normal_timeout,
+ custom_dim_timeout);
+
+ return changed;
+}
+
+static int setting_cb(keynode_t *key_nodes, void *data)
+{
+ keynode_t *tmp = key_nodes;
+ int index;
+
+ index = (int)((intptr_t)data);
+ if (index > SETTING_END) {
+ _E("Unknown setting key: %s, idx=%d",
+ vconf_keynode_get_name(tmp), index);
+ return -1;
+ }
+ if (disp_plgn.update_pm_setting)
+ disp_plgn.update_pm_setting(index, vconf_keynode_get_int(tmp));
+
+ return 0;
+}
+
+int init_setting(int (*func) (int key_idx, int val))
+{
+ int i;
+
+ if (func != NULL) {
+ disp_plgn.update_pm_setting = func;
+ }
+
+ for (i = SETTING_BEGIN; i < SETTING_GET_END; i++) {
+ /*
+ * To pass an index data through the vconf infratstructure
+ * without memory allocation, an index data becomes typecast
+ * to proper pointer size on each architecture.
+ */
+ vconf_notify_key_changed(setting_keys[i], (void *)setting_cb,
+ (void *)((intptr_t)i));
+ }
+
+ disp_plgn.get_lock_screen_state = __get_lock_screen_state;
+
+ return 0;
+}
+
+int exit_setting(void)
+{
+ int i;
+ for (i = SETTING_BEGIN; i < SETTING_GET_END; i++)
+ vconf_ignore_key_changed(setting_keys[i], (void *)setting_cb);
+
+ return 0;
+}
+