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"
34 #define DEFAULT_PMQOS_TIMER 3000
36 #define PMQOS_CONF_PATH "/etc/deviced/pmqos.conf"
43 static dd_list *pmqos_head;
45 int set_cpu_pmqos(const char *name, int val)
49 snprintf(scenario, sizeof(scenario), "%s%s", name, (val ? "Lock" : "Unlock"));
50 _D("Set pm scenario : %s", scenario);
51 device_notify(DEVICE_NOTIFIER_PMQOS, (void *)scenario);
52 return device_set_property(DEVICE_TYPE_CPU, PROP_CPU_PM_SCENARIO, (int)scenario);
55 static int pmqos_cpu_cancel(const char *name)
58 struct pmqos_cpu *cpu;
60 /* Find previous request */
61 DD_LIST_FOREACH(pmqos_head, elem, cpu) {
62 if (!strcmp(cpu->name, name))
66 /* In case of already end up request */
68 _I("%s request is already canceled", name);
73 set_cpu_pmqos(cpu->name, false);
75 /* Delete previous request */
76 DD_LIST_REMOVE(pmqos_head, cpu);
77 ecore_timer_del(cpu->timer);
83 static Eina_Bool pmqos_cpu_timer(void *data)
85 char *name = (char*)data;
88 _I("%s request will be unlocked", name);
89 ret = pmqos_cpu_cancel(name);
91 _E("Can not find %s request", name);
94 return ECORE_CALLBACK_CANCEL;
97 static int pmqos_cpu_request(const char *name, int val)
100 struct pmqos_cpu *cpu;
104 /* Check valid parameter */
105 if (val > DEFAULT_PMQOS_TIMER) {
106 _I("The timer value cannot be higher than default time value(%dms)", DEFAULT_PMQOS_TIMER);
107 val = DEFAULT_PMQOS_TIMER;
110 /* Find previous request */
111 DD_LIST_FOREACH(pmqos_head, elem, cpu) {
112 if (!strcmp(cpu->name, name)) {
113 ecore_timer_reset(cpu->timer);
119 /* In case of first request */
122 timer = ecore_timer_add(val/1000.f, pmqos_cpu_timer, (void*)strdup(name));
126 cpu = malloc(sizeof(struct pmqos_cpu));
128 ecore_timer_del(timer);
131 snprintf(cpu->name, sizeof(cpu->name), "%s", name);
133 DD_LIST_APPEND(pmqos_head, cpu);
138 set_cpu_pmqos(cpu->name, true);
144 static int pmqos_powersaving(void *data)
146 return set_cpu_pmqos("PowerSaving", (int)data);
149 static int pmqos_lowbat(void *data)
151 return set_cpu_pmqos("LowBattery", (int)data);
154 static int pmqos_emergency(void *data)
156 return set_cpu_pmqos("Emergency", (int)data);
159 static int pmqos_poweroff(void *data)
161 return set_cpu_pmqos("PowerOff", (int)data);
164 static DBusMessage *dbus_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
166 DBusMessageIter iter;
171 if (!dbus_message_get_args(msg, NULL,
172 DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) {
173 _E("there is no message");
183 member = dbus_message_get_member(msg);
186 ret = pmqos_cpu_request(member, val);
188 ret = pmqos_cpu_cancel(member);
191 reply = dbus_message_new_method_return(msg);
192 dbus_message_iter_init_append(reply, &iter);
193 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
197 static DBusMessage *dbus_wifi_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg)
199 DBusMessageIter iter;
205 if (!dbus_message_get_args(msg, NULL,
206 DBUS_TYPE_INT32, &bps,
207 DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) {
208 _E("there is no message");
213 if (bps < 0 || val < 0) {
218 member = dbus_message_get_member(msg);
220 /* combine bps and member */
221 snprintf(name, sizeof(name), "%s%d", member, bps);
224 ret = pmqos_cpu_request(name, val);
226 ret = pmqos_cpu_cancel(name);
229 reply = dbus_message_new_method_return(msg);
230 dbus_message_iter_init_append(reply, &iter);
231 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
235 static DBusMessage *dbus_getdefaultlocktime(E_DBus_Object *obj, DBusMessage *msg)
237 DBusMessageIter iter;
241 ret = DEFAULT_PMQOS_TIMER;
243 reply = dbus_message_new_method_return(msg);
244 dbus_message_iter_init_append(reply, &iter);
245 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
249 static int get_methods_from_conf(const char *path, struct edbus_method **edbus_methods)
251 struct edbus_method *methods;
252 struct pmqos_scenario scenarios = {0,};
255 /* get pmqos table from conf */
256 ret = get_pmqos_table(path, &scenarios);
258 /* release scenarios memory */
259 release_pmqos_table(&scenarios);
263 /* if do not support scenario */
264 if (!scenarios.support)
267 /* if do not have scenarios */
268 if (scenarios.num <= 0)
271 /* allocate edbus methods structure */
272 methods = malloc(sizeof(struct edbus_method)*scenarios.num);
274 _E("failed to allocate methods memory : %s", strerror(errno));
275 /* release scenarios memory */
276 release_pmqos_table(&scenarios);
280 /* set edbus_methods structure */
281 for (i = 0; i < scenarios.num; ++i) {
283 /* if this scenario does not support */
284 if (!scenarios.list[i].support) {
285 _I("do not support [%s] scenario", scenarios.list[i].name);
289 methods[i].member = scenarios.list[i].name;
290 methods[i].signature = "i";
291 methods[i].reply_signature = "i";
292 methods[i].func = dbus_pmqos_handler;
293 _D("support [%s] scenario", scenarios.list[i].name);
296 *edbus_methods = methods;
297 return scenarios.num;
300 /* Add pmqos name as alphabetically */
301 static const struct edbus_method edbus_methods[] = {
302 { "AppLaunch", "i", "i", dbus_pmqos_handler },
303 { "BeautyShot", "i", "i", dbus_pmqos_handler },
304 { "Browser", "i", "i", dbus_pmqos_handler },
305 { "BrowserDash", "i", "i", dbus_pmqos_handler },
306 { "BrowserJavaScript", "i", "i", dbus_pmqos_handler },
307 { "BrowserLoading", "i", "i", dbus_pmqos_handler },
308 { "BrowserScroll", "i", "i", dbus_pmqos_handler },
309 { "CallSound", "i", "i", dbus_pmqos_handler },
310 { "CameraBurstShot", "i", "i", dbus_pmqos_handler },
311 { "CameraCaptureAtRec", "i", "i", dbus_pmqos_handler },
312 { "CameraPreview", "i", "i", dbus_pmqos_handler },
313 { "CameraSoundAndShot", "i", "i", dbus_pmqos_handler },
314 { "Emergency", "i", "i", dbus_pmqos_handler },
315 { "GalleryRotation", "i", "i", dbus_pmqos_handler },
316 { "GetDefaultLockTime", NULL, "i", dbus_getdefaultlocktime },
317 { "GpsSerialCno", "i", "i", dbus_pmqos_handler },
318 { "GpuBoost", "i", "i", dbus_pmqos_handler },
319 { "GpuWakeup", "i", "i", dbus_pmqos_handler },
320 { "ImageViewer", "i", "i", dbus_pmqos_handler },
321 { "IMEInput", "i", "i", dbus_pmqos_handler },
322 { "LockScreen", "i", "i", dbus_pmqos_handler },
323 { "LowBattery", "i", "i", dbus_pmqos_handler },
324 { "MtpSendFile", "i", "i", dbus_pmqos_handler },
325 { "PowerSaving", "i", "i", dbus_pmqos_handler },
326 { "ProcessCrashed", "i", "i", dbus_pmqos_handler },
327 { "ReservedMode", "i", "i", dbus_pmqos_handler },
328 { "ScreenMirroring", "i", "i", dbus_pmqos_handler },
329 { "SmemoZoom", "i", "i", dbus_pmqos_handler },
330 { "SVoice", "i", "i", dbus_pmqos_handler },
331 { "WebappLaunch", "i", "i", dbus_pmqos_handler },
332 { "WifiThroughput", "ii", "i", dbus_wifi_pmqos_handler },
333 { "PowerOff", "i", "i", dbus_pmqos_handler },
334 { "WebAppDrag", "i", "i", dbus_pmqos_handler },
335 { "WebAppFlick", "i", "i", dbus_pmqos_handler },
336 { "SensorWakeup", "i", "i", dbus_pmqos_handler },
339 static void pmqos_init(void *data)
341 struct edbus_method *methods = NULL;
344 /* register edbus methods */
345 ret = register_edbus_method(DEVICED_PATH_PMQOS, edbus_methods, ARRAY_SIZE(edbus_methods));
347 _E("fail to init edbus method(%d)", ret);
349 /* get methods from config file */
350 size = get_methods_from_conf(PMQOS_CONF_PATH, &methods);
352 _E("failed to load configuration file(%s)", PMQOS_CONF_PATH);
354 /* register edbus methods for pmqos */
356 ret = register_edbus_method(DEVICED_PATH_PMQOS, methods, size);
358 _E("fail to init edbus method from conf(%d)", ret);
362 /* register notifier for each event */
363 register_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving);
364 register_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat);
365 register_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency);
366 register_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff);
369 static void pmqos_exit(void *data)
371 /* unregister notifier for each event */
372 unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving);
373 unregister_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat);
374 unregister_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency);
375 unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff);
378 static const struct device_ops pmqos_device_ops = {
379 .priority = DEVICE_PRIORITY_NORMAL,
385 DEVICE_OPS_REGISTER(&pmqos_device_ops)