From a8423167a9ca8289e00296454b862a5eb5ac9528 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Mon, 6 Mar 2017 15:59:31 -0800 Subject: [PATCH] qcacmn: Implement Wifi Positioning Init/Deinit Implement Init/Deinit for the WIFI Positioning component. Change-Id: Iec0f4199935f63f7019de5ae16fc760817165954 CRs-Fixed: 2003488 --- os_if/linux/wifi_pos/inc/os_if_wifi_pos.h | 96 +++++++++ os_if/linux/wifi_pos/src/os_if_wifi_pos.c | 91 ++++++++ umac/wifi_pos/inc/wifi_pos_api.h | 241 ++++++++++++++++++++++ umac/wifi_pos/src/wifi_pos_api.c | 164 +++++++++++++++ umac/wifi_pos/src/wifi_pos_main.c | 213 +++++++++++++++++++ umac/wifi_pos/src/wifi_pos_main_i.h | 31 ++- umac/wifi_pos/src/wifi_pos_ucfg.c | 21 ++ umac/wifi_pos/src/wifi_pos_ucfg_i.h | 23 ++- umac/wifi_pos/src/wifi_pos_utils.c | 92 +++++++++ umac/wifi_pos/src/wifi_pos_utils_i.h | 237 ++++++++++++++++++++- 10 files changed, 1206 insertions(+), 3 deletions(-) diff --git a/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h b/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h index dd81433e5c..570241e67b 100644 --- a/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h +++ b/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h @@ -32,4 +32,100 @@ #ifndef _OS_IF_WIFI_POS_H_ #define _OS_IF_WIFI_POS_H_ +#include "qdf_types.h" +#include "qdf_status.h" + + +/* forward declaration */ +struct wifi_pos_ch_info; +struct wlan_objmgr_psoc; +struct wifi_pos_driver_caps; + +#ifdef WIFI_POS_CONVERGED +/** + * os_if_wifi_pos_register_nl() - abstration API to register callback with GENL + * socket. + * + * Return: status of operation + */ +int os_if_wifi_pos_register_nl(void); + +/** + * os_if_wifi_pos_deregister_nl() - abstration API to deregister callback with + * GENL socket. + * + * Return: status of operation + */ +int os_if_wifi_pos_deregister_nl(void); + +/** + * os_if_wifi_pos_send_peer_status() - Function to send peer status to a + * registered application + * @peer_mac: MAC address of peer + * @peer_status: ePeerConnected or ePeerDisconnected + * @peer_timing_meas_cap: 0: RTT/RTT2, 1: RTT3. Default is 0 + * @session_id: SME session id, i.e. vdev_id + * @chan_info: operating channel information + * @dev_mode: dev mode for which indication is sent + * + * Return: none + */ +void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac, + uint8_t peer_status, + uint8_t peer_timing_meas_cap, + uint8_t session_id, + struct wifi_pos_ch_info *chan_info, + enum tQDF_ADAPTER_MODE dev_mode); + +/** + * os_if_wifi_pos_set_ftm_cap() - set ftm capabilities + * @psoc: psoc object + * @val: value to set + * + * Return: none + */ +void os_if_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val); + +/** + * os_if_wifi_pos_populate_caps() - populate oem capabilities + * @psoc: psoc object + * @caps: pointer to populate the capabilities + * + * Return: error code + */ +int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps); +#else +static inline int os_if_wifi_pos_register_nl(void) +{ + return 0; +} + +static inline int os_if_wifi_pos_deregister_nl(void) +{ + return 0; +} + +static inline void os_if_wifi_pos_send_peer_status( + struct qdf_mac_addr *peer_mac, + uint8_t peer_status, + uint8_t peer_timing_meas_cap, + uint8_t session_id, + struct wifi_pos_ch_info *chan_info, + enum tQDF_ADAPTER_MODE dev_mode) +{ +} + +static inline void os_if_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, + uint32_t val) +{ +} + +static inline int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps) +{ + return 0; +} +#endif + #endif /* _OS_IF_WIFI_POS_H_ */ diff --git a/os_if/linux/wifi_pos/src/os_if_wifi_pos.c b/os_if/linux/wifi_pos/src/os_if_wifi_pos.c index cd87d9b7ab..e88c106042 100644 --- a/os_if/linux/wifi_pos/src/os_if_wifi_pos.c +++ b/os_if/linux/wifi_pos/src/os_if_wifi_pos.c @@ -31,3 +31,94 @@ * component's os_if layer. */ +#include "wlan_nlink_srv.h" +#include "wlan_ptt_sock_svc.h" +#include "wlan_nlink_common.h" +#include "os_if_wifi_pos.h" +#include "wifi_pos_api.h" +#include "wlan_cfg80211.h" +#ifdef CNSS_GENL +#include +#endif + +/** + * os_if_wifi_pos_callback() - callback registered with NL service socket to + * process wifi pos request + * @skb: request message sk_buff + * + * Return: status of operation + */ +#ifdef CNSS_GENL +static void os_if_wifi_pos_callback(const void *data, int data_len, + void *ctx, int pid) +{ + QDF_STATUS status; + struct wifi_pos_req_msg req = {0}; + struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); + + if (!psoc) { + cfg80211_err("global psoc object not registered yet."); + return; + } + + wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID); + + /* implemention is TBD */ + status = ucfg_wifi_pos_process_req(psoc, &req, NULL); + if (QDF_IS_STATUS_ERROR(status)) + cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d", + status); + + wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); +} + +int os_if_wifi_pos_register_nl(void) +{ + int ret = register_cld_cmd_cb(WLAN_NL_MSG_OEM, + os_if_wifi_pos_callback, NULL); + if (ret) + cfg80211_err("register_cld_cmd_cb failed") + + return ret; +} + +int os_if_wifi_pos_deregister_nl(void) +{ + int ret = deregister_cld_cmd_cb(WLAN_NL_MSG_OEM); + if (ret) + cfg80211_err("deregister_cld_cmd_cb failed") + + return ret; +} +#else +int os_if_wifi_pos_register_nl(void) +{ + return 0; +} + +int os_if_wifi_pos_deregister_nl(void) +{ + return 0; +} +#endif + +void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac, + uint8_t peer_status, + uint8_t peer_timing_meas_cap, + uint8_t session_id, + struct wifi_pos_ch_info *chan_info, + enum tQDF_ADAPTER_MODE dev_mode) +{ + /* implemention TBD */ +} + +int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps) +{ + if (!psoc || !caps) { + cfg80211_err("psoc or caps buffer is null"); + return -EINVAL; + } + + return qdf_status_to_os_return(wifi_pos_populate_caps(psoc, caps)); +} diff --git a/umac/wifi_pos/inc/wifi_pos_api.h b/umac/wifi_pos/inc/wifi_pos_api.h index 306b820c51..5c9eb0dbe0 100644 --- a/umac/wifi_pos/inc/wifi_pos_api.h +++ b/umac/wifi_pos/inc/wifi_pos_api.h @@ -32,4 +32,245 @@ #ifndef _WIFI_POS_API_H_ #define _WIFI_POS_API_H_ +/* Include files */ +#include "qdf_types.h" + +/* forward reference */ +struct wlan_objmgr_psoc; +struct wifi_pos_driver_caps; + +#ifdef WIFI_POS_CONVERGED +/** + * enum oem_err_msg - err msg returned to user space + * @OEM_ERR_NULL_CONTEXT: NULL context + * @OEM_ERR_APP_NOT_REGISTERED: OEM App is not registered + * @OEM_ERR_INVALID_SIGNATURE: Invalid signature + * @OEM_ERR_NULL_MESSAGE_HEADER: Invalid message header + * @OEM_ERR_INVALID_MESSAGE_TYPE: Invalid message type + * @OEM_ERR_INVALID_MESSAGE_LENGTH: Invalid length in message body + */ +enum oem_err_msg { + OEM_ERR_NULL_CONTEXT = 1, + OEM_ERR_APP_NOT_REGISTERED, + OEM_ERR_INVALID_SIGNATURE, + OEM_ERR_NULL_MESSAGE_HEADER, + OEM_ERR_INVALID_MESSAGE_TYPE, + OEM_ERR_INVALID_MESSAGE_LENGTH +}; + +/* this struct is needed since MLME is not converged yet */ +struct wifi_pos_ch_info { + uint8_t chan_id; + uint32_t mhz; + uint32_t band_center_freq1; + uint32_t band_center_freq2; + uint32_t info; + uint32_t reg_info_1; + uint32_t reg_info_2; + uint8_t nss; + uint32_t rate_flags; + uint8_t sec_ch_offset; + uint32_t ch_width; +}; + +/** + * typedef wifi_pos_ch_info_rsp - Channel information + * @chan_id: channel id + * @reserved0: reserved for padding and future use + * @mhz: primary 20 MHz channel frequency in mhz + * @band_center_freq1: Center frequency 1 in MHz + * @band_center_freq2: Center frequency 2 in MHz, valid only for 11ac + * VHT 80+80 mode + * @info: channel info + * @reg_info_1: regulatory information field 1 which contains min power, + * max power, reg power and reg class id + * @reg_info_2: regulatory information field 2 which contains antennamax + */ +struct qdf_packed wifi_pos_ch_info_rsp { + uint32_t chan_id; + uint32_t reserved0; + uint32_t mhz; + uint32_t band_center_freq1; + uint32_t band_center_freq2; + uint32_t info; + uint32_t reg_info_1; + uint32_t reg_info_2; +}; + +/** + * struct wmi_pos_peer_status_info - Status information for a given peer + * @peer_mac_addr: peer mac address + * @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED + * @vdev_id: vdev_id for the peer mac + * @peer_capability: peer capability: 0: RTT/RTT2, 1: RTT3. Default is 0 + * @reserved0: reserved0 + * @peer_chan_info: channel info on which peer is connected + */ +struct qdf_packed wmi_pos_peer_status_info { + uint8_t peer_mac_addr[ETH_ALEN]; + uint8_t peer_status; + uint8_t vdev_id; + uint32_t peer_capability; + uint32_t reserved0; + struct wifi_pos_ch_info_rsp peer_chan_info; +}; + +/** + * struct wifi_pos_req_msg - wifi pos request struct + * @msg_type: message type + * @pid: process id + * @buf: request buffer + * @buf_len: request buffer length + * @field_info_buf: buffer containing field info + * @field_info_buf_len: length of field info buffer + * + */ +struct wifi_pos_req_msg { + uint32_t msg_type; + uint32_t pid; + uint8_t *buf; + uint32_t buf_len; + struct wifi_pos_field_info *field_info_buf; + uint32_t field_info_buf_len; +}; + +/** + * wifi_pos_init: initializes WIFI POS component, called by dispatcher init + * + * Return: status of operation + */ +QDF_STATUS wifi_pos_init(void); + +/** + * wifi_pos_deinit: de-initializes WIFI POS component, called by dispatcher init + * + * Return: status of operation + */ +QDF_STATUS wifi_pos_deinit(void); + +/** + * wifi_pos_set_oem_target_type: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_oem_target_type(struct wlan_objmgr_psoc *psoc, uint32_t val); + +/** + * wifi_pos_set_oem_fw_version: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_oem_fw_version(struct wlan_objmgr_psoc *psoc, uint32_t val); + +/** + * wifi_pos_set_drv_ver_major: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_drv_ver_major(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * wifi_pos_set_drv_ver_minor: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_drv_ver_minor(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * wifi_pos_set_drv_ver_patch: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_drv_ver_patch(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * wifi_pos_set_drv_ver_build: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_drv_ver_build(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * wifi_pos_set_dwell_time_min: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_dwell_time_min(struct wlan_objmgr_psoc *psoc, uint16_t val); + +/** + * wifi_pos_set_dwell_time_max: public API to set param in wifi_pos private + * object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_dwell_time_max(struct wlan_objmgr_psoc *psoc, uint16_t val); + +/** + * wifi_pos_set_current_dwell_time_min: public API to set param in wifi_pos + * private object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_current_dwell_time_min(struct wlan_objmgr_psoc *psoc, + uint16_t val); + +/** + * wifi_pos_set_current_dwell_time_max: public API to set param in wifi_pos + * private object + * @psoc: pointer to PSOC + * @val: value to set + * + * Return: None + */ +void wifi_pos_set_current_dwell_time_max(struct wlan_objmgr_psoc *psoc, + uint16_t val); + +/** + * wifi_pos_populate_caps() - populate oem capabilities + * @psoc: psoc object + * @caps: pointer to populate the capabilities + * + * Return: error code + */ +QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps); + +#else +static inline QDF_STATUS wifi_pos_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS wifi_pos_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + +#endif + #endif diff --git a/umac/wifi_pos/src/wifi_pos_api.c b/umac/wifi_pos/src/wifi_pos_api.c index b0ae36f0f1..f50c720cac 100644 --- a/umac/wifi_pos/src/wifi_pos_api.c +++ b/umac/wifi_pos/src/wifi_pos_api.c @@ -20,3 +20,167 @@ * This file defines the APIs wifi_pos component. */ +#include "wifi_pos_api.h" +#include "wifi_pos_utils_i.h" +#include "wifi_pos_main_i.h" +#include "os_if_wifi_pos.h" +#include "target_if_wifi_pos.h" +#include "wlan_objmgr_cmn.h" +#include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_psoc_obj.h" + +QDF_STATUS wifi_pos_init(void) +{ + QDF_STATUS status; + + /* register psoc create handler functions. */ + status = wlan_objmgr_register_psoc_create_handler( + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_psoc_obj_created_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("register_psoc_create_handler failed, status: %d", + status); + return status; + } + + /* register psoc delete handler functions. */ + status = wlan_objmgr_register_psoc_destroy_handler( + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_psoc_obj_destroyed_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("register_psoc_destroy_handler failed, status: %d", + status); + } + + return status; +} + +QDF_STATUS wifi_pos_deinit(void) +{ + QDF_STATUS status; + + /* deregister psoc create handler functions. */ + status = wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_psoc_obj_created_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("unregister_psoc_create_handler failed, status: %d", + status); + return status; + } + + /* deregister psoc delete handler functions. */ + status = wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_psoc_obj_destroyed_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("unregister_psoc_destroy_handler failed, status: %d", + status); + } + return QDF_STATUS_SUCCESS; +} + +void wifi_pos_set_oem_target_type(struct wlan_objmgr_psoc *psoc, uint32_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->oem_target_type = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_oem_fw_version(struct wlan_objmgr_psoc *psoc, uint32_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->oem_fw_version = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_drv_ver_major(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->driver_version.major = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_drv_ver_minor(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->driver_version.minor = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_drv_ver_patch(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->driver_version.patch = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_drv_ver_build(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->driver_version.build = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_dwell_time_min(struct wlan_objmgr_psoc *psoc, uint16_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->allowed_dwell_time_min = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} +void wifi_pos_set_dwell_time_max(struct wlan_objmgr_psoc *psoc, uint16_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->allowed_dwell_time_max = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_current_dwell_time_max(struct wlan_objmgr_psoc *psoc, + uint16_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->current_dwell_time_max = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +void wifi_pos_set_current_dwell_time_min(struct wlan_objmgr_psoc *psoc, + uint16_t val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->current_dwell_time_max = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c index 90d24f2acf..179a5ebde1 100644 --- a/umac/wifi_pos/src/wifi_pos_main.c +++ b/umac/wifi_pos/src/wifi_pos_main.c @@ -30,3 +30,216 @@ * This file defines the important functions pertinent to * wifi positioning to initialize and de-initialize the component. */ +#include "target_if_wifi_pos.h" +#include "os_if_wifi_pos.h" +#include "wifi_pos_utils_i.h" +#include "wifi_pos_api.h" +#include "wifi_pos_main_i.h" +#include "wifi_pos_ucfg_i.h" +#include "wlan_objmgr_cmn.h" +#include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_psoc_obj.h" + +#ifdef UMAC_REG_COMPONENT +/* enable this when regulatory component gets merged */ +#include "wlan_reg_services_api.h" +/* forward declartion */ +struct regulatory_channel; +#endif + +/** + * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg + * @psoc: psoc object + * + * Return: status of operation + */ +static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc) +{ + /* this is TBD */ + return true; +} + +/** + * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req + * @wmi_msg: wmi type request msg + * + * Return: status of operation + */ +static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_req_msg *req) +{ + /* actual implementation of cmds start here */ + /* TBD - decide if ANI_MSG_OEM_DATA_REQ goest to MC thread or not */ + return QDF_STATUS_SUCCESS; +} + +/** + * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV + * type req + * @wmi_msg: wmi type request msg + * + * Return: status of operation + */ +static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_req_msg *req) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wifi_pos_psoc_obj_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list) +{ + QDF_STATUS status; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj; + + /* + * this is for WIN, if they have multiple psoc, we dont want to create + * multiple priv object. Since there is just one LOWI app registered to + * one driver, avoid 2nd private object with another psoc. + */ + if (wifi_pos_get_psoc()) { + wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object"); + return QDF_STATUS_SUCCESS; + } else { + wifi_pos_debug("setting global pos object"); + wifi_pos_set_psoc(psoc); + } + + /* initialize wifi-pos psoc priv object */ + wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj)); + if (!wifi_pos_obj) { + wifi_pos_alert("Mem alloc failed for wifi pos psoc priv obj"); + wifi_pos_clear_psoc(); + return QDF_STATUS_E_NOMEM; + } + + qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock); + /* Register TLV or non-TLV callbacks depending on target fw version */ + if (wifi_pos_get_tlv_support(psoc)) + wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback; + else + wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback; + + /* + * MGMT Rx is not handled in this phase since wifi pos only uses few + * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are + * used for 80211k. That part is not yet converged and still follows + * legacy MGMT Rx to work. Action frame in new TXRX can be registered + * at per ACTION Frame type granularity only. + */ + + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_obj, + QDF_STATUS_SUCCESS); + + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("obj attach with psoc failed with status: %d", + status); + qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock); + qdf_mem_free(wifi_pos_obj); + wifi_pos_clear_psoc(); + } + + return status; +} + +QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list) +{ + QDF_STATUS status; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL; + + if (wifi_pos_get_psoc() == psoc) { + wifi_pos_debug("deregistering wifi_pos_psoc object"); + wifi_pos_clear_psoc(); + } else { + wifi_pos_warn("un-related PSOC closed. do nothing"); + return QDF_STATUS_SUCCESS; + } + + wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc); + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos_obj is NULL"); + return QDF_STATUS_E_FAULT; + } + + status = wlan_objmgr_psoc_component_obj_detach(psoc, + WLAN_UMAC_COMP_WIFI_POS, + wifi_pos_obj); + if (status != QDF_STATUS_SUCCESS) + wifi_pos_err("wifi_pos_obj detach failed"); + + wifi_pos_debug("wifi_pos_obj deleted with status %d", status); + qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock); + qdf_mem_free(wifi_pos_obj); + + return status; +} + +#ifdef UMAC_REG_COMPONENT +/* enable this when regulatory component gets merged */ +static void get_ch_info(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps) +{ + QDF_STATUS status; + uint32_t i, num_ch = 0; + struct regulatory_channel ch_lst[OEM_CAP_MAX_NUM_CHANNELS]; + struct reg_freq_range freq_range; + + freq_range.low_freq = WLAN_REG_CH_TO_FREQ(MIN_24GHZ_CHANNEL); + freq_range.high_freq = WLAN_REG_CH_TO_FREQ(MAX_5GHZ_CHANNEL); + status = wlan_reg_get_current_chan_list_by_range(psoc, ch_lst, &num_ch); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("wlan_reg_get_current_chan_list_by_range failed"); + return; + } + + if (num_ch > OEM_CAP_MAX_NUM_CHANNELS) { + wifi_pos_err("num channels: %d more than MAX: %d", + num_ch, OEM_CAP_MAX_NUM_CHANNELS); + return; + } + + for (i = 0; i < num_ch; i++) + caps->channel_list[i] = ch_lst[i].chan_num; + + caps->num_channels = num_ch; +} +#endif + +QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_driver_caps *caps) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + wifi_pos_debug("Enter"); + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos_obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + strlcpy(caps->oem_target_signature, + OEM_TARGET_SIGNATURE, + OEM_TARGET_SIGNATURE_LEN); + caps->oem_target_type = wifi_pos_obj->oem_target_type; + caps->oem_fw_version = wifi_pos_obj->oem_fw_version; + caps->driver_version.major = wifi_pos_obj->driver_version.major; + caps->driver_version.minor = wifi_pos_obj->driver_version.minor; + caps->driver_version.patch = wifi_pos_obj->driver_version.patch; + caps->driver_version.build = wifi_pos_obj->driver_version.build; + caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min; + caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max; + caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min; + caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max; + caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc); + /* + * wifi_pos_populate_caps does not have alternate definition. + * following #ifdef will be removed once regulatory comp gets merged + */ +#ifdef UMAC_REG_COMPONENT + get_ch_info(psoc, caps); +#endif + return QDF_STATUS_SUCCESS; +} diff --git a/umac/wifi_pos/src/wifi_pos_main_i.h b/umac/wifi_pos/src/wifi_pos_main_i.h index ea19bc77ef..656ed42986 100644 --- a/umac/wifi_pos/src/wifi_pos_main_i.h +++ b/umac/wifi_pos/src/wifi_pos_main_i.h @@ -17,7 +17,7 @@ */ /** - * DOC: wifi_pos_main.h + * DOC: wifi_pos_main_i.h * This file prototyps the important functions pertinent to wifi positioning * component. */ @@ -25,4 +25,33 @@ #ifndef _WIFI_POS_MAIN_H_ #define _WIFI_POS_MAIN_H_ +/* forward reference */ +struct wlan_objmgr_psoc; + +/** + * wifi_pos_psoc_obj_created_notification: callback registered to be called when + * psoc object is created. + * @psoc: pointer to psoc object just created + * @arg_list: argument list + * + * This function will: + * create WIFI POS psoc object and attach to psoc + * register TLV vs nonTLV callbacks + * Return: status of operation + */ +QDF_STATUS wifi_pos_psoc_obj_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list); + +/** + * wifi_pos_psoc_obj_destroyed_notification: callback registered to be called + * when psoc object is destroyed. + * @psoc: pointer to psoc object just about to be destroyed + * @arg_list: argument list + * + * This function will: + * detach WIFI POS from psoc object and free + * Return: status of operation + */ +QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg_list); #endif diff --git a/umac/wifi_pos/src/wifi_pos_ucfg.c b/umac/wifi_pos/src/wifi_pos_ucfg.c index a8e6d4e88a..7752ee344f 100644 --- a/umac/wifi_pos/src/wifi_pos_ucfg.c +++ b/umac/wifi_pos/src/wifi_pos_ucfg.c @@ -20,4 +20,25 @@ * This file defines the important dispatcher APIs pertinent to * wifi positioning. */ +#include "wifi_pos_utils_i.h" +#include "wifi_pos_api.h" +#include "wifi_pos_ucfg_i.h" +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 *)) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_psoc_obj) { + wifi_pos_err("wifi_pos_psoc_obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + /* assign callback pointer to be called for rsp or error */ + wifi_pos_psoc_obj->wifi_pos_send_rsp = send_rsp_cb; + + return wifi_pos_psoc_obj->wifi_pos_req_handler(psoc, req); +} diff --git a/umac/wifi_pos/src/wifi_pos_ucfg_i.h b/umac/wifi_pos/src/wifi_pos_ucfg_i.h index 985dadf026..fe614ed8ec 100644 --- a/umac/wifi_pos/src/wifi_pos_ucfg_i.h +++ b/umac/wifi_pos/src/wifi_pos_ucfg_i.h @@ -17,6 +17,7 @@ */ /** + * DOC: wifi_pos_ucfg_i.h * This file prototyps the important functions pertinent to wifi positioning * component. */ @@ -24,4 +25,24 @@ #ifndef _WIFI_POS_UCFG_H_ #define _WIFI_POS_UCFG_H_ -#endif +#include "qdf_types.h" +#include "qdf_status.h" + +struct wlan_objmgr_psoc; +struct wifi_pos_req_msg; + +/** + * 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)(struct wlan_objmgr_psoc *, + uint32_t, uint32_t, uint8_t *)); + +#endif /* _WIFI_POS_UCFG_H_ */ diff --git a/umac/wifi_pos/src/wifi_pos_utils.c b/umac/wifi_pos/src/wifi_pos_utils.c index 3bd29aed28..63cc03aa95 100644 --- a/umac/wifi_pos/src/wifi_pos_utils.c +++ b/umac/wifi_pos/src/wifi_pos_utils.c @@ -20,3 +20,95 @@ * This file defines the utility helper functions for wifi_pos component. */ +#include "qdf_types.h" +#include "wlan_objmgr_cmn.h" +#include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wifi_pos_utils_i.h" + +/* + * WIFI pos command are not associated with any pdev/psoc/vdev, so the callback + * registered with GENL socket does not receive any pdev/pdev/vdev object. + * Since PSOC is top most object, it was decided to keep WIFI POS private obj + * within PSOC and hence, this module need to hang on to the first PSOC that + * was created for all its internal usage. + */ +static struct wlan_objmgr_psoc *wifi_pos_psoc_obj; + +struct wlan_objmgr_psoc *wifi_pos_get_psoc(void) +{ + return wifi_pos_psoc_obj; +} + +void wifi_pos_set_psoc(struct wlan_objmgr_psoc *psoc) +{ + if (wifi_pos_psoc_obj) + wifi_pos_warn("global psoc obj already set"); + else + wifi_pos_psoc_obj = psoc; +} + +void wifi_pos_clear_psoc(void) +{ + if (!wifi_pos_psoc_obj) + wifi_pos_warn("global psoc obj already cleared"); + else + wifi_pos_psoc_obj = NULL; +} + +/** + * wifi_pos_get_psoc_priv_obj: returns wifi_pos priv object within psoc + * @psoc: pointer to psoc object + * + * Return: wifi_pos_psoc_priv_obj + */ +struct wifi_pos_psoc_priv_obj *wifi_pos_get_psoc_priv_obj( + struct wlan_objmgr_psoc *psoc) +{ + struct wifi_pos_psoc_priv_obj *obj; + + wlan_psoc_obj_lock(psoc); + obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_WIFI_POS); + wlan_psoc_obj_unlock(psoc); + + 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; +} diff --git a/umac/wifi_pos/src/wifi_pos_utils_i.h b/umac/wifi_pos/src/wifi_pos_utils_i.h index f08186942f..6c95dafb9b 100644 --- a/umac/wifi_pos/src/wifi_pos_utils_i.h +++ b/umac/wifi_pos/src/wifi_pos_utils_i.h @@ -26,11 +26,246 @@ */ /** - * DOC: wifi_pos_utils.h + * DOC: wifi_pos_utils_i.h * This file defines the prototypes for the utility helper functions * for the wifi_pos component. */ + +#ifdef WIFI_POS_CONVERGED #ifndef _WIFI_POS_UTILS_H_ #define _WIFI_POS_UTILS_H_ +/* Include files */ +#include "qdf_types.h" +#include "qdf_status.h" +#include "ol_defines.h" +#include "qdf_trace.h" +struct wlan_objmgr_psoc; + +#define wifi_pos_log(level, args...) \ + QDF_TRACE(QDF_MODULE_ID_WIFIPOS, level, ## args) +#define wifi_pos_logfl(level, format, args...) \ + wifi_pos_log(level, FL(format), ## args) + +#define wifi_pos_alert(format, args...) \ + wifi_pos_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args) +#define wifi_pos_err(format, args...) \ + wifi_pos_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args) +#define wifi_pos_warn(format, args...) \ + wifi_pos_logfl(QDF_TRACE_LEVEL_WARN, format, ## args) +#define wifi_pos_notice(format, args...) \ + wifi_pos_logfl(QDF_TRACE_LEVEL_INFO, format, ## args) +#define wifi_pos_debug(format, args...) \ + wifi_pos_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args) + +#define OEM_APP_SIGNATURE_LEN 16 +#define OEM_APP_SIGNATURE_STR "QUALCOMM-OEM-APP" + +#define OEM_TARGET_SIGNATURE_LEN 8 +#define OEM_TARGET_SIGNATURE "QUALCOMM" + +#define OEM_CAP_MAX_NUM_CHANNELS 128 + +#ifndef OEM_DATA_RSP_SIZE +#define OEM_DATA_RSP_SIZE 1724 #endif + +/** + * struct oem_data_req - data request to be sent to firmware + * @data_len: len of data + * @data: buffer containing data + * + */ +struct oem_data_req { + uint32_t data_len; + uint8_t *data; +}; + +/** + * struct oem_data_rsp - response from firmware to data request sent earlier + * @data_len: len of data + * @data: buffer containing data + * + */ +struct oem_data_rsp { + uint32_t rsp_len; + uint8_t *data; +}; + +/** + * typedef 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_req_msg { + uint32_t msg_type; + uint32_t pid; + uint8_t *buf; + uint32_t buf_len; + struct wifi_pos_field_info *field_info_buf; + uint32_t field_info_buf_len; +}; + +/** + * struct wifi_pos_psoc_priv_obj - psoc obj data for wifi_pos + * @app_pid: pid of app registered to host driver + * @is_app_registered: indicates if app is registered + * @fine_time_meas_cap: FTM cap for different roles, reflection of ini + * @ftm_rr: configured value of FTM Ranging Request capability + * @lci_capability: configured value of LCI capability + * @rsvd: reserved + * @wifi_pos_req_handler: function pointer to handle TLV or non-TLV + * wifi pos request messages + * <----- fine_time_meas_cap (in bits) -----> + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + *| 8-31 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + *| reserved | SAP | SAP |P2P-GO|P2P-GO|P2P-CLI|P2P-CLI| STA | STA | + *| |resp |init |resp |init |resp |init |resp |init | + *+----------+-----+-----+------+------+-------+-------+-----+-----+ + * resp - responder role; init- initiator role + * + */ +struct wifi_pos_psoc_priv_obj { + uint32_t app_pid; + bool is_app_registered; + uint32_t fine_time_meas_cap; + uint32_t ftm_rr:1; + uint32_t lci_capability:1; + uint32_t rsvd:30; + + /* following are populated from HDD */ + 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 current_dwell_time_min; + uint16_t current_dwell_time_max; + + qdf_spinlock_t wifi_pos_lock; + + QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_req_msg *req); + void (*wifi_pos_send_rsp)(struct wlan_objmgr_psoc *psoc, + uint32_t rsp_msg_type, uint32_t buf_len, + uint8_t *buf); +}; + +/** + * wifi_pos_get_psoc_priv_obj: API to get wifi_psoc private object + * @psoc: pointer to psoc object + * + * Return: psoc private object on success, NULL otherwise + */ +struct wifi_pos_psoc_priv_obj *wifi_pos_get_psoc_priv_obj( + struct wlan_objmgr_psoc *psoc); + +/** + * wifi_pos_set_psoc: API to set global PSOC object + * @psoc: pointer to psoc object + * + * Since request from userspace is not associated with any vdev/pdev/psoc, this + * API is used to set global psoc object. + * + * Return: none. + */ +void wifi_pos_set_psoc(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); + +/** + * wifi_pos_get_psoc: API to clear global PSOC object + * + * Return: none. + */ +void wifi_pos_clear_psoc(void); + +/** + * wifi_pos_populate_caps: API to get OEM caps + * @psoc: psoc object + * @caps: capabilites buffer to populate + * + * Return: status of operation. + */ +QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, + 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. + * @psoc: pointer to psoc object + * + * Return: oem app pid + */ +uint32_t wifi_pos_get_app_pid(struct wlan_objmgr_psoc *psoc); + +/** + * wifi_pos_lock: acquires wifi_pos lock + * @psoc: pointer to psoc object + * + * Return: None + */ +void wifi_pos_lock(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_CONVERGED */