qcacmn: Implement WIFI_POS commands

Implement following commands for WIFI_POS:
1) ANI_MSG_APP_REG_REQ
2) ANI_MSG_CHANNEL_INFO_REQ
3) ANI_MSG_SET_OEM_CAP_REQ
4) ANI_MSG_GET_OEM_CAP_REQ
5) ANI_MSG_OEM_DATA_REQ
6) ANI_MSG_PEER_STATUS_IND

Change-Id: I7e3b502660b169f4cdb654cb5f433446a24d2421
CRs-Fixed: 2003488
This commit is contained in:
Naveen Rawat
2017-03-17 19:35:46 -07:00
committed by Sandeep Puligilla
parent 18ceca16b7
commit 922724f2db
10 changed files with 776 additions and 93 deletions

View File

@@ -37,10 +37,126 @@
#include "os_if_wifi_pos.h" #include "os_if_wifi_pos.h"
#include "wifi_pos_api.h" #include "wifi_pos_api.h"
#include "wlan_cfg80211.h" #include "wlan_cfg80211.h"
#include "wlan_objmgr_psoc_obj.h"
#ifdef CNSS_GENL #ifdef CNSS_GENL
#include <net/cnss_nl.h> #include <net/cnss_nl.h>
#endif #endif
/**
* os_if_wifi_pos_send_rsp() - send oem registration response
*
* This function sends oem message to registered application process
*
* Return: none
*/
static void os_if_wifi_pos_send_rsp(uint32_t pid, uint32_t rsp_msg_type,
uint32_t buf_len, uint8_t *buf)
{
tAniMsgHdr *aniHdr;
struct sk_buff *skb;
struct nlmsghdr *nlh;
/* OEM msg is always to a specific process and cannot be a broadcast */
if (pid == 0) {
cfg80211_err("invalid dest pid");
return;
}
skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len), GFP_ATOMIC);
if (skb == NULL) {
cfg80211_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 = rsp_msg_type;
qdf_mem_copy(&aniHdr[1], buf, buf_len);
aniHdr->length = buf_len;
skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len));
cfg80211_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,
struct wifi_pos_req_msg *req)
{
tAniMsgHdr *msg_hdr;
struct nlattr *tb[CLD80211_ATTR_MAX + 1];
if (nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) {
cfg80211_err("invalid data in request");
return OEM_ERR_INVALID_MESSAGE_TYPE;
}
if (!tb[CLD80211_ATTR_DATA]) {
cfg80211_err("CLD80211_ATTR_DATA not present");
return OEM_ERR_INVALID_MESSAGE_TYPE;
}
msg_hdr = (tAniMsgHdr *)nla_data(tb[CLD80211_ATTR_DATA]);
if (!msg_hdr) {
cfg80211_err("msg_hdr null");
return OEM_ERR_NULL_MESSAGE_HEADER;
}
req->msg_type = msg_hdr->type;
req->buf_len = msg_hdr->length;
req->buf = (uint8_t *)&msg_hdr[1];
req->pid = pid;
if (tb[CLD80211_ATTR_META_DATA]) {
req->field_info_buf = (struct wifi_pos_field_info *)
nla_data(tb[CLD80211_ATTR_META_DATA]);
req->field_info_buf_len = nla_len(tb[CLD80211_ATTR_META_DATA]);
}
return 0;
}
#else
static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req)
{
/* SKB->data contains NL msg */
/* NLMSG_DATA(nlh) contains ANI msg */
struct nlmsghdr *nlh;
tAniMsgHdr *msg_hdr;
nlh = (struct nlmsghdr *)skb->data;
if (!nlh) {
cfg80211_err("Netlink header null");
return OEM_ERR_NULL_MESSAGE_HEADER;
}
msg_hdr = NLMSG_DATA(nlh);
if (!msg_hdr) {
cfg80211_err("Message header null");
return OEM_ERR_NULL_MESSAGE_HEADER;
}
if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*msg_hdr) + msg_hdr->length)) {
cfg80211_err("nlmsg_len(%d) and animsg_len(%d) mis-match",
nlh->nlmsg_len, msg_hdr->length);
return OEM_ERR_INVALID_MESSAGE_LENGTH;
}
req->msg_type = msg_hdr->type;
req->buf_len = msg_hdr->length;
req->buf = (uint8_t *)&msg_hdr[1];
req->pid = nlh->nlmsg_pid;
return 0;
}
#endif
/** /**
* os_if_wifi_pos_callback() - callback registered with NL service socket to * os_if_wifi_pos_callback() - callback registered with NL service socket to
* process wifi pos request * process wifi pos request
@@ -52,26 +168,70 @@
static void os_if_wifi_pos_callback(const void *data, int data_len, static void os_if_wifi_pos_callback(const void *data, int data_len,
void *ctx, int pid) void *ctx, int pid)
{ {
uint8_t err;
QDF_STATUS status; QDF_STATUS status;
struct wifi_pos_req_msg req = {0}; struct wifi_pos_req_msg req = {0};
struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
cfg80211_debug("enter: pid %d", pid);
if (!psoc) { if (!psoc) {
cfg80211_err("global psoc object not registered yet."); cfg80211_err("global psoc object not registered yet.");
return; return;
} }
wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID); wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID);
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);
status = QDF_STATUS_E_INVAL;
goto release_psoc_ref;
}
/* implemention is TBD */ status = ucfg_wifi_pos_process_req(psoc, &req, os_if_wifi_pos_send_rsp);
status = ucfg_wifi_pos_process_req(psoc, &req, NULL);
if (QDF_IS_STATUS_ERROR(status)) if (QDF_IS_STATUS_ERROR(status))
cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d", cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d",
status); status);
release_psoc_ref:
wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
} }
#else
static int os_if_wifi_pos_callback(struct sk_buff *skb)
{
uint8_t err;
QDF_STATUS status;
struct wifi_pos_req_msg req = {0};
struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
cfg80211_debug("enter");
if (!psoc) {
cfg80211_err("global psoc object not registered yet.");
return -EINVAL;
}
wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID);
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);
status = QDF_STATUS_E_INVAL;
goto release_psoc_ref;
}
status = ucfg_wifi_pos_process_req(psoc, &req, os_if_wifi_pos_send_rsp);
if (QDF_IS_STATUS_ERROR(status))
cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d",
status);
release_psoc_ref:
wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
return qdf_status_to_os_return(status);
}
#endif
#ifdef CNSS_GENL
int os_if_wifi_pos_register_nl(void) int os_if_wifi_pos_register_nl(void)
{ {
int ret = register_cld_cmd_cb(WLAN_NL_MSG_OEM, int ret = register_cld_cmd_cb(WLAN_NL_MSG_OEM,
@@ -81,7 +241,14 @@ int os_if_wifi_pos_register_nl(void)
return ret; return ret;
} }
#else
int os_if_wifi_pos_register_nl(void)
{
return nl_srv_register(WLAN_NL_MSG_OEM, os_if_wifi_pos_callback);
}
#endif /* CNSS_GENL */
#ifdef CNSS_GENL
int os_if_wifi_pos_deregister_nl(void) int os_if_wifi_pos_deregister_nl(void)
{ {
int ret = deregister_cld_cmd_cb(WLAN_NL_MSG_OEM); int ret = deregister_cld_cmd_cb(WLAN_NL_MSG_OEM);
@@ -91,16 +258,11 @@ int os_if_wifi_pos_deregister_nl(void)
return ret; return ret;
} }
#else #else
int os_if_wifi_pos_register_nl(void)
{
return 0;
}
int os_if_wifi_pos_deregister_nl(void) int os_if_wifi_pos_deregister_nl(void)
{ {
return 0; return 0;
} }
#endif #endif /* CNSS_GENL */
void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac, void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac,
uint8_t peer_status, uint8_t peer_status,
@@ -109,7 +271,62 @@ void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac,
struct wifi_pos_ch_info *chan_info, struct wifi_pos_ch_info *chan_info,
enum tQDF_ADAPTER_MODE dev_mode) enum tQDF_ADAPTER_MODE dev_mode)
{ {
/* implemention TBD */ struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
struct wmi_pos_peer_status_info *peer_info;
if (!psoc) {
cfg80211_err("global wifi_pos psoc object not registered");
return;
}
if (!wifi_pos_is_app_registered(psoc) ||
wifi_pos_get_app_pid(psoc) == 0) {
cfg80211_err("app is not registered or pid is invalid");
return;
}
peer_info = qdf_mem_malloc(sizeof(*peer_info));
if (!peer_info) {
cfg80211_alert("malloc failed");
return;
}
qdf_mem_copy(peer_info->peer_mac_addr, peer_mac->bytes,
sizeof(peer_mac->bytes));
peer_info->peer_status = peer_status;
peer_info->vdev_id = session_id;
peer_info->peer_capability = peer_timing_meas_cap;
peer_info->reserved0 = 0;
/* Set 0th bit of reserved0 for STA mode */
if (QDF_STA_MODE == dev_mode)
peer_info->reserved0 |= 0x01;
if (chan_info) {
peer_info->peer_chan_info.chan_id = chan_info->chan_id;
peer_info->peer_chan_info.reserved0 = 0;
peer_info->peer_chan_info.mhz = chan_info->mhz;
peer_info->peer_chan_info.band_center_freq1 =
chan_info->band_center_freq1;
peer_info->peer_chan_info.band_center_freq2 =
chan_info->band_center_freq2;
peer_info->peer_chan_info.info = chan_info->info;
peer_info->peer_chan_info.reg_info_1 = chan_info->reg_info_1;
peer_info->peer_chan_info.reg_info_2 = chan_info->reg_info_2;
}
os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc),
ANI_MSG_PEER_STATUS_IND,
sizeof(*peer_info), (uint8_t *)peer_info);
return;
}
void os_if_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val)
{
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
wifi_pos_set_ftm_cap(psoc, val);
} }
int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,

View File

@@ -49,17 +49,44 @@ static int wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
uint8_t *data_buf, uint8_t *data_buf,
uint32_t data_len) uint32_t data_len)
{ {
struct oem_data_rsp *oem_rsp = NULL; int ret;
struct wlan_objmgr_psoc *psoc = NULL; struct oem_data_rsp oem_rsp = {0};
struct wifi_pos_psoc_priv_obj *wifi_pos_psoc;
struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL; struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL;
WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf =
(WMI_OEM_RESPONSE_EVENTID_param_tlvs *)data_buf;
if (!psoc) {
wifi_pos_err("psoc is null");
return QDF_STATUS_NOT_INITIALIZED;
}
wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc);
if (!wifi_pos_psoc) {
wifi_pos_err("wifi_pos_psoc is null");
return QDF_STATUS_NOT_INITIALIZED;
}
qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID);
wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc);
/* this will be implemented later */ /* this will be implemented later */
if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) {
wifi_pos_err("lmac callbacks not registered"); wifi_pos_err("lmac callbacks not registered");
return QDF_STATUS_NOT_INITIALIZED; ret = QDF_STATUS_NOT_INITIALIZED;
goto release_psoc_ref;
} }
return wifi_pos_rx_ops->oem_rsp_event_rx(psoc, oem_rsp); oem_rsp.rsp_len = param_buf->num_data;
oem_rsp.data = param_buf->data;
ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp);
release_psoc_ref:
wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
return ret;
} }
/** /**

View File

@@ -34,6 +34,8 @@
/* Include files */ /* Include files */
#include "qdf_types.h" #include "qdf_types.h"
#include "qdf_status.h"
#include "qdf_trace.h"
/* forward reference */ /* forward reference */
struct wlan_objmgr_psoc; struct wlan_objmgr_psoc;
@@ -134,6 +136,19 @@ struct wifi_pos_req_msg {
uint32_t field_info_buf_len; uint32_t field_info_buf_len;
}; };
/**
* ucfg_wifi_pos_process_req: ucfg API to be called from HDD/OS_IF to process a
* wifi_pos request from userspace
* @psoc: pointer to psoc object
* @req: wifi_pos request msg
* @send_rsp_cb: callback pointer required to send msg to userspace
*
* Return: status of operation
*/
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 *));
/** /**
* wifi_pos_init: initializes WIFI POS component, called by dispatcher init * wifi_pos_init: initializes WIFI POS component, called by dispatcher init
* *
@@ -276,6 +291,40 @@ void wifi_pos_set_current_dwell_time_max(struct wlan_objmgr_psoc *psoc,
QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_driver_caps *caps); struct wifi_pos_driver_caps *caps);
/**
* wifi_pos_set_ftm_cap: API to set fine timing measurement caps
* @psoc: psoc object
* @val: value to set
*
* Return: None
*/
void wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val);
/**
* wifi_pos_get_app_pid: returns oem app pid.
* @psoc: pointer to psoc object
*
* Return: oem app pid
*/
uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc);
/**
* wifi_pos_is_app_registered: indicates if oem app is registered.
* @psoc: pointer to psoc object
*
* Return: true if app is registered, false otherwise
*/
bool wifi_pos_is_app_registered(struct wlan_objmgr_psoc *psoc);
/**
* wifi_pos_get_psoc: API to get global PSOC object
*
* Since request from userspace is not associated with any vdev/pdev/psoc, this
* API is used to get global psoc object.
* Return: global psoc object.
*/
struct wlan_objmgr_psoc *wifi_pos_get_psoc(void);
#else #else
static inline QDF_STATUS wifi_pos_init(void) static inline QDF_STATUS wifi_pos_init(void)
{ {

View File

@@ -204,3 +204,56 @@ void wifi_pos_set_current_dwell_time_min(struct wlan_objmgr_psoc *psoc,
wifi_pos_psoc->current_dwell_time_max = val; wifi_pos_psoc->current_dwell_time_max = val;
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
} }
void wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val)
{
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;
}
qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
wifi_pos_psoc->fine_time_meas_cap = val;
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
}
uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc)
{
uint32_t app_pid;
struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
wifi_pos_get_psoc_priv_obj(psoc);
if (!wifi_pos_psoc) {
wifi_pos_err("wifi_pos priv obj is null");
return 0;
}
qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
app_pid = wifi_pos_psoc->app_pid;
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
return app_pid;
}
bool wifi_pos_is_app_registered(struct wlan_objmgr_psoc *psoc)
{
bool is_app_registered;
struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
wifi_pos_get_psoc_priv_obj(psoc);
if (!wifi_pos_psoc) {
wifi_pos_err("wifi_pos priv obj is null");
return false;
}
qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
is_app_registered = wifi_pos_psoc->is_app_registered;
qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
return is_app_registered;
}

View File

@@ -31,7 +31,7 @@
* wifi positioning to initialize and de-initialize the component. * wifi positioning to initialize and de-initialize the component.
*/ */
#include "target_if_wifi_pos.h" #include "target_if_wifi_pos.h"
#include "os_if_wifi_pos.h" #include "wifi_pos_oem_interface_i.h"
#include "wifi_pos_utils_i.h" #include "wifi_pos_utils_i.h"
#include "wifi_pos_api.h" #include "wifi_pos_api.h"
#include "wifi_pos_main_i.h" #include "wifi_pos_main_i.h"
@@ -39,6 +39,9 @@
#include "wlan_objmgr_cmn.h" #include "wlan_objmgr_cmn.h"
#include "wlan_objmgr_global_obj.h" #include "wlan_objmgr_global_obj.h"
#include "wlan_objmgr_psoc_obj.h" #include "wlan_objmgr_psoc_obj.h"
#include "wlan_objmgr_pdev_obj.h"
#include "wlan_objmgr_vdev_obj.h"
#include "wlan_ptt_sock_svc.h"
#ifdef UMAC_REG_COMPONENT #ifdef UMAC_REG_COMPONENT
/* enable this when regulatory component gets merged */ /* enable this when regulatory component gets merged */
@@ -47,6 +50,15 @@
struct regulatory_channel; struct regulatory_channel;
#endif #endif
/*
* obj mgr api to iterate over vdevs does not provide a direct array or vdevs,
* rather takes a callback that is called for every vdev. wifi pos needs to
* store device mode and vdev id of all active vdevs and provide this info to
* user space as part of APP registration response. due to this, vdev_idx is
* used to identify how many vdevs have been populated by obj manager API.
*/
static uint32_t vdev_idx;
/** /**
* wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg
* @psoc: psoc object * @psoc: psoc object
@@ -59,6 +71,263 @@ static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
return true; return true;
} }
static int wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req)
{
uint8_t idx;
uint32_t sub_type = 0;
uint32_t channel_mhz = 0;
void *pdev_id = NULL;
uint32_t offset;
struct oem_data_req data_req;
struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
wifi_pos_debug("Received data req pid(%d), len(%d)",
req->pid, req->buf_len);
/* look for fields */
if (req->field_info_buf)
for (idx = 0; idx < req->field_info_buf->count; idx++) {
offset = req->field_info_buf->fields[idx].offset;
/*
* replace following reads with read_api based on
* length
*/
if (req->field_info_buf->fields[idx].id ==
WMIRTT_FIELD_ID_oem_data_sub_type) {
sub_type = *((uint32_t *)&req->buf[offset]);
continue;
}
if (req->field_info_buf->fields[idx].id ==
WMIRTT_FIELD_ID_channel_mhz) {
channel_mhz = *((uint32_t *)&req->buf[offset]);
continue;
}
if (req->field_info_buf->fields[idx].id ==
WMIRTT_FIELD_ID_pdev) {
pdev_id = &req->buf[offset];
continue;
}
}
switch (sub_type) {
case TARGET_OEM_CAPABILITY_REQ:
/* TBD */
break;
case TARGET_OEM_CONFIGURE_LCR:
/* TBD */
break;
case TARGET_OEM_CONFIGURE_LCI:
/* TBD */
break;
case TARGET_OEM_MEASUREMENT_REQ:
/* TBD */
break;
case TARGET_OEM_CONFIGURE_FTMRR:
/* TBD */
break;
case TARGET_OEM_CONFIGURE_WRU:
/* TBD */
break;
default:
wifi_pos_debug("invalid sub type or not passed");
/*
* this is legacy MCL operation. pass whole msg to firmware as
* it is.
*/
tx_ops = target_if_wifi_pos_get_txops(psoc);
data_req.data_len = req->buf_len;
data_req.data = req->buf;
tx_ops->data_req_tx(psoc, &data_req);
break;
}
return 0;
}
static int wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req)
{
int error_code;
struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
wifi_pos_get_psoc_priv_obj(psoc);
struct wifi_pos_user_defined_caps *caps =
(struct wifi_pos_user_defined_caps *)req->buf;
wifi_pos_debug("Received set cap req pid(%d), len(%d)",
req->pid, req->buf_len);
wifi_pos_obj->ftm_rr = caps->ftm_rr;
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,
sizeof(error_code),
(uint8_t *)&error_code);
return 0;
}
static int wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req)
{
struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
wifi_pos_get_psoc_priv_obj(psoc);
wifi_pos_debug("Received get cap req pid(%d), len(%d)",
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,
sizeof(cap_rsp),
(uint8_t *)&cap_rsp);
return 0;
}
static int wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req)
{
uint8_t idx;
uint8_t *buf;
uint32_t len;
uint8_t *channels = req->buf;
uint32_t num_ch = req->buf_len;
struct wifi_pos_ch_info_rsp *ch_info;
struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
wifi_pos_get_psoc_priv_obj(psoc);
wifi_pos_debug("Received ch info req pid(%d), len(%d)",
req->pid, req->buf_len);
len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) * num_ch;
buf = qdf_mem_malloc(len);
if (!buf) {
wifi_pos_alert("malloc failed");
return -ENOMEM;
}
/* First byte of message body will have num of channels */
buf[0] = num_ch;
ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
for (idx = 0; idx < num_ch; idx++) {
ch_info[idx].chan_id = channels[idx];
ch_info[idx].reserved0 = 0;
#ifdef UMAC_REG_COMPONENT
/*
* please note that this is feature macro temp and will go away
* once regulatory component gets merged:
* identify regulatory API to get following information
*/
ch_info[idx].mhz = cds_chan_to_freq(channels[idx]);
ch_info[idx].band_center_freq1 = ch_info[idx].mhz;
#endif
ch_info[idx].band_center_freq2 = 0;
ch_info[idx].info = 0;
#ifdef UMAC_REG_COMPONENT
/*
* please note that this is feature macro temp and will go away
* once regulatory component gets merged:
* identify regulatory API to replace update_channel_bw_info
* and to get following information
*/
if (CHANNEL_STATE_DFS == cds_get_channel_state(channels[idx]))
WMI_SET_CHANNEL_FLAG(&ch_info[idx], WMI_CHAN_FLAG_DFS);
#endif
ch_info[idx].reg_info_1 = 0;
ch_info[idx].reg_info_2 = 0;
}
wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
ANI_MSG_CHANNEL_INFO_RSP,
len, buf);
qdf_mem_free(buf);
return 0;
}
static void wifi_pos_populate_vdev_info(struct wlan_objmgr_psoc *psoc,
void *vdev, void *arg)
{
struct app_reg_rsp_vdev_info *vdev_info = arg;
wlan_vdev_obj_lock(vdev);
vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
wlan_vdev_obj_unlock(vdev);
vdev_idx++;
}
static int wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req)
{
int ret = 0;
uint8_t err = 0;
uint32_t rsp_len;
char *sign_str = NULL;
struct wifi_app_reg_rsp *app_reg_rsp;
struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
= { { 0 } };
struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
wifi_pos_get_psoc_priv_obj(psoc);
wifi_pos_err("Received App Req Req pid(%d), len(%d)",
req->pid, req->buf_len);
sign_str = (char *)req->buf;
/* Registration request is only allowed for Qualcomm Application */
if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
(strncmp(sign_str, OEM_APP_SIGNATURE_STR,
OEM_APP_SIGNATURE_LEN))) {
wifi_pos_err("Invalid signature pid(%d)", req->pid);
ret = -EPERM;
err = OEM_ERR_INVALID_SIGNATURE;
goto app_reg_failed;
}
wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
wifi_pos_obj->is_app_registered = true;
wifi_pos_obj->app_pid = req->pid;
vdev_idx = 0;
wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
wifi_pos_populate_vdev_info,
vdevs_info, 1, WLAN_WIFI_POS_ID);
rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
+ sizeof(uint8_t);
app_reg_rsp = qdf_mem_malloc(rsp_len);
if (!app_reg_rsp) {
wifi_pos_alert("malloc failed");
ret = -ENOMEM;
err = OEM_ERR_NULL_CONTEXT;
goto app_reg_failed;
}
app_reg_rsp->num_inf = vdev_idx;
qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
if (!vdev_idx)
wifi_pos_debug("no active vdev");
vdev_idx = 0;
wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP,
rsp_len, (uint8_t *)app_reg_rsp);
qdf_mem_free(app_reg_rsp);
return ret;
app_reg_failed:
wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR,
sizeof(err), &err);
return ret;
}
/** /**
* wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
* @wmi_msg: wmi type request msg * @wmi_msg: wmi type request msg
@@ -68,9 +337,23 @@ static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc, static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_req_msg *req) struct wifi_pos_req_msg *req)
{ {
/* actual implementation of cmds start here */ wifi_pos_debug("enter: msg_type: %d", req->msg_type);
/* TBD - decide if ANI_MSG_OEM_DATA_REQ goest to MC thread or not */ switch (req->msg_type) {
return QDF_STATUS_SUCCESS; case ANI_MSG_APP_REG_REQ:
return wifi_pos_process_app_reg_req(psoc, req);
case ANI_MSG_OEM_DATA_REQ:
return wifi_pos_process_data_req(psoc, req);
case ANI_MSG_CHANNEL_INFO_REQ:
return wifi_pos_process_ch_info_req(psoc, req);
case ANI_MSG_SET_OEM_CAP_REQ:
return wifi_pos_process_set_cap_req(psoc, req);
case ANI_MSG_GET_OEM_CAP_REQ:
return wifi_pos_process_get_cap_req(psoc, req);
default:
wifi_pos_err("invalid request type");
break;
}
return 0;
} }
/** /**
@@ -190,8 +473,10 @@ int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
wifi_pos_debug("sending oem data rsp, len: %d to pid: %d", wifi_pos_debug("sending oem data rsp, len: %d to pid: %d",
oem_rsp->rsp_len, wifi_pos_obj->app_pid); oem_rsp->rsp_len, wifi_pos_obj->app_pid);
wifi_pos_obj->wifi_pos_send_rsp(psoc, ANI_MSG_OEM_DATA_RSP, wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
oem_rsp->rsp_len, oem_rsp->data); ANI_MSG_OEM_DATA_RSP,
oem_rsp->rsp_len,
oem_rsp->data);
return 0; return 0;
} }

View File

@@ -22,4 +22,45 @@
#ifndef _WIFI_POS_OEM_INTERFACE_H_ #ifndef _WIFI_POS_OEM_INTERFACE_H_
#define _WIFI_POS_OEM_INTERFACE_H_ #define _WIFI_POS_OEM_INTERFACE_H_
/* Include files */
#include "qdf_types.h"
#include "qdf_status.h"
#include "wlan_objmgr_cmn.h"
#define TARGET_OEM_CAPABILITY_REQ 0x01
#define TARGET_OEM_CAPABILITY_RSP 0x02
#define TARGET_OEM_MEASUREMENT_REQ 0x03
#define TARGET_OEM_MEASUREMENT_RSP 0x04
#define TARGET_OEM_ERROR_REPORT_RSP 0x05
#define TARGET_OEM_NAN_MEAS_REQ 0x06
#define TARGET_OEM_NAN_MEAS_RSP 0x07
#define TARGET_OEM_NAN_PEER_INFO 0x08
#define TARGET_OEM_CONFIGURE_LCR 0x09
#define TARGET_OEM_CONFIGURE_LCI 0x0A
#define TARGET_OEM_CONFIGURE_WRU 0x80
#define TARGET_OEM_CONFIGURE_FTMRR 0x81
struct wifi_pos_field {
uint32_t id;
uint32_t offset;
uint32_t length;
};
struct wifi_pos_field_info {
uint32_t count;
struct wifi_pos_field fields[1];
};
/**
* enum WMIRTT_FIELD_ID - identifies which field is being specified
* @WMIRTT_FIELD_ID_oem_data_sub_type: oem data req sub type
* @WMIRTT_FIELD_ID_channel_mhz: channel mhz info
* @WMIRTT_FIELD_ID_pdev: pdev info
*/
enum WMIRTT_FIELD_ID {
WMIRTT_FIELD_ID_oem_data_sub_type,
WMIRTT_FIELD_ID_channel_mhz,
WMIRTT_FIELD_ID_pdev,
};
#endif #endif

View File

@@ -23,22 +23,51 @@
#include "wifi_pos_utils_i.h" #include "wifi_pos_utils_i.h"
#include "wifi_pos_api.h" #include "wifi_pos_api.h"
#include "wifi_pos_ucfg_i.h" #include "wifi_pos_ucfg_i.h"
#include "wlan_ptt_sock_svc.h"
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 *, void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *))
uint32_t, uint32_t, uint8_t *))
{ {
uint8_t err;
uint32_t app_pid;
QDF_STATUS status;
bool is_app_registered;
struct wifi_pos_psoc_priv_obj *wifi_pos_psoc_obj = struct wifi_pos_psoc_priv_obj *wifi_pos_psoc_obj =
wifi_pos_get_psoc_priv_obj(psoc); wifi_pos_get_psoc_priv_obj(psoc);
wifi_pos_debug("enter");
if (!wifi_pos_psoc_obj) { if (!wifi_pos_psoc_obj) {
wifi_pos_err("wifi_pos_psoc_obj is null"); wifi_pos_err("wifi_pos_psoc_obj is null");
return QDF_STATUS_E_NULL_VALUE; return QDF_STATUS_E_NULL_VALUE;
} }
/* assign callback pointer to be called for rsp or error */ qdf_spin_lock_bh(&wifi_pos_psoc_obj->wifi_pos_lock);
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;
app_pid = wifi_pos_psoc_obj->app_pid;
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);
status = QDF_STATUS_E_NULL_VALUE;
goto unlock_and_exit;
}
return wifi_pos_psoc_obj->wifi_pos_req_handler(psoc, req); if (req->msg_type != ANI_MSG_APP_REG_REQ &&
(!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);
status = QDF_STATUS_E_INVAL;
goto unlock_and_exit;
}
status = wifi_pos_psoc_obj->wifi_pos_req_handler(psoc, req);
unlock_and_exit:
qdf_spin_unlock_bh(&wifi_pos_psoc_obj->wifi_pos_lock);
return status;
} }

View File

@@ -42,7 +42,6 @@ struct wifi_pos_req_msg;
*/ */
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)(struct wlan_objmgr_psoc *, void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *));
uint32_t, uint32_t, uint8_t *));
#endif /* _WIFI_POS_UCFG_H_ */ #endif /* _WIFI_POS_UCFG_H_ */

View File

@@ -74,41 +74,3 @@ struct wifi_pos_psoc_priv_obj *wifi_pos_get_psoc_priv_obj(
return obj; return obj;
} }
bool wifi_pos_is_app_registered(struct wlan_objmgr_psoc *psoc)
{
struct wifi_pos_psoc_priv_obj *obj;
if (!psoc) {
wifi_pos_err("psoc is null");
return false;
}
obj = wifi_pos_get_psoc_priv_obj(psoc);
if (!obj) {
wifi_pos_err("wifi_pos priv obj is null");
return false;
}
return obj->is_app_registered;
}
uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc)
{
struct wifi_pos_psoc_priv_obj *obj;
if (!psoc) {
wifi_pos_err("psoc is null");
return 0;
}
obj = wifi_pos_get_psoc_priv_obj(psoc);
if (!obj) {
wifi_pos_err("wifi_pos priv obj is null");
return 0;
}
return obj->app_pid;
}

View File

@@ -41,6 +41,7 @@
#include "qdf_trace.h" #include "qdf_trace.h"
struct wlan_objmgr_psoc; struct wlan_objmgr_psoc;
struct wifi_pos_req_msg;
#define wifi_pos_log(level, args...) \ #define wifi_pos_log(level, args...) \
QDF_TRACE(QDF_MODULE_ID_WIFIPOS, level, ## args) QDF_TRACE(QDF_MODULE_ID_WIFIPOS, level, ## args)
@@ -70,6 +71,28 @@ struct wlan_objmgr_psoc;
#define OEM_DATA_RSP_SIZE 1724 #define OEM_DATA_RSP_SIZE 1724
#endif #endif
/**
* struct app_reg_rsp_vdev_info - vdev info struct
* @dev_mode: device mode
* @vdev_id: vdev id
*
*/
struct qdf_packed app_reg_rsp_vdev_info {
uint8_t dev_mode;
uint8_t vdev_id;
};
/**
* struct wifi_app_reg_rsp - app registration response struct
* @num_inf: number of interfaces active
* @vdevs: array indicating all active vdev's information
*
*/
struct qdf_packed wifi_app_reg_rsp {
uint8_t num_inf;
struct app_reg_rsp_vdev_info vdevs[1];
};
/** /**
* struct oem_data_req - data request to be sent to firmware * struct oem_data_req - data request to be sent to firmware
* @data_len: len of data * @data_len: len of data
@@ -93,7 +116,7 @@ struct oem_data_rsp {
}; };
/** /**
* typedef wifi_pos_driver_version - Driver version identifier (w.x.y.z) * struct wifi_pos_driver_version - Driver version identifier (w.x.y.z)
* @major: Version ID major number * @major: Version ID major number
* @minor: Version ID minor number * @minor: Version ID minor number
* @patch: Version ID patch number * @patch: Version ID patch number
@@ -134,13 +157,29 @@ struct qdf_packed wifi_pos_driver_caps {
uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS]; uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS];
}; };
struct wifi_pos_req_msg { /**
uint32_t msg_type; * struct wifi_pos_user_defined_caps - OEM capability to be exchanged between host
uint32_t pid; * and userspace
uint8_t *buf; * @ftm_rr: FTM range report capability bit
uint32_t buf_len; * @lci_capability: LCI capability bit
struct wifi_pos_field_info *field_info_buf; * @reserved1: reserved
uint32_t field_info_buf_len; * @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 - capabilites 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;
}; };
/** /**
@@ -184,9 +223,7 @@ struct wifi_pos_psoc_priv_obj {
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)(struct wlan_objmgr_psoc *psoc, void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
uint32_t rsp_msg_type, uint32_t buf_len,
uint8_t *buf);
}; };
/** /**
@@ -235,14 +272,6 @@ void wifi_pos_clear_psoc(void);
QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
struct wifi_pos_driver_caps *caps); struct wifi_pos_driver_caps *caps);
/**
* wifi_pos_is_app_registered: indicates if oem app is registered.
* @psoc: pointer to psoc object
*
* Return: true if app is registered, false otherwise
*/
bool wifi_pos_is_app_registered(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
@@ -252,20 +281,12 @@ bool wifi_pos_is_app_registered(struct wlan_objmgr_psoc *psoc);
uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc); uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc);
/** /**
* wifi_pos_lock: acquires wifi_pos lock * wifi_pos_is_app_registered: indicates if oem app is registered.
* @psoc: pointer to psoc object * @psoc: pointer to psoc object
* *
* Return: None * Return: true if app is registered, false otherwise
*/ */
void wifi_pos_lock(struct wlan_objmgr_psoc *psoc); bool wifi_pos_is_app_registered(struct wlan_objmgr_psoc *psoc);
/**
* wifi_pos_unlock: releases wifi_pos lock
* @psoc: pointer to psoc object
*
* Return: None
*/
void wifi_pos_unlock(struct wlan_objmgr_psoc *psoc);
#endif /* _WIFI_POS_UTILS_H_ */ #endif /* _WIFI_POS_UTILS_H_ */
#endif /* WIFI_POS_CONVERGED */ #endif /* WIFI_POS_CONVERGED */