diff options
author | Christopher Wiley <wiley@google.com> | 2016-06-16 16:31:01 -0700 |
---|---|---|
committer | Christopher Wiley <wiley@google.com> | 2016-06-17 11:50:59 -0700 |
commit | a591506fbf1445877fc2f97bca1e00b51ccc3a85 (patch) | |
tree | b06882f46a46c89b8320d6b4e4b5eb89eacbad6c /libwifi_hal | |
parent | 6579c9dc1d5ebc056ba7dcc6c23aa25732227124 (diff) | |
download | android_frameworks_opt_net_wifi-a591506fbf1445877fc2f97bca1e00b51ccc3a85.tar.gz android_frameworks_opt_net_wifi-a591506fbf1445877fc2f97bca1e00b51ccc3a85.tar.bz2 android_frameworks_opt_net_wifi-a591506fbf1445877fc2f97bca1e00b51ccc3a85.zip |
Move device dependent functionality to libwifi-hal
Bug: 29418968
Change-Id: I0fa3047972c57af7128ce6384b62960f6f017d93
Test: wifi works/unittests pass on bullhead
Diffstat (limited to 'libwifi_hal')
-rw-r--r-- | libwifi_hal/Android.mk | 61 | ||||
-rw-r--r-- | libwifi_hal/include/hardware_legacy/wifi.h | 64 | ||||
-rw-r--r-- | libwifi_hal/wifi_hal_common.cpp | 240 |
3 files changed, 357 insertions, 8 deletions
diff --git a/libwifi_hal/Android.mk b/libwifi_hal/Android.mk index e83c25e47..879ad8711 100644 --- a/libwifi_hal/Android.mk +++ b/libwifi_hal/Android.mk @@ -15,12 +15,7 @@ LOCAL_PATH := $(call my-dir) ifneq ($(TARGET_BUILD_PDK), true) -# A fallback "vendor" HAL library. -# Don't link this, link libwifi-hal. -# ============================================================ -include $(CLEAR_VARS) -LOCAL_MODULE := libwifi-hal-fallback -LOCAL_CFLAGS := \ +wifi_hal_cflags := \ -Wall \ -Werror \ -Wextra \ @@ -30,6 +25,53 @@ LOCAL_CFLAGS := \ -Wshadow \ -Wunused-variable \ -Wwrite-strings +ifdef WIFI_DRIVER_MODULE_PATH +wifi_hal_cflags += -DWIFI_DRIVER_MODULE_PATH=\"$(WIFI_DRIVER_MODULE_PATH)\" +endif +ifdef WIFI_DRIVER_MODULE_ARG +wifi_hal_cflags += -DWIFI_DRIVER_MODULE_ARG=\"$(WIFI_DRIVER_MODULE_ARG)\" +endif +ifdef WIFI_DRIVER_MODULE_NAME +wifi_hal_cflags += -DWIFI_DRIVER_MODULE_NAME=\"$(WIFI_DRIVER_MODULE_NAME)\" +endif +ifdef WIFI_DRIVER_FW_PATH_STA +wifi_hal_cflags += -DWIFI_DRIVER_FW_PATH_STA=\"$(WIFI_DRIVER_FW_PATH_STA)\" +endif +ifdef WIFI_DRIVER_FW_PATH_AP +wifi_hal_cflags += -DWIFI_DRIVER_FW_PATH_AP=\"$(WIFI_DRIVER_FW_PATH_AP)\" +endif +ifdef WIFI_DRIVER_FW_PATH_P2P +wifi_hal_cflags += -DWIFI_DRIVER_FW_PATH_P2P=\"$(WIFI_DRIVER_FW_PATH_P2P)\" +endif +ifdef WIFI_DRIVER_FW_PATH_PARAM +wifi_hal_cflags += -DWIFI_DRIVER_FW_PATH_PARAM=\"$(WIFI_DRIVER_FW_PATH_PARAM)\" +endif + +ifdef WIFI_DRIVER_STATE_CTRL_PARAM +wifi_hal_cflags += -DWIFI_DRIVER_STATE_CTRL_PARAM=\"$(WIFI_DRIVER_STATE_CTRL_PARAM)\" +endif +ifdef WIFI_DRIVER_STATE_ON +wifi_hal_cflags += -DWIFI_DRIVER_STATE_ON=\"$(WIFI_DRIVER_STATE_ON)\" +endif +ifdef WIFI_DRIVER_STATE_OFF +wifi_hal_cflags += -DWIFI_DRIVER_STATE_OFF=\"$(WIFI_DRIVER_STATE_OFF)\" +endif + +# Common code shared between the HALs. +# ============================================================ +include $(CLEAR_VARS) +LOCAL_MODULE := libwifi-hal-common +LOCAL_CFLAGS := $(wifi_hal_cflags) +LOCAL_SRC_FILES := wifi_hal_common.cpp +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +include $(BUILD_STATIC_LIBRARY) + +# A fallback "vendor" HAL library. +# Don't link this, link libwifi-hal. +# ============================================================ +include $(CLEAR_VARS) +LOCAL_MODULE := libwifi-hal-fallback +LOCAL_CFLAGS := $(wifi_hal_cflags) LOCAL_SRC_FILES := wifi_hal_fallback.cpp LOCAL_C_INCLUDES := $(call include-path-for, libhardware_legacy) include $(BUILD_STATIC_LIBRARY) @@ -54,12 +96,15 @@ endif # ============================================================ include $(CLEAR_VARS) LOCAL_MODULE := libwifi-hal -LOCAL_EXPORT_C_INCLUDE_DIRS := $(call include-path-for, libhardware_legacy) +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/include \ + $(call include-path-for, libhardware_legacy) LOCAL_SHARED_LIBRARIES := \ + libcutils \ liblog \ libnl \ libutils -LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL) +LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL) libwifi-hal-common include $(BUILD_SHARED_LIBRARY) endif diff --git a/libwifi_hal/include/hardware_legacy/wifi.h b/libwifi_hal/include/hardware_legacy/wifi.h new file mode 100644 index 000000000..defff0a19 --- /dev/null +++ b/libwifi_hal/include/hardware_legacy/wifi.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HARDWARE_LEGACY_WIFI_H +#define HARDWARE_LEGACY_WIFI_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * Load the Wi-Fi driver. + * + * @return 0 on success, < 0 on failure. + */ +int wifi_load_driver(); + +/** + * Unload the Wi-Fi driver. + * + * @return 0 on success, < 0 on failure. + */ +int wifi_unload_driver(); + +/** + * Check if the Wi-Fi driver is loaded. + * Check if the Wi-Fi driver is loaded. + + * @return 0 on success, < 0 on failure. + */ +int is_wifi_driver_loaded(); + +/** + * Return the path to requested firmware + */ +#define WIFI_GET_FW_PATH_STA 0 +#define WIFI_GET_FW_PATH_AP 1 +#define WIFI_GET_FW_PATH_P2P 2 +const char *wifi_get_fw_path(int fw_type); + +/** + * Change the path to firmware for the wlan driver + */ +int wifi_change_fw_path(const char *fwpath); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HARDWARE_LEGACY_WIFI_H */ diff --git a/libwifi_hal/wifi_hal_common.cpp b/libwifi_hal/wifi_hal_common.cpp new file mode 100644 index 000000000..54c38e135 --- /dev/null +++ b/libwifi_hal/wifi_hal_common.cpp @@ -0,0 +1,240 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hardware_legacy/wifi.h" + +#define LOG_TAG "WifiHalCommon" + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#include <cutils/log.h> +#include <cutils/misc.h> +#include <cutils/properties.h> + +extern int init_module(void *, unsigned long, const char *); +extern int delete_module(const char *, unsigned int); + +#ifndef WIFI_DRIVER_FW_PATH_STA +#define WIFI_DRIVER_FW_PATH_STA NULL +#endif +#ifndef WIFI_DRIVER_FW_PATH_AP +#define WIFI_DRIVER_FW_PATH_AP NULL +#endif +#ifndef WIFI_DRIVER_FW_PATH_P2P +#define WIFI_DRIVER_FW_PATH_P2P NULL +#endif +#ifndef WIFI_DRIVER_FW_PATH_PARAM +#define WIFI_DRIVER_FW_PATH_PARAM "/sys/module/wlan/parameters/fwpath" +#endif + +#ifndef WIFI_DRIVER_MODULE_ARG +#define WIFI_DRIVER_MODULE_ARG "" +#endif + +static const char DRIVER_PROP_NAME[] = "wlan.driver.status"; +#ifdef WIFI_DRIVER_MODULE_PATH +static const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME; +static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " "; +static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH; +static const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG; +static const char MODULE_FILE[] = "/proc/modules"; +#endif + +static int insmod(const char *filename, const char *args) +{ + void *module; + unsigned int size; + int ret; + + module = load_file(filename, &size); + if (!module) + return -1; + + ret = init_module(module, size, args); + + free(module); + + return ret; +} + +static int rmmod(const char *modname) +{ + int ret = -1; + int maxtry = 10; + + while (maxtry-- > 0) { + ret = delete_module(modname, O_NONBLOCK | O_EXCL); + if (ret < 0 && errno == EAGAIN) + usleep(500000); + else + break; + } + + if (ret != 0) + ALOGD("Unable to unload driver module \"%s\": %s\n", + modname, strerror(errno)); + return ret; +} + +#ifdef WIFI_DRIVER_STATE_CTRL_PARAM +int wifi_change_driver_state(const char *state) +{ + int len; + int fd; + int ret = 0; + + if (!state) + return -1; + fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY)); + if (fd < 0) { + ALOGE("Failed to open driver state control param (%s)", strerror(errno)); + return -1; + } + len = strlen(state) + 1; + if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) { + ALOGE("Failed to write driver state control param (%s)", strerror(errno)); + ret = -1; + } + close(fd); + return ret; +} +#endif + +int is_wifi_driver_loaded() { + char driver_status[PROPERTY_VALUE_MAX]; +#ifdef WIFI_DRIVER_MODULE_PATH + FILE *proc; + char line[sizeof(DRIVER_MODULE_TAG)+10]; +#endif + + if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) + || strcmp(driver_status, "ok") != 0) { + return 0; /* driver not loaded */ + } +#ifdef WIFI_DRIVER_MODULE_PATH + /* + * If the property says the driver is loaded, check to + * make sure that the property setting isn't just left + * over from a previous manual shutdown or a runtime + * crash. + */ + if ((proc = fopen(MODULE_FILE, "r")) == NULL) { + ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno)); + property_set(DRIVER_PROP_NAME, "unloaded"); + return 0; + } + while ((fgets(line, sizeof(line), proc)) != NULL) { + if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { + fclose(proc); + return 1; + } + } + fclose(proc); + property_set(DRIVER_PROP_NAME, "unloaded"); + return 0; +#else + return 1; +#endif +} + +int wifi_load_driver() +{ +#ifdef WIFI_DRIVER_MODULE_PATH + if (is_wifi_driver_loaded()) { + return 0; + } + + if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) + return -1; + +#elif defined WIFI_DRIVER_STATE_CTRL_PARAM + if (is_wifi_driver_loaded()) { + return 0; + } + + if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) + return -1; +#endif + property_set(DRIVER_PROP_NAME, "ok"); + return 0; +} + +int wifi_unload_driver() +{ + usleep(200000); /* allow to finish interface down */ +#ifdef WIFI_DRIVER_MODULE_PATH + if (rmmod(DRIVER_MODULE_NAME) == 0) { + int count = 20; /* wait at most 10 seconds for completion */ + while (count-- > 0) { + if (!is_wifi_driver_loaded()) + break; + usleep(500000); + } + usleep(500000); /* allow card removal */ + if (count) { + return 0; + } + return -1; + } else + return -1; +#else +#ifdef WIFI_DRIVER_STATE_CTRL_PARAM + if (is_wifi_driver_loaded()) { + if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) + return -1; + } +#endif + property_set(DRIVER_PROP_NAME, "unloaded"); + return 0; +#endif +} + +const char *wifi_get_fw_path(int fw_type) +{ + switch (fw_type) { + case WIFI_GET_FW_PATH_STA: + return WIFI_DRIVER_FW_PATH_STA; + case WIFI_GET_FW_PATH_AP: + return WIFI_DRIVER_FW_PATH_AP; + case WIFI_GET_FW_PATH_P2P: + return WIFI_DRIVER_FW_PATH_P2P; + } + return NULL; +} + +int wifi_change_fw_path(const char *fwpath) +{ + int len; + int fd; + int ret = 0; + + if (!fwpath) + return ret; + fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); + if (fd < 0) { + ALOGE("Failed to open wlan fw path param (%s)", strerror(errno)); + return -1; + } + len = strlen(fwpath) + 1; + if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { + ALOGE("Failed to write wlan fw path param (%s)", strerror(errno)); + ret = -1; + } + close(fd); + return ret; +} |