diff --git a/components/nan/core/inc/nan_public_structs.h b/components/nan/core/inc/nan_public_structs.h index 2af9af935fd3..66885c782b0e 100644 --- a/components/nan/core/inc/nan_public_structs.h +++ b/components/nan/core/inc/nan_public_structs.h @@ -42,6 +42,18 @@ struct wlan_objmgr_vdev; #define NAN_PASSPHRASE_MAX_LEN 63 #define NAN_CH_INFO_MAX_CHANNELS 4 +/** + * enum nan_discovery_msg_type - NAN msg type + * @NAN_GENERIC_REQ: Type for all the NAN requests other than enable/disable + * @NAN_ENABLE_REQ: Request type for enabling the NAN Discovery + * @NAN_DISABLE_REQ: Request type for disabling the NAN Discovery + */ +enum nan_discovery_msg_type { + NAN_GENERIC_REQ = 0, + NAN_ENABLE_REQ = 1, + NAN_DISABLE_REQ = 2, +}; + /** * enum nan_datapath_msg_type - NDP msg type * @NAN_DATAPATH_INF_CREATE_REQ: ndi create request @@ -460,6 +472,58 @@ struct nan_datapath_end_req { uint32_t ndp_ids[NDP_NUM_INSTANCE_ID]; }; +/** + * struct nan_msg_params - NAN request params + * @request_data_len: request data length + * @request_data: request data + */ +struct nan_msg_params { + uint16_t request_data_len; + /* Variable length, do not add anything after this */ + uint8_t request_data[]; +}; + +/** + * struct nan_generic_req - A NAN request for the Target + * @psoc: Pointer to the psoc object + * @params: NAN request structure containing message fr the Target + */ +struct nan_generic_req { + struct wlan_objmgr_psoc *psoc; + /* Variable length, do not add anything after this */ + struct nan_msg_params params; +}; + +/** + * struct nan_disable_req - NAN request to disable NAN Discovery + * @psoc: Pointer to the psoc object + * @disable_2g_discovery: Flag for disabling Discovery in 2G band + * @disable_5g_discovery: Flag for disabling Discovery in 5G band + * @params: NAN request structure containing message for the target + */ +struct nan_disable_req { + struct wlan_objmgr_psoc *psoc; + bool disable_2g_discovery; + bool disable_5g_discovery; + /* Variable length, do not add anything after this */ + struct nan_msg_params params; +}; + +/** + * struct nan_enable_req - NAN request to enable NAN Discovery + * @psoc: Pointer to the psoc object + * @social_chan_2g: Social channel in 2G band for the NAN Discovery + * @social_chan_5g: Social channel in 5G band for the NAN Discovery + * @params: NAN request structure containing message for the target + */ +struct nan_enable_req { + struct wlan_objmgr_psoc *psoc; + uint8_t social_chan_2g; + uint8_t social_chan_5g; + /* Variable length, do not add anything after this */ + struct nan_msg_params params; +}; + /** * struct nan_datapath_end_rsp_event - firmware response to ndp end request * @vdev: pointer to vdev object diff --git a/components/nan/dispatcher/inc/nan_ucfg_api.h b/components/nan/dispatcher/inc/nan_ucfg_api.h index 4462eca50f5f..bdf605c9b5ce 100644 --- a/components/nan/dispatcher/inc/nan_ucfg_api.h +++ b/components/nan/dispatcher/inc/nan_ucfg_api.h @@ -23,15 +23,8 @@ #ifndef _NAN_UCFG_API_H_ #define _NAN_UCFG_API_H_ -#include "qdf_types.h" -#include "qdf_status.h" #include "wlan_objmgr_cmn.h" - -struct nan_callbacks; -struct wlan_objmgr_vdev; -struct wlan_objmgr_psoc; -struct wlan_objmgr_vdev; -struct nan_callbacks; +#include "nan_public_structs.h" /** * ucfg_nan_set_ndi_state: set ndi state @@ -235,5 +228,40 @@ int ucfg_nan_register_lim_callbacks(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, struct nan_callbacks *cb_obj); -#endif /* _NAN_UCFG_API_H_ */ +/** + * ucfg_nan_discovery_req: ucfg API for NAN Discovery related requests + * @in_req: NAN request + * @req_type: Request type + * + * Return: status of operation + */ +static inline QDF_STATUS ucfg_nan_discovery_req(void *in_req, uint32_t req_type) +{ + return QDF_STATUS_SUCCESS; +} +/** + * ucfg_is_nan_dbs_supported() - ucfg API to query NAN DBS support + * @psoc: pointer to psoc object + * + * This function returns NAN DBS support status + * + * Return: True if NAN DBS is supported, False otherwise + */ +static inline bool ucfg_is_nan_dbs_supported(struct wlan_objmgr_psoc *psoc) +{ + return true; +} + +/** + * ucfg_is_nan_enable_allowed() - ucfg API to query if NAN Discovery is + * allowed + * @psoc: pointer to psoc object + * + * Return: True if NAN Discovery enable is allowed, False otherwise + */ +static inline bool ucfg_is_nan_enable_allowed(struct wlan_objmgr_psoc *psoc) +{ + return true; +} +#endif /* _NAN_UCFG_API_H_ */ diff --git a/core/hdd/inc/wlan_hdd_nan.h b/core/hdd/inc/wlan_hdd_nan.h index 57ec6b2604fc..0f6ef923eb37 100644 --- a/core/hdd/inc/wlan_hdd_nan.h +++ b/core/hdd/inc/wlan_hdd_nan.h @@ -31,6 +31,18 @@ struct hdd_context; struct wiphy; struct wireless_dev; +/** + * wlan_hdd_cfg80211_nan_request() - handle NAN request + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to send a NAN request to + * firmware. This is an SSR-protected wrapper function. + * + * Return: 0 on success, negative errno on failure + */ int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, @@ -51,7 +63,68 @@ bool wlan_hdd_nan_is_supported(struct hdd_context *hdd_ctx); * Return: nothing */ void wlan_hdd_cfg80211_nan_callback(hdd_handle_t hdd_handle, tSirNanEvent *msg); -#else + +/** + * wlan_hdd_cfg80211_nan_ext_request() - handle NAN Extended request + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * This function is called by userspace to send a NAN request to + * firmware. This is an SSR-protected wrapper function. + * + * Return: 0 on success, negative errno on failure + */ +int wlan_hdd_cfg80211_nan_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +#define FEATURE_NAN_VENDOR_COMMANDS \ + { \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_nan_request \ + }, \ + { \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_nan_ext_request \ + }, \ + { \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_process_ndp_cmd \ + }, +#else /* WLAN_FEATURE_NAN */ +#define FEATURE_NAN_VENDOR_COMMANDS + +static inline int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + return 0; +} + +static inline int wlan_hdd_cfg80211_nan_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + return 0; +} + static inline bool wlan_hdd_nan_is_supported(struct hdd_context *hdd_ctx) { return false; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e1e186ce4b80..8451542e55a9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1189,14 +1189,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY }, -#ifdef WLAN_FEATURE_NAN [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN }, -#endif #ifdef WLAN_FEATURE_STATS_EXT [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = { @@ -1452,12 +1450,10 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = }, #endif /*FEATURE_LFR_SUBNET_DETECTION */ -#ifdef WLAN_FEATURE_NAN_DATAPATH [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP }, -#endif /* WLAN_FEATURE_NAN_DATAPATH */ [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, @@ -1491,6 +1487,10 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT, }, + [QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT + }, #ifdef WLAN_UMAC_CONVERGENCE COMMON_VENDOR_EVENTS #endif @@ -11421,16 +11421,6 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { .doit = is_driver_dfs_capable }, -#ifdef WLAN_FEATURE_NAN - { - .info.vendor_id = QCA_NL80211_VENDOR_ID, - .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | - WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, - .doit = wlan_hdd_cfg80211_nan_request - }, -#endif - #ifdef WLAN_FEATURE_STATS_EXT { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -11920,16 +11910,6 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS -#ifdef WLAN_FEATURE_NAN_DATAPATH - { - .info.vendor_id = QCA_NL80211_VENDOR_ID, - .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP, - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | - WIPHY_VENDOR_CMD_NEED_NETDEV | - WIPHY_VENDOR_CMD_NEED_RUNNING, - .doit = wlan_hdd_cfg80211_process_ndp_cmd - }, -#endif { .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS, @@ -12052,7 +12032,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { }, FEATURE_ACTIVE_TOS_VENDOR_COMMANDS - + FEATURE_NAN_VENDOR_COMMANDS }; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) diff --git a/core/hdd/src/wlan_hdd_nan.c b/core/hdd/src/wlan_hdd_nan.c index 0d675af5309b..79e84cd17d87 100644 --- a/core/hdd/src/wlan_hdd_nan.c +++ b/core/hdd/src/wlan_hdd_nan.c @@ -34,6 +34,22 @@ #include #include #include "cfg_nan_api.h" +#include "os_if_nan.h" + +/** + * wlan_hdd_nan_is_supported() - HDD NAN support query function + * @hdd_ctx: Pointer to hdd context + * + * This function is called to determine if NAN is supported by the + * driver and by the firmware. + * + * Return: true if NAN is supported by the driver and firmware + */ +bool wlan_hdd_nan_is_supported(struct hdd_context *hdd_ctx) +{ + return cfg_nan_get_enable(hdd_ctx->psoc) && + sme_is_feature_supported_by_fw(NAN); +} /** * __wlan_hdd_cfg80211_nan_request() - cfg80211 NAN request handler @@ -85,18 +101,6 @@ static int __wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, return ret_val; } -/** - * wlan_hdd_cfg80211_nan_request() - handle NAN request - * @wiphy: pointer to wireless wiphy structure. - * @wdev: pointer to wireless_dev structure. - * @data: Pointer to the data to be passed via vendor interface - * @data_len:Length of the data to be passed - * - * This function is called by userspace to send a NAN request to - * firmware. This is an SSR-protected wrapper function. - * - * Return: 0 on success, negative errno on failure - */ int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, @@ -156,16 +160,56 @@ void wlan_hdd_cfg80211_nan_callback(hdd_handle_t hdd_handle, tSirNanEvent *msg) } /** - * wlan_hdd_nan_is_supported() - HDD NAN support query function - * @hdd_ctx: Pointer to hdd context + * __wlan_hdd_cfg80211_nan_ext_request() - cfg80211 NAN extended request handler + * @wiphy: driver's wiphy struct + * @wdev: wireless device to which the request is targeted + * @data: actual request data (netlink-encapsulated) + * @data_len: length of @data * - * This function is called to determine if NAN is supported by the - * driver and by the firmware. + * Handles NAN Extended vendor commands, sends the command to NAN component + * which parses and forwards the NAN requests. * - * Return: true if NAN is supported by the driver and firmware + * Return: 0 on success, negative errno on failure */ -bool wlan_hdd_nan_is_supported(struct hdd_context *hdd_ctx) +static int __wlan_hdd_cfg80211_nan_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) { - return cfg_nan_get_enable(hdd_ctx->psoc) && - sme_is_feature_supported_by_fw(NAN); + int ret_val; + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + + hdd_enter_dev(wdev->netdev); + + ret_val = wlan_hdd_validate_context(hdd_ctx); + if (ret_val) + return ret_val; + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_err_rl("Command not allowed in FTM mode"); + return -EPERM; + } + + if (!wlan_hdd_nan_is_supported(hdd_ctx)) { + hdd_err_rl("NAN is not supported"); + return -EPERM; + } + + return os_if_process_nan_req(hdd_ctx->psoc, + data, data_len); +} + +int wlan_hdd_cfg80211_nan_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) + +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_nan_ext_request(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; } diff --git a/os_if/nan/inc/os_if_nan.h b/os_if/nan/inc/os_if_nan.h index 338ea7462d45..e8f8cd172da3 100644 --- a/os_if/nan/inc/os_if_nan.h +++ b/os_if/nan/inc/os_if_nan.h @@ -24,14 +24,10 @@ #define _OS_IF_NAN_H_ #include "qdf_types.h" +#ifdef WLAN_FEATURE_NAN_CONVERGENCE #include "nan_public_structs.h" #include "nan_ucfg_api.h" -struct wlan_objmgr_psoc; -struct wlan_objmgr_vdev; - -#ifdef WLAN_FEATURE_NAN_CONVERGENCE - /** * os_if_nan_process_ndp_cmd: os_if api to handle nan request message * @psoc: pointer to psoc object @@ -150,6 +146,16 @@ static inline QDF_STATUS os_if_nan_set_ndp_delete_transaction_id( return ucfg_nan_set_ndp_delete_transaction_id(vdev, val); } +/** + * os_if_process_nan_req: os_if api to handle nan request message + * @psoc: pointer to psoc object + * @data: request data. contains vendor cmd tlvs + * @data_len: length of data + * + * Return: status of operation + */ +int os_if_process_nan_req(struct wlan_objmgr_psoc *psoc, + const void *data, int data_len); #else static inline void os_if_nan_post_ndi_create_rsp(struct wlan_objmgr_psoc *psoc, diff --git a/os_if/nan/src/os_if_nan.c b/os_if/nan/src/os_if_nan.c index 6f98e93dd2b2..cc293ccb43a8 100644 --- a/os_if/nan/src/os_if_nan.c +++ b/os_if/nan/src/os_if_nan.c @@ -26,7 +26,6 @@ #include "os_if_nan.h" #include "wlan_nan_api.h" #include "nan_ucfg_api.h" -#include "nan_public_structs.h" #include "wlan_osif_priv.h" #include #include "wlan_cfg80211.h" @@ -35,6 +34,30 @@ #include "wlan_objmgr_vdev_obj.h" #include "wlan_objmgr_peer_obj.h" #include "wlan_utility.h" +#include "wlan_osif_request_manager.h" + +#define NAN_CMD_MAX_SIZE 300 + +/* NLA policy */ +static const struct nla_policy +nan_attr_policy[QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA] = { + .type = NLA_BINARY, + .len = NAN_CMD_MAX_SIZE + }, + [QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE] = { + .type = NLA_U32, + .len = sizeof(uint32_t) + }, + [QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ] = { + .type = NLA_U32, + .len = sizeof(uint32_t) + }, + [QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ] = { + .type = NLA_U32, + .len = sizeof(uint32_t) + }, +}; /* NLA policy */ static const struct nla_policy @@ -2168,3 +2191,156 @@ void os_if_nan_ndi_session_end(struct wlan_objmgr_vdev *vdev) failure: kfree_skb(vendor_event); } + +static int os_if_nan_generic_req(struct wlan_objmgr_psoc *psoc, + struct nlattr **tb) +{ + struct nan_generic_req *nan_req; + uint32_t buf_len; + QDF_STATUS status; + + buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]); + + nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len); + if (!nan_req) { + cfg80211_err("Request allocation failure"); + return -ENOMEM; + } + + nan_req->psoc = psoc; + nan_req->params.request_data_len = buf_len; + nla_memcpy(nan_req->params.request_data, + tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len); + + cfg80211_debug("sending NAN Req"); + status = ucfg_nan_discovery_req(nan_req, NAN_GENERIC_REQ); + + if (QDF_IS_STATUS_SUCCESS(status)) + cfg80211_err("Successfully sent a NAN request"); + else + cfg80211_err("Unable to send a NAN request"); + + qdf_mem_free(nan_req); + return qdf_status_to_os_return(status); +} + +static int os_if_process_nan_disable_req(struct wlan_objmgr_psoc *psoc, + struct nlattr **tb) +{ + struct nan_disable_req *nan_req; + uint32_t buf_len; + QDF_STATUS status; + + buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]); + + nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len); + if (!nan_req) { + cfg80211_err("Request allocation failure"); + return -ENOMEM; + } + + nan_req->psoc = psoc; + nan_req->params.request_data_len = buf_len; + nla_memcpy(nan_req->params.request_data, + tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len); + + cfg80211_debug("sending NAN Disable Req"); + status = ucfg_nan_discovery_req(nan_req, NAN_DISABLE_REQ); + + if (QDF_IS_STATUS_SUCCESS(status)) + cfg80211_err("Successfully sent NAN Disable request"); + else + cfg80211_err("Unable to disable NAN Discovery"); + + qdf_mem_free(nan_req); + return qdf_status_to_os_return(status); +} + +static int os_if_process_nan_enable_req(struct wlan_objmgr_psoc *psoc, + struct nlattr **tb) +{ + uint32_t chan_freq_2g, chan_freq_5g = 0; + uint32_t buf_len; + QDF_STATUS status; + struct nan_enable_req *nan_req; + + if (!ucfg_is_nan_enable_allowed(psoc)) { + cfg80211_err("NAN Enable not allowed at this moment"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ]) { + cfg80211_err("NAN Social channel for 2.4Gz is unavailable!"); + return -EINVAL; + } + chan_freq_2g = + nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ]); + + if (tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ]) + chan_freq_5g = + nla_get_u32(tb[ + QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ]); + + buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]); + + nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len); + + if (!nan_req) { + cfg80211_err("Request allocation failure"); + return -ENOMEM; + } + nan_req->social_chan_2g = wlan_freq_to_chan(chan_freq_2g); + nan_req->social_chan_5g = wlan_freq_to_chan(chan_freq_5g); + nan_req->psoc = psoc; + nan_req->params.request_data_len = buf_len; + + nla_memcpy(nan_req->params.request_data, + tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len); + + cfg80211_debug("Sending NAN Enable Req"); + status = ucfg_nan_discovery_req(nan_req, NAN_ENABLE_REQ); + + if (QDF_IS_STATUS_SUCCESS(status)) + cfg80211_err("Successfully sent NAN Enable"); + else + cfg80211_err("Unable to enable NAN Discovery"); + + qdf_mem_free(nan_req); + return qdf_status_to_os_return(status); +} + +int os_if_process_nan_req(struct wlan_objmgr_psoc *psoc, + const void *data, int data_len) +{ + uint32_t nan_subcmd; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX + 1]; + + if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX, + data, data_len, nan_attr_policy)) { + cfg80211_err("Invalid NAN vendor command attributes"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]) { + cfg80211_err("NAN cmd data missing!"); + return -EINVAL; + } + + if (!ucfg_is_nan_dbs_supported(psoc)) + return os_if_nan_generic_req(psoc, tb); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE]) + return os_if_nan_generic_req(psoc, tb); + + nan_subcmd = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE]); + + switch (nan_subcmd) { + case QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ: + return os_if_process_nan_enable_req(psoc, tb); + case QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ: + return os_if_process_nan_disable_req(psoc, tb); + default: + cfg80211_err("Unrecognized NAN subcmd type(%d)", nan_subcmd); + return -EINVAL; + } +}