diff options
author | Amarnath Hullur Subramanyam <amarnath@codeaurora.org> | 2015-06-21 18:21:44 -0700 |
---|---|---|
committer | Vineeta Srivastava <vsrivastava@google.com> | 2015-07-09 11:59:07 -0700 |
commit | e0d30a0148b9a6fc9d54cc190f26b5b069e93647 (patch) | |
tree | 518e36ced4a0d89ef22e236477e382343d2b6d72 /qcwcn/wifi_hal/common.cpp | |
parent | 54116b8d4368a78ca0dcf75a98d9444c9dff1985 (diff) | |
download | wlan-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.cpp | 183 |
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; +} + |