wifi_hal_common.cpp revision af52902e4746aab2bd667ac9bdeb1bbb3e46b539
1a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley/* 2a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Copyright 2016, The Android Open Source Project 3a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * 4a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Licensed under the Apache License, Version 2.0 (the "License"); 5a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * you may not use this file except in compliance with the License. 6a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * You may obtain a copy of the License at 7a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * 8a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * http://www.apache.org/licenses/LICENSE-2.0 9a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * 10a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Unless required by applicable law or agreed to in writing, software 11a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * distributed under the License is distributed on an "AS IS" BASIS, 12a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * See the License for the specific language governing permissions and 14a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * limitations under the License. 15a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley */ 16a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 17a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include "hardware_legacy/wifi.h" 18a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 19a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#define LOG_TAG "WifiHalCommon" 20a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 21a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <fcntl.h> 22a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <stdlib.h> 23a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <unistd.h> 24a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 25a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/log.h> 26a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/misc.h> 27a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/properties.h> 28a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 29217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int init_module(void *, unsigned long, const char *); 30217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int delete_module(const char *, unsigned int); 31a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 32a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_STA 33af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_STA NULL 34a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 35a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_AP 36af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_AP NULL 37a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 38a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_P2P 39af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_P2P NULL 40a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 41a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 42a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_MODULE_ARG 43af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_MODULE_ARG "" 44a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 45a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 46af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_PROP_NAME[] = "wlan.driver.status"; 47a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 48af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME; 49af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " "; 50af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH; 51af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG; 52af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char MODULE_FILE[] = "/proc/modules"; 53a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 54a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 55af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int insmod(const char *filename, const char *args) { 56af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley void *module; 57af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley unsigned int size; 58af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret; 59a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 60af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley module = load_file(filename, &size); 61af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!module) return -1; 62a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 63af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = init_module(module, size, args); 64a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 65af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley free(module); 66a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 67af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 68a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 69a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 70af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int rmmod(const char *modname) { 71af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = -1; 72af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int maxtry = 10; 73af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 74af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (maxtry-- > 0) { 75af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = delete_module(modname, O_NONBLOCK | O_EXCL); 76af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret < 0 && errno == EAGAIN) 77af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 78af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley else 79af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley break; 80af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 81af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 82af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret != 0) 83af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGD("Unable to unload driver module \"%s\": %s\n", modname, 84af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley strerror(errno)); 85af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 86a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 87a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 88a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 89af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_driver_state(const char *state) { 90af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 91af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 92af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 93af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 94af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!state) return -1; 95af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY)); 96af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 97af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGE("Failed to open driver state control param (%s)", strerror(errno)); 98af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 99af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 100af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(state) + 1; 101af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) { 102af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGE("Failed to write driver state control param (%s)", strerror(errno)); 103af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 104af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 105af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 106af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 107a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 108a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 109a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 110a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wileyint is_wifi_driver_loaded() { 111af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char driver_status[PROPERTY_VALUE_MAX]; 112a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 113af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley FILE *proc; 114af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char line[sizeof(DRIVER_MODULE_TAG) + 10]; 115a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 116a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 117af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) || 118af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley strcmp(driver_status, "ok") != 0) { 119af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; /* driver not loaded */ 120af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 121a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 122af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley /* 123af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * If the property says the driver is loaded, check to 124af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * make sure that the property setting isn't just left 125af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * over from a previous manual shutdown or a runtime 126af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * crash. 127af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley */ 128af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if ((proc = fopen(MODULE_FILE, "r")) == NULL) { 129af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno)); 130a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 131a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley return 0; 132af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 133af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while ((fgets(line, sizeof(line), proc)) != NULL) { 134af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { 135af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 136af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 137af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 138af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 139af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 140af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 141af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 142a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 143af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 144a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 145a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 146a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 147af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_load_driver() { 148a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 149af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 150af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 151af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 152a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 153af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1; 154a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 155a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#elif defined WIFI_DRIVER_STATE_CTRL_PARAM 156af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 157af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 158af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 159a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 160af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1; 161a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 162af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "ok"); 163af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 164a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 165a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 166af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_unload_driver() { 167af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(200000); /* allow to finish interface down */ 168a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 169af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (rmmod(DRIVER_MODULE_NAME) == 0) { 170af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int count = 20; /* wait at most 10 seconds for completion */ 171af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (count-- > 0) { 172af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!is_wifi_driver_loaded()) break; 173af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 174af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 175af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); /* allow card removal */ 176af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (count) { 177af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 178af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 179af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 180af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } else 181af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 182a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 183a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 184af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 185af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) return -1; 186af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 187a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 188af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 189af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 190a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 191a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 192a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 193af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyconst char *wifi_get_fw_path(int fw_type) { 194af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley switch (fw_type) { 195a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_STA: 196af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_STA; 197a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_AP: 198af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_AP; 199a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_P2P: 200af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_P2P; 201af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 202af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return NULL; 203a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 204a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 205af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_fw_path(const char *fwpath) { 206af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 207af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 208af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 209af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 210af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!fwpath) return ret; 211af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); 212af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 213af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGE("Failed to open wlan fw path param (%s)", strerror(errno)); 214af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 215af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 216af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(fwpath) + 1; 217af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { 218af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ALOGE("Failed to write wlan fw path param (%s)", strerror(errno)); 219af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 220af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 221af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 222af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 223a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 224