power: Add setter for DEVICED_POWER_ATTR_INT_VITAL_MODE
[platform/core/system/deviced.git] / src / power / resource-power.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdio.h>
21 #include <stdint.h>
22
23 #include <libsyscommon/resource-manager.h>
24 #include <libsyscommon/resource-type.h>
25 #include <system/syscommon-plugin-deviced-power.h>
26 #include <system/syscommon-plugin-deviced-power-interface.h>
27 #include <system/syscommon-plugin-deviced-common-interface.h>
28
29 #include "power.h"
30 #include "power-suspend.h"
31
32 typedef union {
33         int32_t i32;
34         int64_t i64;
35         uint32_t u32;
36         uint64_t u64;
37         double d;
38         void* p;
39         bool b;
40 } resource_attr_data_t;
41
42 static int set_current_state(int resource_id, const struct syscommon_resman_resource_attribute *attr,
43         const void *data1, const void *data2, const void *data3, const void *data4,
44         int count1, int count2, int count3, int count4)
45 {
46         uint64_t curr;
47         uint64_t next;
48         int reason;
49         const void *user_data;
50
51         if (!data1 || !data2 || !data3 || !data4)
52                 return -EINVAL;
53
54         curr = *(uint64_t *) data1;
55         next = *(uint64_t *) data2;
56         reason = *(int *) data3;
57         user_data = *(const void **) data4;
58
59         power_request_change_state_strict(curr, next, reason, user_data);
60
61         return 0;
62 }
63
64 static int set_tuple2_power_attr_data(int resource_id,
65         const struct syscommon_resman_resource_attribute *attr,
66         const void *data1, const void *data2, int count1, int count2)
67 {
68         if (!data1 || !data2)
69                 return -EINVAL;
70
71         switch (attr->id) {
72         case DEVICED_POWER_ATTR_TUPLE2_HISTORY_LOG:
73                 {
74                         enum syscommon_deviced_power_log_type type = *(enum syscommon_deviced_power_log_type *) data1;
75                         int code = *(int *) data2;
76
77                         pm_history_save(type, code);
78
79                         return 0;
80                 }
81                 break;
82         default:
83                 return -EINVAL;
84         }
85
86         return 0;
87 }
88
89
90 static int get_power_attr_data(int resource_id,
91         const struct syscommon_resman_resource_attribute *attr, void *data)
92 {
93         int ret = 0;
94         resource_attr_data_t attr_data = { 0, };
95
96         if (!data)
97                 return -EINVAL;
98
99         switch (attr->id) {
100         case DEVICED_POWER_ATTR_UINT64_CURRENT_STATE:
101                 {
102                         attr_data.i32 = power_get_state();
103                 }
104                 break;
105         case DEVICED_POWER_ATTR_INT_WAKEUP_REASON:
106                 {
107                         attr_data.i32 = power_get_wakeup_reason();
108                 }
109                 break;
110         case DEVICED_POWER_ATTR_INT_VITAL_MODE:
111                 {
112                         attr_data.i32 = vital_mode();
113                 }
114                 break;
115         default:
116                 ret = -EINVAL;
117                 break;
118         }
119
120         if (ret < 0)
121                 return ret;
122
123         switch (attr->type) {
124         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
125                 *(int32_t *) data = attr_data.i32;
126                 break;
127         case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
128                 *(int64_t *) data = attr_data.i64;
129                 break;
130         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
131                 *(uint32_t *) data = attr_data.u32;
132                 break;
133         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
134                 *(uint64_t *) data = attr_data.u64;
135                 break;
136         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
137                 *(double *) data = attr_data.d;
138                 break;
139         case SYSCOMMON_RESMAN_DATA_TYPE_PTR:
140                 *(void **) data = attr_data.p;
141                 break;
142         case SYSCOMMON_RESMAN_DATA_TYPE_BOOLEAN:
143                 *(bool *) data = attr_data.b;
144                 break;
145         default:
146                 return -EINVAL;
147         }
148
149         return 0;
150 }
151
152 static int set_power_attr_data(int resource_id,
153         const struct syscommon_resman_resource_attribute *attr,
154         const void *data, int count)
155 {
156         if (!data)
157                 return -EINVAL;
158
159         switch (attr->id) {
160         case DEVICED_POWER_ATTR_INT_VITAL_MODE:
161                 {
162                         int mode = *(const int *) data;
163                         vital_state_changed(mode);
164                 }
165                 break;
166         default:
167                 return -EINVAL;
168         }
169
170         return 0;
171 }
172
173 /**
174  * FIXME: After developing the power abstraction layer, this attribute should
175  * be fixed. Because the suspend-to-ram supports both echo-mem and wakelock
176  * style without any different external interface.
177  */
178 static int g_wakelock_counter;
179 static gboolean event_release_wakelock(gpointer data)
180 {
181         if (g_wakelock_counter < 0)
182                 return G_SOURCE_REMOVE;
183
184         --g_wakelock_counter;
185
186         if (g_wakelock_counter == 0)
187                 syscommon_notifier_emit_notify(DEVICED_NOTIFIER_EVENT_RELEASE_WAKELOCK, NULL);
188
189         return G_SOURCE_REMOVE;
190 }
191
192 static int set_wakelock(int resource_id, const struct syscommon_resman_resource_attribute *attr,
193         const void *data1, const void *data2, int count1, int count2)
194 {
195         uint64_t event_id;
196         uint64_t timeout;
197
198         if (!data1 || !data2)
199                 return -EINVAL;
200
201         event_id = *(uint64_t *) data1;
202         timeout = *(uint64_t *) data2;
203
204         if (timeout <= 0)
205                 return -EINVAL;
206
207         ++g_wakelock_counter;
208
209         g_timeout_add_seconds(timeout, event_release_wakelock, (gpointer)(intptr_t) event_id);
210
211         if (g_wakelock_counter == 1)
212                 syscommon_notifier_emit_notify(DEVICED_NOTIFIER_EVENT_ACQUIRE_WAKELOCK, NULL);
213
214         return 0;
215 }
216
217 static const struct syscommon_resman_resource_attribute power_attrs[] = {
218         {
219                 .name = "DEVICED_POWER_ATTR_UINT64_4_CURRENT_STATE",
220                 .id = DEVICED_POWER_ATTR_UINT64_4_CURRENT_STATE,
221                 .type = SYSCOMMON_RESMAN_DATA_TYPE_4_UINT64,
222                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
223                 .ops = {
224                         .set_4_tuple = set_current_state,
225                         .is_supported = syscommon_resman_resource_attr_supported_always,
226                 },
227         }, {
228                 .name = "DEVICED_POWER_ATTR_UINT64_CURRENT_STATE",
229                 .id = DEVICED_POWER_ATTR_UINT64_CURRENT_STATE,
230                 .type = SYSCOMMON_RESMAN_DATA_TYPE_UINT64,
231                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
232                 .ops = {
233                         .get = get_power_attr_data,
234                         .is_supported = syscommon_resman_resource_attr_supported_always,
235                 },
236         }, {
237                 .name = "DEVICED_POWER_ATTR_INT_WAKEUP_REASON",
238                 .id = DEVICED_POWER_ATTR_INT_WAKEUP_REASON,
239                 .type = SYSCOMMON_RESMAN_DATA_TYPE_INT,
240                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
241                 .ops = {
242                         .get = get_power_attr_data,
243                         .is_supported = syscommon_resman_resource_attr_supported_always,
244                 },
245         }, {
246                 .name = "DEVICED_POWER_ATTR_TUPLE2_WAKELOCK",
247                 .id = DEVICED_POWER_ATTR_TUPLE2_WAKELOCK,
248                 .type = SYSCOMMON_RESMAN_DATA_TYPE_2_UINT64,
249                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
250                 .ops = {
251                         .set_2_tuple = set_wakelock,
252                         .is_supported = syscommon_resman_resource_attr_supported_always,
253                 },
254         }, {
255                 .name = "DEVICED_POWER_ATTR_INT_VITAL_MODE",
256                 .id = DEVICED_POWER_ATTR_INT_VITAL_MODE,
257                 .type = SYSCOMMON_RESMAN_DATA_TYPE_INT,
258                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
259                 .ops = {
260                         .get = get_power_attr_data,
261                         .set = set_power_attr_data,
262                         .is_supported = syscommon_resman_resource_attr_supported_always,
263                 },
264         }, {
265                 .name = "DEVICED_POWER_ATTR_TUPLE2_HISTORY_LOG",
266                 .id = DEVICED_POWER_ATTR_TUPLE2_HISTORY_LOG,
267                 .type = SYSCOMMON_RESMAN_DATA_TYPE_2_UINT64,
268                 .flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC,
269                 .ops = {
270                         .set_2_tuple = set_tuple2_power_attr_data,
271                         .is_supported = syscommon_resman_resource_attr_supported_always,
272                 },
273         }
274 };
275
276 static const struct syscommon_resman_resource_driver deviced_power_driver = {
277         .name           = "power",
278         .type           = DEVICED_RESOURCE_TYPE_POWER,
279         .flag           = SYSCOMMON_RESMAN_RESOURCE_DRIVER_FLAG_COUNT_ONLY_ONE,
280         .attrs          = power_attrs,
281         .num_attrs      = ARRAY_SIZE(power_attrs),
282 };
283 SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER(&deviced_power_driver);