summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaveen Rawat <nrawat@qca.qualcomm.com>2016-02-04 13:47:57 -0800
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-04-13 10:11:30 +0530
commitb02cb8d0ddbc86c3c69b755919c617f2c1f118a9 (patch)
treef15e2bc0a5849ff23594956b6b9ed5fb8aa73a1f
parente740ca8e9b1171bcbe6a240f1a4baf10da0d3ddf (diff)
qcacld-2.0: Add support for get and set OEM capability
Add support for get and set OEM capability over private netlink socket. Change-Id: I8c4a8c19633845750ec9d2492632471c68ba410d CRs-Fixed: 949469
-rw-r--r--CORE/HDD/inc/wlan_hdd_oemdata.h22
-rw-r--r--CORE/HDD/src/wlan_hdd_oemdata.c541
-rw-r--r--CORE/SME/inc/sme_Api.h20
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c54
-rw-r--r--CORE/SVC/inc/wlan_ptt_sock_svc.h6
5 files changed, 508 insertions, 135 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_oemdata.h b/CORE/HDD/inc/wlan_hdd_oemdata.h
index 1d4ba472473c..8822ccebbff4 100644
--- a/CORE/HDD/inc/wlan_hdd_oemdata.h
+++ b/CORE/HDD/inc/wlan_hdd_oemdata.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -158,6 +158,26 @@ typedef PACKED_PRE struct PACKED_POST
tHddChannelInfo peer_chan_info;
} tPeerStatusInfo;
+/**
+ * enum oem_capability_mask - mask field for userspace client capabilities
+ * @OEM_CAP_RM_FTMRR: FTM range report mask bit
+ * @OEM_CAP_RM_LCI: LCI capability mask bit
+ */
+enum oem_capability_mask {
+ OEM_CAP_RM_FTMRR = (1 << (0)),
+ OEM_CAP_RM_LCI = (1 << (1)),
+};
+
+/**
+ * struct oem_get_capability_rsp - capabilites set by userspace and target.
+ * @target_cap: target capabilities
+ * @client_capabilities: capabilities set by userspace via set request
+ */
+struct oem_get_capability_rsp {
+ t_iw_oem_data_cap target_cap;
+ struct sme_oem_capability cap;
+};
+
#endif //__WLAN_HDD_OEM_DATA_H__
#endif //FEATURE_OEM_DATA_SUPPORT
diff --git a/CORE/HDD/src/wlan_hdd_oemdata.c b/CORE/HDD/src/wlan_hdd_oemdata.c
index 3ea48119d52b..91cffba1ba6a 100644
--- a/CORE/HDD/src/wlan_hdd_oemdata.c
+++ b/CORE/HDD/src/wlan_hdd_oemdata.c
@@ -49,6 +49,77 @@
#include "wma.h"
static struct hdd_context_s *pHddCtx;
+/**
+ * populate_oem_data_cap() - populate oem capabilities
+ * @adapter: device adapter
+ * @data_cap: pointer to populate the capabilities
+ *
+ * Return: error code
+ */
+static int populate_oem_data_cap(hdd_adapter_t *adapter,
+ t_iw_oem_data_cap *data_cap)
+{
+ VOS_STATUS status = VOS_STATUS_E_FAILURE;
+ hdd_config_t *config;
+ uint32_t num_chan;
+ uint8_t *chan_list;
+ hdd_context_t *hdd_ctx = adapter->pHddCtx;
+
+ config = hdd_ctx->cfg_ini;
+ if (!config) {
+ hddLog(LOGE, FL("HDD configuration is null"));
+ return -EINVAL;
+ }
+ chan_list = vos_mem_malloc(sizeof(uint8_t) * OEM_CAP_MAX_NUM_CHANNELS);
+ if (NULL == chan_list) {
+ hddLog(LOGE, FL("Memory allocation failed"));
+ return -ENOMEM;
+ }
+
+ strlcpy(data_cap->oem_target_signature, OEM_TARGET_SIGNATURE,
+ OEM_TARGET_SIGNATURE_LEN);
+ data_cap->oem_target_type = hdd_ctx->target_type;
+ data_cap->oem_fw_version = hdd_ctx->target_fw_version;
+ data_cap->driver_version.major = QWLAN_VERSION_MAJOR;
+ data_cap->driver_version.minor = QWLAN_VERSION_MINOR;
+ data_cap->driver_version.patch = QWLAN_VERSION_PATCH;
+ data_cap->driver_version.build = QWLAN_VERSION_BUILD;
+ data_cap->allowed_dwell_time_min = config->nNeighborScanMinChanTime;
+ data_cap->allowed_dwell_time_max = config->nNeighborScanMaxChanTime;
+ data_cap->curr_dwell_time_min =
+ sme_getNeighborScanMinChanTime(hdd_ctx->hHal,
+ adapter->sessionId);
+ data_cap->curr_dwell_time_max =
+ sme_getNeighborScanMaxChanTime(hdd_ctx->hHal,
+ adapter->sessionId);
+ data_cap->supported_bands = config->nBandCapability;
+
+ /* request for max num of channels */
+ num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ status = sme_GetCfgValidChannels(hdd_ctx->hHal, &chan_list[0],
+ &num_chan);
+ if (VOS_STATUS_SUCCESS != status) {
+ hddLog(LOGE, FL("failed to get valid channel list, status: %d"),
+ status);
+ vos_mem_free(chan_list);
+ return -EINVAL;
+ }
+
+ /* make sure num channels is not more than chan list array */
+ if (num_chan > OEM_CAP_MAX_NUM_CHANNELS) {
+ hddLog(LOGE, FL("Num of channels-%d > length-%d of chan_list"),
+ num_chan, OEM_CAP_MAX_NUM_CHANNELS);
+ vos_mem_free(chan_list);
+ return -EINVAL;
+ }
+
+ data_cap->num_channels = num_chan;
+ vos_mem_copy(data_cap->channel_list, chan_list,
+ sizeof(uint8_t) * num_chan);
+
+ vos_mem_free(chan_list);
+ return 0;
+}
/**---------------------------------------------------------------------------
@@ -71,15 +142,11 @@ int iw_get_oem_data_cap(
union iwreq_data *wrqu,
char *extra)
{
- eHalStatus status;
- t_iw_oem_data_cap oemDataCap;
+ int status;
+ t_iw_oem_data_cap oemDataCap = { {0} };
t_iw_oem_data_cap *pHddOemDataCap;
hdd_adapter_t *pAdapter = netdev_priv(dev);
hdd_context_t *pHddContext;
- hdd_config_t *pConfig;
- tANI_U32 numChannels;
- tANI_U8 chanList[OEM_CAP_MAX_NUM_CHANNELS];
- tANI_U32 i;
int ret;
ENTER();
@@ -96,61 +163,14 @@ int iw_get_oem_data_cap(
if (0 != ret)
return ret;
- pConfig = pHddContext->cfg_ini;
+ status = populate_oem_data_cap(pAdapter, &oemDataCap);
+ if (0 != status) {
+ hddLog(LOGE, FL("Failed to populate oem data capabilities"));
+ return status;
+ }
- do
- {
- vos_mem_zero(&oemDataCap, sizeof(oemDataCap));
- strlcpy(oemDataCap.oem_target_signature, OEM_TARGET_SIGNATURE,
- OEM_TARGET_SIGNATURE_LEN);
- oemDataCap.oem_target_type = pHddContext->target_type;
- oemDataCap.oem_fw_version = pHddContext->target_fw_version;
- oemDataCap.driver_version.major = QWLAN_VERSION_MAJOR;
- oemDataCap.driver_version.minor = QWLAN_VERSION_MINOR;
- oemDataCap.driver_version.patch = QWLAN_VERSION_PATCH;
- oemDataCap.driver_version.build = QWLAN_VERSION_BUILD;
- oemDataCap.allowed_dwell_time_min = pConfig->nNeighborScanMinChanTime;
- oemDataCap.allowed_dwell_time_max = pConfig->nNeighborScanMaxChanTime;
- oemDataCap.curr_dwell_time_min =
- sme_getNeighborScanMinChanTime(pHddContext->hHal,
- pAdapter->sessionId);
- oemDataCap.curr_dwell_time_max =
- sme_getNeighborScanMaxChanTime(pHddContext->hHal,
- pAdapter->sessionId);
- oemDataCap.supported_bands = pConfig->nBandCapability;
-
- /* request for max num of channels */
- numChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN;
- status = sme_GetCfgValidChannels(pHddContext->hHal,
- &chanList[0],
- &numChannels);
- if (eHAL_STATUS_SUCCESS != status)
- {
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "%s:failed to get valid channel list", __func__);
- return -ENOENT;
- }
- else
- {
- /* make sure num channels is not more than chan list array */
- if (numChannels > OEM_CAP_MAX_NUM_CHANNELS)
- {
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "%s:Num of channels(%d) more than length(%d) of chanlist",
- __func__, numChannels, OEM_CAP_MAX_NUM_CHANNELS);
- return -ENOMEM;
- }
-
- oemDataCap.num_channels = numChannels;
- for (i = 0; i < numChannels; i++)
- {
- oemDataCap.channel_list[i] = chanList[i];
- }
- }
-
- pHddOemDataCap = (t_iw_oem_data_cap *)(extra);
- vos_mem_copy(pHddOemDataCap, &oemDataCap, sizeof(*pHddOemDataCap));
- } while (0);
+ pHddOemDataCap = (t_iw_oem_data_cap *) (extra);
+ *pHddOemDataCap = oemDataCap;
EXIT();
return 0;
@@ -553,6 +573,133 @@ static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
return 0;
}
+/**
+ * oem_process_set_cap_req_msg() - process oem set capability request
+ * @oem_cap_len: Length of OEM capability
+ * @oem_cap: Pointer to OEM capability buffer
+ * @app_pid: process ID, to which rsp message is to be sent
+ *
+ * This function sends oem message to SME
+ *
+ * Return: error code
+ */
+static int oem_process_set_cap_req_msg(int oem_cap_len,
+ char *oem_cap, int32_t app_pid)
+{
+ VOS_STATUS status;
+ int error_code;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ tAniMsgHdr *ani_hdr;
+ uint8_t *buf;
+
+ if (!oem_cap) {
+ hddLog(LOGE, FL("oem_cap is null"));
+ return -EINVAL;
+ }
+
+ status = sme_oem_update_capability(pHddCtx->hHal,
+ (struct sme_oem_capability *)oem_cap);
+ if (!VOS_IS_STATUS_SUCCESS(status))
+ hddLog(LOGE, FL("error updating rm capability, status: %d"),
+ status);
+ error_code = vos_status_to_os_return(status);
+
+ skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
+ if (skb == NULL) {
+ hddLog(LOGE, FL("alloc_skb failed"));
+ return -ENOMEM;
+ }
+
+ 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;
+ ani_hdr = NLMSG_DATA(nlh);
+ ani_hdr->type = ANI_MSG_SET_OEM_CAP_RSP;
+ /* 64 bit alignment */
+ ani_hdr->length = sizeof(error_code);
+ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + ani_hdr->length);
+
+ /* message body will contain only status code */
+ buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
+ vos_mem_copy(buf, &error_code, ani_hdr->length);
+
+ skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + ani_hdr->length));
+
+ hddLog(LOG1, FL("sending oem response to process pid %d"), app_pid);
+
+ (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
+
+ return error_code;
+}
+
+/**
+ * oem_process_get_cap_req_msg() - process oem get capability request
+ *
+ * This function process the get capability request from OEM and responds
+ * with the capability.
+ *
+ * Return: error code
+ */
+static int oem_process_get_cap_req_msg(void)
+{
+ int error_code;
+ struct oem_get_capability_rsp *cap_rsp;
+ t_iw_oem_data_cap data_cap = { {0} };
+ struct sme_oem_capability oem_cap;
+ hdd_adapter_t *adapter;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ tAniMsgHdr *ani_hdr;
+ uint8_t *buf;
+
+ /* for now, STA interface only */
+ adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
+ if (!adapter) {
+ hddLog(LOGE, FL("No adapter for STA mode"));
+ return -EINVAL;
+ }
+
+ error_code = populate_oem_data_cap(adapter, &data_cap);
+ if (0 != error_code)
+ return error_code;
+
+ skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(*cap_rsp)),
+ GFP_KERNEL);
+ if (skb == NULL) {
+ hddLog(LOGE, FL("alloc_skb failed"));
+ return -ENOMEM;
+ }
+
+ 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;
+ ani_hdr = NLMSG_DATA(nlh);
+ ani_hdr->type = ANI_MSG_GET_OEM_CAP_RSP;
+
+ ani_hdr->length = sizeof(*cap_rsp);
+ nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
+
+ buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
+ vos_mem_copy(buf, &data_cap, sizeof(data_cap));
+
+ buf = (char *) buf + sizeof(data_cap);
+ vos_mem_zero(&oem_cap, sizeof(oem_cap));
+ sme_oem_get_capability(pHddCtx->hHal, &oem_cap);
+ vos_mem_copy(buf, &oem_cap, sizeof(oem_cap));
+
+ skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
+ hddLog(LOG1, FL("send rsp to oem-pid:%d for get_capability"),
+ pHddCtx->oem_pid);
+
+ (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT);
+ return 0;
+}
+
/**---------------------------------------------------------------------------
\brief hdd_SendPeerStatusIndToOemApp()
@@ -670,6 +817,196 @@ void hdd_SendPeerStatusIndToOemApp(v_MACADDR_t *peerMac,
return;
}
+/**
+ * oem_app_reg_req_handler() - function to handle APP registration request
+ * from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @nlh: pointer to NL message header
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_app_reg_req_handler(struct hdd_context_s *hdd_ctx,
+ tAniMsgHdr *msg_hdr, struct nlmsghdr *nlh)
+{
+ char *sign_str = NULL;
+
+ /* Registration request is only allowed for Qualcomm Application */
+ hddLog(LOG1,
+ FL("Received App Reg Req from App process pid(%d), len(%d)"),
+ nlh->nlmsg_pid, msg_hdr->length);
+
+ sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
+ if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
+ (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
+ OEM_APP_SIGNATURE_LEN))) {
+ hddLog(LOG1,
+ FL("Valid App Reg Req from oem app process pid(%d)"),
+ nlh->nlmsg_pid);
+
+ hdd_ctx->oem_app_registered = TRUE;
+ hdd_ctx->oem_pid = nlh->nlmsg_pid;
+ send_oem_reg_rsp_nlink_msg();
+ } else {
+ hddLog(LOGE,
+ FL("Invalid signature in App Reg Req from pid(%d)"),
+ nlh->nlmsg_pid);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_INVALID_SIGNATURE);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+/**
+ * oem_data_req_handler() - function to handle data_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @nlh: pointer to NL message header
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_data_req_handler(struct hdd_context_s *hdd_ctx,
+ tAniMsgHdr *msg_hdr, struct nlmsghdr *nlh)
+{
+ hddLog(LOG1, FL("Received Oem Data Request length(%d) from pid: %d"),
+ msg_hdr->length, nlh->nlmsg_pid);
+
+ if ((!hdd_ctx->oem_app_registered) ||
+ (nlh->nlmsg_pid != hdd_ctx->oem_pid)) {
+ /* either oem app is not registered yet or pid is different */
+ hddLog(LOGE, FL("OEM DataReq: app not registered(%d) or incorrect pid(%d)"),
+ hdd_ctx->oem_app_registered, nlh->nlmsg_pid);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_APP_NOT_REGISTERED);
+ return -EPERM;
+ }
+
+ if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
+ hddLog(LOGE, FL("Invalid length (%d) in Oem Data Request"),
+ msg_hdr->length);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_INVALID_MESSAGE_LENGTH);
+ return -EPERM;
+ }
+
+ oem_process_data_req_msg(msg_hdr->length,
+ (char *) ((char *)msg_hdr +
+ sizeof(tAniMsgHdr)));
+
+ return 0;
+}
+
+/**
+ * oem_chan_info_req_handler() - function to handle chan_info_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @nlh: pointer to NL message header
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_chan_info_req_handler(struct hdd_context_s *hdd_ctx,
+ tAniMsgHdr *msg_hdr, struct nlmsghdr *nlh)
+{
+ hddLog(LOG1,
+ FL("Received channel info request, num channel(%d) from pid: %d"),
+ msg_hdr->length, nlh->nlmsg_pid);
+
+ if ((!hdd_ctx->oem_app_registered) ||
+ (nlh->nlmsg_pid != hdd_ctx->oem_pid)) {
+ /* either oem app is not registered yet or pid is different */
+ hddLog(LOGE,
+ FL("Chan InfoReq: app not registered(%d) or incorrect pid(%d)"),
+ hdd_ctx->oem_app_registered, nlh->nlmsg_pid);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_APP_NOT_REGISTERED);
+ return -EPERM;
+ }
+
+ /* message length contains list of channel ids */
+ if ((!msg_hdr->length) ||
+ (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
+ hddLog(LOGE,
+ FL("Invalid length (%d) in channel info request"),
+ msg_hdr->length);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_INVALID_MESSAGE_LENGTH);
+ return -EPERM;
+ }
+ oem_process_channel_info_req_msg(msg_hdr->length,
+ (char *)((char *)msg_hdr + sizeof(tAniMsgHdr)));
+
+ return 0;
+}
+
+/**
+ * oem_set_cap_req_handler() - function to handle set_cap_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @nlh: pointer to NL message header
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_set_cap_req_handler(struct hdd_context_s *hdd_ctx,
+ tAniMsgHdr *msg_hdr, struct nlmsghdr *nlh)
+{
+ hddLog(LOG1, FL("Received set oem cap req of length:%d from pid: %d"),
+ msg_hdr->length, nlh->nlmsg_pid);
+
+ if ((!hdd_ctx->oem_app_registered) ||
+ (nlh->nlmsg_pid != hdd_ctx->oem_pid)) {
+ /* oem app is not registered yet or pid is different */
+ hddLog(LOGE, FL("set_oem_capability : app not registered(%d) or incorrect pid(%d)"),
+ hdd_ctx->oem_app_registered, nlh->nlmsg_pid);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_APP_NOT_REGISTERED);
+ return -EPERM;
+ }
+
+ if ((!msg_hdr->length) ||
+ (sizeof(struct sme_oem_capability) < msg_hdr->length)) {
+ hddLog(LOGE, FL("Invalid length (%d) in set_oem_capability"),
+ msg_hdr->length);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_INVALID_MESSAGE_LENGTH);
+ return -EPERM;
+ }
+
+ oem_process_set_cap_req_msg(msg_hdr->length, (char *)
+ ((char *)msg_hdr + sizeof(tAniMsgHdr)),
+ nlh->nlmsg_pid);
+ return 0;
+}
+
+/**
+ * oem_get_cap_req_handler() - function to handle get_cap_req from userspace
+ * @hdd_ctx: handle to HDD context
+ * @msg_hdr: pointer to ANI message header
+ * @nlh: pointer to NL message header
+ *
+ * Return: 0 if success, error code otherwise
+ */
+static int oem_get_cap_req_handler(struct hdd_context_s *hdd_ctx,
+ tAniMsgHdr *msg_hdr, struct nlmsghdr *nlh)
+{
+ hddLog(LOG1, FL("Rcvd get oem capability req - length:%d from pid: %d"),
+ msg_hdr->length, nlh->nlmsg_pid);
+
+ if ((!hdd_ctx->oem_app_registered) ||
+ (nlh->nlmsg_pid != hdd_ctx->oem_pid)) {
+ /* oem app is not registered yet or pid is different */
+ hddLog(LOGE, FL("get_oem_capability : app not registered(%d) or incorrect pid(%d)"),
+ hdd_ctx->oem_app_registered, nlh->nlmsg_pid);
+ send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
+ OEM_ERR_APP_NOT_REGISTERED);
+ return -EPERM;
+ }
+
+ oem_process_get_cap_req_msg();
+ return 0;
+}
+
/*
* Callback function invoked by Netlink service for all netlink
* messages (from user space) addressed to WLAN_NL_MSG_OEM
@@ -690,7 +1027,7 @@ static int oem_msg_callback(struct sk_buff *skb)
struct nlmsghdr *nlh;
tAniMsgHdr *msg_hdr;
int ret;
- char *sign_str = NULL;
+
nlh = (struct nlmsghdr *)skb->data;
if (!nlh) {
@@ -720,83 +1057,23 @@ static int oem_msg_callback(struct sk_buff *skb)
switch (msg_hdr->type) {
case ANI_MSG_APP_REG_REQ:
- /* Registration request is only allowed for Qualcomm Application */
- hddLog(LOG1, FL("Received App Req Req from App process pid(%d), len(%d)"),
- nlh->nlmsg_pid, msg_hdr->length);
-
- sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
- if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
- (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
- OEM_APP_SIGNATURE_LEN))) {
- hddLog(LOG1, FL("Valid App Req Req from oem app process pid(%d)"),
- nlh->nlmsg_pid);
-
- pHddCtx->oem_app_registered = TRUE;
- pHddCtx->oem_pid = nlh->nlmsg_pid;
- send_oem_reg_rsp_nlink_msg();
- } else {
- hddLog(LOGE, FL("Invalid signature in App Reg Request from pid(%d)"),
- nlh->nlmsg_pid);
- send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
- OEM_ERR_INVALID_SIGNATURE);
- return -EPERM;
- }
+ ret = oem_app_reg_req_handler(pHddCtx, msg_hdr, nlh);
break;
case ANI_MSG_OEM_DATA_REQ:
- hddLog(LOG1, FL("Received Oem Data Request length(%d) from pid: %d"),
- msg_hdr->length, nlh->nlmsg_pid);
-
- if ((!pHddCtx->oem_app_registered) ||
- (nlh->nlmsg_pid != pHddCtx->oem_pid)) {
- /* either oem app is not registered yet or pid is different */
- hddLog(LOGE, FL("OEM DataReq: app not registered(%d) or incorrect pid(%d)"),
- pHddCtx->oem_app_registered, nlh->nlmsg_pid);
- send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
- OEM_ERR_APP_NOT_REGISTERED);
- return -EPERM;
- }
-
- if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
- hddLog(LOGE, FL("Invalid length (%d) in Oem Data Request"),
- msg_hdr->length);
- send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
- OEM_ERR_INVALID_MESSAGE_LENGTH);
- return -EPERM;
- }
- oem_process_data_req_msg(msg_hdr->length,
- (char *) ((char *)msg_hdr +
- sizeof(tAniMsgHdr)));
+ ret = oem_data_req_handler(pHddCtx, msg_hdr, nlh);
break;
case ANI_MSG_CHANNEL_INFO_REQ:
- hddLog(LOG1,
- FL("Received channel info request, num channel(%d) from pid: %d"),
- msg_hdr->length, nlh->nlmsg_pid);
-
- if ((!pHddCtx->oem_app_registered) ||
- (nlh->nlmsg_pid != pHddCtx->oem_pid)) {
- /* either oem app is not registered yet or pid is different */
- hddLog(LOGE,
- FL("Chan InfoReq: app not registered(%d) or incorrect pid(%d)"),
- pHddCtx->oem_app_registered, nlh->nlmsg_pid);
- send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
- OEM_ERR_APP_NOT_REGISTERED);
- return -EPERM;
- }
+ ret = oem_chan_info_req_handler(pHddCtx, msg_hdr, nlh);
+ break;
- /* message length contains list of channel ids */
- if ((!msg_hdr->length) ||
- (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
- hddLog(LOGE,
- FL("Invalid length (%d) in channel info request"),
- msg_hdr->length);
- send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
- OEM_ERR_INVALID_MESSAGE_LENGTH);
- return -EPERM;
- }
- oem_process_channel_info_req_msg(msg_hdr->length,
- (char *)((char*)msg_hdr + sizeof(tAniMsgHdr)));
+ case ANI_MSG_SET_OEM_CAP_REQ:
+ ret = oem_set_cap_req_handler(pHddCtx, msg_hdr, nlh);
+ break;
+
+ case ANI_MSG_GET_OEM_CAP_REQ:
+ ret = oem_get_cap_req_handler(pHddCtx, msg_hdr, nlh);
break;
default:
@@ -807,7 +1084,7 @@ static int oem_msg_callback(struct sk_buff *skb)
OEM_ERR_INVALID_MESSAGE_TYPE);
return -EPERM;
}
- return 0;
+ return ret;
}
static int __oem_msg_callback(struct sk_buff *skb)
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 93488174c453..e7d356e49bc4 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -250,6 +250,21 @@ struct sme_ap_find_request_req{
};
#endif /* WLAN_FEATURE_APFIND */
+/**
+ * struct sme_oem_capability - 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 sme_oem_capability {
+ uint32_t ftm_rr:1;
+ uint32_t lci_capability:1;
+ uint32_t reserved1:30;
+ uint32_t reserved2;
+};
+
/*-------------------------------------------------------------------------
Function declarations and documentation
------------------------------------------------------------------------*/
@@ -1953,6 +1968,11 @@ eHalStatus sme_OemDataReq(tHalHandle hHal,
tOemDataReqConfig *,
tANI_U32 *pOemDataReqID);
+VOS_STATUS sme_oem_update_capability(tHalHandle hHal,
+ struct sme_oem_capability *cap);
+VOS_STATUS sme_oem_get_capability(tHalHandle hHal,
+ struct sme_oem_capability *cap);
+
#endif /*FEATURE_OEM_DATA_SUPPORT*/
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index a5a56c8eaee3..044ac94fecde 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -18677,7 +18677,6 @@ VOS_STATUS sme_set_btc_bt_wlan_interval_page_sap(uint32_t bt_interval,
return vos_status;
}
-
/**
* sme_send_disassoc_req_frame - send disassoc req
* @hal: handler to hal
@@ -18800,3 +18799,56 @@ eHalStatus sme_enable_disable_chanavoidind_event(tHalHandle hal,
return eHAL_STATUS_FAILURE;
}
+/**
+ * sme_oem_update_capability() - update UMAC's oem related capability.
+ * @hal: Handle returned by mac_open
+ * @oem_cap: pointer to oem_capability
+ *
+ * This function updates OEM capability to UMAC. Currently RTT
+ * related capabilities are updated. More capabilities can be
+ * added in future.
+ *
+ * Return: VOS_STATUS
+ */
+VOS_STATUS sme_oem_update_capability(tHalHandle hal,
+ struct sme_oem_capability *cap)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pmac = PMAC_STRUCT(hal);
+ uint8_t *bytes;
+
+ bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability;
+
+ if (cap->ftm_rr)
+ bytes[4] |= RM_CAP_FTM_RANGE_REPORT;
+ if (cap->lci_capability)
+ bytes[4] |= RM_CAP_CIVIC_LOC_MEASUREMENT;
+
+ return status;
+}
+
+/**
+ * sme_oem_get_capability() - get oem capability
+ * @hal: Handle returned by mac_open
+ * @oem_cap: pointer to oem_capability
+ *
+ * This function is used to get the OEM capability from UMAC.
+ * Currently RTT related capabilities are received. More
+ * capabilities can be added in future.
+ *
+ * Return: VOS_STATUS
+ */
+VOS_STATUS sme_oem_get_capability(tHalHandle hal,
+ struct sme_oem_capability *cap)
+{
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal pmac = PMAC_STRUCT(hal);
+ uint8_t *bytes;
+
+ bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability;
+
+ cap->ftm_rr = bytes[4] & RM_CAP_FTM_RANGE_REPORT;
+ cap->lci_capability = bytes[4] & RM_CAP_CIVIC_LOC_MEASUREMENT;
+
+ return status;
+}
diff --git a/CORE/SVC/inc/wlan_ptt_sock_svc.h b/CORE/SVC/inc/wlan_ptt_sock_svc.h
index 9a2c71884b9b..a662d95255f3 100644
--- a/CORE/SVC/inc/wlan_ptt_sock_svc.h
+++ b/CORE/SVC/inc/wlan_ptt_sock_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -67,6 +67,10 @@
#define ANI_MSG_CHANNEL_INFO_RSP (ANI_DRIVER_MSG_START + 5)
#define ANI_MSG_OEM_ERROR (ANI_DRIVER_MSG_START + 6)
#define ANI_MSG_PEER_STATUS_IND (ANI_DRIVER_MSG_START + 7)
+#define ANI_MSG_SET_OEM_CAP_REQ (ANI_DRIVER_MSG_START + 8)
+#define ANI_MSG_SET_OEM_CAP_RSP (ANI_DRIVER_MSG_START + 9)
+#define ANI_MSG_GET_OEM_CAP_REQ (ANI_DRIVER_MSG_START + 10)
+#define ANI_MSG_GET_OEM_CAP_RSP (ANI_DRIVER_MSG_START + 11)
#define ANI_MAX_RADIOS 3
#define ANI_NL_MSG_OK 0