power: add read wakeup source function
[platform/hal/backend/device-common.git] / src / power / power.c
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <glib.h>
20 #include <string.h>
21
22 #include "hal-backend-common.h"
23
24 #define WAKEUP_SOURCES_PATH     "/sys/kernel/debug/wakeup_sources"
25
26 #define MAX_NAME_LENGTH         50
27 #define MAX_NUM_WAKEUP_SOURCES  100
28 #define NUM_INFORMATION         10
29
30 struct wakeup_source {
31         char name[MAX_NAME_LENGTH + 1];
32         int active_count;
33         int event_count;
34         int wakeup_count;
35         int expire_count;
36         int active_since;
37         int total_time;
38         int max_time;
39         int last_change;
40         int prevent_suspend_time;
41 };
42
43 static struct wakeup_source source[MAX_NUM_WAKEUP_SOURCES];
44
45 static int read_wakeup_sources(char ***wakeup_source_name, int *wakeup_source_number)
46 {
47         char **new_wakeup_source_name;
48         char buf[MAX_NAME_LENGTH + 1] = {0, };
49         struct wakeup_source input = {0, };
50         int source_index = 0; /* for iteration of all wakeup sources */
51         int changed_source_number = 0; /* the number of wakeup sources that increase wakeup_count */
52         int ret;
53         FILE *fp;
54
55         if (!wakeup_source_name || !wakeup_source_number)
56                 return -EINVAL;
57
58         fp = fopen(WAKEUP_SOURCES_PATH, "r");
59         if (!fp) {
60                 _E("There is no node %s", WAKEUP_SOURCES_PATH);
61                 return -errno;
62         }
63
64         for (int i = 0; i < NUM_INFORMATION; ++i) {
65                 ret = fscanf(fp, "%50s", buf);
66                 if (ret < 1)
67                         goto parse_err;
68         }
69
70         new_wakeup_source_name = calloc(MAX_NUM_WAKEUP_SOURCES, sizeof(char*));
71         if (!new_wakeup_source_name) {
72                 _E("Failed to allocate memory");
73                 return -errno;
74         }
75
76         while (!feof(fp)) {
77                 if (source_index >= MAX_NUM_WAKEUP_SOURCES) {
78                         _E("Exceed max wakeup source number");
79                         for (int i = 0; i < changed_source_number; ++i)
80                                 free(new_wakeup_source_name[i]);
81                         free(new_wakeup_source_name);
82                         return -EPERM;
83                 }
84
85                 ret = fscanf(fp, "%50s %d %d %d %d %d %d %d %d %d\n", input.name,
86                         &input.active_count, &input.event_count,
87                         &input.wakeup_count, &input.expire_count,
88                         &input.active_since, &input.total_time,
89                         &input.max_time, &input.last_change,
90                         &input.prevent_suspend_time);
91
92                 if (ret < 10)
93                         goto parse_err;
94
95                 /* check whether the wakeup count increases */
96                 if (source[source_index].wakeup_count < input.wakeup_count) {
97                         new_wakeup_source_name[changed_source_number] =
98                                 calloc(MAX_NAME_LENGTH + 1, sizeof(char));
99                         strncpy(new_wakeup_source_name[changed_source_number++],
100                                 input.name, MAX_NAME_LENGTH + 1);
101                         _D("%s wakeup source detected", input.name);
102                 }
103
104                 source[source_index++] = input;
105         }
106
107         fclose(fp);
108         *wakeup_source_number = changed_source_number;
109         *wakeup_source_name = new_wakeup_source_name;
110         return 0;
111
112 parse_err:
113         _E("Failed to parse %s", WAKEUP_SOURCES_PATH);
114         for (int i = 0; i < changed_source_number; ++i)
115                 free(new_wakeup_source_name[i]);
116         free(new_wakeup_source_name);
117         fclose(fp);
118         return -EINVAL;
119 }
120
121 EXPORT int hal_backend_device_common_read_wakeup_sources(char ***wakeup_source_name, int *wakeup_source_number)
122 {
123         return read_wakeup_sources(wakeup_source_name, wakeup_source_number);
124 }