4 * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <hw/touchscreen.h>
22 #include <libsyscommon/dbus-system.h>
25 #include "core/devices.h"
26 #include "core/common.h"
28 #include "core/device-notifier.h"
29 #include "battery/power-supply.h"
30 #include "display/core.h"
31 #include "display/display-ops.h"
32 #include "power/boot.h"
33 #include "shared/plugin.h"
40 static struct display_plugin *disp_plgn;
41 static struct battery_plugin *battery_plgn;
42 static struct touchscreen_device *touchscreen_dev;
43 static int touchscreen_enable = DEVICE_OPS_STATUS_START;
44 static int powersaving_support = true;
46 static int touchscreen_start(enum device_flags flags);
47 static int touchscreen_stop(enum device_flags flags);
49 static int booting_done(void *data);
51 static struct display_config *_display_conf;
52 static struct _backlight_ops *_backlight_ops;
53 static struct battery_status *battery = NULL;
55 static struct _backlight_ops* (*_get_var_backlight_ops)(void);
56 static struct display_config* (*_get_var_display_config)(void);
57 static struct battery_status* (*_get_var_battery_status)(void);
59 static void touchscreen_wakeup_status(keynode_t *key, void *data)
64 if (!_display_conf || !_backlight_ops)
67 _display_conf->touch_wakeup = vconf_keynode_get_bool(key);
69 if (_backlight_ops->get_lcd_power() != DPMS_ON) {
70 if (_display_conf->touch_wakeup)
71 touchscreen_start(NORMAL_MODE);
73 touchscreen_stop(TOUCH_SCREEN_OFF_MODE);
77 static int touchscreen_powersaving(enum ps_mode mode)
82 if (!powersaving_support)
85 if (touchscreen_enable != DEVICE_OPS_STATUS_START)
88 if (mode == POWERSAVING_ON)
90 else if (mode == POWERSAVING_OFF)
95 if (touchscreen_dev && touchscreen_dev->set_powersaving) {
96 ret = touchscreen_dev->set_powersaving(state);
98 _E("Failed to set touch powersaving node.");
103 _I("Set touch powersaving %s.", state ? "ON" : "OFF");
107 static int touchscreen_probe(void *data)
110 struct hw_info *info;
115 ret = hw_get_info(TOUCHSCREEN_HARDWARE_DEVICE_ID,
116 (const struct hw_info **)&info);
118 _E("Failed to load touchscreen shared library: %d", ret);
123 _E("Failed to open touchscreen device: open(NULL)");
127 ret = info->open(info, NULL, (struct hw_common **)&touchscreen_dev);
129 _E("Failed to get touchscreen device structure: %d", ret);
133 _I("Touchscreen device structure load success.");
137 static void touchscreen_exit(void *data)
139 struct hw_info *info;
141 if (!touchscreen_dev)
144 info = touchscreen_dev->common.info;
147 info->close((struct hw_common *)touchscreen_dev);
148 touchscreen_dev = NULL;
151 static int touchscreen_set_state(enum touchscreen_state state)
156 if (!touchscreen_dev) {
157 _E("Touchscreen device structure is not loaded.");
161 if (state != TOUCHSCREEN_ON && state != TOUCHSCREEN_OFF) {
162 _E("Invalid parameter.");
166 if (!touchscreen_dev->set_state) {
167 _E("Touchscreen state change is not supported.");
171 act = (state == TOUCHSCREEN_ON) ? "enable" : "disable";
173 ret = touchscreen_dev->set_state(state);
175 _I("Success to %s touchscreen.", act);
177 _E("Failed to %s touchscreen: %d", act, ret);
182 static int touchscreen_execute(void *data)
184 touchscreen_enable = (int)((intptr_t)data);
188 static int touchscreen_start(enum device_flags flags)
192 if (touchscreen_enable != DEVICE_OPS_STATUS_START)
195 if (!_backlight_ops || !_backlight_ops->get_lcd_power)
198 /* Do not enable touchscreen during silent boot mode */
199 if (silent_boot && !booting_done(NULL))
203 * It is safe to turn touchscreen on before powersaving on/off.
205 ret = touchscreen_set_state(TOUCHSCREEN_ON);
207 state = _backlight_ops->get_lcd_power();
209 if (state == DPMS_OFF)
210 touchscreen_powersaving(POWERSAVING_ON);
212 touchscreen_powersaving(POWERSAVING_OFF);
217 static int touchscreen_stop(enum device_flags flags)
219 if (!_display_conf || !_backlight_ops) {
220 _I("Touchscreen is not initialized.");
225 * Touchscreen control priority
226 * 1. Touchscreen module control by execute(touchscreen_enable)
227 * 2. Device charger status by charging dock
228 * 3. Touch wakeup setting(touch_wakeup_enable) value
229 * 4. Normal mode(Basic request)
231 if (touchscreen_enable != DEVICE_OPS_STATUS_START)
234 if (flags & TOUCH_SCREEN_OFF_MODE) {
235 touchscreen_powersaving(POWERSAVING_OFF);
236 return touchscreen_set_state(TOUCHSCREEN_OFF);
239 if (battery && battery->online_type >= CHARGER_TYPE_WIRE) {
240 _I("Battery charging one %d %d.", battery->online, battery->online_type);
241 return touchscreen_powersaving(POWERSAVING_ON);
244 if (_display_conf->touch_wakeup) {
245 _I("Touch wakeup enabled.");
246 return touchscreen_powersaving(POWERSAVING_ON);
250 touchscreen_powersaving(POWERSAVING_OFF);
251 return touchscreen_set_state(TOUCHSCREEN_OFF);
254 static int touchscreen_dump(FILE *fp, int mode, void *dump_data)
257 enum touchscreen_state state;
259 if (!touchscreen_dev || !touchscreen_dev->get_state)
262 ret = touchscreen_dev->get_state(&state);
264 _E("Failed to get touchscreen state: %d", ret);
266 if (state == TOUCHSCREEN_ON)
267 LOG_DUMP(fp, "Touchscreen is enabled\n");
269 LOG_DUMP(fp, "Touchscreen is disabled\n");
274 static GVariant *dbus_touchscreen_enable(GDBusConnection *conn,
275 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
276 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
279 ret = touchscreen_start(NORMAL_MODE);
281 return g_variant_new("(i)", ret);
284 static GVariant *dbus_touchscreen_disable(GDBusConnection *conn,
285 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
286 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
289 ret = touchscreen_stop(TOUCH_SCREEN_OFF_MODE);
291 return g_variant_new("(i)", ret);
294 static const dbus_method_s dbus_methods[] = {
295 { "Enable", NULL, "i", dbus_touchscreen_enable },
296 { "Disable", NULL, "i", dbus_touchscreen_disable },
297 /* Add methods here */
300 static const dbus_interface_u dbus_interface = {
302 .name = DEVICED_INTERFACE_TOUCH,
303 .methods = dbus_methods,
304 .nr_methods = ARRAY_SIZE(dbus_methods),
307 static int booting_done(void *data)
309 static int done = false;
319 static void touchscreen_init(void *data)
323 _get_var_display_config = dlsym(disp_plgn->handle, "get_display_config");
324 if (_get_var_display_config) {
325 _display_conf = _get_var_display_config();
327 _E("Failed to get display config.");
329 _E("Failed to obtain address of get_display_config, %s.", dlerror());
331 /* 'backlight_ops' is declared static and used a lot of places with same name.
332 * So it fails that fetching symbol directly with name 'backlight_ops'.
333 * To avoid this, fetches getter function 'get_backlight_ops' instead, and
334 * retrieve the 'backlight_ops' by using it */
335 _get_var_backlight_ops = dlsym(disp_plgn->handle, "get_backlight_ops");
336 if (_get_var_backlight_ops) {
337 _backlight_ops = _get_var_backlight_ops();
339 _E("Failed to get backlight operator.");
341 _E("Failed to obtain address of get_backlight_ops, %s.", dlerror());
343 if (battery_plgn->handle) {
344 _get_var_battery_status = dlsym(battery_plgn->handle, "get_var_battery_status");
345 if (_get_var_battery_status) {
346 battery = _get_var_battery_status();
348 _E("Failed to get battery status.");
350 _E("Failed to obtain address of get_var_battery_status, %s.", dlerror());
352 _I("There is no battery module.");
354 if (touchscreen_dev && touchscreen_dev->set_powersaving) {
355 ret = touchscreen_dev->set_powersaving(0);
357 powersaving_support = false;
359 powersaving_support = true;
361 powersaving_support = false;
364 vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_WAKEUP_ENABLE,
365 touchscreen_wakeup_status, NULL);
366 ret = vconf_get_bool(VCONFKEY_SETAPPL_TOUCH_WAKEUP_ENABLE, &val);
367 if (_display_conf && ret == 0)
368 _display_conf->touch_wakeup = val;
371 ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_TOUCH, &dbus_interface);
374 _E("Failed to init dbus method. (%d)", ret);
376 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
379 static const struct device_ops touchscreen_device_ops = {
380 DECLARE_NAME_LEN("touchscreen"),
381 .probe = touchscreen_probe,
382 .init = touchscreen_init,
383 .exit = touchscreen_exit,
384 .start = touchscreen_start,
385 .stop = touchscreen_stop,
386 .dump = touchscreen_dump,
387 .execute = touchscreen_execute,
390 DEVICE_OPS_REGISTER(&touchscreen_device_ops)
392 static void __CONSTRUCTOR__ initialize(void)
394 disp_plgn = get_display_plugin();
396 _E("Failed to get display plugin.");
399 battery_plgn = get_battery_plugin();
401 _E("Failed to get battery plugin.");