Explorar o código

qcacmn: Add support for NLA type CAP_RESP in LOWI

Host driver processes cld80211 vendor sub command
CLD80211_VENDOR_SUB_CMD_GET_CAPS and respond with
NLA type CAP response

CRs-Fixed: 2595140
Change-Id: I5a6aa1fac537ca618404520b81c541a20dafd6fb
Vinay Gannevaram %!s(int64=5) %!d(string=hai) anos
pai
achega
23a3603951

+ 70 - 1
os_if/linux/wifi_pos/inc/os_if_wifi_pos.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, 2020 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
@@ -105,4 +105,73 @@ static inline int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
 }
 #endif
 
+#ifdef CNSS_GENL
+/**
+ * enum cld80211_vendor_sub_cmds
+ * @CLD80211_VENDOR_SUB_CMD_INVALID: invalid cmd type
+ * @CLD80211_VENDOR_SUB_CMD_REGISTRATION: app registration
+ * @CLD80211_VENDOR_SUB_CMD_SET_CAPS: set driver capabilities
+ * @CLD80211_VENDOR_SUB_CMD_GET_CAPS: get driver capabilities
+ * @CLD80211_VENDOR_SUB_CMD_GET_CH_INFO: get channel info
+ * @CLD80211_VENDOR_SUB_CMD_OEM_DATA: oem data req/rsp
+ * @CLD80211_VENDOR_SUB_CMD_OEM_ERROR: oem error rsp
+ * @CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND: peer status indication
+ * @CLD80211_VENDOR_SUB_CMD_MAX: Max cld80211 vendor sub cmds
+ */
+enum cld80211_vendor_sub_cmds {
+	CLD80211_VENDOR_SUB_CMD_INVALID = 0,
+	CLD80211_VENDOR_SUB_CMD_REGISTRATION = 1,
+	CLD80211_VENDOR_SUB_CMD_SET_CAPS = 2,
+	CLD80211_VENDOR_SUB_CMD_GET_CAPS = 3,
+	CLD80211_VENDOR_SUB_CMD_GET_CH_INFO = 4,
+	CLD80211_VENDOR_SUB_CMD_OEM_DATA = 5,
+	CLD80211_VENDOR_SUB_CMD_OEM_ERROR = 6,
+	CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND = 7,
+	/* keep last */
+	CLD80211_VENDOR_SUB_CMD__AFTER_LAST,
+	CLD80211_VENDOR_SUB_CMD_MAX =
+		CLD80211_VENDOR_SUB_CMD__AFTER_LAST - 1
+};
+
+/**
+ * enum cld80211_sub_attr_cap_rsp - Capability response sub attribute
+ * @CLD80211_SUB_ATTR_CAPS_INVALID: Invalid capability
+ * @CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE: OEM target signature
+ * @CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE: OEM target type
+ * @CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION: OEM firmware version
+ * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR: Driver version major
+ * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR: Driver version minor
+ * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH: Driver version patch
+ * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD: Driver version build
+ * @CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN: Allowed dwell time min
+ * @CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX: Allowed dwell time max
+ * @CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN: Current dwell time min
+ * @CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX: Current dwell time max
+ * @CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS: Supported bands
+ * @CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS: User defined capabilities
+ * @CLD80211_SUB_ATTR_CAPS_MAX: Max number for CAP sub attribute
+ *
+ */
+enum cld80211_sub_attr_cap_rsp {
+	CLD80211_SUB_ATTR_CAPS_INVALID = 0,
+	CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE = 1,
+	CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE = 2,
+	CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION = 3,
+	CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR = 4,
+	CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR = 5,
+	CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH = 6,
+	CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD = 7,
+	CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN = 8,
+	CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX = 9,
+	CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN = 10,
+	CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX = 11,
+	CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS = 12,
+	CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS = 13,
+
+	/* keep last */
+	CLD80211_SUB_ATTR_CAPS_AFTER_LAST,
+	CLD80211_SUB_ATTR_CAPS_MAX =
+		CLD80211_SUB_ATTR_CAPS_AFTER_LAST - 1
+};
+#endif
 #endif /* _OS_IF_WIFI_POS_H_ */

+ 294 - 36
os_if/linux/wifi_pos/src/os_if_wifi_pos.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 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
@@ -33,6 +33,206 @@
 #include "wlan_objmgr_psoc_obj.h"
 #ifdef CNSS_GENL
 #include <net/cnss_nl.h>
+#include "linux/genetlink.h"
+#include "wifi_pos_utils_pub.h"
+#endif
+
+#ifdef CNSS_GENL
+#define WLAN_CLD80211_MAX_SIZE SKB_WITH_OVERHEAD(8192UL)
+
+#define CLD80211_ATTR_CMD 4
+#define CLD80211_ATTR_CMD_TAG_DATA 5
+#define CLD80211_ATTR_MAX 5
+
+static const uint32_t
+cap_resp_sub_attr_len[CLD80211_SUB_ATTR_CAPS_MAX + 1] = {
+	[CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE] =
+				OEM_TARGET_SIGNATURE_LEN,
+	[CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE] = sizeof(uint32_t),
+	[CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION] = sizeof(uint32_t),
+	[CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR] = sizeof(uint8_t),
+	[CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR] = sizeof(uint8_t),
+	[CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH] = sizeof(uint8_t),
+	[CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD] = sizeof(uint8_t),
+	[CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN] = sizeof(uint16_t),
+	[CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX] = sizeof(uint16_t),
+	[CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN] = sizeof(uint16_t),
+	[CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX] = sizeof(uint16_t),
+	[CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS] = sizeof(uint16_t),
+	[CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS] =
+				sizeof(struct wifi_pos_user_defined_caps),
+};
+#endif
+
+static int map_wifi_pos_cmd_to_ani_msg_rsp(
+		enum wifi_pos_cmd_ids cmd)
+{
+	switch (cmd) {
+	case WIFI_POS_CMD_REGISTRATION:
+		return ANI_MSG_APP_REG_RSP;
+	case WIFI_POS_CMD_SET_CAPS:
+		return ANI_MSG_SET_OEM_CAP_RSP;
+	case WIFI_POS_CMD_GET_CAPS:
+		return ANI_MSG_GET_OEM_CAP_RSP;
+	case WIFI_POS_CMD_GET_CH_INFO:
+		return ANI_MSG_CHANNEL_INFO_RSP;
+	case WIFI_POS_CMD_OEM_DATA:
+		return ANI_MSG_OEM_DATA_RSP;
+	case WIFI_POS_CMD_ERROR:
+		return ANI_MSG_OEM_ERROR;
+	case WIFI_POS_PEER_STATUS_IND:
+		return ANI_MSG_PEER_STATUS_IND;
+	default:
+		osif_err("response message is invalid :%d", cmd);
+		return -EINVAL;
+	}
+}
+
+static enum wifi_pos_cmd_ids
+map_ani_msg_req_to_wifi_pos_cmd(uint32_t cmd)
+{
+	switch (cmd) {
+	case ANI_MSG_APP_REG_REQ:
+		return WIFI_POS_CMD_REGISTRATION;
+	case ANI_MSG_SET_OEM_CAP_REQ:
+		return WIFI_POS_CMD_SET_CAPS;
+	case ANI_MSG_GET_OEM_CAP_REQ:
+		return WIFI_POS_CMD_GET_CAPS;
+	case ANI_MSG_CHANNEL_INFO_REQ:
+		return WIFI_POS_CMD_GET_CH_INFO;
+	case ANI_MSG_OEM_DATA_REQ:
+		return WIFI_POS_CMD_OEM_DATA;
+	default:
+		osif_err("ani req is invalid :%d", cmd);
+		return WIFI_POS_CMD_INVALID;
+	}
+}
+
+#ifdef CNSS_GENL
+static enum wifi_pos_cmd_ids
+map_cld_vendor_sub_cmd_to_wifi_pos_cmd(
+		enum cld80211_vendor_sub_cmds cmd)
+{
+	switch (cmd) {
+	case CLD80211_VENDOR_SUB_CMD_REGISTRATION:
+		return WIFI_POS_CMD_REGISTRATION;
+	case CLD80211_VENDOR_SUB_CMD_SET_CAPS:
+		return WIFI_POS_CMD_SET_CAPS;
+	case CLD80211_VENDOR_SUB_CMD_GET_CAPS:
+		return WIFI_POS_CMD_GET_CAPS;
+	case CLD80211_VENDOR_SUB_CMD_GET_CH_INFO:
+		return WIFI_POS_CMD_GET_CH_INFO;
+	case CLD80211_VENDOR_SUB_CMD_OEM_DATA:
+		return WIFI_POS_CMD_OEM_DATA;
+	default:
+		osif_err("cld vendor subcmd is invalid :%d", cmd);
+		return WIFI_POS_CMD_INVALID;
+	}
+}
+
+static enum cld80211_vendor_sub_cmds
+map_wifi_pos_cmd_to_cld_vendor_sub_cmd(
+		enum wifi_pos_cmd_ids cmd)
+{
+	switch (cmd) {
+	case WIFI_POS_CMD_REGISTRATION:
+		return CLD80211_VENDOR_SUB_CMD_REGISTRATION;
+	case WIFI_POS_CMD_SET_CAPS:
+		return CLD80211_VENDOR_SUB_CMD_SET_CAPS;
+	case WIFI_POS_CMD_GET_CAPS:
+		return CLD80211_VENDOR_SUB_CMD_GET_CAPS;
+	case WIFI_POS_CMD_GET_CH_INFO:
+		return CLD80211_VENDOR_SUB_CMD_GET_CH_INFO;
+	case WIFI_POS_CMD_OEM_DATA:
+		return CLD80211_VENDOR_SUB_CMD_OEM_DATA;
+	case WIFI_POS_CMD_ERROR:
+		return ANI_MSG_OEM_ERROR;
+	case WIFI_POS_PEER_STATUS_IND:
+		return ANI_MSG_PEER_STATUS_IND;
+	default:
+		osif_err("response message is invalid :%d", cmd);
+		return CLD80211_VENDOR_SUB_CMD_INVALID;
+	}
+}
+
+static void os_if_send_cap_nl_resp(uint32_t pid, uint8_t *buf)
+{
+	void *hdr;
+	int flags = GFP_KERNEL;
+	struct sk_buff *msg = NULL;
+	struct nlattr *nest1, *nest2;
+	struct wifi_pos_oem_get_cap_rsp *cap_rsp;
+
+	msg = cld80211_oem_rsp_alloc_skb(pid, &hdr, &nest1, &flags);
+	if (!msg) {
+		osif_err("alloc_skb failed");
+		return;
+	}
+
+	nla_put_u32(msg, CLD80211_ATTR_CMD,
+	map_wifi_pos_cmd_to_cld_vendor_sub_cmd(WIFI_POS_CMD_GET_CAPS));
+
+	cap_rsp = (struct wifi_pos_oem_get_cap_rsp *)(buf);
+	nest2 = nla_nest_start(msg, CLD80211_ATTR_CMD_TAG_DATA);
+
+	if (!nest2) {
+		osif_err("nla_nest_start failed");
+		dev_kfree_skb(msg);
+		return;
+	}
+
+	nla_put(msg, CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE,
+		OEM_TARGET_SIGNATURE_LEN, OEM_TARGET_SIGNATURE);
+	nla_put_u32(msg, CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE,
+		    cap_rsp->driver_cap.oem_target_type);
+	nla_put_u32(msg, CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION,
+		    cap_rsp->driver_cap.oem_fw_version);
+	nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR,
+		   cap_rsp->driver_cap.driver_version.major);
+	nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR,
+		   cap_rsp->driver_cap.driver_version.minor);
+	nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH,
+		   cap_rsp->driver_cap.driver_version.patch);
+	nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD,
+		   cap_rsp->driver_cap.driver_version.build);
+	nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN,
+		    cap_rsp->driver_cap.allowed_dwell_time_min);
+	nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX,
+		    cap_rsp->driver_cap.allowed_dwell_time_max);
+	nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN,
+		    cap_rsp->driver_cap.curr_dwell_time_min);
+	nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX,
+		    cap_rsp->driver_cap.curr_dwell_time_max);
+	nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS,
+		    cap_rsp->driver_cap.supported_bands);
+	nla_put(msg, CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS,
+		sizeof(struct wifi_pos_user_defined_caps),
+		&cap_rsp->user_defined_cap);
+	nla_nest_end(msg, nest2);
+
+	osif_debug("sending oem rsp: type: %d to pid (%d)",
+		    CLD80211_VENDOR_SUB_CMD_GET_CAPS, pid);
+
+	cld80211_oem_send_reply(msg, hdr, nest1, flags);
+}
+
+
+static void os_if_send_nl_resp(uint32_t pid, uint8_t *buf,
+			       enum wifi_pos_cmd_ids cmd)
+{
+	switch (cmd) {
+	case WIFI_POS_CMD_GET_CAPS:
+		os_if_send_cap_nl_resp(pid, buf);
+		break;
+	default:
+		osif_err("response message is invalid :%d", cmd);
+	}
+}
+#else
+static void os_if_send_nl_resp(uint32_t pid, uint8_t *buf,
+			       enum wifi_pos_cmd_ids cmd)
+{
+}
 #endif
 
 /**
@@ -42,12 +242,13 @@
  *
  * Return:  none
  */
-static void os_if_wifi_pos_send_rsp(uint32_t pid, uint32_t rsp_msg_type,
+static void os_if_wifi_pos_send_rsp(uint32_t pid, enum wifi_pos_cmd_ids cmd,
 				    uint32_t buf_len, uint8_t *buf)
 {
 	tAniMsgHdr *aniHdr;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct nlmsghdr *nlh;
+	struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
 
 	/* OEM msg is always to a specific process and cannot be a broadcast */
 	if (pid == 0) {
@@ -55,46 +256,76 @@ static void os_if_wifi_pos_send_rsp(uint32_t pid, uint32_t rsp_msg_type,
 		return;
 	}
 
-	skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len), GFP_ATOMIC);
-	if (!skb) {
-		osif_alert("alloc_skb failed");
-		return;
+	if (ucfg_wifi_pos_is_nl_rsp(psoc)) {
+		os_if_send_nl_resp(pid, buf, cmd);
+	} else {
+		skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len),
+				GFP_ATOMIC);
+		if (!skb) {
+			osif_alert("alloc_skb failed");
+			return;
+		}
+
+		nlh = (struct nlmsghdr *)skb->data;
+		nlh->nlmsg_pid = 0;     /* from kernel */
+		nlh->nlmsg_flags = 0;
+		nlh->nlmsg_seq = 0;
+		nlh->nlmsg_type = WLAN_NL_MSG_OEM;
+		nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + buf_len);
+
+		aniHdr = NLMSG_DATA(nlh);
+		aniHdr->type = map_wifi_pos_cmd_to_ani_msg_rsp(cmd);
+		qdf_mem_copy(&aniHdr[1], buf, buf_len);
+		aniHdr->length = buf_len;
+
+		skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len));
+		osif_debug("sending oem rsp: type: %d len(%d) to pid (%d)",
+			   aniHdr->type, buf_len, pid);
+		nl_srv_ucast_oem(skb, pid, MSG_DONTWAIT);
 	}
-
-	nlh = (struct nlmsghdr *)skb->data;
-	nlh->nlmsg_pid = 0;     /* from kernel */
-	nlh->nlmsg_flags = 0;
-	nlh->nlmsg_seq = 0;
-	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
-	nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + buf_len);
-
-	aniHdr = NLMSG_DATA(nlh);
-	aniHdr->type = rsp_msg_type;
-	qdf_mem_copy(&aniHdr[1], buf, buf_len);
-	aniHdr->length = buf_len;
-
-	skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len));
-	osif_debug("sending oem rsp: type: %d len(%d) to pid (%d)",
-		   rsp_msg_type, buf_len, pid);
-	nl_srv_ucast_oem(skb, pid, MSG_DONTWAIT);
 }
 
 #ifdef CNSS_GENL
-static int  wifi_pos_parse_req(const void *data, int len, int pid,
+
+static int  wifi_pos_parse_nla_req(const void *data, int len, int pid,
 		    struct wifi_pos_req_msg *req)
 {
-	tAniMsgHdr *msg_hdr;
+	uint8_t *msg;
 	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
-	uint32_t msg_len, id, nl_field_info_size, expected_field_info_size;
-	struct wifi_pos_field_info *field_info;
+	uint32_t msg_len;
 
 	if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) {
 		osif_err("invalid data in request");
 		return OEM_ERR_INVALID_MESSAGE_TYPE;
 	}
 
-	if (!tb[CLD80211_ATTR_DATA]) {
-		osif_err("CLD80211_ATTR_DATA not present");
+	req->pid = pid;
+	req->msg_type = map_cld_vendor_sub_cmd_to_wifi_pos_cmd(
+				nla_get_u32(tb[CLD80211_ATTR_CMD]));
+	req->rsp_version = WIFI_POS_RSP_V2_NL;
+
+	if (tb[CLD80211_ATTR_CMD_TAG_DATA]) {
+		msg_len = nla_len(tb[CLD80211_ATTR_CMD_TAG_DATA]);
+		msg = nla_data(tb[CLD80211_ATTR_CMD_TAG_DATA]);
+		req->buf_len = msg_len;
+		req->buf = msg;
+	}
+	if (tb[CLD80211_ATTR_META_DATA])
+		osif_err("meta data dropped. Apps can use CLD80211_ATTR_CMD_TAG_DATA sub attrs");
+
+	return 0;
+}
+
+static int  wifi_pos_parse_ani_req(const void *data, int len, int pid,
+		    struct wifi_pos_req_msg *req)
+{
+	tAniMsgHdr *msg_hdr;
+	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
+	uint32_t msg_len, id, nl_field_info_size, expected_field_info_size;
+	struct wifi_pos_field_info *field_info;
+
+	if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) {
+		osif_err("invalid data in request");
 		return OEM_ERR_INVALID_MESSAGE_TYPE;
 	}
 
@@ -105,7 +336,9 @@ static int  wifi_pos_parse_req(const void *data, int len, int pid,
 	}
 
 	msg_hdr = nla_data(tb[CLD80211_ATTR_DATA]);
-	req->msg_type = msg_hdr->type;
+	req->msg_type = map_ani_msg_req_to_wifi_pos_cmd(
+				(uint32_t)msg_hdr->type);
+	req->rsp_version = WIFI_POS_RSP_V1_FLAT_MEMORY;
 
 	if (msg_len < sizeof(*msg_hdr) + msg_hdr->length) {
 		osif_err("Insufficient length for msg_hdr buffer: %u",
@@ -148,6 +381,29 @@ static int  wifi_pos_parse_req(const void *data, int len, int pid,
 
 	return 0;
 }
+
+
+static int  wifi_pos_parse_req(const void *data, int len, int pid,
+		    struct wifi_pos_req_msg *req)
+{
+	int status = 0;
+	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
+
+	if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) {
+		osif_err("invalid data in request");
+		return OEM_ERR_INVALID_MESSAGE_TYPE;
+	}
+
+	if (tb[CLD80211_ATTR_DATA]) {
+		status = wifi_pos_parse_ani_req(data, len, pid, req);
+	} else if (tb[CLD80211_ATTR_CMD]) {
+		status = wifi_pos_parse_nla_req(data, len, pid, req);
+	} else {
+		osif_err("Valid CLD80211 ATTR not present");
+		return OEM_ERR_INVALID_MESSAGE_TYPE;
+	}
+	return status;
+}
 #else
 static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req)
 {
@@ -181,7 +437,9 @@ static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req)
 		return OEM_ERR_INVALID_MESSAGE_LENGTH;
 	}
 
-	req->msg_type = msg_hdr->type;
+	req->msg_type = map_ani_msg_req_to_wifi_pos_cmd(
+				(uint32_t)msg_hdr->type);
+	req->rsp_version = WIFI_POS_RSP_V1_FLAT_MEMORY;
 	req->buf_len = msg_hdr->length;
 	req->buf = (uint8_t *)&msg_hdr[1];
 	req->pid = nlh->nlmsg_pid;
@@ -225,7 +483,7 @@ static void __os_if_wifi_pos_callback(const void *data, int data_len,
 	err = wifi_pos_parse_req(data, data_len, pid, &req);
 	if (err) {
 		os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc),
-					ANI_MSG_OEM_ERROR, sizeof(err), &err);
+					WIFI_POS_CMD_ERROR, sizeof(err), &err);
 		status = QDF_STATUS_E_INVAL;
 		goto release_psoc_ref;
 	}
@@ -268,7 +526,7 @@ static int __os_if_wifi_pos_callback(struct sk_buff *skb)
 	err = wifi_pos_parse_req(skb, &req);
 	if (err) {
 		os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc),
-					ANI_MSG_OEM_ERROR, sizeof(err), &err);
+					WIFI_POS_CMD_ERROR, sizeof(err), &err);
 		status = QDF_STATUS_E_INVAL;
 		goto release_psoc_ref;
 	}
@@ -341,7 +599,7 @@ void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac,
 				enum QDF_OPMODE dev_mode)
 {
 	struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
-	struct wmi_pos_peer_status_info *peer_info;
+	struct wifi_pos_peer_status_info *peer_info;
 
 	if (!psoc) {
 		osif_err("global wifi_pos psoc object not registered");
@@ -382,7 +640,7 @@ void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac,
 	}
 
 	os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc),
-				ANI_MSG_PEER_STATUS_IND,
+				WIFI_POS_PEER_STATUS_IND,
 				sizeof(*peer_info), (uint8_t *)peer_info);
 	qdf_mem_free(peer_info);
 }

+ 3 - 1
target_if/wifi_pos/src/target_if_wifi_pos.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020 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
@@ -22,6 +22,8 @@
  * target if layer.
  */
 #include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h"
+#include "wifi_pos_utils_pub.h"
+
 #include "wmi_unified_api.h"
 #include "wlan_lmac_if_def.h"
 #include "target_if_wifi_pos.h"

+ 14 - 6
umac/wifi_pos/inc/wifi_pos_api.h

@@ -24,9 +24,7 @@
 #define _WIFI_POS_API_H_
 
 /* Include files */
-#include "qdf_types.h"
-#include "qdf_status.h"
-#include "qdf_trace.h"
+#include "wifi_pos_utils_pub.h"
 
 /* forward reference */
 struct wlan_objmgr_psoc;
@@ -113,7 +111,7 @@ struct qdf_packed wifi_pos_ch_info_rsp {
 };
 
 /**
- * struct wmi_pos_peer_status_info - Status information for a given peer
+ * struct wifi_pos_peer_status_info - Status information for a given peer
  * @peer_mac_addr: peer mac address
  * @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED
  * @vdev_id: vdev_id for the peer mac
@@ -121,7 +119,7 @@ struct qdf_packed wifi_pos_ch_info_rsp {
  * @reserved0: reserved0
  * @peer_chan_info: channel info on which peer is connected
  */
-struct qdf_packed wmi_pos_peer_status_info {
+struct qdf_packed wifi_pos_peer_status_info {
 	uint8_t peer_mac_addr[ETH_ALEN];
 	uint8_t peer_status;
 	uint8_t vdev_id;
@@ -138,15 +136,17 @@ struct qdf_packed wmi_pos_peer_status_info {
  * @buf_len: request buffer length
  * @field_info_buf: buffer containing field info
  * @field_info_buf_len: length of field info buffer
+ * @rsp_version: nl type or ani type
  *
  */
 struct wifi_pos_req_msg {
-	uint32_t msg_type;
+	enum wifi_pos_cmd_ids msg_type;
 	uint32_t pid;
 	uint8_t *buf;
 	uint32_t buf_len;
 	struct wifi_pos_field_info *field_info_buf;
 	uint32_t field_info_buf_len;
+	uint32_t rsp_version;
 };
 
 /**
@@ -340,6 +340,14 @@ void ucfg_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val);
 void ucfg_wifi_pos_set_oem_6g_supported(struct wlan_objmgr_psoc *psoc,
 					bool val);
 
+/**
+ * ucfg_wifi_pos_is_nl_rsp: API to check if response is nl or ani type
+ * @psoc: psoc object
+ *
+ * Return: true if response is nl type
+ */
+bool ucfg_wifi_pos_is_nl_rsp(struct wlan_objmgr_psoc *psoc);
+
 /**
  * wifi_pos_get_app_pid: returns oem app pid.
  * @psoc: pointer to psoc object

+ 129 - 0
umac/wifi_pos/inc/wifi_pos_utils_pub.h

@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020, 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: wifi_pos_utils_pub.h
+ * This file declares public utils of wifi positioning component
+ */
+#ifndef _WIFI_POS_UTILS_PUB_H_
+#define _WIFI_POS_UTILS_PUB_H_
+
+/* Include files */
+#include "qdf_types.h"
+#include "qdf_status.h"
+#include "qdf_trace.h"
+
+#define WIFIPOS_RESERVE_BYTES      100
+#define OEM_TARGET_SIGNATURE_LEN   8
+#define OEM_TARGET_SIGNATURE       "QUALCOMM"
+
+#define OEM_CAP_MAX_NUM_CHANNELS   128
+
+#define WIFI_POS_RSP_V1_FLAT_MEMORY  0x00000001
+#define WIFI_POS_RSP_V2_NL  0x00000002
+
+/**
+ * enum wifi_pos_cmd_ids
+ * @WIFI_POS_CMD_REGISTRATION: app registration
+ * @WIFI_POS_CMD_GET_CAPS: get driver capabilities
+ * @WIFI_POS_CMD_GET_CH_INFO: get channel info
+ * @WIFI_POS_CMD_OEM_DATA: oem data req/rsp
+ * @WIFI_POS_CMD_MAX: Max cld80211 vendor sub cmds
+ */
+
+enum wifi_pos_cmd_ids {
+	WIFI_POS_CMD_INVALID = 0,
+	WIFI_POS_CMD_REGISTRATION = 1,
+	WIFI_POS_CMD_SET_CAPS = 2,
+	WIFI_POS_CMD_GET_CAPS = 3,
+	WIFI_POS_CMD_GET_CH_INFO = 4,
+	WIFI_POS_CMD_OEM_DATA = 5,
+	WIFI_POS_CMD_ERROR = 6,
+	WIFI_POS_PEER_STATUS_IND = 7,
+	/* keep last */
+	WIFI_POS_CMD__AFTER_LAST,
+	WIFI_POS_CMD_MAX =
+		WIFI_POS_CMD__AFTER_LAST - 1
+};
+
+
+/**
+ * struct wifi_pos_driver_version - Driver version identifier (w.x.y.z)
+ * @major: Version ID major number
+ * @minor: Version ID minor number
+ * @patch: Version ID patch number
+ * @build: Version ID build number
+ */
+struct qdf_packed wifi_pos_driver_version {
+	uint8_t major;
+	uint8_t minor;
+	uint8_t patch;
+	uint8_t build;
+};
+
+/**
+ * struct wifi_pos_driver_caps - OEM Data Capabilities
+ * @oem_target_signature: Signature of chipset vendor
+ * @oem_target_type: Chip type
+ * @oem_fw_version: Firmware version
+ * @driver_version: Host software version
+ * @allowed_dwell_time_min: Channel dwell time - allowed minimum
+ * @allowed_dwell_time_max: Channel dwell time - allowed maximum
+ * @curr_dwell_time_min: Channel dwell time - current minimim
+ * @curr_dwell_time_max: Channel dwell time - current maximum
+ * @supported_bands: Supported bands, 2.4G or 5G Hz
+ * @num_channels: Num of channels IDs to follow
+ * @channel_list: List of channel IDs
+ */
+struct qdf_packed wifi_pos_driver_caps {
+	uint8_t oem_target_signature[OEM_TARGET_SIGNATURE_LEN];
+	uint32_t oem_target_type;
+	uint32_t oem_fw_version;
+	struct wifi_pos_driver_version driver_version;
+	uint16_t allowed_dwell_time_min;
+	uint16_t allowed_dwell_time_max;
+	uint16_t curr_dwell_time_min;
+	uint16_t curr_dwell_time_max;
+	uint16_t supported_bands;
+	uint16_t num_channels;
+	uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS];
+};
+
+/**
+ * struct wifi_pos_user_defined_caps - OEM capability to be exchanged between
+ * host and userspace
+ * @ftm_rr: FTM range report capability bit
+ * @lci_capability: LCI capability bit
+ * @reserved1: reserved
+ * @reserved2: reserved
+ */
+struct wifi_pos_user_defined_caps {
+	uint32_t ftm_rr:1;
+	uint32_t lci_capability:1;
+	uint32_t reserved1:30;
+	uint32_t reserved2;
+};
+
+/**
+ * struct wifi_pos_oem_get_cap_rsp - capabilities set by userspace and target.
+ * @driver_cap: target capabilities
+ * @user_defined_cap: capabilities set by userspace via set request
+ */
+struct qdf_packed wifi_pos_oem_get_cap_rsp {
+	struct wifi_pos_driver_caps driver_cap;
+	struct wifi_pos_user_defined_caps user_defined_cap;
+};
+#endif

+ 14 - 13
umac/wifi_pos/src/wifi_pos_main.c

@@ -216,7 +216,7 @@ static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
 	wifi_pos_obj->lci_capability = caps->lci_capability;
 	error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
-					ANI_MSG_SET_OEM_CAP_RSP,
+					WIFI_POS_CMD_SET_CAPS,
 					sizeof(error_code),
 					(uint8_t *)&error_code);
 
@@ -236,13 +236,14 @@ static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
 	}
 
 	wifi_pos_debug("Received get cap req pid(%d), len(%d)",
-			req->pid, req->buf_len);
+		       req->pid, req->buf_len);
 
 	wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
 	cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
 	cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
+
 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
-					ANI_MSG_GET_OEM_CAP_RSP,
+					WIFI_POS_CMD_GET_CAPS,
 					sizeof(cap_rsp),
 					(uint8_t *)&cap_rsp);
 
@@ -276,7 +277,7 @@ QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
 	memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
 
 	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
-			ANI_MSG_OEM_DATA_RSP,
+			WIFI_POS_CMD_OEM_DATA,
 			sizeof(err_report),
 			(uint8_t *)&err_report);
 
@@ -548,7 +549,7 @@ static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
 		wifi_pos_debug("no active vdev");
 
 	vdev_idx = 0;
-	wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP,
+	wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_REGISTRATION,
 					rsp_len, (uint8_t *)app_reg_rsp);
 
 	qdf_mem_free(app_reg_rsp);
@@ -556,7 +557,7 @@ static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
 
 app_reg_failed:
 
-	wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR,
+	wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_ERROR,
 					sizeof(err), &err);
 	return ret;
 }
@@ -572,15 +573,15 @@ static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
 {
 	wifi_pos_debug("enter: msg_type: %d", req->msg_type);
 	switch (req->msg_type) {
-	case ANI_MSG_APP_REG_REQ:
+	case WIFI_POS_CMD_REGISTRATION:
 		return wifi_pos_process_app_reg_req(psoc, req);
-	case ANI_MSG_OEM_DATA_REQ:
+	case WIFI_POS_CMD_OEM_DATA:
 		return wifi_pos_process_data_req(psoc, req);
-	case ANI_MSG_CHANNEL_INFO_REQ:
+	case WIFI_POS_CMD_GET_CH_INFO:
 		return wifi_pos_process_ch_info_req(psoc, req);
-	case ANI_MSG_SET_OEM_CAP_REQ:
+	case WIFI_POS_CMD_SET_CAPS:
 		return wifi_pos_process_set_cap_req(psoc, req);
-	case ANI_MSG_GET_OEM_CAP_REQ:
+	case WIFI_POS_CMD_GET_CAPS:
 		return wifi_pos_process_get_cap_req(psoc, req);
 	default:
 		wifi_pos_err("invalid request type");
@@ -740,10 +741,10 @@ int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
 		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
 			     oem_rsp->data_2, oem_rsp->rsp_len_2);
 
-		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data);
+		wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA, len, data);
 		qdf_mem_free(data);
 	} else {
-		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP,
+		wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA,
 				  oem_rsp->rsp_len_1, oem_rsp->data_1);
 	}
 

+ 29 - 4
umac/wifi_pos/src/wifi_pos_ucfg.c

@@ -27,7 +27,8 @@
 
 QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc,
 		struct wifi_pos_req_msg *req,
-		void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *))
+		void (*send_rsp_cb)(uint32_t, enum wifi_pos_cmd_ids,
+		uint32_t, uint8_t *))
 {
 	uint8_t err;
 	uint32_t app_pid;
@@ -46,21 +47,22 @@ QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc,
 	wifi_pos_psoc_obj->wifi_pos_send_rsp = send_rsp_cb;
 	is_app_registered = wifi_pos_psoc_obj->is_app_registered;
 	app_pid = wifi_pos_psoc_obj->app_pid;
+	wifi_pos_psoc_obj->rsp_version = req->rsp_version;
 	qdf_spin_unlock_bh(&wifi_pos_psoc_obj->wifi_pos_lock);
 
 	if (!wifi_pos_psoc_obj->wifi_pos_req_handler) {
 		wifi_pos_err("wifi_pos_psoc_obj->wifi_pos_req_handler is null");
 		err = OEM_ERR_NULL_CONTEXT;
-		send_rsp_cb(app_pid, ANI_MSG_OEM_ERROR, sizeof(err), &err);
+		send_rsp_cb(app_pid, WIFI_POS_CMD_ERROR, sizeof(err), &err);
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
-	if (req->msg_type != ANI_MSG_APP_REG_REQ &&
+	if (req->msg_type != WIFI_POS_CMD_REGISTRATION &&
 		(!is_app_registered || app_pid != req->pid)) {
 		wifi_pos_err("requesting app is not registered, app_registered: %d, requesting pid: %d, stored pid: %d",
 			is_app_registered, req->pid, app_pid);
 		err = OEM_ERR_APP_NOT_REGISTERED;
-		send_rsp_cb(app_pid, ANI_MSG_OEM_ERROR, sizeof(err), &err);
+		send_rsp_cb(app_pid, WIFI_POS_CMD_ERROR, sizeof(err), &err);
 		return QDF_STATUS_E_INVAL;
 	}
 
@@ -115,3 +117,26 @@ void ucfg_wifi_pos_set_oem_6g_supported(struct wlan_objmgr_psoc *psoc,
 	wifi_pos_psoc->oem_6g_support_disable = val;
 	qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
 }
+
+bool ucfg_wifi_pos_is_nl_rsp(struct wlan_objmgr_psoc *psoc)
+{
+	uint32_t val = 0;
+	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
+			wifi_pos_get_psoc_priv_obj(psoc);
+
+	if (!wifi_pos_psoc) {
+		wifi_pos_alert("unable to get wifi_pos psoc obj");
+		return false;
+	}
+
+	qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
+	val = wifi_pos_psoc->rsp_version;
+	qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
+
+	if (val == WIFI_POS_RSP_V2_NL)
+		return true;
+	else
+		return false;
+
+}
+

+ 5 - 73
umac/wifi_pos/src/wifi_pos_utils_i.h

@@ -31,6 +31,7 @@
 #include "ol_defines.h"
 #include "qdf_trace.h"
 #include "qdf_module.h"
+#include "wifi_pos_utils_pub.h"
 
 struct wlan_objmgr_psoc;
 struct wifi_pos_req_msg;
@@ -60,11 +61,6 @@ struct wifi_pos_req_msg;
 #define OEM_APP_SIGNATURE_LEN      16
 #define OEM_APP_SIGNATURE_STR      "QUALCOMM-OEM-APP"
 
-#define OEM_TARGET_SIGNATURE_LEN   8
-#define OEM_TARGET_SIGNATURE       "QUALCOMM"
-
-#define OEM_CAP_MAX_NUM_CHANNELS   128
-
 #ifndef OEM_DATA_RSP_SIZE
 #define OEM_DATA_RSP_SIZE 1724
 #endif
@@ -121,73 +117,6 @@ struct oem_data_rsp {
 	void *vaddr;
 };
 
-/**
- * struct wifi_pos_driver_version - Driver version identifier (w.x.y.z)
- * @major: Version ID major number
- * @minor: Version ID minor number
- * @patch: Version ID patch number
- * @build: Version ID build number
- */
-struct qdf_packed wifi_pos_driver_version {
-	uint8_t major;
-	uint8_t minor;
-	uint8_t patch;
-	uint8_t build;
-};
-
-/**
- * struct wifi_pos_driver_caps - OEM Data Capabilities
- * @oem_target_signature: Signature of chipset vendor, e.g. QUALCOMM
- * @oem_target_type: Chip type
- * @oem_fw_version: Firmware version
- * @driver_version: Host software version
- * @allowed_dwell_time_min: Channel dwell time - allowed minimum
- * @allowed_dwell_time_max: Channel dwell time - allowed maximum
- * @curr_dwell_time_min: Channel dwell time - current minimim
- * @curr_dwell_time_max: Channel dwell time - current maximum
- * @supported_bands: Supported bands, 2.4G or 5G Hz
- * @num_channels: Num of channels IDs to follow
- * @channel_list: List of channel IDs
- */
-struct qdf_packed wifi_pos_driver_caps {
-	uint8_t oem_target_signature[OEM_TARGET_SIGNATURE_LEN];
-	uint32_t oem_target_type;
-	uint32_t oem_fw_version;
-	struct wifi_pos_driver_version driver_version;
-	uint16_t allowed_dwell_time_min;
-	uint16_t allowed_dwell_time_max;
-	uint16_t curr_dwell_time_min;
-	uint16_t curr_dwell_time_max;
-	uint16_t supported_bands;
-	uint16_t num_channels;
-	uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS];
-};
-
-/**
- * struct wifi_pos_user_defined_caps - OEM capability to be exchanged between
- * host and userspace
- * @ftm_rr: FTM range report capability bit
- * @lci_capability: LCI capability bit
- * @reserved1: reserved
- * @reserved2: reserved
- */
-struct wifi_pos_user_defined_caps {
-	uint32_t ftm_rr:1;
-	uint32_t lci_capability:1;
-	uint32_t reserved1:30;
-	uint32_t reserved2;
-};
-
-/**
- * struct wifi_pos_oem_get_cap_rsp - capabilities set by userspace and target.
- * @driver_cap: target capabilities
- * @user_defined_cap: capabilities set by userspace via set request
- */
-struct qdf_packed wifi_pos_oem_get_cap_rsp {
-	struct wifi_pos_driver_caps driver_cap;
-	struct wifi_pos_user_defined_caps user_defined_cap;
-};
-
 /**
  * struct wifi_pos_err_rpt - Error report response for userspace.
  * @tag_len: tlv header of the message.
@@ -310,6 +239,7 @@ struct wifi_pos_dma_rings_cfg {
  *                                     for given freq and channel width
  * @wifi_pos_send_action: function pointer to send registered action frames
  *                        to userspace APP
+ * @rsp_version: rsp version
  *
  * wifi pos request messages
  * <----- fine_time_meas_cap (in bits) ----->
@@ -348,13 +278,15 @@ struct wifi_pos_psoc_priv_obj {
 	bool oem_6g_support_disable;
 	QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc,
 				    struct wifi_pos_req_msg *req);
-	void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
+	void (*wifi_pos_send_rsp)(uint32_t, enum wifi_pos_cmd_ids,
+				  uint32_t, uint8_t *);
 	void (*wifi_pos_get_phy_mode)(uint8_t, uint32_t, uint32_t *);
 	void (*wifi_pos_get_fw_phy_mode_for_freq)(uint32_t, uint32_t,
 						  uint32_t *);
 	void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc,
 				     uint32_t oem_subtype, uint8_t *buf,
 				     uint32_t len);
+	uint32_t rsp_version;
 };
 
 /**

+ 45 - 1
utils/nlink/inc/wlan_nlink_srv.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, 2019-2020 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
@@ -40,6 +40,35 @@
 
 typedef int (*nl_srv_msg_callback)(struct sk_buff *skb);
 
+/**
+ * cld80211_oem_send_reply() - API to send cld80211 msg
+ * @skb: Sk buffer
+ * @hdr: nl80211hdr pointer
+ * @nest: pointer of vendor nested attribute
+ * @flags: Flags
+ *
+ * API to send cld80211 msg to applications
+ *
+ * Return: None
+ */
+void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
+				    struct nlattr *nest, int flags);
+
+/**
+ * nl80211hdr_put() - API to allocate skb for cld80211 msg
+ * @hdr: nl80211hdr pointer
+ * @portid: Port ID
+ * @nest: pointer of vendor nested attribute
+ * @flags: Flags
+ *
+ * API to allocate skb for cld80211 msg
+ *
+ * Return: Pointer to skbuff
+ */
+
+struct sk_buff *
+cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
+			   int *flags);
 int nl_srv_init(void *wiphy, int proto);
 void nl_srv_exit(void);
 int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
@@ -50,6 +79,21 @@ int nl_srv_unregister(tWlanNlModTypes msg_type,
 int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
 			int app_id, int mcgroup_id);
 int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id);
+
+/**
+ * nl80211hdr_put() - API to fill genlmsg header
+ * @skb: Sk buffer
+ * @portid: Port ID
+ * @seq: Sequence number
+ * @flags: Flags
+ * @cmd: Command id
+ *
+ * API to fill genl message header for brodcast events to user space
+ *
+ * Return: Pointer to user specific header/payload
+ */
+void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
+		     uint32_t seq, int flags, uint8_t cmd);
 #else
 int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
 int nl_srv_bcast(struct sk_buff *skb);

+ 51 - 16
utils/nlink/src/wlan_nlink_srv.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 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
@@ -267,6 +267,54 @@ qdf_export_symbol(nl_srv_is_initialized);
 #include <net/genetlink.h>
 #include <net/cnss_nl.h>
 
+void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
+				    struct nlattr *nest, int flags)
+{
+	struct genl_family *cld80211_fam = cld80211_get_genl_family();
+
+	nla_nest_end(msg, nest);
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
+				CLD80211_MCGRP_OEM_MSGS, flags);
+}
+
+struct sk_buff *
+cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
+			   int *flags)
+{
+	static struct sk_buff *msg;
+
+	if (in_interrupt() || irqs_disabled() || in_atomic())
+		*flags = GFP_ATOMIC;
+
+	msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags);
+	if (!msg) {
+		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+					"nlmsg malloc fails");
+		return NULL;
+	}
+
+	*hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM);
+	if (*hdr == NULL) {
+		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+					"nl80211 hdr put failed");
+		goto nla_put_failure;
+	}
+
+	*nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
+	if (*nest == NULL) {
+		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+					"nla_nest_start failed");
+		goto nla_put_failure;
+	}
+	return msg;
+nla_put_failure:
+	genlmsg_cancel(msg, *hdr);
+	nlmsg_free(msg);
+	return NULL;
+}
+
 /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
 int nl_srv_init(void *wiphy, int proto)
 {
@@ -293,21 +341,8 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
 	return 0;
 }
 
-
-/**
- * nl80211hdr_put() - API to fill genlmsg header
- * @skb: Sk buffer
- * @portid: Port ID
- * @seq: Sequence number
- * @flags: Flags
- * @cmd: Command id
- *
- * API to fill genl message header for brodcast events to user space
- *
- * Return: Pointer to user specific header/payload
- */
-static inline void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
-					uint32_t seq, int flags, uint8_t cmd)
+void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
+		     uint32_t seq, int flags, uint8_t cmd)
 {
 	struct genl_family *cld80211_fam = cld80211_get_genl_family();