1 /*
2 * linux-5.4/drivers/media/platform/sunxi-vin/utility/cfg_op.c
3 *
4 * Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17 #ifdef CONFIG_SENSOR_LIST_MODULE
18
19 #include <linux/kernel.h>
20 #include <linux/fs.h>
21 #include <linux/string.h>
22 #include <linux/slab.h>
23 #include <asm/uaccess.h>
24
25 #include "cfg_op.h"
26
27 #define CFG_OK 0
28 #define CFG_ERR -10
29 #define CFG_ERR_OPEN -21
30 #define CFG_ERR_CREAT -22
31 #define CFG_ERR_RD -23
32 #define CFG_ERR_WR -24
33 #define CFG_NOT_FOUND -30
34 #define CFG_ERR_FMT -30
35 #define CFG_ERR_NOT_INIT -40
36
37 static char sct_pre = '[', sct_post = ']'; /* Section Symbol */
38 static char kv_iso = '='; /* isolator between key and value */
39 static char comment_pre = '#'; /* comment prefix */
40
41 /*
42 * name: strim_char
43 * func: trim a specific charator at front and end of a string
44 * input: char *s(string that should be trimed) char *c(specific charator)
45 * output:
46 * return: the string
47 */
strim_char(char * s,char c)48 static char *strim_char(char *s, char c)
49 {
50 int i, k, n;
51
52 n = strlen((char *)s);
53 if (n < 1)
54 return s;
55
56 for (i = 0; i < n; i++)
57 if (s[i] != c)
58 break;
59 if (i >= n)
60 return s;
61
62 k = i;
63 for (i++; i < n; i++)
64 if (s[i] == c)
65 break;
66 if (i <= n)
67 s[i] = '\0';
68
69 return s + k;
70 }
71
72 /*
73 * name: get_one_line
74 * func: get one line string from buffer to line_buf
75 * input: char *buffer, int maxlen,
76 * output: char *line_buf
77 * return: the actual length of buffer which has been read
78 */
get_one_line(char * buffer,char * line_buf,int maxlen)79 static int get_one_line(char *buffer, char *line_buf, int maxlen)
80 {
81 int i;
82 char buf;
83
84 for (i = 0; i < maxlen;) {
85 buf = *buffer;
86
87 if (buf == '\n' || buf == 0x00) /* new line */
88 break;
89 if (buf == '\f' || buf == 0x1A) { /* '\f':new page */
90 line_buf[i++] = buf;
91 break;
92 }
93 if (buf != '\r')
94 line_buf[i++] = buf; /* ignore enter */
95
96 buffer++;
97 }
98 line_buf[i++] = '\0';
99 return i;
100 }
101
102 /*
103 * name: split_key_value
104 * func: split key and value from buf
105 * input: char *buf
106 * output: char *key, char *val
107 * return: 1 --- ok
108 * 0 --- blank line
109 * -1 --- no key, "=value"
110 * -2 --- only key, no '='
111 */
split_key_value(char * buf,char * key,char * val)112 static int split_key_value(char *buf, char *key, char *val)
113 {
114 int i, k1, k2, n;
115
116 n = strlen((char *)buf);
117 if (n < 1)
118 return 0;
119
120 /* search for the first none space or tab value */
121 for (i = 0; i < n; i++)
122 if (buf[i] != ' ' && buf[i] != '\t')
123 break;
124 if (i >= n)
125 return 0;
126
127 /* return -1 when key is null */
128 if (buf[i] == kv_iso)
129 return -1;
130
131 /* search for key */
132 k1 = i;
133 for (i++; i < n; i++)
134 if (buf[i] == kv_iso)
135 break;
136
137 /* return -2 when only key(no isolator) */
138 if (i >= n)
139 return -2;
140
141 /* search for value */
142 k2 = i;
143 for (i++; i < n; i++)
144 if (buf[i] != ' ' && buf[i] != '\t')
145 break;
146
147 buf[k2] = '\0';
148
149 strcpy(key, buf + k1);
150 strcpy(val, buf + i);
151
152 return 1;
153 }
154
155 /*
156 * name: get_one_key_value
157 * func: get a key value in the specific section from buffer
158 * input: char *buffer, void *section,void *key
159 * output: void *value
160 * return: error number
161 */
get_one_key_value(char * buffer,void * section,void * key,void * value)162 static int get_one_key_value(char *buffer, void *section, void *key,
163 void *value)
164 {
165 char buf[LINE_MAX_CHAR_NUM + 1];
166 char key_ptr[MAX_NAME_LEN] = { 0 }, val_ptr[MAX_NAME_LEN] = {
167 0};
168 int n, ret;
169 unsigned int i, buf_len;
170
171 buf_len = strlen((char *)buffer);
172 if (buf_len < 1)
173 return CFG_ERR;
174 for (i = 0; i < buf_len;) { /* search for section */
175 ret = CFG_ERR_RD;
176 n = get_one_line(buffer, buf, LINE_MAX_CHAR_NUM);
177 buffer += n;
178 i += n;
179
180 ret = CFG_NOT_FOUND;
181 if (n < 0)
182 goto g_one_key_end; /* end of file */
183
184 n = strlen(strim(buf));
185 if (n == 0 || buf[0] == comment_pre)
186 continue; /* null line or comment line */
187 ret = CFG_ERR_FMT;
188 if (n > 2 && ((buf[0] == sct_pre && buf[n - 1] != sct_post)))
189 goto g_one_key_end;
190 if (buf[0] == sct_pre) {
191 buf[n - 1] = 0x00;
192 if (strcmp(buf + 1, section) == 0)
193 break; /* section found */
194 }
195 }
196
197 for (; i < buf_len;) { /* search for key */
198 ret = CFG_ERR_RD;
199 n = get_one_line(buffer, buf, LINE_MAX_CHAR_NUM);
200 buffer += n;
201 i += n;
202
203 ret = CFG_NOT_FOUND;
204 if (n < 0)
205 goto g_one_key_end; /* end of file */
206
207 n = strlen(strim(buf));
208 if (n == 0 || buf[0] == comment_pre)
209 continue; /* null line or comment line */
210 ret = CFG_NOT_FOUND;
211 if (buf[0] == sct_pre)
212 goto g_one_key_end;
213
214 ret = CFG_ERR_FMT;
215 if (split_key_value(buf, key_ptr, val_ptr) != 1)
216 goto g_one_key_end;
217 strim(key_ptr);
218 if (strcmp(key_ptr, key) != 0)
219 continue; /* not match */
220 strcpy(value, val_ptr);
221 break;
222 }
223 ret = CFG_OK;
224 g_one_key_end:
225 return ret;
226 }
227
228 /*
229 * name: get_all_keys_value
230 * func: get all key values in the specific section from buffer
231 * input: char *buffer, void *section
232 * output: char *keys[],void *value[]
233 * return: if correct, return keys number else return error number
234 */
get_all_keys_value(char * buffer,void * section,char * keys[],void * value[])235 static int get_all_keys_value(char *buffer, void *section, char *keys[],
236 void *value[])
237 {
238 char buf[LINE_MAX_CHAR_NUM + 1];
239 char key_ptr[MAX_NAME_LEN], val_ptr[MAX_VALUE_LEN];
240 int n, n_keys = 0, ret;
241 unsigned int i, buf_len;
242
243 buf_len = strlen((char *)buffer);
244 if (buf_len < 1)
245 return CFG_ERR;
246 for (i = 0; i < buf_len;) { /* search for section */
247 ret = CFG_ERR_RD;
248 n = get_one_line(buffer, buf, LINE_MAX_CHAR_NUM);
249 buffer += n;
250 i += n;
251
252 ret = CFG_NOT_FOUND;
253 if (n < 0)
254 goto g_all_keys_end; /* end of file */
255 n = strlen(strim(buf));
256 if (n == 0 || buf[0] == comment_pre)
257 continue; /* null line or comment line */
258 ret = CFG_ERR_FMT;
259 if (n > 2 && ((buf[0] == sct_pre && buf[n - 1] != sct_post)))
260 goto g_all_keys_end;
261 if (buf[0] == sct_pre) {
262 buf[n - 1] = 0x00;
263 if (strcmp(buf + 1, section) == 0)
264 break; /* section found */
265 }
266 }
267 for (; i < buf_len;) { /* search for keys */
268 ret = CFG_ERR_RD;
269 n = get_one_line(buffer, buf, LINE_MAX_CHAR_NUM);
270 buffer += n;
271 i += n;
272
273 if (n < 0)
274 break; /* end of file */
275 n = strlen(strim(buf));
276 if (n == 0 || buf[0] == comment_pre)
277 continue; /* null line or comment line */
278 ret = CFG_NOT_FOUND;
279 if (buf[0] == sct_pre)
280 break; /* another section */
281 ret = CFG_ERR_FMT;
282 if (split_key_value(buf, key_ptr, val_ptr) != 1)
283 goto g_all_keys_end;
284
285 strim(key_ptr);
286 strcpy(keys[n_keys], key_ptr);
287 strim(val_ptr);
288 strcpy(value[n_keys], val_ptr);
289
290 n_keys++;
291 }
292 ret = n_keys;
293 g_all_keys_end:
294 return ret;
295 }
296
297 /*
298 * name: get_sections
299 * func: API: get all mainkey from buffer to *sections[]
300 * input: struct file *buffer
301 * output: char *sections[]
302 * return: number of sections or error number (negative)
303 */
cfg_get_sections(char * buffer,char * sections[])304 int cfg_get_sections(char *buffer, char *sections[])
305 {
306 char buf[LINE_MAX_CHAR_NUM + 1];
307 int n, n_sections = 0, ret;
308 unsigned int i, buf_len;
309
310 buf_len = strlen((char *)buffer);
311 if (buf_len < 1)
312 return CFG_ERR;
313
314 for (i = 0; i < buf_len;) { /* search for section */
315 ret = CFG_ERR_RD;
316 n = get_one_line(buffer, buf, LINE_MAX_CHAR_NUM);
317 buffer += n;
318 i += n;
319
320 if (n < 0)
321 break; /* end of file */
322
323 n = strlen(strim(buf));
324 if (n == 0 || buf[0] == comment_pre)
325 continue; /* null line or comment line */
326 ret = CFG_ERR_FMT;
327 if (n > 2 && ((buf[0] == sct_pre && buf[n - 1] != sct_post)))
328 goto get_scts_end;
329 if (buf[0] == sct_pre) {
330 buf[n - 1] = 0x00;
331 strcpy(sections[n_sections], buf + 1);
332 n_sections++;
333 }
334 }
335 ret = n_sections;
336 get_scts_end:
337 return ret;
338 }
339
340 /*
341 * name: cfg_get_one_key_value
342 * func: API: get a key value in the specific section from buffer
343 * input: char *buffer, struct cfg_mainkey *scts
344 * output: struct cfg_subkey *subkey
345 * return: error number
346 */
cfg_get_one_key_value(char * buffer,struct cfg_mainkey * scts,struct cfg_subkey * subkey)347 int cfg_get_one_key_value(char *buffer, struct cfg_mainkey *scts,
348 struct cfg_subkey *subkey)
349 {
350 int ret, len;
351 char str_tmp[MAX_NAME_LEN];
352 char *endp;
353
354 if (scts == NULL || subkey == NULL)
355 return CFG_ERR_NOT_INIT;
356
357 if (scts->cfg_flag != CFG_KEY_INIT || subkey->cfg_flag != CFG_KEY_INIT)
358 return CFG_ERR_NOT_INIT;
359
360 ret =
361 get_one_key_value(buffer, scts->name, subkey->name,
362 (void *)subkey->value.str);
363 if (ret)
364 return ret;
365
366 len = strlen(subkey->value.str);
367 strcpy(str_tmp, subkey->value.str);
368
369 if (str_tmp[0] == '"' && str_tmp[len - 1] == '"') {
370 subkey->type = CFG_ITEM_VALUE_TYPE_STR;
371 strcpy(subkey->value.str, strim_char(subkey->value.str, '"'));
372 } else if ((str_tmp[0] >= 0x30 && str_tmp[0] <= 0x39)
373 || str_tmp[0] == '-') {
374 subkey->type = CFG_ITEM_VALUE_TYPE_INT;
375 endp = "\0";
376 subkey->value.val =
377 (int)simple_strtol(subkey->value.str, &endp, 0);
378 } else {
379 subkey->type = CFG_ITEM_VALUE_TYPE_INVALID;
380 }
381 return 0;
382 }
383
384 /*
385 * name: cfg_get_all_keys_value
386 * func: API: get all key values in the specific section from buffer
387 * input: char *buffer, struct cfg_mainkey *scts
388 * output: struct cfg_mainkey *scts
389 * return: error number
390 */
cfg_get_all_keys_value(char * buffer,struct cfg_mainkey * scts)391 int cfg_get_all_keys_value(char *buffer, struct cfg_mainkey *scts)
392 {
393 int i, len;
394 char str_tmp[MAX_NAME_LEN];
395 char *endp;
396
397 if (scts == NULL)
398 return CFG_ERR_NOT_INIT;
399
400 if (scts->cfg_flag != CFG_KEY_INIT)
401 return CFG_ERR_NOT_INIT;
402
403 scts->subkey_cnt =
404 get_all_keys_value(buffer, scts->name, scts->subkey_name,
405 (void *)scts->subkey_value);
406
407 if (scts->subkey_cnt <= 0)
408 return 0;
409
410 for (i = 0; i < scts->subkey_cnt; i++) {
411 len = strlen(scts->subkey[i].value.str);
412 strcpy(str_tmp, scts->subkey[i].value.str);
413
414 if (str_tmp[0] == '"' && str_tmp[len - 1] == '"') {
415 scts->subkey[i].type = CFG_ITEM_VALUE_TYPE_STR;
416 strcpy(scts->subkey[i].value.str,
417 strim_char(scts->subkey[i].value.str, '"'));
418 } else if ((str_tmp[0] >= 0x30 && str_tmp[0] <= 0x39)
419 || str_tmp[0] == '-') {
420 scts->subkey[i].type = CFG_ITEM_VALUE_TYPE_INT;
421 endp = "\0";
422 scts->subkey[i].value.val =
423 (int)simple_strtol(scts->subkey[i].value.str, &endp,
424 0);
425 } else {
426 scts->subkey[i].type = CFG_ITEM_VALUE_TYPE_INVALID;
427 }
428 }
429
430 return scts->subkey_cnt;
431 }
432
433 /*
434 * name: cfg_mainkey_init
435 * func: API: init resource before using mainkey
436 * input: struct cfg_mainkey **mainkey
437 * output:
438 * return: error number
439 */
cfg_mainkey_init(struct cfg_mainkey ** mainkey,char ** mainkey_name)440 void cfg_mainkey_init(struct cfg_mainkey **mainkey, char **mainkey_name)
441 {
442 int n;
443 *mainkey = (struct cfg_mainkey *)vmalloc(sizeof(struct cfg_mainkey));
444 memset(*mainkey, 0, sizeof(struct cfg_mainkey));
445 *mainkey_name = (*mainkey)->name;
446 for (n = 0; n < MAX_SUBKEY_NUM; n++) {
447 (*mainkey)->subkey_name[n] = (*mainkey)->subkey[n].name;
448 (*mainkey)->subkey_value[n] = (*mainkey)->subkey[n].value.str;
449 }
450 (*mainkey)->cfg_flag = CFG_KEY_INIT;
451 }
452
453 /*
454 * name: cfg_mainkey_release
455 * func: API: release resource after using mainkey
456 * input: struct cfg_mainkey **mainkey
457 * output:
458 * return: error number
459 */
cfg_mainkey_release(struct cfg_mainkey ** mainkey,char ** mainkey_name)460 void cfg_mainkey_release(struct cfg_mainkey **mainkey, char **mainkey_name)
461 {
462 (*mainkey)->cfg_flag = CFG_KEY_RELEASE;
463 if (*mainkey)
464 vfree(*mainkey);
465 }
466
467 /*
468 * name: cfg_section_init
469 * func: API: init resource before using cfg_section
470 * input: struct cfg_section **cfg_sct
471 * output:
472 * return: error number
473 */
cfg_section_init(struct cfg_section ** cfg_sct)474 void cfg_section_init(struct cfg_section **cfg_sct)
475 {
476 int i;
477
478 *cfg_sct =
479 (struct cfg_section *)kzalloc(sizeof(struct cfg_section),
480 GFP_KERNEL);
481 for (i = 0; i < MAX_MAINKEY_NUM; i++)
482 cfg_mainkey_init(&(*cfg_sct)->mainkey[i],
483 &(*cfg_sct)->mainkey_name[i]);
484 (*cfg_sct)->cfg_flag = CFG_KEY_INIT;
485 }
486
487 /*
488 * name: cfg_section_release
489 * func: API: release resource after using cfg_section
490 * input: struct cfg_section **cfg_sct
491 * output:
492 * return: error number
493 */
cfg_section_release(struct cfg_section ** cfg_sct)494 void cfg_section_release(struct cfg_section **cfg_sct)
495 {
496 int i;
497
498 (*cfg_sct)->cfg_flag = CFG_KEY_RELEASE;
499 for (i = 0; i < MAX_MAINKEY_NUM; i++)
500 cfg_mainkey_release(&(*cfg_sct)->mainkey[i],
501 &(*cfg_sct)->mainkey_name[i]);
502 if (*cfg_sct)
503 kfree(*cfg_sct);
504 }
505
cfg_open_file(char * file_path)506 struct file *cfg_open_file(char *file_path)
507 {
508 struct file *fp;
509
510 fp = filp_open(file_path, O_RDWR | O_APPEND | O_CREAT, 0644);
511 if (IS_ERR(fp)) {
512 pr_info("[vin_warn]open %s failed!, ERR NO is %ld.\n", file_path,
513 (long)fp);
514 }
515 return fp;
516 }
cfg_close_file(struct file * fp)517 int cfg_close_file(struct file *fp)
518 {
519 if (IS_ERR(fp)) {
520 pr_info("[vin_warn]colse file failed,fp is invaild!\n");
521 return -1;
522 } else {
523 filp_close(fp, NULL);
524 return 0;
525 }
526 }
527
528 /*
529 * name: cfg_read_file
530 * func: API: read from file to buf
531 * input: char *file_path,size_t len
532 * output: char *buf
533 * return: the actual length has been read
534 */
cfg_read_file(char * file_path,char * buf,size_t len)535 int cfg_read_file(char *file_path, char *buf, size_t len)
536 {
537 struct file *fp;
538 mm_segment_t old_fs;
539 loff_t pos = 0;
540 int buf_len;
541
542 fp = filp_open(file_path, O_RDONLY, 0);
543 if (IS_ERR(fp)) {
544 pr_info("[vin_warn]open file failed!\n");
545 return -EFAULT;
546 }
547
548 old_fs = get_fs();
549 set_fs(KERNEL_DS);
550 buf_len = vfs_read(fp, buf, len, &pos);
551 set_fs(old_fs);
552
553 if (fp)
554 filp_close(fp, NULL);
555
556 if (buf_len < 0)
557 return -1;
558
559 return buf_len;
560 }
561
cfg_write_file(struct file * fp,char * buf,size_t len)562 int cfg_write_file(struct file *fp, char *buf, size_t len)
563 {
564 mm_segment_t old_fs;
565 loff_t pos = 0;
566 int buf_len;
567
568 if (IS_ERR_OR_NULL(fp)) {
569 pr_info("cfg write file error, fp is null!");
570 return -1;
571 }
572 old_fs = get_fs();
573 set_fs(KERNEL_DS);
574 buf_len = vfs_write(fp, buf, len, &pos);
575 set_fs(old_fs);
576
577 if (buf_len < 0)
578 return -1;
579 if (buf_len != len)
580 pr_info("buf_len = %x, len = %pa\n", buf_len, &len);
581 return buf_len;
582 }
583
584 /*
585 * name: cfg_read_ini
586 * func: API: read from file, parse mainkey and sunkey value,save to cfg_setction
587 * input: char *file_path
588 * output: struct cfg_section **cfg_section
589 * return: error number
590 */
cfg_read_ini(char * file_path,struct cfg_section ** cfg_section)591 int cfg_read_ini(char *file_path, struct cfg_section **cfg_section)
592 {
593 unsigned int i;
594 struct cfg_section *cfg_sct = *(cfg_section);
595 char *buf;
596 int buf_len, ret = 0;
597
598 buf = (char *)vmalloc(INI_MAX_CHAR_NUM);
599 memset(buf, 0, INI_MAX_CHAR_NUM);
600
601 buf_len = cfg_read_file(file_path, buf, INI_MAX_CHAR_NUM);
602 if (buf_len < 0) {
603 ret = -1;
604 goto rd_ini_end;
605 }
606 buf[buf_len] = '\0';
607
608 /* parse file */
609 cfg_sct->mainkey_cnt = cfg_get_sections(buf, cfg_sct->mainkey_name);
610 for (i = 0; i < cfg_sct->mainkey_cnt; i++) {
611 cfg_sct->mainkey[i]->subkey_cnt =
612 cfg_get_all_keys_value(buf, cfg_sct->mainkey[i]);
613 }
614
615 rd_ini_end:
616 if (buf)
617 vfree(buf);
618
619 return ret;
620 }
621
622 /*
623 * name: cfg_get_ini_item
624 * func: API: read from cfg_setction, parse mainkey and sunkey value,save to cfg_setction
625 * input: struct cfg_section *cfg_section, char *main, char *sub
626 * output: struct cfg_subkey *subkey
627 * return: error number
628 */
cfg_get_one_subkey(struct cfg_section * cs,char * main,char * sub,struct cfg_subkey * subkey)629 int cfg_get_one_subkey(struct cfg_section *cs, char *main, char *sub,
630 struct cfg_subkey *subkey)
631 {
632 int i, j, ret;
633
634 for (i = 0; i < cs->mainkey_cnt; i++) {
635 if (strcmp(cs->mainkey_name[i], main) != 0)
636 continue;
637 for (j = 0; j < cs->mainkey[i]->subkey_cnt; j++) {
638 if (strcmp(cs->mainkey[i]->subkey_name[j], sub) == 0) {
639 ret = cs->mainkey[i]->subkey[j].type;
640 memcpy(subkey, &cs->mainkey[i]->subkey[j],
641 sizeof(struct cfg_subkey));
642 subkey = &cs->mainkey[i]->subkey[j];
643 return ret;
644 }
645 }
646 }
647 return -1;
648 }
649 #endif
650
651