4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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.
24 #include <device-node.h>
27 #include "core/edbus-handler.h"
28 #include "core/devices.h"
29 #include "core/common.h"
30 #include "core/list.h"
31 #include "core/device-notifier.h"
32 #include "powersaver/powersaver.h"
35 #define DEFAULT_PMQOS_TIMER 3000
37 #define PMQOS_CONF_PATH "/etc/deviced/pmqos.conf"
44 static dd_list *pmqos_head;
46 int set_cpu_pmqos(const char *name, int val)
50 snprintf(scenario, sizeof(scenario), "%s%s", name, (val ? "Lock" : "Unlock"));
51 _D("Set pm scenario : %s", scenario);
52 device_notify(DEVICE_NOTIFIER_PMQOS, (void *)scenario);
53 return device_set_property(DEVICE_TYPE_CPU, PROP_CPU_PM_SCENARIO, (int)scenario);
56 static int pmqos_cpu_cancel(const char *name)
59 struct pmqos_cpu *cpu;
61 /* Find previous request */
62 DD_LIST_FOREACH(pmqos_head, elem, cpu) {
63 if (!strcmp(cpu->name, name))
67 /* In case of already end up request */
69 _I("%s request is already canceled", name);
74 set_cpu_pmqos(cpu->name, false);
76 /* Delete previous request */
77 DD_LIST_REMOVE(pmqos_head, cpu);
78 ecore_timer_del(cpu->timer);
84 static Eina_Bool pmqos_cpu_timer(void *data)
86 char *name = (char*)data;
89 _I("%s request will be unlocked", name);
90 ret = pmqos_cpu_cancel(name);
92 _E("Can not find %s request", name);
95 return ECORE_CALLBACK_CANCEL;
98 static int pmqos_cpu_request(const char *name, int val)
101 struct pmqos_cpu *cpu;
105 /* Check valid parameter */
106 if (val > DEFAULT_PMQOS_TIMER) {
107 _I("The timer value cannot be higher than default time value(%dms)", DEFAULT_PMQOS_TIMER);
108 val = DEFAULT_PMQOS_TIMER;
111 /* Find previous request */
112 DD_LIST_FOREACH(pmqos_head, elem, cpu) {
113 if (!strcmp(cpu->name, name)) {
114 ecore_timer_reset(cpu->timer);
120 /* In case of first request */
123 timer = ecore_timer_add(val/1000.f, pmqos_cpu_timer, (void*)strdup(name));
127 cpu = malloc(sizeof(struct pmqos_cpu));
129 ecore_timer_del(timer);
132 snprintf(cpu->name, sizeof(cpu->name), "%s", name);
134 DD_LIST_APPEND(pmqos_head, cpu);
139 set_cpu_pmqos(cpu->name, true);
145 static int pmqos_powersaving(void *data)
147 return set_cpu_pmqos("PowerSaving", (int)data);
150 static int pmqos_lowbat(void *data)
152 return set_cpu_pmqos("LowBattery", (int)data);
155 static int pmqos_emergency(void *data)
157 return set_cpu_pmqos("Emergency", (int)data);
160 static int pmqos_poweroff(void *data)
162 return set_cpu_pmqos("PowerOff", (int)data);
165 static int pmqos_ultrapowersaving(void *data)
167 int mode = (int)data;
172 case POWERSAVER_BASIC:
175 case POWERSAVER_ENHANCED:
181 return set_cpu_pmqos("UltraPowerSaving", (int)on);
184 static int pmqos_hall(void *data)
186 return pmqos_cpu_request("LockScreen", (int)data);
189 static DBusMessage *dbus_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
191 DBusMessageIter iter;
196 if (!dbus_message_get_args(msg, NULL,
197 DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) {
198 _E("there is no message");
208 member = dbus_message_get_member(msg);
211 ret = pmqos_cpu_request(member, val);
213 ret = pmqos_cpu_cancel(member);
216 reply = dbus_message_new_method_return(msg);
217 dbus_message_iter_init_append(reply, &iter);
218 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
222 static DBusMessage *dbus_wifi_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
224 DBusMessageIter iter;
230 if (!dbus_message_get_args(msg, NULL,
231 DBUS_TYPE_INT32, &bps,
232 DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) {
233 _E("there is no message");
238 if (bps < 0 || val < 0) {
243 member = dbus_message_get_member(msg);
245 /* combine bps and member */
246 snprintf(name, sizeof(name), "%s%d", member, bps);
249 ret = pmqos_cpu_request(name, val);
251 ret = pmqos_cpu_cancel(name);
254 reply = dbus_message_new_method_return(msg);
255 dbus_message_iter_init_append(reply, &iter);
256 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
260 static DBusMessage *dbus_getdefaultlocktime(E_DBus_Object *obj, DBusMessage *msg)
262 DBusMessageIter iter;
266 ret = DEFAULT_PMQOS_TIMER;
268 reply = dbus_message_new_method_return(msg);
269 dbus_message_iter_init_append(reply, &iter);
270 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
274 static int get_methods_from_conf(const char *path, struct edbus_method **edbus_methods)
276 struct edbus_method *methods;
277 struct pmqos_scenario scenarios = {0,};
280 /* get pmqos table from conf */
281 ret = get_pmqos_table(path, &scenarios);
283 /* release scenarios memory */
284 release_pmqos_table(&scenarios);
288 /* if do not support scenario */
289 if (!scenarios.support)
292 /* if do not have scenarios */
293 if (scenarios.num <= 0)
296 /* allocate edbus methods structure */
297 methods = malloc(sizeof(struct edbus_method)*scenarios.num);
299 _E("failed to allocate methods memory : %s", strerror(errno));
300 /* release scenarios memory */
301 release_pmqos_table(&scenarios);
305 /* set edbus_methods structure */
306 for (i = 0; i < scenarios.num; ++i) {
308 /* if this scenario does not support */
309 if (!scenarios.list[i].support) {
310 _I("do not support [%s] scenario", scenarios.list[i].name);
314 methods[i].member = scenarios.list[i].name;
315 methods[i].signature = "i";
316 methods[i].reply_signature = "i";
317 methods[i].func = dbus_pmqos_handler;
318 _D("support [%s] scenario", scenarios.list[i].name);
321 *edbus_methods = methods;
322 return scenarios.num;
325 /* Add pmqos name as alphabetically */
326 static const struct edbus_method edbus_methods[] = {
327 { "AppLaunch", "i", "i", dbus_pmqos_handler },
328 { "AppLaunchHome", "i", "i", dbus_pmqos_handler },
329 { "BeautyShot", "i", "i", dbus_pmqos_handler },
330 { "Browser", "i", "i", dbus_pmqos_handler },
331 { "BrowserDash", "i", "i", dbus_pmqos_handler },
332 { "BrowserJavaScript", "i", "i", dbus_pmqos_handler },
333 { "BrowserLoading", "i", "i", dbus_pmqos_handler },
334 { "BrowserScroll", "i", "i", dbus_pmqos_handler },
335 { "CallSound", "i", "i", dbus_pmqos_handler },
336 { "CameraBurstShot", "i", "i", dbus_pmqos_handler },
337 { "CameraCaptureAtRec", "i", "i", dbus_pmqos_handler },
338 { "CameraPreview", "i", "i", dbus_pmqos_handler },
339 { "CameraSoundAndShot", "i", "i", dbus_pmqos_handler },
340 { "ContactSearch", "i", "i", dbus_pmqos_handler },
341 { "Emergency", "i", "i", dbus_pmqos_handler },
342 { "GalleryScroll", "i", "i", dbus_pmqos_handler },
343 { "GalleryRotation", "i", "i", dbus_pmqos_handler },
344 { "GetDefaultLockTime", NULL, "i", dbus_getdefaultlocktime },
345 { "GpsSerialCno", "i", "i", dbus_pmqos_handler },
346 { "GpuBoost", "i", "i", dbus_pmqos_handler },
347 { "GpuWakeup", "i", "i", dbus_pmqos_handler },
348 { "HomeScreen", "i", "i", dbus_pmqos_handler },
349 { "ImageViewer", "i", "i", dbus_pmqos_handler },
350 { "IMEInput", "i", "i", dbus_pmqos_handler },
351 { "LockScreen", "i", "i", dbus_pmqos_handler },
352 { "LowBattery", "i", "i", dbus_pmqos_handler },
353 { "MtpSendFile", "i", "i", dbus_pmqos_handler },
354 { "MusicPlayLcdOn", "i", "i", dbus_pmqos_handler },
355 { "PowerSaving", "i", "i", dbus_pmqos_handler },
356 { "ProcessCrashed", "i", "i", dbus_pmqos_handler },
357 { "ReservedMode", "i", "i", dbus_pmqos_handler },
358 { "ScreenMirroring", "i", "i", dbus_pmqos_handler },
359 { "SmemoZoom", "i", "i", dbus_pmqos_handler },
360 { "SVoice", "i", "i", dbus_pmqos_handler },
361 { "WebappLaunch", "i", "i", dbus_pmqos_handler },
362 { "WifiThroughput", "ii", "i", dbus_wifi_pmqos_handler },
363 { "PowerOff", "i", "i", dbus_pmqos_handler },
364 { "WebAppDrag", "i", "i", dbus_pmqos_handler },
365 { "WebAppFlick", "i", "i", dbus_pmqos_handler },
366 { "SensorWakeup", "i", "i", dbus_pmqos_handler },
369 static int booting_done(void *data)
372 struct edbus_method *methods = NULL;
381 /* register edbus methods */
382 ret = register_edbus_method(DEVICED_PATH_PMQOS, edbus_methods, ARRAY_SIZE(edbus_methods));
384 _E("fail to init edbus method(%d)", ret);
386 /* get methods from config file */
387 size = get_methods_from_conf(PMQOS_CONF_PATH, &methods);
389 _E("failed to load configuration file(%s)", PMQOS_CONF_PATH);
391 /* register edbus methods for pmqos */
393 ret = register_edbus_method(DEVICED_PATH_PMQOS, methods, size);
395 _E("fail to init edbus method from conf(%d)", ret);
399 /* register notifier for each event */
400 register_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving);
401 register_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat);
402 register_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency);
403 register_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff);
404 register_notifier(DEVICE_NOTIFIER_PMQOS_ULTRAPOWERSAVING,
405 pmqos_ultrapowersaving);
406 register_notifier(DEVICE_NOTIFIER_PMQOS_HALL, pmqos_hall);
412 static void pmqos_init(void *data)
414 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
417 static void pmqos_exit(void *data)
419 /* unregister notifier for each event */
420 unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving);
421 unregister_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat);
422 unregister_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency);
423 unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff);
424 unregister_notifier(DEVICE_NOTIFIER_PMQOS_ULTRAPOWERSAVING,
425 pmqos_ultrapowersaving);
426 unregister_notifier(DEVICE_NOTIFIER_PMQOS_HALL, pmqos_hall);
429 static const struct device_ops pmqos_device_ops = {
430 .priority = DEVICE_PRIORITY_NORMAL,
436 DEVICE_OPS_REGISTER(&pmqos_device_ops)