diff --git a/Kbuild b/Kbuild index 6e957b55ba..e9145bd42c 100644 --- a/Kbuild +++ b/Kbuild @@ -734,6 +734,19 @@ MLME_INC := -I$(WLAN_ROOT)/$(MLME_DIR)/core/inc \ MLME_OBJS := $(MLME_DIR)/core/src/wlan_mlme_main.o +########## ACTION OUI ########## + +ACTION_OUI_DIR := components/action_oui +ACTION_OUI_INC := -I$(WLAN_ROOT)/$(ACTION_OUI_DIR)/core/inc \ + -I$(WLAN_ROOT)/$(ACTION_OUI_DIR)/dispatcher/inc + +ifeq ($(CONFIG_WLAN_FEATURE_ACTION_OUI), y) +ACTION_OUI_OBJS := $(ACTION_OUI_DIR)/core/src/wlan_action_oui_main.o \ + $(ACTION_OUI_DIR)/core/src/wlan_action_oui_parse.o \ + $(ACTION_OUI_DIR)/dispatcher/src/wlan_action_oui_tgt_api.o \ + $(ACTION_OUI_DIR)/dispatcher/src/wlan_action_oui_ucfg_api.o +endif + ########## CLD TARGET_IF ####### CLD_TARGET_IF_DIR := components/target_if @@ -771,6 +784,11 @@ CLD_TARGET_IF_INC += -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/ipa/inc CLD_TARGET_IF_OBJ += $(CLD_TARGET_IF_DIR)/ipa/src/target_if_ipa.o endif +ifeq ($(CONFIG_WLAN_FEATURE_ACTION_OUI), y) +CLD_TARGET_IF_INC += -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/action_oui/inc +CLD_TARGET_IF_OBJ += $(CLD_TARGET_IF_DIR)/action_oui/src/target_if_action_oui.o +endif + ############## UMAC P2P ########### P2P_DIR := umac/p2p P2P_CORE_DIR := $(P2P_DIR)/core @@ -878,6 +896,10 @@ ifeq ($(CONFIG_QCACLD_FEATURE_APF), y) WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_apf_tlv.o endif +ifeq ($(CONFIG_WLAN_FEATURE_ACTION_OUI), y) +WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_action_oui_tlv.o +endif + ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) ifeq ($(CONFIG_OCB_UT_FRAMEWORK), y) WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_ocb_ut.o @@ -1463,6 +1485,7 @@ INCS += $(HOST_DIAG_LOG_INC) endif INCS += $(DISA_INC) +INCS += $(ACTION_OUI_INC) INCS += $(UMAC_DISP_INC) INCS += $(UMAC_SCAN_INC) @@ -1551,6 +1574,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_DISA), y) OBJS += $(DISA_OBJS) endif +ifeq ($(CONFIG_WLAN_FEATURE_ACTION_OUI), y) +OBJS += $(ACTION_OUI_OBJS) +endif + OBJS += $(UMAC_DISP_OBJS) OBJS += $(UMAC_SCAN_OBJS) OBJS += $(UMAC_COMMON_OBJS) @@ -1971,6 +1998,8 @@ cppflags-$(CONFIG_WLAN_OFFLOAD_PACKETS) += -DWLAN_FEATURE_OFFLOAD_PACKETS cppflags-$(CONFIG_WLAN_FEATURE_DISA) += -DWLAN_FEATURE_DISA +cppflags-$(CONFIG_WLAN_FEATURE_ACTION_OUI) += -DWLAN_FEATURE_ACTION_OUI + cppflags-$(CONFIG_WLAN_FEATURE_FIPS) += -DWLAN_FEATURE_FIPS cppflags-$(CONFIG_LFR_SUBNET_DETECTION) += -DFEATURE_LFR_SUBNET_DETECTION diff --git a/components/action_oui/core/inc/wlan_action_oui_main.h b/components/action_oui/core/inc/wlan_action_oui_main.h new file mode 100644 index 0000000000..7777476a62 --- /dev/null +++ b/components/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 +#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_ */ diff --git a/components/action_oui/core/inc/wlan_action_oui_objmgr.h b/components/action_oui/core/inc/wlan_action_oui_objmgr.h new file mode 100644 index 0000000000..17d0b09c89 --- /dev/null +++ b/components/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 */ diff --git a/components/action_oui/core/inc/wlan_action_oui_priv.h b/components/action_oui/core/inc/wlan_action_oui_priv.h new file mode 100644 index 0000000000..2b325b4ae8 --- /dev/null +++ b/components/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 +#include +#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_ */ diff --git a/components/action_oui/core/src/wlan_action_oui_main.c b/components/action_oui/core/src/wlan_action_oui_main.c new file mode 100644 index 0000000000..825b989a16 --- /dev/null +++ b/components/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; +} diff --git a/components/action_oui/core/src/wlan_action_oui_parse.c b/components/action_oui/core/src/wlan_action_oui_parse.c new file mode 100644 index 0000000000..cde32c756f --- /dev/null +++ b/components/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 +#include + +/** + * 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; +} diff --git a/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h b/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h new file mode 100644 index 0000000000..5d19fefc66 --- /dev/null +++ b/components/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 +#include +#include + +/* + * 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_ */ diff --git a/components/action_oui/dispatcher/inc/wlan_action_oui_tgt_api.h b/components/action_oui/dispatcher/inc/wlan_action_oui_tgt_api.h new file mode 100644 index 0000000000..7a1d4f3080 --- /dev/null +++ b/components/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_ */ diff --git a/components/action_oui/dispatcher/inc/wlan_action_oui_ucfg_api.h b/components/action_oui/dispatcher/inc/wlan_action_oui_ucfg_api.h new file mode 100644 index 0000000000..00daeb9b66 --- /dev/null +++ b/components/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 +#include +#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_ */ diff --git a/components/action_oui/dispatcher/src/wlan_action_oui_tgt_api.c b/components/action_oui/dispatcher/src/wlan_action_oui_tgt_api.c new file mode 100644 index 0000000000..e3c2177d85 --- /dev/null +++ b/components/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; +} diff --git a/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c b/components/action_oui/dispatcher/src/wlan_action_oui_ucfg_api.c new file mode 100644 index 0000000000..7a3e38b5f9 --- /dev/null +++ b/components/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_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; +} diff --git a/components/target_if/action_oui/inc/target_if_action_oui.h b/components/target_if/action_oui/inc/target_if_action_oui.h new file mode 100644 index 0000000000..4bd65b7d06 --- /dev/null +++ b/components/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 +#include +#include +#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_ */ diff --git a/components/target_if/action_oui/src/target_if_action_oui.c b/components/target_if/action_oui/src/target_if_action_oui.c new file mode 100644 index 0000000000..1627e59b0c --- /dev/null +++ b/components/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; +} diff --git a/configs/default_defconfig b/configs/default_defconfig index c0a29331e0..49c0a90eb2 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -123,6 +123,9 @@ endif #Flag to enable Fast Transition (11r) feature CONFIG_QCOM_VOWIFI_11R := y +#Flag to enable disable ACTION OUI feature +CONFIG_WLAN_FEATURE_ACTION_OUI := y + #Flag to enable FILS Feature (11ai) CONFIG_WLAN_FEATURE_FILS := y ifneq ($(CONFIG_QCA_CLD_WLAN),) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 47dc63f01f..f9e345e642 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -37,6 +37,7 @@ #include "osapi_linux.h" #include #include "wlan_pmo_hw_filter_public_struct.h" +#include "wlan_action_oui_public_struct.h" #include "wlan_hdd_green_ap_cfg.h" struct hdd_context; @@ -14137,6 +14138,275 @@ enum hdd_external_acs_policy { #define CFG_TX_SCH_DELAY_MAX (5) #define CFG_TX_SCH_DELAY_DEFAULT (0) +/* + * Start of action oui inis + * + * To enable action oui feature, set gEnableActionOUI + * + * Each action oui is expected in the following format: + * ..... (maximum 10) + * + * whereas, each Extension is separated by space and have the following format: + * + * where each Token is a string of hexa-decimal digits and + * following are the details about each token + * + * Token1 = OUI + * Token2 = Data_Length + * Token3 = Data + * Token4 = Data_Mask + * Token5 = Info_Presence_Bit + * Token6 = MAC_Address + * Token7 = Mac_Address Mask + * Token8 = Capability + * + * is mandatory and it can be either 3 or 5 bytes means 6 or 10 + * hexa-decimal characters + * + * is mandatory field and should give length of + * the if present else zero + * + * Presence of is controlled by , if is 0, + * then is not expected else Data of the size Data Length bytes are + * expected which means the length of Data string is 2 * Data Length, + * since every byte constitutes two hexa-decimal characters. + * + * is mandatory if is present and length of the + * Data mask string depends on the + * If is 06, then length of Data Mask string is + * 2 characters (represents 1 byte) + * data_mask_length = ((Data_Length - (Data_Length % 8)) / 8) + + * ((Data_Length % 8) ? 1 : 0) + * and has to be constructed from left to right. + * + * Presence of and is + * controlled by which is mandatory + * will give the information for + * OUI – bit 0 (set/reset don't effect the behaviour, + * always enabled in the code) + * Mac Address present – bit 1 + * NSS – bit 2 + * HT check – bit 3 + * VHT check – bit 4 + * Band info – bit 5 + * reserved – bit 6 (should always be zero) + * reserved – bit 7 (should always be zero) + * and should be constructed from right to left (b7b6b5b4b3b2b1b0) + * + * for should be constructed from left to right + * + * is 1 byte long and it contains the below info + * NSS – 4 bits starting from LSB (b0 – b3) + * HT enabled – bit 4 + * VHT enabled – bit 5 + * 2G band – bit 6 + * 5G band – bit 7 + * and should be constructed from right to left (b7b6b5b4b3b2b1b0) + * is present if atleast one of the bit is set + * from b2 - b6 in + * + * Example 1: + * + * OUI is 00-10-18, data length is 05 (hex form), data is 02-11-04-5C-DE and + * need to consider first 3 bytes and last byte of data for comparision + * mac-addr EE-1A-59-FE-FD-AF is present and first 3 bytes and last byte of + * mac address should be considered for comparision + * capability is not present + * then action OUI for gActionOUIITOExtension is as follows: + * + * gActionOUIITOExtension=001018 05 0211045CDE E8 03 EE1A59FEFDAF E4 + * + * data mask calculation in above example: + * Data[0] = 02 ---- d0 = 1 + * Data[1] = 11 ---- d1 = 1 + * Data[2] = 04 ---- d2 = 1 + * Data[3] = 5C ---- d3 = 0 + * Data[4] = DE ---- d4 = 1 + * data_mask = d0d1d2d3d4 + append with zeros to complete 8-bit = 11101000 = E8 + * + * mac mask calculation in above example: + * mac_addr[0] = EE ---- m0 = 1 + * mac_addr[1] = 1A ---- m1 = 1 + * mac_addr[2] = 59 ---- m2 = 1 + * mac_addr[3] = FE ---- m3 = 0 + * mac_addr[4] = FD ---- m4 = 0 + * mac_addr[5] = AF ---- m5 = 1 + * mac_mask = m0m1m2m3m4m5 + append with zeros to complete 8-bit = 11100100 = E4 + * + * Example 2: + * + * OUI is 00-10-18, data length is 00 and no Mac Address and capability + * + * gActionOUIITOExtension=001018 00 01 + * + */ + +/* + * + * gEnableActionOUI - Enable/Disable action oui feature + * @Min: 0 (disable) + * @Max: 1 (enable) + * @Default: 1 (enable) + * + * This ini is used to enable the action oui feature to control + * mode of connection, connected AP's in-activity time, Tx rate etc., + * + * Related: If gEnableActionOUI is set, then at least one of the following inis + * must be set with the proper action oui extensions: + * gActionOUIConnect1x1, gActionOUIITOExtension, gActionOUICCKM1X1 + * + * Supported Feature: action ouis + * + * Usage: External + * + * + */ +#define CFG_ENABLE_ACTION_OUI "gEnableActionOUI" +#define CFG_ENABLE_ACTION_OUI_MIN (0) +#define CFG_ENABLE_ACTION_OUI_MAX (1) +#define CFG_ENABLE_ACTION_OUI_DEFAULT (1) + +/* + * + * gActionOUIConnect1x1 - Used to specify action OUIs for 1x1 connection + * @Default: 000C43 00 25 42 001018 06 02FFF02C0000 BC 25 42 001018 06 02FF040C0000 BC 25 42 00037F 00 35 6C + * Note: User should strictly add new action OUIs at the end of this + * default value. + * + * Default OUIs: (All values in Hex) + * OUI 1 : 000C43 + * OUI data Len : 00 + * Info Mask : 25 - Check for NSS and Band + * Capabilities: 42 - NSS == 2 && Band == 2G + * OUI 2 : 001018 + * OUI data Len : 06 + * OUI Data : 02FFF02C0000 + * OUI data Mask: BC - 10111100 + * Info Mask : 25 - Check for NSS and Band + * Capabilities: 42 - NSS == 2 && Band == 2G + * OUI 3 : 001018 + * OUI data Len : 06 + * OUI Data : 02FF040C0000 + * OUI data Mask: BC - 10111100 + * Info Mask : 25 - Check for NSS and Band + * Capabilities: 42 - NSS == 2 && Band == 2G + * OUI 4 : 00037F + * OUI data Len : 00 + * Info Mask : 35 - Check for NSS, VHT Caps and Band + * Capabilities: 6C - (NSS == 3 or 4) && VHT Caps Preset && Band == 2G + * + * This ini is used to specify the AP OUIs with which only 1x1 connection + * is allowed. + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_CONNECT_1X1_NAME "gActionOUIConnect1x1" +#define CFG_ACTION_OUI_CONNECT_1X1_DEFAULT "000C43 00 25 42 001018 06 02FFF02C0000 BC 25 42 001018 06 02FF040C0000 BC 25 42 00037F 00 35 6C" + +/* + * + * gActionOUIITOExtension - Used to extend in-activity time for specified APs + * @Default: 00037F 06 01010000FF7F FC 01 000AEB 02 0100 C0 01 000B86 03 010408 E0 01 + * Note: User should strictly add new action OUIs at the end of this + * default value. + * + * Default OUIs: (All values in Hex) + * OUI 1: 00037F + * OUI data Len: 06 + * OUI Data: 01010000FF7F + * OUI data Mask: FC - 11111100 + * Info Mask : 01 - only OUI present in Info mask + * + * OUI 2: 000AEB + * OUI data Len: 02 + * OUI Data: 0100 + * OUI data Mask: C0 - 11000000 + * Info Mask : 01 - only OUI present in Info mask + * + * OUI 3: 000B86 + * OUI data Len: 03 + * OUI Data: 010408 + * OUI data Mask: E0 - 11100000 + * Info Mask : 01 - only OUI present in Info mask + * + * This ini is used to specify AP OUIs using which station's in-activity time + * can be extended with the respective APs + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_ITO_EXTENSION_NAME "gActionOUIITOExtension" +#define CFG_ACTION_OUI_ITO_EXTENSION_DEFAULT "00037F 06 01010000FF7F FC 01 000AEB 02 0100 C0 01 000B86 03 010408 E0 01" + +/* + * + * gActionOUICCKM1X1 - Used to specify action OUIs to control station's TX rates + * + * This ini is used to specify AP OUIs for which station's CCKM TX rates + * should be 1x1 only. + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_CCKM_1X1_NAME "gActionOUICCKM1X1" +#define CFG_ACTION_OUI_CCKM_1X1_DEFAULT "" + +/* + * + * gActionOUIITOAlternate - Used to specify action OUIs to have alternate ITO in + * weak RSSI state + * + * This ini is used to specify AP OUIs for which the stations will have + * alternate ITOs for the case when the RSSI is weak. + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ + #define CFG_ACTION_OUI_ITO_ALTERNATE_NAME "gActionOUIITOAlternate" + #define CFG_ACTION_OUI_ITO_ALTERNATE_DEFAULT "001018 06 0202001c0000 FC 01" + +/* + * + * gActionOUISwitchTo11nMode - Used to specify action OUIs for switching to 11n + * + * This ini is used to specify which AP for which the connection has to be + * made in 2x2 mode with HT capabilities only and not VHT. + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_SWITCH_TO_11N_MODE_NAME "gActionOUISwitchTo11nMode" +#define CFG_ACTION_OUI_SWITCH_TO_11N_MODE_DEFAULT "00904C 03 FFFFBF 20 21 40" + + /* End of action oui inis */ + + /* * * gEnableUnitTestFramework - Enable/Disable unit test framework @@ -15116,6 +15386,8 @@ struct hdd_config { uint32_t neighbor_report_offload_per_threshold_offset; uint32_t neighbor_report_offload_cache_timeout; uint32_t neighbor_report_offload_max_req_cap; + bool action_oui_enable; + uint8_t action_oui_str[ACTION_OUI_MAXIMUM_ID][ACTION_OUI_MAX_STR_LEN]; uint32_t channel_select_logic_conc; uint16_t wmi_wq_watchdog_timeout; bool enable_bt_chain_separation; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 67e3bf9f6d..77522de523 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -4786,6 +4786,40 @@ struct reg_table_entry g_registry_table[] = { CFG_LOWER_BRSSI_THRESH_MIN, CFG_LOWER_BRSSI_THRESH_MAX), + REG_VARIABLE(CFG_ENABLE_ACTION_OUI, WLAN_PARAM_Integer, + struct hdd_config, action_oui_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_ACTION_OUI_DEFAULT, + CFG_ENABLE_ACTION_OUI_MIN, + CFG_ENABLE_ACTION_OUI_MAX), + + REG_VARIABLE_STRING(CFG_ACTION_OUI_CONNECT_1X1_NAME, WLAN_PARAM_String, + struct hdd_config, action_oui_str[0], + VAR_FLAGS_OPTIONAL, + (void *)CFG_ACTION_OUI_CONNECT_1X1_DEFAULT), + + REG_VARIABLE_STRING(CFG_ACTION_OUI_ITO_EXTENSION_NAME, + WLAN_PARAM_String, + struct hdd_config, action_oui_str[1], + VAR_FLAGS_OPTIONAL, + (void *)CFG_ACTION_OUI_ITO_EXTENSION_DEFAULT), + + REG_VARIABLE_STRING(CFG_ACTION_OUI_CCKM_1X1_NAME, WLAN_PARAM_String, + struct hdd_config, action_oui_str[2], + VAR_FLAGS_OPTIONAL, + (void *)CFG_ACTION_OUI_CCKM_1X1_DEFAULT), + + REG_VARIABLE_STRING(CFG_ACTION_OUI_ITO_ALTERNATE_NAME, + WLAN_PARAM_String, + struct hdd_config, action_oui_str[3], + VAR_FLAGS_OPTIONAL, + (void *)CFG_ACTION_OUI_ITO_ALTERNATE_DEFAULT), + REG_VARIABLE_STRING(CFG_ACTION_OUI_SWITCH_TO_11N_MODE_NAME, + WLAN_PARAM_String, + struct hdd_config, action_oui_str[4], + VAR_FLAGS_OPTIONAL, + (void *)CFG_ACTION_OUI_SWITCH_TO_11N_MODE_DEFAULT), + REG_VARIABLE(CFG_DTIM_1CHRX_ENABLE_NAME, WLAN_PARAM_Integer, struct hdd_config, enable_dtim_1chrx, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d6d2687720..6eac267b5a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -128,6 +128,7 @@ #include "wlan_hdd_sysfs.h" #include "wlan_disa_ucfg_api.h" #include "wlan_disa_obj_mgmt_api.h" +#include "wlan_action_oui_ucfg_api.h" #include "wlan_ipa_ucfg_api.h" #include #include "wlan_hdd_nud_tracking.h" @@ -292,6 +293,7 @@ static const struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = { [QDF_MODULE_ID_GREEN_AP] = {QDF_TRACE_LEVEL_ALL}, [QDF_MODULE_ID_OCB] = {QDF_TRACE_LEVEL_ALL}, [QDF_MODULE_ID_IPA] = {QDF_TRACE_LEVEL_ALL}, + [QDF_MODULE_ID_ACTION_OUI] = {QDF_TRACE_LEVEL_ALL}, [QDF_MODULE_ID_CONFIG] = {QDF_TRACE_LEVEL_ALL}, }; @@ -8721,6 +8723,12 @@ static void hdd_override_ini_config(struct hdd_context *hdd_ctx) hdd_ctx->config->enable_bcast_probe_rsp); hdd_ctx->config->oce_sta_enabled = 0; } + + if (hdd_ctx->config->action_oui_enable && !ucfg_action_oui_enabled()) { + hdd_ctx->config->action_oui_enable = 0; + hdd_err("Ignore ini: %s, since no action_oui component", + CFG_ENABLE_ACTION_OUI); + } } /** @@ -10488,6 +10496,56 @@ static void hdd_v2_flow_pool_unmap(int vdev_id) cds_get_context(QDF_MODULE_ID_TXRX), vdev_id); } +/** + * hdd_action_oui_config() - Configure action_oui strings + * @hdd_ctx: pointer to hdd context + * + * This is a HDD wrapper function which invokes ucfg api + * of action_oui component to parse action oui strings. + * + * Return: None + */ +static void hdd_action_oui_config(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + uint32_t id; + uint8_t *str; + + if (!hdd_ctx->config->action_oui_enable) + return; + + for (id = 0; id < ACTION_OUI_MAXIMUM_ID; id++) { + str = hdd_ctx->config->action_oui_str[id]; + if (!qdf_str_len(str)) + continue; + + status = ucfg_action_oui_parse(hdd_ctx->hdd_psoc, str, id); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to parse action_oui str: %u", id); + } +} + +/** + * hdd_action_oui_send() - Send action_oui extensions to firmware + * @hdd_ctx: pointer to hdd context + * + * This is a HDD wrapper function which invokes ucfg api + * of action_oui component to send action oui extensions to firmware. + * + * Return: None + */ +static void hdd_action_oui_send(struct hdd_context *hdd_ctx) +{ + QDF_STATUS status; + + if (!hdd_ctx->config->action_oui_enable) + return; + + status = ucfg_action_oui_send(hdd_ctx->hdd_psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to send one or all action_ouis"); +} + /** * hdd_configure_cds() - Configure cds modules * @hdd_ctx: HDD context @@ -10509,6 +10567,9 @@ int hdd_configure_cds(struct hdd_context *hdd_ctx) struct policy_mgr_dp_cbacks dp_cbs = {0}; mac_handle = hdd_ctx->mac_handle; + + hdd_action_oui_send(hdd_ctx); + if (hdd_ctx->config->is_force_1x1) sme_cli_set_command(0, (int)WMI_PDEV_PARAM_SET_IOT_PATTERN, 1, PDEV_CMD); @@ -11059,6 +11120,8 @@ int hdd_wlan_startup(struct device *dev) goto err_hdd_free_context; } + hdd_action_oui_config(hdd_ctx); + qdf_nbuf_init_replenish_timer(); #ifdef FEATURE_WLAN_CH_AVOID mutex_init(&hdd_ctx->avoid_freq_lock); @@ -12360,6 +12423,7 @@ static void component_init(void) disa_init(); ucfg_ocb_init(); ipa_init(); + ucfg_action_oui_init(); } /** @@ -12369,6 +12433,7 @@ static void component_init(void) */ static void component_deinit(void) { + ucfg_action_oui_deinit(); ipa_deinit(); ucfg_ocb_deinit(); pmo_deinit();