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> 2693c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar#include <sys/syscall.h> 27a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 28217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int init_module(void *, unsigned long, const char *); 29217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int delete_module(const char *, unsigned int); 30a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 31a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_STA 32af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_STA NULL 33a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 34a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_AP 35af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_AP NULL 36a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 37a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_P2P 38af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_P2P NULL 39a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 40a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 41a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_MODULE_ARG 42af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_MODULE_ARG "" 43a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 44a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 45af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_PROP_NAME[] = "wlan.driver.status"; 46a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 47af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME; 48af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " "; 49af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH; 50af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG; 51af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char MODULE_FILE[] = "/proc/modules"; 52a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 53a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 54af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int insmod(const char *filename, const char *args) { 55af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret; 5693c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar int fd; 57a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 5893c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); 5993c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar if (fd < 0) { 6093c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar PLOG(ERROR) << "Failed to open " << filename; 6193c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar return -1; 6293c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar } 63a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 6493c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar ret = syscall(__NR_finit_module, fd, args, 0); 65a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 6693c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar close(fd); 6793c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar if (ret < 0) { 6893c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar PLOG(ERROR) << "finit_module return: " << ret; 6993c106de19af6a648c26e4d5f0cd0502740b4c51Ajit Kumar } 70a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 71af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 72a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 73a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 74af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int rmmod(const char *modname) { 75af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = -1; 76af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int maxtry = 10; 77af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 78af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (maxtry-- > 0) { 79af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = delete_module(modname, O_NONBLOCK | O_EXCL); 80af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret < 0 && errno == EAGAIN) 81af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 82af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley else 83af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley break; 84af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 85af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 86af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (ret != 0) 8786105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(DEBUG) << "Unable to unload driver module '" << modname << "'"; 88af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 89a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 90a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 91a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 92af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_driver_state(const char *state) { 93af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 94af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 95af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 96af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 97af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!state) return -1; 98af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY)); 99af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 10086105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to open driver state control param"; 101af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 102af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 103af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(state) + 1; 104af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) { 10586105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to write driver state control param"; 106af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 107af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 108af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 109af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 110a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 111a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 112a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 113a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wileyint is_wifi_driver_loaded() { 114af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char driver_status[PROPERTY_VALUE_MAX]; 115a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 116af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley FILE *proc; 117af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley char line[sizeof(DRIVER_MODULE_TAG) + 10]; 118a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 119a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 120af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) || 121af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley strcmp(driver_status, "ok") != 0) { 122af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; /* driver not loaded */ 123af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 124a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 125af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley /* 126af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * If the property says the driver is loaded, check to 127af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * make sure that the property setting isn't just left 128af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * over from a previous manual shutdown or a runtime 129af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley * crash. 130af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley */ 131af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if ((proc = fopen(MODULE_FILE, "r")) == NULL) { 13286105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(WARNING) << "Could not open " << MODULE_FILE; 133a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 134a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley return 0; 135af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 136af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while ((fgets(line, sizeof(line), proc)) != NULL) { 137af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { 138af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 139af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 140af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 141af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 142af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fclose(proc); 143af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 144af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 145a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 146af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 1; 147a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 148a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 149a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 150af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_load_driver() { 151a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 152af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 153af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 154af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 155a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 156af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1; 157278ed48124665c6285f9fae66649bfc3cc0a21c1Kumar Anand#endif 158a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 159278ed48124665c6285f9fae66649bfc3cc0a21c1Kumar Anand#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 160af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 161af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 162af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 163a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 164af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1; 165a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 166af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "ok"); 167af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 168a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 169a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 170af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_unload_driver() { 171823a774406c76128c549e026a808ff5ad0a63ebeWei Wang if (!is_wifi_driver_loaded()) { 172823a774406c76128c549e026a808ff5ad0a63ebeWei Wang return 0; 173823a774406c76128c549e026a808ff5ad0a63ebeWei Wang } 174af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(200000); /* allow to finish interface down */ 175a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH 176af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (rmmod(DRIVER_MODULE_NAME) == 0) { 177af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int count = 20; /* wait at most 10 seconds for completion */ 178af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley while (count-- > 0) { 179af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!is_wifi_driver_loaded()) break; 180af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); 181af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 182af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley usleep(500000); /* allow card removal */ 183af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (count) { 184af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 185af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 186af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 187af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } else 188af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 189a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else 190a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM 191af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (is_wifi_driver_loaded()) { 192af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) return -1; 193af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 194a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 195af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley property_set(DRIVER_PROP_NAME, "unloaded"); 196af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return 0; 197a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif 198a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 199a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 200af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyconst char *wifi_get_fw_path(int fw_type) { 201af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley switch (fw_type) { 202a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_STA: 203af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_STA; 204a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_AP: 205af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_AP; 206a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley case WIFI_GET_FW_PATH_P2P: 207af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return WIFI_DRIVER_FW_PATH_P2P; 208af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 209af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return NULL; 210a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 211a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley 212af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_fw_path(const char *fwpath) { 213af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int len; 214af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int fd; 215af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley int ret = 0; 216af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley 217af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (!fwpath) return ret; 218af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); 219af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (fd < 0) { 22086105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to open wlan fw path param"; 221af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return -1; 222af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 223af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley len = strlen(fwpath) + 1; 224af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { 22586105fb24919eca17e71a5ec820d75ac57bbdc65Christopher Wiley PLOG(ERROR) << "Failed to write wlan fw path param"; 226af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley ret = -1; 227af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley } 228af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley close(fd); 229af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley return ret; 230a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley} 231