input: add handling code to avoid memory leak issue
[platform/core/system/deviced.git] / src / input / input-parser.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 #include <stdio.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdbool.h>
24 #include <unistd.h>
25
26 #include <libsyscommon/ini-parser.h>
27 #include <libsyscommon/list.h>
28 #include <hal/device/hal-device-input.h>
29
30 #include "shared/log.h"
31 #include "input-parser.h"
32 #include "input-device-manager.h"
33
34 #define INPUT_CONF_PATH    "/hal/etc/deviced/input.conf"
35
36 struct input_device_info {
37         int input_device_type;
38         int input_device_id;
39         char *input_device_name;
40         int input_device_default;
41 };
42
43 static GHashTable *g_hash_table_to_check_default_duplicated;
44
45 static bool is_default_input_device_duplicated(int input_device_type)
46 {
47         gint *hash_key = g_new(gint, 1);
48         *hash_key = input_device_type;
49         if (g_hash_table_contains(g_hash_table_to_check_default_duplicated, hash_key)) {
50                 g_free(hash_key);
51                 return true;
52         } else {
53                 g_hash_table_insert(g_hash_table_to_check_default_duplicated, hash_key, NULL);
54         }
55         return false;
56 }
57
58 static int parse_input_device_property(gpointer data, gpointer user_data)
59 {
60         struct section_property *prop = (struct section_property *) data;
61         struct input_device_info *input_dev_info = *(struct input_device_info **)user_data;
62
63         if (!prop || !input_dev_info)
64                 return 0;
65
66         if (MATCH(prop->key, "InputDeviceType")) {
67                 if (MATCH(prop->value, "unknown"))
68                         input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_UNKNOWN;
69                 else if (MATCH(prop->value, "mouse"))
70                         input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_MOUSE;
71                 else if (MATCH(prop->value, "keyboard"))
72                         input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_KEYBOARD;
73                 else if (MATCH(prop->value, "custom_knob"))
74                         input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_CUSTOM_KNOB;
75                 else
76                         return -EPERM;
77         } else if (MATCH(prop->key, "InputDeviceId")) {
78                 sscanf(prop->value, "%d", (&input_dev_info->input_device_id));
79         } else if (MATCH(prop->key, "InputDeviceName")) {
80                 int str_len = sizeof(prop->value);
81                 input_dev_info->input_device_name = strndup(prop->value, str_len);
82         } else if (MATCH(prop->key, "InputDeviceDefault")) {
83                 if (MATCH(prop->value, "yes"))
84                         input_dev_info->input_device_default = 1;
85                 else if (MATCH(prop->value, "no"))
86                         input_dev_info->input_device_default = 0;
87                 else
88                         return -EPERM;
89         }
90         return 0;
91 }
92
93 static int parse_input_device_section(const struct parse_result *result, void *data)
94 {
95         struct input_device_info *input_dev_info;
96         struct section_property *temp_section_prop;
97         GList *temp_glist;
98         int ret;
99
100         if (!result || !result->props)
101                 return 0;
102
103         if (!MATCH(result->section, "InputDevice"))
104                 return 0;
105
106         input_dev_info = calloc(1, sizeof(struct input_device_info));
107         if (!input_dev_info)
108                 return -ENOMEM;
109
110         SYS_G_LIST_FOREACH(result->props, temp_glist, temp_section_prop) {
111                 if (parse_input_device_property(temp_section_prop, &input_dev_info) < 0)
112                         goto out_parsing_fail;
113         }
114
115         if (input_dev_info->input_device_default == 1) {
116                 if (is_default_input_device_duplicated(input_dev_info->input_device_type))
117                         goto out_parsing_fail;
118         }
119         ret = input_devman_add_device(input_dev_info->input_device_type,
120                 input_dev_info->input_device_id,
121                 input_dev_info->input_device_default,
122                 input_dev_info->input_device_name);
123         free(input_dev_info->input_device_name);
124         free(input_dev_info);
125
126         if (ret < 0)
127                 return ret;
128
129         return 0;
130
131 out_parsing_fail:
132         free(input_dev_info->input_device_name);
133         free(input_dev_info);
134         return -EPERM;
135 }
136
137 int input_parser_init(void)
138 {
139         int ret;
140
141         g_hash_table_to_check_default_duplicated = g_hash_table_new_full(g_int_hash, g_int_equal,
142                 g_free, g_free);
143
144         if (access(INPUT_CONF_PATH, F_OK) == -1)
145                 return 0;
146
147         ret = libsys_config_parse_by_section(INPUT_CONF_PATH, parse_input_device_section, NULL);
148
149         if (g_hash_table_to_check_default_duplicated) {
150                 g_hash_table_destroy(g_steal_pointer(&g_hash_table_to_check_default_duplicated));
151         }
152
153         if (ret < 0)
154                 return ret;
155
156         return 0;
157 }