Add HBM, LBM module 62/213362/6 accepted/tizen/unified/20190911.111739 submit/tizen/20190909.095136
authorYoungjae Cho <y0.cho@samsung.com>
Wed, 4 Sep 2019 12:16:36 +0000 (21:16 +0900)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Mon, 9 Sep 2019 04:03:25 +0000 (04:03 +0000)
Change-Id: I64a3090092f622f879d2c754e71b5354682936c6
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
conf/org.tizen.system.deviced.conf
conf/wearable-display.conf
plugins/wearable/display/auto-brightness-sensorhub.c [new file with mode: 0644]
plugins/wearable/display/auto-brightness-sensorhub.h [new file with mode: 0644]
plugins/wearable/display/display-handler.c [new file with mode: 0644]
plugins/wearable/display/hbm.c [new file with mode: 0644]
plugins/wearable/display/hbm.h [new file with mode: 0644]
plugins/wearable/display/lbm.c [new file with mode: 0644]
plugins/wearable/display/lbm.h [new file with mode: 0644]
plugins/wearable/display/weaks.h [new file with mode: 0644]

index 0fa137a..5ef074e 100644 (file)
@@ -18,6 +18,7 @@
     <policy user="system_fw">
       <allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.Battery" send_member="power_supply"/>
       <allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.ExtCon"/>
+      <allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.display" send_member="AutoBrightnessChanged"/>
     </policy>
 
     <policy user="security_fw">
index f17b4ca..a3393ea 100644 (file)
@@ -40,4 +40,9 @@ ControlDisplay=no
 PowerKeyDoublePressSupport=yes
 AccelSensorOn=no
 ContinuousSampling=no
-Dimming=no
\ No newline at end of file
+Dimming=no
+LBMsupport=yes
+Level=4
+BrtTable=1,20,40,50,60,70,80,90,95,100
+AodBrightnessLevel=40
+
diff --git a/plugins/wearable/display/auto-brightness-sensorhub.c b/plugins/wearable/display/auto-brightness-sensorhub.c
new file mode 100644 (file)
index 0000000..6e96daf
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 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 <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <vconf.h>
+
+#include "hbm.h"
+#include "lbm.h"
+#include "auto-brightness-sensorhub.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/device-notifier.h"
+#include "battery/power-supply.h"
+
+#define SPECIFIC_MODE_OFF      0
+#define LBM_LEVEL                      110
+#define HBM_LEVEL                      120
+
+#define LOWBATCAPACITY 5
+
+static int auto_brightness_state = SETTING_BRIGHTNESS_AUTOMATIC_OFF;
+
+static void change_brightness_transit(int start, int end)
+{
+       backlight_ops.transit_brt(start, end,
+                       display_conf.brightness_change_step);
+}
+
+static void set_brightness_level(int level)
+{
+       int old_level = 0;
+       if (pm_cur_state != S_NORMAL)
+               return;
+/*
+       if (battery.capacity <= LOWBATCAPACITY && battery.charge_now != CHARGER_CHARGING)
+               return;
+*/
+       _I("level changed! %d", level);
+
+       if ((level > PM_MAX_BRIGHTNESS || level < PM_MIN_BRIGHTNESS) &&
+           (level != LBM_LEVEL && level != HBM_LEVEL && level != SPECIFIC_MODE_OFF)) {
+               _E("Invalid level %d", level);
+               return;
+       }
+
+       backlight_ops.get_brightness(&old_level);
+
+       switch (level) {
+       case LBM_LEVEL:
+               /*
+                * received LBM enable
+                * change brightness to under LBM_BRIGHTNESS_LOW and set lbm state
+                */
+               if (hbm_get_state()) {
+                       hbm_set_state(false);
+                       _I("HBM mode disabled.");
+               }
+               if (!lbm_get_state()) {
+                       lbm_set_state(true);
+                       _I("LBM mode enabled.");
+               }
+               break;
+       case HBM_LEVEL:
+               /* HBM must do not turn on at DIM_STY state. */
+               if (pm_status_flag & DIM_MASK)
+                       break;
+
+               /*
+                * received HBM enable
+                * change brightness to MAX value and set hbm state
+                */
+               if (lbm_get_state()) {
+                       lbm_set_state(false);
+                       _I("Disabling LBM before enabling HBM.");
+               }
+
+               change_brightness_transit(old_level, PM_MAX_BRIGHTNESS);
+               hbm_set_state(true);
+               _I("HBM mode enabled.");
+
+               break;
+       case SPECIFIC_MODE_OFF:
+               /*
+                * received HBM disable
+                * unset hbm state and change brightness to setting value
+                */
+
+               level = backlight_ops.get_default_brt();
+
+               if (hbm_get_state())
+                       hbm_set_state(false);
+
+               if (lbm_get_state())
+                       lbm_set_state(false);
+
+               change_brightness_transit(old_level, level);
+
+               break;
+       default:
+               /*
+                * received automatic brightness by the light sensor
+                */
+               if (auto_brightness_state != SETTING_BRIGHTNESS_AUTOMATIC_ON)
+                       return;
+
+               if (hbm_get_state())
+                       hbm_set_state(false);
+
+               if (lbm_get_state())
+                       lbm_set_state(false);
+
+               if (old_level != level) {
+                       change_brightness_transit(old_level, level);
+                       backlight_ops.set_default_brt(level);
+               }
+
+               break;
+       }
+
+        device_notify(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, NULL);
+}
+
+static void set_default_brightness(void)
+{
+       int default_brt;
+
+       default_brt = backlight_ops.get_default_brt();
+       backlight_ops.set_default_brt(default_brt);
+       backlight_ops.update();
+}
+
+static void set_automatic_state_cb(keynode_t *key_nodes, void *data)
+{
+       if (key_nodes == NULL) {
+               _E("Wrong parameter, key_nodes is null.");
+               return;
+       }
+       auto_brightness_state = vconf_keynode_get_int(key_nodes);
+
+       switch (auto_brightness_state) {
+       case SETTING_BRIGHTNESS_AUTOMATIC_OFF:
+               if (hbm_get_state())
+                       hbm_set_state(false);
+               /* escape dim state if it's in low battery.*/
+               set_brightness_changed_state();
+               set_default_brightness();
+               break;
+       case SETTING_BRIGHTNESS_AUTOMATIC_PAUSE:
+               if (hbm_get_state())
+                       hbm_set_state(false);
+               break;
+       case SETTING_BRIGHTNESS_AUTOMATIC_ON:
+               set_brightness_changed_state();
+               break;
+       default:
+               _E("Invalid value %d.", auto_brightness_state);
+       }
+}
+
+int prepare_level_handler(void)
+{
+       int status, ret;
+
+       display_info.set_brightness_level = set_brightness_level;
+
+       ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
+       if (ret >= 0)
+               auto_brightness_state = status;
+
+       vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+                                set_automatic_state_cb, NULL);
+
+       return 0;
+}
+
+void exit_level_handler(void)
+{
+       vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+                                set_automatic_state_cb);
+       set_default_brightness();
+}
diff --git a/plugins/wearable/display/auto-brightness-sensorhub.h b/plugins/wearable/display/auto-brightness-sensorhub.h
new file mode 100644 (file)
index 0000000..56243fb
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 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.
+ */
+
+
+/**
+ * @file       auto-brightness-sensorhub.h
+ * @brief      auto-brightness-sensorhub header file
+ */
+#ifndef __AUTO_BRT_SENSORHUB_H__
+#define __AUTO_BRT_SENSORHUB_H__
+
+int prepare_level_handler(void);
+void exit_level_handler(void);
+
+#endif
diff --git a/plugins/wearable/display/display-handler.c b/plugins/wearable/display/display-handler.c
new file mode 100644 (file)
index 0000000..11226c6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2016 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <error.h>
+#include <device-node.h>
+
+#include "auto-brightness-sensorhub.h"
+#include "core/device-notifier.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/poll.h"
+#include "core/common.h"
+#include "core/devices.h"
+#include "display/display-actor.h"
+#include "display/display-ops.h"
+#include "display-info.h"
+
+#define CHARGER_LCD_NODE "/sys/class/power_supply/battery/lcd"
+
+enum charging_lcd_state {
+       CHARGING_LCD_OFF = 0,
+       CHARGING_LCD_ON = 1,
+};
+
+static GVariant *dbus_autobrightnesschanged(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 level;
+
+       g_variant_get(param, "(i)", &level);
+
+       if (display_info.set_brightness_level)
+               display_info.set_brightness_level(level);
+       else
+               ret = -ENOTSUP;
+
+       return g_variant_new("(i)", ret);
+}
+
+static const dbus_method_s dbus_methods[] = {
+       { "AutoBrightnessChanged",   "i",   "i", dbus_autobrightnesschanged },
+};
+
+static const dbus_interface_u dbus_interface = {
+       .oh = NULL,
+       .name = DEVICED_INTERFACE_DISPLAY,
+       .methods = dbus_methods,
+       .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+
+static int display_state_changed(void *data)
+{
+       enum state_t state;
+       int ret = 0;
+
+       state = DATA_VALUE_INT(data);
+
+       if (state == S_LCDON)
+               ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_ON);
+       else
+               ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_OFF);
+
+       if (ret < 0)
+               _E("Can't write %s node %d.", CHARGER_LCD_NODE, state);
+
+       return 0;
+}
+
+static void display_handler_init(void *data)
+{
+       int ret;
+
+       prepare_level_handler();
+       register_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+
+       ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_ON);
+       if (ret < 0)
+               _E("Can't write %s node.", CHARGER_LCD_NODE);
+
+       ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+       if (ret < 0)
+               _E("Failed to register dbus object.");
+}
+
+static const struct display_ops display_handler_ops = {
+       .name     = "dislay-handler",
+       .init     = display_handler_init,
+};
+
+DISPLAY_OPS_REGISTER(&display_handler_ops)
diff --git a/plugins/wearable/display/hbm.c b/plugins/wearable/display/hbm.c
new file mode 100644 (file)
index 0000000..4d0fde5
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 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 "weaks.h"
+#include "display-info.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/common.h"
+#include "core/device-notifier.h"
+#include "core/config-parser.h"
+
+#define BOARD_CONF_FILE "/etc/deviced/display.conf"
+
+#define ON             "on"
+#define OFF            "off"
+
+#define SIGNAL_HBM_ON  "HBMOn"
+#define SIGNAL_HBM_OFF "HBMOff"
+
+#define HBM_LEVEL      120
+#define DEFAULT_BRIGHTNESS_LEVEL       80
+
+#define LCD_PATH    "sys/class/lcd/"
+#define HBM_PATH    "/hbm"
+#define DEVICE_PATH "/device"
+#define PATH_BUFFER_MAX    256
+
+static guint timer;
+static struct timespec offtime;
+static char *hbm_path;
+
+static void broadcast_hbm_state(char *state)
+{
+       dbus_handle_emit_dbus_signal(NULL,
+                       DEVICED_PATH_DISPLAY,
+                       DEVICED_INTERFACE_DISPLAY,
+                       state,
+                       NULL);
+}
+
+static void hbm_set_offtime(int timeout)
+{
+       struct timespec now;
+
+       if (timeout <= 0) {
+               offtime.tv_sec = 0;
+               return;
+       }
+
+       clock_gettime(CLOCK_REALTIME, &now);
+       offtime.tv_sec = now.tv_sec + timeout;
+}
+
+static gboolean hbm_off_cb(void *data)
+{
+       int ret;
+
+       timer = 0;
+
+       if (pm_cur_state != S_NORMAL) {
+               _D("Hbm timeout, but it's not display normal.");
+               return G_SOURCE_REMOVE;
+       }
+       hbm_set_offtime(0);
+
+       ret = sys_set_str(hbm_path, OFF);
+       if (ret < 0)
+               _E("Failed to off hbm.");
+
+       ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+           DEFAULT_BRIGHTNESS_LEVEL);
+       if (ret < 0) {
+               _E("Failed to set vconf value lcd brightness, %d.", ret);
+               return G_SOURCE_REMOVE;
+       }
+       backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL);
+       backlight_ops.update();
+       broadcast_hbm_state(SIGNAL_HBM_OFF);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void hbm_start_timer(int timeout)
+{
+       if (timer) {
+               g_source_remove(timer);
+               timer = 0;
+       }
+       if (!timer) {
+               timer = g_timeout_add_seconds(timeout, hbm_off_cb, NULL);
+       }
+}
+
+static void hbm_end_timer(void)
+{
+       if (timer) {
+               g_source_remove(timer);
+               timer = 0;
+       }
+}
+
+int hbm_get_state(void)
+{
+       char state[5];
+       int ret, hbm;
+
+       if (!hbm_path)
+               return -ENODEV;
+
+       ret = sys_get_str(hbm_path, state, sizeof(state));
+       if (ret < 0)
+               return ret;
+
+       if (!strncmp(state, ON, strlen(ON)))
+               hbm = true;
+       else if (!strncmp(state, OFF, strlen(OFF)))
+               hbm = false;
+       else
+               hbm = -EINVAL;
+
+       return hbm;
+}
+
+int hbm_set_state(int hbm)
+{
+       if (!hbm_path)
+               return -ENODEV;
+
+       if (hbm)
+               broadcast_hbm_state(SIGNAL_HBM_ON);
+       else
+               broadcast_hbm_state(SIGNAL_HBM_OFF);
+
+       return sys_set_str(hbm_path, (hbm ? ON : OFF));
+}
+
+static void hbm_turn_on(void)
+{
+       if (!hbm_get_state())
+               hbm_set_state(true);
+}
+
+static void hbm_turn_off(void)
+{
+       if (hbm_get_state())
+               hbm_set_state(false);
+}
+
+static int hbm_set_state_with_timeout(int hbm, int timeout)
+{
+       int ret;
+
+       if (hbm && (timeout <= 0))
+               return -EINVAL;
+
+       ret = hbm_set_state(hbm);
+       if (ret < 0)
+               return ret;
+
+       _D("timeout is %d", timeout);
+
+       if (hbm) {
+               /*
+                * hbm is turned off after timeout.
+                */
+               hbm_set_offtime(timeout);
+               hbm_start_timer(timeout);
+       } else {
+               hbm_set_offtime(0);
+               hbm_end_timer();
+               broadcast_hbm_state(SIGNAL_HBM_OFF);
+       }
+
+       return 0;
+}
+
+void hbm_check_timeout(void)
+{
+       struct timespec now;
+       int ret;
+
+       if (timer) {
+               g_source_remove(timer);
+               timer = 0;
+       }
+
+       if (offtime.tv_sec == 0) {
+               if (hbm_get_state() == true) {
+                       _E("It's invalid state. HBM is turned off.");
+                       hbm_set_state(false);
+               }
+               return;
+       }
+
+       clock_gettime(CLOCK_REALTIME, &now);
+       _D("now %ld, offtime %ld", now.tv_sec, offtime.tv_sec);
+
+       /* check it's timeout */
+       if (now.tv_sec >= offtime.tv_sec) {
+               hbm_set_offtime(0);
+
+               ret = sys_set_str(hbm_path, OFF);
+               if (ret < 0)
+                       _E("Failed to off HBM.");
+               backlight_ops.update();
+               broadcast_hbm_state(SIGNAL_HBM_OFF);
+       } else {
+               _D("HBM state is restored.");
+               hbm_set_state(true);
+               hbm_start_timer(offtime.tv_sec - now.tv_sec);
+       }
+}
+
+static void hbm_get_level(GVariant *var, void *user_data, GError *err)
+{
+       int level, brt;
+
+       if (!var) {
+               _D("Invalid parameter.");
+               return;
+       }
+
+       if (!dh_get_param_from_var(var, "(i)", &level)) {
+               _E("Failed to get message, %s.", g_variant_get_type_string(var));
+               goto out;
+       }
+
+       if (level == HBM_LEVEL && hbm_get_state() == false) {
+               _I("Lux was high already, HBM enable");
+               backlight_ops.get_brightness(&brt);
+               backlight_ops.transit_brt(brt, PM_MAX_BRIGHTNESS,
+                               display_conf.brightness_change_step);
+               hbm_set_state(true);
+       }
+out:
+       g_variant_unref(var);
+}
+
+static gboolean hbm_check_handler(gpointer data)
+{
+       int ret;
+
+       ret = dbus_handle_method_async_with_reply(COORD_BUS_NAME,
+                       COORD_PATH_AUTOBRIGHTNESS,
+                       COORD_INTERFACE_AUTOBRIGHTNESS,
+                       "GetLevel",
+                       NULL,
+                       NULL,
+                       hbm_get_level,
+                       -1,
+                       NULL);
+
+       if (ret < 0)
+               _D("Failed to call coord.autobrightness.GetLevel method, %d", ret);
+
+       return G_SOURCE_REMOVE;
+}
+
+static int display_state_changed(void *data)
+{
+       int state;
+       int ret;
+
+       state = DATA_VALUE_INT(data);
+
+       if (get_outdoor_setting)
+               if (get_outdoor_setting())
+                       return 0;
+
+       switch (state) {
+       case S_NORMAL:
+               /*
+                * outdoor-enhance-mode not supported
+                *  : check & restore hbm always.
+                * outdoor-enhance-mode supported
+                *  : check & restore hbm when old state is dim only.
+                */
+               if (!get_outdoor_setting || pm_old_state == S_LCDDIM)
+                       hbm_check_timeout();
+
+               (void) g_timeout_add(300, hbm_check_handler, NULL);
+               break;
+       case S_LCDDIM:
+       case S_LCDOFF:
+       case S_SLEEP:
+               if (hbm_get_state() == true) {
+                       ret = hbm_set_state(false);
+                       if (ret < 0)
+                               _E("Failed to off hbm.");
+               }
+               hbm_end_timer();
+               break;
+       }
+
+       return 0;
+}
+
+static int display_off_changed(void *data)
+{
+       int brt;
+
+       if (hbm_get_state() == false)
+               return 0;
+
+       hbm_turn_off();
+
+       brt = backlight_ops.get_default_brt();
+       if (pm_status_flag & DIMSTAY_FLAG)
+               _D("skip auto change brightness");
+       else
+               backlight_ops.transit_brt(PM_MAX_BRIGHTNESS, brt, display_conf.brightness_change_step);
+
+       return 0;
+}
+
+static GVariant *dbus_gethbm(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+       return g_variant_new("(i)", hbm_get_state());
+}
+
+static GVariant *dbus_sethbm_timeout(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+       int hbm, timeout, ret;
+
+       g_variant_get(param, "(ii)", &hbm, &timeout);
+
+       if (timeout <= 0) {
+               _E("Timeout can not be setting(%d).", timeout);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = hbm_set_state_with_timeout(hbm, timeout);
+
+       if (ret < 0)
+               _E("Failed to set HBM (ret=%d, hbm=%d, time=%d).", ret, hbm, timeout);
+       else
+               _I("Set hbm (ret=%d, hbm=%d, time=%d).", ret, hbm, timeout);
+
+out:
+       return g_variant_new("(i)", ret);
+}
+
+static const dbus_method_s dbus_methods[] = {
+       { "GetHBM",          NULL,   "i", dbus_gethbm },
+       { "SetHBMTimeout",   "ii",   "i", dbus_sethbm_timeout },
+};
+
+static const dbus_interface_u dbus_interface = {
+       .oh = NULL,
+       .name = DEVICED_INTERFACE_DISPLAY,
+       .methods = dbus_methods,
+       .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+
+static int hbm_func(unsigned int cmd, void *arg)
+{
+       int ret = 0;
+       int *on;
+       struct hbmsetstate *hss;
+
+       switch (cmd) {
+       case HBM_GET_STATE:
+               ret = hbm_get_state();
+               break;
+       case HBM_SET_STATE:
+               on = (int *)arg;
+               ret = hbm_set_state(*on);
+               break;
+       case HBM_TURN_ON:
+               hbm_turn_on();
+               break;
+       case HBM_TURN_OFF:
+               hbm_turn_off();
+               break;
+       case HBM_SET_TIMEOUT_STATE:
+               hss = (struct hbmsetstate *)arg;
+               ret = hbm_set_state_with_timeout(hss->hbm, hss->timeout);
+               break;
+       case HBM_TURN_OFF_STATE:
+               hbm_turn_off();
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static char *check_and_copy_path(char *path)
+{
+       int fd;
+       char *buf = NULL;
+
+       fd = open(path, O_RDONLY);
+       if (fd >= 0) {
+               buf = strndup(path, strlen(path));
+               close(fd);
+       } else {
+               _E("Failed to open HBM node.");
+       }
+
+       return buf;
+}
+
+static char *find_hbm_node()
+{
+       DIR *d;
+       struct dirent *dir;
+       char buf[PATH_BUFFER_MAX];
+       char *result = NULL;
+
+       d = opendir(LCD_PATH);
+       if (!d)
+               return NULL;
+
+       while ((dir = readdir(d))) {
+               if (dir->d_name[0] == '.')
+                       continue;
+
+               snprintf(buf, sizeof(buf), "%s%s%s", LCD_PATH,
+                   dir->d_name, HBM_PATH);
+
+               result = check_and_copy_path(buf);
+               if (result)
+                       break;
+
+               snprintf(buf, sizeof(buf), "%s%s%s%s", LCD_PATH,
+                   dir->d_name, DEVICE_PATH, HBM_PATH);
+
+               result = check_and_copy_path(buf);
+               if (result)
+                       break;
+       }
+       closedir(d);
+
+       return result;
+}
+
+static void hbm_init(void *data)
+{
+       int ret;
+
+       hbm_path = find_hbm_node();
+
+       if (!hbm_path) {
+               _E("Failed to find HBM node.");
+               return;
+       } else {
+               _I("HBM node: %s.", hbm_path);
+       }
+
+       ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+       if (ret < 0)
+               _E("Failed to register dbus object.");
+
+       /* register notifier */
+       register_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+       register_notifier(DEVICE_NOTIFIER_LCD_OFF, display_off_changed);
+}
+
+static void hbm_exit(void *data)
+{
+       /* unregister notifier */
+       unregister_notifier(DEVICE_NOTIFIER_LCD_OFF, display_off_changed);
+       unregister_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+
+       /*
+        * set default brightness
+        * if display logic is stopped in hbm state.
+        */
+       if (hbm_get_state() == true) {
+               hbm_set_offtime(0);
+               _I("set brightness to default value!");
+       }
+}
+
+static const struct display_ops display_hbm_ops = {
+       .name     = "hbm",
+       .init     = hbm_init,
+       .exit     = hbm_exit,
+       .func     = hbm_func,
+};
+
+DISPLAY_OPS_REGISTER(&display_hbm_ops)
+
diff --git a/plugins/wearable/display/hbm.h b/plugins/wearable/display/hbm.h
new file mode 100644 (file)
index 0000000..d555152
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 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.
+ */
+
+
+/**
+ * @file       hbm.h
+ * @brief      High Brightness Mode header file
+ */
+#ifndef __HBM_H__
+#define __HBM_H__
+
+/*
+ * @brief Configuration structure
+ */
+struct hbm_config {
+       int on;
+       int off;
+       int on_count;
+       int off_count;
+};
+
+int hbm_get_state(void);
+int hbm_set_state(int hbm);
+
+/*
+ * Global variables
+ *   hbm_conf : configuration of hbm
+ */
+extern struct hbm_config hbm_conf;
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/plugins/wearable/display/lbm.c b/plugins/wearable/display/lbm.c
new file mode 100644 (file)
index 0000000..c098efd
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. 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 <stdbool.h>
+#include <math.h>
+
+#include "lbm.h"
+#include "display-info.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/common.h"
+#include "core/config-parser.h"
+#include "core/device-notifier.h"
+
+#define DISPLAY_CONF_FILE      "/etc/deviced/display.conf"
+
+#define SIGNAL_LBM_ON  "LBMOn"
+#define SIGNAL_LBM_OFF "LBMOff"
+
+#define LCD_PHASED_DELAY               10000   /* microsecond */
+
+#define LBM_TRANSIT_STEP               20
+
+struct lbm_config lbm_conf = {
+       .support = 0,
+       .down_level = 0,
+       .brt_table_size = 0,
+       .brt_table = NULL,
+       .aod_brightness_level = 0,
+};
+
+static bool lbm_state;
+static int lbm_setting_mode;
+static int system_brightness;
+static struct display_device *display_dev;
+
+static void broadcast_lbm_state(int state)
+{
+       char *str;
+
+       if (state == 1)
+               str = SIGNAL_LBM_ON;
+       else
+               str = SIGNAL_LBM_OFF;
+
+       dbus_handle_emit_dbus_signal(NULL,
+                       DEVICED_PATH_DISPLAY,
+                       DEVICED_INTERFACE_DISPLAY,
+                       str,
+                       NULL);
+}
+
+static int get_level_by_brt(int brt)
+{
+       int iter;
+       for (iter = 0; iter < lbm_conf.brt_table_size; iter++) {
+               if (lbm_conf.brt_table[iter] == brt)
+                       return iter;
+       }
+       return -EINVAL;
+}
+
+static int lbm_down_brt(int brt)
+{
+       int level;
+       int down_level;
+
+       if (lbm_conf.down_level == 0) {
+               _I("LBM down level setting is 0.");
+               return brt;
+       }
+
+       if (lbm_conf.brt_table == NULL || lbm_setting_mode == 0) {
+               _I("LBM setting mode is %d.", lbm_setting_mode);
+               return brt;
+       }
+
+       level = get_level_by_brt(brt);
+       down_level = level - lbm_conf.down_level;
+
+       if (down_level < 0)
+               down_level = 0;
+
+       return lbm_conf.brt_table[down_level];
+}
+
+int lbm_get_state(void)
+{
+       if (!lbm_conf.support)
+               return -ENODEV;
+
+       return lbm_state;
+}
+
+static int lbm_get_brightness(int *val)
+{
+       if (system_brightness == 0)
+               _E("Failed to get brightness.");
+
+       *val = system_brightness;
+
+       return 0;
+}
+
+static int lbm_set_brightness(int val)
+{
+       int brt = 0;
+
+       if (!display_dev || !display_dev->set_brightness) {
+               _E("There is no display device.");
+               return -ENOENT;
+       }
+
+       if (pm_status_flag & DIM_MASK)
+               val = 0;
+       else
+               brt = lbm_down_brt(val);
+
+       system_brightness = val;
+
+       _I("Set brightness(LBM on) system=%d, real=%d.", val, brt);
+       device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
+
+       return display_dev->set_brightness(brt);
+}
+
+static void lbm_change_brightness(int start, int end, int step)
+{
+       int diff, val;
+       int ret = -1;
+       int prev;
+
+       if (display_dimstay_check())
+               return;
+
+       ret = backlight_ops.get_brightness(&prev);
+
+       if (ret < 0) {
+               _E("Failed to get brightness, %d.", ret);
+               return;
+       }
+
+       if (prev == end)
+               return;
+
+       if (pm_status_flag & DIM_MASK)
+               end = 0;
+
+       _I("Start %d, end %d, step %d.", start, end, step);
+
+       if (display_dev && display_dev->set_multi_brightness) {
+               diff = lbm_down_brt(end);
+
+               ret = display_dev->set_multi_brightness(diff, step, LCD_PHASED_DELAY);
+               if (ret < 0)
+                       _E("Failed to set_multi_brightness, %d.", ret);
+
+               backlight_ops.set_brightness(end);
+
+               return;
+       }
+
+       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;
+
+               usleep(LCD_PHASED_DELAY);
+               backlight_ops.set_brightness(start);
+       }
+}
+
+int lbm_set_state(int lbm)
+{
+       int brt;
+       _I("lbm_set_state");
+
+       if (lbm == lbm_state) {
+               _W("already lbm %s", (lbm_state ? "on" : "off"));
+               return 0;
+       }
+
+       if (!lbm || lbm_setting_mode) {
+               lbm_state = lbm;
+               broadcast_lbm_state(lbm_state);
+       }
+
+       brt = backlight_ops.get_default_brt();
+       _I("Default brightness: %d", brt);
+       if (lbm && lbm_setting_mode) {
+               _I("Lowering Brightness.");
+               backlight_ops.transit_brt(brt, lbm_down_brt(brt), LBM_TRANSIT_STEP);
+               backlight_ops.get_brightness(&system_brightness);
+               backlight_ops.set_brightness = lbm_set_brightness;
+               backlight_ops.get_brightness = lbm_get_brightness;
+               backlight_ops.transit_brt = lbm_change_brightness;
+       } else {
+               system_brightness = 0;
+               backlight_ops.restore_brightness_func();
+               backlight_ops.transit_brt(lbm_down_brt(brt), brt, display_conf.brightness_change_step);
+       }
+
+       backlight_ops.set_brightness(brt);
+
+       return 0;
+}
+
+static void lbm_table_load(char *value, struct lbm_config *c)
+{
+       char *p, *saveptr;
+       int level_count = 1;
+       int i;
+
+       if (value == '\0')
+               return;
+
+       for (i = 0; *(value + i) != '\0'; i++) {
+               if (*(value + i) == ',')
+                       level_count++;
+       }
+
+       c->brt_table = malloc(sizeof(int) * level_count);
+       if (!c->brt_table) {
+               _E("Failed to allocate memory.");
+               return;
+       }
+       c->brt_table_size = level_count;
+
+       i = 0;
+       p = strtok_r(value, ",", &saveptr);
+       if (p)
+               c->brt_table[i++] = atoi(p);
+
+       while (p != NULL) {
+               p = strtok_r(NULL, ",", &saveptr);
+               if (p)
+                       c->brt_table[i++] = atoi(p);
+       }
+}
+
+static int lbm_load_config(struct parse_result *result, void *user_data)
+{
+       struct lbm_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, "LBMsupport")) {
+               c->support = (MATCH(result->value, "yes") ? 1 : 0);
+               _D("lbm support is %d", c->support);
+       } else if (MATCH(result->name, "Level")) {
+               SET_CONF(c->down_level, atoi(result->value));
+               _D("lbm down level is %d", c->down_level);
+       } else if (MATCH(result->name, "BrtTable")) {
+               lbm_table_load(result->value, c);
+               _D("LBM table loaded.");
+       }
+
+       return 0;
+}
+
+static void lbm_mode_changed(keynode_t *key_nodes, void *data)
+{
+       int mode = vconf_keynode_get_bool(key_nodes);
+
+       _I("LBM setting value is %s.", mode ? "enable" : "disable");
+
+       lbm_setting_mode = mode;
+
+       if (lbm_get_state())
+               lbm_set_state(false);
+}
+
+static int display_off_changed(void *data)
+{
+       int brt;
+
+       backlight_ops.get_brightness(&brt);
+       backlight_ops.restore_brightness_func();
+       backlight_ops.set_brightness(brt);
+
+       lbm_state = 0;
+
+       return 0;
+}
+
+static GVariant *dbus_getlbm(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+       int lbm;
+
+       lbm = lbm_get_state();
+       if (lbm < 0)
+               _E("Failed to get low brightness mode %d.", lbm);
+       else
+               _D("Get low brightness mode %d.", lbm);
+
+       return g_variant_new("(i)", lbm);
+}
+
+static const dbus_method_s dbus_methods[] = {
+       { "GetLBM",          NULL,   "i", dbus_getlbm },
+};
+
+static const dbus_interface_u dbus_interface = {
+       .oh = NULL,
+       .name = DEVICED_INTERFACE_DISPLAY,
+       .methods = dbus_methods,
+       .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+static void lbm_init(void *data)
+{
+       int ret;
+
+       /* load configutation */
+       ret = config_parse(DISPLAY_CONF_FILE, lbm_load_config, &lbm_conf);
+       if (ret < 0)
+               _W("Failed to load %s, %d. Use default value.", DISPLAY_CONF_FILE, ret);
+
+       ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, &lbm_setting_mode);
+       if (ret < 0)
+               _E("Failed to get VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, %d.", ret);
+
+       vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, lbm_mode_changed, NULL);
+
+       ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+       if (ret < 0)
+               _E("Failed to init dbus method, %d.", ret);
+
+       display_dev = display_dev_get();
+
+       _I("LBM setting value is %d.", lbm_setting_mode);
+
+       /* register notifier */
+       register_notifier(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, display_off_changed);
+}
+
+static const struct display_ops display_lbm_ops = {
+       .name     = "lbm",
+       .init     = lbm_init,
+};
+
+DISPLAY_OPS_REGISTER(&display_lbm_ops)
diff --git a/plugins/wearable/display/lbm.h b/plugins/wearable/display/lbm.h
new file mode 100644 (file)
index 0000000..5b1e319
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 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.
+ */
+
+/**
+ * @file       lbm.h
+ * @brief      Low Brightness Mode header file
+ */
+#ifndef __LBM_H__
+#define __LBM_H__
+
+/*
+ * @brief Configuration structure
+ */
+struct lbm_config {
+       int support;
+       int down_level;
+       int brt_table_size;
+       int *brt_table;
+       int aod_brightness_level;
+};
+
+/*
+ * Global variables
+ *   lbm_conf : configuration of lbm
+ */
+struct lbm_config lbm_conf;
+
+int lbm_get_state(void);
+int lbm_set_state(int lbm);
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/plugins/wearable/display/weaks.h b/plugins/wearable/display/weaks.h
new file mode 100644 (file)
index 0000000..e8c764e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+
+#ifndef __DISPLAY_WEAKS_H__
+#define __DISPLAY_WEAKS_H__
+
+#include "core/common.h"
+#include "display/core.h"
+
+bool __WEAK__ get_outdoor_setting(void);
+
+#endif
+