qcacmn: Implement Wifi Positioning Init/Deinit

Implement Init/Deinit for the WIFI Positioning component.

Change-Id: Iec0f4199935f63f7019de5ae16fc760817165954
CRs-Fixed: 2003488
diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c
index 90d24f2..179a5eb 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;
+}