blob: 79f4c41981eed21d95d60577c08b48da88d635b4 [file] [log] [blame]
you.chen99d26d12024-02-05 20:55:10 +08001//SPDX-License-Identifier: MediaTekProprietary
2/*
3 * Copyright (C) 2006 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "libuciwrapper"
19// #define LOG_NDEBUG 0
20
21#include <stdlib.h>
22#include <string.h>
23#include <ctype.h>
24#include <unistd.h>
25//#include <cutils/sockets.h>
26#include <errno.h>
27#include <assert.h>
28
29#include <cutils/properties.h>
30#include <stdbool.h>
31#include <inttypes.h>
32#include <log/log.h>
33
34int8_t property_get_bool(const char *key, int8_t default_value) {
35 if (!key) {
36 return default_value;
37 }
38
39 int8_t result = default_value;
40 char buf[PROPERTY_VALUE_MAX] = {'\0',};
41
42 int len = property_get(key, buf, "");
43 if (len == 1) {
44 char ch = buf[0];
45 if (ch == '0' || ch == 'n') {
46 result = false;
47 } else if (ch == '1' || ch == 'y') {
48 result = true;
49 }
50 } else if (len > 1) {
51 if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
52 result = false;
53 } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
54 result = true;
55 }
56 }
57
58 return result;
59}
60
61// Convert string property to int (default if fails); return default value if out of bounds
62static intmax_t property_get_imax(const char *key, intmax_t lower_bound, intmax_t upper_bound,
63 intmax_t default_value) {
64 if (!key) {
65 return default_value;
66 }
67
68 intmax_t result = default_value;
69 char buf[PROPERTY_VALUE_MAX] = {'\0',};
70 char *end = NULL;
71
72 int len = property_get(key, buf, "");
73 if (len > 0) {
74 int tmp = errno;
75 errno = 0;
76
77 // Infer base automatically
78 result = strtoimax(buf, &end, /*base*/0);
79 if ((result == INTMAX_MIN || result == INTMAX_MAX) && errno == ERANGE) {
80 // Over or underflow
81 result = default_value;
82 ALOGV("%s(%s,%" PRIdMAX ") - overflow", __FUNCTION__, key, default_value);
83 } else if (result < lower_bound || result > upper_bound) {
84 // Out of range of requested bounds
85 result = default_value;
86 ALOGV("%s(%s,%" PRIdMAX ") - out of range", __FUNCTION__, key, default_value);
87 } else if (end == buf) {
88 // Numeric conversion failed
89 result = default_value;
90 ALOGV("%s(%s,%" PRIdMAX ") - numeric conversion failed",
91 __FUNCTION__, key, default_value);
92 }
93
94 errno = tmp;
95 }
96
97 return result;
98}
99
100int64_t property_get_int64(const char *key, int64_t default_value) {
101 return (int64_t)property_get_imax(key, INT64_MIN, INT64_MAX, default_value);
102}
103
104int32_t property_get_int32(const char *key, int32_t default_value) {
105 return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value);
106}
107
108#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
109#include <sys/_system_properties.h>
110
111#include <uci.h>
112#define UCI_CONFIG_FILE "/etc/config/radio_property"
113
114static pthread_mutex_t property_mutex = PTHREAD_MUTEX_INITIALIZER;
115
116int property_set(const char *key, const char *new_value) {
117
118 if (NULL == key || NULL == new_value) {
119 return 0;
120 }
121
122 pthread_mutex_lock(&property_mutex);
123
124 int retValue = 0;
125 int value = 0;
126 struct uci_context *_ctx = uci_alloc_context();
127 struct uci_ptr ptr;
128 struct uci_package *pkg = NULL;
129 memset(&ptr, 0, sizeof(ptr));
130
131 // replace '.' with '_' to avoid uci r/w error
132 char tmp_string[PROPERTY_KEY_MAX];
133 int str_i = 0;
134 strncpy(tmp_string, key, PROPERTY_KEY_MAX - 1);
135 for (str_i = 0; str_i < PROPERTY_KEY_MAX; str_i++) {
136 if (tmp_string[str_i] == '.') {
137 tmp_string[str_i] = '_';
138 }
139 }
140
141 ptr.package = "radio_property";
142 ptr.section = "property";
143 ptr.option = tmp_string;
144 if (strlen(new_value) == 0) {
145 ptr.value = ":empty";
146 } else {
147 ptr.value = new_value;
148 }
149 value = uci_set(_ctx, &ptr);
150 if (value == 0) {
151 value = uci_commit(_ctx, &ptr.p, false);
152 if (value == 0) {
153 retValue = 1;
154 ALOGV("property_set ok. %s=%s return %d\n", key, new_value, value);
155 } else {
156 ALOGE("property_set uci_commit fail %s=%s return %d\n", key, new_value, value);
157 }
158 } else {
159 ALOGE("uci_set fail %s=%s return %d\n", key, new_value, value);
160 }
161 uci_unload(_ctx, ptr.p);
162 uci_free_context(_ctx);
163 _ctx = NULL;
164
165 pthread_mutex_unlock(&property_mutex);
166 return retValue;
167}
168
169
170int property_get(const char *key, char *value, const char *default_value) {
171 if (NULL == key || NULL == value) {
172 return 0;
173 }
174
175 pthread_mutex_lock(&property_mutex);
176
177 int retValue = 0;
178 struct uci_context *uciCtx = uci_alloc_context();
179 const char *pValueData = NULL;
180 struct uci_package *pkg = NULL;
181 struct uci_element *e;
182
183 // replace '.' with '_' to avoid uci r/w error
184 char tmp_string[PROPERTY_KEY_MAX];
185 int str_i = 0;
186 strncpy(tmp_string, key, PROPERTY_KEY_MAX - 1);
187 for (str_i = 0; str_i < PROPERTY_KEY_MAX; str_i++) {
188 if (tmp_string[str_i] == '.') {
189 tmp_string[str_i] = '_';
190 }
191 }
192
193
194 if (UCI_OK != uci_load(uciCtx, UCI_CONFIG_FILE, &pkg)) {
195 if (default_value) {
196 int len = strlen(default_value);
197 memcpy(value, default_value, len);
198 value[len] = '\0';
199 retValue = 1;
200 }
201 ALOGE("%s(), uci load fail, file: %s\n", __FUNCTION__, UCI_CONFIG_FILE);
202 goto cleanup;
203 }
204
205 uci_foreach_element(&pkg->sections, e) {
206 struct uci_section *s = uci_to_section(e);
207 if (NULL != (pValueData = uci_lookup_option_string(uciCtx, s, tmp_string))) {
208 if (!strncmp(pValueData, ":empty", strlen(":empty"))) {
209 value[0] = '\0';
210 } else {
211 strncpy(value, pValueData, strlen(pValueData));
212 }
213 retValue = 1;
214 ALOGV("property_get, %s: %s\n", key, value);
215 }
216 }
217 if (!retValue) {
218 if (default_value) {
219 int len = strlen(default_value);
220 memcpy(value, default_value, len);
221 value[len] = '\0';
222 retValue = 1;
223 ALOGV("property_get use default value, %s: %s\n", key, value);
224 }
225 }
226
227 uci_unload(uciCtx, pkg);
228
229cleanup:
230 uci_free_context(uciCtx);
231 uciCtx = NULL;
232
233 pthread_mutex_unlock(&property_mutex);
234 return retValue;
235}
236
237
238struct property_list_callback_data {
239 void (*propfn)(const char *key, const char *value, void *cookie);
240 void *cookie;
241};
242
243static void property_list_callback(const prop_info *pi, void *cookie) {
244 char name[PROP_NAME_MAX];
245 char value[PROP_VALUE_MAX];
246 struct property_list_callback_data *data = cookie;
247
248 //__system_property_read(pi, name, value);
249 data->propfn(name, value, data->cookie);
250}
251
252int property_list(
253 void (*propfn)(const char *key, const char *value, void *cookie),
254 void *cookie) {
255 struct property_list_callback_data data = { propfn, cookie };
256 return 0;
257}