Selaa lähdekoodia

qcacmn: Add support for section parsing in ini

Add support for section parsing in ini, such that we could
read specific section of the file and update the ini values
instead of redundant values or updating the same in the
scripts based on the config

Change-Id: Ibdb08a04d709746c04c3e7c47ee3bb4a7ce85346
CRs-Fixed: 3107545
Surya Prakash Raajen 3 vuotta sitten
vanhempi
sitoutus
edf9fd0441
4 muutettua tiedostoa jossa 206 lisäystä ja 32 poistoa
  1. 14 0
      cfg/inc/cfg_ucfg_api.h
  2. 26 1
      cfg/src/cfg.c
  3. 29 0
      qdf/inc/qdf_parse.h
  4. 137 31
      qdf/src/qdf_parse.c

+ 14 - 0
cfg/inc/cfg_ucfg_api.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -165,6 +166,19 @@ QDF_STATUS cfg_psoc_parse(struct wlan_objmgr_psoc *psoc, const char *path);
 QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
 				   const char *path);
 
+/**
+ * cfg_section_parse_to_psoc_store() - Parse specific section from file @path
+ *                                     and update psoc ini store
+ * @psoc: The psoc whose config store should be updated
+ * @path: The full file path of the ini file to parse
+ * @section_name: Section name to be parsed
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cfg_section_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
+					   const char *path,
+					   const char *section_name);
+
 /**
  * cfg_parse_to_global_store() Parse file @path and update global ini store
  * @path: The full file path of the ini file to parse

+ 26 - 1
cfg/src/cfg.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -556,6 +557,21 @@ cfg_ini_parse_to_store(const char *path, struct cfg_value_store *store)
 	return status;
 }
 
+static QDF_STATUS
+cfg_ini_section_parse_to_store(const char *path, const char *section_name,
+			       struct cfg_value_store *store)
+{
+	QDF_STATUS status;
+
+	status = qdf_ini_section_parse(path, store, cfg_ini_item_handler,
+				       section_name);
+	if (QDF_IS_STATUS_ERROR(status))
+		cfg_err("Failed to parse *.ini file @ %s; status:%d",
+			path, status);
+
+	return status;
+}
+
 QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
 				   const char *path)
 {
@@ -564,6 +580,16 @@ QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
 
 qdf_export_symbol(cfg_parse_to_psoc_store);
 
+QDF_STATUS cfg_section_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
+					   const char *path,
+					   const char *section_name)
+{
+	return cfg_ini_section_parse_to_store(path, section_name,
+			cfg_psoc_get_ctx(psoc)->store);
+}
+
+qdf_export_symbol(cfg_section_parse_to_psoc_store);
+
 QDF_STATUS cfg_parse_to_global_store(const char *path)
 {
 	if (!__cfg_global_store) {
@@ -940,4 +966,3 @@ put_store:
 }
 
 qdf_export_symbol(cfg_psoc_parse);
-

+ 29 - 0
qdf/inc/qdf_parse.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -59,5 +60,33 @@ QDF_STATUS
 qdf_ini_parse(const char *ini_path, void *context,
 	      qdf_ini_item_cb item_cb, qdf_ini_section_cb section_cb);
 
+/**
+ * qdf_ini_section_parse() - parse a section from ini file
+ * @ini_path: The full file path of the ini file to parse
+ * @context: The caller supplied context to pass into callbacks
+ * @item_cb: Ini item (key/value pair) handler callback function
+ *	Return QDF_STATUS_SUCCESS to continue parsing, else to abort
+ * @section_name: Ini section name to be parsed from file
+ *	Return QDF_STATUS_SUCCESS to continue parsing, else to abort
+ *
+ * The *.ini file format is a simple format consisting of a list of key/value
+ * pairs (items), separated by an '=' character. Comments are initiated with
+ * a '#' character. Sections are also supported, using '[' and ']' around the
+ * section name. e.g.
+ *
+ *	# comments are started with a '#' character
+ *	# items are key/value string pairs, separated by the '=' character
+ *	someKey1=someValue1
+ *	someKey2=someValue2 # this is also a comment
+ *
+ *	# section headers are enclosed in square brackets
+ *	[some section header] # new section begins
+ *	someKey3=someValue3
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS qdf_ini_section_parse(const char *ini_path, void *context,
+				 qdf_ini_item_cb item_cb,
+				 const char *section_name);
 #endif /* __QDF_PARSE_H */
 

+ 137 - 31
qdf/src/qdf_parse.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -24,25 +25,19 @@
 #include "qdf_trace.h"
 #include "qdf_types.h"
 
-QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
-			 qdf_ini_item_cb item_cb, qdf_ini_section_cb section_cb)
-{
-	QDF_STATUS status;
-	char *fbuf;
-	char *cursor;
-	int ini_read_count = 0;
+#ifdef WLAN_USE_CONFIG_PARAMS
+#define QDF_SECTION_FOUND break
+#else
+#define QDF_SECTION_FOUND continue
+#endif
 
-	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
-		status = qdf_module_param_file_read(ini_path, &fbuf);
-	else
-		status = qdf_file_read(ini_path, &fbuf);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		qdf_err("Failed to read *.ini file @ %s", ini_path);
-		return status;
-	}
+static QDF_STATUS qdf_ini_read_values(char **main_cursor,
+				      char **read_key, char **read_value,
+				      bool *section_item)
+{
+	char *cursor = *main_cursor;
 
 	/* foreach line */
-	cursor = fbuf;
 	while (*cursor != '\0') {
 		char *key = cursor;
 		char *value = NULL;
@@ -78,7 +73,6 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 				break;
 
 			case '#':
-			case '[':
 				/*
 				 * We don't process comments, so we can null-
 				 * terminate unconditionally here (unlike '=').
@@ -93,7 +87,6 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 		}
 
 		key = qdf_str_trim(key);
-
 		/*
 		 * Ignoring comments, a valid ini line contains one of:
 		 *	1) some 'key=value' config item
@@ -101,28 +94,27 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 		 *	3) a line containing whitespace
 		 */
 		if (value) {
-			status = item_cb(context, key, value);
-			if (QDF_IS_STATUS_ERROR(status))
-				goto free_fbuf;
-			else
-				ini_read_count++;
+			*read_key = key;
+			*read_value = value;
+			*section_item = 0;
+			*main_cursor = cursor;
+			return QDF_STATUS_SUCCESS;
 		} else if (key[0] == '[') {
 			qdf_size_t len = qdf_str_len(key);
 
 			if (key[len - 1] != ']') {
 				qdf_err("Invalid *.ini syntax '%s'", key);
+				return QDF_STATUS_E_INVAL;
 			} else {
 				key[len - 1] = '\0';
-				if (section_cb)
-					status = section_cb(context, key + 1);
-				else
-					status = QDF_STATUS_E_NULL_VALUE;
-
-				if (QDF_IS_STATUS_ERROR(status))
-					goto free_fbuf;
+				*read_key = key + 1;
+				*section_item = 1;
+				*main_cursor = cursor;
+				return QDF_STATUS_SUCCESS;
 			}
 		} else if (key[0] != '\0') {
 			qdf_err("Invalid *.ini syntax '%s'", key);
+			return QDF_STATUS_E_INVAL;
 		}
 
 		/* skip remaining EoL characters */
@@ -130,6 +122,51 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 			cursor++;
 	}
 
+	return QDF_STATUS_E_INVAL;
+}
+
+QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
+			 qdf_ini_item_cb item_cb, qdf_ini_section_cb section_cb)
+{
+	QDF_STATUS status;
+	char *read_key;
+	char *read_value;
+	bool section_item;
+	int ini_read_count = 0;
+	char *fbuf;
+	char *cursor;
+
+	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
+		status = qdf_module_param_file_read(ini_path, &fbuf);
+	else
+		status = qdf_file_read(ini_path, &fbuf);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_err("Failed to read *.ini file @ %s", ini_path);
+		return status;
+	}
+
+	/* foreach line */
+	cursor = fbuf;
+
+	while (qdf_ini_read_values(&cursor, &read_key, &read_value,
+				   &section_item) == QDF_STATUS_SUCCESS) {
+		if (!section_item) {
+			status = item_cb(context, read_key, read_value);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+			else
+				ini_read_count++;
+		} else  {
+			qdf_debug("Section started in global file");
+		/* Currently AP Platforms supports and uses Sections,
+		 * hence break the loop, sections will be parsed separately,
+		 * in case of non AP platforms, sections are used as
+		 * logical separators hence continue reading the values.
+		 */
+			QDF_SECTION_FOUND;
+		}
+	}
+
 	qdf_info("INI values read: %d", ini_read_count);
 	if (ini_read_count != 0) {
 		qdf_info("INI file parse successful");
@@ -139,7 +176,6 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 		status = QDF_STATUS_E_INVAL;
 	}
 
-free_fbuf:
 	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
 		qdf_module_param_file_free(fbuf);
 	else
@@ -147,5 +183,75 @@ free_fbuf:
 
 	return status;
 }
+
 qdf_export_symbol(qdf_ini_parse);
 
+QDF_STATUS qdf_ini_section_parse(const char *ini_path, void *context,
+				 qdf_ini_item_cb item_cb,
+				 const char *section_name)
+{
+	QDF_STATUS status;
+	char *read_key;
+	char *read_value;
+	bool section_item;
+	bool section_found = 0;
+	bool section_complete = 0;
+	int ini_read_count = 0;
+	char *fbuf;
+	char *cursor;
+
+	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
+		status = qdf_module_param_file_read(ini_path, &fbuf);
+	else
+		status = qdf_file_read(ini_path, &fbuf);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_err("Failed to read *.ini file @ %s", ini_path);
+		return status;
+	}
+
+	/* foreach line */
+	cursor = fbuf;
+
+	while (qdf_ini_read_values(&cursor, &read_key, &read_value,
+				   &section_item) == QDF_STATUS_SUCCESS) {
+		if (section_item) {
+			if (qdf_str_cmp(read_key, section_name) == 0) {
+				section_found = 1;
+				section_complete = 0;
+			} else {
+				if (section_found == 1)
+					section_complete = 1;
+				section_found = 0;
+			}
+		} else if (section_found) {
+			status = item_cb(context, read_key, read_value);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+			else
+				ini_read_count++;
+		} else if (section_complete) {
+			break;
+		}
+	}
+
+	qdf_info("INI values parse successful read: %d from section %s",
+		 ini_read_count, section_name);
+
+	if (ini_read_count != 0) {
+		status = QDF_STATUS_SUCCESS;
+	} else {
+		qdf_debug("INI file parse fail: Section not found %s",
+			  section_name);
+		status = QDF_STATUS_SUCCESS;
+	}
+
+	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
+		qdf_module_param_file_free(fbuf);
+	else
+		qdf_file_buf_free(fbuf);
+
+	return status;
+}
+
+qdf_export_symbol(qdf_ini_section_parse);
+