瀏覽代碼

qcacld-3.0: Add support for action OUI extensions

Add support for action OUI extensions which can be used by station
to control mode of connection, connected AP's in-activity time and
Tx rate etc.,

Change-Id: Ie85e29c4b0ed7ac2815709d7a4e607c4ba46c6ca
CRs-Fixed: 2254502
Rajeev Kumar Sirasanagandla 7 年之前
父節點
當前提交
3d70d218cf

+ 79 - 0
action_oui/core/inc/wlan_action_oui_main.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare private API which shall be used internally only
+ * in action_oui component. This file shall include prototypes of
+ * various notification handlers and logging functions.
+ *
+ * Note: This API should be never accessed out of action_oui component.
+ */
+
+#ifndef _WLAN_ACTION_OUI_MAIN_H_
+#define _WLAN_ACTION_OUI_MAIN_H_
+
+#include <qdf_types.h>
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_priv.h"
+#include "wlan_action_oui_objmgr.h"
+
+#define action_oui_log(level, args...) \
+	QDF_TRACE(QDF_MODULE_ID_ACTION_OUI, level, ## args)
+
+#define action_oui_logfl(level, format, args...) \
+	action_oui_log(level, FL(format), ## args)
+
+#define action_oui_fatal(format, args...) \
+		action_oui_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
+#define action_oui_err(format, args...) \
+		action_oui_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args)
+#define action_oui_warn(format, args...) \
+		action_oui_logfl(QDF_TRACE_LEVEL_WARN, format, ## args)
+#define action_oui_info(format, args...) \
+		action_oui_logfl(QDF_TRACE_LEVEL_INFO, format, ## args)
+#define action_oui_debug(format, args...) \
+		action_oui_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
+
+#define ACTION_OUI_ENTER() action_oui_debug("enter")
+#define ACTION_OUI_EXIT() action_oui_debug("exit")
+
+/**
+ * action_oui_psoc_create_notification(): Handler for psoc create notify.
+ * @psoc: psoc which is going to be created by objmgr
+ * @arg: argument for notification handler.
+ *
+ * Allocate and attach psoc private object.
+ *
+ * Return: QDF_STATUS status in case of success else return error.
+ */
+QDF_STATUS
+action_oui_psoc_create_notification(struct wlan_objmgr_psoc *psoc, void *arg);
+
+/**
+ * action_oui_psoc_destroy_notification(): Handler for psoc destroy notify.
+ * @psoc: psoc which is going to be destroyed by objmgr
+ * @arg: argument for notification handler.
+ *
+ * Deallocate and detach psoc private object.
+ *
+ * Return QDF_STATUS status in case of success else return error
+ */
+QDF_STATUS
+action_oui_psoc_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg);
+
+#endif /* end  of _WLAN_ACTION_OUI_MAIN_H_ */

+ 79 - 0
action_oui/core/inc/wlan_action_oui_objmgr.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: This file contains various object manager related wrappers and helpers
+ */
+
+#ifndef _WLAN_ACTION_OUI_OBJMGR_H
+#define _WLAN_ACTION_OUI_OBJMGR_H
+
+#include "wlan_cmn.h"
+#include "wlan_objmgr_cmn.h"
+#include "wlan_objmgr_psoc_obj.h"
+
+/**
+ * action_oui_psoc_get_ref() - Wrapper to increment action_oui ref count
+ * @psoc: psoc object
+ *
+ * Wrapper for action_oui to increment ref count after checking valid
+ * object state.
+ *
+ * Return: SUCCESS/FAILURE
+ */
+static inline
+QDF_STATUS action_oui_psoc_get_ref(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_objmgr_psoc_try_get_ref(psoc, WLAN_ACTION_OUI_ID);
+}
+
+/**
+ * action_oui_psoc_put_ref() - Wrapper to decrement action_oui ref count
+ * @psoc: psoc object
+ *
+ * Wrapper for action_oui to decrement ref count of psoc.
+ *
+ * Return: SUCCESS/FAILURE
+ */
+static inline
+void action_oui_psoc_put_ref(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_objmgr_psoc_release_ref(psoc, WLAN_ACTION_OUI_ID);
+}
+
+/**
+ * action_oui_psoc_get_priv(): Wrapper to retrieve psoc priv obj
+ * @psoc: psoc pointer
+ *
+ * Wrapper for action_oui to get psoc private object pointer.
+ *
+ * Return: Private object of psoc
+ */
+static inline struct action_oui_psoc_priv *
+action_oui_psoc_get_priv(struct wlan_objmgr_psoc *psoc)
+{
+	struct action_oui_psoc_priv *psoc_priv;
+
+	psoc_priv = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+					WLAN_UMAC_COMP_ACTION_OUI);
+	QDF_BUG(psoc_priv);
+
+	return psoc_priv;
+}
+
+#endif /* _WLAN_ACTION_OUI_OBJMGR_H */

+ 147 - 0
action_oui/core/inc/wlan_action_oui_priv.h

@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare private API which shall be used internally only
+ * in action_oui component. This file shall include prototypes of
+ * action_oui parsing and send logic.
+ *
+ * Note: This API should be never accessed out of action_oui component.
+ */
+
+#ifndef _WLAN_ACTION_OUI_PRIV_STRUCT_H_
+#define _WLAN_ACTION_OUI_PRIV_STRUCT_H_
+
+#include <qdf_list.h>
+#include <qdf_types.h>
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_tgt_api.h"
+#include "wlan_action_oui_objmgr.h"
+
+/**
+ * enum action_oui_token_type - String token types expected.
+ * @ACTION_OUI_TOKEN: oui string
+ * @ACTION_OUI_DATA_LENGTH_TOKEN: data length string
+ * @ACTION_OUI_DATA_TOKEN: OUI data string
+ * @ACTION_OUI_DATA_MASK_TOKEN: data mask string
+ * @ACTION_OUI_INFO_MASK_TOKEN: info mask string
+ * @ACTION_OUI_MAC_ADDR_TOKEN: mac addr string
+ * @ACTION_OUI_MAC_MASK_TOKEN: mac mask string
+ * @ACTION_OUI_CAPABILITY_TOKEN: capability string
+ * @ACTION_OUI_END_TOKEN: end of one oui extension
+ */
+enum action_oui_token_type {
+	ACTION_OUI_TOKEN = 1 << 0,
+	ACTION_OUI_DATA_LENGTH_TOKEN = 1 << 1,
+	ACTION_OUI_DATA_TOKEN = 1 << 2,
+	ACTION_OUI_DATA_MASK_TOKEN = 1 << 3,
+	ACTION_OUI_INFO_MASK_TOKEN = 1 << 4,
+	ACTION_OUI_MAC_ADDR_TOKEN = 1 << 5,
+	ACTION_OUI_MAC_MASK_TOKEN = 1 << 6,
+	ACTION_OUI_CAPABILITY_TOKEN = 1 << 7,
+	ACTION_OUI_END_TOKEN = 1 << 8,
+};
+
+/**
+ * struct action_oui_extension_priv - Private contents of extension.
+ * @item: list element
+ * @extension: Extension contents
+ *
+ * This structure encapsulates action_oui_extension and list item.
+ */
+struct action_oui_extension_priv {
+	qdf_list_node_t item;
+	struct action_oui_extension extension;
+};
+
+/**
+ * struct action_oui_priv - Each action info.
+ * @id: type of action
+ * @extension_list: list of extensions
+ * @extension_lock: lock to control access to @extension_list
+ *
+ * All extensions of action specified by action_id are stored
+ * at @extension_list as linked list.
+ */
+struct action_oui_priv {
+	enum action_oui_id id;
+	qdf_list_t extension_list;
+	qdf_mutex_t extension_lock;
+};
+
+/**
+ * struct action_oui_psoc_priv - Private object to be stored in psoc
+ * @psoc: pointer to psoc object
+ * @total_extensions: total count of extensions from all actions
+ * @oui_priv: array of pointers used to refer each action info
+ * @tx_ops: call-back functions to send OUIs to firmware
+ */
+struct action_oui_psoc_priv {
+	struct wlan_objmgr_psoc *psoc;
+	uint32_t total_extensions;
+	struct action_oui_priv *oui_priv[ACTION_OUI_MAXIMUM_ID];
+	struct action_oui_tx_ops tx_ops;
+};
+
+/**
+ * action_oui_parse() - Parse action oui string
+ * @psoc_priv: pointer to action_oui psoc priv obj
+ * @oui_string: string to be parsed
+ * @ation_id: type of the action to be parsed
+ *
+ * This function parses the action oui string, extracts extensions and
+ * stores them @action_oui_priv using list data structure.
+ *
+ * Return: QDF_STATUS
+ *
+ */
+QDF_STATUS
+action_oui_parse(struct action_oui_psoc_priv *psoc_priv,
+		 uint8_t *oui_string, enum action_oui_id action_id);
+
+/**
+ * action_oui_send() - Send action oui extensions to target_if.
+ * @psoc_priv: pointer to action_oui psoc priv obj
+ * @ation_id: type of the action to be send
+ *
+ * This function sends action oui extensions to target_if.
+ *
+ * Return: QDF_STATUS
+ *
+ */
+QDF_STATUS
+action_oui_send(struct action_oui_psoc_priv *psoc_priv,
+		enum action_oui_id action_id);
+
+/**
+ * action_oui_search() - Check if Vendor OUIs are present in IE buffer
+ * @psoc_priv: pointer to action_oui psoc priv obj
+ * @attr: pointer to structure containing type of action, beacon IE data etc.,
+ * @action_id: type of action to be checked
+ *
+ * This function parses the IE buffer and finds if any of the vendor OUI
+ * and related attributes are present in it.
+ *
+ * Return: If vendor OUI is present return true else false
+ */
+bool
+action_oui_search(struct action_oui_psoc_priv *psoc_priv,
+		  struct action_oui_search_attr *attr,
+		  enum action_oui_id action_id);
+
+#endif /* End  of _WLAN_ACTION_OUI_PRIV_STRUCT_H_ */

+ 199 - 0
action_oui/core/src/wlan_action_oui_main.c

@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Implement various notification handlers which are accessed
+ * internally in action_oui component only.
+ */
+
+#include "wlan_action_oui_main.h"
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_tgt_api.h"
+#include "target_if_action_oui.h"
+
+/**
+ * action_oui_allocate() - Allocates memory for various actions.
+ * @psoc_priv: pointer to action_oui psoc priv obj
+ *
+ * This function allocates memory for all the action_oui types
+ * and initializes the respective lists to store extensions
+ * extracted from action_oui_extract().
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+action_oui_allocate(struct action_oui_psoc_priv *psoc_priv)
+{
+	struct action_oui_priv *oui_priv;
+	uint32_t i;
+	uint32_t j;
+
+	for (i = 0; i < ACTION_OUI_MAXIMUM_ID; i++) {
+		oui_priv = qdf_mem_malloc(sizeof(*oui_priv));
+		if (!oui_priv) {
+			action_oui_err("Mem alloc failed for oui_priv id: %u",
+					i);
+			goto free_mem;
+		}
+		oui_priv->id = i;
+		qdf_list_create(&oui_priv->extension_list,
+				ACTION_OUI_MAX_EXTENSIONS);
+		qdf_mutex_create(&oui_priv->extension_lock);
+		psoc_priv->oui_priv[i] = oui_priv;
+	}
+
+	return QDF_STATUS_SUCCESS;
+
+free_mem:
+	for (j = 0; j < i; j++) {
+		oui_priv = psoc_priv->oui_priv[j];
+		if (!oui_priv)
+			continue;
+
+		qdf_list_destroy(&oui_priv->extension_list);
+		qdf_mutex_destroy(&oui_priv->extension_lock);
+		psoc_priv->oui_priv[j] = NULL;
+	}
+
+	return QDF_STATUS_E_NOMEM;
+}
+
+/**
+ * action_oui_destroy() - Deallocates memory for various actions.
+ * @psoc_priv: pointer to action_oui psoc priv obj
+ *
+ * This function Deallocates memory for all the action_oui types.
+ * As a part of deallocate, all extensions are destroyed.
+ *
+ * Return: None
+ */
+static void
+action_oui_destroy(struct action_oui_psoc_priv *psoc_priv)
+{
+	struct action_oui_priv *oui_priv;
+	struct action_oui_extension_priv *ext_priv;
+	qdf_list_t *ext_list;
+	QDF_STATUS status;
+	qdf_list_node_t *node = NULL;
+	uint32_t i;
+
+	psoc_priv->total_extensions = 0;
+	for (i = 0; i < ACTION_OUI_MAXIMUM_ID; i++) {
+		oui_priv = psoc_priv->oui_priv[i];
+		psoc_priv->oui_priv[i] = NULL;
+		if (!oui_priv)
+			continue;
+
+		ext_list = &oui_priv->extension_list;
+		qdf_mutex_acquire(&oui_priv->extension_lock);
+		while (!qdf_list_empty(ext_list)) {
+			status = qdf_list_remove_front(ext_list, &node);
+			if (!QDF_IS_STATUS_SUCCESS(status)) {
+				action_oui_err("Invalid delete in action: %u",
+						oui_priv->id);
+				break;
+			}
+			ext_priv = qdf_container_of(node,
+					struct action_oui_extension_priv,
+					item);
+			qdf_mem_free(ext_priv);
+			ext_priv = NULL;
+		}
+
+		qdf_list_destroy(ext_list);
+		qdf_mutex_release(&oui_priv->extension_lock);
+		qdf_mutex_destroy(&oui_priv->extension_lock);
+		qdf_mem_free(oui_priv);
+		oui_priv = NULL;
+	}
+}
+
+QDF_STATUS
+action_oui_psoc_create_notification(struct wlan_objmgr_psoc *psoc, void *arg)
+{
+	struct action_oui_psoc_priv *psoc_priv;
+	QDF_STATUS status;
+
+	ACTION_OUI_ENTER();
+
+	psoc_priv = qdf_mem_malloc(sizeof(*psoc_priv));
+	if (!psoc_priv) {
+		action_oui_err("Failed to allocate psoc_priv");
+		status = QDF_STATUS_E_NOMEM;
+		goto exit;
+	}
+
+	status = wlan_objmgr_psoc_component_obj_attach(psoc,
+				WLAN_UMAC_COMP_ACTION_OUI,
+				(void *)psoc_priv, QDF_STATUS_SUCCESS);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		action_oui_err("Failed to attach priv with psoc");
+		goto free_psoc_priv;
+	}
+
+	target_if_action_oui_register_tx_ops(&psoc_priv->tx_ops);
+	psoc_priv->psoc = psoc;
+
+	status = action_oui_allocate(psoc_priv);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		action_oui_err("Failed to alloc action_oui");
+		goto detach_psoc_priv;
+	}
+
+	action_oui_debug("psoc priv attached");
+	goto exit;
+
+detach_psoc_priv:
+	wlan_objmgr_psoc_component_obj_detach(psoc,
+					      WLAN_UMAC_COMP_ACTION_OUI,
+					      (void *)psoc_priv);
+free_psoc_priv:
+	qdf_mem_free(psoc_priv);
+	status = QDF_STATUS_E_INVAL;
+exit:
+	ACTION_OUI_EXIT();
+	return status;
+}
+
+QDF_STATUS
+action_oui_psoc_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg)
+{
+	struct action_oui_psoc_priv *psoc_priv = NULL;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	ACTION_OUI_ENTER();
+
+	psoc_priv = action_oui_psoc_get_priv(psoc);
+	if (!psoc_priv) {
+		action_oui_err("psoc priv is NULL");
+		goto exit;
+	}
+
+	status = wlan_objmgr_psoc_component_obj_detach(psoc,
+					WLAN_UMAC_COMP_ACTION_OUI,
+					(void *)psoc_priv);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		action_oui_err("Failed to detach priv with psoc");
+
+	action_oui_destroy(psoc_priv);
+	qdf_mem_free(psoc_priv);
+
+exit:
+	ACTION_OUI_EXIT();
+	return status;
+}

+ 939 - 0
action_oui/core/src/wlan_action_oui_parse.c

@@ -0,0 +1,939 @@
+/*
+ * Copyright (c) 2012-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Implement parsing logic for action_oui strings, extract
+ * extensions and store them using linked list. Functions defined in
+ * this file can be accessed internally in action_oui component only.
+ */
+
+#include "wlan_action_oui_main.h"
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_tgt_api.h"
+#include "target_if_action_oui.h"
+#include <qdf_str.h>
+#include <wlan_utility.h>
+
+/**
+ * action_oui_string_to_hex() - convert string to uint8_t hex array
+ * @token - string to be converted
+ * @hex - output string to hold converted string
+ * @no_of_lengths - count of possible lengths for input string
+ * @possible_lengths - array holding possible lengths
+ *
+ * This function converts the continuous input string of even length and
+ * containing hexa decimal characters into hexa decimal array of uint8_t type.
+ * Input string needs to be NULL terminated and the length should match with
+ * one of entries in @possible_lengths
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool action_oui_string_to_hex(uint8_t *token, uint8_t *hex,
+			      uint32_t no_of_lengths,
+			      uint32_t *possible_lengths)
+{
+	uint32_t token_len = qdf_str_len(token);
+	uint32_t hex_str_len;
+	uint32_t i;
+	int ret;
+
+	if (!token_len || (token_len & 0x01)) {
+		action_oui_err("Token len is not multiple of 2");
+		return false;
+	}
+
+	for (i = 0; i < no_of_lengths; i++)
+		if (token_len == possible_lengths[i])
+			break;
+
+	if (i == no_of_lengths) {
+		action_oui_err("Token len doesn't match with expected len");
+		return false;
+	}
+
+	hex_str_len = token_len / 2;
+
+	ret = qdf_hex_str_to_binary(hex, token, hex_str_len);
+	if (ret) {
+		action_oui_err("Token doesn't contain hex digits");
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * action_oui_token_string() - converts enum value to string
+ * token_id: enum value to be converted to string
+ *
+ * This function converts the enum value of type action_oui_token_type
+ * to string
+ *
+ * Return: converted string
+ */
+static
+uint8_t *action_oui_token_string(enum action_oui_token_type token_id)
+{
+	switch (token_id) {
+		CASE_RETURN_STRING(ACTION_OUI_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_DATA_LENGTH_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_DATA_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_DATA_MASK_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_INFO_MASK_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_MAC_ADDR_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_MAC_MASK_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_CAPABILITY_TOKEN);
+		CASE_RETURN_STRING(ACTION_OUI_END_TOKEN);
+	}
+
+	return (uint8_t *) "UNKNOWN";
+}
+
+/**
+ * validate_and_convert_oui() - validate and convert OUI str to hex array
+ * @token: OUI string
+ * @ext: pointer to container which holds converted hex array
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the OUI string for action OUI inis, convert them to hex array and store it
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static
+bool validate_and_convert_oui(uint8_t *token,
+			struct action_oui_extension *ext,
+			enum action_oui_token_type *action_token)
+{
+	bool valid;
+	uint32_t expected_token_len[2] = {6, 10};
+
+	valid = action_oui_string_to_hex(token, ext->oui, 2,
+					 expected_token_len);
+	if (!valid)
+		return false;
+
+	ext->oui_length = qdf_str_len(token) / 2;
+
+	*action_token = ACTION_OUI_DATA_LENGTH_TOKEN;
+
+	return valid;
+}
+
+/**
+ * validate_and_convert_data_length() - validate data len str
+ * @token: data length string
+ * @ext: pointer to container which holds hex value formed from input str
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the data length string for action OUI inis, convert it to hex value and
+ * store it in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_data_length(uint8_t *token,
+				struct action_oui_extension *ext,
+				enum action_oui_token_type *action_token)
+{
+	uint32_t token_len = qdf_str_len(token);
+	int ret;
+	uint8_t len = 0;
+
+	if (token_len != 1 && token_len != 2) {
+		action_oui_err("Invalid str token len for action OUI data len");
+		return false;
+	}
+
+	ret = kstrtou8(token, 16, &len);
+	if (ret) {
+		action_oui_err("Invalid char in action OUI data len str token");
+		return false;
+	}
+
+	if ((uint32_t)len > ACTION_OUI_MAX_DATA_LENGTH) {
+		action_oui_err("action OUI data len is more than %u",
+			ACTION_OUI_MAX_DATA_LENGTH);
+		return false;
+	}
+
+	ext->data_length = len;
+
+	if (!ext->data_length)
+		*action_token = ACTION_OUI_INFO_MASK_TOKEN;
+	else
+		*action_token = ACTION_OUI_DATA_TOKEN;
+
+	return true;
+}
+
+/**
+ * validate_and_convert_data() - validate and convert data str to hex array
+ * @token: data string
+ * @ext: pointer to container which holds converted hex array
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the data string for action OUI inis, convert it to hex array and store in
+ * action_oui extension. After successful parsing update the @action_token
+ * to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_data(uint8_t *token,
+			      struct action_oui_extension *ext,
+			      enum action_oui_token_type *action_token)
+{
+	bool valid;
+	uint32_t expected_token_len[1] = {2 * ext->data_length};
+
+	valid = action_oui_string_to_hex(token, ext->data, 1,
+					 expected_token_len);
+	if (!valid)
+		return false;
+
+	*action_token = ACTION_OUI_DATA_MASK_TOKEN;
+
+	return true;
+}
+
+/**
+ * validate_and_convert_data_mask() - validate and convert data mask str
+ * @token: data mask string
+ * @ext: pointer to container which holds converted hex array
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the data mask string for action OUI inis, convert it to hex array and store
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_data_mask(uint8_t *token,
+				   struct action_oui_extension *ext,
+				   enum action_oui_token_type *action_token)
+{
+	bool valid;
+	uint32_t expected_token_len[1];
+	uint32_t data_mask_length;
+	uint32_t data_length = ext->data_length;
+
+	if (data_length % 8 == 0)
+		data_mask_length = data_length / 8;
+	else
+		data_mask_length = ((data_length / 8) + 1);
+
+	if (data_mask_length > ACTION_OUI_MAX_DATA_MASK_LENGTH)
+		return false;
+
+	expected_token_len[0] = 2 * data_mask_length;
+
+	valid = action_oui_string_to_hex(token, ext->data_mask, 1,
+				  expected_token_len);
+	if (!valid)
+		return false;
+
+	ext->data_mask_length = data_mask_length;
+
+	*action_token = ACTION_OUI_INFO_MASK_TOKEN;
+
+	return valid;
+}
+
+/**
+ * validate_and_convert_info_mask() - validate and convert info mask str
+ * @token: info mask string
+ * @ext: pointer to container which holds converted hex array
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the info mask string for action OUI inis, convert it to hex array and store
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_info_mask(uint8_t *token,
+				   struct action_oui_extension *ext,
+				   enum action_oui_token_type *action_token)
+{
+	uint32_t token_len = qdf_str_len(token);
+	uint8_t hex_value = 0;
+	uint32_t info_mask;
+	int ret;
+
+	if (token_len != 2) {
+		action_oui_err("action OUI info mask str token len is not of 2 chars");
+		return false;
+	}
+
+	ret = kstrtou8(token, 16, &hex_value);
+	if (ret) {
+		action_oui_err("Invalid char in action OUI info mask str token");
+		return false;
+	}
+
+	info_mask = hex_value;
+
+	info_mask |= ACTION_OUI_INFO_OUI;
+	ext->info_mask = info_mask;
+
+	if (!info_mask || !(info_mask & ~ACTION_OUI_INFO_OUI)) {
+		*action_token = ACTION_OUI_END_TOKEN;
+		return true;
+	}
+
+	if (info_mask & ~ACTION_OUI_INFO_MASK) {
+		action_oui_err("Invalid bits are set in action OUI info mask");
+		return false;
+	}
+
+	if (info_mask & ACTION_OUI_INFO_MAC_ADDRESS) {
+		*action_token = ACTION_OUI_MAC_ADDR_TOKEN;
+		return true;
+	}
+
+	*action_token = ACTION_OUI_CAPABILITY_TOKEN;
+	return true;
+}
+
+/**
+ * validate_and_convert_mac_addr() - validate and convert mac addr str
+ * @token: mac address string
+ * @ext: pointer to container which holds converted hex array
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the mac address string for action OUI inis, convert it to hex array and store
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_mac_addr(uint8_t *token,
+				  struct action_oui_extension *ext,
+				  enum action_oui_token_type *action_token)
+{
+	uint32_t expected_token_len[1] = {2 * QDF_MAC_ADDR_SIZE};
+	bool valid;
+
+	valid = action_oui_string_to_hex(token, ext->mac_addr, 1,
+				  expected_token_len);
+	if (!valid)
+		return false;
+
+	ext->mac_addr_length = QDF_MAC_ADDR_SIZE;
+
+	*action_token = ACTION_OUI_MAC_MASK_TOKEN;
+
+	return true;
+}
+
+/**
+ * validate_and_convert_mac_mask() - validate and convert mac mask
+ * @token: mac mask string
+ * @ext: pointer to container which holds converted hex value
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the mac mask string for action OUI inis, convert it to hex value and store
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_mac_mask(uint8_t *token,
+				  struct action_oui_extension *ext,
+				  enum action_oui_token_type *action_token)
+{
+	uint32_t expected_token_len[1] = {2};
+	uint32_t info_mask = ext->info_mask;
+	bool valid;
+	uint32_t mac_mask_length;
+
+	valid = action_oui_string_to_hex(token, ext->mac_mask, 1,
+				  expected_token_len);
+	if (!valid)
+		return false;
+
+	mac_mask_length = qdf_str_len(token) / 2;
+	if (mac_mask_length > ACTION_OUI_MAC_MASK_LENGTH) {
+		action_oui_err("action OUI mac mask str token len is more than %u chars",
+			expected_token_len[0]);
+		return false;
+	}
+
+	ext->mac_mask_length = mac_mask_length;
+
+	if ((info_mask & ACTION_OUI_INFO_AP_CAPABILITY_NSS) ||
+	    (info_mask & ACTION_OUI_INFO_AP_CAPABILITY_HT) ||
+	    (info_mask & ACTION_OUI_INFO_AP_CAPABILITY_VHT) ||
+	    (info_mask & ACTION_OUI_INFO_AP_CAPABILITY_BAND)) {
+		*action_token = ACTION_OUI_CAPABILITY_TOKEN;
+		return true;
+	}
+
+	*action_token = ACTION_OUI_END_TOKEN;
+	return true;
+}
+
+/**
+ * validate_and_convert_capability() - validate and convert capability str
+ * @token: capability string
+ * @ext: pointer to container which holds converted hex value
+ * @action_token: next action to be parsed
+ *
+ * This is an internal function invoked from action_oui_parse to validate
+ * the capability string for action OUI inis, convert it to hex value and store
+ * in action_oui extension. After successful parsing update the
+ * @action_token to hold the next expected string.
+ *
+ * Return: If conversion is successful return true else false
+ */
+static bool
+validate_and_convert_capability(uint8_t *token,
+				struct action_oui_extension *ext,
+				enum action_oui_token_type *action_token)
+{
+	uint32_t expected_token_len[1] = {2};
+	uint32_t info_mask = ext->info_mask;
+	uint32_t capability_length;
+	uint8_t caps_0;
+	bool valid;
+
+	valid = action_oui_string_to_hex(token, ext->capability, 1,
+				  expected_token_len);
+	if (!valid)
+		return false;
+
+	capability_length = qdf_str_len(token) / 2;
+	if (capability_length > ACTION_OUI_MAX_CAPABILITY_LENGTH) {
+		action_oui_err("action OUI capability str token len is more than %u chars",
+			expected_token_len[0]);
+		return false;
+	}
+
+	caps_0 = ext->capability[0];
+
+	if ((info_mask & ACTION_OUI_INFO_AP_CAPABILITY_NSS) &&
+	    (!(caps_0 & ACTION_OUI_CAPABILITY_NSS_MASK))) {
+		action_oui_err("Info presence for NSS is set but respective bits in capability are not set");
+		return false;
+	}
+
+	if ((info_mask & ACTION_OUI_INFO_AP_CAPABILITY_BAND) &&
+	    (!(caps_0 & ACTION_OUI_CAPABILITY_BAND_MASK))) {
+		action_oui_err("Info presence for BAND is set but respective bits in capability are not set");
+		return false;
+	}
+
+	ext->capability_length = capability_length;
+
+	*action_token = ACTION_OUI_END_TOKEN;
+
+	return true;
+}
+
+/**
+ * action_oui_extension_store() - store action oui extension
+ * @priv_obj: pointer to action_oui priv obj
+ * @oui_priv: type of the action
+ * @ext: oui extension to store in sme
+ *
+ * This function stores the parsed oui extension
+ *
+ * Return: QDF_STATUS
+ *
+ */
+static QDF_STATUS
+action_oui_extension_store(struct action_oui_psoc_priv *psoc_priv,
+			   struct action_oui_priv *oui_priv,
+			   struct action_oui_extension ext)
+{
+	struct action_oui_extension_priv *ext_priv;
+
+	qdf_mutex_acquire(&oui_priv->extension_lock);
+	if (qdf_list_size(&oui_priv->extension_list) ==
+			  ACTION_OUI_MAX_EXTENSIONS) {
+		qdf_mutex_release(&oui_priv->extension_lock);
+		action_oui_err("Reached maximum OUI extensions");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	ext_priv = qdf_mem_malloc(sizeof(*ext_priv));
+	if (!ext_priv) {
+		qdf_mutex_release(&oui_priv->extension_lock);
+		action_oui_err("Failed to allocate memory for action oui extension priv");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	ext_priv->extension = ext;
+	qdf_list_insert_back(&oui_priv->extension_list, &ext_priv->item);
+	psoc_priv->total_extensions++;
+	qdf_mutex_release(&oui_priv->extension_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+action_oui_parse(struct action_oui_psoc_priv *psoc_priv,
+		 uint8_t *oui_string, enum action_oui_id action_id)
+{
+	struct action_oui_extension ext = {0};
+	enum action_oui_token_type action_token = ACTION_OUI_TOKEN;
+	char *str1;
+	char *str2;
+	char *token;
+	bool valid = true;
+	bool oui_count_exceed = false;
+	uint32_t oui_index = 0;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct action_oui_priv *oui_priv;
+
+	if (!oui_string) {
+		action_oui_err("Invalid string for action oui: %u", action_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	oui_priv = psoc_priv->oui_priv[action_id];
+	if (!oui_priv) {
+		action_oui_err("action oui priv not allocated");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	str1 = qdf_str_trim((char *)oui_string);
+
+	while (str1) {
+		str2 = skip_spaces(str1);
+		if (str2[0] == '\0') {
+			action_oui_err("Invalid spaces in action oui: %u at extension: %u for token: %s",
+				action_id,
+				oui_index + 1,
+				action_oui_token_string(action_token));
+			valid = false;
+			break;
+		}
+
+		token = strsep(&str2, " ");
+		if (!token) {
+			action_oui_err("Invalid string for token: %s at extension: %u in action oui: %u",
+				action_oui_token_string(action_token),
+				oui_index + 1, action_id);
+			valid = false;
+			break;
+		}
+
+		str1 = str2;
+
+		switch (action_token) {
+
+		case ACTION_OUI_TOKEN:
+			valid = validate_and_convert_oui(token, &ext,
+							 &action_token);
+			break;
+
+		case ACTION_OUI_DATA_LENGTH_TOKEN:
+			valid = validate_and_convert_data_length(token, &ext,
+								&action_token);
+			break;
+
+		case ACTION_OUI_DATA_TOKEN:
+			valid = validate_and_convert_data(token, &ext,
+							&action_token);
+			break;
+
+		case ACTION_OUI_DATA_MASK_TOKEN:
+			valid = validate_and_convert_data_mask(token, &ext,
+							&action_token);
+			break;
+
+		case ACTION_OUI_INFO_MASK_TOKEN:
+			valid = validate_and_convert_info_mask(token, &ext,
+							&action_token);
+			break;
+
+		case ACTION_OUI_MAC_ADDR_TOKEN:
+			valid = validate_and_convert_mac_addr(token, &ext,
+							&action_token);
+			break;
+
+		case ACTION_OUI_MAC_MASK_TOKEN:
+			valid = validate_and_convert_mac_mask(token, &ext,
+							&action_token);
+			break;
+
+		case ACTION_OUI_CAPABILITY_TOKEN:
+			valid = validate_and_convert_capability(token, &ext,
+							&action_token);
+			break;
+
+		default:
+			valid = false;
+			break;
+		}
+
+		if (!valid) {
+			action_oui_err("Invalid string for token: %s at extension: %u in action oui: %u",
+				action_oui_token_string(action_token),
+				oui_index + 1,
+				action_id);
+			break;
+		}
+
+		if (action_token != ACTION_OUI_END_TOKEN)
+			continue;
+
+		status = action_oui_extension_store(psoc_priv, oui_priv, ext);
+		if (!QDF_IS_STATUS_SUCCESS(status)) {
+			valid = false;
+			action_oui_err("sme set of extension: %u for action oui: %u failed",
+				oui_index + 1, action_id);
+			break;
+		}
+
+		oui_index++;
+		if (oui_index == ACTION_OUI_MAX_EXTENSIONS) {
+			if (str1)
+				oui_count_exceed = true;
+			break;
+		}
+
+		/* reset the params for next action OUI parse */
+		action_token = ACTION_OUI_TOKEN;
+		qdf_mem_zero(&ext, sizeof(ext));
+	}
+
+	if (oui_count_exceed) {
+		action_oui_err("Reached Maximum extensions: %u in action_oui: %u, ignoring the rest",
+			ACTION_OUI_MAX_EXTENSIONS, action_id);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	if (action_token != ACTION_OUI_TOKEN &&
+	    action_token != ACTION_OUI_END_TOKEN &&
+	    valid && !str1) {
+		action_oui_err("No string for token: %s at extension: %u in action oui: %u",
+			action_oui_token_string(action_token),
+			oui_index + 1,
+			action_id);
+		valid = false;
+	}
+
+	if (!oui_index) {
+		action_oui_err("Not able to parse any extension in action oui: %u",
+			action_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (valid)
+		action_oui_debug("All extensions: %u parsed successfully in action oui: %u",
+			  oui_index, action_id);
+	else
+		action_oui_err("First %u extensions parsed successfully in action oui: %u",
+			oui_index, action_id);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS action_oui_send(struct action_oui_psoc_priv *psoc_priv,
+			enum action_oui_id action_id)
+{
+	QDF_STATUS status;
+	struct action_oui_request *req;
+	struct action_oui_priv *oui_priv;
+	struct action_oui_extension *extension;
+	struct action_oui_extension_priv *ext_priv;
+	qdf_list_node_t *node = NULL;
+	qdf_list_node_t *next_node = NULL;
+	qdf_list_t *extension_list;
+	uint32_t len;
+	uint32_t no_oui_extensions;
+
+	oui_priv = psoc_priv->oui_priv[action_id];
+	if (!oui_priv)
+		return QDF_STATUS_SUCCESS;
+
+	extension_list = &oui_priv->extension_list;
+	qdf_mutex_acquire(&oui_priv->extension_lock);
+	if (qdf_list_empty(extension_list)) {
+		qdf_mutex_release(&oui_priv->extension_lock);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	no_oui_extensions = qdf_list_size(extension_list);
+	len = sizeof(*req) + no_oui_extensions * sizeof(*extension);
+	req = qdf_mem_malloc(len);
+	if (!req) {
+		action_oui_err("Failed to allocate memory for action_oui");
+		qdf_mutex_release(&oui_priv->extension_lock);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	req->action_id = oui_priv->id;
+	req->no_oui_extensions = no_oui_extensions;
+	req->total_no_oui_extensions = psoc_priv->total_extensions;
+
+	extension = req->extension;
+	qdf_list_peek_front(extension_list, &node);
+	while (node) {
+		ext_priv = qdf_container_of(node,
+					   struct action_oui_extension_priv,
+					   item);
+		*extension = ext_priv->extension;
+		status = qdf_list_peek_next(extension_list, node,
+						&next_node);
+		if (!QDF_IS_STATUS_SUCCESS(status))
+			break;
+		node = next_node;
+		next_node = NULL;
+		extension++;
+	}
+
+	qdf_mutex_release(&oui_priv->extension_lock);
+
+	status = tgt_action_oui_send(psoc_priv->psoc, req);
+	qdf_mem_free(req);
+
+	return status;
+}
+
+/**
+ * check_for_vendor_oui_data() - compares for vendor OUI data from IE
+ * and returns true if OUI data matches with the ini
+ * @extension: pointer to action oui extension data
+ * @oui_ptr: pointer to Vendor IE in the beacon
+ *
+ * Return: true or false
+ */
+static bool
+check_for_vendor_oui_data(struct action_oui_extension *extension,
+			  const uint8_t *oui_ptr)
+{
+	const uint8_t *data;
+	uint8_t i, j, elem_len, data_len;
+	uint8_t data_mask = 0x80;
+
+	elem_len = oui_ptr[1];
+	if (elem_len < extension->oui_length)
+		return false;
+
+	data_len = elem_len - extension->oui_length;
+	if (data_len < extension->data_length)
+		return false;
+
+	data = &oui_ptr[2 + extension->oui_length];
+	for (i = 0, j = 0;
+	     (i < data_len && j < extension->data_mask_length);
+	     i++) {
+		if ((extension->data_mask[j] & data_mask) &&
+		    !(extension->data[i] == data[i]))
+			return false;
+		data_mask = data_mask >> 1;
+		if (!data_mask) {
+			data_mask = 0x80;
+			j++;
+		}
+	}
+
+	return true;
+}
+
+/**
+ * check_for_vendor_ap_mac() - compares for vendor AP MAC in the ini with
+ * bssid from the session and returns true if matches
+ * @extension: pointer to action oui extension data
+ * @attr: pointer to structure containing mac_addr (bssid) of AP
+ *
+ * Return: true or false
+ */
+static bool
+check_for_vendor_ap_mac(struct action_oui_extension *extension,
+			struct action_oui_search_attr *attr)
+{
+	uint8_t i;
+	uint8_t mac_mask = 0x80;
+	uint8_t *mac_addr = attr->mac_addr;
+
+	for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) {
+		if ((*extension->mac_mask & mac_mask) &&
+		    !(extension->mac_addr[i] == mac_addr[i]))
+			return false;
+		mac_mask = mac_mask >> 1;
+	}
+
+	return true;
+}
+
+/**
+ * check_for_vendor_ap_capabilities() - Compares various Vendor AP
+ * capabilities like NSS, HT, VHT, Band from the ini with the AP's capability
+ * from the beacon and returns true if all the capability matches
+ * @extension: pointer to oui extension data
+ * @attr: pointer to structure containing type of action, ap capabilities
+ *
+ * Return: true or false
+ */
+static bool
+check_for_vendor_ap_capabilities(struct action_oui_extension *extension,
+				 struct action_oui_search_attr *attr)
+{
+	uint8_t nss_mask;
+
+	if (extension->info_mask & ACTION_OUI_INFO_AP_CAPABILITY_NSS) {
+		nss_mask = 1 << (attr->nss - 1);
+		if (!((*extension->capability &
+		    ACTION_OUI_CAPABILITY_NSS_MASK) &
+		    nss_mask))
+		return false;
+	}
+
+	if (extension->info_mask & ACTION_OUI_INFO_AP_CAPABILITY_HT) {
+		if (*extension->capability &
+		    ACTION_OUI_CAPABILITY_HT_ENABLE_MASK) {
+			if (!attr->ht_cap)
+				return false;
+		} else {
+			if (attr->ht_cap)
+				return false;
+		}
+	}
+
+	if (extension->info_mask & ACTION_OUI_INFO_AP_CAPABILITY_VHT) {
+		if (*extension->capability &
+		    ACTION_OUI_CAPABILITY_VHT_ENABLE_MASK) {
+			if (!attr->vht_cap)
+				return false;
+		} else {
+			if (attr->vht_cap)
+				return false;
+		}
+	}
+
+	if (extension->info_mask & ACTION_OUI_INFO_AP_CAPABILITY_BAND) {
+		if ((*extension->capability &
+		    ACTION_OUI_CAPABILITY_2G_BAND_MASK) &&
+		    !attr->enable_2g)
+			return false;
+		if ((*extension->capability &
+		    ACTION_CAPABILITY_5G_BAND_MASK) &&
+		    !attr->enable_5g)
+			return false;
+	}
+
+	return true;
+}
+
+bool
+action_oui_search(struct action_oui_psoc_priv *psoc_priv,
+		  struct action_oui_search_attr *attr,
+		  enum action_oui_id action_id)
+{
+	struct action_oui_priv *oui_priv;
+	struct action_oui_extension_priv *priv_ext;
+	struct action_oui_extension *extension;
+	qdf_list_node_t *node = NULL;
+	qdf_list_node_t *next_node = NULL;
+	qdf_list_t *extension_list;
+	QDF_STATUS qdf_status;
+	const uint8_t *oui_ptr;
+
+	oui_priv = psoc_priv->oui_priv[action_id];
+	if (!oui_priv) {
+		action_oui_debug("action oui for id %d is empty",
+				 action_id);
+		return false;
+	}
+
+	extension_list = &oui_priv->extension_list;
+	qdf_mutex_acquire(&oui_priv->extension_lock);
+	if (qdf_list_empty(extension_list)) {
+		qdf_mutex_release(&oui_priv->extension_lock);
+		action_oui_debug("OUI List Empty");
+		return false;
+	}
+
+	qdf_list_peek_front(extension_list, &node);
+	while (node) {
+		priv_ext = qdf_container_of(node,
+					   struct action_oui_extension_priv,
+					   item);
+		extension = &priv_ext->extension;
+		oui_ptr = wlan_get_vendor_ie_ptr_from_oui(extension->oui,
+							 extension->oui_length,
+							 attr->ie_data,
+							 attr->ie_length);
+		if (!oui_ptr) {
+			action_oui_debug("No matching IE found for OUI");
+			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
+					   QDF_TRACE_LEVEL_DEBUG,
+					   extension->oui,
+					   extension->oui_length);
+			goto next;
+		}
+
+		action_oui_debug("IE found for OUI");
+		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
+				   QDF_TRACE_LEVEL_DEBUG,
+				   extension->oui,
+				   extension->oui_length);
+
+		if (extension->data_length &&
+		    !check_for_vendor_oui_data(extension, oui_ptr)) {
+			action_oui_debug("Vendor IE Data mismatch");
+			goto next;
+		}
+
+		if ((extension->info_mask & ACTION_OUI_INFO_MAC_ADDRESS) &&
+		    !check_for_vendor_ap_mac(extension, attr)) {
+			action_oui_debug("Vendor IE MAC Mismatch");
+			goto next;
+		}
+
+		if (!check_for_vendor_ap_capabilities(extension, attr)) {
+			action_oui_debug("Vendor IE capabilties mismatch");
+			goto next;
+		}
+
+		action_oui_debug("Vendor AP found for OUI");
+		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
+				   extension->oui, extension->oui_length);
+		qdf_mutex_release(&oui_priv->extension_lock);
+		return true;
+next:
+		qdf_status = qdf_list_peek_next(extension_list,
+						node, &next_node);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
+			break;
+
+		node = next_node;
+		next_node = NULL;
+	}
+
+	qdf_mutex_release(&oui_priv->extension_lock);
+	return false;
+}

+ 197 - 0
action_oui/dispatcher/inc/wlan_action_oui_public_struct.h

@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2016-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare structs and macros which can be accessed by various
+ * components and modules.
+ */
+
+#ifndef _WLAN_ACTION_OUI_PUBLIC_STRUCT_H_
+#define _WLAN_ACTION_OUI_PUBLIC_STRUCT_H_
+
+#include <wlan_cmn.h>
+#include <qdf_status.h>
+#include <qdf_types.h>
+
+/*
+ * Maximum ini string length of actions oui extensions,
+ * (n * 83) + (n - 1) spaces + 1 (terminating character),
+ * where n is the no of oui extensions
+ * currently, max no of oui extensions is 10
+ */
+#define ACTION_OUI_MAX_STR_LEN 840
+
+/*
+ * Maximum number of action oui extensions supported in
+ * each action oui category
+ */
+#define ACTION_OUI_MAX_EXTENSIONS 10
+
+#define ACTION_OUI_MAX_OUI_LENGTH 5
+#define ACTION_OUI_MAX_DATA_LENGTH 20
+#define ACTION_OUI_MAX_DATA_MASK_LENGTH 3
+#define ACTION_OUI_MAC_MASK_LENGTH 1
+#define ACTION_OUI_MAX_CAPABILITY_LENGTH 1
+
+/*
+ * NSS Mask and NSS Offset to extract NSS info from
+ * capability field of action oui extension
+ */
+#define ACTION_OUI_CAPABILITY_NSS_MASK 0x0f
+#define ACTION_OUI_CAPABILITY_NSS_OFFSET 0
+#define ACTION_OUI_CAPABILITY_NSS_MASK_1X1 1
+#define ACTION_OUI_CAPABILITY_NSS_MASK_2X2 2
+#define ACTION_OUI_CAPABILITY_NSS_MASK_3X3 4
+#define ACTION_OUI_CAPABILITY_NSS_MASK_4X4 8
+
+/*
+ * Mask and offset to extract HT and VHT info from
+ * capability field of action oui extension
+ */
+#define ACTION_OUI_CAPABILITY_HT_ENABLE_MASK 0x10
+#define ACTION_OUI_CAPABILITY_HT_ENABLE_OFFSET 4
+#define ACTION_OUI_CAPABILITY_VHT_ENABLE_MASK 0x20
+#define ACTION_OUI_CAPABILITY_VHT_ENABLE_OFFSET 5
+
+/*
+ * Mask and offset to extract Band (2G and 5G) info from
+ * capability field of action oui extension
+ */
+#define ACTION_OUI_CAPABILITY_BAND_MASK 0xC0
+#define ACTION_OUI_CAPABILITY_BAND_OFFSET 6
+#define ACTION_OUI_CAPABILITY_2G_BAND_MASK 0x40
+#define ACTION_OUI_CAPABILITY_2G_BAND_OFFSET 6
+#define ACTION_CAPABILITY_5G_BAND_MASK 0x80
+#define ACTION_CAPABILITY_5G_BAND_OFFSET 7
+
+/**
+ * enum action_oui_id - to identify type of action oui
+ * @ACTION_OUI_CONNECT_1X1: for 1x1 connection only
+ * @ACTION_OUI_ITO_EXTENSION: for extending inactivity time of station
+ * @ACTION_OUI_CCKM_1X1: for TX with CCKM 1x1 only
+ * @ACTION_OUI_MAXIMUM_ID: maximun number of action oui types
+ */
+enum action_oui_id {
+	ACTION_OUI_CONNECT_1X1 = 0,
+	ACTION_OUI_ITO_EXTENSION = 1,
+	ACTION_OUI_CCKM_1X1 = 2,
+	ACTION_OUI_ITO_ALTERNATE = 3,
+	ACTION_OUI_SWITCH_TO_11N_MODE = 4,
+	ACTION_OUI_MAXIMUM_ID
+};
+
+/**
+ * enum action_oui_info - to indicate presence of various action OUI
+ * fields in action oui extension, following identifiers are to be set in
+ * the info mask field of action oui extension
+ * @ACTION_OUI_INFO_OUI: to indicate presence of OUI string
+ * @ACTION_OUI_INFO_MAC_ADDRESS: to indicate presence of mac address
+ * @ACTION_OUI_INFO_AP_CAPABILITY_NSS: to indicate presence of nss info
+ * @ACTION_OUI_INFO_AP_CAPABILITY_HT: to indicate presence of HT cap
+ * @ACTION_OUI_INFO_AP_CAPABILITY_VHT: to indicate presence of VHT cap
+ * @ACTION_OUI_INFO_AP_CAPABILITY_BAND: to indicate presence of band info
+ */
+enum action_oui_info {
+	/*
+	 * OUI centric parsing, expect OUI in each action OUI extension,
+	 * hence, ACTION_OUI_INFO_OUI is dummy
+	 */
+	ACTION_OUI_INFO_OUI = 1 << 0,
+	ACTION_OUI_INFO_MAC_ADDRESS = 1 << 1,
+	ACTION_OUI_INFO_AP_CAPABILITY_NSS = 1 << 2,
+	ACTION_OUI_INFO_AP_CAPABILITY_HT = 1 << 3,
+	ACTION_OUI_INFO_AP_CAPABILITY_VHT = 1 << 4,
+	ACTION_OUI_INFO_AP_CAPABILITY_BAND = 1 << 5,
+};
+
+/* Total mask of all enum action_oui_info IDs */
+#define ACTION_OUI_INFO_MASK 0x3F
+
+/**
+ * struct action_oui_extension - action oui extension contents
+ * @info_mask: info mask
+ * @oui_length: length of the oui, either 3 or 5 bytes
+ * @data_length: length of the oui data
+ * @data_mask_length: length of the data mask
+ * @mac_addr_length: length of the mac addr
+ * @mac_mask_length: length of the mac mask
+ * @capability_length: length of the capability
+ * @oui: oui value
+ * @data: data buffer
+ * @data_mask: data mask buffer
+ * @mac_addr: mac addr
+ * @mac_mask: mac mask
+ * @capability: capability buffer
+ */
+struct action_oui_extension {
+	uint32_t info_mask;
+	uint32_t oui_length;
+	uint32_t data_length;
+	uint32_t data_mask_length;
+	uint32_t mac_addr_length;
+	uint32_t mac_mask_length;
+	uint32_t capability_length;
+	uint8_t oui[ACTION_OUI_MAX_OUI_LENGTH];
+	uint8_t data[ACTION_OUI_MAX_DATA_LENGTH];
+	uint8_t data_mask[ACTION_OUI_MAX_DATA_MASK_LENGTH];
+	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
+	uint8_t mac_mask[ACTION_OUI_MAC_MASK_LENGTH];
+	uint8_t capability[ACTION_OUI_MAX_CAPABILITY_LENGTH];
+};
+
+/**
+ * struct action_oui_request - Contains specific action oui information
+ * @action_id: type of action from enum action_oui_info
+ * @no_oui_extensions: number of action oui extensions of type @action_id
+ * @total_no_oui_extensions: total no of oui extensions from all
+ * action oui types, this is just a total count needed by firmware
+ * @extension: pointer to zero length array, to indicate this structure is
+ * followed by a array of @no_oui_extensions structures of
+ * type struct action_oui_extension
+ */
+struct action_oui_request {
+	enum action_oui_id action_id;
+	uint32_t no_oui_extensions;
+	uint32_t total_no_oui_extensions;
+	struct action_oui_extension extension[0];
+};
+
+/**
+ * struct action_oui_search_attr - Used to check against action_oui ini input
+ *
+ * @ie_data: beacon ie data
+ * @ie_length: length of ie data
+ * @mac_addr: bssid of access point
+ * @nss: AP spatial stream info
+ * @ht_cap: Whether AP is HT capable
+ * @vht_cap: Whether AP is VHT capable
+ * @enable_2g: Whether 2.4GHz band is enabled in AP
+ * @enable_5g: Whether 5GHz band is enabled in AP
+ */
+struct action_oui_search_attr {
+	uint8_t *ie_data;
+	uint32_t ie_length;
+	uint8_t *mac_addr;
+	uint32_t nss;
+	bool ht_cap;
+	bool vht_cap;
+	bool enable_2g;
+	bool enable_5g;
+};
+
+#endif /* _WLAN_ACTION_OUI_PUBLIC_STRUCT_H_ */

+ 51 - 0
action_oui/dispatcher/inc/wlan_action_oui_tgt_api.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare public API for action_oui to interact with target/WMI
+ */
+
+#ifndef _WLAN_ACTION_OUI_TGT_API_H_
+#define _WLAN_ACTION_OUI_TGT_API_H_
+
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_objmgr.h"
+
+#define GET_ACTION_OUI_TX_OPS_FROM_PSOC(psoc) \
+	(&action_oui_psoc_get_priv(psoc)->tx_ops)
+
+/**
+ * tgt_action_oui_send() - Send request to target if
+ * @psoc: objmgr psoc object
+ * @req: action_oui request to be send
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_action_oui_send(struct wlan_objmgr_psoc *psoc,
+				struct action_oui_request *req);
+
+/**
+ * struct action_oui_tx_ops - structure of tx operations
+ * @send_req: Pointer to hold target_if send function
+ */
+struct action_oui_tx_ops {
+	QDF_STATUS (*send_req)(struct wlan_objmgr_psoc *psoc,
+			       struct action_oui_request *req);
+};
+
+#endif /* _WLAN_ACTION_OUI_TGT_API_H_ */

+ 210 - 0
action_oui/dispatcher/inc/wlan_action_oui_ucfg_api.h

@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare public API related to the action_oui called by north bound
+ * HDD/OSIF/LIM
+ */
+
+#ifndef _WLAN_ACTION_OUI_UCFG_API_H_
+#define _WLAN_ACTION_OUI_UCFG_API_H_
+
+#include <qdf_status.h>
+#include <qdf_types.h>
+#include "wlan_action_oui_public_struct.h"
+#include "wlan_action_oui_objmgr.h"
+
+#ifdef WLAN_FEATURE_ACTION_OUI
+
+/**
+ * ucfg_action_oui_init() - Register notification handlers.
+ *
+ * This function registers action_oui notification handlers which are
+ * invoked from psoc create/destroy handlers.
+ *
+ * Return: For successful registration - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+QDF_STATUS ucfg_action_oui_init(void);
+
+/**
+ * ucfg_action_oui_deinit() - Unregister notification handlers.
+ *
+ * This function Unregisters action_oui notification handlers which are
+ * invoked from psoc create/destroy handlers.
+ *
+ * Return: None
+ */
+void ucfg_action_oui_deinit(void);
+
+/**
+ * ucfg_action_oui_parse() - Parse input string and extract extensions.
+ * @psoc: objmgr psoc object
+ * @in_str: input string to be parsed
+ * @action_id: action to which given string corresponds
+ *
+ * This is a wrapper function which invokes internal function
+ * action_oui_extract() to extract OUIs and related attributes.
+ *
+ * Return: For successful parse - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+QDF_STATUS
+ucfg_action_oui_parse(struct wlan_objmgr_psoc *psoc,
+		      const uint8_t *in_str,
+		      enum action_oui_id action_id);
+
+/**
+ * ucfg_action_oui_send() - Send action_oui and related attributes to Fw.
+ * @psoc: objmgr psoc object
+ *
+ * This is a wrapper function which invokes internal function
+ * action_oui_send() to send OUIs and related attributes to firmware.
+ *
+ * Return: For successful send - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+QDF_STATUS ucfg_action_oui_send(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * ucfg_action_oui_enabled() - State of action_oui component
+ *
+ * Return: When action_oui component is present return true
+ *	   else return false.
+ */
+static inline bool ucfg_action_oui_enabled(void)
+{
+	return true;
+}
+
+/**
+ * ucfg_action_oui_search() - Check for OUIs and related info in IE data.
+ * @psoc: objmgr psoc object
+ * @attr: pointer to structure containing type of action, beacon IE data etc.,
+ * @action_id: type of action to be checked
+ *
+ * This is a wrapper function which invokes internal function to search
+ * for OUIs and related info (specified from ini file) in vendor specific
+ * data of beacon IE for given action.
+ *
+ * Return: If search is successful return true else false.
+ */
+bool ucfg_action_oui_search(struct wlan_objmgr_psoc *psoc,
+			    struct action_oui_search_attr *attr,
+			    enum action_oui_id action_id);
+
+#else
+
+/**
+ * ucfg_action_oui_init() - Register notification handlers.
+ *
+ * This function registers action_oui notification handlers which are
+ * invoked from psoc create/destroy handlers.
+ *
+ * Return: For successful registration - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+static inline
+QDF_STATUS ucfg_action_oui_init(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * ucfg_action_oui_deinit() - Unregister notification handlers.
+ *
+ * This function Unregisters action_oui notification handlers which are
+ * invoked from psoc create/destroy handlers.
+ *
+ * Return: None
+ */
+static inline
+void ucfg_action_oui_deinit(void)
+{
+}
+
+/**
+ * ucfg_action_oui_parse() - Parse input string of action_id specified.
+ * @psoc: objmgr psoc object
+ * @in_str: input string to be parsed
+ * @action_id: action to which given string corresponds
+ *
+ * This is a wrapper function which invokes internal function
+ * action_oui_extract() to extract OUIs and related attributes.
+ *
+ * Return: For successful parse - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+static inline QDF_STATUS
+ucfg_action_oui_parse(struct wlan_objmgr_psoc *psoc,
+		      const uint8_t *in_str,
+		      enum action_oui_id action_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * ucfg_action_oui_send() - Send action_oui and related attributes to Fw.
+ * @psoc: objmgr psoc object
+ *
+ * This is a wrapper function which invokes internal function
+ * action_oui_send() to send OUIs and related attributes to firmware.
+ *
+ * Return: For successful send - QDF_STATUS_SUCCESS,
+ *	   else QDF_STATUS error codes.
+ */
+static inline
+QDF_STATUS ucfg_action_oui_send(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * ucfg_action_oui_enabled() - State of action_oui component
+ *
+ * Return: When action_oui component is present return true
+ *	   else return false.
+ */
+static inline bool ucfg_action_oui_enabled(void)
+{
+	return false;
+}
+
+/**
+ * ucfg_action_oui_search() - Check for OUIs and related info in IE data.
+ * @psoc: objmgr psoc object
+ * @attr: pointer to structure containing type of action, beacon IE data etc.,
+ * @action_id: type of action to be checked
+ *
+ * This is a wrapper function which invokes internal function to search
+ * for OUIs and related info (specified from ini file) in vendor specific
+ * data of beacon IE for given action.
+ *
+ * Return: If search is successful return true else false.
+ */
+static inline
+bool ucfg_action_oui_search(struct wlan_objmgr_psoc *psoc,
+			    struct action_oui_search_attr *attr,
+			    enum action_oui_id action_id)
+{
+	return false;
+}
+
+#endif /* WLAN_FEATURE_ACTION_OUI */
+
+#endif /* _WLAN_ACTION_OUI_UCFG_API_H_ */

+ 43 - 0
action_oui/dispatcher/src/wlan_action_oui_tgt_api.c

@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Implements public API for action_oui to interact with target/WMI
+ */
+
+#include "wlan_action_oui_tgt_api.h"
+#include "wlan_action_oui_main.h"
+#include "wlan_action_oui_public_struct.h"
+
+QDF_STATUS tgt_action_oui_send(struct wlan_objmgr_psoc *psoc,
+			       struct action_oui_request *req)
+{
+	struct action_oui_tx_ops *tx_ops;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	ACTION_OUI_ENTER();
+
+	tx_ops = GET_ACTION_OUI_TX_OPS_FROM_PSOC(psoc);
+	QDF_ASSERT(tx_ops->send_req);
+	if (tx_ops->send_req)
+		status = tx_ops->send_req(psoc, req);
+
+	ACTION_OUI_EXIT();
+
+	return status;
+}

+ 201 - 0
action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c

@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2012-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Public API implementation of action_oui called by north bound HDD/OSIF.
+ */
+
+#include "wlan_action_oui_ucfg_api.h"
+#include "wlan_action_oui_main.h"
+#include "wlan_action_oui_main.h"
+#include "target_if_action_oui.h"
+#include "wlan_action_oui_tgt_api.h"
+#include <qdf_str.h>
+
+QDF_STATUS ucfg_action_oui_init(void)
+{
+	QDF_STATUS status;
+
+	ACTION_OUI_ENTER();
+
+	status = wlan_objmgr_register_psoc_create_handler(
+				WLAN_UMAC_COMP_ACTION_OUI,
+				action_oui_psoc_create_notification, NULL);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		action_oui_err("Failed to register psoc create handler");
+		goto exit;
+	}
+
+	status = wlan_objmgr_register_psoc_destroy_handler(
+				WLAN_UMAC_COMP_ACTION_OUI,
+				action_oui_psoc_destroy_notification, NULL);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		action_oui_debug("psoc create/delete notifications registered");
+		goto exit;
+	}
+
+	action_oui_err("Failed to register psoc delete handler");
+	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_ACTION_OUI,
+			action_oui_psoc_create_notification, NULL);
+
+exit:
+	ACTION_OUI_EXIT();
+	return status;
+}
+
+void ucfg_action_oui_deinit(void)
+{
+	QDF_STATUS status;
+
+	ACTION_OUI_ENTER();
+
+	status = wlan_objmgr_unregister_psoc_create_handler(
+				WLAN_UMAC_COMP_ACTION_OUI,
+				action_oui_psoc_create_notification, NULL);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		action_oui_err("Failed to unregister psoc create handler");
+
+	status = wlan_objmgr_unregister_psoc_destroy_handler(
+				WLAN_UMAC_COMP_ACTION_OUI,
+				action_oui_psoc_destroy_notification,
+				NULL);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		action_oui_err("Failed to unregister psoc delete handler");
+
+	ACTION_OUI_EXIT();
+}
+
+QDF_STATUS
+ucfg_action_oui_parse(struct wlan_objmgr_psoc *psoc,
+		      const uint8_t *in_str,
+		      enum action_oui_id action_id)
+{
+	struct action_oui_psoc_priv *psoc_priv;
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+	uint8_t *oui_str;
+	int len;
+
+	ACTION_OUI_ENTER();
+
+	if (!psoc) {
+		action_oui_err("psoc is NULL");
+		goto exit;
+	}
+
+	if (action_id >= ACTION_OUI_MAXIMUM_ID) {
+		action_oui_err("Invalid action_oui id: %u", action_id);
+		goto exit;
+	}
+
+	psoc_priv = action_oui_psoc_get_priv(psoc);
+	if (!psoc_priv) {
+		action_oui_err("psoc priv is NULL");
+		goto exit;
+	}
+
+	len = qdf_str_len(in_str);
+	if (len <= 0 || len > ACTION_OUI_MAX_STR_LEN - 1) {
+		action_oui_err("Invalid string length: %u", action_id);
+		goto exit;
+	}
+
+	oui_str = qdf_mem_malloc(len + 1);
+	if (!oui_str) {
+		action_oui_err("Mem alloc failed for string: %u", action_id);
+		status = QDF_STATUS_E_NOMEM;
+		goto exit;
+	}
+
+	qdf_mem_copy(oui_str, in_str, len);
+	oui_str[len] = '\0';
+
+	status = action_oui_parse(psoc_priv, oui_str, action_id);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		action_oui_err("Failed to parse: %u", action_id);
+
+	qdf_mem_free(oui_str);
+
+exit:
+	ACTION_OUI_EXIT();
+	return status;
+}
+
+QDF_STATUS ucfg_action_oui_send(struct wlan_objmgr_psoc *psoc)
+{
+	struct action_oui_psoc_priv *psoc_priv;
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+	uint32_t id;
+
+	ACTION_OUI_ENTER();
+
+	if (!psoc) {
+		action_oui_err("psoc is NULL");
+		goto exit;
+	}
+
+	psoc_priv = action_oui_psoc_get_priv(psoc);
+	if (!psoc_priv) {
+		action_oui_err("psoc priv is NULL");
+		goto exit;
+	}
+
+	for (id = 0; id < ACTION_OUI_MAXIMUM_ID; id++) {
+		status = action_oui_send(psoc_priv, id);
+		if (!QDF_IS_STATUS_SUCCESS(status))
+			action_oui_err("Failed to send: %u", id);
+	}
+
+exit:
+	ACTION_OUI_EXIT();
+	return status;
+}
+
+bool ucfg_action_oui_search(struct wlan_objmgr_psoc *psoc,
+			    struct action_oui_search_attr *attr,
+			    enum action_oui_id action_id)
+{
+	struct action_oui_psoc_priv *psoc_priv;
+	bool found = false;
+
+	ACTION_OUI_ENTER();
+
+	if (!psoc || !attr) {
+		action_oui_err("Invalid psoc or search attrs");
+		goto exit;
+	}
+
+	if (action_id >= ACTION_OUI_MAXIMUM_ID ||
+	    !attr->ie_data || !attr->ie_length) {
+		action_oui_err("Invalid action_oui id: %u", action_id);
+		goto exit;
+	}
+
+	psoc_priv = action_oui_psoc_get_priv(psoc);
+	if (!psoc_priv) {
+		action_oui_err("psoc priv is NULL");
+		goto exit;
+	}
+
+	found = action_oui_search(psoc_priv, attr, action_id);
+	if (found)
+		action_oui_debug("Search Successful");
+
+exit:
+	ACTION_OUI_EXIT();
+	return found;
+}

+ 43 - 0
target_if/action_oui/inc/target_if_action_oui.h

@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare various api/struct which shall be used
+ * by action_oui component for wmi command path.
+ */
+
+#ifndef _TARGET_IF_ACTION_OUI_H_
+#define _TARGET_IF_ACTION_OUI_H_
+
+#include "target_if.h"
+#include <wmi_unified_api.h>
+#include <wmi_unified_priv.h>
+#include <wmi_unified_param.h>
+#include "wlan_action_oui_tgt_api.h"
+#include "wlan_action_oui_public_struct.h"
+
+/**
+ * target_if_action_oui_register_tx_ops() - Register action_oui component TX OPS
+ * @tx_ops: action_oui transmit ops
+ *
+ * Return: None
+ */
+void
+target_if_action_oui_register_tx_ops(struct action_oui_tx_ops *tx_ops);
+
+#endif /* _TARGET_IF_ACTION_OUI_H_ */

+ 46 - 0
target_if/action_oui/src/target_if_action_oui.c

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013-2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Target interface file for action_oui component to
+ * Implement api's which shall be used by action_oui component
+ * in target_if internally.
+ */
+
+#include "target_if_action_oui.h"
+#include "wlan_action_oui_tgt_api.h"
+#include "wlan_action_oui_public_struct.h"
+
+static QDF_STATUS
+target_if_action_oui_send_req(struct wlan_objmgr_psoc *psoc,
+		struct action_oui_request *req)
+{
+	return wmi_unified_send_action_oui_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
+						req);
+}
+
+void
+target_if_action_oui_register_tx_ops(struct action_oui_tx_ops *tx_ops)
+{
+	if (!tx_ops) {
+		target_if_err("action_oui tx_ops is null");
+		return;
+	}
+
+	tx_ops->send_req = target_if_action_oui_send_req;
+}