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#include <fcntl.h> 20a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <stdlib.h> 21a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <unistd.h> 22a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 2386105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley#include <android-base/logging.h> 24a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/misc.h> 25a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/properties.h> 26a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 27217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int init_module(void *, unsigned long, const char *); 28217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int delete_module(const char *, unsigned int); 29a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 30a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_STA 31af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_STA NULL 32a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 33a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_AP 34af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_AP NULL 35a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 36a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_P2P 37af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_P2P NULL 38a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 39a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 40a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_MODULE_ARG 41af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_MODULE_ARG "" 42a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 43a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 44af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_PROP_NAME[] = "wlan.driver.status"; 45a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 46af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME; 47af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " "; 48af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH; 49af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG; 50af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char MODULE_FILE[] = "/proc/modules"; 51a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 52a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 53af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int insmod(const char *filename, const char *args) { 54af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley void *module; 55af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley unsigned int size; 56af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret; 57a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 58af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley module = load_file(filename, &size); 59af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!module) return -1; 60a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 61af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = init_module(module, size, args); 62a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 63af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley free(module); 64a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 65af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 66a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 67a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 68af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int rmmod(const char *modname) { 69af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = -1; 70af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int maxtry = 10; 71af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 72af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (maxtry-- > 0) { 73af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = delete_module(modname, O_NONBLOCK | O_EXCL); 74af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret < 0 && errno == EAGAIN) 75af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 76af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley else 77af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley break; 78af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 79af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 80af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret != 0) 8186105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(DEBUG) << "Unable to unload driver module '" << modname << "'"; 82af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 83a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 84a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 85a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 86af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_driver_state(const char *state) { 87af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 88af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 89af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 90af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 91af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!state) return -1; 92af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY)); 93af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 9486105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to open driver state control param"; 95af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 96af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 97af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(state) + 1; 98af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) { 9986105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to write driver state control param"; 100af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 101af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 102af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 103af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 104a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 105a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 106a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 107a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wileyint is_wifi_driver_loaded() { 108af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char driver_status[PROPERTY_VALUE_MAX]; 109a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 110af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley FILE *proc; 111af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char line[sizeof(DRIVER_MODULE_TAG) + 10]; 112a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 113a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 114af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) || 115af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley strcmp(driver_status, "ok") != 0) { 116af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; /* driver not loaded */ 117af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 118a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 119af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley /* 120af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * If the property says the driver is loaded, check to 121af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * make sure that the property setting isn't just left 122af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * over from a previous manual shutdown or a runtime 123af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * crash. 124af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley */ 125af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if ((proc = fopen(MODULE_FILE, "r")) == NULL) { 12686105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(WARNING) << "Could not open " << MODULE_FILE; 127a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 128a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley return 0; 129af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 130af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while ((fgets(line, sizeof(line), proc)) != NULL) { 131af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { 132af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 133af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 134af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 135af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 136af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 137af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 138af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 139a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 140af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 141a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 142a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 143a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 144af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_load_driver() { 145a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 146af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 147af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 148af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 149a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 150af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1; 151278ed48124665c6285f9fae66649bfc3cc0a21c1Kumar Anand#endif 152a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 153278ed48124665c6285f9fae66649bfc3cc0a21c1Kumar Anand#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 154af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 155af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 156af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 157a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 158af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1; 159a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 160af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "ok"); 161af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 162a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 163a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 164af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_unload_driver() { 165823a774406c76128c549e026a808ff5ad0a63ebeWei Wang if (!is_wifi_driver_loaded()) { 166823a774406c76128c549e026a808ff5ad0a63ebeWei Wang return 0; 167823a774406c76128c549e026a808ff5ad0a63ebeWei Wang } 168af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(200000); /* allow to finish interface down */ 169a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 170af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (rmmod(DRIVER_MODULE_NAME) == 0) { 171af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int count = 20; /* wait at most 10 seconds for completion */ 172af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (count-- > 0) { 173af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!is_wifi_driver_loaded()) break; 174af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 175af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 176af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); /* allow card removal */ 177af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (count) { 178af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 179af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 180af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 181af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } else 182af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 183a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 184a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 185af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 186af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) return -1; 187af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 188a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 189af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 190af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 191a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 192a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 193a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 194af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyconst char *wifi_get_fw_path(int fw_type) { 195af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley switch (fw_type) { 196a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_STA: 197af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_STA; 198a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_AP: 199af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_AP; 200a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_P2P: 201af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_P2P; 202af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 203af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return NULL; 204a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 205a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 206af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_fw_path(const char *fwpath) { 207af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 208af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 209af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 210af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 211af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!fwpath) return ret; 212af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); 213af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 21486105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to open wlan fw path param"; 215af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 216af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 217af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(fwpath) + 1; 218af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { 21986105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to write wlan fw path param"; 220af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 221af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 222af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 223af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 224a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 225