From c02c167266e884f8e0e9adae9cef02501c7363ce Mon Sep 17 00:00:00 2001 From: Guoyin Chen Date: Tue, 1 Dec 2015 22:01:59 +0800 Subject: Add bcm4339 wifi hal for imx6ul Change-Id: Ia175f518c03ded3ce99bf5c1f5fb11daf9ea4710 Signed-off-by: Guoyin Chen --- peripheral/wifi/bcm4339/.gitignore | 1 + peripheral/wifi/bcm4339/Android.mk | 32 +++ peripheral/wifi/bcm4339/peripheral.mk | 29 +++ peripheral/wifi/bcm4339/wifi_driver_hal_bcmdhd.cpp | 225 +++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 peripheral/wifi/bcm4339/.gitignore create mode 100644 peripheral/wifi/bcm4339/Android.mk create mode 100644 peripheral/wifi/bcm4339/peripheral.mk create mode 100644 peripheral/wifi/bcm4339/wifi_driver_hal_bcmdhd.cpp diff --git a/peripheral/wifi/bcm4339/.gitignore b/peripheral/wifi/bcm4339/.gitignore new file mode 100644 index 0000000..9cf6616 --- /dev/null +++ b/peripheral/wifi/bcm4339/.gitignore @@ -0,0 +1 @@ +bcmdhd diff --git a/peripheral/wifi/bcm4339/Android.mk b/peripheral/wifi/bcm4339/Android.mk new file mode 100644 index 0000000..6735f86 --- /dev/null +++ b/peripheral/wifi/bcm4339/Android.mk @@ -0,0 +1,32 @@ +# Copyright (C) 2015 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. + +ifeq ($(findstring imx, $(soc_name)), imx) +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -Wno-unused-parameter +LOCAL_C_INCLUDES += device/generic/brillo/wifi_driver_hal/include +LOCAL_SHARED_LIBRARIES := libcutils +LOCAL_CPPFLAGS += -DLOG_TAG=\"hal_bcmdhd\" +#LOCAL_CPPFLAGS += -DBCMDHD_USE_KERNEL_MODULE +LOCAL_SRC_FILES := wifi_driver_hal_bcmdhd.cpp +LOCAL_MODULE := wifi_driver.$(soc_name) +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_MODULE_TAGS := eng + +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/peripheral/wifi/bcm4339/peripheral.mk b/peripheral/wifi/bcm4339/peripheral.mk new file mode 100644 index 0000000..6a88c80 --- /dev/null +++ b/peripheral/wifi/bcm4339/peripheral.mk @@ -0,0 +1,29 @@ +# +# Copyright 2015 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. +# + +BCMDHD_FIRMWARE_MK := hardware/bsp/freescale/peripheral/wifi/bcm4339/bcmdhd +ifeq ($(BCMDHD_FIRMWARE_MK), $(wildcard $(BCMDHD_FIRMWARE_MK))) +WLAN_FIRMWARE_SRC_FOLDER = hardware/bsp/freescale/peripheral/wifi/bcm4339/bcmdhd/firmware/ZP_BCM4339/ +FIRMWARE_DST_FOLDER = system/vendor/firmware/wlan/bcm4339 + +SRC_FILES := bcmdhd.ZP.SDIO.cal fw_bcmdhd.bin fw_bcmdhd_apsta.bin +COPY_FILES += \ + $(join $(patsubst %, $(WLAN_FIRMWARE_SRC_FOLDER)/%, $(SRC_FILES)), $(patsubst %, :$(FIRMWARE_DST_FOLDER)/%, $(SRC_FILES))) +endif + +PRODUCT_COPY_FILES += $(COPY_FILES) +WIFI_DRIVER_HAL_MODULE := wifi_driver.$(soc_name) +WIFI_DRIVER_HAL_PERIPHERAL := bcm4339 diff --git a/peripheral/wifi/bcm4339/wifi_driver_hal_bcmdhd.cpp b/peripheral/wifi/bcm4339/wifi_driver_hal_bcmdhd.cpp new file mode 100644 index 0000000..64e347d --- /dev/null +++ b/peripheral/wifi/bcm4339/wifi_driver_hal_bcmdhd.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#if BCMDHD_USE_KERNEL_MODULE +#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) +#endif + +namespace { + + enum CheckmodResult{ + MOD_INSED, + NOT_FOUND + }; + +const char kCfg80211KoPath[] = "/system/lib/modules/cfg80211.ko"; +const char kCfg80211KoName[] = "cfg80211"; +const char kBcmdhdDriverPath[] = "/system/lib/modules/bcmdhd.ko"; +const char kBcmdhdDriverName[] = "bcmdhd"; +const char kBcmdhdApFirmwarePath[] = "/system/vendor/firmware/wlan/bcm4339/fw_bcmdhd_apsta.bin"; +const char kBcmdhdStaFirmwarePath[] = "/system/vendor/firmware/wlan/bcm4339/fw_bcmdhd.bin"; +const char kBcmdhdFirmwareConfigPath[] = "/sys/module/bcmdhd/parameters/firmware_path"; +const char kBcmdhdNvramConfigPath[] = "/sys/module/bcmdhd/parameters/nvram_path"; +const char kBcmdhdNvramPath[] = "/system/vendor/firmware/wlan/bcm4339/bcmdhd.ZP.SDIO.cal"; +const char kModulesSysfsPath[] = "/proc/modules"; + +const char kApDeviceName[] = "wlan0"; +const char kStationDeviceName[] = "wlan0"; + + +static bool read_file(const std::string& filename, std::string* buffer, + size_t buffer_size) { + int fd = open(filename.c_str(), O_RDONLY); + if (fd < 0) { + ALOGE("Cannot open %s for reading", filename.c_str()); + return false; + } + char buffer_data[buffer_size]; + ssize_t count = read(fd, buffer_data, buffer_size); + close(fd); + + if (count <= 0) { + ALOGE("Cannot read any data from %s", filename.c_str()); + return false; + } + + buffer->assign(buffer_data, count); + return true; +} + +#if BCMDHD_USE_KERNEL_MODULE +static int checkmod(const char *mod_name) { + std::string module_path(kModulesSysfsPath); + std::string module_name(mod_name); + std::string module_content; + read_file(module_path, &module_content, 1024); + if (module_content.find(module_name, 0) == std::string::npos) + return NOT_FOUND; + else + return MOD_INSED; + +} +#endif + +#if BCMDHD_USE_KERNEL_MODULE +static int insmod(const char *filename, const char *args) { + void *module; + unsigned int size; + int ret; + module = load_file(filename, &size); + if (!module) { + ALOGE("insmod:load_file %s error", filename); + return -1; + } + ret = init_module(module, size, args); + free(module); + return ret; +} +#endif + + +static bool write_file( + const std::string& filename, const std::string& content) { + int fd = open(filename.c_str(), O_WRONLY); + if (fd < 0) { + ALOGE("Cannot open %s for writing", filename.c_str()); + return false; + } + ssize_t write_count = content.size(); + ssize_t actual_count = write(fd, content.c_str(), write_count); + close(fd); + + if (actual_count != write_count) { + ALOGE("Expected to write %d bytes to %s but write returns %d", + write_count, filename.c_str(), actual_count); + return false; + } + return true; +} + + + +static wifi_driver_error wifi_driver_initialize_bcmdhd() { + + int ret = -1; + ALOGD("bcmdhd wifi_driver init."); +#if BCMDHD_USE_KERNEL_MODULE + if (checkmod(kCfg80211KoName) == NOT_FOUND) { + if (insmod(kCfg80211KoPath, "")) { + ALOGE("Cannot insmod cfg80211"); + return WIFI_ERROR_UNKNOWN; + } + } + if (checkmod(kBcmdhdDriverName) == NOT_FOUND) { + if (insmod(kBcmdhdDriverPath, "")) { + ALOGE("Cannot insmod bcmdhd driver."); + return WIFI_ERROR_UNKNOWN; + } + } +#endif + return WIFI_SUCCESS; +} + +static wifi_driver_error wifi_driver_set_mode_bcmdhd( + wifi_driver_mode mode, + char* wifi_device_name, + size_t wifi_device_name_size) { + const char* device_name = nullptr; + ALOGD("Wifi HAL setup mode: %s to %s mode", wifi_device_name, mode==WIFI_MODE_AP? "AP":"STA"); + std::string ap_firmware(kBcmdhdApFirmwarePath); + std::string sta_firmware(kBcmdhdStaFirmwarePath); + std::string firmware_config(kBcmdhdFirmwareConfigPath); + std::string nvram_config(kBcmdhdNvramConfigPath); + std::string nvram_file(kBcmdhdNvramPath); + switch (mode) { + case WIFI_MODE_AP: + strlcpy(wifi_device_name, kApDeviceName, wifi_device_name_size); + write_file(firmware_config, ap_firmware); + break; + + case WIFI_MODE_STATION: + strlcpy(wifi_device_name, kStationDeviceName, wifi_device_name_size); + write_file(firmware_config, sta_firmware); + break; + + default: + ALOGE("Unkonwn WiFi driver mode %d", mode); + return WIFI_ERROR_INVALID_ARGS; + } + write_file(nvram_config, nvram_file); + + return WIFI_SUCCESS; +} + +static int close_bcmdhd_driver(struct hw_device_t* device) { + wifi_driver_device_t* dev = reinterpret_cast(device); + if (dev) + free(dev); + return 0; +} + +static int open_bcmdhd_driver(const struct hw_module_t* module, const char*, + struct hw_device_t** device) { + wifi_driver_device_t* dev = reinterpret_cast( + calloc(1, sizeof(wifi_driver_device_t))); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = WIFI_DRIVER_DEVICE_API_VERSION_0_1; + // We're forced into this cast by the existing API. This pattern is + // common among users of the HAL. + dev->common.module = const_cast(module); + dev->common.close = close_bcmdhd_driver; + dev->wifi_driver_initialize = wifi_driver_initialize_bcmdhd; + dev->wifi_driver_set_mode = wifi_driver_set_mode_bcmdhd; + + *device = &dev->common; + + return 0; +} + +static struct hw_module_methods_t bcmdhd_driver_module_methods = { + open: open_bcmdhd_driver +}; + +} // namespace {} + +hw_module_t HAL_MODULE_INFO_SYM = { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: WIFI_DRIVER_HARDWARE_MODULE_ID, + name: "BCM4339", + author: "Freescale", + methods: &bcmdhd_driver_module_methods, + dso: NULL, + reserved: {0}, +}; -- cgit v1.2.3