diff --git a/core/hdd/inc/wlan_hdd_oemdata.h b/core/hdd/inc/wlan_hdd_oemdata.h index d7ea393f92cd..58b704634078 100644 --- a/core/hdd/inc/wlan_hdd_oemdata.h +++ b/core/hdd/inc/wlan_hdd_oemdata.h @@ -25,6 +25,8 @@ #ifndef __WLAN_HDD_OEM_DATA_H__ #define __WLAN_HDD_OEM_DATA_H__ +#include "wmi_unified_param.h" + struct hdd_context; #ifdef FEATURE_OEM_DATA_SUPPORT @@ -271,4 +273,19 @@ int wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy, #else #define FEATURE_OEM_DATA_VENDOR_COMMANDS #endif + +#ifdef FEATURE_OEM_DATA +/** + * hdd_oem_event_handler_cb() - callback for oem data event + * @oem_event_data: oem data received in the event from the FW + * + * Return: None + */ +void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data); +#else +static inline void hdd_oem_event_handler_cb(void *oem_event_data) +{ +} +#endif + #endif /* __WLAN_HDD_OEM_DATA_H__ */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index dcb1d7e1efff..b13bc224b5af 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1574,6 +1574,10 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM, }, + [QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA, + }, }; /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 9f2bbbca9bae..47737c39151e 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -13126,6 +13126,7 @@ int hdd_register_cb(struct hdd_context *hdd_ctx) hdd_sme_close_session_callback, hdd_common_roam_callback); + sme_set_oem_data_event_handler_cb(mac_handle, hdd_oem_event_handler_cb); hdd_exit(); return ret; @@ -13152,6 +13153,9 @@ void hdd_deregister_cb(struct hdd_context *hdd_ctx) } mac_handle = hdd_ctx->mac_handle; + + sme_reset_oem_data_event_handler_cb(mac_handle); + sme_deregister_tx_queue_cb(mac_handle); sme_reset_link_layer_stats_ind_cb(mac_handle); diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c index b4ab85c38e94..184a15a2cfe1 100644 --- a/core/hdd/src/wlan_hdd_oemdata.c +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -1126,6 +1126,44 @@ oem_data_attr_policy[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1] = { }, }; +void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data) +{ + struct sk_buff *vendor_event; + uint32_t len; + int ret; + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + hdd_enter(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return; + + len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN; + vendor_event = + cfg80211_vendor_event_alloc( + hdd_ctx->wiphy, NULL, len, + QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + hdd_err("cfg80211_vendor_event_alloc failed"); + return; + } + + ret = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA, + oem_event_data->data_len, oem_event_data->data); + if (ret) { + hdd_err("OEM event put fails status %d", ret); + kfree_skb(vendor_event); + return; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + hdd_exit(); +} + /** * __wlan_hdd_cfg80211_oem_data_handler() - the handler for oem data * @wiphy: wiphy structure pointer diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 61d0cc369a10..adec3a0c4fc7 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3988,4 +3988,42 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs, struct wmi_host_ani_level_event *ani, uint8_t num, void *context), void *context); #endif /* FEATURE_ANI_LEVEL_REQUEST */ + +#ifdef FEATURE_OEM_DATA +/** + * sme_set_oem_data_event_handler_cb() - Register oem data event handler + * callback + * @mac_handle: Opaque handle to the MAC context + * @oem_data_event_handler_cb: callback to be registered + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_set_oem_data_event_handler_cb( + mac_handle_t mac_handle, + void (*oem_data_event_handler_cb) + (const struct oem_data *oem_event_data)); + +/** + * sme_reset_oem_data_event_handler_cb() - De-register oem data event handler + * @mac_handle: Handler return by mac_open + * + * This function De-registers the OEM data event handler callback to SME + * + * Return: None + */ +void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle); +#else +static inline QDF_STATUS sme_set_oem_data_event_handler_cb( + mac_handle_t mac_handle, + void (*oem_data_event_handler_cb) + (void *oem_event_data)) +{ + return QDF_STATUS_SUCCESS; +} + +static inline void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle) +{ +} +#endif + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 29cc50851822..cf14a882f30e 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -37,6 +37,7 @@ #include "csr_link_list.h" #include "sme_power_save.h" #include "wmi_unified.h" +#include "wmi_unified_param.h" struct wmi_twt_enable_complete_event_param; /*-------------------------------------------------------------------------- @@ -387,6 +388,10 @@ struct sme_context { beacon_report_cb beacon_report_cb; beacon_pause_cb beacon_pause_cb; #endif +#ifdef FEATURE_OEM_DATA + void (*oem_data_event_handler_cb) + (const struct oem_data *oem_event_data); +#endif }; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 74f8bc4b0b84..e6994358116a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -16268,3 +16268,39 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs, return status; } #endif /* FEATURE_ANI_LEVEL_REQUEST */ + +#ifdef FEATURE_OEM_DATA +QDF_STATUS sme_set_oem_data_event_handler_cb( + mac_handle_t mac_handle, + void (*oem_data_event_handler_cb) + (const struct oem_data *oem_event_data)) +{ + struct mac_context *mac = MAC_CONTEXT(mac_handle); + QDF_STATUS qdf_status; + + qdf_status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + mac->sme.oem_data_event_handler_cb = oem_data_event_handler_cb; + sme_release_global_lock(&mac->sme); + } + return qdf_status; +} + +void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle) +{ + struct mac_context *pmac; + QDF_STATUS qdf_status; + + if (!mac_handle) { + sme_err("mac_handle is not valid"); + return; + } + pmac = MAC_CONTEXT(mac_handle); + + qdf_status = sme_acquire_global_lock(&pmac->sme); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + pmac->sme.oem_data_event_handler_cb = NULL; + sme_release_global_lock(&pmac->sme); + } +} +#endif diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 1171abacb94e..ce147ccbb5c9 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1902,6 +1902,18 @@ void wma_send_vdev_down(tp_wma_handle wma, struct del_bss_resp *req); int wma_cold_boot_cal_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len); +#ifdef FEATURE_OEM_DATA +/** + * wma_oem_event_handler() - oem data event handler + * @wma_ctx: wma handle + * @event_buff: event data + * @len: length of event buffer + * + * Return: Success or Failure status + */ +int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len); +#endif + /** * wma_set_roam_triggers() - Send roam trigger bitmap to WMI * @wma_handle: wma handle diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 3107322ea6d5..56402eb74f34 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3179,6 +3179,13 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wma_cold_boot_cal_event_handler, WMA_RX_WORK_CTX); +#ifdef FEATURE_OEM_DATA + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_oem_data_event_id, + wma_oem_event_handler, + WMA_RX_WORK_CTX); +#endif + #ifdef WLAN_FEATURE_LINK_LAYER_STATS /* Register event handler for processing Link Layer Stats * response from the FW diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 76e9b573f05b..a2490e6f7639 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -4713,3 +4713,50 @@ int wma_cold_boot_cal_event_handler(void *wma_ctx, uint8_t *event_buff, return 0; } + +#ifdef FEATURE_OEM_DATA +int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len) +{ + WMI_OEM_DATA_EVENTID_param_tlvs *param_buf; + struct mac_context *pmac = + (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); + wmi_oem_data_event_fixed_param *event; + struct oem_data oem_event_data; + + if (!pmac) { + wma_err("NULL mac handle"); + return -EINVAL; + } + + if (!pmac->sme.oem_data_event_handler_cb) { + wma_err("oem data handler cb is not registered"); + return -EINVAL; + } + + param_buf = + (WMI_OEM_DATA_EVENTID_param_tlvs *)event_buff; + if (!param_buf) { + wma_err("Invalid oem data Event"); + return -EINVAL; + } + + event = param_buf->fixed_param; + if (!event) { + wma_err("Invalid fixed param in oem data Event"); + return -EINVAL; + } + + if (event->data_len > param_buf->num_data) { + wma_err("Invalid data len %d num_data %d", event->data_len, + param_buf->num_data); + return -EINVAL; + } + + oem_event_data.data_len = event->data_len; + oem_event_data.data = param_buf->data; + + pmac->sme.oem_data_event_handler_cb(&oem_event_data); + + return QDF_STATUS_SUCCESS; +} +#endif