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
This commit is contained in:
Vinay Gannevaram
2019-12-23 21:58:09 +05:30
committed by nshrivas
parent 644413b274
commit 23a3603951
10 changed files with 654 additions and 151 deletions

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * 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 #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_ */ #endif /* _OS_IF_WIFI_POS_H_ */

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -33,6 +33,206 @@
#include "wlan_objmgr_psoc_obj.h" #include "wlan_objmgr_psoc_obj.h"
#ifdef CNSS_GENL #ifdef CNSS_GENL
#include <net/cnss_nl.h> #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 #endif
/** /**
@@ -42,12 +242,13 @@
* *
* Return: none * 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) uint32_t buf_len, uint8_t *buf)
{ {
tAniMsgHdr *aniHdr; tAniMsgHdr *aniHdr;
struct sk_buff *skb; struct sk_buff *skb = NULL;
struct nlmsghdr *nlh; 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 */ /* OEM msg is always to a specific process and cannot be a broadcast */
if (pid == 0) { if (pid == 0) {
@@ -55,32 +256,67 @@ static void os_if_wifi_pos_send_rsp(uint32_t pid, uint32_t rsp_msg_type,
return; return;
} }
skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len), GFP_ATOMIC); if (ucfg_wifi_pos_is_nl_rsp(psoc)) {
if (!skb) { os_if_send_nl_resp(pid, buf, cmd);
osif_alert("alloc_skb failed"); } else {
return; 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 #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)
{
uint8_t *msg;
struct nlattr *tb[CLD80211_ATTR_MAX + 1];
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;
}
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) struct wifi_pos_req_msg *req)
{ {
tAniMsgHdr *msg_hdr; tAniMsgHdr *msg_hdr;
@@ -93,11 +329,6 @@ static int wifi_pos_parse_req(const void *data, int len, int pid,
return OEM_ERR_INVALID_MESSAGE_TYPE; return OEM_ERR_INVALID_MESSAGE_TYPE;
} }
if (!tb[CLD80211_ATTR_DATA]) {
osif_err("CLD80211_ATTR_DATA not present");
return OEM_ERR_INVALID_MESSAGE_TYPE;
}
msg_len = nla_len(tb[CLD80211_ATTR_DATA]); msg_len = nla_len(tb[CLD80211_ATTR_DATA]);
if (msg_len < sizeof(*msg_hdr)) { if (msg_len < sizeof(*msg_hdr)) {
osif_err("Insufficient length for msg_hdr: %u", msg_len); osif_err("Insufficient length for msg_hdr: %u", msg_len);
@@ -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]); 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) { if (msg_len < sizeof(*msg_hdr) + msg_hdr->length) {
osif_err("Insufficient length for msg_hdr buffer: %u", 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; 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 #else
static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req) 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; 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_len = msg_hdr->length;
req->buf = (uint8_t *)&msg_hdr[1]; req->buf = (uint8_t *)&msg_hdr[1];
req->pid = nlh->nlmsg_pid; 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); err = wifi_pos_parse_req(data, data_len, pid, &req);
if (err) { if (err) {
os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc), 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; status = QDF_STATUS_E_INVAL;
goto release_psoc_ref; 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); err = wifi_pos_parse_req(skb, &req);
if (err) { if (err) {
os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc), 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; status = QDF_STATUS_E_INVAL;
goto release_psoc_ref; 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) enum QDF_OPMODE dev_mode)
{ {
struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); 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) { if (!psoc) {
osif_err("global wifi_pos psoc object not registered"); 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), 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); sizeof(*peer_info), (uint8_t *)peer_info);
qdf_mem_free(peer_info); qdf_mem_free(peer_info);
} }

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -22,6 +22,8 @@
* target if layer. * target if layer.
*/ */
#include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h" #include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h"
#include "wifi_pos_utils_pub.h"
#include "wmi_unified_api.h" #include "wmi_unified_api.h"
#include "wlan_lmac_if_def.h" #include "wlan_lmac_if_def.h"
#include "target_if_wifi_pos.h" #include "target_if_wifi_pos.h"

View File

@@ -24,9 +24,7 @@
#define _WIFI_POS_API_H_ #define _WIFI_POS_API_H_
/* Include files */ /* Include files */
#include "qdf_types.h" #include "wifi_pos_utils_pub.h"
#include "qdf_status.h"
#include "qdf_trace.h"
/* forward reference */ /* forward reference */
struct wlan_objmgr_psoc; 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_mac_addr: peer mac address
* @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED * @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED
* @vdev_id: vdev_id for the peer mac * @vdev_id: vdev_id for the peer mac
@@ -121,7 +119,7 @@ struct qdf_packed wifi_pos_ch_info_rsp {
* @reserved0: reserved0 * @reserved0: reserved0
* @peer_chan_info: channel info on which peer is connected * @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_mac_addr[ETH_ALEN];
uint8_t peer_status; uint8_t peer_status;
uint8_t vdev_id; uint8_t vdev_id;
@@ -138,15 +136,17 @@ struct qdf_packed wmi_pos_peer_status_info {
* @buf_len: request buffer length * @buf_len: request buffer length
* @field_info_buf: buffer containing field info * @field_info_buf: buffer containing field info
* @field_info_buf_len: length of field info buffer * @field_info_buf_len: length of field info buffer
* @rsp_version: nl type or ani type
* *
*/ */
struct wifi_pos_req_msg { struct wifi_pos_req_msg {
uint32_t msg_type; enum wifi_pos_cmd_ids msg_type;
uint32_t pid; uint32_t pid;
uint8_t *buf; uint8_t *buf;
uint32_t buf_len; uint32_t buf_len;
struct wifi_pos_field_info *field_info_buf; struct wifi_pos_field_info *field_info_buf;
uint32_t field_info_buf_len; 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, void ucfg_wifi_pos_set_oem_6g_supported(struct wlan_objmgr_psoc *psoc,
bool val); 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. * wifi_pos_get_app_pid: returns oem app pid.
* @psoc: pointer to psoc object * @psoc: pointer to psoc object

View File

@@ -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

View File

@@ -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; wifi_pos_obj->lci_capability = caps->lci_capability;
error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS); error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, 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), sizeof(error_code),
(uint8_t *)&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)", 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); 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.ftm_rr = wifi_pos_obj->ftm_rr;
cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability; cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, 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), sizeof(cap_rsp),
(uint8_t *)&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); 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, 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), sizeof(err_report),
(uint8_t *)&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"); wifi_pos_debug("no active vdev");
vdev_idx = 0; 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); rsp_len, (uint8_t *)app_reg_rsp);
qdf_mem_free(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: 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); sizeof(err), &err);
return ret; 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); wifi_pos_debug("enter: msg_type: %d", req->msg_type);
switch (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); 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); 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); 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); 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); return wifi_pos_process_get_cap_req(psoc, req);
default: default:
wifi_pos_err("invalid request type"); 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], qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
oem_rsp->data_2, oem_rsp->rsp_len_2); 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); qdf_mem_free(data);
} else { } 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); oem_rsp->rsp_len_1, oem_rsp->data_1);
} }

View File

@@ -27,7 +27,8 @@
QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc, QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req, 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; uint8_t err;
uint32_t app_pid; 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; wifi_pos_psoc_obj->wifi_pos_send_rsp = send_rsp_cb;
is_app_registered = wifi_pos_psoc_obj->is_app_registered; is_app_registered = wifi_pos_psoc_obj->is_app_registered;
app_pid = wifi_pos_psoc_obj->app_pid; 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); qdf_spin_unlock_bh(&wifi_pos_psoc_obj->wifi_pos_lock);
if (!wifi_pos_psoc_obj->wifi_pos_req_handler) { if (!wifi_pos_psoc_obj->wifi_pos_req_handler) {
wifi_pos_err("wifi_pos_psoc_obj->wifi_pos_req_handler is null"); wifi_pos_err("wifi_pos_psoc_obj->wifi_pos_req_handler is null");
err = OEM_ERR_NULL_CONTEXT; 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; 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)) { (!is_app_registered || app_pid != req->pid)) {
wifi_pos_err("requesting app is not registered, app_registered: %d, requesting pid: %d, stored pid: %d", wifi_pos_err("requesting app is not registered, app_registered: %d, requesting pid: %d, stored pid: %d",
is_app_registered, req->pid, app_pid); is_app_registered, req->pid, app_pid);
err = OEM_ERR_APP_NOT_REGISTERED; 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; 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; wifi_pos_psoc->oem_6g_support_disable = val;
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); 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;
}

View File

@@ -31,6 +31,7 @@
#include "ol_defines.h" #include "ol_defines.h"
#include "qdf_trace.h" #include "qdf_trace.h"
#include "qdf_module.h" #include "qdf_module.h"
#include "wifi_pos_utils_pub.h"
struct wlan_objmgr_psoc; struct wlan_objmgr_psoc;
struct wifi_pos_req_msg; struct wifi_pos_req_msg;
@@ -60,11 +61,6 @@ struct wifi_pos_req_msg;
#define OEM_APP_SIGNATURE_LEN 16 #define OEM_APP_SIGNATURE_LEN 16
#define OEM_APP_SIGNATURE_STR "QUALCOMM-OEM-APP" #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 #ifndef OEM_DATA_RSP_SIZE
#define OEM_DATA_RSP_SIZE 1724 #define OEM_DATA_RSP_SIZE 1724
#endif #endif
@@ -121,73 +117,6 @@ struct oem_data_rsp {
void *vaddr; 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. * struct wifi_pos_err_rpt - Error report response for userspace.
* @tag_len: tlv header of the message. * @tag_len: tlv header of the message.
@@ -310,6 +239,7 @@ struct wifi_pos_dma_rings_cfg {
* for given freq and channel width * for given freq and channel width
* @wifi_pos_send_action: function pointer to send registered action frames * @wifi_pos_send_action: function pointer to send registered action frames
* to userspace APP * to userspace APP
* @rsp_version: rsp version
* *
* wifi pos request messages * wifi pos request messages
* <----- fine_time_meas_cap (in bits) -----> * <----- fine_time_meas_cap (in bits) ----->
@@ -348,13 +278,15 @@ struct wifi_pos_psoc_priv_obj {
bool oem_6g_support_disable; bool oem_6g_support_disable;
QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc, QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req); 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_phy_mode)(uint8_t, uint32_t, uint32_t *);
void (*wifi_pos_get_fw_phy_mode_for_freq)(uint32_t, uint32_t, void (*wifi_pos_get_fw_phy_mode_for_freq)(uint32_t, uint32_t,
uint32_t *); uint32_t *);
void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc, void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc,
uint32_t oem_subtype, uint8_t *buf, uint32_t oem_subtype, uint8_t *buf,
uint32_t len); uint32_t len);
uint32_t rsp_version;
}; };
/** /**

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * 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); 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); int nl_srv_init(void *wiphy, int proto);
void nl_srv_exit(void); void nl_srv_exit(void);
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); 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 nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
int app_id, int mcgroup_id); int app_id, int mcgroup_id);
int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_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 #else
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag); int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
int nl_srv_bcast(struct sk_buff *skb); int nl_srv_bcast(struct sk_buff *skb);

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * 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/genetlink.h>
#include <net/cnss_nl.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 */ /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
int nl_srv_init(void *wiphy, int proto) 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; return 0;
} }
void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
/** uint32_t seq, int flags, uint8_t cmd)
* 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)
{ {
struct genl_family *cld80211_fam = cld80211_get_genl_family(); struct genl_family *cld80211_fam = cld80211_get_genl_family();