summaryrefslogtreecommitdiff
path: root/qcwcn/wifi_hal/common.cpp
diff options
context:
space:
mode:
authorAmarnath Hullur Subramanyam <amarnath@codeaurora.org>2015-06-21 18:21:44 -0700
committerVineeta Srivastava <vsrivastava@google.com>2015-07-09 11:59:07 -0700
commite0d30a0148b9a6fc9d54cc190f26b5b069e93647 (patch)
tree518e36ced4a0d89ef22e236477e382343d2b6d72 /qcwcn/wifi_hal/common.cpp
parent54116b8d4368a78ca0dcf75a98d9444c9dff1985 (diff)
downloadwlan-e0d30a0148b9a6fc9d54cc190f26b5b069e93647.tar.gz
Wi-Fi HAL: Implement changes required for routing GSCAN over LOWI
- With this change, Wi-Fi HAL first tries to direct GSCAN requests through HAL<-->LOWI interface rather than directly sending them to the driver. Routing is done based on version and capability check. If HAL<-->LOWI interface is not supported, Wi-Fi HAL will then proceed the normal way by sending commands to the driver. -Moved the utility functions used to open LOWI shared library, retrieve handler to LOWI APIs table, and initialize LOWI module out of RTT module into the HAL common module. Change-Id: Ib81ff69bec07e71ab4b4d553f1038e122b535ae6
Diffstat (limited to 'qcwcn/wifi_hal/common.cpp')
-rw-r--r--qcwcn/wifi_hal/common.cpp183
1 files changed, 182 insertions, 1 deletions
diff --git a/qcwcn/wifi_hal/common.cpp b/qcwcn/wifi_hal/common.cpp
index 9d9e71a..884330d 100644
--- a/qcwcn/wifi_hal/common.cpp
+++ b/qcwcn/wifi_hal/common.cpp
@@ -18,6 +18,7 @@
#include <linux/pkt_sched.h>
#include <netlink/object-api.h>
#include <netlink-types.h>
+#include <dlfcn.h>
#include "wifi_hal.h"
#include "common.h"
@@ -79,7 +80,7 @@ wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_
info->event_cb[info->num_event_cb].cb_arg = arg;
info->num_event_cb++;
ALOGI("Successfully added event handler %p for command %d", func, cmd);
- result = WIFI_SUCCESS;
+ result = WIFI_SUCCESS;
} else {
result = WIFI_ERROR_OUT_OF_MEMORY;
}
@@ -267,3 +268,183 @@ void hexdump(void *buf, u16 len)
#ifdef __cplusplus
}
#endif /* __cplusplus */
+
+/* Pointer to the table of LOWI callback funcs */
+lowi_cb_table_t *LowiWifiHalApi = NULL;
+/* LowiSupportedCapabilities read */
+u32 lowiSupportedCapabilities = 0;
+
+int compareLowiVersion(u16 major, u16 minor, u16 micro)
+{
+ u32 currVersion = 0x10000*(WIFIHAL_LOWI_MAJOR_VERSION) + \
+ 0x100*(WIFIHAL_LOWI_MINOR_VERSION) + \
+ WIFIHAL_LOWI_MICRO_VERSION;
+
+ u32 lowiVersion = 0x10000*(major) + \
+ 0x100*(minor) + \
+ micro;
+
+ return (memcmp(&currVersion, &lowiVersion, sizeof(u32)));
+}
+
+/*
+ * This function will open the lowi shared library and obtain the
+ * Lowi Callback table and the capabilities supported.
+ * A version check is also performed in this function and if the version
+ * check fails then the callback table returned will be NULL.
+ */
+wifi_error fetchLowiCbTableAndCapabilities(lowi_cb_table_t **lowi_wifihal_api,
+ bool *lowi_get_capa_supported)
+{
+ getCbTable_t* lowiCbTable = NULL;
+ int ret = 0;
+ wifi_error retVal = WIFI_SUCCESS;
+
+ *lowi_wifihal_api = NULL;
+ *lowi_get_capa_supported = false;
+
+#if __WORDSIZE == 64
+ void* lowi_handle = dlopen("/vendor/lib64/liblowi_wifihal.so", RTLD_NOW);
+#else
+ void* lowi_handle = dlopen("/vendor/lib/liblowi_wifihal.so", RTLD_NOW);
+#endif
+ if (!lowi_handle) {
+ ALOGE("%s: NULL lowi_handle, err: %s", __FUNCTION__, dlerror());
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ lowiCbTable = (getCbTable_t*)dlsym(lowi_handle,
+ "lowi_wifihal_get_cb_table");
+ if (!lowiCbTable) {
+ ALOGE("%s: NULL lowi callback table", __FUNCTION__);
+ return WIFI_ERROR_UNKNOWN;
+ }
+
+ *lowi_wifihal_api = lowiCbTable();
+
+ /* First check whether lowi module implements the get_lowi_version
+ * function. All the functions in lowi module starts with
+ * "lowi_wifihal_" prefix thus the below function name.
+ */
+ if ((dlsym(lowi_handle, "lowi_wifihal_get_lowi_version") != NULL) &&
+ ((*lowi_wifihal_api)->get_lowi_version != NULL)) {
+ u16 lowiMajorVersion = WIFIHAL_LOWI_MAJOR_VERSION;
+ u16 lowiMinorVersion = WIFIHAL_LOWI_MINOR_VERSION;
+ u16 lowiMicroVersion = WIFIHAL_LOWI_MICRO_VERSION;
+ int versionCheck = -1;
+
+ ret = (*lowi_wifihal_api)->get_lowi_version(&lowiMajorVersion,
+ &lowiMinorVersion,
+ &lowiMicroVersion);
+ if (ret) {
+ ALOGI("%s: get_lowi_version returned error:%d",
+ __FUNCTION__, ret);
+ retVal = WIFI_ERROR_NOT_SUPPORTED;
+ goto cleanup;
+ }
+ ALOGI("%s: Lowi version:%d.%d.%d", __FUNCTION__,
+ lowiMajorVersion, lowiMinorVersion,
+ lowiMicroVersion);
+
+ /* Compare the version with version in wifihal_internal.h */
+ versionCheck = compareLowiVersion(lowiMajorVersion,
+ lowiMinorVersion,
+ lowiMicroVersion);
+ if (versionCheck < 0) {
+ ALOGI("%s: Version Check failed:%d", __FUNCTION__,
+ versionCheck);
+ retVal = WIFI_ERROR_NOT_SUPPORTED;
+ goto cleanup;
+ }
+ else {
+ ALOGI("%s: Version Check passed:%d", __FUNCTION__,
+ versionCheck);
+ }
+ }
+ else {
+ ALOGI("%s: lowi_wifihal_get_lowi_version not present",
+ __FUNCTION__);
+ }
+
+
+ /* Check if get_lowi_capabilities func pointer exists in
+ * the lowi lib and populate lowi_get_capa_supported
+ * All the functions in lowi modules starts with
+ * "lowi_wifihal_ prefix" thus the below function name.
+ */
+ if (dlsym(lowi_handle, "lowi_wifihal_get_lowi_capabilities") != NULL) {
+ *lowi_get_capa_supported = true;
+ }
+ else {
+ ALOGI("lowi_wifihal_get_lowi_capabilities() is not supported.");
+ *lowi_get_capa_supported = false;
+ }
+cleanup:
+ if (retVal) {
+ *lowi_wifihal_api = NULL;
+ }
+ return retVal;
+}
+
+lowi_cb_table_t *getLowiCallbackTable(u32 requested_lowi_capabilities)
+{
+ int ret = WIFI_SUCCESS;
+ bool lowi_get_capabilities_support = false;
+
+ ALOGI("%s: Entry", __FUNCTION__);
+ if (LowiWifiHalApi == NULL) {
+ ALOGI("%s: LowiWifiHalApi Null, Initialize Lowi",
+ __FUNCTION__);
+ ret = fetchLowiCbTableAndCapabilities(&LowiWifiHalApi,
+ &lowi_get_capabilities_support);
+ if (ret != WIFI_SUCCESS || LowiWifiHalApi == NULL ||
+ LowiWifiHalApi->init == NULL) {
+ ALOGI("%s: LOWI is not supported.", __FUNCTION__);
+ goto cleanup;
+ }
+ /* Initialize LOWI if it isn't up already. */
+ ret = LowiWifiHalApi->init();
+ if (ret) {
+ ALOGE("%s: failed lowi initialization. "
+ "Returned error:%d. Exit.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ if (!lowi_get_capabilities_support ||
+ LowiWifiHalApi->get_lowi_capabilities == NULL) {
+ ALOGI("%s: Allow rtt APIs thru LOWI to proceed even though "
+ "get_lowi_capabilities() is not supported. Returning",
+ __FUNCTION__);
+ lowiSupportedCapabilities |=
+ (ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
+ return LowiWifiHalApi;
+ }
+ ret =
+ LowiWifiHalApi->get_lowi_capabilities(&lowiSupportedCapabilities);
+ if (ret) {
+ ALOGI("%s: failed to get lowi supported capabilities."
+ "Returned error:%d. Exit.", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ }
+
+ if ((lowiSupportedCapabilities & requested_lowi_capabilities) == 0) {
+ ALOGE("%s: requested lowi capabilities: 0x%08x is not "
+ " in supported capabilities: 0x%08x. Return NULL.",
+ __FUNCTION__, requested_lowi_capabilities,
+ lowiSupportedCapabilities);
+ return NULL;
+ }
+ ALOGI("%s: Returning valid LowiWifiHalApi instance:%p",
+ __FUNCTION__, LowiWifiHalApi);
+ return LowiWifiHalApi;
+
+cleanup:
+ ALOGI("%s: Cleaning up Lowi due to failure. Return NULL", __FUNCTION__);
+ if (LowiWifiHalApi && LowiWifiHalApi->destroy) {
+ ret = LowiWifiHalApi->destroy();
+ }
+ LowiWifiHalApi = NULL;
+ lowiSupportedCapabilities = 0;
+ return LowiWifiHalApi;
+}
+