+++ /dev/null
-/*
- * deviced
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * 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 <stdbool.h>
-#include <time.h>
-
-#include "shared/common.h"
-#include "core/log.h"
-#include "shared/device-notifier.h"
-#include "shared/devices.h"
-#include "display/display-ops.h"
-#include "display/display-lock.h"
-#include "power/power.h"
-#include "power/power-off.h"
-#include "power/power-suspend.h"
-#include "core.h"
-#include "poll.h"
-#include "device-interface.h"
-#include "util.h"
-#include "shared/plugin.h"
-
-#define PRE_STATE_CHANGE_TIMEOUT 500*1000 /* 500ms */
-#define SIGNAL_CHANGE_STATE "ChangeState"
-#define SIGNAL_PRE_CHANGE_STATE "PreChangeState"
-#define SIGNAL_WAKEUP "WakeUp"
-#define SIGNAL_PRE_WAKEUP "PreWakeUp"
-#define SIGNAL_POST_WAKEUP "PostWakeUp"
-#define SIGNAL_EARLY_WAKEUP "EarlyWakeUp"
-
-static struct display_plugin *disp_plgn;
-static struct _backlight_ops *backlight_ops;
-static guint standby_timer;
-
-static int change_state(pid_t pid, int type, enum state_t st)
-{
- int ret;
-
- if (type == PM_CONTROL_EVENT && state_st(st)->check) {
- ret = state_st(get_pm_cur_state())->check(get_pm_cur_state(), st);
- if (ret != 0) {
- _E("(%s) State Locked. Cannot be changed to (%s)",
- state_st(get_pm_cur_state())->name, state_st(st)->name);
- return ret;
- }
- }
-
- if (state_st(st)->trans) {
- ret = state_st(st)->trans(type);
- if (ret < 0) {
- _E("Failed to trans state (%s, ret:%d)", state_st(st)->name, ret);
- return ret;
- }
- }
-
- _I("Success to change state (%s) requested by pid(%d)", state_st(st)->name, pid);
-
- return 0;
-}
-
-static int tv_proc_change_state(unsigned int cond, pid_t pid)
-{
- enum state_t next;
- int ret;
-
- next = GET_COND_STATE(cond);
- if (get_pm_cur_state() == next) {
- _I("current state (%d) == next state (%d)", get_pm_cur_state(), next);
- return 0;
- }
-
- if (pid < INTERNAL_LOCK_BASE) { /* Request from other process*/
- if (next == S_SUSPEND || next == S_POWEROFF) {
- _E("Do not change to suspend or power off directly");
- return -EPERM;
- }
- }
-
- _I("Change State to %s (%d)", state_st(next)->name, pid);
-
- ret = change_state(pid, PM_CONTROL_EVENT, next);
- if (ret != 0) {
- _E("Failed to change state (%d)", ret);
- return ret;
- }
-
- return 0;
-}
-
-unsigned long long get_uptime(void)
-{
- struct timespec t;
- clock_gettime(CLOCK_MONOTONIC, &t);
- return t.tv_sec;
-}
-
-static int lcdon_check(int curr, int next)
-{
- /* do not changed to next state if who lock the normal mode */
- check_processes(get_pm_cur_state());
- if (check_lock_state(get_pm_cur_state())) {
- _I("S_LCDON Lock state");
- return 1;
- }
-
- return 0;
-}
-
-static int lcdon_pre(void *data)
-{
- int ret;
- /* TODO: cancel suspend */
-
- /* That will unlock callback registration in case of getting back to normal
- * from partial poweroff. If someone start poweroff with standby lock and then
- * unlock, change state to lcdon, registration of poweroff callback would be blocked
- * as unblocking is done when resuming from suspend.
- */
- device_notify(DEVICE_NOTIFIER_POWER_RESUME, NULL);
-
- if (get_pm_cur_state() == S_STANDBY) {
- _I("send pre state change NORMAL");
- ret = gdbus_signal_emit(NULL,
- DEVICED_PATH_DISPLAY,
- DEVICED_INTERFACE_DISPLAY,
- SIGNAL_PRE_CHANGE_STATE,
- g_variant_new("(s)", state_st(S_LCDON)->name));
- if (ret < 0)
- _E("Failed to send dbus signal(%s)", SIGNAL_PRE_CHANGE_STATE);
- /*Give time to process callback */
- usleep(PRE_STATE_CHANGE_TIMEOUT);
- }
-
- return 0;
-}
-
-static int lcdon_post(void *data)
-{
- int ret;
-
- ret = gdbus_signal_emit(NULL,
- DEVICED_PATH_DISPLAY,
- DEVICED_INTERFACE_DISPLAY,
- SIGNAL_CHANGE_STATE,
- g_variant_new("(s)", state_st(S_LCDON)->name));
- if (ret < 0)
- _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE);
-
- /* TODO: set_power */
-
- return 0;
-}
-
-static int lcdon_action(int timeout)
-{
- if ((get_pm_cur_state() != get_pm_old_state()) &&
- (get_pm_cur_state() != S_SLEEP))
- set_setting_pmstate(get_pm_cur_state());
-
- if ((get_pm_old_state() != S_LCDOFF) &&
- (get_pm_old_state() != S_SLEEP)) {
- _I("pm_old_state (%s). Skip lcd on", state_st(get_pm_old_state())->name);
- return 0;
- }
-
- /* TODO: post resume */
-
- backlight_ops->on(0);
-
- return 0;
-}
-
-static int lcdon_trans(int evt)
-{
- int ret;
- struct state *st;
-
- ret = lcdon_pre(NULL);
- if (ret < 0) {
- _E("S_LCDON pre-operation failed(%d)", ret);
- return ret;
- }
-
- /* state transition */
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_LCDON);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- ret = lcdon_post(NULL);
- if (ret < 0)
- _E("S_LCDON post-operation failed(%d)", ret);
-
- return 0;
-}
-
-static int lcdoff_check(int curr, int next)
-{
- /* LCD OFF can change to LCD ON and STANDBY state */
- return 0;
-}
-
-static int lcdoff_pre(void *data)
-{
- return 0;
-}
-
-static int lcdoff_post(void *data)
-{
- int ret;
-
- /* broadcast to other application */
- ret = gdbus_signal_emit(NULL,
- DEVICED_PATH_DISPLAY,
- DEVICED_INTERFACE_DISPLAY,
- SIGNAL_CHANGE_STATE,
- g_variant_new("(s)", state_st(S_LCDOFF)->name));
- if (ret < 0)
- _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE);
-
- return 0;
-}
-
-static int lcdoff_action(int timeout)
-{
- if ((get_pm_cur_state() != get_pm_old_state()) &&
- (get_pm_cur_state() != S_SLEEP))
- set_setting_pmstate(get_pm_cur_state());
-
- if ((get_pm_old_state() == S_SUSPEND) ||
- (get_pm_old_state() == S_LCDOFF))
- return 0;
-
- backlight_ops->off(0);
-
- return 0;
-}
-
-static int lcdoff_trans(int evt)
-{
- int ret;
- struct state *st;
-
- ret = lcdoff_pre(NULL);
- if (ret < 0) {
- _E("S_LCDOFF pre-operation failed (%d)", ret);
- return ret;
- }
-
- /* state transition */
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_LCDOFF);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- ret = lcdoff_post(NULL);
- if (ret < 0)
- _E("S_LCDOFF post-operation failed (%d)", ret);
-
- return 0;
-}
-
-static int standby_check(int curr, int next)
-{
- /* STANDBY can change to LCD ON or POWER OFF state */
- if (next == S_LCDOFF)
- return -EPERM;
-
- /* do not change to next state if who lock the standby mode */
- check_processes(S_LCDOFF);
- if (check_lock_state(S_LCDOFF)) {
- _I("S_LCDOFF Lock state");
- return 1;
- }
-
- /* TODO: Instant on timer */
-
- return 0;
-}
-
-static int standby_pre(void *data)
-{
- return 0;
-}
-
-static int standby_post(void *data)
-{
- int ret;
-
- /* broadcast to other application */
- ret = gdbus_signal_emit(NULL,
- DEVICED_PATH_DISPLAY,
- DEVICED_INTERFACE_DISPLAY,
- SIGNAL_CHANGE_STATE,
- g_variant_new("(s)", state_st(S_STANDBY)->name));
- if (ret < 0)
- _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE);
-
- backlight_ops->off(0);
-
- /* Set power */
-
- return 0;
-}
-
-static int poweroff_trans(int evt);
-
-static gboolean standby_go_next_state(void *data)
-{
- int ret = 0;
-
- if (standby_timer) {
- g_source_remove(standby_timer);
- standby_timer = 0;
- }
-
- if (disp_plgn->pm_change_internal)
- ret = disp_plgn->pm_change_internal(INTERNAL_LOCK_SUSPEND, SUSPEND);
- if (ret < 0) {
- _E("Failed to change state to S_SUSPEND. Now Power off !!");
- poweroff_trans(0);
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static int standby_action(int timeout)
-{
- if ((get_pm_cur_state() != get_pm_old_state()) &&
- (get_pm_cur_state() != S_SLEEP))
- set_setting_pmstate(get_pm_cur_state());
-
- backlight_ops->off(0);
-
- standby_timer = g_timeout_add_seconds(0,
- standby_go_next_state, NULL);
- if (!standby_timer)
- _E("Failed to add timer to go to next state of S_STANDBY");
-
- return 0;
-}
-
-static int standby_trans(int evt)
-{
- int ret;
- struct state *st;
-
- ret = standby_pre(NULL);
- if (ret < 0) {
- _E("S_STANDBY pre-operation failed(%d)", ret);
- return ret;
- }
-
- /* state transition */
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_STANDBY);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- ret = standby_post(NULL);
- if (ret < 0)
- _E("S_STANDBY post-operation failed(%d)", ret);
-
- return 0;
-}
-
-static int suspend_check(int curr, int next)
-{
- /* DO NOT USE THIS FUNCTION */
- return 0;
-}
-
-static int suspend_pre(void *data)
-{
- return 0;
-}
-
-static int suspend_post(void *data)
-{
- int ret;
- unsigned int cond = 0;
-
- /* TODO: count InstandOn */
-
- cond = S_LCDON;
- ret = tv_proc_change_state(cond, INTERNAL_LOCK_SUSPEND);
- if (ret < 0)
- _E("Fail to change state to next_state(%s)", state_st(cond)->name);
-
- /* Broadcast pre-wakeup signal */
- ret = gdbus_signal_emit(NULL,
- DEVICED_PATH_POWER,
- DEVICED_INTERFACE_POWER,
- SIGNAL_PRE_WAKEUP,
- g_variant_new("(i)", 0));
- if (ret < 0)
- _E("Failed to send dbus signal(%s)", SIGNAL_PRE_WAKEUP);
-
- /* Notify resume state */
- device_notify(DEVICE_NOTIFIER_POWER_RESUME, NULL);
-
- return 0;
-}
-
-static int suspend_action(int timeout)
-{
- struct state *st;
-
- if ((get_pm_cur_state() != get_pm_old_state()) &&
- (get_pm_cur_state() != S_SLEEP))
- set_setting_pmstate(get_pm_cur_state());
-
- /* TODO: set wakeup count */
-
- /* sleep state : set system mode to SUSPEND */
- pm_suspend();
-
- _I("system wakeup!!");
-
- /* Resume !! */
- /* system waked up by devices */
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_LCDOFF);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- return 0;
-}
-
-static int suspend_trans(int evt)
-{
- int ret;
- struct state *st;
-
- ret = suspend_pre(NULL);
- if (ret < 0) {
- _E("S_SUSPEND pre-operation failed(%d)", ret);
- return ret;
- }
-
- /* state transition */
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_LCDOFF);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- set_pm_old_state(get_pm_cur_state());
- set_pm_cur_state(S_SUSPEND);
- st = state_st(get_pm_cur_state());
-
- if (st->action)
- st->action(0);
-
- ret = suspend_post(NULL);
- if (ret < 0)
- _E("S_SUSPEND post-operation failed(%d)", ret);
-
- return 0;
-}
-
-static int poweroff_check(int curr, int next)
-{
- /* DO NOT USE THIS FUNCTION */
- return 0;
-}
-
-static int poweroff_action(int timeout)
-{
- power_request_change_state(POWER_STATE_POWEROFF, 9000);
-
- return 0;
-}
-
-static int poweroff_trans(int evt)
-{
- struct state *st;
- st = state_st(S_POWEROFF);
- if (st->action)
- st->action(0);
- return 0;
-}
-
-static int display_lock_changed(void *data)
-{
- bool state = (bool)data;
-
- if (get_pm_cur_state() != S_STANDBY)
- return 0;
-
- if (!state)
- standby_go_next_state(NULL);
-
- return 0;
-}
-
-static void set_tv_operations(enum state_t st,
- char *name,
- int (*check) (int curr, int next),
- int (*trans) (int evt),
- int (*action) (int timeout))
-{
- change_state_name(st, name);
- change_state_check(st, check);
- change_state_trans(st, trans);
- change_state_action(st, action);
-}
-
-static struct _tv_states {
- enum state_t state;
- char *name;
- int (*check)(int curr, int next);
- int (*trans)(int evt);
- int (*action)(int timeout);
-} tv_states[] = {
- { S_LCDON, "S_LCDON", lcdon_check, lcdon_trans, lcdon_action },
- { S_LCDDIM, "S_LCDDIM", NULL, NULL, NULL },
- { S_LCDOFF, "S_LCDOFF", lcdoff_check, lcdoff_trans, lcdoff_action },
- { S_STANDBY, "S_STANDBY", standby_check, standby_trans, standby_action },
- { S_SUSPEND, "S_SUSPEND", suspend_check, suspend_trans, suspend_action },
- { S_POWEROFF, "S_POWEROFF", poweroff_check, poweroff_trans, poweroff_action },
-};
-
-void state_tv_init(void)
-{
- int i;
-
- _I("TV Profile !!");
-
- for (i = 0 ; i < ARRAY_SIZE(tv_states) ; i++)
- set_tv_operations(tv_states[i].state,
- tv_states[i].name,
- tv_states[i].check,
- tv_states[i].trans,
- tv_states[i].action);
-
- change_proc_change_state(tv_proc_change_state);
-
- register_notifier(DEVICE_NOTIFIER_DISPLAY_LOCK, display_lock_changed);
-}
-
-void state_tv_deinit(void)
-{
- unregister_notifier(DEVICE_NOTIFIER_DISPLAY_LOCK, display_lock_changed);
-}
-
-static void __CONSTRUCTOR__ initialize(void)
-{
- disp_plgn = get_var_display_plugin();
- if (!disp_plgn)
- _E("Failed to get display plugin variable.");
-
- backlight_ops = get_var_backlight_ops();
- if (!backlight_ops)
- _E("Failed to get backlight operator variable.");
-}