• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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